| cmake_policy(VERSION 3.25) |
| |
| # Determine the remote URL of the project containing the working_directory. |
| # This will leave output_variable unset if the URL can't be determined. |
| function(_ep_get_git_remote_url output_variable working_directory) |
| set("${output_variable}" "" PARENT_SCOPE) |
| |
| find_package(Git QUIET REQUIRED) |
| |
| execute_process( |
| COMMAND ${GIT_EXECUTABLE} symbolic-ref --short HEAD |
| WORKING_DIRECTORY "${working_directory}" |
| OUTPUT_VARIABLE git_symbolic_ref |
| OUTPUT_STRIP_TRAILING_WHITESPACE |
| ERROR_QUIET |
| ) |
| |
| if(NOT git_symbolic_ref STREQUAL "") |
| # We are potentially on a branch. See if that branch is associated with |
| # an upstream remote (might be just a local one or not a branch at all). |
| execute_process( |
| COMMAND ${GIT_EXECUTABLE} config branch.${git_symbolic_ref}.remote |
| WORKING_DIRECTORY "${working_directory}" |
| OUTPUT_VARIABLE git_remote_name |
| OUTPUT_STRIP_TRAILING_WHITESPACE |
| ERROR_QUIET |
| ) |
| endif() |
| |
| if(NOT git_remote_name) |
| # Can't select a remote based on a branch. If there's only one remote, |
| # or we have multiple remotes but one is called "origin", choose that. |
| execute_process( |
| COMMAND ${GIT_EXECUTABLE} remote |
| WORKING_DIRECTORY "${working_directory}" |
| OUTPUT_VARIABLE git_remote_list |
| OUTPUT_STRIP_TRAILING_WHITESPACE |
| ERROR_QUIET |
| ) |
| string(REPLACE "\n" ";" git_remote_list "${git_remote_list}") |
| list(LENGTH git_remote_list git_remote_list_length) |
| |
| if(git_remote_list_length EQUAL 0) |
| message(FATAL_ERROR "Git remote not found in parent project.") |
| elseif(git_remote_list_length EQUAL 1) |
| list(GET git_remote_list 0 git_remote_name) |
| else() |
| set(base_warning_msg "Multiple git remotes found for parent project") |
| if("origin" IN_LIST git_remote_list) |
| message(WARNING "${base_warning_msg}, defaulting to origin.") |
| set(git_remote_name "origin") |
| else() |
| message(FATAL_ERROR "${base_warning_msg}, none of which are origin.") |
| endif() |
| endif() |
| endif() |
| |
| if(GIT_VERSION VERSION_LESS 1.7.5) |
| set(_git_remote_url_cmd_args config remote.${git_remote_name}.url) |
| elseif(GIT_VERSION VERSION_LESS 2.7) |
| set(_git_remote_url_cmd_args ls-remote --get-url ${git_remote_name}) |
| else() |
| set(_git_remote_url_cmd_args remote get-url ${git_remote_name}) |
| endif() |
| |
| execute_process( |
| COMMAND ${GIT_EXECUTABLE} ${_git_remote_url_cmd_args} |
| WORKING_DIRECTORY "${working_directory}" |
| OUTPUT_VARIABLE git_remote_url |
| OUTPUT_STRIP_TRAILING_WHITESPACE |
| COMMAND_ERROR_IS_FATAL LAST |
| ENCODING UTF-8 # Needed to handle non-ascii characters in local paths |
| ) |
| |
| set("${output_variable}" "${git_remote_url}" PARENT_SCOPE) |
| endfunction() |
| |
| |
| function(_ep_is_relative_git_remote output_variable remote_url) |
| if(remote_url MATCHES "^\\.\\./") |
| set("${output_variable}" TRUE PARENT_SCOPE) |
| else() |
| set("${output_variable}" FALSE PARENT_SCOPE) |
| endif() |
| endfunction() |
| |
| |
| # Return an absolute remote URL given an existing remote URL and relative path. |
| # The output_variable will be set to an empty string if an absolute URL |
| # could not be computed (no error message is output). |
| function(_ep_resolve_relative_git_remote |
| output_variable |
| parent_remote_url |
| relative_remote_url |
| ) |
| set("${output_variable}" "" PARENT_SCOPE) |
| |
| if(parent_remote_url STREQUAL "") |
| return() |
| endif() |
| |
| string(REGEX MATCH |
| "^(([A-Za-z0-9][A-Za-z0-9+.-]*)://)?(([^/@]+)@)?(\\[[A-Za-z0-9:]+\\]|[^/:]+)?([/:]/?)(.+(\\.git)?/?)$" |
| git_remote_url_components |
| "${parent_remote_url}" |
| ) |
| |
| set(protocol "${CMAKE_MATCH_1}") |
| set(auth "${CMAKE_MATCH_3}") |
| set(host "${CMAKE_MATCH_5}") |
| set(separator "${CMAKE_MATCH_6}") |
| set(path "${CMAKE_MATCH_7}") |
| |
| string(REPLACE "/" ";" remote_path_components "${path}") |
| string(REPLACE "/" ";" relative_path_components "${relative_remote_url}") |
| |
| foreach(relative_path_component IN LISTS relative_path_components) |
| if(NOT relative_path_component STREQUAL "..") |
| break() |
| endif() |
| |
| list(LENGTH remote_path_components remote_path_component_count) |
| |
| if(remote_path_component_count LESS 1) |
| return() |
| endif() |
| |
| list(POP_BACK remote_path_components) |
| list(POP_FRONT relative_path_components) |
| endforeach() |
| |
| list(APPEND final_path_components ${remote_path_components} ${relative_path_components}) |
| list(JOIN final_path_components "/" path) |
| |
| set("${output_variable}" "${protocol}${auth}${host}${separator}${path}" PARENT_SCOPE) |
| endfunction() |
| |
| |
| # The output_variable will be set to the original git_repository if it |
| # could not be resolved (no error message is output). The original value is |
| # also returned if it doesn't need to be resolved. |
| function(_ep_resolve_git_remote |
| output_variable |
| git_repository |
| cmp0150 |
| cmp0150_old_base_dir |
| ) |
| if(git_repository STREQUAL "") |
| set("${output_variable}" "" PARENT_SCOPE) |
| return() |
| endif() |
| |
| _ep_is_relative_git_remote(_git_repository_is_relative "${git_repository}") |
| |
| if(NOT _git_repository_is_relative) |
| set("${output_variable}" "${git_repository}" PARENT_SCOPE) |
| return() |
| endif() |
| |
| if(cmp0150 STREQUAL "NEW") |
| _ep_get_git_remote_url(_parent_git_remote_url "${CMAKE_CURRENT_SOURCE_DIR}") |
| _ep_resolve_relative_git_remote(_resolved_git_remote_url "${_parent_git_remote_url}" "${git_repository}") |
| |
| if(_resolved_git_remote_url STREQUAL "") |
| message(FATAL_ERROR |
| "Failed to resolve relative git remote URL:\n" |
| " Relative URL: ${git_repository}\n" |
| " Parent URL: ${_parent_git_remote_url}" |
| ) |
| endif() |
| set("${output_variable}" "${_resolved_git_remote_url}" PARENT_SCOPE) |
| return() |
| elseif(cmp0150 STREQUAL "") |
| cmake_policy(GET_WARNING CMP0150 _cmp0150_warning) |
| message(AUTHOR_WARNING |
| "${_cmp0150_warning}\n" |
| "A relative GIT_REPOSITORY path was detected. " |
| "This will be interpreted as a local path to where the project is being cloned. " |
| "Set GIT_REPOSITORY to an absolute path or set policy CMP0150 to NEW to avoid " |
| "this warning." |
| ) |
| endif() |
| |
| set("${output_variable}" "${cmp0150_old_base_dir}/${git_repository}" PARENT_SCOPE) |
| endfunction() |
| |
| |
| macro(_ep_get_hash_algos out_var) |
| set(${out_var} |
| MD5 |
| SHA1 |
| SHA224 |
| SHA256 |
| SHA384 |
| SHA512 |
| SHA3_224 |
| SHA3_256 |
| SHA3_384 |
| SHA3_512 |
| ) |
| endmacro() |
| |
| |
| macro(_ep_get_hash_regex out_var) |
| _ep_get_hash_algos(${out_var}) |
| list(JOIN ${out_var} "|" ${out_var}) |
| set(${out_var} "^(${${out_var}})=([0-9A-Fa-f]+)$") |
| endmacro() |
| |
| |
| function(_ep_parse_arguments_to_vars |
| f |
| keywords |
| name |
| ns |
| args |
| ) |
| # Transfer the arguments into variables in the calling scope. |
| # Because some keywords can be repeated, we can't use cmake_parse_arguments(). |
| # Instead, we loop through the args and consider the namespace starting with |
| # an upper-case letter followed by at least two more upper-case letters, |
| # numbers or underscores to be keywords. |
| |
| foreach(key IN LISTS keywords) |
| unset(${ns}${key}) |
| endforeach() |
| |
| set(key) |
| |
| foreach(arg IN LISTS args) |
| set(is_value 1) |
| |
| if(arg MATCHES "^[A-Z][A-Z0-9_][A-Z0-9_]+$" AND |
| NOT (("x${arg}x" STREQUAL "x${key}x") AND |
| ("x${key}x" STREQUAL "xCOMMANDx")) AND |
| NOT arg MATCHES "^(TRUE|FALSE|YES)$") |
| if(arg IN_LIST keywords) |
| set(is_value 0) |
| endif() |
| endif() |
| |
| if(is_value) |
| if(key) |
| # Value |
| list(APPEND ${ns}${key} "${arg}") |
| else() |
| # Missing Keyword |
| message(AUTHOR_WARNING |
| "value '${arg}' with no previous keyword in ${f}" |
| ) |
| endif() |
| else() |
| set(key "${arg}") |
| endif() |
| endforeach() |
| |
| foreach(key IN LISTS keywords) |
| if(DEFINED ${ns}${key}) |
| set(${ns}${key} "${${ns}${key}}" PARENT_SCOPE) |
| else() |
| unset(${ns}${key} PARENT_SCOPE) |
| endif() |
| endforeach() |
| |
| endfunction() |
| |
| |
| # NOTE: This cannot be a macro because that will evaluate anything that looks |
| # like a CMake variable in any of the args. |
| function(_ep_parse_arguments |
| f |
| keywords |
| name |
| ns |
| args |
| ) |
| _ep_parse_arguments_to_vars( |
| "${f}" |
| "${keywords}" |
| ${name} |
| ${ns} |
| "${args}" |
| ) |
| |
| foreach(key IN LISTS keywords) |
| if(DEFINED ${ns}${key}) |
| set(${ns}${key} "${${ns}${key}}" PARENT_SCOPE) |
| else() |
| unset(${ns}${key} PARENT_SCOPE) |
| endif() |
| endforeach() |
| |
| # Transfer the arguments to the target as target properties. These are |
| # read by the various steps, potentially from different scopes. |
| foreach(key IN LISTS keywords) |
| if(DEFINED ${ns}${key}) |
| set_property(TARGET ${name} PROPERTY ${ns}${key} "${${ns}${key}}") |
| endif() |
| endforeach() |
| |
| endfunction() |
| |
| |
| function(_ep_get_tls_version name tls_version_var) |
| # Note that the arguments are assumed to have already been parsed and have |
| # been translated into variables with the prefix _EP_... by a call to |
| # ep_parse_arguments() or ep_parse_arguments_to_vars(). |
| set(tls_version_regex "^1\\.[0-3]$") |
| set(tls_version "${_EP_TLS_VERSION}") |
| if(NOT "x${tls_version}" STREQUAL "x") |
| if(NOT tls_version MATCHES "${tls_version_regex}") |
| message(FATAL_ERROR "TLS_VERSION '${tls_version}' not known") |
| endif() |
| elseif(NOT "x${CMAKE_TLS_VERSION}" STREQUAL "x") |
| set(tls_version "${CMAKE_TLS_VERSION}") |
| if(NOT tls_version MATCHES "${tls_version_regex}") |
| message(FATAL_ERROR "CMAKE_TLS_VERSION '${tls_version}' not known") |
| endif() |
| elseif(NOT "x$ENV{CMAKE_TLS_VERSION}" STREQUAL "x") |
| set(tls_version "$ENV{CMAKE_TLS_VERSION}") |
| if(NOT tls_version MATCHES "${tls_version_regex}") |
| message(FATAL_ERROR "ENV{CMAKE_TLS_VERSION} '${tls_version}' not known") |
| endif() |
| endif() |
| set("${tls_version_var}" "${tls_version}" PARENT_SCOPE) |
| endfunction() |
| |
| |
| function(_ep_get_tls_verify name tls_verify_var) |
| # Note that the arguments are assumed to have already been parsed and have |
| # been translated into variables with the prefix _EP_... by a call to |
| # ep_parse_arguments() or ep_parse_arguments_to_vars(). |
| set(tls_verify "${_EP_TLS_VERIFY}") |
| if("x${tls_verify}" STREQUAL "x") |
| if(NOT "x${CMAKE_TLS_VERIFY}" STREQUAL "x") |
| set(tls_verify "${CMAKE_TLS_VERIFY}") |
| elseif(NOT "x$ENV{CMAKE_TLS_VERIFY}" STREQUAL "x") |
| set(tls_verify "$ENV{CMAKE_TLS_VERIFY}") |
| endif() |
| endif() |
| set("${tls_verify_var}" "${tls_verify}" PARENT_SCOPE) |
| endfunction() |
| |
| |
| function(_ep_get_tls_cainfo name tls_cainfo_var) |
| # Note that the arguments are assumed to have already been parsed and have |
| # been translated into variables with the prefix _EP_... by a call to |
| # ep_parse_arguments() or ep_parse_arguments_to_vars(). |
| set(tls_cainfo "${_EP_TLS_CAINFO}") |
| if("x${tls_cainfo}" STREQUAL "x" AND DEFINED CMAKE_TLS_CAINFO) |
| set(tls_cainfo "${CMAKE_TLS_CAINFO}") |
| endif() |
| set("${tls_cainfo_var}" "${tls_cainfo}" PARENT_SCOPE) |
| endfunction() |
| |
| |
| function(_ep_get_netrc name netrc_var) |
| # Note that the arguments are assumed to have already been parsed and have |
| # been translated into variables with the prefix _EP_... by a call to |
| # ep_parse_arguments() or ep_parse_arguments_to_vars(). |
| set(netrc "${_EP_NETRC}") |
| if("x${netrc}" STREQUAL "x" AND DEFINED CMAKE_NETRC) |
| set(netrc "${CMAKE_NETRC}") |
| endif() |
| set("${netrc_var}" "${netrc}" PARENT_SCOPE) |
| endfunction() |
| |
| |
| function(_ep_get_netrc_file name netrc_file_var) |
| # Note that the arguments are assumed to have already been parsed and have |
| # been translated into variables with the prefix _EP_... by a call to |
| # ep_parse_arguments() or ep_parse_arguments_to_vars(). |
| set(netrc_file "${_EP_NETRC_FILE}") |
| if("x${netrc_file}" STREQUAL "x" AND DEFINED CMAKE_NETRC_FILE) |
| set(netrc_file "${CMAKE_NETRC_FILE}") |
| endif() |
| set("${netrc_file_var}" "${netrc_file}" PARENT_SCOPE) |
| endfunction() |
| |
| |
| function(_ep_write_gitclone_script |
| script_filename |
| source_dir |
| git_EXECUTABLE |
| git_repository |
| git_tag |
| git_remote_name |
| init_submodules |
| git_submodules_recurse |
| git_submodules |
| git_shallow |
| git_progress |
| git_config |
| src_name |
| work_dir |
| gitclone_infofile |
| gitclone_stampfile |
| tls_version |
| tls_verify |
| ) |
| |
| if(NOT GIT_VERSION_STRING VERSION_LESS 1.8.5) |
| # Use `git checkout <tree-ish> --` to avoid ambiguity with a local path. |
| set(git_checkout_explicit-- "--") |
| else() |
| # Use `git checkout <branch>` even though this risks ambiguity with a |
| # local path. Unfortunately we cannot use `git checkout <tree-ish> --` |
| # because that will not search for remote branch names, a common use case. |
| set(git_checkout_explicit-- "") |
| endif() |
| if("${git_tag}" STREQUAL "") |
| message(FATAL_ERROR "Tag for git checkout should not be empty.") |
| endif() |
| |
| if(GIT_VERSION_STRING VERSION_LESS 2.20 OR |
| 2.21 VERSION_LESS_EQUAL GIT_VERSION_STRING) |
| set(git_clone_options "--no-checkout") |
| else() |
| set(git_clone_options) |
| endif() |
| if(git_shallow) |
| if(NOT GIT_VERSION_STRING VERSION_LESS 1.7.10) |
| list(APPEND git_clone_options "--depth 1 --no-single-branch") |
| else() |
| list(APPEND git_clone_options "--depth 1") |
| endif() |
| endif() |
| if(git_progress) |
| list(APPEND git_clone_options --progress) |
| endif() |
| foreach(config IN LISTS git_config) |
| list(APPEND git_clone_options --config \"${config}\") |
| endforeach() |
| if(NOT ${git_remote_name} STREQUAL "origin") |
| list(APPEND git_clone_options --origin \"${git_remote_name}\") |
| endif() |
| |
| # The clone config option is sticky, it will apply to all subsequent git |
| # update operations. The submodules config option is not sticky, because |
| # git doesn't provide any way to do that. Thus, we will have to pass the |
| # same config option in the update step too for submodules, but not for |
| # the main git repo. |
| set(git_submodules_config_options "") |
| if(NOT "x${tls_version}" STREQUAL "x") |
| list(APPEND git_clone_options -c http.sslVersion=tlsv${tls_version}) |
| list(APPEND git_submodules_config_options -c http.sslVersion=tlsv${tls_version}) |
| endif() |
| if(NOT "x${tls_verify}" STREQUAL "x") |
| if(tls_verify) |
| # Default git behavior is "true", but the user might have changed the |
| # global default to "false". Since TLS_VERIFY was given, ensure we honor |
| # the specified setting regardless of what the global default might be. |
| list(APPEND git_clone_options -c http.sslVerify=true) |
| list(APPEND git_submodules_config_options -c http.sslVerify=true) |
| else() |
| list(APPEND git_clone_options -c http.sslVerify=false) |
| list(APPEND git_submodules_config_options -c http.sslVerify=false) |
| endif() |
| endif() |
| |
| string (REPLACE ";" " " git_clone_options "${git_clone_options}") |
| |
| configure_file( |
| ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/gitclone.cmake.in |
| ${script_filename} |
| @ONLY |
| ) |
| endfunction() |
| |
| |
| function(_ep_write_hgclone_script |
| script_filename |
| source_dir |
| hg_EXECUTABLE |
| hg_repository |
| hg_tag |
| src_name |
| work_dir |
| hgclone_infofile |
| hgclone_stampfile |
| ) |
| |
| if("${hg_tag}" STREQUAL "") |
| message(FATAL_ERROR "Tag for hg checkout should not be empty.") |
| endif() |
| |
| configure_file( |
| ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/hgclone.cmake.in |
| ${script_filename} |
| @ONLY |
| ) |
| endfunction() |
| |
| |
| function(_ep_write_gitupdate_script |
| script_filename |
| git_EXECUTABLE |
| git_tag |
| git_remote_name |
| init_submodules |
| git_submodules_recurse |
| git_submodules |
| git_repository |
| work_dir |
| git_update_strategy |
| tls_version |
| tls_verify |
| ) |
| |
| if("${git_tag}" STREQUAL "") |
| message(FATAL_ERROR "Tag for git checkout should not be empty.") |
| endif() |
| set(git_stash_save_options --quiet) |
| if(GIT_VERSION_STRING VERSION_GREATER_EQUAL 1.7.7) |
| # This avoids stashing files covered by .gitignore |
| list(APPEND git_stash_save_options --include-untracked) |
| elseif(GIT_VERSION_STRING VERSION_GREATER_EQUAL 1.7.6) |
| # Untracked files, but also ignored files, so potentially slower |
| list(APPEND git_stash_save_options --all) |
| endif() |
| |
| # The submodules config option is not sticky, git doesn't provide any way |
| # to do that. We have to pass this config option for the update step too. |
| # We don't need to set it for the non-submodule update because it gets |
| # recorded as part of the clone operation in a sticky manner. |
| set(git_submodules_config_options "") |
| if(NOT "x${tls_version}" STREQUAL "x") |
| list(APPEND git_submodules_config_options -c http.sslVersion=tlsv${tls_version}) |
| endif() |
| if(NOT "x${tls_verify}" STREQUAL "x") |
| if(tls_verify) |
| # Default git behavior is "true", but the user might have changed the |
| # global default to "false". Since TLS_VERIFY was given, ensure we honor |
| # the specified setting regardless of what the global default might be. |
| list(APPEND git_submodules_config_options -c http.sslVerify=true) |
| else() |
| list(APPEND git_submodules_config_options -c http.sslVerify=false) |
| endif() |
| endif() |
| |
| configure_file( |
| "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/gitupdate.cmake.in" |
| "${script_filename}" |
| @ONLY |
| ) |
| endfunction() |
| |
| |
| function(_ep_write_downloadfile_script |
| script_filename |
| REMOTE |
| LOCAL |
| timeout |
| inactivity_timeout |
| no_progress |
| hash |
| tls_version |
| tls_verify |
| tls_cainfo |
| userpwd |
| http_headers |
| netrc |
| netrc_file |
| ) |
| if("x${REMOTE}" STREQUAL "x") |
| message(FATAL_ERROR "REMOTE can't be empty") |
| endif() |
| if("x${LOCAL}" STREQUAL "x") |
| message(FATAL_ERROR "LOCAL can't be empty") |
| endif() |
| |
| # REMOTE could contain special characters that parse as separate arguments. |
| # Things like parentheses are legitimate characters in a URL, but would be |
| # seen as the start of a new unquoted argument by the cmake language parser. |
| # Avoid those special cases by preparing quoted strings for direct inclusion |
| # in the foreach() call that iterates over the set of URLs in REMOTE. |
| set(REMOTE "[====[${REMOTE}]====]") |
| string(REPLACE ";" "]====] [====[" REMOTE "${REMOTE}") |
| |
| if(timeout) |
| set(TIMEOUT_ARGS TIMEOUT ${timeout}) |
| set(TIMEOUT_MSG "${timeout} seconds") |
| else() |
| set(TIMEOUT_ARGS "# no TIMEOUT") |
| set(TIMEOUT_MSG "none") |
| endif() |
| if(inactivity_timeout) |
| set(INACTIVITY_TIMEOUT_ARGS INACTIVITY_TIMEOUT ${inactivity_timeout}) |
| set(INACTIVITY_TIMEOUT_MSG "${inactivity_timeout} seconds") |
| else() |
| set(INACTIVITY_TIMEOUT_ARGS "# no INACTIVITY_TIMEOUT") |
| set(INACTIVITY_TIMEOUT_MSG "none") |
| endif() |
| |
| if(no_progress) |
| set(SHOW_PROGRESS "") |
| else() |
| set(SHOW_PROGRESS "SHOW_PROGRESS") |
| endif() |
| |
| _ep_get_hash_regex(_ep_hash_regex) |
| if("${hash}" MATCHES "${_ep_hash_regex}") |
| set(ALGO "${CMAKE_MATCH_1}") |
| string(TOLOWER "${CMAKE_MATCH_2}" EXPECT_VALUE) |
| else() |
| set(ALGO "") |
| set(EXPECT_VALUE "") |
| endif() |
| |
| set(TLS_VERSION_CODE "") |
| if(NOT "x${tls_version}" STREQUAL "x") |
| set(TLS_VERSION_CODE "set(CMAKE_TLS_VERSION \"${tls_version}\")") |
| endif() |
| |
| set(TLS_VERIFY_CODE "") |
| if(NOT "x${tls_verify}" STREQUAL "x") |
| set(TLS_VERIFY_CODE "set(CMAKE_TLS_VERIFY \"${tls_verify}\")") |
| endif() |
| |
| set(TLS_CAINFO_CODE "") |
| if(NOT "x${tls_cainfo}" STREQUAL "x") |
| set(TLS_CAINFO_CODE "set(CMAKE_TLS_CAINFO \"${tls_cainfo}\")") |
| endif() |
| |
| set(NETRC_CODE "") |
| if(NOT "x${netrc}" STREQUAL "x") |
| set(NETRC_CODE "set(CMAKE_NETRC \"${netrc}\")") |
| endif() |
| |
| set(NETRC_FILE_CODE "") |
| if(NOT "x${netrc_file}" STREQUAL "x") |
| set(NETRC_FILE_CODE "set(CMAKE_NETRC_FILE \"${netrc_file}\")") |
| endif() |
| |
| if(userpwd STREQUAL ":") |
| set(USERPWD_ARGS) |
| else() |
| set(USERPWD_ARGS USERPWD "${userpwd}") |
| endif() |
| |
| set(HTTP_HEADERS_ARGS "") |
| if(NOT http_headers STREQUAL "") |
| foreach(header IN LISTS http_headers) |
| string(PREPEND HTTP_HEADERS_ARGS |
| "HTTPHEADER \"${header}\"\n " |
| ) |
| endforeach() |
| endif() |
| |
| # Used variables: |
| # * TLS_VERSION_CODE |
| # * TLS_VERIFY_CODE |
| # * TLS_CAINFO_CODE |
| # * ALGO |
| # * EXPECT_VALUE |
| # * REMOTE |
| # * LOCAL |
| # * SHOW_PROGRESS |
| # * TIMEOUT_ARGS |
| # * TIMEOUT_MSG |
| # * USERPWD_ARGS |
| # * HTTP_HEADERS_ARGS |
| configure_file( |
| "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/download.cmake.in" |
| "${script_filename}" |
| @ONLY |
| ) |
| endfunction() |
| |
| |
| function(_ep_write_verifyfile_script |
| script_filename |
| LOCAL |
| hash |
| ) |
| _ep_get_hash_regex(_ep_hash_regex) |
| if("${hash}" MATCHES "${_ep_hash_regex}") |
| set(ALGO "${CMAKE_MATCH_1}") |
| string(TOLOWER "${CMAKE_MATCH_2}" EXPECT_VALUE) |
| else() |
| set(ALGO "") |
| set(EXPECT_VALUE "") |
| endif() |
| |
| # Used variables: |
| # * ALGO |
| # * EXPECT_VALUE |
| # * LOCAL |
| configure_file( |
| "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/verify.cmake.in" |
| "${script_filename}" |
| @ONLY |
| ) |
| endfunction() |
| |
| |
| function(_ep_write_extractfile_script |
| script_filename |
| name |
| filename |
| directory |
| options |
| ) |
| set(args "") |
| |
| if(filename MATCHES |
| "(\\.|=)(7z|tar\\.bz2|tar\\.gz|tar\\.xz|tbz2|tgz|txz|zip)$") |
| set(args xfz) |
| endif() |
| |
| if(filename MATCHES "(\\.|=)tar$") |
| set(args xf) |
| endif() |
| |
| if(args STREQUAL "") |
| message(FATAL_ERROR |
| "Do not know how to extract '${filename}' -- known types are: " |
| ".7z, .tar, .tar.bz2, .tar.gz, .tar.xz, .tbz2, .tgz, .txz and .zip" |
| ) |
| endif() |
| |
| configure_file( |
| "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/extractfile.cmake.in" |
| "${script_filename}" |
| @ONLY |
| ) |
| endfunction() |
| |
| |
| function(_ep_is_dir_empty dir empty_var) |
| file(GLOB gr "${dir}/*") |
| if("${gr}" STREQUAL "") |
| set(${empty_var} 1 PARENT_SCOPE) |
| else() |
| set(${empty_var} 0 PARENT_SCOPE) |
| endif() |
| endfunction() |
| |
| function(_ep_get_git_submodules_recurse git_submodules_recurse) |
| # Checks for GIT_SUBMODULES_RECURSE argument. Default is ON, which sets |
| # git_submodules_recurse output variable to "--recursive". Otherwise, the |
| # output variable is set to an empty value "". |
| # Note that the arguments are assumed to have already been parsed and have |
| # been translated into variables with the prefix _EP_... by a call to |
| # ep_parse_arguments() or ep_parse_arguments_to_vars(). |
| if(NOT DEFINED _EP_GIT_SUBMODULES_RECURSE) |
| set(recurseFlag "--recursive") |
| else() |
| if(_EP_GIT_SUBMODULES_RECURSE) |
| set(recurseFlag "--recursive") |
| else() |
| set(recurseFlag "") |
| endif() |
| endif() |
| set(${git_submodules_recurse} "${recurseFlag}" PARENT_SCOPE) |
| |
| # The git submodule update '--recursive' flag requires git >= v1.6.5 |
| if(recurseFlag AND GIT_VERSION_STRING VERSION_LESS 1.6.5) |
| message(FATAL_ERROR |
| "git version 1.6.5 or later required for --recursive flag with " |
| "'git submodule ...': GIT_VERSION_STRING='${GIT_VERSION_STRING}'" |
| ) |
| endif() |
| endfunction() |
| |
| |
| function(_ep_add_script_commands script_var work_dir cmd) |
| # We only support a subset of what ep_replace_location_tags() handles |
| set(location_tags |
| SOURCE_DIR |
| SOURCE_SUBDIR |
| BINARY_DIR |
| TMP_DIR |
| DOWNLOAD_DIR |
| DOWNLOADED_FILE |
| ) |
| |
| # There can be multiple COMMANDs, but we have to split those up to |
| # one command per call to execute_process() |
| string(CONCAT execute_process_cmd |
| "execute_process(\n" |
| " WORKING_DIRECTORY \"${work_dir}\"\n" |
| " COMMAND_ERROR_IS_FATAL LAST\n" |
| ) |
| cmake_language(GET_MESSAGE_LOG_LEVEL active_log_level) |
| if(active_log_level MATCHES "VERBOSE|DEBUG|TRACE") |
| string(APPEND execute_process_cmd " COMMAND_ECHO STDOUT\n") |
| endif() |
| string(APPEND execute_process_cmd " COMMAND ") |
| |
| string(APPEND ${script_var} "${execute_process_cmd}") |
| |
| foreach(cmd_arg IN LISTS cmd) |
| if(cmd_arg STREQUAL "COMMAND") |
| string(APPEND ${script_var} "\n)\n${execute_process_cmd}") |
| else() |
| if(_EP_LIST_SEPARATOR) |
| string(REPLACE "${_EP_LIST_SEPARATOR}" "\\;" cmd_arg "${cmd_arg}") |
| endif() |
| foreach(dir IN LISTS location_tags) |
| string(REPLACE "<${dir}>" "${_EP_${dir}}" cmd_arg "${cmd_arg}") |
| endforeach() |
| string(APPEND ${script_var} " [====[${cmd_arg}]====]") |
| endif() |
| endforeach() |
| |
| string(APPEND ${script_var} "\n)") |
| set(${script_var} "${${script_var}}" PARENT_SCOPE) |
| endfunction() |
| |
| |
| function(_ep_add_download_command name) |
| set(noValueOptions ) |
| set(singleValueOptions |
| SCRIPT_FILE # These should only be used by FetchContent |
| DEPENDS_VARIABLE # |
| ) |
| set(multiValueOptions ) |
| cmake_parse_arguments(PARSE_ARGV 1 arg |
| "${noValueOptions}" "${singleValueOptions}" "${multiValueOptions}" |
| ) |
| |
| # The various _EP_... variables mentioned here and throughout this function |
| # are expected to already have been set by the caller via a call to |
| # _ep_parse_arguments() or ep_parse_arguments_to_vars(). Other variables |
| # with different names are assigned to for historical reasons only to keep |
| # the code more readable and minimize change. |
| |
| set(source_dir "${_EP_SOURCE_DIR}") |
| set(stamp_dir "${_EP_STAMP_DIR}") |
| set(download_dir "${_EP_DOWNLOAD_DIR}") |
| set(tmp_dir "${_EP_TMP_DIR}") |
| |
| set(cmd "${_EP_DOWNLOAD_COMMAND}") |
| set(cvs_repository "${_EP_CVS_REPOSITORY}") |
| set(svn_repository "${_EP_SVN_REPOSITORY}") |
| set(git_repository "${_EP_GIT_REPOSITORY}") |
| set(hg_repository "${_EP_HG_REPOSITORY}") |
| set(url "${_EP_URL}") |
| set(fname "${_EP_DOWNLOAD_NAME}") |
| |
| # TODO: Perhaps file:// should be copied to download dir before extraction. |
| string(REGEX REPLACE "file://" "" url "${url}") |
| |
| set(step_script_contents) |
| set(depends) |
| set(comment) |
| set(work_dir) |
| set(extra_repo_info) |
| |
| if(DEFINED _EP_DOWNLOAD_COMMAND) |
| set(work_dir ${download_dir}) |
| set(method custom) |
| if(NOT "x${cmd}" STREQUAL "x" AND arg_SCRIPT_FILE) |
| _ep_add_script_commands( |
| step_script_contents |
| "${work_dir}" |
| "${cmd}" # Must be a single quoted argument |
| ) |
| endif() |
| |
| elseif(cvs_repository) |
| set(method cvs) |
| find_package(CVS QUIET) |
| if(NOT CVS_EXECUTABLE) |
| message(FATAL_ERROR "error: could not find cvs for checkout of ${name}") |
| endif() |
| |
| set(cvs_module "${_EP_CVS_MODULE}") |
| if(NOT cvs_module) |
| message(FATAL_ERROR "error: no CVS_MODULE") |
| endif() |
| |
| set(cvs_tag "${_EP_CVS_TAG}") |
| get_filename_component(src_name "${source_dir}" NAME) |
| get_filename_component(work_dir "${source_dir}" PATH) |
| set(comment "Performing download step (CVS checkout) for '${name}'") |
| set(cmd |
| ${CVS_EXECUTABLE} |
| -d ${cvs_repository} |
| -q |
| co ${cvs_tag} |
| -d ${src_name} |
| ${cvs_module} |
| ) |
| if(arg_SCRIPT_FILE) |
| _ep_add_script_commands( |
| step_script_contents |
| "${work_dir}" |
| "${cmd}" # Must be a single quoted argument |
| ) |
| endif() |
| |
| elseif(svn_repository) |
| set(method svn) |
| find_package(Subversion QUIET) |
| if(NOT Subversion_SVN_EXECUTABLE) |
| message(FATAL_ERROR "error: could not find svn for checkout of ${name}") |
| endif() |
| |
| set(svn_revision "${_EP_SVN_REVISION}") |
| set(svn_username "${_EP_SVN_USERNAME}") |
| set(svn_password "${_EP_SVN_PASSWORD}") |
| set(svn_trust_cert "${_EP_SVN_TRUST_CERT}") |
| set(uses_terminal "${_EP_USES_TERMINAL_DOWNLOAD}") |
| # The --trust-server-cert option requires --non-interactive |
| if(uses_terminal AND NOT svn_trust_cert) |
| set(svn_interactive_args "") |
| else() |
| set(svn_interactive_args "--non-interactive") |
| endif() |
| |
| get_filename_component(src_name "${source_dir}" NAME) |
| get_filename_component(work_dir "${source_dir}" PATH) |
| set(comment "Performing download step (SVN checkout) for '${name}'") |
| set(svn_user_pw_args "") |
| if(DEFINED _EP_SVN_USERNAME) |
| set(svn_user_pw_args ${svn_user_pw_args} "--username=${svn_username}") |
| endif() |
| if(DEFINED _EP_SVN_PASSWORD) |
| set(svn_user_pw_args ${svn_user_pw_args} "--password=${svn_password}") |
| endif() |
| if(svn_trust_cert) |
| set(svn_trust_cert_args --trust-server-cert) |
| endif() |
| set(cmd |
| ${Subversion_SVN_EXECUTABLE} |
| co |
| ${svn_repository} |
| ${svn_revision} |
| ${svn_interactive_args} |
| ${svn_trust_cert_args} |
| ${svn_user_pw_args} |
| ${src_name} |
| ) |
| if(arg_SCRIPT_FILE) |
| _ep_add_script_commands( |
| step_script_contents |
| "${work_dir}" |
| "${cmd}" # Must be a single quoted argument |
| ) |
| endif() |
| |
| elseif(git_repository) |
| set(method git) |
| # FetchContent gives us these directly, so don't try to recompute them |
| if(NOT GIT_EXECUTABLE OR NOT GIT_VERSION_STRING) |
| unset(CMAKE_MODULE_PATH) # Use CMake builtin find module |
| find_package(Git QUIET) |
| if(NOT GIT_EXECUTABLE) |
| message(FATAL_ERROR "error: could not find git for clone of ${name}") |
| endif() |
| endif() |
| |
| _ep_get_git_submodules_recurse(git_submodules_recurse) |
| |
| set(git_tag "${_EP_GIT_TAG}") |
| if(NOT git_tag) |
| set(git_tag "master") |
| endif() |
| |
| set(git_init_submodules TRUE) |
| if(DEFINED _EP_GIT_SUBMODULES) |
| set(git_submodules "${_EP_GIT_SUBMODULES}") |
| if(git_submodules STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW") |
| set(git_init_submodules FALSE) |
| endif() |
| endif() |
| |
| set(git_remote_name "${_EP_GIT_REMOTE_NAME}") |
| if(NOT git_remote_name) |
| set(git_remote_name "origin") |
| endif() |
| |
| _ep_get_tls_version(${name} tls_version) |
| _ep_get_tls_verify(${name} tls_verify) |
| set(git_shallow "${_EP_GIT_SHALLOW}") |
| set(git_progress "${_EP_GIT_PROGRESS}") |
| set(git_config "${_EP_GIT_CONFIG}") |
| |
| # If git supports it, make checkouts quiet when checking out a git hash. |
| # This avoids the very noisy detached head message. |
| if(GIT_VERSION_STRING VERSION_GREATER_EQUAL 1.7.7) |
| list(PREPEND git_config advice.detachedHead=false) |
| endif() |
| |
| # The command doesn't expose any details, so we need to record additional |
| # information in the RepositoryInfo.txt file. For the download step, only |
| # the things specifically affecting the clone operation should be recorded. |
| # If the repo changes, the clone script should be run again. |
| # But if only the tag changes, avoid running the clone script again. |
| # Let the 'always' running update step checkout the new tag. |
| # |
| set(extra_repo_info |
| "repository=${git_repository} |
| remote=${git_remote_name} |
| init_submodules=${git_init_submodules} |
| recurse_submodules=${git_submodules_recurse} |
| submodules=${git_submodules} |
| CMP0097=${_EP_CMP0097} |
| ") |
| get_filename_component(src_name "${source_dir}" NAME) |
| get_filename_component(work_dir "${source_dir}" PATH) |
| |
| # Since git clone doesn't succeed if the non-empty source_dir exists, |
| # create a cmake script to invoke as download command. |
| # The script will delete the source directory and then call git clone. |
| # |
| set(clone_script ${tmp_dir}/${name}-gitclone.cmake) |
| _ep_write_gitclone_script( |
| ${clone_script} |
| ${source_dir} |
| ${GIT_EXECUTABLE} |
| ${git_repository} |
| ${git_tag} |
| ${git_remote_name} |
| ${git_init_submodules} |
| "${git_submodules_recurse}" |
| "${git_submodules}" |
| "${git_shallow}" |
| "${git_progress}" |
| "${git_config}" |
| ${src_name} |
| ${work_dir} |
| ${stamp_dir}/${name}-gitinfo.txt |
| ${stamp_dir}/${name}-gitclone-lastrun.txt |
| "${tls_version}" |
| "${tls_verify}" |
| ) |
| set(comment "Performing download step (git clone) for '${name}'") |
| set(cmd ${CMAKE_COMMAND} |
| -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE |
| -P ${clone_script} |
| ) |
| |
| if(arg_SCRIPT_FILE) |
| set(step_script_contents "include(\"${clone_script}\")") |
| list(APPEND depends ${clone_script}) |
| endif() |
| |
| elseif(hg_repository) |
| set(method hg) |
| find_package(Hg QUIET) |
| if(NOT HG_EXECUTABLE) |
| message(FATAL_ERROR "error: could not find hg for clone of ${name}") |
| endif() |
| |
| set(hg_tag "${_EP_HG_TAG}") |
| if(NOT hg_tag) |
| set(hg_tag "tip") |
| endif() |
| |
| # The command doesn't expose any details, so we need to record additional |
| # information in the RepositoryInfo.txt file. For the download step, only |
| # the things specifically affecting the clone operation should be recorded. |
| # If the repo changes, the clone script should be run again. |
| # But if only the tag changes, avoid running the clone script again. |
| # Let the 'always' running update step checkout the new tag. |
| # |
| set(extra_repo_info "repository=${hg_repository}") |
| get_filename_component(src_name "${source_dir}" NAME) |
| get_filename_component(work_dir "${source_dir}" PATH) |
| |
| # Since hg clone doesn't succeed if the non-empty source_dir exists, |
| # create a cmake script to invoke as download command. |
| # The script will delete the source directory and then call hg clone. |
| # |
| set(clone_script ${tmp_dir}/${name}-hgclone.cmake) |
| _ep_write_hgclone_script( |
| ${clone_script} |
| ${source_dir} |
| ${HG_EXECUTABLE} |
| ${hg_repository} |
| ${hg_tag} |
| ${src_name} |
| ${work_dir} |
| ${stamp_dir}/${name}-hginfo.txt |
| ${stamp_dir}/${name}-hgclone-lastrun.txt |
| ) |
| set(comment "Performing download step (hg clone) for '${name}'") |
| set(cmd ${CMAKE_COMMAND} |
| -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE |
| -P ${clone_script} |
| ) |
| |
| if(arg_SCRIPT_FILE) |
| set(step_script_contents "include(\"${clone_script}\")") |
| list(APPEND depends ${clone_script}) |
| endif() |
| |
| elseif(url) |
| set(method url) |
| get_filename_component(work_dir "${source_dir}" PATH) |
| set(hash "${_EP_URL_HASH}") |
| _ep_get_hash_regex(_ep_hash_regex) |
| if(hash AND NOT "${hash}" MATCHES "${_ep_hash_regex}") |
| _ep_get_hash_algos(_ep_hash_algos) |
| list(JOIN _ep_hash_algos "|" _ep_hash_algos) |
| message(FATAL_ERROR |
| "URL_HASH is set to\n" |
| " ${hash}\n" |
| "but must be ALGO=value where ALGO is\n" |
| " ${_ep_hash_algos}\n" |
| "and value is a hex string." |
| ) |
| endif() |
| set(md5 "${_EP_URL_MD5}") |
| if(md5 AND NOT "MD5=${md5}" MATCHES "${_ep_hash_regex}") |
| message(FATAL_ERROR |
| "URL_MD5 is set to\n" |
| " ${md5}\n" |
| "but must be a hex string." |
| ) |
| endif() |
| if(md5 AND NOT hash) |
| set(hash "MD5=${md5}") |
| endif() |
| set(extra_repo_info |
| "url(s)=${url} |
| hash=${hash} |
| ") |
| |
| list(LENGTH url url_list_length) |
| if(NOT "${url_list_length}" STREQUAL "1") |
| foreach(entry IN LISTS url) |
| if(NOT "${entry}" MATCHES "^[a-z]+://") |
| message(FATAL_ERROR |
| "At least one entry of URL is a path (invalid in a list)" |
| ) |
| endif() |
| endforeach() |
| if("x${fname}" STREQUAL "x") |
| list(GET url 0 fname) |
| endif() |
| endif() |
| |
| if(IS_DIRECTORY "${url}") |
| get_filename_component(abs_dir "${url}" ABSOLUTE) |
| set(comment "Performing download step (DIR copy) for '${name}'") |
| set(cmd |
| ${CMAKE_COMMAND} -E rm -rf ${source_dir} |
| COMMAND ${CMAKE_COMMAND} -E copy_directory ${abs_dir} ${source_dir} |
| ) |
| if(arg_SCRIPT_FILE) |
| # While it may be tempting to implement the two operations directly |
| # with file(), the behavior is different. file(COPY) preserves input |
| # file timestamps, which we don't want. Therefore, still use the same |
| # external commands so that we get the same behavior. |
| _ep_add_script_commands( |
| step_script_contents |
| "${work_dir}" |
| "${cmd}" # Must be a single quoted argument |
| ) |
| endif() |
| else() |
| set(no_extract "${_EP_DOWNLOAD_NO_EXTRACT}") |
| string(APPEND extra_repo_info "no_extract=${no_extract}\n") |
| set(verify_script "${stamp_dir}/verify-${name}.cmake") |
| if("${url}" MATCHES "^[a-z]+://") |
| # TODO: Should download and extraction be different steps? |
| if("x${fname}" STREQUAL "x") |
| set(fname "${url}") |
| endif() |
| set(ext_regex [[7z|tar|tar\.bz2|tar\.gz|tar\.xz|tbz2|tgz|txz|zip]]) |
| if("${fname}" MATCHES "([^/\\?#]+(\\.|=)(${ext_regex}))([/?#].*)?$") |
| set(fname "${CMAKE_MATCH_1}") |
| elseif(no_extract) |
| get_filename_component(fname "${fname}" NAME) |
| else() |
| # Fall back to a default file name. The actual file name does not |
| # matter because it is used only internally and our extraction tool |
| # inspects the file content directly. If it turns out the wrong URL |
| # was given that will be revealed during the build which is an easier |
| # place for users to diagnose than an error here anyway. |
| set(fname "archive.tar") |
| endif() |
| string(REPLACE ";" "-" fname "${fname}") |
| set(file ${download_dir}/${fname}) |
| set(timeout "${_EP_TIMEOUT}") |
| set(inactivity_timeout "${_EP_INACTIVITY_TIMEOUT}") |
| set(no_progress "${_EP_DOWNLOAD_NO_PROGRESS}") |
| _ep_get_tls_version(${name} tls_version) |
| _ep_get_tls_verify(${name} tls_verify) |
| _ep_get_tls_cainfo(${name} tls_cainfo) |
| _ep_get_netrc(${name} netrc) |
| _ep_get_netrc_file(${name} netrc_file) |
| set(http_username "${_EP_HTTP_USERNAME}") |
| set(http_password "${_EP_HTTP_PASSWORD}") |
| set(http_headers "${_EP_HTTP_HEADER}") |
| set(download_script "${stamp_dir}/download-${name}.cmake") |
| _ep_write_downloadfile_script( |
| "${download_script}" |
| "${url}" |
| "${file}" |
| "${timeout}" |
| "${inactivity_timeout}" |
| "${no_progress}" |
| "${hash}" |
| "${tls_version}" |
| "${tls_verify}" |
| "${tls_cainfo}" |
| "${http_username}:${http_password}" |
| "${http_headers}" |
| "${netrc}" |
| "${netrc_file}" |
| ) |
| set(cmd |
| ${CMAKE_COMMAND} |
| -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE |
| -P "${download_script}" |
| COMMAND |
| ) |
| if(arg_SCRIPT_FILE) |
| set(step_script_contents "include(\"${download_script}\")\n") |
| endif() |
| |
| if (no_extract) |
| set(steps "download and verify") |
| else () |
| set(steps "download, verify and extract") |
| endif () |
| set(comment "Performing download step (${steps}) for '${name}'") |
| # already verified by 'download_script' |
| file(WRITE "${verify_script}" "") |
| |
| # Rather than adding everything to the RepositoryInfo.txt file, it is |
| # more robust to just depend on the download script. That way, we will |
| # re-download if any aspect of the download changes. |
| list(APPEND depends "${download_script}") |
| else() |
| set(file "${url}") |
| if (no_extract) |
| set(steps "verify") |
| else () |
| set(steps "verify and extract") |
| endif () |
| set(comment "Performing download step (${steps}) for '${name}'") |
| _ep_write_verifyfile_script( |
| "${verify_script}" |
| "${file}" |
| "${hash}" |
| ) |
| endif() |
| list(APPEND cmd ${CMAKE_COMMAND} |
| -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE |
| -P ${verify_script} |
| ) |
| if(arg_SCRIPT_FILE) |
| string(APPEND step_script_contents "include(\"${verify_script}\")\n") |
| list(APPEND depends ${verify_script}) |
| endif() |
| set(extract_timestamp "${_EP_DOWNLOAD_EXTRACT_TIMESTAMP}") |
| if(no_extract) |
| if(DEFINED _EP_DOWNLOAD_EXTRACT_TIMESTAMP) |
| message(FATAL_ERROR |
| "Cannot specify DOWNLOAD_EXTRACT_TIMESTAMP when using " |
| "DOWNLOAD_NO_EXTRACT TRUE" |
| ) |
| endif() |
| if(arg_SCRIPT_FILE) |
| # There's no target to record the location of the downloaded file. |
| # Instead, we copy it to the source directory within the script, |
| # which is what FetchContent always does in this situation. |
| cmake_path(SET safe_file NORMALIZE "${file}") |
| cmake_path(GET safe_file FILENAME filename) |
| string(APPEND step_script_contents |
| "file(COPY_FILE\n" |
| " \"${file}\"\n" |
| " \"${source_dir}/${filename}\"\n" |
| " ONLY_IF_DIFFERENT\n" |
| " INPUT_MAY_BE_RECENT\n" |
| ")" |
| ) |
| list(APPEND depends ${source_dir}/${filename}) |
| else() |
| set_property(TARGET ${name} PROPERTY _EP_DOWNLOADED_FILE ${file}) |
| endif() |
| else() |
| if(NOT DEFINED _EP_DOWNLOAD_EXTRACT_TIMESTAMP) |
| # Default depends on policy CMP0135 |
| if(_EP_CMP0135 STREQUAL "") |
| message(AUTHOR_WARNING |
| "The DOWNLOAD_EXTRACT_TIMESTAMP option was not given and policy " |
| "CMP0135 is not set. The policy's OLD behavior will be used. " |
| "When using a URL download, the timestamps of extracted files " |
| "should preferably be that of the time of extraction, otherwise " |
| "code that depends on the extracted contents might not be " |
| "rebuilt if the URL changes. The OLD behavior preserves the " |
| "timestamps from the archive instead, but this is usually not " |
| "what you want. Update your project to the NEW behavior or " |
| "specify the DOWNLOAD_EXTRACT_TIMESTAMP option with a value of " |
| "true to avoid this robustness issue." |
| ) |
| set(extract_timestamp TRUE) |
| elseif(_EP_CMP0135 STREQUAL "NEW") |
| set(extract_timestamp FALSE) |
| else() |
| set(extract_timestamp TRUE) |
| endif() |
| endif() |
| if(extract_timestamp) |
| set(options "") |
| else() |
| set(options "--touch") |
| endif() |
| set(extract_script "${stamp_dir}/extract-${name}.cmake") |
| _ep_write_extractfile_script( |
| "${extract_script}" |
| "${name}" |
| "${file}" |
| "${source_dir}" |
| "${options}" |
| ) |
| list(APPEND cmd |
| COMMAND ${CMAKE_COMMAND} |
| -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE |
| -P ${extract_script} |
| ) |
| if(arg_SCRIPT_FILE) |
| string(APPEND step_script_contents "include(\"${extract_script}\")\n") |
| list(APPEND depends ${extract_script}) |
| endif() |
| endif () |
| endif() |
| else() |
| set(method source_dir) |
| _ep_is_dir_empty("${source_dir}" empty) |
| if(${empty}) |
| message(FATAL_ERROR |
| "No download info given for '${name}' and its source directory:\n" |
| " ${source_dir}\n" |
| "is not an existing non-empty directory. Please specify one of:\n" |
| " * SOURCE_DIR with an existing non-empty directory\n" |
| " * DOWNLOAD_COMMAND\n" |
| " * URL\n" |
| " * GIT_REPOSITORY\n" |
| " * SVN_REPOSITORY\n" |
| " * HG_REPOSITORY\n" |
| " * CVS_REPOSITORY and CVS_MODULE" |
| ) |
| endif() |
| if(arg_SCRIPT_FILE) |
| set(step_script_contents "message(VERBOSE [[Using SOURCE_DIR as is]])") |
| endif() |
| endif() |
| |
| # We use configure_file() to write the repo_info_file so that the file's |
| # timestamp is not updated if we don't change the contents |
| |
| set(repo_info_file ${stamp_dir}/${name}-${method}info.txt) |
| list(APPEND depends ${repo_info_file}) |
| configure_file( |
| "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/RepositoryInfo.txt.in" |
| "${repo_info_file}" |
| @ONLY |
| ) |
| |
| if(arg_SCRIPT_FILE) |
| set(step_name download) |
| configure_file( |
| "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/stepscript.cmake.in" |
| "${arg_SCRIPT_FILE}" |
| @ONLY |
| ) |
| set(${arg_DEPENDS_VARIABLE} "${depends}" PARENT_SCOPE) |
| return() |
| endif() |
| |
| # Nothing below this point is applicable when we've been asked to put the |
| # download step in a script file (which is the FetchContent case). |
| |
| if(_EP_LOG_DOWNLOAD) |
| set(log LOG 1) |
| else() |
| set(log "") |
| endif() |
| |
| if(_EP_USES_TERMINAL_DOWNLOAD) |
| set(uses_terminal USES_TERMINAL 1) |
| else() |
| set(uses_terminal "") |
| endif() |
| |
| set(__cmdQuoted) |
| foreach(__item IN LISTS cmd) |
| string(APPEND __cmdQuoted " [==[${__item}]==]") |
| endforeach() |
| cmake_language(EVAL CODE " |
| ExternalProject_Add_Step(\${name} download |
| INDEPENDENT TRUE |
| COMMENT \${comment} |
| COMMAND ${__cmdQuoted} |
| WORKING_DIRECTORY \${work_dir} |
| DEPENDS \${depends} |
| DEPENDEES mkdir |
| ${log} |
| ${uses_terminal} |
| )" |
| ) |
| endfunction() |
| |
| function(_ep_get_update_disconnected var name) |
| # Note that the arguments are assumed to have already been parsed and have |
| # been translated into variables with the prefix _EP_... by a call to |
| # ep_parse_arguments() or ep_parse_arguments_to_vars(). |
| if(DEFINED _EP_UPDATE_DISCONNECTED) |
| set(update_disconnected "${_EP_UPDATE_DISCONNECTED}") |
| else() |
| get_property(update_disconnected |
| DIRECTORY |
| PROPERTY EP_UPDATE_DISCONNECTED |
| ) |
| endif() |
| set(${var} "${update_disconnected}" PARENT_SCOPE) |
| endfunction() |
| |
| function(_ep_add_update_command name) |
| set(noValueOptions ) |
| set(singleValueOptions |
| SCRIPT_FILE # These should only be used by FetchContent |
| DEPEND_VARIABLE # |
| ) |
| set(multiValueOptions ) |
| cmake_parse_arguments(PARSE_ARGV 1 arg |
| "${noValueOptions}" "${singleValueOptions}" "${multiValueOptions}" |
| ) |
| |
| # The various _EP_... variables mentioned here and throughout this function |
| # are expected to already have been set by the caller via a call to |
| # _ep_parse_arguments() or ep_parse_arguments_to_vars(). Other variables |
| # with different names are assigned to for historical reasons only to keep |
| # the code more readable and minimize change. |
| |
| set(source_dir "${_EP_SOURCE_DIR}") |
| set(stamp_dir "${_EP_STAMP_DIR}") |
| set(tmp_dir "${_EP_TMP_DIR}") |
| |
| set(cmd "${_EP_UPDATE_COMMAND}") |
| set(cvs_repository "${_EP_CVS_REPOSITORY}") |
| set(svn_repository "${_EP_SVN_REPOSITORY}") |
| set(git_repository "${_EP_GIT_REPOSITORY}") |
| set(hg_repository "${_EP_HG_REPOSITORY}") |
| |
| _ep_get_update_disconnected(update_disconnected ${name}) |
| |
| set(work_dir) |
| set(comment) |
| set(always) |
| set(file_deps) |
| |
| if(DEFINED _EP_UPDATE_COMMAND) |
| set(work_dir ${source_dir}) |
| if(NOT "x${cmd}" STREQUAL "x") |
| set(always 1) |
| _ep_add_script_commands( |
| step_script_contents |
| "${work_dir}" |
| "${cmd}" # Must be a single quoted argument |
| ) |
| endif() |
| |
| elseif(cvs_repository) |
| if(NOT CVS_EXECUTABLE) |
| message(FATAL_ERROR "error: could not find cvs for update of ${name}") |
| endif() |
| set(work_dir ${source_dir}) |
| set(comment "Performing update step (CVS update) for '${name}'") |
| set(cvs_tag "${_EP_CVS_TAG}") |
| set(cmd ${CVS_EXECUTABLE} -d ${cvs_repository} -q up -dP ${cvs_tag}) |
| set(always 1) |
| |
| if(arg_SCRIPT_FILE) |
| _ep_add_script_commands( |
| step_script_contents |
| "${work_dir}" |
| "${cmd}" # Must be a single quoted argument |
| ) |
| endif() |
| |
| elseif(svn_repository) |
| if(NOT Subversion_SVN_EXECUTABLE) |
| message(FATAL_ERROR "error: could not find svn for update of ${name}") |
| endif() |
| set(work_dir ${source_dir}) |
| set(comment "Performing update step (SVN update) for '${name}'") |
| set(svn_revision "${_EP_SVN_REVISION}") |
| set(svn_username "${_EP_SVN_USERNAME}") |
| set(svn_password "${_EP_SVN_PASSWORD}") |
| set(svn_trust_cert "${_EP_SVN_TRUST_CERT}") |
| set(uses_terminal "${_EP_USES_TERMINAL_UPDATE}") |
| # The --trust-server-cert option requires --non-interactive |
| if(uses_terminal AND NOT svn_trust_cert) |
| set(svn_interactive_args "") |
| else() |
| set(svn_interactive_args "--non-interactive") |
| endif() |
| set(svn_user_pw_args "") |
| if(DEFINED svn_username) |
| set(svn_user_pw_args ${svn_user_pw_args} "--username=${svn_username}") |
| endif() |
| if(DEFINED svn_password) |
| set(svn_user_pw_args ${svn_user_pw_args} "--password=${svn_password}") |
| endif() |
| if(svn_trust_cert) |
| set(svn_trust_cert_args --trust-server-cert) |
| endif() |
| set(cmd |
| ${Subversion_SVN_EXECUTABLE} |
| up |
| ${svn_revision} |
| ${svn_interactive_args} |
| ${svn_trust_cert_args} |
| ${svn_user_pw_args} |
| ) |
| set(always 1) |
| |
| if(arg_SCRIPT_FILE) |
| _ep_add_script_commands( |
| step_script_contents |
| "${work_dir}" |
| "${cmd}" # Must be a single quoted argument |
| ) |
| endif() |
| |
| elseif(git_repository) |
| # FetchContent gives us these directly, so don't try to recompute them |
| if(NOT GIT_EXECUTABLE OR NOT GIT_VERSION_STRING) |
| unset(CMAKE_MODULE_PATH) # Use CMake builtin find module |
| find_package(Git QUIET) |
| if(NOT GIT_EXECUTABLE) |
| message(FATAL_ERROR "error: could not find git for fetch of ${name}") |
| endif() |
| endif() |
| set(work_dir ${source_dir}) |
| set(comment "Performing update step for '${name}'") |
| set(comment_disconnected "Performing disconnected update step for '${name}'") |
| |
| set(git_tag "${_EP_GIT_TAG}") |
| if(NOT git_tag) |
| set(git_tag "master") |
| endif() |
| |
| set(git_remote_name "${_EP_GIT_REMOTE_NAME}") |
| if(NOT git_remote_name) |
| set(git_remote_name "origin") |
| endif() |
| |
| set(git_init_submodules TRUE) |
| if(DEFINED _EP_GIT_SUBMODULES) |
| set(git_submodules "${_EP_GIT_SUBMODULES}") |
| if(git_submodules STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW") |
| set(git_init_submodules FALSE) |
| endif() |
| endif() |
| |
| set(git_update_strategy "${_EP_GIT_REMOTE_UPDATE_STRATEGY}") |
| if(NOT git_update_strategy) |
| set(git_update_strategy "${CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY}") |
| endif() |
| if(NOT git_update_strategy) |
| set(git_update_strategy REBASE) |
| endif() |
| set(strategies CHECKOUT REBASE REBASE_CHECKOUT) |
| if(NOT git_update_strategy IN_LIST strategies) |
| message(FATAL_ERROR |
| "'${git_update_strategy}' is not one of the supported strategies: " |
| "${strategies}" |
| ) |
| endif() |
| |
| _ep_get_git_submodules_recurse(git_submodules_recurse) |
| |
| _ep_get_tls_version(${name} tls_version) |
| _ep_get_tls_verify(${name} tls_verify) |
| |
| set(update_script "${tmp_dir}/${name}-gitupdate.cmake") |
| list(APPEND file_deps ${update_script}) |
| _ep_write_gitupdate_script( |
| "${update_script}" |
| "${GIT_EXECUTABLE}" |
| "${git_tag}" |
| "${git_remote_name}" |
| "${git_init_submodules}" |
| "${git_submodules_recurse}" |
| "${git_submodules}" |
| "${git_repository}" |
| "${work_dir}" |
| "${git_update_strategy}" |
| "${tls_version}" |
| "${tls_verify}" |
| ) |
| set(cmd ${CMAKE_COMMAND} |
| -Dcan_fetch=YES |
| -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE |
| -P ${update_script} |
| ) |
| set(cmd_disconnected ${CMAKE_COMMAND} |
| -Dcan_fetch=NO |
| -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE |
| -P ${update_script} |
| ) |
| set(always 1) |
| |
| if(arg_SCRIPT_FILE) |
| if(update_disconnected) |
| set(can_fetch_default NO) |
| else() |
| set(can_fetch_default YES) |
| endif() |
| set(step_script_contents "include(\"${update_script}\")") |
| endif() |
| |
| elseif(hg_repository) |
| if(NOT HG_EXECUTABLE) |
| message(FATAL_ERROR "error: could not find hg for pull of ${name}") |
| endif() |
| set(work_dir ${source_dir}) |
| set(comment "Performing update step (hg pull) for '${name}'") |
| set(comment_disconnected "Performing disconnected update step for '${name}'") |
| |
| set(hg_tag "${_EP_HG_TAG}") |
| if(NOT hg_tag) |
| set(hg_tag "tip") |
| endif() |
| |
| if("${HG_VERSION_STRING}" STREQUAL "2.1") |
| set(notesAnchor |
| "#A2.1.1:_revert_pull_return_code_change.2C_compile_issue_on_OS_X" |
| ) |
| message(WARNING |
| "Mercurial 2.1 does not distinguish an empty pull from a failed pull: |
| http://mercurial.selenic.com/wiki/UpgradeNotes${notesAnchor} |
| http://thread.gmane.org/gmane.comp.version-control.mercurial.devel/47656 |
| Update to Mercurial >= 2.1.1. |
| ") |
| endif() |
| |
| set(cmd |
| ${HG_EXECUTABLE} pull |
| COMMAND ${HG_EXECUTABLE} update ${hg_tag} |
| ) |
| set(cmd_disconnected ${HG_EXECUTABLE} update ${hg_tag}) |
| set(always 1) |
| |
| if(arg_SCRIPT_FILE) |
| # These commands are simple, and we know whether updates need to be |
| # disconnected or not for this case, so write them directly instead of |
| # forming them from "cmd" and "cmd_disconnected". |
| if(NOT update_disconnected) |
| string(APPEND step_script_contents |
| "execute_process(\n" |
| " WORKING_DIRECTORY \"${work_dir}\"\n" |
| " COMMAND_ERROR_IS_FATAL LAST\n" |
| " COMMAND \"${HG_EXECUTABLE}\" pull\n" |
| ")" |
| ) |
| endif() |
| string(APPEND step_script_contents |
| "execute_process(\n" |
| " WORKING_DIRECTORY \"${work_dir}\"\n" |
| " COMMAND_ERROR_IS_FATAL LAST\n" |
| " COMMAND \"${HG_EXECUTABLE}\" update \"${hg_tag}\"\n" |
| ")" |
| ) |
| endif() |
| endif() |
| |
| # We use configure_file() to write the update_info_file so that the file's |
| # timestamp is not updated if we don't change the contents |
| if(NOT DEFINED cmd_disconnected) |
| set(cmd_disconnected "${cmd}") |
| endif() |
| set(update_info_file ${stamp_dir}/${name}-update-info.txt) |
| list(APPEND file_deps ${update_info_file}) |
| configure_file( |
| "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/UpdateInfo.txt.in" |
| "${update_info_file}" |
| @ONLY |
| ) |
| |
| if(arg_SCRIPT_FILE) |
| set(step_name update) |
| configure_file( |
| "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/stepscript.cmake.in" |
| "${arg_SCRIPT_FILE}" |
| @ONLY |
| ) |
| set(${arg_DEPENDS_VARIABLE} "${file_deps}" PARENT_SCOPE) |
| return() |
| endif() |
| |
| # Nothing below this point is applicable when we've been asked to put the |
| # update step in a script file (which is the FetchContent case). |
| |
| if(_EP_LOG_UPDATE) |
| set(log LOG 1) |
| else() |
| set(log "") |
| endif() |
| |
| if(_EP_USES_TERMINAL_UPDATE) |
| set(uses_terminal USES_TERMINAL 1) |
| else() |
| set(uses_terminal "") |
| endif() |
| |
| set(__cmdQuoted) |
| foreach(__item IN LISTS cmd) |
| string(APPEND __cmdQuoted " [==[${__item}]==]") |
| endforeach() |
| cmake_language(EVAL CODE " |
| ExternalProject_Add_Step(${name} update |
| INDEPENDENT TRUE |
| COMMENT \${comment} |
| COMMAND ${__cmdQuoted} |
| ALWAYS \${always} |
| EXCLUDE_FROM_MAIN \${update_disconnected} |
| WORKING_DIRECTORY \${work_dir} |
| DEPENDEES download |
| DEPENDS \${file_deps} |
| ${log} |
| ${uses_terminal} |
| )" |
| ) |
| if(update_disconnected) |
| if(NOT DEFINED comment_disconnected) |
| set(comment_disconnected "${comment}") |
| endif() |
| set(__cmdQuoted) |
| foreach(__item IN LISTS cmd_disconnected) |
| string(APPEND __cmdQuoted " [==[${__item}]==]") |
| endforeach() |
| |
| cmake_language(EVAL CODE " |
| ExternalProject_Add_Step(${name} update_disconnected |
| INDEPENDENT TRUE |
| COMMENT \${comment_disconnected} |
| COMMAND ${__cmdQuoted} |
| WORKING_DIRECTORY \${work_dir} |
| DEPENDEES download |
| DEPENDS \${file_deps} |
| ${log} |
| ${uses_terminal} |
| )" |
| ) |
| endif() |
| |
| endfunction() |
| |
| |
| function(_ep_add_patch_command name) |
| set(noValueOptions ) |
| set(singleValueOptions |
| SCRIPT_FILE # These should only be used by FetchContent |
| ) |
| set(multiValueOptions ) |
| cmake_parse_arguments(PARSE_ARGV 1 arg |
| "${noValueOptions}" "${singleValueOptions}" "${multiValueOptions}" |
| ) |
| |
| # The various _EP_... variables mentioned here and throughout this function |
| # are expected to already have been set by the caller via a call to |
| # _ep_parse_arguments() or ep_parse_arguments_to_vars(). Other variables |
| # with different names are assigned to for historical reasons only to keep |
| # the code more readable and minimize change. |
| |
| set(source_dir "${_EP_SOURCE_DIR}") |
| set(stamp_dir "${_EP_STAMP_DIR}") |
| |
| set(cmd "${_EP_PATCH_COMMAND}") |
| set(step_script_contents "") |
| |
| set(work_dir) |
| if(DEFINED _EP_PATCH_COMMAND) |
| set(work_dir ${source_dir}) |
| if(arg_SCRIPT_FILE) |
| _ep_add_script_commands( |
| step_script_contents |
| "${work_dir}" |
| "${cmd}" # Must be a single quoted argument |
| ) |
| endif() |
| endif() |
| |
| # We use configure_file() to write the patch_info_file so that the file's |
| # timestamp is not updated if we don't change the contents |
| set(patch_info_file ${stamp_dir}/${name}-patch-info.txt) |
| configure_file( |
| "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/PatchInfo.txt.in" |
| "${patch_info_file}" |
| @ONLY |
| ) |
| |
| if(arg_SCRIPT_FILE) |
| set(step_name patch) |
| configure_file( |
| "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/stepscript.cmake.in" |
| "${arg_SCRIPT_FILE}" |
| @ONLY |
| ) |
| return() |
| endif() |
| |
| # Nothing below this point is applicable when we've been asked to put the |
| # patch step in a script file (which is the FetchContent case). |
| |
| if(_EP_LOG_PATCH) |
| set(log LOG 1) |
| else() |
| set(log "") |
| endif() |
| |
| if(_EP_USES_TERMINAL_PATCH) |
| set(uses_terminal USES_TERMINAL 1) |
| else() |
| set(uses_terminal "") |
| endif() |
| |
| _ep_get_update_disconnected(update_disconnected ${name}) |
| |
| set(__cmdQuoted) |
| foreach(__item IN LISTS cmd) |
| string(APPEND __cmdQuoted " [==[${__item}]==]") |
| endforeach() |
| cmake_language(EVAL CODE " |
| ExternalProject_Add_Step(${name} patch |
| INDEPENDENT TRUE |
| COMMAND ${__cmdQuoted} |
| WORKING_DIRECTORY \${work_dir} |
| EXCLUDE_FROM_MAIN \${update_disconnected} |
| DEPENDEES update |
| DEPENDS \${patch_info_file} |
| ${log} |
| ${uses_terminal} |
| )" |
| ) |
| |
| if(update_disconnected) |
| cmake_language(EVAL CODE " |
| ExternalProject_Add_Step(${name} patch_disconnected |
| INDEPENDENT TRUE |
| COMMAND ${__cmdQuoted} |
| WORKING_DIRECTORY \${work_dir} |
| DEPENDEES update_disconnected |
| DEPENDS \${patch_info_file} |
| ${log} |
| ${uses_terminal} |
| )" |
| ) |
| endif() |
| |
| endfunction() |
| |
| |
| macro(_ep_get_add_keywords out_var) |
| set(${out_var} |
| # |
| # Directory options |
| # |
| PREFIX |
| TMP_DIR |
| STAMP_DIR |
| LOG_DIR |
| DOWNLOAD_DIR |
| SOURCE_DIR |
| BINARY_DIR |
| INSTALL_DIR |
| # |
| # Download step options |
| # |
| DOWNLOAD_COMMAND |
| # |
| URL |
| URL_HASH |
| URL_MD5 |
| DOWNLOAD_NAME |
| DOWNLOAD_EXTRACT_TIMESTAMP |
| DOWNLOAD_NO_EXTRACT |
| DOWNLOAD_NO_PROGRESS |
| TIMEOUT |
| INACTIVITY_TIMEOUT |
| HTTP_USERNAME |
| HTTP_PASSWORD |
| HTTP_HEADER |
| TLS_VERSION # Also used for git clone operations |
| TLS_VERIFY # Also used for git clone operations |
| TLS_CAINFO |
| NETRC |
| NETRC_FILE |
| # |
| GIT_REPOSITORY |
| GIT_TAG |
| GIT_REMOTE_NAME |
| GIT_SUBMODULES |
| GIT_SUBMODULES_RECURSE |
| GIT_SHALLOW |
| GIT_PROGRESS |
| GIT_CONFIG |
| GIT_REMOTE_UPDATE_STRATEGY |
| # |
| SVN_REPOSITORY |
| SVN_REVISION |
| SVN_USERNAME |
| SVN_PASSWORD |
| SVN_TRUST_CERT |
| # |
| HG_REPOSITORY |
| HG_TAG |
| # |
| CVS_REPOSITORY |
| CVS_MODULE |
| CVS_TAG |
| # |
| # Update step options |
| # |
| UPDATE_COMMAND |
| UPDATE_DISCONNECTED |
| # |
| # Patch step options |
| # |
| PATCH_COMMAND |
| # |
| # Configure step options |
| # |
| CONFIGURE_COMMAND |
| CMAKE_COMMAND |
| CMAKE_GENERATOR |
| CMAKE_GENERATOR_PLATFORM |
| CMAKE_GENERATOR_TOOLSET |
| CMAKE_GENERATOR_INSTANCE |
| CMAKE_ARGS |
| CMAKE_CACHE_ARGS |
| CMAKE_CACHE_DEFAULT_ARGS |
| SOURCE_SUBDIR |
| CONFIGURE_HANDLED_BY_BUILD |
| # |
| # Build step options |
| # |
| BUILD_COMMAND |
| BUILD_IN_SOURCE |
| BUILD_ALWAYS |
| BUILD_BYPRODUCTS |
| BUILD_JOB_SERVER_AWARE |
| # |
| # Install step options |
| # |
| INSTALL_COMMAND |
| INSTALL_BYPRODUCTS |
| # |
| # Test step options |
| # |
| TEST_COMMAND |
| TEST_BEFORE_INSTALL |
| TEST_AFTER_INSTALL |
| TEST_EXCLUDE_FROM_MAIN |
| # |
| # Logging options |
| # |
| LOG_DOWNLOAD |
| LOG_UPDATE |
| LOG_PATCH |
| LOG_CONFIGURE |
| LOG_BUILD |
| LOG_INSTALL |
| LOG_TEST |
| LOG_MERGED_STDOUTERR |
| LOG_OUTPUT_ON_FAILURE |
| # |
| # Terminal access options |
| # |
| USES_TERMINAL_DOWNLOAD |
| USES_TERMINAL_UPDATE |
| USES_TERMINAL_PATCH |
| USES_TERMINAL_CONFIGURE |
| USES_TERMINAL_BUILD |
| USES_TERMINAL_INSTALL |
| USES_TERMINAL_TEST |
| # |
| # Target options |
| # |
| DEPENDS |
| EXCLUDE_FROM_ALL |
| STEP_TARGETS |
| INDEPENDENT_STEP_TARGETS |
| # |
| # Miscellaneous options |
| # |
| LIST_SEPARATOR |
| # |
| # Internal options (undocumented) |
| # |
| EXTERNALPROJECT_INTERNAL_ARGUMENT_SEPARATOR |
| ) |
| endmacro() |