mirror of
https://github.com/Kitware/CMake.git
synced 2025-12-31 19:00:54 -06:00
@@ -0,0 +1,8 @@
|
||||
external-project-configure-handled-by-build
|
||||
-------------------------------------------
|
||||
|
||||
* The :module:`ExternalProject` function ``ExternalProject_Add`` learned a new
|
||||
``CONFIGURE_HANDLED_BY_BUILD`` option to have subsequent runs of the configure
|
||||
step be triggered by the build step when an external project dependency
|
||||
rebuilds instead of always rerunning the configure step when an external
|
||||
project dependency rebuilds.
|
||||
@@ -543,6 +543,18 @@ External Project Definition
|
||||
When ``BUILD_IN_SOURCE`` option is enabled, the ``BUILD_COMMAND``
|
||||
is used to point to an alternative directory within the source tree.
|
||||
|
||||
``CONFIGURE_HANDLED_BY_BUILD <bool>``
|
||||
.. versionadded:: 3.20
|
||||
|
||||
Enabling this option relaxes the dependencies of the configure step on
|
||||
other external projects to order-only. This means the configure step will
|
||||
be executed after its external project dependencies are built but it will
|
||||
not be marked dirty when one of its external project dependencies is
|
||||
rebuilt. This option can be enabled when the build step is smart enough
|
||||
to figure out if the configure step needs to be rerun. CMake and Meson are
|
||||
examples of build systems whose build step is smart enough to know if the
|
||||
configure step needs to be rerun.
|
||||
|
||||
**Build Step Options:**
|
||||
If the configure step assumed the external project uses CMake as its build
|
||||
system, the build step will also. Otherwise, the build step will assume a
|
||||
@@ -3081,6 +3093,23 @@ function(_ep_add_patch_command name)
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(_ep_get_file_deps var name)
|
||||
set(file_deps)
|
||||
|
||||
get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS)
|
||||
foreach(dep IN LISTS deps)
|
||||
get_property(dep_type TARGET ${dep} PROPERTY TYPE)
|
||||
if(dep_type STREQUAL "UTILITY")
|
||||
get_property(is_ep TARGET ${dep} PROPERTY _EP_IS_EXTERNAL_PROJECT)
|
||||
if(is_ep)
|
||||
_ep_get_step_stampfile(${dep} "done" done_stamp_file)
|
||||
list(APPEND file_deps ${done_stamp_file})
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set("${var}" "${file_deps}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(_ep_extract_configure_command var name)
|
||||
get_property(cmd_set TARGET ${name} PROPERTY _EP_CONFIGURE_COMMAND SET)
|
||||
@@ -3189,19 +3218,13 @@ endfunction()
|
||||
function(_ep_add_configure_command name)
|
||||
ExternalProject_Get_Property(${name} binary_dir tmp_dir)
|
||||
|
||||
# Depend on other external projects (file-level).
|
||||
set(file_deps)
|
||||
get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS)
|
||||
foreach(dep IN LISTS deps)
|
||||
get_property(dep_type TARGET ${dep} PROPERTY TYPE)
|
||||
if(dep_type STREQUAL "UTILITY")
|
||||
get_property(is_ep TARGET ${dep} PROPERTY _EP_IS_EXTERNAL_PROJECT)
|
||||
if(is_ep)
|
||||
_ep_get_step_stampfile(${dep} "done" done_stamp_file)
|
||||
list(APPEND file_deps ${done_stamp_file})
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
get_property(configure_handled_by_build TARGET ${name}
|
||||
PROPERTY _EP_CONFIGURE_HANDLED_BY_BUILD)
|
||||
if(NOT configure_handled_by_build)
|
||||
# Depend on other external projects (file-level)
|
||||
_ep_get_file_deps(file_deps ${name})
|
||||
endif()
|
||||
|
||||
_ep_extract_configure_command(cmd ${name})
|
||||
|
||||
@@ -3252,6 +3275,14 @@ endfunction()
|
||||
function(_ep_add_build_command name)
|
||||
ExternalProject_Get_Property(${name} binary_dir)
|
||||
|
||||
set(file_deps)
|
||||
get_property(configure_handled_by_build TARGET ${name}
|
||||
PROPERTY _EP_CONFIGURE_HANDLED_BY_BUILD)
|
||||
if(configure_handled_by_build)
|
||||
# Depend on other external projects (file-level)
|
||||
_ep_get_file_deps(file_deps ${name})
|
||||
endif()
|
||||
|
||||
get_property(cmd_set TARGET ${name} PROPERTY _EP_BUILD_COMMAND SET)
|
||||
if(cmd_set)
|
||||
get_property(cmd TARGET ${name} PROPERTY _EP_BUILD_COMMAND)
|
||||
@@ -3294,6 +3325,7 @@ function(_ep_add_build_command name)
|
||||
BYPRODUCTS \${build_byproducts}
|
||||
WORKING_DIRECTORY \${binary_dir}
|
||||
DEPENDEES configure
|
||||
DEPENDS \${file_deps}
|
||||
ALWAYS \${always}
|
||||
${log}
|
||||
${uses_terminal}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
file(TIMESTAMP "${STAMP_DIR}/proj1-configure" PROJ1_CONFIGURE_TIMESTAMP_AFTER "%s")
|
||||
# When BUILD_ALWAYS is set, the build stamp is never created.
|
||||
file(TIMESTAMP "${STAMP_DIR}/proj2-configure" PROJ2_CONFIGURE_TIMESTAMP_AFTER "%s")
|
||||
file(TIMESTAMP "${STAMP_DIR}/proj2-build" PROJ2_BUILD_TIMESTAMP_AFTER "%s")
|
||||
|
||||
if(NOT PROJ1_CONFIGURE_TIMESTAMP_BEFORE EQUAL PROJ1_CONFIGURE_TIMESTAMP_AFTER)
|
||||
set(RunCMake_TEST_FAILED "Unexpected rebuild of proj1 configure step (${PROJ1_CONFIGURE_TIMESTAMP_BEFORE} != ${PROJ1_CONFIGURE_TIMESTAMP_AFTER})")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(NOT PROJ2_CONFIGURE_TIMESTAMP_BEFORE EQUAL PROJ2_CONFIGURE_TIMESTAMP_AFTER)
|
||||
set(RunCMake_TEST_FAILED "Unexpected rebuild of proj2 configure step (${PROJ2_CONFIGURE_TIMESTAMP_BEFORE} != ${PROJ2_CONFIGURE_TIMESTAMP_AFTER})")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(PROJ2_BUILD_TIMESTAMP_BEFORE EQUAL PROJ2_BUILD_TIMESTAMP_AFTER)
|
||||
set(RunCMake_TEST_FAILED "proj2 build step did not rebuild (${PROJ2_BUILD_TIMESTAMP_BEFORE} != ${PROJ2_BUILD_TIMESTAMP_AFTER})")
|
||||
return()
|
||||
endif()
|
||||
@@ -0,0 +1,28 @@
|
||||
include(ExternalProject)
|
||||
|
||||
# Given this setup, on the first build, both configure steps and both build
|
||||
# steps will run. On a noop rebuild, only the build steps will run. Without
|
||||
# CONFIGURE_HANDLED_BY_BUILD, the configure step of proj2 would also run on a
|
||||
# noop rebuild.
|
||||
|
||||
ExternalProject_Add(proj1
|
||||
DOWNLOAD_COMMAND ""
|
||||
SOURCE_DIR ""
|
||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E echo "Doing something"
|
||||
# file(TIMESTAMP) gives back the timestamp in seconds so we sleep a second to
|
||||
# make sure we get a different timestamp on the stamp file
|
||||
BUILD_COMMAND ${CMAKE_COMMAND} -E sleep 1
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_ALWAYS ON
|
||||
STAMP_DIR "stamp"
|
||||
)
|
||||
ExternalProject_Add(proj2
|
||||
DOWNLOAD_COMMAND ""
|
||||
SOURCE_DIR ""
|
||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E echo "Doing something"
|
||||
BUILD_COMMAND ${CMAKE_COMMAND} -E sleep 1
|
||||
INSTALL_COMMAND ""
|
||||
CONFIGURE_HANDLED_BY_BUILD ON
|
||||
DEPENDS proj1
|
||||
STAMP_DIR "stamp"
|
||||
)
|
||||
@@ -151,3 +151,33 @@ endif()
|
||||
if(doSubstitutionTest)
|
||||
__ep_test_with_build(Substitutions)
|
||||
endif()
|
||||
|
||||
function(__ep_test_CONFIGURE_HANDLED_BY_BUILD)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CONFIGURE_HANDLED_BY_BUILD-build)
|
||||
run_cmake(CONFIGURE_HANDLED_BY_BUILD)
|
||||
|
||||
if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
|
||||
set(BUILD_CONFIG --config Debug)
|
||||
set(STAMP_DIR "${RunCMake_TEST_BINARY_DIR}/stamp/Debug")
|
||||
else()
|
||||
set(BUILD_CONFIG "")
|
||||
set(STAMP_DIR "${RunCMake_TEST_BINARY_DIR}/stamp")
|
||||
endif()
|
||||
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
run_cmake_command(CONFIGURE_HANDLED_BY_BUILD-build ${CMAKE_COMMAND} --build . ${BUILD_CONFIG})
|
||||
|
||||
# Calculate timestamps before rebuilding so we can compare before and after in
|
||||
# CONFIGURE_HANDLED_BY_BUILD-rebuild-check.cmake
|
||||
|
||||
file(TIMESTAMP "${STAMP_DIR}/proj1-configure" PROJ1_CONFIGURE_TIMESTAMP_BEFORE "%s")
|
||||
# When BUILD_ALWAYS is set, the build stamp is never created.
|
||||
file(TIMESTAMP "${STAMP_DIR}/proj2-configure" PROJ2_CONFIGURE_TIMESTAMP_BEFORE "%s")
|
||||
file(TIMESTAMP "${STAMP_DIR}/proj2-build" PROJ2_BUILD_TIMESTAMP_BEFORE "%s")
|
||||
|
||||
run_cmake_command(CONFIGURE_HANDLED_BY_BUILD-rebuild ${CMAKE_COMMAND} --build . ${BUILD_CONFIG})
|
||||
endfunction()
|
||||
|
||||
if(NOT RunCMake_GENERATOR MATCHES "Visual Studio 9 ")
|
||||
__ep_test_CONFIGURE_HANDLED_BY_BUILD()
|
||||
endif()
|
||||
|
||||
Reference in New Issue
Block a user