summaryrefslogtreecommitdiff
path: root/Modules/FetchContent.cmake
diff options
context:
space:
mode:
authorCraig Scott <craig.scott@crascit.com>2021-01-29 23:22:45 +1100
committerCraig Scott <craig.scott@crascit.com>2021-02-05 07:33:38 +1100
commit17e5516e608ba5c9c1f2dfad3d64f8f90874f108 (patch)
treeae0f88a262c3734cda45ee1040aee303e131d13d /Modules/FetchContent.cmake
parent4f3d1abbb4dca3d1e6b019471fa5d8be296492e3 (diff)
downloadcmake-17e5516e608ba5c9c1f2dfad3d64f8f90874f108.tar.gz
FetchContent: Invoke steps directly and avoid a separate sub-build
The cost of setting up and executing a separate sub-build to do the download, update and patch steps required for FetchContent population can be significant with some platforms and CMake generators. Avoid the sub-build altogether by invoking the step scripts directly. Previously, if no generator was set (e.g. population was being done in script mode), a generator needed to be available on the default PATH. Since we no longer use a sub-build, this restriction is also now gone. Fixes: #21703
Diffstat (limited to 'Modules/FetchContent.cmake')
-rw-r--r--Modules/FetchContent.cmake131
1 files changed, 17 insertions, 114 deletions
diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake
index 8adef47778..6a4cf38884 100644
--- a/Modules/FetchContent.cmake
+++ b/Modules/FetchContent.cmake
@@ -849,8 +849,6 @@ function(__FetchContent_directPopulate contentName)
SUBBUILD_DIR
SOURCE_DIR
BINARY_DIR
- # We need special processing if DOWNLOAD_NO_EXTRACT is true
- DOWNLOAD_NO_EXTRACT
# Prevent the following from being passed through
CONFIGURE_COMMAND
BUILD_COMMAND
@@ -894,123 +892,28 @@ function(__FetchContent_directPopulate contentName)
set(${contentName}_SOURCE_DIR "${ARG_SOURCE_DIR}" PARENT_SCOPE)
set(${contentName}_BINARY_DIR "${ARG_BINARY_DIR}" PARENT_SCOPE)
- # The unparsed arguments may contain spaces, so build up ARG_EXTRA
- # in such a way that it correctly substitutes into the generated
- # CMakeLists.txt file with each argument quoted.
- unset(ARG_EXTRA)
- foreach(arg IN LISTS ARG_UNPARSED_ARGUMENTS)
- set(ARG_EXTRA "${ARG_EXTRA} \"${arg}\"")
- endforeach()
-
- if(ARG_DOWNLOAD_NO_EXTRACT)
- set(ARG_EXTRA "${ARG_EXTRA} DOWNLOAD_NO_EXTRACT YES")
- set(__FETCHCONTENT_COPY_FILE
-"
-ExternalProject_Get_Property(${contentName}-populate DOWNLOADED_FILE)
-get_filename_component(dlFileName \"\${DOWNLOADED_FILE}\" NAME)
-
-ExternalProject_Add_Step(${contentName}-populate copyfile
- COMMAND \"${CMAKE_COMMAND}\" -E copy_if_different
- \"<DOWNLOADED_FILE>\" \"${ARG_SOURCE_DIR}\"
- DEPENDEES patch
- DEPENDERS configure
- BYPRODUCTS \"${ARG_SOURCE_DIR}/\${dlFileName}\"
- COMMENT \"Copying file to SOURCE_DIR\"
-)
-")
+ if(ARG_QUIET)
+ set(quiet TRUE)
else()
- unset(__FETCHCONTENT_COPY_FILE)
- endif()
-
- # Hide output if requested, but save it to a variable in case there's an
- # error so we can show the output upon failure. When not quiet, don't
- # capture the output to a variable because the user may want to see the
- # output as it happens (e.g. progress during long downloads). Combine both
- # stdout and stderr in the one capture variable so the output stays in order.
- if (ARG_QUIET)
- set(outputOptions
- OUTPUT_VARIABLE capturedOutput
- ERROR_VARIABLE capturedOutput
- )
- else()
- set(capturedOutput)
- set(outputOptions)
+ set(quiet FALSE)
message(STATUS "Populating ${contentName}")
endif()
- if(CMAKE_GENERATOR)
- set(subCMakeOpts "-G${CMAKE_GENERATOR}")
- if(CMAKE_GENERATOR_PLATFORM)
- list(APPEND subCMakeOpts "-A${CMAKE_GENERATOR_PLATFORM}")
- endif()
- if(CMAKE_GENERATOR_TOOLSET)
- list(APPEND subCMakeOpts "-T${CMAKE_GENERATOR_TOOLSET}")
- endif()
-
- if(CMAKE_MAKE_PROGRAM)
- list(APPEND subCMakeOpts "-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}")
- endif()
-
- else()
- # Likely we've been invoked via CMake's script mode where no
- # generator is set (and hence CMAKE_MAKE_PROGRAM could not be
- # trusted even if provided). We will have to rely on being
- # able to find the default generator and build tool.
- unset(subCMakeOpts)
- endif()
-
- if(DEFINED CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY)
- list(APPEND subCMakeOpts
- "-DCMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY=${CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY}")
- endif()
-
- # Avoid using if(... IN_LIST ...) so we don't have to alter policy settings
- set(__FETCHCONTENT_CACHED_INFO "")
- list(FIND ARG_UNPARSED_ARGUMENTS GIT_REPOSITORY indexResult)
- if(indexResult GREATER_EQUAL 0)
- find_package(Git QUIET)
- set(__FETCHCONTENT_CACHED_INFO
-"# Pass through things we've already detected in the main project to avoid
-# paying the cost of redetecting them again in ExternalProject_Add()
-set(GIT_EXECUTABLE [==[${GIT_EXECUTABLE}]==])
-set(GIT_VERSION_STRING [==[${GIT_VERSION_STRING}]==])
-set_property(GLOBAL PROPERTY _CMAKE_FindGit_GIT_EXECUTABLE_VERSION
- [==[${GIT_EXECUTABLE};${GIT_VERSION_STRING}]==]
-)
-")
- endif()
-
- # Create and build a separate CMake project to carry out the population.
- # If we've already previously done these steps, they will not cause
- # anything to be updated, so extra rebuilds of the project won't occur.
- # Make sure to pass through CMAKE_MAKE_PROGRAM in case the main project
- # has this set to something not findable on the PATH.
- configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/FetchContent/CMakeLists.cmake.in"
- "${ARG_SUBBUILD_DIR}/CMakeLists.txt")
- execute_process(
- COMMAND ${CMAKE_COMMAND} ${subCMakeOpts} .
- RESULT_VARIABLE result
- ${outputOptions}
- WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}"
- )
- if(result)
- if(capturedOutput)
- message("${capturedOutput}")
- endif()
- message(FATAL_ERROR "CMake step for ${contentName} failed: ${result}")
- endif()
- execute_process(
- COMMAND ${CMAKE_COMMAND} --build .
- RESULT_VARIABLE result
- ${outputOptions}
- WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}"
+ include(ExternalProject)
+ set(argsQuoted)
+ foreach(__item IN LISTS ARG_UNPARSED_ARGUMENTS)
+ string(APPEND argsQuoted " [==[${__item}]==]")
+ endforeach()
+ cmake_language(EVAL CODE "
+ _ep_do_preconfigure_steps_now(${contentName}
+ ${argsQuoted}
+ QUIET ${quiet}
+ SOURCE_DIR [==[${ARG_SOURCE_DIR}]==]
+ BINARY_DIR [==[${ARG_BINARY_DIR}]==]
+ USES_TERMINAL_DOWNLOAD YES
+ USES_TERMINAL_UPDATE YES
+ )"
)
- if(result)
- if(capturedOutput)
- message("${capturedOutput}")
- endif()
- message(FATAL_ERROR "Build step for ${contentName} failed: ${result}")
- endif()
endfunction()