blob: 463c3a10e35970fe890ce6f751a59c8600458014 [file] [log] [blame]
Benedek Tomasik90bd41e2021-03-10 11:23:45 +00001#-------------------------------------------------------------------------------
Gyorgy Szingc3271e72023-04-18 15:44:49 +02002# Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved.
Benedek Tomasik90bd41e2021-03-10 11:23:45 +00003#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6#-------------------------------------------------------------------------------
7
8# Determine the number of processes to run while running parallel builds.
9# Pass -DPROCESSOR_COUNT=<n> to cmake to override.
10if(NOT DEFINED PROCESSOR_COUNT)
11 include(ProcessorCount)
12 ProcessorCount(PROCESSOR_COUNT)
13 set(PROCESSOR_COUNT ${PROCESSOR_COUNT} CACHE STRING "Number of cores to use for parallel builds.")
14endif()
15
16#[===[.rst:
17Common fetch interface for external dependencies.
18-------------------------------------------------
Gyorgy Szingf934bab2023-08-31 10:48:40 +000019
20The following variables can be set in cmake or in the environment to make the build of a specific
21dependency verbose. Note: <DEP_NAME> is the name of the dependency as set int the cmake script
22with all characters converted to uppercase.
23
24``<DEP_NAME>_VERBOSE_CONFIG``
25 Global variable or environment variable.
26 Pass `--trace-expand` to cmake if set.
27``<DEP_NAME>_VERBOSE_BUILD``
28 Global variable or environment variable.
29 Turn the build step to verbose mode if set.
30
Benedek Tomasik90bd41e2021-03-10 11:23:45 +000031#]===]
32
33#[===[.rst:
34.. cmake:command:: LazyFetch_Fetch
35
36 .. code:: cmake
37 LazyFetch_Fetch(DEP_NAME <dependency name> OPTIONS <list of options for FetchContent_Declare>)
38
39 INPUTS:
40 ``DEP_NAME``
41 Unique name for the dependency, used by FetchContent_* functions
42 ``OPTIONS``
43 List of options for FetchContent_Declare, e.g. git url and refspec, check cmake documentations for more
44 information
45 #]===]
46
47function(LazyFetch_Fetch DEP_NAME OPTIONS)
48 include(FetchContent)
49
50 # Fetching dependency
51 FetchContent_Declare(
52 ${DEP_NAME}
53 ${OPTIONS}
54 )
55
56 FetchContent_GetProperties(${DEP_NAME})
57 if(NOT "${DEP_NAME}_POPULATED")
58 message(STATUS "Fetching ${DEP_NAME}")
59 FetchContent_Populate(${DEP_NAME})
60 endif()
61endfunction()
62
63#[===[.rst:
64.. cmake:command:: LazyFetch_ConfigAndBuild
65
66 .. code:: cmake
67 LazyFetch_ConfigAndBuild(DEP_NAME <dependency name> SRC_DIR <source code dir> BIN_DIR <binary dir>
68 CACHE_FILE <path to the initial cache file> INSTALL_DIR <install path>)
69
70 INPUTS:
71 ``DEP_NAME``
72 Unique name for the dependency
73 ``SRC_DIR``
74 Source directory
75 ``BIN_DIR``
76 Build directory
77 ``CACHE_FILE``
78 Path to the initial cache file. Setting cache variables in this file can be used to augment
79 the configure process. The file goes through :cmake:function:`configure_file(... @ONLY)`, this
80 can be used to pass variables to the external project.
81 ``INSTALL_DIR``
82 Install path. If not set, the install step will be skipped.
Gyorgy Szingf934bab2023-08-31 10:48:40 +000083 ``<DEP_NAME>_VERBOSE_CONFIG``
84 Global variable or environment variable.
85 Pass `--trace-expand` to cmake if set.
86 ``<DEP_NAME>_VERBOSE_BUILD``
87 Global variable or environment variable.
88 Turn the build step to verbose mode if set.
Benedek Tomasik90bd41e2021-03-10 11:23:45 +000089 #]===]
90
91function(LazyFetch_ConfigAndBuild)
92 set(oneValueArgs DEP_NAME SRC_DIR BIN_DIR CACHE_FILE INSTALL_DIR)
93 cmake_parse_arguments(BUILD "${__options}" "${oneValueArgs}" "${_multipleValueArgs}" ${ARGN})
94 message(STATUS "Configuring and building ${BUILD_DEP_NAME}")
95
96 # Store config file in build dir, so it gets cleaned up
97 set(CONFIGURED_CACHE_FILE ${CMAKE_BINARY_DIR}/${BUILD_DEP_NAME}-init-cache.cmake)
98 configure_file(${BUILD_CACHE_FILE} ${CONFIGURED_CACHE_FILE} @ONLY)
99
Gyorgy Szing34aaf212022-10-20 07:26:23 +0200100 string(TOUPPER ${BUILD_DEP_NAME} UC_DEP_NAME)
101
102 if (NOT DEFINED ${UC_DEP_NAME}_BUILD_TYPE)
103 message(FATAL_ERROR "Build type for external component ${DEP_NAME} is not set. Please pass "
104 "-D${UC_DEP_NAME}_BUILD_TYPE=<build type> to cmake. Supported build types are"
105 "component specific. Pleas refer to the upstream documentation for more information.")
106 endif()
107
Gyorgy Szingf934bab2023-08-31 10:48:40 +0000108 if (DEFINED ${UC_DEP_NAME}_VERBOSE_CONFIG OR DEFINED ENV{${UC_DEP_NAME}_VERBOSE_CONFIG})
109 set(_CMAKE_VERBOSE_CFG_FLAG "--trace-expand")
110 endif()
111
Benedek Tomasik90bd41e2021-03-10 11:23:45 +0000112 execute_process(COMMAND
113 ${CMAKE_COMMAND} -E env "CROSS_COMPILE=${CROSS_COMPILE}"
114 ${CMAKE_COMMAND}
115 "-C${CONFIGURED_CACHE_FILE}"
Gyorgy Szingc3271e72023-04-18 15:44:49 +0200116 -DCMAKE_BUILD_TYPE=${${UC_DEP_NAME}_BUILD_TYPE}
Benedek Tomasik90bd41e2021-03-10 11:23:45 +0000117 -S ${BUILD_SRC_DIR}
118 -B ${BUILD_BIN_DIR}
Gyorgy Szingf934bab2023-08-31 10:48:40 +0000119 ${_CMAKE_VERBOSE_CFG_FLAG}
Benedek Tomasik90bd41e2021-03-10 11:23:45 +0000120 RESULT_VARIABLE
121 _exec_error
122 )
123 if (NOT _exec_error EQUAL 0)
124 message(FATAL_ERROR "Configuring ${BUILD_DEP_NAME} build failed. `${_exec_error}`")
125 endif()
126
Gyorgy Szingf934bab2023-08-31 10:48:40 +0000127 if (DEFINED ${UC_DEP_NAME}_VERBOSE_BUILD OR DEFINED ENV{${UC_DEP_NAME}_VERBOSE_BUILD})
128 set(_CMAKE_VERBOSE_CFG_FLAG "--verbose")
129 endif()
130
Benedek Tomasik90bd41e2021-03-10 11:23:45 +0000131 if (BUILD_INSTALL_DIR)
132 execute_process(COMMAND
133 ${CMAKE_COMMAND} -E env "CROSS_COMPILE=${CROSS_COMPILE}"
134 ${CMAKE_COMMAND}
135 --build ${BUILD_BIN_DIR}
136 --parallel ${PROCESSOR_COUNT}
137 --target install
Gyorgy Szingf934bab2023-08-31 10:48:40 +0000138 ${_CMAKE_VERBOSE_BLD_FLAG}
Benedek Tomasik90bd41e2021-03-10 11:23:45 +0000139 RESULT_VARIABLE
140 _exec_error
141 )
142 else()
143 execute_process(COMMAND
144 ${CMAKE_COMMAND} -E env "CROSS_COMPILE=${CROSS_COMPILE}"
145 ${CMAKE_COMMAND}
146 --build ${BUILD_BIN_DIR}
147 --parallel ${PROCESSOR_COUNT}
Gyorgy Szingf934bab2023-08-31 10:48:40 +0000148 ${_CMAKE_VERBOSE_BLD_FLAG}
Benedek Tomasik90bd41e2021-03-10 11:23:45 +0000149 RESULT_VARIABLE
150 _exec_error
151 )
152 endif()
153 if (NOT _exec_error EQUAL 0)
154 message(FATAL_ERROR "Building ${BUILD_DEP_NAME} failed. ${_exec_error}")
155 endif()
156endfunction()
157
158#[===[.rst:
159.. cmake:command:: LazyFetch_MakeAvailable
160
161 .. code:: cmake
162 LazyFetch_MakeAvailable(DEP_NAME <dependency name> INSTALL_DIR <install path>
163 PACKAGE_DIR <directory of moduleConfig.cmake file>
164 CACHE_FILE <path to the cache init file> FETCH_OPTIONS <options for the fetching process>)
165
166 INPUTS:
167 ``DEP_NAME``
168 If set, this path overwrites the default base path for the FetchContent process
169 ``SOURCE_DIR``
170 Location of source code.
171 ``INSTALL_DIR``
172 Build install path
173 ``PACKAGE_DIR``
174 If set find_package will search this directory for the config file
175 ``CACHE_FILE``
176 Path to the cache init file, setting cache variables in this file can be used to augment the
177 configure process. The file goes through the :cmake:function:`configure_file(... @ONLY)`, this
178 can be used to pass variables to the cache file
179 ``FETCH_OPTIONS``
180 Configure the dependency fetching process, this is passed to FetchContent_Declare, check the
181 cmake documentation for more info
182 ``SOURCE_SUBDIR``
183 A subdirectory relative to the top level directory of the fetched component, where the CMakeLists.txt file
184 can be found.
Gyorgy Szingf934bab2023-08-31 10:48:40 +0000185 ``<DEP_NAME>_VERBOSE_CONFIG``
186 Global variable or environment variable.
187 Pass `--trace-expand` to cmake if set.
188 ``<DEP_NAME>_VERBOSE_BUILD``
189 Global variable or environment variable.
190 Turn the build step to verbose mode if set.
Benedek Tomasik90bd41e2021-03-10 11:23:45 +0000191 #]===]
192
193macro(LazyFetch_MakeAvailable)
194 set(oneValueArgs DEP_NAME SOURCE_DIR BINARY_DIR INSTALL_DIR PACKAGE_DIR CACHE_FILE SOURCE_SUBDIR)
195 set(multipleValueArgs FETCH_OPTIONS)
196 cmake_parse_arguments(MY "${__options}" "${oneValueArgs}" "${multipleValueArgs}" ${ARGN})
197 message(STATUS "Looking for dependency ${MY_DEP_NAME}")
198
199 if (NOT DEFINED MY_DEP_NAME)
200 message(FATAL_ERROR "Mandatory parameter DEP_NAME is missing.")
201 endif()
202
203 # FetchContent* functions use this form
204 string(TOLOWER ${MY_DEP_NAME} MY_LC_DEP_NAME)
Gyorgy Szingf934bab2023-08-31 10:48:40 +0000205 # We also need the upper case version
206 string(TOUPPER ${MY_DEP_NAME} MY_UC_DEP_NAME)
Benedek Tomasik90bd41e2021-03-10 11:23:45 +0000207
Gyorgy Szing9882afb2022-07-19 08:13:00 +0000208 # Look for name collision. We can collide with project() commands, other external components defined with
209 # LazyFetch, FetchCOntent or ExternalProject.
210 if(DEFINED ${MY_LC_DEP_NAME}_BINARY_DIR AND NOT DEFINED ${MY_LC_DEP_NAME}_BINARY_DIR_LZF)
211 string(CONCAT _msg "External dependency name \"${MY_DEP_NAME}\" collides with a project or another external"
212 " dependency name.")
213 message(FATAL_ERROR ${_msg})
214 endif()
215 # This variable is used to avoid false colision detection when re-configuring the project.
216 set(${MY_LC_DEP_NAME}_BINARY_DIR_LZF On CACHE BOOL "")
217 mark_as_advanced(${MY_LC_DEP_NAME}_BINARY_DIR_LZF)
Benedek Tomasik90bd41e2021-03-10 11:23:45 +0000218 # These two variables are also set by the normal FetchContent process and users could depend on them,
219 # so they are not unset at the end of the macro
220 if (MY_BINARY_DIR)
221 set(${MY_LC_DEP_NAME}_BINARY_DIR ${MY_BINARY_DIR})
222 else()
Gyorgy Szing9882afb2022-07-19 08:13:00 +0000223 set(${MY_LC_DEP_NAME}_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/_deps/${MY_LC_DEP_NAME}-build)
Benedek Tomasik90bd41e2021-03-10 11:23:45 +0000224 endif()
Gyorgy Szing9882afb2022-07-19 08:13:00 +0000225 set(${MY_LC_DEP_NAME}_BINARY_DIR ${${MY_LC_DEP_NAME}_BINARY_DIR} CACHE PATH
226 "Build directory for ${MY_LC_DEP_NAME}" FORCE)
227
Benedek Tomasik90bd41e2021-03-10 11:23:45 +0000228 if (MY_SOURCE_DIR)
229 set(${MY_LC_DEP_NAME}_SOURCE_DIR ${MY_SOURCE_DIR})
230 else()
Gyorgy Szing9882afb2022-07-19 08:13:00 +0000231 set(${MY_LC_DEP_NAME}_SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/_deps/${MY_LC_DEP_NAME}-src)
Benedek Tomasik90bd41e2021-03-10 11:23:45 +0000232 endif()
Gyorgy Szing9882afb2022-07-19 08:13:00 +0000233 set(${MY_LC_DEP_NAME}_SOURCE_DIR ${${MY_LC_DEP_NAME}_SOURCE_DIR} CACHE PATH
234 "Source directory for ${MY_LC_DEP_NAME}" FORCE)
Benedek Tomasik90bd41e2021-03-10 11:23:45 +0000235
Gyorgy Szing9882afb2022-07-19 08:13:00 +0000236 set(${MY_LC_DEP_NAME}_SUBBUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/_deps/${MY_LC_DEP_NAME}-subbuild CACHE
237 STRING "Sub-build directory for ${MY_LC_DEP_NAME}")
Benedek Tomasik90bd41e2021-03-10 11:23:45 +0000238
239 list(APPEND MY_FETCH_OPTIONS
240 SOURCE_DIR "${${MY_LC_DEP_NAME}_SOURCE_DIR}"
241 BINARY_DIR "${${MY_LC_DEP_NAME}_BINARY_DIR}"
242 SUBBUILD_DIR "${${MY_LC_DEP_NAME}_SUBBUILD_DIR}")
243
244 if (NOT DEFINED MY_INSTALL_DIR OR NOT EXISTS ${MY_INSTALL_DIR})
245 if (NOT EXISTS ${${MY_LC_DEP_NAME}_BINARY_DIR} OR NOT EXISTS ${${MY_LC_DEP_NAME}_SOURCE_DIR})
246 if (NOT EXISTS ${${MY_LC_DEP_NAME}_SOURCE_DIR})
247 LazyFetch_Fetch(${MY_LC_DEP_NAME} "${MY_FETCH_OPTIONS}")
248 file(REMOVE_RECURSE "${${MY_LC_DEP_NAME}_BINARY_DIR}")
249 file(REMOVE_RECURSE "${${MY_LC_DEP_NAME}_SUBBUILD_DIR}")
250 endif()
251 if (MY_CACHE_FILE)
252 LazyFetch_ConfigAndBuild(
253 DEP_NAME ${MY_LC_DEP_NAME}
254 SRC_DIR ${${MY_LC_DEP_NAME}_SOURCE_DIR}/${MY_SOURCE_SUBDIR}
255 BIN_DIR ${${MY_LC_DEP_NAME}_BINARY_DIR}
256 CACHE_FILE ${MY_CACHE_FILE}
257 INSTALL_DIR ${MY_INSTALL_DIR}
258 )
259 endif()
260 elseif(DEFINED MY_INSTALL_DIR)
Gyorgy Szingf934bab2023-08-31 10:48:40 +0000261 if(DEFINED ${MY_UC_DEP_NAME}_VERBOSE_BUILD OR DEFINED ENV{${MY_UC_DEP_NAME}_VERBOSE_BUILD})
262 set(_CMAKE_VERBOSE_BLD_FLAG "--verbose")
263 endif()
264
Benedek Tomasik90bd41e2021-03-10 11:23:45 +0000265 execute_process(COMMAND
266 ${CMAKE_COMMAND} -E env "CROSS_COMPILE=${CROSS_COMPILE}"
267 ${CMAKE_COMMAND}
268 --build ${${MY_LC_DEP_NAME}_BINARY_DIR}
269 --parallel ${PROCESSOR_COUNT}
270 --target install
Gyorgy Szingf934bab2023-08-31 10:48:40 +0000271 ${_CMAKE_VERBOSE_BLD_FLAG}
Benedek Tomasik90bd41e2021-03-10 11:23:45 +0000272 RESULT_VARIABLE
273 _exec_error
274 )
275 if (NOT _exec_error EQUAL 0)
276 message(FATAL_ERROR "Installing ${BUILD_DEP_NAME} failed. ${_exec_error}")
277 endif()
278 endif()
279 endif()
280
281 # Run find_package again if we just needed the build and install step
282 if (MY_PACKAGE_DIR)
283 unset(${MY_LC_DEP_NAME}_DIR)
284 unset(${MY_LC_DEP_NAME}_DIR CACHE)
285 unset(${MY_DEP_NAME}-FOUND CACHE)
286 find_package(${MY_DEP_NAME} CONFIG REQUIRED NO_DEFAULT_PATH PATHS ${MY_PACKAGE_DIR})
287 set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${MY_DEP_NAME}_CONFIG)
288 endif()
289
290 unset(MY_DEP_NAME)
291 unset(MY_SOURCE_DIR)
292 unset(MY_BINARY_DIR)
293 unset(MY_INSTALL_DIR)
294 unset(MY_PACKAGE_DIR)
295 unset(MY_CACHE_FILE)
296 unset(MY_SOURCE_SUBDIR)
297 unset(MY_FETCH_OPTIONS)
298 unset(MY_LC_DEP_NAME)
299 unset(oneValueArgs)
300 unset(multipleValueArgs)
301endmacro()