Преглед изворни кода

Merge topic 'ExternalProject_UPDATE_DISCONNECTED'

3c497f11 Help: Add notes for topic 'ExternalProject_UPDATE_DISCONNECTED'
aba5cec6 ExternalProject: Add unit tests for UPDATE_DISCONNECTED
3f606fa7 ExternalProject: Add UPDATE_DISCONNECTED option
c0b749cf ExternalProject: Always add a command to a step
Brad King пре 11 година
родитељ
комит
2c71fe6d62

+ 6 - 0
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.

+ 63 - 1
Modules/ExternalProject.cmake

@@ -80,6 +80,8 @@ Create custom targets to build projects in external trees
 
   ``UPDATE_COMMAND <cmd>...``
     Source work-tree update command
+  ``UPDATE_DISCONNECTED 1``
+    Never update automatically from the remote repository
   ``PATCH_COMMAND <cmd>...``
     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 \"\")
@@ -1436,6 +1455,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}
@@ -1829,6 +1857,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)
@@ -1918,10 +1952,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()
 
 
@@ -2043,10 +2093,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}
     )

+ 12 - 0
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_DIR>
+    INSTALL_COMMAND ""
+    UPDATE_DISCONNECTED 1
+  )
+  ExternalProject_Add_StepDependencies(${proj} download SetupLocalGITRepository)
+  set_property(TARGET ${proj} PROPERTY FOLDER "GIT")
 endif()
 
 

+ 96 - 0
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)