diff options
Diffstat (limited to 'Modules/FetchContent.cmake')
-rw-r--r-- | Modules/FetchContent.cmake | 131 |
1 files changed, 114 insertions, 17 deletions
diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index 6a4cf38..8adef47 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -849,6 +849,8 @@ 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 @@ -892,28 +894,123 @@ function(__FetchContent_directPopulate contentName) set(${contentName}_SOURCE_DIR "${ARG_SOURCE_DIR}" PARENT_SCOPE) set(${contentName}_BINARY_DIR "${ARG_BINARY_DIR}" PARENT_SCOPE) - if(ARG_QUIET) - set(quiet TRUE) + # 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\" +) +") else() - set(quiet FALSE) + 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) message(STATUS "Populating ${contentName}") endif() - 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(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}" ) + if(result) + if(capturedOutput) + message("${capturedOutput}") + endif() + message(FATAL_ERROR "Build step for ${contentName} failed: ${result}") + endif() endfunction() |