ctkMacroCheckExternalProjectDependency.cmake 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022
  1. #.rst:
  2. # ExternalProjectDependency
  3. # -------------------------
  4. #
  5. # .. only:: html
  6. #
  7. # .. contents::
  8. ###########################################################################
  9. #
  10. # Library: CTK
  11. #
  12. # Copyright (c) Kitware Inc.
  13. #
  14. # Licensed under the Apache License, Version 2.0 (the "License");
  15. # you may not use this file except in compliance with the License.
  16. # You may obtain a copy of the License at
  17. #
  18. # http://www.apache.org/licenses/LICENSE-2.0.txt
  19. #
  20. # Unless required by applicable law or agreed to in writing, software
  21. # distributed under the License is distributed on an "AS IS" BASIS,
  22. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  23. # See the License for the specific language governing permissions and
  24. # limitations under the License.
  25. #
  26. ###########################################################################
  27. include(CMakeParseArguments)
  28. #.rst:
  29. # Global Variables
  30. # ^^^^^^^^^^^^^^^^
  31. #.rst:
  32. # .. cmake:variable:: EXTERNAL_PROJECT_DIR
  33. #
  34. # This variable describes the directory in which external project files
  35. # matching ``<EXTERNAL_PROJECT_FILE_PREFIX><projectname>.cmake`` expression are globbed.
  36. #
  37. if(NOT EXISTS "${EXTERNAL_PROJECT_DIR}")
  38. set(EXTERNAL_PROJECT_DIR ${CMAKE_SOURCE_DIR}/SuperBuild)
  39. endif()
  40. #.rst:
  41. # .. cmake:variable:: EXTERNAL_PROJECT_ADDITIONAL_DIR
  42. #
  43. # If set, this variable represents an other directory in which external project files
  44. # are searched for if not already found in ``EXTERNAL_PROJECT_DIR``.
  45. #.rst:
  46. # .. cmake:variable:: EXTERNAL_PROJECT_FILE_PREFIX
  47. #
  48. # This variable describes the prefix of the external project files looked up in
  49. # ``EXTERNAL_PROJECT_DIR``. It defaults to ``External_``.
  50. #
  51. if(NOT DEFINED EXTERNAL_PROJECT_FILE_PREFIX)
  52. set(EXTERNAL_PROJECT_FILE_PREFIX "External_")
  53. endif()
  54. #.rst:
  55. # .. cmake:variable:: SUPERBUILD_TOPLEVEL_PROJECT
  56. #
  57. # This variable can be set to explicitly identify the name of the top-level project.
  58. # If not set, it default to the value of ``CMAKE_PROJECT_NAME``.
  59. if(NOT DEFINED SUPERBUILD_TOPLEVEL_PROJECT)
  60. if(NOT DEFINED CMAKE_PROJECT_NAME)
  61. message(FATAL_ERROR "Failed to initialize variable SUPERBUILD_TOPLEVEL_PROJECT. Variable CMAKE_PROJECT_NAME is not defined.")
  62. endif()
  63. set(SUPERBUILD_TOPLEVEL_PROJECT ${CMAKE_PROJECT_NAME})
  64. endif()
  65. #.rst:
  66. # .. cmake:variable:: EP_LIST_SEPARATOR
  67. #
  68. # This variable is used to separate list items when passed in various external project
  69. # ``..._COMMAND`` options.
  70. #
  71. # If defaults to ``^^``.
  72. if(NOT DEFINED EP_LIST_SEPARATOR)
  73. set(EP_LIST_SEPARATOR "^^")
  74. endif()
  75. #.rst:
  76. # .. cmake:variable:: EP_GIT_PROTOCOL
  77. #
  78. # The value of this variable is controled by the option ``<SUPERBUILD_TOPLEVEL_PROJECT>_USE_GIT_PROTOCOL``
  79. # automatically defined by including this CMake module. Setting this option allows to update the value of
  80. # ``EP_GIT_PROTOCOL`` variable.
  81. #
  82. # If enabled, the variable ``EP_GIT_PROTOCOL`` is set to ``git``. Otherwise, it is set to ``https``.
  83. # The option is enabled by default.
  84. #
  85. # The variable ``EP_GIT_PROTOCOL`` can be used when adding external project. For example:
  86. #
  87. # .. code-block:: cmake
  88. #
  89. # ExternalProject_Add(${proj}
  90. # ${${proj}_EP_ARGS}
  91. # GIT_REPOSITORY "${EP_GIT_PROTOCOL}://github.com/Foo/Foo.git"
  92. # [...]
  93. # )
  94. #
  95. option(${SUPERBUILD_TOPLEVEL_PROJECT}_USE_GIT_PROTOCOL "If behind a firewall turn this off to use https instead." ON)
  96. set(EP_GIT_PROTOCOL "git")
  97. if(NOT ${SUPERBUILD_TOPLEVEL_PROJECT}_USE_GIT_PROTOCOL)
  98. set(EP_GIT_PROTOCOL "https")
  99. endif()
  100. # Compute -G arg for configuring external projects with the same CMake generator:
  101. if(CMAKE_EXTRA_GENERATOR)
  102. set(EP_CMAKE_GENERATOR "${CMAKE_EXTRA_GENERATOR} - ${CMAKE_GENERATOR}")
  103. else()
  104. set(EP_CMAKE_GENERATOR "${CMAKE_GENERATOR}")
  105. endif()
  106. set(EP_CMAKE_GENERATOR_PLATFORM "${CMAKE_GENERATOR_PLATFORM}")
  107. set(EP_CMAKE_GENERATOR_TOOLSET "${CMAKE_GENERATOR_TOOLSET}")
  108. #.rst:
  109. # Functions
  110. # ^^^^^^^^^
  111. #.rst:
  112. # .. cmake:function:: mark_as_superbuild
  113. #
  114. # .. code-block:: cmake
  115. #
  116. # mark_as_superbuild(<varname1>[:<vartype1>] [<varname2>[:<vartype2>] [...]])
  117. #
  118. # .. code-block:: cmake
  119. #
  120. # mark_as_superbuild(
  121. # VARS <varname1>[:<vartype1>] [<varname2>[:<vartype2>] [...]]
  122. # [PROJECTS <projectname> [<projectname> [...]] | ALL_PROJECTS]
  123. # [LABELS <label1> [<label2> [...]]]
  124. # )
  125. #
  126. # .. code-block:: cmake
  127. #
  128. # PROJECTS corresponds to a list of <projectname> that will be added using 'ExternalProject_Add' function.
  129. # If not specified and called within a project file, it defaults to the value of 'SUPERBUILD_TOPLEVEL_PROJECT'.
  130. # If instead 'ALL_PROJECTS' is specified, the variables and labels will be passed to all projects.
  131. #
  132. # VARS is an expected list of variables specified as <varname>:<vartype> to pass to <projectname>
  133. #
  134. #
  135. # LABELS is an optional list of label to associate with the variable names specified using 'VARS' and passed to
  136. # the <projectname> as CMake CACHE args of the form:
  137. # -D<projectname>_EP_LABEL_<label1>=<varname1>;<varname2>[...]
  138. # -D<projectname>_EP_LABEL_<label2>=<varname1>;<varname2>[...]
  139. #
  140. function(mark_as_superbuild)
  141. set(options ALL_PROJECTS CMAKE_CMD)
  142. set(oneValueArgs)
  143. set(multiValueArgs VARS PROJECTS LABELS)
  144. cmake_parse_arguments(_sb "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  145. set(_vars ${_sb_UNPARSED_ARGUMENTS})
  146. set(_named_parameters_expected 0)
  147. if(_sb_PROJECTS OR _sb_ALL_PROJECTS OR _sb_LABELS OR _sb_VARS)
  148. set(_named_parameters_expected 1)
  149. set(_vars ${_sb_VARS})
  150. endif()
  151. if(_named_parameters_expected AND _sb_UNPARSED_ARGUMENTS)
  152. message(FATAL_ERROR "Arguments '${_sb_UNPARSED_ARGUMENTS}' should be associated with VARS parameter !")
  153. endif()
  154. if(_sb_PROJECTS AND _sb_ALL_PROJECTS)
  155. message(FATAL_ERROR "Arguments 'PROJECTS' and 'ALL_PROJECTS' are mutually exclusive !")
  156. endif()
  157. foreach(var ${_vars})
  158. set(_type_specified 0)
  159. if(var MATCHES ":")
  160. set(_type_specified 1)
  161. endif()
  162. # XXX Display warning with variable type is also specified for cache variable.
  163. set(_var ${var})
  164. if(NOT _type_specified)
  165. get_property(_type_set_in_cache CACHE ${_var} PROPERTY TYPE SET)
  166. set(_var_name ${_var})
  167. set(_var_type "STRING")
  168. if(_type_set_in_cache)
  169. get_property(_var_type CACHE ${_var_name} PROPERTY TYPE)
  170. endif()
  171. set(_var ${_var_name}:${_var_type})
  172. endif()
  173. list(APPEND _vars_with_type ${_var})
  174. endforeach()
  175. if(_sb_ALL_PROJECTS)
  176. set(optional_arg_ALL_PROJECTS "ALL_PROJECTS")
  177. else()
  178. set(optional_arg_ALL_PROJECTS PROJECTS ${_sb_PROJECTS})
  179. endif()
  180. _sb_append_to_cmake_args(
  181. VARS ${_vars_with_type} LABELS ${_sb_LABELS} ${optional_arg_ALL_PROJECTS})
  182. endfunction()
  183. #
  184. # _sb_extract_varname_and_vartype(<cmake_varname_and_type> <varname_var> [<vartype_var>])
  185. #
  186. # <cmake_varname_and_type> corresponds to variable name and variable type passed as "<varname>:<vartype>"
  187. #
  188. # <varname_var> will be set to "<varname>"
  189. #
  190. # <vartype_var> is an optional variable name that will be set to "<vartype>"
  191. #
  192. function(_sb_extract_varname_and_vartype cmake_varname_and_type varname_var)
  193. set(_vartype_var "${ARGV2}")
  194. string(REPLACE ":" ";" varname_and_vartype ${cmake_varname_and_type})
  195. list(GET varname_and_vartype 0 _varname)
  196. list(GET varname_and_vartype 1 _vartype)
  197. set(${varname_var} ${_varname} PARENT_SCOPE)
  198. if(_vartype_var MATCHES ".+")
  199. set(${_vartype_var} ${_vartype} PARENT_SCOPE)
  200. endif()
  201. endfunction()
  202. function(_sb_list_to_string separator input_list output_string_var)
  203. set(_string "")
  204. # Get list length
  205. list(LENGTH input_list list_length)
  206. # If the list has 0 or 1 element, there is no need to loop over.
  207. if(list_length LESS 2)
  208. set(_string "${input_list}")
  209. else()
  210. math(EXPR last_element_index "${list_length} - 1")
  211. foreach(index RANGE ${last_element_index})
  212. # Get current item_value
  213. list(GET input_list ${index} item_value)
  214. if(NOT item_value STREQUAL "")
  215. # .. and append non-empty value to output string
  216. set(_string "${_string}${item_value}")
  217. # Append separator if current element is NOT the last one.
  218. if(NOT index EQUAL last_element_index)
  219. set(_string "${_string}${separator}")
  220. endif()
  221. endif()
  222. endforeach()
  223. endif()
  224. set(${output_string_var} ${_string} PARENT_SCOPE)
  225. endfunction()
  226. #
  227. # _sb_cmakevar_to_cmakearg(<cmake_varname_and_type> <cmake_arg_var> <has_cfg_intdir_var> [<varname_var> [<vartype_var>]])
  228. #
  229. # <cmake_varname_and_type> corresponds to variable name and variable type passed as "<varname>:<vartype>"
  230. #
  231. # <cmake_arg_var> is a variable name that will be set to "-D<varname>:<vartype>=${<varname>}"
  232. #
  233. # <has_int_dir_var> is set to either TRUE or FALSE.
  234. # FALSE means that the value does NOT reference ${CMAKE_CFG_INTDIR} and
  235. # the generated cmake argument should be passed to ExternalProject_Add as CMAKE_CACHE_ARGS.
  236. # TRUEmeans that the value does reference ${CMAKE_CFG_INTDIR} and
  237. # the generated cmake argument should be passed to ExternalProject_Add as CMAKE_ARGS.
  238. #
  239. # <varname_var> is an optional variable name that will be set to "<varname>"
  240. #
  241. # <vartype_var> is an optional variable name that will be set to "<vartype>"
  242. #
  243. function(_sb_cmakevar_to_cmakearg cmake_varname_and_type cmake_arg_var has_cfg_intdir_var)
  244. set(_varname_var "${ARGV3}")
  245. set(_vartype_var "${ARGV4}")
  246. _sb_extract_varname_and_vartype(${cmake_varname_and_type} _varname _vartype)
  247. set(_var_value "${${_varname}}")
  248. # Use cache value unless it is INTERNAL
  249. if(_vartype STREQUAL "INTERNAL")
  250. set(_vartype "STRING")
  251. else()
  252. get_property(_value_set_in_cache CACHE ${_varname} PROPERTY VALUE SET)
  253. if(_value_set_in_cache)
  254. get_property(_var_value CACHE ${_varname} PROPERTY VALUE)
  255. endif()
  256. endif()
  257. set(_has_cfg_intdir FALSE)
  258. if(CMAKE_CONFIGURATION_TYPES)
  259. string(FIND "${_var_value}" ${CMAKE_CFG_INTDIR} _index)
  260. if(NOT _index EQUAL -1)
  261. # Separate list item with <EP_LIST_SEPARATOR>
  262. _sb_list_to_string(${EP_LIST_SEPARATOR} "${_var_value}" _var_value)
  263. set(_has_cfg_intdir TRUE)
  264. endif()
  265. endif()
  266. if(NOT _has_cfg_intdir)
  267. string(REPLACE "\"" "\\\"" _var_value "${_var_value}")
  268. endif()
  269. set(${cmake_arg_var} -D${_varname}:${_vartype}=${_var_value} PARENT_SCOPE)
  270. set(${has_cfg_intdir_var} ${_has_cfg_intdir} PARENT_SCOPE)
  271. if(_varname_var MATCHES ".+")
  272. set(${_varname_var} ${_varname} PARENT_SCOPE)
  273. endif()
  274. if(_vartype_var MATCHES ".+")
  275. set(${_vartype_var} ${_vartype} PARENT_SCOPE)
  276. endif()
  277. endfunction()
  278. set(_ALL_PROJECT_IDENTIFIER "ALLALLALL")
  279. #
  280. # _sb_append_to_cmake_args(
  281. # [VARS <varname1>:<vartype1> [<varname2>:<vartype2> [...]]]
  282. # [PROJECTS <projectname> [<projectname> [...]] | ALL_PROJECTS]
  283. # [LABELS <label1> [<label2> [...]]]
  284. # )
  285. #
  286. # PROJECTS corresponds to a list of <projectname> that will be added using 'ExternalProject_Add' function.
  287. # If not specified and called within a project file, it defaults to the value of 'SUPERBUILD_TOPLEVEL_PROJECT'.
  288. # If instead 'ALL_PROJECTS' is specified, the variables and labels will be passed to all projects.
  289. #
  290. # VARS is an expected list of variables specified as <varname>:<vartype> to pass to <projectname>
  291. #
  292. #
  293. # LABELS is an optional list of label to associate with the variable names specified using 'VARS' and passed to
  294. # the <projectname> as CMake CACHE args of the form:
  295. # -D<projectname>_EP_LABEL_<label1>=<varname1>;<varname2>[...]
  296. # -D<projectname>_EP_LABEL_<label2>=<varname1>;<varname2>[...]
  297. #
  298. function(_sb_append_to_cmake_args)
  299. set(options ALL_PROJECTS)
  300. set(oneValueArgs)
  301. set(multiValueArgs VARS PROJECTS LABELS)
  302. cmake_parse_arguments(_sb "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  303. if(NOT _sb_PROJECTS AND NOT _sb_ALL_PROJECTS)
  304. set(_sb_PROJECTS ${SUPERBUILD_TOPLEVEL_PROJECT})
  305. endif()
  306. if(_sb_ALL_PROJECTS)
  307. set(_sb_PROJECTS ${_ALL_PROJECT_IDENTIFIER})
  308. endif()
  309. foreach(_sb_PROJECT ${_sb_PROJECTS})
  310. set(_ep_varnames "")
  311. foreach(varname_and_vartype ${_sb_VARS})
  312. if(NOT TARGET ${_sb_PROJECT})
  313. set_property(GLOBAL APPEND PROPERTY ${_sb_PROJECT}_EP_CMAKE_ARGS ${varname_and_vartype})
  314. _sb_extract_varname_and_vartype(${varname_and_vartype} _varname)
  315. else()
  316. message(FATAL_ERROR "Function _sb_append_to_cmake_args not allowed because project '${_sb_PROJECT}' already added !")
  317. endif()
  318. list(APPEND _ep_varnames ${_varname})
  319. endforeach()
  320. if(_sb_LABELS)
  321. set_property(GLOBAL APPEND PROPERTY ${_sb_PROJECT}_EP_LABELS ${_sb_LABELS})
  322. foreach(label ${_sb_LABELS})
  323. set_property(GLOBAL APPEND PROPERTY ${_sb_PROJECT}_EP_LABEL_${label} ${_ep_varnames})
  324. endforeach()
  325. endif()
  326. endforeach()
  327. endfunction()
  328. #.rst:
  329. # .. cmake:function:: ExternalProject_DeclareLabels
  330. #
  331. # .. code-block:: cmake
  332. #
  333. # ExternalProject_DeclareLabels(
  334. # [PROJECTS <projectname> [<projectname> [...]] | ALL_PROJECTS]
  335. # LABELS <label1> [<label2> [...]]
  336. # )
  337. #
  338. # .. code-block:: cmake
  339. #
  340. # PROJECTS corresponds to a list of <projectname> that will be added using 'ExternalProject_Add' function.
  341. # If not specified and called within a project file, it defaults to the value of 'SUPERBUILD_TOPLEVEL_PROJECT'.
  342. # If instead 'ALL_PROJECTS' is specified, the variables and labels will be passed to all projects.
  343. #
  344. # LABELS is a list of label to pass to the <projectname> as CMake CACHE args of the
  345. # form -D<projectname>_EP_LABEL_<label>= unless specific variables
  346. # have been associated with the labels using mark_as_superbuild.
  347. #
  348. function(ExternalProject_DeclareLabels)
  349. set(options ALL_PROJECTS)
  350. set(oneValueArgs)
  351. set(multiValueArgs PROJECTS LABELS)
  352. cmake_parse_arguments(_sb "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  353. if(_sb_PROJECTS AND _sb_ALL_PROJECTS)
  354. message(FATAL_ERROR "Arguments 'PROJECTS' and 'ALL_PROJECTS' are mutually exclusive !")
  355. endif()
  356. if(_sb_ALL_PROJECTS)
  357. set(optional_arg_ALL_PROJECTS "ALL_PROJECTS")
  358. else()
  359. set(optional_arg_ALL_PROJECTS PROJECTS ${_sb_PROJECTS})
  360. endif()
  361. _sb_append_to_cmake_args(
  362. LABELS ${_sb_LABELS} ${optional_arg_ALL_PROJECTS})
  363. endfunction()
  364. function(_sb_get_external_project_arguments proj varname)
  365. mark_as_superbuild(${SUPERBUILD_TOPLEVEL_PROJECT}_USE_SYSTEM_${proj}:BOOL)
  366. function(_sb_collect_args proj)
  367. # Set list of CMake args associated with each label
  368. get_property(_labels GLOBAL PROPERTY ${proj}_EP_LABELS)
  369. if(_labels)
  370. list(REMOVE_DUPLICATES _labels)
  371. foreach(label ${_labels})
  372. get_property(${proj}_EP_LABEL_${label} GLOBAL PROPERTY ${proj}_EP_LABEL_${label})
  373. if(${proj}_EP_LABEL_${label})
  374. list(REMOVE_DUPLICATES ${proj}_EP_LABEL_${label})
  375. endif()
  376. _sb_append_to_cmake_args(PROJECTS ${proj}
  377. VARS ${proj}_EP_LABEL_${label}:STRING)
  378. endforeach()
  379. endif()
  380. get_property(_args GLOBAL PROPERTY ${proj}_EP_CMAKE_ARGS)
  381. foreach(var ${_args})
  382. _sb_cmakevar_to_cmakearg(${var} cmake_arg _has_cfg_intdir)
  383. set(_ep_property "CMAKE_CACHE_ARGS")
  384. if(_has_cfg_intdir)
  385. set(_ep_property "CMAKE_ARGS")
  386. endif()
  387. set_property(GLOBAL APPEND PROPERTY ${proj}_EP_PROPERTY_${_ep_property} ${cmake_arg})
  388. endforeach()
  389. endfunction()
  390. _sb_collect_args(${proj})
  391. _sb_collect_args(${_ALL_PROJECT_IDENTIFIER})
  392. set(_ep_arguments "")
  393. # Automatically propagate CMake options
  394. foreach(_cmake_option IN ITEMS
  395. CMAKE_EXPORT_COMPILE_COMMANDS
  396. CMAKE_JOB_POOL_COMPILE
  397. CMAKE_JOB_POOL_LINK
  398. CMAKE_JOB_POOLS
  399. )
  400. if(DEFINED ${_cmake_option})
  401. list(APPEND _ep_arguments CMAKE_CACHE_ARGS
  402. -D${_cmake_option}:BOOL=${${_cmake_option}}
  403. )
  404. endif()
  405. endforeach()
  406. foreach(property CMAKE_ARGS CMAKE_CACHE_ARGS)
  407. get_property(${proj}_EP_PROPERTY_${property} GLOBAL PROPERTY ${proj}_EP_PROPERTY_${property})
  408. get_property(${_ALL_PROJECT_IDENTIFIER}_EP_PROPERTY_${property} GLOBAL PROPERTY ${_ALL_PROJECT_IDENTIFIER}_EP_PROPERTY_${property})
  409. set(_all ${${proj}_EP_PROPERTY_${property}} ${${_ALL_PROJECT_IDENTIFIER}_EP_PROPERTY_${property}})
  410. list(LENGTH _all _num_properties)
  411. if(_num_properties GREATER 0)
  412. list(APPEND _ep_arguments ${property} ${_all})
  413. endif()
  414. endforeach()
  415. list(APPEND _ep_arguments LIST_SEPARATOR ${EP_LIST_SEPARATOR})
  416. list(APPEND _ep_arguments CMAKE_GENERATOR ${_sb_CMAKE_GENERATOR})
  417. if(CMAKE_VERSION VERSION_GREATER "3.0")
  418. list(APPEND _ep_arguments CMAKE_GENERATOR_PLATFORM ${_sb_CMAKE_GENERATOR_PLATFORM})
  419. endif()
  420. list(APPEND _ep_arguments CMAKE_GENERATOR_TOOLSET ${_sb_CMAKE_GENERATOR_TOOLSET})
  421. if(CMAKE_VERSION VERSION_EQUAL "3.4" OR CMAKE_VERSION VERSION_GREATER "3.4")
  422. # USES_TERMINAL_* options were introduced in CMake 3.4
  423. foreach(step IN ITEMS DOWNLOAD UPDATE CONFIGURE BUILD TEST INSTALL)
  424. list(APPEND _ep_arguments
  425. USES_TERMINAL_${step} 1
  426. )
  427. endforeach()
  428. endif()
  429. set(${varname} ${_ep_arguments} PARENT_SCOPE)
  430. endfunction()
  431. function(_sb_update_indent proj)
  432. superbuild_stack_size(SB_PROJECT_STACK _stack_size)
  433. set(_indent "")
  434. if(_stack_size GREATER 0)
  435. foreach(not_used RANGE 1 ${_stack_size})
  436. set(_indent " ${_indent}")
  437. endforeach()
  438. endif()
  439. set_property(GLOBAL PROPERTY SUPERBUILD_${proj}_INDENT ${_indent})
  440. endfunction()
  441. #.rst:
  442. # .. cmake:function:: ExternalProject_Message
  443. #
  444. # .. code-block:: cmake
  445. #
  446. # ExternalProject_Message(<project_name> <msg> [condition])
  447. #
  448. function(ExternalProject_Message proj msg)
  449. set(_display 1)
  450. if(NOT "x${ARGV2}" STREQUAL "x")
  451. set(_display ${ARGN})
  452. endif()
  453. if(${_display})
  454. get_property(_indent GLOBAL PROPERTY SUPERBUILD_${proj}_INDENT)
  455. message(STATUS "SuperBuild - ${_indent}${msg}")
  456. endif()
  457. endfunction()
  458. #
  459. # superbuild_stack_content(<stack_name> <output_var>)
  460. #
  461. # <stack_name> corresponds to the name of stack.
  462. #
  463. # <output_var> is the name of CMake variable that will be set with the content
  464. # of the stack identified by <stack_name>.
  465. #
  466. function(superbuild_stack_content stack_name output_var)
  467. get_property(_stack GLOBAL PROPERTY ${stack_name})
  468. set(${output_var} ${_stack} PARENT_SCOPE)
  469. endfunction()
  470. #
  471. # superbuild_stack_size(<stack_name> <output_var>)
  472. #
  473. # <stack_name> corresponds to the name of stack.
  474. #
  475. # <output_var> is the name of CMake variable that will be set with the size
  476. # of the stack identified by <stack_name>.
  477. #
  478. function(superbuild_stack_size stack_name output_var)
  479. get_property(_stack GLOBAL PROPERTY ${stack_name})
  480. list(LENGTH _stack _stack_size)
  481. set(${output_var} ${_stack_size} PARENT_SCOPE)
  482. endfunction()
  483. #
  484. # superbuild_stack_push(<stack_name> <value>)
  485. #
  486. # <stack_name> corresponds to the name of stack.
  487. #
  488. # <value> is appended to the stack identified by <stack_name>.
  489. #
  490. function(superbuild_stack_push stack_name value)
  491. set_property(GLOBAL APPEND PROPERTY ${stack_name} ${value})
  492. endfunction()
  493. #
  494. # superbuild_stack_pop(<stack_name> <item_var>)
  495. #
  496. # <stack_name> corresponds to the name of stack.
  497. #
  498. # <item_var> names a CMake variable that will be set with the item
  499. # removed from the stack identified by <stack_name>
  500. #
  501. function(superbuild_stack_pop stack_name item_var)
  502. get_property(_stack GLOBAL PROPERTY ${stack_name})
  503. list(LENGTH _stack _stack_size)
  504. if(_stack_size GREATER 0)
  505. math(EXPR _index_to_remove "${_stack_size} - 1")
  506. list(GET _stack ${_index_to_remove} _item)
  507. list(REMOVE_AT _stack ${_index_to_remove})
  508. set_property(GLOBAL PROPERTY ${stack_name} ${_stack})
  509. set(${item_var} ${_item} PARENT_SCOPE)
  510. endif()
  511. endfunction()
  512. function(_sb_is_optional proj output_var)
  513. set(_include_project 1)
  514. if(COMMAND superbuild_is_external_project_includable)
  515. superbuild_is_external_project_includable("${proj}" _include_project)
  516. endif()
  517. set(optional 1)
  518. if(_include_project)
  519. set(optional 0)
  520. endif()
  521. set(${output_var} ${optional} PARENT_SCOPE)
  522. endfunction()
  523. #.rst:
  524. # .. cmake:function:: ExternalProject_Include_Dependencies
  525. #
  526. # .. code-block:: cmake
  527. #
  528. # ExternalProject_Include_Dependencies(<project_name>
  529. # [PROJECT_VAR <project_var>]
  530. # [EP_ARGS_VAR <external_project_args_var>]
  531. # [DEPENDS_VAR <depends_var>]
  532. # [USE_SYSTEM_VAR <use_system_var>]
  533. # [SUPERBUILD_VAR <superbuild_var>]
  534. # [CMAKE_GENERATOR <cmake_generator>]
  535. # [CMAKE_GENERATOR_PLATFORM <cmake_generator_platform>]
  536. # [CMAKE_GENERATOR_TOOLSET <cmake_generator_toolset>]
  537. # )
  538. #
  539. #
  540. # .. code-block:: cmake
  541. #
  542. # PROJECT_VAR Name of the variable containing the name of the included project.
  543. # By default, it is `proj` and it is set to `<project_name>`.
  544. #
  545. # EP_ARGS_VAR Name of the variable listing arguments to pass to ExternalProject.
  546. # If not specified, variable name default to `<project_name>_EP_ARGS`.
  547. #
  548. # DEPENDS_VAR Name of the variable containing the dependency of the included project.
  549. # By default, it is `<project_name>_DEPENDS`.
  550. #
  551. #
  552. # USE_SYSTEM_VAR Name of the variable indicating if the system version of <project_name>
  553. # should be looked up. Lookup of the project is left to the developer implementing
  554. # the external project file.
  555. # By default, it is `<SUPERBUILD_TOPLEVEL_PROJECT>_USE_SYSTEM_<project_name>`.
  556. #
  557. # SUPERBUILD_VAR Name of the variable indicating if the top-level or inner project is being built.
  558. # By default, it is `<SUPERBUILD_TOPLEVEL_PROJECT>_SUPERBUILD`.
  559. #
  560. #
  561. # CMAKE_GENERATOR
  562. # CMAKE_GENERATOR_PLATFORM
  563. # CMAKE_GENERATOR_TOOLSET These three options allow to overwrite the values set in the top-level project that
  564. # would otherwise automatically be propagated to dependent projects.
  565. #
  566. macro(ExternalProject_Include_Dependencies project_name)
  567. set(options)
  568. set(oneValueArgs PROJECT_VAR DEPENDS_VAR EP_ARGS_VAR USE_SYSTEM_VAR SUPERBUILD_VAR
  569. CMAKE_GENERATOR
  570. CMAKE_GENERATOR_PLATFORM
  571. CMAKE_GENERATOR_TOOLSET
  572. )
  573. set(multiValueArgs)
  574. cmake_parse_arguments(_sb "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  575. # Sanity checks
  576. if(x${project_name} STREQUAL xPROJECT_VAR
  577. OR x${project_name} STREQUAL xEP_ARGS_VAR
  578. OR x${project_name} STREQUAL xDEPENDS_VAR
  579. OR x${project_name} STREQUAL xUSE_SYSTEM_VAR
  580. OR x${project_name} STREQUAL xSUPERBUILD_VAR
  581. OR x${project_name} STREQUAL xCMAKE_GENERATOR
  582. OR x${project_name} STREQUAL xCMAKE_GENERATOR_PLATFORM
  583. OR x${project_name} STREQUAL xCMAKE_GENERATOR_TOOLSET
  584. )
  585. message(FATAL_ERROR "Argument <project_name> is missing !")
  586. endif()
  587. if(_sb_UNPARSED_ARGUMENTS)
  588. message(FATAL_ERROR "Invalid arguments: ${_sb_UNPARSED_ARGUMENTS}")
  589. endif()
  590. # Set default for optional PROJECT_VAR parameter
  591. if(NOT _sb_PROJECT_VAR)
  592. set(_sb_PROJECT_VAR proj)
  593. set(${_sb_PROJECT_VAR} ${project_name})
  594. #message("[${project_name}] Setting _sb_PROJECT_VAR with default value '${_sb_PROJECT_VAR}'")
  595. endif()
  596. if(_sb_PROJECT_VAR AND NOT x${project_name} STREQUAL x${${_sb_PROJECT_VAR}})
  597. message(FATAL_ERROR
  598. "Argument <project_name>:${project_name} and PROJECT_VAR:${_sb_PROJECT_VAR}:${${_sb_PROJECT_VAR}} are different !")
  599. endif()
  600. set(_sb_proj ${project_name})
  601. # Skip if project already included
  602. get_property(_is_included GLOBAL PROPERTY SB_${_sb_proj}_FILE_INCLUDED)
  603. if(_is_included)
  604. return()
  605. endif()
  606. # Set default for optional DEPENDS_VAR and EP_ARGS parameters
  607. foreach(param DEPENDS EP_ARGS)
  608. if(NOT _sb_${param}_VAR)
  609. set(_sb_${param}_VAR ${_sb_proj}_${param})
  610. #message("[${project_name}] Setting _sb_${param}_VAR with default value '${_sb_${param}_VAR}'")
  611. endif()
  612. endforeach()
  613. # Set top level project
  614. superbuild_stack_size(SB_PROJECT_STACK _stack_size)
  615. if(_stack_size EQUAL 0)
  616. set(SUPERBUILD_TOPLEVEL_PROJECT ${_sb_proj})
  617. endif()
  618. # Set default for optional USE_SYSTEM_VAR parameter
  619. if(NOT _sb_USE_SYSTEM_VAR)
  620. set(_sb_USE_SYSTEM_VAR ${SUPERBUILD_TOPLEVEL_PROJECT}_USE_SYSTEM_${_sb_proj})
  621. #message("[${project_name}] Setting _sb_USE_SYSTEM_VAR with default value '${_sb_USE_SYSTEM_VAR}'")
  622. endif()
  623. # Set default for optional SUPERBUILD_VAR parameter
  624. if(NOT _sb_SUPERBUILD_VAR)
  625. set(_sb_SUPERBUILD_VAR ${SUPERBUILD_TOPLEVEL_PROJECT}_SUPERBUILD)
  626. #message("[${project_name}] Setting _sb_SUPERBUILD_VAR with default value '${_sb_SUPERBUILD_VAR}'")
  627. endif()
  628. # Set default for optional CMAKE_GENERATOR_* parameters
  629. foreach(varname IN ITEMS
  630. "CMAKE_GENERATOR"
  631. "CMAKE_GENERATOR_PLATFORM"
  632. "CMAKE_GENERATOR_TOOLSET"
  633. )
  634. if(NOT _sb_${varname})
  635. set(_sb_${varname} ${EP_${varname}})
  636. #message("[${project_name}] Setting _sb_${varname} with default value '${_sb_${varname}}'")
  637. else()
  638. #message("[${project_name}] Setting _sb_${varname} to value '${_sb_${varname}}'")
  639. endif()
  640. endforeach()
  641. # Keeping track of variable name independently of the recursion
  642. if(NOT DEFINED _sb_SB_VAR)
  643. set(_sb_SB_VAR ${_sb_SUPERBUILD_VAR})
  644. #message("[${project_name}] Setting _sb_SB_VAR with default value '${_sb_SB_VAR}'")
  645. endif()
  646. # Set local variables
  647. set(_sb_DEPENDS ${${_sb_DEPENDS_VAR}})
  648. set(_sb_USE_SYSTEM ${${_sb_USE_SYSTEM_VAR}})
  649. _sb_update_indent(${_sb_proj})
  650. # Keep track of the projects
  651. list(APPEND SB_${SUPERBUILD_TOPLEVEL_PROJECT}_POSSIBLE_DEPENDS ${_sb_proj})
  652. # Use system ?
  653. get_property(_use_system_set GLOBAL PROPERTY SB_${_sb_proj}_USE_SYSTEM SET)
  654. if(_use_system_set)
  655. get_property(_sb_USE_SYSTEM GLOBAL PROPERTY SB_${_sb_proj}_USE_SYSTEM)
  656. endif()
  657. # Is this the first run ?
  658. if(${_sb_proj} STREQUAL ${SUPERBUILD_TOPLEVEL_PROJECT} AND NOT DEFINED SB_FIRST_PASS)
  659. message(STATUS "SuperBuild - First pass")
  660. set(SB_FIRST_PASS TRUE)
  661. endif()
  662. set(_sb_REQUIRED_DEPENDS)
  663. foreach(dep ${_sb_DEPENDS})
  664. if(NOT ${_sb_proj} STREQUAL ${SUPERBUILD_TOPLEVEL_PROJECT})
  665. # Set "use system" variable if it has NOT already been explicitly set
  666. get_property(_sb_${dep}_USE_SYSTEM_VAR GLOBAL PROPERTY SB_${dep}_USE_SYSTEM_VAR)
  667. if(_sb_USE_SYSTEM AND NOT DEFINED ${_sb_${dep}_USE_SYSTEM_VAR})
  668. set_property(GLOBAL PROPERTY SB_${dep}_USE_SYSTEM ${_sb_USE_SYSTEM})
  669. #message(${_sb_proj} "Property SB_${dep}_USE_SYSTEM set to [${_sb_USE_SYSTEM_VAR}:${_sb_USE_SYSTEM}]")
  670. endif()
  671. endif()
  672. _sb_is_optional(${dep} _optional)
  673. set_property(GLOBAL PROPERTY SB_${dep}_OPTIONAL ${_optional})
  674. #message(${_sb_proj} "[${_sb_proj}] Property SB_${dep}_OPTIONAL set to ${_optional}")
  675. if(NOT _optional)
  676. list(APPEND _sb_REQUIRED_DEPENDS ${dep})
  677. endif()
  678. endforeach()
  679. # Display dependency of project being processed
  680. if(_sb_REQUIRED_DEPENDS AND SB_SECOND_PASS AND ${_sb_SB_VAR})
  681. set(dependency_str "")
  682. foreach(dep ${_sb_REQUIRED_DEPENDS})
  683. get_property(_is_included GLOBAL PROPERTY SB_${dep}_FILE_INCLUDED)
  684. set(_include_status "")
  685. if(_is_included)
  686. set(_include_status "[INCLUDED]")
  687. endif()
  688. set(dependency_str "${dependency_str}${dep}${_include_status}, ")
  689. endforeach()
  690. ExternalProject_Message(${_sb_proj} "${_sb_proj} => Requires ${dependency_str}")
  691. endif()
  692. # Save variables
  693. set_property(GLOBAL PROPERTY SB_${_sb_proj}_REQUIRED_DEPENDS ${_sb_REQUIRED_DEPENDS})
  694. set_property(GLOBAL PROPERTY SB_${_sb_proj}_DEPENDS ${_sb_DEPENDS})
  695. set_property(GLOBAL PROPERTY SB_${_sb_proj}_DEPENDS_VAR ${_sb_DEPENDS_VAR})
  696. set_property(GLOBAL PROPERTY SB_${_sb_proj}_EP_ARGS_VAR ${_sb_EP_ARGS_VAR})
  697. set_property(GLOBAL PROPERTY SB_${_sb_proj}_USE_SYSTEM ${_sb_USE_SYSTEM})
  698. set_property(GLOBAL PROPERTY SB_${_sb_proj}_USE_SYSTEM_VAR ${_sb_USE_SYSTEM_VAR})
  699. set_property(GLOBAL PROPERTY SB_${_sb_proj}_PROJECT_VAR ${_sb_PROJECT_VAR})
  700. foreach(varname IN ITEMS
  701. "CMAKE_GENERATOR"
  702. "CMAKE_GENERATOR_PLATFORM"
  703. "CMAKE_GENERATOR_TOOLSET"
  704. )
  705. set_property(GLOBAL PROPERTY SB_${_sb_proj}_${varname} ${_sb_${varname}})
  706. endforeach()
  707. superbuild_stack_push(SB_PROJECT_STACK ${_sb_proj})
  708. # Include dependencies
  709. foreach(dep ${_sb_DEPENDS})
  710. get_property(_included GLOBAL PROPERTY SB_${dep}_FILE_INCLUDED)
  711. if(NOT _included)
  712. # XXX - Refactor - Add a single variable named 'EXTERNAL_PROJECT_DIRS'
  713. if(EXISTS "${EXTERNAL_PROJECT_DIR}/${EXTERNAL_PROJECT_FILE_PREFIX}${dep}.cmake")
  714. include(${EXTERNAL_PROJECT_DIR}/${EXTERNAL_PROJECT_FILE_PREFIX}${dep}.cmake)
  715. elseif(EXISTS "${${dep}_FILEPATH}")
  716. include(${${dep}_FILEPATH})
  717. elseif(EXISTS "${EXTERNAL_PROJECT_ADDITIONAL_DIR}/${EXTERNAL_PROJECT_FILE_PREFIX}${dep}.cmake")
  718. include(${EXTERNAL_PROJECT_ADDITIONAL_DIR}/${EXTERNAL_PROJECT_FILE_PREFIX}${dep}.cmake)
  719. else()
  720. message(FATAL_ERROR "Can't find ${EXTERNAL_PROJECT_FILE_PREFIX}${dep}.cmake")
  721. endif()
  722. set_property(GLOBAL PROPERTY SB_${dep}_FILE_INCLUDED 1)
  723. endif()
  724. endforeach()
  725. # Restore variables
  726. superbuild_stack_pop(SB_PROJECT_STACK _sb_proj)
  727. foreach(varname IN ITEMS
  728. "CMAKE_GENERATOR"
  729. "CMAKE_GENERATOR_PLATFORM"
  730. "CMAKE_GENERATOR_TOOLSET"
  731. )
  732. get_property(_sb_${varname} GLOBAL PROPERTY SB_${_sb_proj}_${varname})
  733. endforeach()
  734. get_property(_sb_PROJECT_VAR GLOBAL PROPERTY SB_${_sb_proj}_PROJECT_VAR)
  735. get_property(_sb_USE_SYSTEM_VAR GLOBAL PROPERTY SB_${_sb_proj}_USE_SYSTEM_VAR)
  736. get_property(_sb_USE_SYSTEM GLOBAL PROPERTY SB_${_sb_proj}_USE_SYSTEM)
  737. get_property(_sb_EP_ARGS_VAR GLOBAL PROPERTY SB_${_sb_proj}_EP_ARGS_VAR)
  738. get_property(_sb_DEPENDS_VAR GLOBAL PROPERTY SB_${_sb_proj}_DEPENDS_VAR)
  739. get_property(_sb_DEPENDS GLOBAL PROPERTY SB_${_sb_proj}_DEPENDS)
  740. get_property(_sb_REQUIRED_DEPENDS GLOBAL PROPERTY SB_${_sb_proj}_REQUIRED_DEPENDS)
  741. # Use system ?
  742. set(_include_type "")
  743. if(_sb_USE_SYSTEM)
  744. set(_include_type " (SYSTEM)")
  745. endif()
  746. get_property(_optional GLOBAL PROPERTY SB_${_sb_proj}_OPTIONAL)
  747. ExternalProject_Message(${_sb_proj} "${_sb_proj}[OK]${_include_type}" SB_SECOND_PASS AND ${_sb_SB_VAR} AND NOT _optional)
  748. if(${_sb_proj} STREQUAL ${SUPERBUILD_TOPLEVEL_PROJECT} AND SB_FIRST_PASS)
  749. set(SB_FIRST_PASS FALSE)
  750. ExternalProject_Message(${_sb_proj} "First pass - done")
  751. if(${_sb_SB_VAR})
  752. foreach(possible_proj ${SB_${SUPERBUILD_TOPLEVEL_PROJECT}_POSSIBLE_DEPENDS})
  753. get_property(_optional GLOBAL PROPERTY SB_${possible_proj}_OPTIONAL)
  754. if(_optional)
  755. ExternalProject_Message(${_sb_proj} "${possible_proj}[OPTIONAL]")
  756. endif()
  757. set_property(GLOBAL PROPERTY SB_${possible_proj}_FILE_INCLUDED 0)
  758. endforeach()
  759. set(${_sb_PROJECT_VAR} ${_sb_proj})
  760. set(SB_SECOND_PASS TRUE)
  761. set(_ep_include_deps_EXTRA_ARGS )
  762. foreach(varname IN ITEMS
  763. "CMAKE_GENERATOR"
  764. "CMAKE_GENERATOR_PLATFORM"
  765. "CMAKE_GENERATOR_TOOLSET"
  766. )
  767. list(APPEND _ep_include_deps_EXTRA_ARGS
  768. ${varname} ${_sb_${varname}}
  769. )
  770. endforeach()
  771. ExternalProject_Include_Dependencies(${_sb_proj}
  772. PROJECT_VAR ${_sb_PROJECT_VAR}
  773. DEPENDS_VAR ${_sb_DEPENDS_VAR}
  774. EP_ARGS_VAR ${_sb_EP_ARGS_VAR}
  775. USE_SYSTEM_VAR _sb_USE_SYSTEM
  776. SUPERBUILD_VAR ${_sb_SB_VAR}
  777. ${_ep_include_deps_EXTRA_ARGS}
  778. )
  779. set(SB_SECOND_PASS FALSE)
  780. endif()
  781. endif()
  782. if(SB_FIRST_PASS OR _optional)
  783. if(NOT ${_sb_proj} STREQUAL ${SUPERBUILD_TOPLEVEL_PROJECT})
  784. return()
  785. endif()
  786. endif()
  787. if(SB_SECOND_PASS)
  788. _sb_get_external_project_arguments(${_sb_proj} ${_sb_EP_ARGS_VAR})
  789. endif()
  790. if(NOT SB_FIRST_PASS AND NOT SB_SECOND_PASS
  791. AND ${_sb_proj} STREQUAL ${SUPERBUILD_TOPLEVEL_PROJECT})
  792. #ExternalProject_Message(${_sb_proj} "Clean up")
  793. unset(_sb_SB_VAR)
  794. unset(SB_FIRST_PASS)
  795. unset(SB_SECOND_PASS)
  796. endif()
  797. # Set public variables
  798. set(${_sb_PROJECT_VAR} ${_sb_proj})
  799. set(${_sb_DEPENDS_VAR} ${_sb_REQUIRED_DEPENDS})
  800. set(${_sb_USE_SYSTEM_VAR} ${_sb_USE_SYSTEM})
  801. #message("[${_sb_proj}] #################################")
  802. #message("[${_sb_proj}] Setting ${_sb_PROJECT_VAR}:${_sb_proj}")
  803. #message("[${_sb_proj}] Setting ${_sb_EP_ARGS_VAR}:${${_sb_EP_ARGS_VAR}}")
  804. #message("[${_sb_proj}] Setting ${_sb_DEPENDS_VAR}:${${_sb_DEPENDS_VAR}}")
  805. #message("[${_sb_proj}] Setting ${_sb_USE_SYSTEM_VAR}:${_sb_USE_SYSTEM}")
  806. endmacro()
  807. #.rst:
  808. # .. cmake:function:: ExternalProject_Add_Empty
  809. #
  810. # .. code-block:: cmake
  811. #
  812. # ExternalProject_Add_Empty(<project_name>
  813. # DEPENDS <depends>
  814. # )
  815. #
  816. macro(ExternalProject_Add_Empty project_name)
  817. set(options)
  818. set(oneValueArgs)
  819. set(multiValueArgs DEPENDS)
  820. cmake_parse_arguments(_sb "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  821. # Sanity checks
  822. if(x${project_name} STREQUAL xDEPENDS)
  823. message(FATAL_ERROR "Argument <project_name> is missing !")
  824. endif()
  825. if(_sb_UNPARSED_ARGUMENTS)
  826. message(FATAL_ERROR "Invalid arguments: ${_sb_UNPARSED_ARGUMENTS}")
  827. endif()
  828. ExternalProject_Add(${project_name}
  829. SOURCE_DIR ${CMAKE_BINARY_DIR}/${project_name}
  830. BINARY_DIR ${project_name}-build
  831. DOWNLOAD_COMMAND ""
  832. CONFIGURE_COMMAND ""
  833. BUILD_COMMAND ""
  834. INSTALL_COMMAND ""
  835. DEPENDS ${_sb_DEPENDS}
  836. )
  837. endmacro()
  838. #.rst:
  839. # .. cmake:function:: ExternalProject_Install_CMake
  840. #
  841. # Install an external CMake-based project as part of the ``install`` target.
  842. #
  843. # .. code-block:: cmake
  844. #
  845. # ExternalProject_Install_CMake(<project_name>)
  846. #
  847. # This causes building the main project's ``install`` target to also execute
  848. # the CMake install script for the specified external project. The project must
  849. # be previously declared with :command:`ExternalProject_Add`.
  850. #
  851. function(ExternalProject_Install_CMake project_name)
  852. ExternalProject_Get_Property(${project_name} binary_dir)
  853. install(SCRIPT ${binary_dir}/cmake_install.cmake)
  854. endfunction()
  855. #.rst:
  856. # .. cmake:function:: ExternalProject_SetIfNotDefined
  857. #
  858. # Set a variable to its default value if not already defined.
  859. #
  860. # .. code-block:: cmake
  861. #
  862. # ExternalProject_SetIfNotDefined(<var> <defaultvalue> [OBFUSCATE] [QUIET])
  863. #
  864. # The default value is set with:
  865. # (1) if set, the value environment variable <var>.
  866. # (2) if set, the value of local variable variable <var>.
  867. # (3) if none of the above, the value passed as a parameter.
  868. #
  869. # Setting the optional parameter 'OBFUSCATE' will display 'OBFUSCATED' instead of the real value.
  870. # Setting the optional parameter 'QUIET' will not display any message.
  871. macro(ExternalProject_SetIfNotDefined var defaultvalue)
  872. set(_obfuscate FALSE)
  873. set(_quiet FALSE)
  874. foreach(arg ${ARGN})
  875. if(arg STREQUAL "OBFUSCATE")
  876. set(_obfuscate TRUE)
  877. endif()
  878. if(arg STREQUAL "QUIET")
  879. set(_quiet TRUE)
  880. endif()
  881. endforeach()
  882. if(DEFINED ENV{${var}} AND NOT DEFINED ${var})
  883. set(_value "$ENV{${var}}")
  884. if(_obfuscate)
  885. set(_value "OBFUSCATED")
  886. endif()
  887. if(NOT _quiet)
  888. message(STATUS "Setting '${var}' variable with environment variable value '${_value}'")
  889. endif()
  890. set(${var} $ENV{${var}})
  891. endif()
  892. if(NOT DEFINED ${var})
  893. set(_value "${defaultvalue}")
  894. if(_obfuscate)
  895. set(_value "OBFUSCATED")
  896. endif()
  897. if(NOT _quiet)
  898. message(STATUS "Setting '${var}' variable with default value '${_value}'")
  899. endif()
  900. set(${var} "${defaultvalue}")
  901. endif()
  902. endmacro()
  903. #.rst:
  904. # .. cmake:function:: ExternalProject_AlwaysConfigure
  905. #
  906. # Add a external project step named `forceconfigure` to `project_name` ensuring
  907. # the project will always be reconfigured.
  908. #
  909. # .. code-block:: cmake
  910. #
  911. # ExternalProject_AlwaysConfigure(<project_name>)
  912. function(ExternalProject_AlwaysConfigure proj)
  913. # This custom external project step forces the configure and later
  914. # steps to run.
  915. _ep_get_step_stampfile(${proj} "configure" stampfile)
  916. ExternalProject_Add_Step(${proj} forceconfigure
  917. COMMAND ${CMAKE_COMMAND} -E remove ${stampfile}
  918. COMMENT "Forcing configure step for '${proj}'"
  919. DEPENDEES build
  920. ALWAYS 1
  921. )
  922. endfunction()