From c0b749cf62a2e985c2b1f94ff919107dbd697b2c Mon Sep 17 00:00:00 2001 From: "Daniele E. Domenichelli" Date: Wed, 5 Nov 2014 00:31:32 +0100 Subject: ExternalProject: Always add a command to a step Some generators (i.e. Xcode) will not generate a file level target if no command is set, and therefore the dependencies on this target will be broken. This patch sets an empty echo command that does nothing to avoid this issue. --- Modules/ExternalProject.cmake | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 8513437..bf6cd21 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -1423,6 +1423,15 @@ function(ExternalProject_Add_Step name step) _ep_write_log_script(${name} ${step} command) endif() + if("${command}" STREQUAL "") + # Some generators (i.e. Xcode) will not generate a file level target + # if no command is set, and therefore the dependencies on this + # target will be broken. + # The empty command is replaced by an echo command here in order to + # avoid this issue. + set(command ${CMAKE_COMMAND} -E echo_append) + endif() + add_custom_command( OUTPUT ${stamp_file} COMMENT ${comment} -- cgit v0.12 From 3f606fa7d06a209cc2cd3a97afb84951d1c4c033 Mon Sep 17 00:00:00 2001 From: "Daniele E. Domenichelli" Date: Wed, 5 Nov 2014 00:31:40 +0100 Subject: ExternalProject: Add UPDATE_DISCONNECTED option If UPDATE_DISCONNECTED is set, the update step is not executed automatically when building the main target. The update step can still be added as a step target and called manually. This is useful if you want to allow to build the project when you are disconnected from the network (you might still need the network for the download step). This is disabled by default. The directory property EP_UPDATE_DISCONNECTED can be used to change the default value for all the external projects in the current directory and its subdirectories. --- Modules/ExternalProject.cmake | 55 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index bf6cd21..a9c7519 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -80,6 +80,8 @@ Create custom targets to build projects in external trees ``UPDATE_COMMAND ...`` Source work-tree update command + ``UPDATE_DISCONNECTED 1`` + Never update automatically from the remote repository ``PATCH_COMMAND ...`` Command to patch downloaded source @@ -203,6 +205,16 @@ Create custom targets to build projects in external trees options. The ``URL`` option may refer locally to a directory or source tarball, or refer to a remote tarball (e.g. ``http://.../src.tgz``). + If ``UPDATE_DISCONNECTED`` is set, the update step is not executed + automatically when building the main target. The update step can still + be added as a step target and called manually. This is useful if you + want to allow to build the project when you are disconnected from the + network (you might still need the network for the download step). + This is disabled by default. + The directory property ``EP_UPDATE_DISCONNECTED`` can be used to change + the default value for all the external projects in the current + directory and its subdirectories. + .. command:: ExternalProject_Add_Step The ``ExternalProject_Add_Step`` function adds a custom step to an @@ -439,6 +451,13 @@ define_property(DIRECTORY PROPERTY "EP_INDEPENDENT_STEP_TARGETS" INHERITED "ExternalProject module." ) +define_property(DIRECTORY PROPERTY "EP_UPDATE_DISCONNECTED" INHERITED + BRIEF_DOCS "Never update automatically from the remote repo." + FULL_DOCS + "See documentation of the ExternalProject_Add() function in the " + "ExternalProject module." + ) + function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git_repository git_tag git_submodules src_name work_dir gitclone_infofile gitclone_stampfile) file(WRITE ${script_filename} "if(\"${git_tag}\" STREQUAL \"\") @@ -1825,6 +1844,12 @@ function(_ep_add_update_command name) get_property(svn_repository TARGET ${name} PROPERTY _EP_SVN_REPOSITORY) get_property(git_repository TARGET ${name} PROPERTY _EP_GIT_REPOSITORY) get_property(hg_repository TARGET ${name} PROPERTY _EP_HG_REPOSITORY ) + get_property(update_disconnected_set TARGET ${name} PROPERTY _EP_UPDATE_DISCONNECTED SET) + if(update_disconnected_set) + get_property(update_disconnected TARGET ${name} PROPERTY _EP_UPDATE_DISCONNECTED) + else() + get_property(update_disconnected DIRECTORY PROPERTY EP_UPDATE_DISCONNECTED) + endif() set(work_dir) set(comment) @@ -1914,10 +1939,26 @@ Update to Mercurial >= 2.1.1. COMMENT ${comment} COMMAND ${cmd} ALWAYS ${always} + EXCLUDE_FROM_MAIN ${update_disconnected} WORKING_DIRECTORY ${work_dir} DEPENDEES download ${log} ) + + if(always AND update_disconnected) + _ep_get_step_stampfile(${name} skip-update skip-update_stamp_file) + string(REPLACE "Performing" "Skipping" comment "${comment}") + ExternalProject_Add_Step(${name} skip-update + COMMENT ${comment} + ALWAYS 1 + EXCLUDE_FROM_MAIN 1 + WORKING_DIRECTORY ${work_dir} + DEPENDEES download + ${log} + ) + set_property(SOURCE ${skip-update_stamp_file} PROPERTY SYMBOLIC 1) + endif() + endfunction() @@ -2039,10 +2080,22 @@ function(_ep_add_configure_command name) set(log "") endif() + get_property(update_disconnected_set TARGET ${name} PROPERTY _EP_UPDATE_DISCONNECTED SET) + if(update_disconnected_set) + get_property(update_disconnected TARGET ${name} PROPERTY _EP_UPDATE_DISCONNECTED) + else() + get_property(update_disconnected DIRECTORY PROPERTY EP_UPDATE_DISCONNECTED) + endif() + if(update_disconnected) + set(update_dep skip-update) + else() + set(update_dep update) + endif() + ExternalProject_Add_Step(${name} configure COMMAND ${cmd} WORKING_DIRECTORY ${binary_dir} - DEPENDEES update patch + DEPENDEES ${update_dep} patch DEPENDS ${file_deps} ${log} ) -- cgit v0.12 From aba5cec6b262c392bfd9f94176a80113d1315917 Mon Sep 17 00:00:00 2001 From: "Daniele E. Domenichelli" Date: Wed, 5 Nov 2014 00:31:43 +0100 Subject: ExternalProject: Add unit tests for UPDATE_DISCONNECTED --- Tests/ExternalProjectUpdate/CMakeLists.txt | 12 +++ .../ExternalProjectUpdateTest.cmake | 96 ++++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/Tests/ExternalProjectUpdate/CMakeLists.txt b/Tests/ExternalProjectUpdate/CMakeLists.txt index 582b0a8..fbb3388 100644 --- a/Tests/ExternalProjectUpdate/CMakeLists.txt +++ b/Tests/ExternalProjectUpdate/CMakeLists.txt @@ -72,6 +72,18 @@ if(do_git_tests) ) ExternalProject_Add_StepDependencies(${proj} download SetupLocalGITRepository) set_property(TARGET ${proj} PROPERTY FOLDER "GIT") + + set(proj TutorialStep2-GIT) + ExternalProject_Add(${proj} + GIT_REPOSITORY "${local_git_repo}" + GIT_TAG ${TEST_GIT_TAG} + CMAKE_GENERATOR "${CMAKE_GENERATOR}" + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= + INSTALL_COMMAND "" + UPDATE_DISCONNECTED 1 + ) + ExternalProject_Add_StepDependencies(${proj} download SetupLocalGITRepository) + set_property(TARGET ${proj} PROPERTY FOLDER "GIT") endif() diff --git a/Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake b/Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake index 6c7bcfe..7065f36 100644 --- a/Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake +++ b/Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake @@ -59,6 +59,102 @@ was expected." if( EXISTS ${FETCH_HEAD_file} AND NOT ${fetch_expected}) message( FATAL_ERROR "Fetch DID occur when it was not expected.") endif() + + message( STATUS "Checking ExternalProjectUpdate to tag: ${desired_tag} (disconnected)" ) + + # Remove the FETCH_HEAD file, so we can check if it gets replaced with a 'git + # fetch'. + set( FETCH_HEAD_file ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep2-GIT/.git/FETCH_HEAD ) + file( REMOVE ${FETCH_HEAD_file} ) + + # Check initial SHA + execute_process(COMMAND ${GIT_EXECUTABLE} + rev-list --max-count=1 HEAD + WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep2-GIT + RESULT_VARIABLE error_code + OUTPUT_VARIABLE initial_sha + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + # Configure + execute_process(COMMAND ${CMAKE_COMMAND} + -G ${CMAKE_GENERATOR} -T "${CMAKE_GENERATOR_TOOLSET}" + -A "${CMAKE_GENERATOR_PLATFORM}" + -DTEST_GIT_TAG:STRING=${desired_tag} + ${ExternalProjectUpdate_SOURCE_DIR} + WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR} + RESULT_VARIABLE error_code + ) + if(error_code) + message(FATAL_ERROR "Could not configure the project.") + endif() + + # Build + execute_process(COMMAND ${CMAKE_COMMAND} + --build ${ExternalProjectUpdate_BINARY_DIR} + RESULT_VARIABLE error_code + ) + if(error_code) + message(FATAL_ERROR "Could not build the project.") + endif() + + if( EXISTS ${FETCH_HEAD_file} ) + message( FATAL_ERROR "Fetch occured when it was not expected.") + endif() + + # Check the resulting SHA + execute_process(COMMAND ${GIT_EXECUTABLE} + rev-list --max-count=1 HEAD + WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep2-GIT + RESULT_VARIABLE error_code + OUTPUT_VARIABLE tag_sha + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(error_code) + message(FATAL_ERROR "Could not check the sha.") + endif() + + if(NOT (${tag_sha} STREQUAL ${initial_sha})) + message(FATAL_ERROR "Update occurred when it was not expected.") + endif() + + # Update + execute_process(COMMAND ${CMAKE_COMMAND} + --build ${ExternalProjectUpdate_BINARY_DIR} + --target TutorialStep2-GIT-update + RESULT_VARIABLE error_code + ) + if(error_code) + message(FATAL_ERROR "Could not build the project.") + endif() + + # Check the resulting SHA + execute_process(COMMAND ${GIT_EXECUTABLE} + rev-list --max-count=1 HEAD + WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep2-GIT + RESULT_VARIABLE error_code + OUTPUT_VARIABLE tag_sha + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(error_code) + message(FATAL_ERROR "Could not check the sha.") + endif() + + if(NOT (${tag_sha} STREQUAL ${resulting_sha})) + message(FATAL_ERROR "UPDATE_COMMAND produced + ${tag_sha} +when + ${resulting_sha} +was expected." + ) + endif() + + if( NOT EXISTS ${FETCH_HEAD_file} AND ${fetch_expected}) + message( FATAL_ERROR "Fetch did NOT occur when it was expected.") + endif() + if( EXISTS ${FETCH_HEAD_file} AND NOT ${fetch_expected}) + message( FATAL_ERROR "Fetch DID occur when it was not expected.") + endif() endmacro() find_package(Git) -- cgit v0.12 From 3c497f1129c15bd5857cc6651db13b4eaab112ea Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 13 Nov 2014 09:55:17 -0500 Subject: Help: Add notes for topic 'ExternalProject_UPDATE_DISCONNECTED' --- Help/release/dev/ExternalProject_UPDATE_DISCONNECTED.rst | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 Help/release/dev/ExternalProject_UPDATE_DISCONNECTED.rst diff --git a/Help/release/dev/ExternalProject_UPDATE_DISCONNECTED.rst b/Help/release/dev/ExternalProject_UPDATE_DISCONNECTED.rst new file mode 100644 index 0000000..bed4a89 --- /dev/null +++ b/Help/release/dev/ExternalProject_UPDATE_DISCONNECTED.rst @@ -0,0 +1,6 @@ +ExternalProject_UPDATE_DISCONNECTED +----------------------------------- + +* The :module:`ExternalProject` module ``ExternalProject_Add`` command + learned an ``UPDATE_DISCONNECTED`` option to avoid automatically + updating the source tree checkout from version control. -- cgit v0.12