2 # ExternalProjectDependency
3 # -------------------------
5 ###########################################################################
9 # Copyright (c) Kitware Inc.
11 # Licensed under the Apache License, Version 2.0 (the "License");
12 # you may not use this file except in compliance with the License.
13 # You may obtain a copy of the License at
15 # http://www.apache.org/licenses/LICENSE-2.0.txt
17 # Unless required by applicable law or agreed to in writing, software
18 # distributed under the License is distributed on an "AS IS" BASIS,
19 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 # See the License for the specific language governing permissions and
21 # limitations under the License.
23 ###########################################################################
25 include(CMakeParseArguments)
27 if(NOT DEFINED EP_LIST_SEPARATOR)
28 set(EP_LIST_SEPARATOR "^^")
32 # .. cmake:variable:: EXTERNAL_PROJECT_DIR
34 if(NOT EXISTS "${EXTERNAL_PROJECT_DIR}")
35 set(EXTERNAL_PROJECT_DIR ${CMAKE_SOURCE_DIR}/SuperBuild)
39 # .. cmake:variable:: EXTERNAL_PROJECT_FILE_PREFIX
41 if(NOT DEFINED EXTERNAL_PROJECT_FILE_PREFIX)
42 set(EXTERNAL_PROJECT_FILE_PREFIX "External_")
45 # Compute -G arg for configuring external projects with the same CMake generator:
46 if(CMAKE_EXTRA_GENERATOR)
47 set(EP_CMAKE_GENERATOR "${CMAKE_EXTRA_GENERATOR} - ${CMAKE_GENERATOR}")
49 set(EP_CMAKE_GENERATOR "${CMAKE_GENERATOR}")
51 set(EP_CMAKE_GENERATOR_PLATFORM "${CMAKE_GENERATOR_PLATFORM}")
52 set(EP_CMAKE_GENERATOR_TOOLSET "${CMAKE_GENERATOR_TOOLSET}")
55 # .. cmake:function:: mark_as_superbuild
57 # .. code-block:: cmake
59 # mark_as_superbuild(<varname1>[:<vartype1>] [<varname2>[:<vartype2>] [...]])
61 # .. code-block:: cmake
64 # VARS <varname1>[:<vartype1>] [<varname2>[:<vartype2>] [...]]
65 # [PROJECTS <projectname> [<projectname> [...]] | ALL_PROJECTS]
66 # [LABELS <label1> [<label2> [...]]]
69 # .. code-block:: cmake
71 # PROJECTS corresponds to a list of <projectname> that will be added using 'ExternalProject_Add' function.
72 # If not specified and called within a project file, it defaults to the value of 'SUPERBUILD_TOPLEVEL_PROJECT'
73 # Otherwise, it defaults to 'CMAKE_PROJECT_NAME'.
74 # If instead 'ALL_PROJECTS' is specified, the variables and labels will be passed to all projects.
76 # VARS is an expected list of variables specified as <varname>:<vartype> to pass to <projectname>
79 # LABELS is an optional list of label to associate with the variable names specified using 'VARS' and passed to
80 # the <projectname> as CMake CACHE args of the form:
81 # -D<projectname>_EP_LABEL_<label1>=<varname1>;<varname2>[...]
82 # -D<projectname>_EP_LABEL_<label2>=<varname1>;<varname2>[...]
84 function(mark_as_superbuild)
85 set(options ALL_PROJECTS CMAKE_CMD)
87 set(multiValueArgs VARS PROJECTS LABELS)
88 cmake_parse_arguments(_sb "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
90 set(_vars ${_sb_UNPARSED_ARGUMENTS})
92 set(_named_parameters_expected 0)
93 if(_sb_PROJECTS OR _sb_ALL_PROJECTS OR _sb_LABELS OR _sb_VARS)
94 set(_named_parameters_expected 1)
95 set(_vars ${_sb_VARS})
98 if(_named_parameters_expected AND _sb_UNPARSED_ARGUMENTS)
99 message(FATAL_ERROR "Arguments '${_sb_UNPARSED_ARGUMENTS}' should be associated with VARS parameter !")
102 if(_sb_PROJECTS AND _sb_ALL_PROJECTS)
103 message(FATAL_ERROR "Arguments 'PROJECTS' and 'ALL_PROJECTS' are mutually exclusive !")
106 foreach(var ${_vars})
107 set(_type_specified 0)
109 set(_type_specified 1)
111 # XXX Display warning with variable type is also specified for cache variable.
113 if(NOT _type_specified)
114 get_property(_type_set_in_cache CACHE ${_var} PROPERTY TYPE SET)
115 set(_var_name ${_var})
116 set(_var_type "STRING")
117 if(_type_set_in_cache)
118 get_property(_var_type CACHE ${_var_name} PROPERTY TYPE)
120 set(_var ${_var_name}:${_var_type})
122 list(APPEND _vars_with_type ${_var})
126 set(optional_arg_ALL_PROJECTS "ALL_PROJECTS")
128 set(optional_arg_ALL_PROJECTS PROJECTS ${_sb_PROJECTS})
131 _sb_append_to_cmake_args(
132 VARS ${_vars_with_type} LABELS ${_sb_LABELS} ${optional_arg_ALL_PROJECTS})
136 # _sb_extract_varname_and_vartype(<cmake_varname_and_type> <varname_var> [<vartype_var>])
138 # <cmake_varname_and_type> corresponds to variable name and variable type passed as "<varname>:<vartype>"
140 # <varname_var> will be set to "<varname>"
142 # <vartype_var> is an optional variable name that will be set to "<vartype>"
144 function(_sb_extract_varname_and_vartype cmake_varname_and_type varname_var)
145 set(_vartype_var "${ARGV2}")
146 string(REPLACE ":" ";" varname_and_vartype ${cmake_varname_and_type})
147 list(GET varname_and_vartype 0 _varname)
148 list(GET varname_and_vartype 1 _vartype)
149 set(${varname_var} ${_varname} PARENT_SCOPE)
150 if(_vartype_var MATCHES ".+")
151 set(${_vartype_var} ${_vartype} PARENT_SCOPE)
156 function(_sb_list_to_string separator input_list output_string_var)
159 list(LENGTH input_list list_length)
160 # If the list has 0 or 1 element, there is no need to loop over.
161 if(list_length LESS 2)
162 set(_string "${input_list}")
164 math(EXPR last_element_index "${list_length} - 1")
165 foreach(index RANGE ${last_element_index})
166 # Get current item_value
167 list(GET input_list ${index} item_value)
168 if(NOT item_value STREQUAL "")
169 # .. and append non-empty value to output string
170 set(_string "${_string}${item_value}")
171 # Append separator if current element is NOT the last one.
172 if(NOT index EQUAL last_element_index)
173 set(_string "${_string}${separator}")
178 set(${output_string_var} ${_string} PARENT_SCOPE)
182 # _sb_cmakevar_to_cmakearg(<cmake_varname_and_type> <cmake_arg_var> <has_cfg_intdir_var> [<varname_var> [<vartype_var>]])
184 # <cmake_varname_and_type> corresponds to variable name and variable type passed as "<varname>:<vartype>"
186 # <cmake_arg_var> is a variable name that will be set to "-D<varname>:<vartype>=${<varname>}"
188 # <has_int_dir_var> is set to either TRUE or FALSE.
189 # FALSE means that the value does NOT reference ${CMAKE_CFG_INTDIR} and
190 # the generated cmake argument should be passed to ExternalProject_Add as CMAKE_CACHE_ARGS.
191 # TRUEmeans that the value does reference ${CMAKE_CFG_INTDIR} and
192 # the generated cmake argument should be passed to ExternalProject_Add as CMAKE_ARGS.
194 # <varname_var> is an optional variable name that will be set to "<varname>"
196 # <vartype_var> is an optional variable name that will be set to "<vartype>"
198 function(_sb_cmakevar_to_cmakearg cmake_varname_and_type cmake_arg_var has_cfg_intdir_var)
199 set(_varname_var "${ARGV3}")
200 set(_vartype_var "${ARGV4}")
202 _sb_extract_varname_and_vartype(${cmake_varname_and_type} _varname _vartype)
204 set(_var_value "${${_varname}}")
206 set(_consider_cache_value 1)
207 if(DEFINED ${_varname}_SKIPCACHEVALUE AND ${_varname}_SKIPCACHEVALUE)
208 set(_consider_cache_value 0)
210 if(_consider_cache_value)
211 get_property(_value_set_in_cache CACHE ${_varname} PROPERTY VALUE SET)
212 if(_value_set_in_cache)
213 get_property(_var_value CACHE ${_varname} PROPERTY VALUE)
217 set(_has_cfg_intdir FALSE)
218 if(CMAKE_CONFIGURATION_TYPES)
219 string(FIND "${_var_value}" ${CMAKE_CFG_INTDIR} _index)
220 if(NOT _index EQUAL -1)
221 # Separate list item with <EP_LIST_SEPARATOR>
222 _sb_list_to_string(${EP_LIST_SEPARATOR} "${_var_value}" _var_value)
223 set(_has_cfg_intdir TRUE)
227 if(NOT _has_cfg_intdir)
228 string(REPLACE "\"" "\\\"" _var_value "${_var_value}")
231 set(${cmake_arg_var} -D${_varname}:${_vartype}=${_var_value} PARENT_SCOPE)
232 set(${has_cfg_intdir_var} ${_has_cfg_intdir} PARENT_SCOPE)
234 if(_varname_var MATCHES ".+")
235 set(${_varname_var} ${_varname} PARENT_SCOPE)
237 if(_vartype_var MATCHES ".+")
238 set(${_vartype_var} ${_vartype} PARENT_SCOPE)
242 set(_ALL_PROJECT_IDENTIFIER "ALLALLALL")
245 # _sb_append_to_cmake_args(
246 # VARS <varname1>:<vartype1> [<varname2>:<vartype2> [...]]
247 # [PROJECTS <projectname> [<projectname> [...]] | ALL_PROJECTS]
248 # [LABELS <label1> [<label2> [...]]]
251 # PROJECTS corresponds to a list of <projectname> that will be added using 'ExternalProject_Add' function.
252 # If not specified and called within a project file, it defaults to the value of 'SUPERBUILD_TOPLEVEL_PROJECT'
253 # Otherwise, it defaults to 'CMAKE_PROJECT_NAME'.
254 # If instead 'ALL_PROJECTS' is specified, the variables and labels will be passed to all projects.
256 # VARS is an expected list of variables specified as <varname>:<vartype> to pass to <projectname>
259 # LABELS is an optional list of label to associate with the variable names specified using 'VARS' and passed to
260 # the <projectname> as CMake CACHE args of the form:
261 # -D<projectname>_EP_LABEL_<label1>=<varname1>;<varname2>[...]
262 # -D<projectname>_EP_LABEL_<label2>=<varname1>;<varname2>[...]
264 function(_sb_append_to_cmake_args)
265 set(options ALL_PROJECTS)
267 set(multiValueArgs VARS PROJECTS LABELS)
268 cmake_parse_arguments(_sb "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
270 if(NOT _sb_PROJECTS AND NOT _sb_ALL_PROJECTS)
271 if(SUPERBUILD_TOPLEVEL_PROJECT)
272 set(_sb_PROJECTS ${SUPERBUILD_TOPLEVEL_PROJECT})
274 set(_sb_PROJECTS ${CMAKE_PROJECT_NAME})
279 set(_sb_PROJECTS ${_ALL_PROJECT_IDENTIFIER})
282 foreach(_sb_PROJECT ${_sb_PROJECTS})
285 foreach(varname_and_vartype ${_sb_VARS})
286 if(NOT TARGET ${_sb_PROJECT})
287 set_property(GLOBAL APPEND PROPERTY ${_sb_PROJECT}_EP_CMAKE_ARGS ${varname_and_vartype})
288 _sb_extract_varname_and_vartype(${varname_and_vartype} _varname)
290 message(FATAL_ERROR "Function _sb_append_to_cmake_args not allowed because project '${_sb_PROJECT}' already added !")
292 list(APPEND _ep_varnames ${_varname})
296 set_property(GLOBAL APPEND PROPERTY ${_sb_PROJECT}_EP_LABELS ${_sb_LABELS})
297 foreach(label ${_sb_LABELS})
298 set_property(GLOBAL APPEND PROPERTY ${_sb_PROJECT}_EP_LABEL_${label} ${_ep_varnames})
304 function(_sb_get_external_project_arguments proj varname)
306 mark_as_superbuild(${SUPERBUILD_TOPLEVEL_PROJECT}_USE_SYSTEM_${proj}:BOOL)
308 function(_sb_collect_args proj)
309 # Set list of CMake args associated with each label
310 get_property(_labels GLOBAL PROPERTY ${proj}_EP_LABELS)
312 list(REMOVE_DUPLICATES _labels)
313 foreach(label ${_labels})
314 get_property(${proj}_EP_LABEL_${label} GLOBAL PROPERTY ${proj}_EP_LABEL_${label})
315 list(REMOVE_DUPLICATES ${proj}_EP_LABEL_${label})
316 _sb_append_to_cmake_args(PROJECTS ${proj}
317 VARS ${proj}_EP_LABEL_${label}:STRING)
321 get_property(_args GLOBAL PROPERTY ${proj}_EP_CMAKE_ARGS)
322 foreach(var ${_args})
323 _sb_cmakevar_to_cmakearg(${var} cmake_arg _has_cfg_intdir)
324 set(_ep_property "CMAKE_CACHE_ARGS")
326 set(_ep_property "CMAKE_ARGS")
328 set_property(GLOBAL APPEND PROPERTY ${proj}_EP_PROPERTY_${_ep_property} ${cmake_arg})
333 _sb_collect_args(${proj})
334 _sb_collect_args(${_ALL_PROJECT_IDENTIFIER})
336 set(_ep_arguments "")
337 foreach(property CMAKE_ARGS CMAKE_CACHE_ARGS)
338 get_property(${proj}_EP_PROPERTY_${property} GLOBAL PROPERTY ${proj}_EP_PROPERTY_${property})
339 get_property(${_ALL_PROJECT_IDENTIFIER}_EP_PROPERTY_${property} GLOBAL PROPERTY ${_ALL_PROJECT_IDENTIFIER}_EP_PROPERTY_${property})
340 set(_all ${${proj}_EP_PROPERTY_${property}} ${${_ALL_PROJECT_IDENTIFIER}_EP_PROPERTY_${property}})
342 list(APPEND _ep_arguments ${property} ${_all})
346 list(APPEND _ep_arguments LIST_SEPARATOR ${EP_LIST_SEPARATOR})
348 list(APPEND _ep_arguments CMAKE_GENERATOR ${_sb_CMAKE_GENERATOR})
349 if(CMAKE_VERSION VERSION_GREATER "3.0")
350 list(APPEND _ep_arguments CMAKE_GENERATOR_PLATFORM ${_sb_CMAKE_GENERATOR_PLATFORM})
352 list(APPEND _ep_arguments CMAKE_GENERATOR_TOOLSET ${_sb_CMAKE_GENERATOR_TOOLSET})
353 if(CMAKE_VERSION VERSION_EQUAL "3.4" OR CMAKE_VERSION VERSION_GREATER "3.4")
354 # USES_TERMINAL_* options were introduced in CMake 3.4
355 foreach(step IN ITEMS DOWNLOAD UPDATE CONFIGURE BUILD TEST INSTALL)
356 list(APPEND _ep_arguments
357 USES_TERMINAL_${step}
361 set(${varname} ${_ep_arguments} PARENT_SCOPE)
364 function(_sb_update_indent proj)
365 superbuild_stack_size(SB_PROJECT_STACK _stack_size)
367 if(_stack_size GREATER 0)
368 foreach(not_used RANGE 1 ${_stack_size})
369 set(_indent " ${_indent}")
372 set_property(GLOBAL PROPERTY SUPERBUILD_${proj}_INDENT ${_indent})
376 # .. cmake:function:: ExternalProject_Message
378 # .. code-block:: cmake
380 # ExternalProject_Message(<project_name> <msg> [condition])
382 function(ExternalProject_Message proj msg)
384 if(NOT "x${ARGV2}" STREQUAL "x")
385 set(_display ${ARGN})
388 get_property(_indent GLOBAL PROPERTY SUPERBUILD_${proj}_INDENT)
389 message(STATUS "SuperBuild - ${_indent}${msg}")
394 # superbuild_stack_content(<stack_name> <output_var>)
396 # <stack_name> corresponds to the name of stack.
398 # <output_var> is the name of CMake variable that will be set with the content
399 # of the stack identified by <stack_name>.
401 function(superbuild_stack_content stack_name output_var)
402 get_property(_stack GLOBAL PROPERTY ${stack_name})
403 set(${output_var} ${_stack} PARENT_SCOPE)
407 # superbuild_stack_size(<stack_name> <output_var>)
409 # <stack_name> corresponds to the name of stack.
411 # <output_var> is the name of CMake variable that will be set with the size
412 # of the stack identified by <stack_name>.
414 function(superbuild_stack_size stack_name output_var)
415 get_property(_stack GLOBAL PROPERTY ${stack_name})
416 list(LENGTH _stack _stack_size)
417 set(${output_var} ${_stack_size} PARENT_SCOPE)
421 # superbuild_stack_push(<stack_name> <value>)
423 # <stack_name> corresponds to the name of stack.
425 # <value> is appended to the stack identified by <stack_name>.
427 function(superbuild_stack_push stack_name value)
428 set_property(GLOBAL APPEND PROPERTY ${stack_name} ${value})
432 # superbuild_stack_pop(<stack_name> <item_var>)
434 # <stack_name> corresponds to the name of stack.
436 # <item_var> names a CMake variable that will be set with the item
437 # removed from the stack identified by <stack_name>
439 function(superbuild_stack_pop stack_name item_var)
440 get_property(_stack GLOBAL PROPERTY ${stack_name})
441 list(LENGTH _stack _stack_size)
442 if(_stack_size GREATER 0)
443 math(EXPR _index_to_remove "${_stack_size} - 1")
444 list(GET _stack ${_index_to_remove} _item)
445 list(REMOVE_AT _stack ${_index_to_remove})
446 set_property(GLOBAL PROPERTY ${stack_name} ${_stack})
447 set(${item_var} ${_item} PARENT_SCOPE)
451 function(_sb_is_optional proj output_var)
452 set(_include_project 1)
453 if(COMMAND superbuild_is_external_project_includable)
454 superbuild_is_external_project_includable("${proj}" _include_project)
460 set(${output_var} ${optional} PARENT_SCOPE)
464 # .. cmake:function:: ExternalProject_Include_Dependencies
466 # .. code-block:: cmake
468 # ExternalProject_Include_Dependencies(<project_name>
469 # [PROJECT_VAR <project_var>]
470 # [EP_ARGS_VAR <external_project_args_var>]
471 # [DEPENDS_VAR <depends_var>]
472 # [USE_SYSTEM_VAR <use_system_var>]
473 # [SUPERBUILD_VAR <superbuild_var>]
474 # [CMAKE_GENERATOR <cmake_generator>]
475 # [CMAKE_GENERATOR_PLATFORM <cmake_generator_platform>]
476 # [CMAKE_GENERATOR_TOOLSET <cmake_generator_toolset>]
479 macro(ExternalProject_Include_Dependencies project_name)
481 set(oneValueArgs PROJECT_VAR DEPENDS_VAR EP_ARGS_VAR USE_SYSTEM_VAR SUPERBUILD_VAR
483 CMAKE_GENERATOR_PLATFORM
484 CMAKE_GENERATOR_TOOLSET
487 cmake_parse_arguments(_sb "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
490 if(x${project_name} STREQUAL xPROJECT_VAR
491 OR x${project_name} STREQUAL xEP_ARGS_VAR
492 OR x${project_name} STREQUAL xDEPENDS_VAR
493 OR x${project_name} STREQUAL xUSE_SYSTEM_VAR
494 OR x${project_name} STREQUAL xSUPERBUILD_VAR
495 OR x${project_name} STREQUAL xCMAKE_GENERATOR
496 OR x${project_name} STREQUAL xCMAKE_GENERATOR_PLATFORM
497 OR x${project_name} STREQUAL xCMAKE_GENERATOR_TOOLSET
499 message(FATAL_ERROR "Argument <project_name> is missing !")
501 if(_sb_UNPARSED_ARGUMENTS)
502 message(FATAL_ERROR "Invalid arguments: ${_sb_UNPARSED_ARGUMENTS}")
505 # Set default for optional PROJECT_VAR parameter
506 if(NOT _sb_PROJECT_VAR)
507 set(_sb_PROJECT_VAR proj)
508 set(${_sb_PROJECT_VAR} ${project_name})
509 #message("[${project_name}] Setting _sb_PROJECT_VAR with default value '${_sb_PROJECT_VAR}'")
512 if(_sb_PROJECT_VAR AND NOT x${project_name} STREQUAL x${${_sb_PROJECT_VAR}})
514 "Argument <project_name>:${project_name} and PROJECT_VAR:${_sb_PROJECT_VAR}:${${_sb_PROJECT_VAR}} are different !")
517 set(_sb_proj ${project_name})
519 # Skip if project already included
520 get_property(_is_included GLOBAL PROPERTY SB_${_sb_proj}_FILE_INCLUDED)
525 # Set default for optional DEPENDS_VAR and EP_ARGS parameters
526 foreach(param DEPENDS EP_ARGS)
527 if(NOT _sb_${param}_VAR)
528 set(_sb_${param}_VAR ${_sb_proj}_${param})
529 #message("[${project_name}] Setting _sb_${param}_VAR with default value '${_sb_${param}_VAR}'")
533 # Set top level project
534 superbuild_stack_size(SB_PROJECT_STACK _stack_size)
535 if(_stack_size EQUAL 0)
536 set(SUPERBUILD_TOPLEVEL_PROJECT ${_sb_proj})
539 # Set default for optional USE_SYSTEM_VAR parameter
540 if(NOT _sb_USE_SYSTEM_VAR)
541 set(_sb_USE_SYSTEM_VAR ${SUPERBUILD_TOPLEVEL_PROJECT}_USE_SYSTEM_${_sb_proj})
542 #message("[${project_name}] Setting _sb_USE_SYSTEM_VAR with default value '${_sb_USE_SYSTEM_VAR}'")
545 # Set default for optional SUPERBUILD_VAR parameter
546 if(NOT _sb_SUPERBUILD_VAR)
547 set(_sb_SUPERBUILD_VAR ${SUPERBUILD_TOPLEVEL_PROJECT}_SUPERBUILD)
548 #message("[${project_name}] Setting _sb_SUPERBUILD_VAR with default value '${_sb_SUPERBUILD_VAR}'")
551 # Set default for optional CMAKE_GENERATOR_* parameters
552 foreach(varname IN ITEMS
554 "CMAKE_GENERATOR_PLATFORM"
555 "CMAKE_GENERATOR_TOOLSET"
557 if(NOT _sb_${varname})
558 set(_sb_${varname} ${EP_${varname}})
559 #message("[${project_name}] Setting _sb_${varname} with default value '${_sb_${varname}}'")
561 #message("[${project_name}] Setting _sb_${varname} to value '${_sb_${varname}}'")
565 # Keeping track of variable name independently of the recursion
566 if(NOT DEFINED _sb_SB_VAR)
567 set(_sb_SB_VAR ${_sb_SUPERBUILD_VAR})
568 #message("[${project_name}] Setting _sb_SB_VAR with default value '${_sb_SB_VAR}'")
571 # Set local variables
572 set(_sb_DEPENDS ${${_sb_DEPENDS_VAR}})
573 set(_sb_USE_SYSTEM ${${_sb_USE_SYSTEM_VAR}})
575 _sb_update_indent(${_sb_proj})
577 # Keep track of the projects
578 list(APPEND SB_${SUPERBUILD_TOPLEVEL_PROJECT}_POSSIBLE_DEPENDS ${_sb_proj})
581 get_property(_use_system_set GLOBAL PROPERTY SB_${_sb_proj}_USE_SYSTEM SET)
583 get_property(_sb_USE_SYSTEM GLOBAL PROPERTY SB_${_sb_proj}_USE_SYSTEM)
586 # Is this the first run ?
587 if(${_sb_proj} STREQUAL ${SUPERBUILD_TOPLEVEL_PROJECT} AND NOT DEFINED SB_FIRST_PASS)
588 message(STATUS "SuperBuild - First pass")
589 set(SB_FIRST_PASS TRUE)
592 set(_sb_REQUIRED_DEPENDS)
593 foreach(dep ${_sb_DEPENDS})
594 if(NOT ${_sb_proj} STREQUAL ${SUPERBUILD_TOPLEVEL_PROJECT})
595 # Set "use system" variable if it has NOT already been explicitly set
596 get_property(_sb_${dep}_USE_SYSTEM_VAR GLOBAL PROPERTY SB_${dep}_USE_SYSTEM_VAR)
597 if(_sb_USE_SYSTEM AND NOT DEFINED ${_sb_${dep}_USE_SYSTEM_VAR})
598 set_property(GLOBAL PROPERTY SB_${dep}_USE_SYSTEM ${_sb_USE_SYSTEM})
599 #message(${_sb_proj} "Property SB_${dep}_USE_SYSTEM set to [${_sb_USE_SYSTEM_VAR}:${_sb_USE_SYSTEM}]")
602 _sb_is_optional(${dep} _optional)
603 set_property(GLOBAL PROPERTY SB_${dep}_OPTIONAL ${_optional})
604 #message(${_sb_proj} "[${_sb_proj}] Property SB_${dep}_OPTIONAL set to ${_optional}")
606 list(APPEND _sb_REQUIRED_DEPENDS ${dep})
610 # Display dependency of project being processed
611 if(_sb_REQUIRED_DEPENDS AND SB_SECOND_PASS AND ${_sb_SB_VAR})
612 set(dependency_str "")
613 foreach(dep ${_sb_REQUIRED_DEPENDS})
614 get_property(_is_included GLOBAL PROPERTY SB_${dep}_FILE_INCLUDED)
615 set(_include_status "")
617 set(_include_status "[INCLUDED]")
619 set(dependency_str "${dependency_str}${dep}${_include_status}, ")
621 ExternalProject_Message(${_sb_proj} "${_sb_proj} => Requires ${dependency_str}")
625 set_property(GLOBAL PROPERTY SB_${_sb_proj}_REQUIRED_DEPENDS ${_sb_REQUIRED_DEPENDS})
626 set_property(GLOBAL PROPERTY SB_${_sb_proj}_DEPENDS ${_sb_DEPENDS})
627 set_property(GLOBAL PROPERTY SB_${_sb_proj}_DEPENDS_VAR ${_sb_DEPENDS_VAR})
628 set_property(GLOBAL PROPERTY SB_${_sb_proj}_EP_ARGS_VAR ${_sb_EP_ARGS_VAR})
629 set_property(GLOBAL PROPERTY SB_${_sb_proj}_USE_SYSTEM ${_sb_USE_SYSTEM})
630 set_property(GLOBAL PROPERTY SB_${_sb_proj}_USE_SYSTEM_VAR ${_sb_USE_SYSTEM_VAR})
631 set_property(GLOBAL PROPERTY SB_${_sb_proj}_PROJECT_VAR ${_sb_PROJECT_VAR})
632 foreach(varname IN ITEMS
634 "CMAKE_GENERATOR_PLATFORM"
635 "CMAKE_GENERATOR_TOOLSET"
637 set_property(GLOBAL PROPERTY SB_${_sb_proj}_${varname} ${_sb_${varname}})
639 superbuild_stack_push(SB_PROJECT_STACK ${_sb_proj})
641 # Include dependencies
642 foreach(dep ${_sb_DEPENDS})
643 get_property(_included GLOBAL PROPERTY SB_${dep}_FILE_INCLUDED)
645 # XXX - Refactor - Add a single variable named 'EXTERNAL_PROJECT_DIRS'
646 if(EXISTS "${EXTERNAL_PROJECT_DIR}/${EXTERNAL_PROJECT_FILE_PREFIX}${dep}.cmake")
647 include(${EXTERNAL_PROJECT_DIR}/${EXTERNAL_PROJECT_FILE_PREFIX}${dep}.cmake)
648 elseif(EXISTS "${${dep}_FILEPATH}")
649 include(${${dep}_FILEPATH})
650 elseif(EXISTS "${EXTERNAL_PROJECT_ADDITIONAL_DIR}/${EXTERNAL_PROJECT_FILE_PREFIX}${dep}.cmake")
651 include(${EXTERNAL_PROJECT_ADDITIONAL_DIR}/${EXTERNAL_PROJECT_FILE_PREFIX}${dep}.cmake)
653 message(FATAL_ERROR "Can't find ${EXTERNAL_PROJECT_FILE_PREFIX}${dep}.cmake")
655 set_property(GLOBAL PROPERTY SB_${dep}_FILE_INCLUDED 1)
660 superbuild_stack_pop(SB_PROJECT_STACK _sb_proj)
661 foreach(varname IN ITEMS
663 "CMAKE_GENERATOR_PLATFORM"
664 "CMAKE_GENERATOR_TOOLSET"
666 get_property(_sb_${varname} GLOBAL PROPERTY SB_${_sb_proj}_${varname})
668 get_property(_sb_PROJECT_VAR GLOBAL PROPERTY SB_${_sb_proj}_PROJECT_VAR)
669 get_property(_sb_USE_SYSTEM_VAR GLOBAL PROPERTY SB_${_sb_proj}_USE_SYSTEM_VAR)
670 get_property(_sb_USE_SYSTEM GLOBAL PROPERTY SB_${_sb_proj}_USE_SYSTEM)
671 get_property(_sb_EP_ARGS_VAR GLOBAL PROPERTY SB_${_sb_proj}_EP_ARGS_VAR)
672 get_property(_sb_DEPENDS_VAR GLOBAL PROPERTY SB_${_sb_proj}_DEPENDS_VAR)
673 get_property(_sb_DEPENDS GLOBAL PROPERTY SB_${_sb_proj}_DEPENDS)
674 get_property(_sb_REQUIRED_DEPENDS GLOBAL PROPERTY SB_${_sb_proj}_REQUIRED_DEPENDS)
677 set(_include_type "")
679 set(_include_type " (SYSTEM)")
681 get_property(_optional GLOBAL PROPERTY SB_${_sb_proj}_OPTIONAL)
682 ExternalProject_Message(${_sb_proj} "${_sb_proj}[OK]${_include_type}" SB_SECOND_PASS AND ${_sb_SB_VAR} AND NOT _optional)
684 if(${_sb_proj} STREQUAL ${SUPERBUILD_TOPLEVEL_PROJECT} AND SB_FIRST_PASS)
685 set(SB_FIRST_PASS FALSE)
686 ExternalProject_Message(${_sb_proj} "First pass - done")
689 foreach(possible_proj ${SB_${SUPERBUILD_TOPLEVEL_PROJECT}_POSSIBLE_DEPENDS})
690 get_property(_optional GLOBAL PROPERTY SB_${possible_proj}_OPTIONAL)
692 ExternalProject_Message(${_sb_proj} "${possible_proj}[OPTIONAL]")
694 set_property(GLOBAL PROPERTY SB_${possible_proj}_FILE_INCLUDED 0)
697 set(${_sb_PROJECT_VAR} ${_sb_proj})
699 set(SB_SECOND_PASS TRUE)
700 set(_ep_include_deps_EXTRA_ARGS )
701 foreach(varname IN ITEMS
703 "CMAKE_GENERATOR_PLATFORM"
704 "CMAKE_GENERATOR_TOOLSET"
706 list(APPEND _ep_include_deps_EXTRA_ARGS
707 ${varname} ${_sb_${varname}}
710 ExternalProject_Include_Dependencies(${_sb_proj}
711 PROJECT_VAR ${_sb_PROJECT_VAR}
712 DEPENDS_VAR ${_sb_DEPENDS_VAR}
713 EP_ARGS_VAR ${_sb_EP_ARGS_VAR}
714 USE_SYSTEM_VAR _sb_USE_SYSTEM
715 SUPERBUILD_VAR ${_sb_SB_VAR}
716 ${_ep_include_deps_EXTRA_ARGS}
718 set(SB_SECOND_PASS FALSE)
722 if(SB_FIRST_PASS OR _optional)
723 if(NOT ${_sb_proj} STREQUAL ${SUPERBUILD_TOPLEVEL_PROJECT})
729 _sb_get_external_project_arguments(${_sb_proj} ${_sb_EP_ARGS_VAR})
732 if(NOT SB_FIRST_PASS AND NOT SB_SECOND_PASS
733 AND ${_sb_proj} STREQUAL ${SUPERBUILD_TOPLEVEL_PROJECT})
734 #ExternalProject_Message(${_sb_proj} "Clean up")
737 unset(SB_SECOND_PASS)
740 # Set public variables
741 set(${_sb_PROJECT_VAR} ${_sb_proj})
742 set(${_sb_DEPENDS_VAR} ${_sb_REQUIRED_DEPENDS})
743 set(${_sb_USE_SYSTEM_VAR} ${_sb_USE_SYSTEM})
745 #message("[${_sb_proj}] #################################")
746 #message("[${_sb_proj}] Setting ${_sb_PROJECT_VAR}:${_sb_proj}")
747 #message("[${_sb_proj}] Setting ${_sb_EP_ARGS_VAR}:${${_sb_EP_ARGS_VAR}}")
748 #message("[${_sb_proj}] Setting ${_sb_DEPENDS_VAR}:${${_sb_DEPENDS_VAR}}")
749 #message("[${_sb_proj}] Setting ${_sb_USE_SYSTEM_VAR}:${_sb_USE_SYSTEM}")
753 # .. cmake:function:: ExternalProject_Add_Empty
755 # .. code-block:: cmake
757 # ExternalProject_Add_Empty(<project_name>
761 macro(ExternalProject_Add_Empty project_name)
764 set(multiValueArgs DEPENDS)
765 cmake_parse_arguments(_sb "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
768 if(x${project_name} STREQUAL xDEPENDS)
769 message(FATAL_ERROR "Argument <project_name> is missing !")
771 if(_sb_UNPARSED_ARGUMENTS)
772 message(FATAL_ERROR "Invalid arguments: ${_sb_UNPARSED_ARGUMENTS}")
775 ExternalProject_Add(${project_name}
776 SOURCE_DIR ${CMAKE_BINARY_DIR}/${project_name}
777 BINARY_DIR ${project_name}-build
782 DEPENDS ${_sb_DEPENDS}
787 # .. cmake:function:: ExternalProject_Install_CMake
789 # Install an external CMake-based project as part of the ``install`` target.
791 # .. code-block:: cmake
793 # ExternalProject_Install_CMake(<project_name>)
795 # This causes building the main project's ``install`` target to also execute
796 # the CMake install script for the specified external project. The project must
797 # be previously declared with :command:`ExternalProject_Add`.
799 function(ExternalProject_Install_CMake project_name)
800 ExternalProject_Get_Property(${project_name} binary_dir)
802 install(SCRIPT ${binary_dir}/cmake_install.cmake)
806 # .. cmake:function:: ExternalProject_SetIfNotDefined
808 # Set a variable to its default value if not already defined.
810 # .. code-block:: cmake
812 # ExternalProject_SetIfNotDefined(<var> <defaultvalue> [OBFUSCATE] [QUIET])
814 # The default value is set with:
815 # (1) if set, the value environment variable <var>.
816 # (2) if set, the value of local variable variable <var>.
817 # (3) if none of the above, the value passed as a parameter.
819 # Setting the optional parameter 'OBFUSCATE' will display 'OBFUSCATED' instead of the real value.
820 # Setting the optional parameter 'QUIET' will not display any message.
821 macro(ExternalProject_SetIfNotDefined var defaultvalue)
822 set(_obfuscate FALSE)
825 if(arg STREQUAL "OBFUSCATE")
828 if(arg STREQUAL "QUIET")
832 if(DEFINED ENV{${var}} AND NOT DEFINED ${var})
833 set(_value "$ENV{${var}}")
835 set(_value "OBFUSCATED")
838 message(STATUS "Setting '${var}' variable with environment variable value '${_value}'")
840 set(${var} $ENV{${var}})
842 if(NOT DEFINED ${var})
843 set(_value "${defaultvalue}")
845 set(_value "OBFUSCATED")
848 message(STATUS "Setting '${var}' variable with default value '${_value}'")
850 set(${var} "${defaultvalue}")
855 # .. cmake:function:: ExternalProject_AlwaysConfigure
857 # Add a external project step named `forceconfigure` to `project_name` ensuring
858 # the project will always be reconfigured.
860 # .. code-block:: cmake
862 # ExternalProject_AlwaysConfigure(<project_name>)
863 function(ExternalProject_AlwaysConfigure proj)
864 # This custom external project step forces the configure and later
866 _ep_get_step_stampfile(${proj} "configure" stampfile)
867 ExternalProject_Add_Step(${proj} forceconfigure
868 COMMAND ${CMAKE_COMMAND} -E remove ${stampfile}
869 COMMENT "Forcing configure step for '${proj}'"