#.rst: # ExternalProjectDependency # ------------------------- # # .. only:: html # # .. contents:: ########################################################################### # # Library: CTK # # Copyright (c) Kitware Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0.txt # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################### include(CMakeParseArguments) #.rst: # Global Variables # ^^^^^^^^^^^^^^^^ #.rst: # .. cmake:variable:: EXTERNAL_PROJECT_DIR # # This variable describes the directory in which external project files # matching ``.cmake`` expression are globbed. # if(NOT EXISTS "${EXTERNAL_PROJECT_DIR}") set(EXTERNAL_PROJECT_DIR ${CMAKE_SOURCE_DIR}/SuperBuild) endif() #.rst: # .. cmake:variable:: EXTERNAL_PROJECT_ADDITIONAL_DIR # # If set, this variable represents an other directory in which external project files # are searched for if not already found in ``EXTERNAL_PROJECT_DIR``. #.rst: # .. cmake:variable:: EXTERNAL_PROJECT_FILE_PREFIX # # This variable describes the prefix of the external project files looked up in # ``EXTERNAL_PROJECT_DIR``. It defaults to ``External_``. # if(NOT DEFINED EXTERNAL_PROJECT_FILE_PREFIX) set(EXTERNAL_PROJECT_FILE_PREFIX "External_") endif() #.rst: # .. cmake:variable:: SUPERBUILD_TOPLEVEL_PROJECT # # This variable can be set to explicitly identify the name of the top-level project. # If not set, it default to the value of ``CMAKE_PROJECT_NAME``. if(NOT DEFINED SUPERBUILD_TOPLEVEL_PROJECT) if(NOT DEFINED CMAKE_PROJECT_NAME) message(FATAL_ERROR "Failed to initialize variable SUPERBUILD_TOPLEVEL_PROJECT. Variable CMAKE_PROJECT_NAME is not defined.") endif() set(SUPERBUILD_TOPLEVEL_PROJECT ${CMAKE_PROJECT_NAME}) endif() #.rst: # .. cmake:variable:: EP_LIST_SEPARATOR # # This variable is used to separate list items when passed in various external project # ``..._COMMAND`` options. # # If defaults to ``^^``. if(NOT DEFINED EP_LIST_SEPARATOR) set(EP_LIST_SEPARATOR "^^") endif() #.rst: # .. cmake:variable:: EP_GIT_PROTOCOL # # The value of this variable is controled by the option ``_USE_GIT_PROTOCOL`` # automatically defined by including this CMake module. Setting this option allows to update the value of # ``EP_GIT_PROTOCOL`` variable. # # If enabled, the variable ``EP_GIT_PROTOCOL`` is set to ``git``. Otherwise, it is set to ``https``. # The option is enabled by default. # # The variable ``EP_GIT_PROTOCOL`` can be used when adding external project. For example: # # .. code-block:: cmake # # ExternalProject_Add(${proj} # ${${proj}_EP_ARGS} # GIT_REPOSITORY "${EP_GIT_PROTOCOL}://github.com/Foo/Foo.git" # [...] # ) # option(${SUPERBUILD_TOPLEVEL_PROJECT}_USE_GIT_PROTOCOL "If behind a firewall turn this off to use https instead." ON) set(EP_GIT_PROTOCOL "git") if(NOT ${SUPERBUILD_TOPLEVEL_PROJECT}_USE_GIT_PROTOCOL) set(EP_GIT_PROTOCOL "https") endif() # Compute -G arg for configuring external projects with the same CMake generator: if(CMAKE_EXTRA_GENERATOR) set(EP_CMAKE_GENERATOR "${CMAKE_EXTRA_GENERATOR} - ${CMAKE_GENERATOR}") else() set(EP_CMAKE_GENERATOR "${CMAKE_GENERATOR}") endif() set(EP_CMAKE_GENERATOR_PLATFORM "${CMAKE_GENERATOR_PLATFORM}") set(EP_CMAKE_GENERATOR_TOOLSET "${CMAKE_GENERATOR_TOOLSET}") #.rst: # Functions # ^^^^^^^^^ #.rst: # .. cmake:function:: mark_as_superbuild # # .. code-block:: cmake # # mark_as_superbuild([:] [[:] [...]]) # # .. code-block:: cmake # # mark_as_superbuild( # VARS [:] [[:] [...]] # [PROJECTS [ [...]] | ALL_PROJECTS] # [LABELS [ [...]]] # ) # # .. code-block:: cmake # # PROJECTS corresponds to a list of that will be added using 'ExternalProject_Add' function. # If not specified and called within a project file, it defaults to the value of 'SUPERBUILD_TOPLEVEL_PROJECT'. # If instead 'ALL_PROJECTS' is specified, the variables and labels will be passed to all projects. # # VARS is an expected list of variables specified as : to pass to # # # LABELS is an optional list of label to associate with the variable names specified using 'VARS' and passed to # the as CMake CACHE args of the form: # -D_EP_LABEL_=;[...] # -D_EP_LABEL_=;[...] # function(mark_as_superbuild) set(options ALL_PROJECTS CMAKE_CMD) set(oneValueArgs) set(multiValueArgs VARS PROJECTS LABELS) cmake_parse_arguments(_sb "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) set(_vars ${_sb_UNPARSED_ARGUMENTS}) set(_named_parameters_expected 0) if(_sb_PROJECTS OR _sb_ALL_PROJECTS OR _sb_LABELS OR _sb_VARS) set(_named_parameters_expected 1) set(_vars ${_sb_VARS}) endif() if(_named_parameters_expected AND _sb_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Arguments '${_sb_UNPARSED_ARGUMENTS}' should be associated with VARS parameter !") endif() if(_sb_PROJECTS AND _sb_ALL_PROJECTS) message(FATAL_ERROR "Arguments 'PROJECTS' and 'ALL_PROJECTS' are mutually exclusive !") endif() foreach(var ${_vars}) set(_type_specified 0) if(var MATCHES ":") set(_type_specified 1) endif() # XXX Display warning with variable type is also specified for cache variable. set(_var ${var}) if(NOT _type_specified) get_property(_type_set_in_cache CACHE ${_var} PROPERTY TYPE SET) set(_var_name ${_var}) set(_var_type "STRING") if(_type_set_in_cache) get_property(_var_type CACHE ${_var_name} PROPERTY TYPE) endif() set(_var ${_var_name}:${_var_type}) endif() list(APPEND _vars_with_type ${_var}) endforeach() if(_sb_ALL_PROJECTS) set(optional_arg_ALL_PROJECTS "ALL_PROJECTS") else() set(optional_arg_ALL_PROJECTS PROJECTS ${_sb_PROJECTS}) endif() _sb_append_to_cmake_args( VARS ${_vars_with_type} LABELS ${_sb_LABELS} ${optional_arg_ALL_PROJECTS}) endfunction() # # _sb_extract_varname_and_vartype( []) # # corresponds to variable name and variable type passed as ":" # # will be set to "" # # is an optional variable name that will be set to "" # function(_sb_extract_varname_and_vartype cmake_varname_and_type varname_var) set(_vartype_var "${ARGV2}") string(REPLACE ":" ";" varname_and_vartype ${cmake_varname_and_type}) list(GET varname_and_vartype 0 _varname) list(GET varname_and_vartype 1 _vartype) set(${varname_var} ${_varname} PARENT_SCOPE) if(_vartype_var MATCHES ".+") set(${_vartype_var} ${_vartype} PARENT_SCOPE) endif() endfunction() function(_sb_list_to_string separator input_list output_string_var) set(_string "") # Get list length list(LENGTH input_list list_length) # If the list has 0 or 1 element, there is no need to loop over. if(list_length LESS 2) set(_string "${input_list}") else() math(EXPR last_element_index "${list_length} - 1") foreach(index RANGE ${last_element_index}) # Get current item_value list(GET input_list ${index} item_value) if(NOT item_value STREQUAL "") # .. and append non-empty value to output string set(_string "${_string}${item_value}") # Append separator if current element is NOT the last one. if(NOT index EQUAL last_element_index) set(_string "${_string}${separator}") endif() endif() endforeach() endif() set(${output_string_var} ${_string} PARENT_SCOPE) endfunction() # # _sb_cmakevar_to_cmakearg( [ []]) # # corresponds to variable name and variable type passed as ":" # # is a variable name that will be set to "-D:=${}" # # is set to either TRUE or FALSE. # FALSE means that the value does NOT reference ${CMAKE_CFG_INTDIR} and # the generated cmake argument should be passed to ExternalProject_Add as CMAKE_CACHE_ARGS. # TRUEmeans that the value does reference ${CMAKE_CFG_INTDIR} and # the generated cmake argument should be passed to ExternalProject_Add as CMAKE_ARGS. # # is an optional variable name that will be set to "" # # is an optional variable name that will be set to "" # function(_sb_cmakevar_to_cmakearg cmake_varname_and_type cmake_arg_var has_cfg_intdir_var) set(_varname_var "${ARGV3}") set(_vartype_var "${ARGV4}") _sb_extract_varname_and_vartype(${cmake_varname_and_type} _varname _vartype) set(_var_value "${${_varname}}") # Use cache value unless it is INTERNAL if(_vartype STREQUAL "INTERNAL") set(_vartype "STRING") else() get_property(_value_set_in_cache CACHE ${_varname} PROPERTY VALUE SET) if(_value_set_in_cache) get_property(_var_value CACHE ${_varname} PROPERTY VALUE) endif() endif() set(_has_cfg_intdir FALSE) if(CMAKE_CONFIGURATION_TYPES) string(FIND "${_var_value}" ${CMAKE_CFG_INTDIR} _index) if(NOT _index EQUAL -1) # Separate list item with _sb_list_to_string(${EP_LIST_SEPARATOR} "${_var_value}" _var_value) set(_has_cfg_intdir TRUE) endif() endif() if(NOT _has_cfg_intdir) string(REPLACE "\"" "\\\"" _var_value "${_var_value}") endif() set(${cmake_arg_var} -D${_varname}:${_vartype}=${_var_value} PARENT_SCOPE) set(${has_cfg_intdir_var} ${_has_cfg_intdir} PARENT_SCOPE) if(_varname_var MATCHES ".+") set(${_varname_var} ${_varname} PARENT_SCOPE) endif() if(_vartype_var MATCHES ".+") set(${_vartype_var} ${_vartype} PARENT_SCOPE) endif() endfunction() set(_ALL_PROJECT_IDENTIFIER "ALLALLALL") # # _sb_append_to_cmake_args( # [VARS : [: [...]]] # [PROJECTS [ [...]] | ALL_PROJECTS] # [LABELS [ [...]]] # ) # # PROJECTS corresponds to a list of that will be added using 'ExternalProject_Add' function. # If not specified and called within a project file, it defaults to the value of 'SUPERBUILD_TOPLEVEL_PROJECT'. # If instead 'ALL_PROJECTS' is specified, the variables and labels will be passed to all projects. # # VARS is an expected list of variables specified as : to pass to # # # LABELS is an optional list of label to associate with the variable names specified using 'VARS' and passed to # the as CMake CACHE args of the form: # -D_EP_LABEL_=;[...] # -D_EP_LABEL_=;[...] # function(_sb_append_to_cmake_args) set(options ALL_PROJECTS) set(oneValueArgs) set(multiValueArgs VARS PROJECTS LABELS) cmake_parse_arguments(_sb "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if(NOT _sb_PROJECTS AND NOT _sb_ALL_PROJECTS) set(_sb_PROJECTS ${SUPERBUILD_TOPLEVEL_PROJECT}) endif() if(_sb_ALL_PROJECTS) set(_sb_PROJECTS ${_ALL_PROJECT_IDENTIFIER}) endif() foreach(_sb_PROJECT ${_sb_PROJECTS}) set(_ep_varnames "") foreach(varname_and_vartype ${_sb_VARS}) if(NOT TARGET ${_sb_PROJECT}) set_property(GLOBAL APPEND PROPERTY ${_sb_PROJECT}_EP_CMAKE_ARGS ${varname_and_vartype}) _sb_extract_varname_and_vartype(${varname_and_vartype} _varname) else() message(FATAL_ERROR "Function _sb_append_to_cmake_args not allowed because project '${_sb_PROJECT}' already added !") endif() list(APPEND _ep_varnames ${_varname}) endforeach() if(_sb_LABELS) set_property(GLOBAL APPEND PROPERTY ${_sb_PROJECT}_EP_LABELS ${_sb_LABELS}) foreach(label ${_sb_LABELS}) set_property(GLOBAL APPEND PROPERTY ${_sb_PROJECT}_EP_LABEL_${label} ${_ep_varnames}) endforeach() endif() endforeach() endfunction() #.rst: # .. cmake:function:: ExternalProject_DeclareLabels # # .. code-block:: cmake # # ExternalProject_DeclareLabels( # [PROJECTS [ [...]] | ALL_PROJECTS] # LABELS [ [...]] # ) # # .. code-block:: cmake # # PROJECTS corresponds to a list of that will be added using 'ExternalProject_Add' function. # If not specified and called within a project file, it defaults to the value of 'SUPERBUILD_TOPLEVEL_PROJECT'. # If instead 'ALL_PROJECTS' is specified, the variables and labels will be passed to all projects. # # LABELS is a list of label to pass to the as CMake CACHE args of the # form -D_EP_LABEL_