summaryrefslogtreecommitdiffstats
path: root/Tests/RunCMake/ExternalProject
diff options
context:
space:
mode:
Diffstat (limited to 'Tests/RunCMake/ExternalProject')
-rw-r--r--Tests/RunCMake/ExternalProject/Add_StepDependencies.cmake25
-rw-r--r--Tests/RunCMake/ExternalProject/Add_StepDependencies_iface-result.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/Add_StepDependencies_iface-stderr.txt5
-rw-r--r--Tests/RunCMake/ExternalProject/Add_StepDependencies_iface.cmake4
-rw-r--r--Tests/RunCMake/ExternalProject/Add_StepDependencies_iface_step-result.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/Add_StepDependencies_iface_step-stderr.txt5
-rw-r--r--Tests/RunCMake/ExternalProject/Add_StepDependencies_iface_step.cmake11
-rw-r--r--Tests/RunCMake/ExternalProject/Add_StepDependencies_no_target.cmake15
-rw-r--r--Tests/RunCMake/ExternalProject/BadIndependentStep1-result.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/BadIndependentStep1-stderr.txt7
-rw-r--r--Tests/RunCMake/ExternalProject/BadIndependentStep1.cmake14
-rw-r--r--Tests/RunCMake/ExternalProject/BadIndependentStep2-result.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/BadIndependentStep2-stderr.txt7
-rw-r--r--Tests/RunCMake/ExternalProject/BadIndependentStep2.cmake13
-rw-r--r--Tests/RunCMake/ExternalProject/CMAKE_CACHE_ARGS-check.cmake44
-rw-r--r--Tests/RunCMake/ExternalProject/CMAKE_CACHE_ARGS.cmake13
-rw-r--r--Tests/RunCMake/ExternalProject/CMAKE_CACHE_DEFAULT_ARGS-check.cmake44
-rw-r--r--Tests/RunCMake/ExternalProject/CMAKE_CACHE_DEFAULT_ARGS.cmake13
-rw-r--r--Tests/RunCMake/ExternalProject/CMAKE_CACHE_mix-check.cmake26
-rw-r--r--Tests/RunCMake/ExternalProject/CMAKE_CACHE_mix.cmake10
-rw-r--r--Tests/RunCMake/ExternalProject/CMakeLists.txt6
-rw-r--r--Tests/RunCMake/ExternalProject/CONFIGURE_HANDLED_BY_BUILD-rebuild-check.cmake19
-rw-r--r--Tests/RunCMake/ExternalProject/CONFIGURE_HANDLED_BY_BUILD.cmake28
-rw-r--r--Tests/RunCMake/ExternalProject/DownloadInactivityResume.cmake5
-rw-r--r--Tests/RunCMake/ExternalProject/DownloadInactivityTimeout-build-result.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/DownloadInactivityTimeout-build-stdout.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/DownloadInactivityTimeout.cmake5
-rw-r--r--Tests/RunCMake/ExternalProject/DownloadServer.py53
-rw-r--r--Tests/RunCMake/ExternalProject/DownloadTimeout-build-result.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/DownloadTimeout-build-stderr.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/DownloadTimeout.cmake5
-rw-r--r--Tests/RunCMake/ExternalProject/FetchGitTags.cmake67
-rw-r--r--Tests/RunCMake/ExternalProject/FetchGitTags/CMakeLists.txt15
-rw-r--r--Tests/RunCMake/ExternalProject/LogOutputOnFailure-build-result.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/LogOutputOnFailure-build-stderr.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/LogOutputOnFailure-build-stdout.txt8
-rw-r--r--Tests/RunCMake/ExternalProject/LogOutputOnFailure.cmake20
-rw-r--r--Tests/RunCMake/ExternalProject/LogOutputOnFailureMerged-build-result.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/LogOutputOnFailureMerged-build-stderr.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/LogOutputOnFailureMerged-build-stdout.txt7
-rw-r--r--Tests/RunCMake/ExternalProject/LogOutputOnFailureMerged.cmake21
-rw-r--r--Tests/RunCMake/ExternalProject/MultiCommand-build-stdout.txt15
-rw-r--r--Tests/RunCMake/ExternalProject/MultiCommand.cmake24
-rw-r--r--Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-Common.cmake17
-rw-r--r--Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-Direct-result.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-Direct-stderr.txt7
-rw-r--r--Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-Direct.cmake4
-rw-r--r--Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-result.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-stderr.txt16
-rw-r--r--Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW.cmake2
-rw-r--r--Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-OLD-stderr.txt61
-rw-r--r--Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-OLD.cmake2
-rw-r--r--Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-WARN-stderr.txt119
-rw-r--r--Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-WARN.cmake2
-rw-r--r--Tests/RunCMake/ExternalProject/NoOptions-result.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/NoOptions-stderr.txt18
-rw-r--r--Tests/RunCMake/ExternalProject/NoOptions.cmake2
-rw-r--r--Tests/RunCMake/ExternalProject/PreserveEmptyArgs-build-stdout.txt21
-rw-r--r--Tests/RunCMake/ExternalProject/PreserveEmptyArgs.cmake13
-rw-r--r--Tests/RunCMake/ExternalProject/RunCMakeTest.cmake190
-rw-r--r--Tests/RunCMake/ExternalProject/SourceEmpty-result.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/SourceEmpty-stderr.txt18
-rw-r--r--Tests/RunCMake/ExternalProject/SourceEmpty.cmake5
-rw-r--r--Tests/RunCMake/ExternalProject/SourceMissing-result.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/SourceMissing-stderr.txt18
-rw-r--r--Tests/RunCMake/ExternalProject/SourceMissing.cmake2
-rw-r--r--Tests/RunCMake/ExternalProject/Steps-CMP0114-Common.cmake34
-rw-r--r--Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW-build-download-check.cmake3
-rw-r--r--Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW-build-install-check.cmake3
-rw-r--r--Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW-build-test-check.cmake2
-rw-r--r--Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW-build-update-check.cmake3
-rw-r--r--Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW.cmake2
-rw-r--r--Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD-build-download-check.cmake3
-rw-r--r--Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD-build-install-check.cmake3
-rw-r--r--Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD-build-test-check.cmake2
-rw-r--r--Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD-build-update-check.cmake3
-rw-r--r--Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD.cmake2
-rw-r--r--Tests/RunCMake/ExternalProject/Substitutions-build-stdout.txt7
-rw-r--r--Tests/RunCMake/ExternalProject/Substitutions.cmake25
-rw-r--r--Tests/RunCMake/ExternalProject/UsesTerminal-check.cmake97
-rw-r--r--Tests/RunCMake/ExternalProject/UsesTerminal.cmake46
-rw-r--r--Tests/RunCMake/ExternalProject/Xcode-CMP0114-stderr.txt11
-rw-r--r--Tests/RunCMake/ExternalProject/Xcode-CMP0114.cmake2
-rw-r--r--Tests/RunCMake/ExternalProject/countArgs.cmake5
84 files changed, 1341 insertions, 0 deletions
diff --git a/Tests/RunCMake/ExternalProject/Add_StepDependencies.cmake b/Tests/RunCMake/ExternalProject/Add_StepDependencies.cmake
new file mode 100644
index 0000000..bfed4fa
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Add_StepDependencies.cmake
@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION ${CMAKE_VERSION})
+if(CMAKE_XCODE_BUILD_SYSTEM VERSION_GREATER_EQUAL 12)
+ cmake_policy(SET CMP0114 NEW)
+else()
+ cmake_policy(SET CMP0114 OLD) # Test deprecated behavior.
+endif()
+
+include(ExternalProject)
+
+ExternalProject_Add(BAR URL https://cmake.org/bar.tar.gz)
+
+ExternalProject_Add(FOO URL https://cmake.org/foo.tar.gz STEP_TARGETS update)
+ExternalProject_Add_Step(FOO do_something COMMAND ${CMAKE_COMMAND} -E echo "Doing something")
+ExternalProject_Add_Step(FOO do_something_else COMMAND ${CMAKE_COMMAND} -E echo "Doing something else")
+ExternalProject_Add_StepTargets(FOO do_something)
+
+# download and do_something_else are not targets, but the file-level
+# dependency are set.
+ExternalProject_Add_StepDependencies(FOO download BAR)
+ExternalProject_Add_StepDependencies(FOO do_something_else BAR)
+
+# update and do_something are targets, therefore both file-level and
+# target-level dependencies are set.
+ExternalProject_Add_StepDependencies(FOO update BAR)
+ExternalProject_Add_StepDependencies(FOO do_something BAR)
diff --git a/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface-result.txt b/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface-stderr.txt b/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface-stderr.txt
new file mode 100644
index 0000000..1c0b601
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at .*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ Target "SomeInterface" was not generated by ExternalProject_Add.
+Call Stack \(most recent call first\):
+ Add_StepDependencies_iface.cmake:[0-9]+ \(ExternalProject_Add_StepDependencies\)
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface.cmake b/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface.cmake
new file mode 100644
index 0000000..f7cfde1
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface.cmake
@@ -0,0 +1,4 @@
+include(ExternalProject)
+
+add_library(SomeInterface INTERFACE)
+ExternalProject_Add_StepDependencies(SomeInterface step dep)
diff --git a/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface_step-result.txt b/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface_step-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface_step-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface_step-stderr.txt b/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface_step-stderr.txt
new file mode 100644
index 0000000..5fa75e8
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface_step-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at .*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ External project "MyProj" does not have a step "IFace".
+Call Stack \(most recent call first\):
+ Add_StepDependencies_iface_step.cmake:[0-9]+ \(ExternalProject_Add_StepDependencies\)
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface_step.cmake b/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface_step.cmake
new file mode 100644
index 0000000..0289493
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Add_StepDependencies_iface_step.cmake
@@ -0,0 +1,11 @@
+include(ExternalProject)
+
+ExternalProject_Add(MyProj
+ DOWNLOAD_COMMAND ""
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ )
+
+add_library(MyProj-IFace INTERFACE)
+ExternalProject_Add_StepDependencies(MyProj IFace dep)
diff --git a/Tests/RunCMake/ExternalProject/Add_StepDependencies_no_target.cmake b/Tests/RunCMake/ExternalProject/Add_StepDependencies_no_target.cmake
new file mode 100644
index 0000000..039dec6
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Add_StepDependencies_no_target.cmake
@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION ${CMAKE_VERSION})
+if(CMAKE_XCODE_BUILD_SYSTEM VERSION_GREATER_EQUAL 12)
+ cmake_policy(SET CMP0114 NEW)
+else()
+ cmake_policy(SET CMP0114 OLD) # Test deprecated behavior.
+endif()
+
+include(ExternalProject)
+
+ExternalProject_Add(BAR URL https://cmake.org/bar.tar.gz)
+
+ExternalProject_Add(FOO URL https://cmake.org/foo.tar.gz STEP_TARGETS update)
+ExternalProject_Add_Step(FOO do_something COMMAND ${CMAKE_COMMAND} -E echo "Doing something")
+ExternalProject_Add_Step(FOO do_something_else COMMAND ${CMAKE_COMMAND} -E echo "Doing something else")
+ExternalProject_Add_StepTargets(FOO do_something)
diff --git a/Tests/RunCMake/ExternalProject/BadIndependentStep1-result.txt b/Tests/RunCMake/ExternalProject/BadIndependentStep1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/BadIndependentStep1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalProject/BadIndependentStep1-stderr.txt b/Tests/RunCMake/ExternalProject/BadIndependentStep1-stderr.txt
new file mode 100644
index 0000000..3188910
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/BadIndependentStep1-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ ExternalProject 'proj' step 'custom' is marked INDEPENDENT but depends on
+ step 'configure' that is not marked INDEPENDENT.
+Call Stack \(most recent call first\):
+ BadIndependentStep1.cmake:[0-9]+ \(ExternalProject_Add_Step\)
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ExternalProject/BadIndependentStep1.cmake b/Tests/RunCMake/ExternalProject/BadIndependentStep1.cmake
new file mode 100644
index 0000000..c81eb07
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/BadIndependentStep1.cmake
@@ -0,0 +1,14 @@
+include(ExternalProject)
+cmake_policy(SET CMP0114 NEW)
+
+ExternalProject_Add(proj
+ SOURCE_DIR "."
+ DOWNLOAD_COMMAND ""
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ )
+ExternalProject_Add_Step(proj custom
+ DEPENDEES configure
+ INDEPENDENT 1
+ )
diff --git a/Tests/RunCMake/ExternalProject/BadIndependentStep2-result.txt b/Tests/RunCMake/ExternalProject/BadIndependentStep2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/BadIndependentStep2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalProject/BadIndependentStep2-stderr.txt b/Tests/RunCMake/ExternalProject/BadIndependentStep2-stderr.txt
new file mode 100644
index 0000000..0b87e5e
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/BadIndependentStep2-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ ExternalProject 'proj' step 'update' is marked INDEPENDENT but depends on
+ step 'custom' that is not marked INDEPENDENT.
+Call Stack \(most recent call first\):
+ BadIndependentStep2.cmake:[0-9]+ \(ExternalProject_Add_Step\)
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ExternalProject/BadIndependentStep2.cmake b/Tests/RunCMake/ExternalProject/BadIndependentStep2.cmake
new file mode 100644
index 0000000..4a530ea
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/BadIndependentStep2.cmake
@@ -0,0 +1,13 @@
+include(ExternalProject)
+cmake_policy(SET CMP0114 NEW)
+
+ExternalProject_Add(proj
+ SOURCE_DIR "."
+ DOWNLOAD_COMMAND ""
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ )
+ExternalProject_Add_Step(proj custom
+ DEPENDERS update
+ )
diff --git a/Tests/RunCMake/ExternalProject/CMAKE_CACHE_ARGS-check.cmake b/Tests/RunCMake/ExternalProject/CMAKE_CACHE_ARGS-check.cmake
new file mode 100644
index 0000000..c501856
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/CMAKE_CACHE_ARGS-check.cmake
@@ -0,0 +1,44 @@
+set(_cache_file "${RunCMake_TEST_BINARY_DIR}/tmp/FOO-cache-Debug.cmake")
+
+if(NOT EXISTS "${_cache_file}")
+ set(RunCMake_TEST_FAILED "Initial cache not created")
+ return()
+endif()
+
+file(READ "${_cache_file}" _cache)
+
+if(NOT "${_cache}" MATCHES "set\\(FOO \"BAR\".+\\)") # \(\)
+ set(RunCMake_TEST_FAILED "Cannot find FOO argument in cache")
+ return()
+endif()
+if(NOT "${CMAKE_MATCH_0}" MATCHES FORCE)
+ set(RunCMake_TEST_FAILED "Expected forced FOO argument")
+ return()
+endif()
+
+if(NOT "${_cache}" MATCHES "set\\(TEST_LIST \"A;B;C\".+\\)")
+ set(RunCMake_TEST_FAILED "Cannot find TEST_LIST argument in cache")
+ return()
+endif()
+if(NOT "${CMAKE_MATCH_0}" MATCHES FORCE)
+ set(RunCMake_TEST_FAILED "Expected forced TEST_LIST argument")
+ return()
+endif()
+
+if(NOT "${_cache}" MATCHES "set\\(TEST_OPTIONAL \"TEST_OPTIONAL-NOTFOUND\".+\\)")
+ set(RunCMake_TEST_FAILED "Cannot find TEST_OPTIONAL argument in cache")
+ return()
+endif()
+if(NOT "${CMAKE_MATCH_0}" MATCHES FORCE)
+ set(RunCMake_TEST_FAILED "Expected forced TEST_OPTIONAL argument")
+ return()
+endif()
+
+if(NOT "${_cache}" MATCHES "set\\(TEST_OPTIONAL_LAST \"TEST_OPTIONAL_LAST-NOTFOUND\".+\\)")
+ set(RunCMake_TEST_FAILED "Cannot find TEST_OPTIONAL_LAST argument in cache")
+ return()
+endif()
+if(NOT "${CMAKE_MATCH_0}" MATCHES FORCE)
+ set(RunCMake_TEST_FAILED "Expected forced TEST_OPTIONAL_LAST argument")
+ return()
+endif()
diff --git a/Tests/RunCMake/ExternalProject/CMAKE_CACHE_ARGS.cmake b/Tests/RunCMake/ExternalProject/CMAKE_CACHE_ARGS.cmake
new file mode 100644
index 0000000..4f7e020
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/CMAKE_CACHE_ARGS.cmake
@@ -0,0 +1,13 @@
+get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(NOT _isMultiConfig)
+ set(CMAKE_BUILD_TYPE Debug)
+endif()
+include(ExternalProject)
+
+ExternalProject_Add(FOO TMP_DIR "${CMAKE_CURRENT_BINARY_DIR}/tmp"
+ DOWNLOAD_COMMAND ""
+ CMAKE_CACHE_ARGS
+ "-DFOO:STRING=$<1:BAR>$<0:BAD>"
+ "-DTEST_LIST:STRING=A;B;C"
+ "-DTEST_OPTIONAL:FILEPATH=TEST_OPTIONAL-NOTFOUND"
+ "-DTEST_OPTIONAL_LAST:FILEPATH=TEST_OPTIONAL_LAST-NOTFOUND")
diff --git a/Tests/RunCMake/ExternalProject/CMAKE_CACHE_DEFAULT_ARGS-check.cmake b/Tests/RunCMake/ExternalProject/CMAKE_CACHE_DEFAULT_ARGS-check.cmake
new file mode 100644
index 0000000..059f6d3
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/CMAKE_CACHE_DEFAULT_ARGS-check.cmake
@@ -0,0 +1,44 @@
+set(_cache_file "${RunCMake_TEST_BINARY_DIR}/tmp/FOO-cache-Debug.cmake")
+
+if(NOT EXISTS "${_cache_file}")
+ set(RunCMake_TEST_FAILED "Initial cache not created")
+ return()
+endif()
+
+file(READ "${_cache_file}" _cache)
+
+if(NOT "${_cache}" MATCHES "set\\(FOO \"BAR\".+\\)") # \(\)
+ set(RunCMake_TEST_FAILED "Cannot find FOO argument in cache")
+ return()
+endif()
+if("${CMAKE_MATCH_0}" MATCHES FORCE)
+ set(RunCMake_TEST_FAILED "Expected not forced FOO argument")
+ return()
+endif()
+
+if(NOT "${_cache}" MATCHES "set\\(TEST_LIST \"A;B;C\".+\\)")
+ set(RunCMake_TEST_FAILED "Cannot find TEST_LIST argument in cache")
+ return()
+endif()
+if("${CMAKE_MATCH_0}" MATCHES FORCE)
+ set(RunCMake_TEST_FAILED "Expected not forced TEST_LIST argument")
+ return()
+endif()
+
+if(NOT "${_cache}" MATCHES "set\\(TEST_OPTIONAL \"TEST_OPTIONAL-NOTFOUND\".+\\)")
+ set(RunCMake_TEST_FAILED "Cannot find TEST_OPTIONAL argument in cache")
+ return()
+endif()
+if("${CMAKE_MATCH_0}" MATCHES FORCE)
+ set(RunCMake_TEST_FAILED "Expected not forced TEST_OPTIONAL argument")
+ return()
+endif()
+
+if(NOT "${_cache}" MATCHES "set\\(TEST_OPTIONAL_LAST \"TEST_OPTIONAL_LAST-NOTFOUND\".+\\)")
+ set(RunCMake_TEST_FAILED "Cannot find TEST_OPTIONAL_LAST argument in cache")
+ return()
+endif()
+if("${CMAKE_MATCH_0}" MATCHES FORCE)
+ set(RunCMake_TEST_FAILED "Expected not forced TEST_OPTIONAL_LAST argument")
+ return()
+endif()
diff --git a/Tests/RunCMake/ExternalProject/CMAKE_CACHE_DEFAULT_ARGS.cmake b/Tests/RunCMake/ExternalProject/CMAKE_CACHE_DEFAULT_ARGS.cmake
new file mode 100644
index 0000000..6133418
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/CMAKE_CACHE_DEFAULT_ARGS.cmake
@@ -0,0 +1,13 @@
+get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(NOT _isMultiConfig)
+ set(CMAKE_BUILD_TYPE Debug)
+endif()
+include(ExternalProject)
+
+ExternalProject_Add(FOO TMP_DIR "${CMAKE_CURRENT_BINARY_DIR}/tmp"
+ DOWNLOAD_COMMAND ""
+ CMAKE_CACHE_DEFAULT_ARGS
+ "-DFOO:STRING=$<1:BAR>$<0:BAD>"
+ "-DTEST_LIST:STRING=A;B;C"
+ "-DTEST_OPTIONAL:FILEPATH=TEST_OPTIONAL-NOTFOUND"
+ "-DTEST_OPTIONAL_LAST:FILEPATH=TEST_OPTIONAL_LAST-NOTFOUND")
diff --git a/Tests/RunCMake/ExternalProject/CMAKE_CACHE_mix-check.cmake b/Tests/RunCMake/ExternalProject/CMAKE_CACHE_mix-check.cmake
new file mode 100644
index 0000000..04d49b9
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/CMAKE_CACHE_mix-check.cmake
@@ -0,0 +1,26 @@
+set(_cache_file "${RunCMake_TEST_BINARY_DIR}/tmp/FOO-cache-Debug.cmake")
+
+if(NOT EXISTS "${_cache_file}")
+ set(RunCMake_TEST_FAILED "Initial cache not created")
+ return()
+endif()
+
+file(READ "${_cache_file}" _cache)
+
+if(NOT "${_cache}" MATCHES "set\\(FOO \"BAR\".+\\)") # \(\)
+ set(RunCMake_TEST_FAILED "Cannot find FOO argument in cache")
+ return()
+endif()
+if(NOT "${CMAKE_MATCH_0}" MATCHES FORCE)
+ set(RunCMake_TEST_FAILED "Expected forced FOO argument")
+ return()
+endif()
+
+if(NOT "${_cache}" MATCHES "set\\(BAR \"BAZ\".+\\)") # \(\)
+ set(RunCMake_TEST_FAILED "Cannot find BAR argument in cache")
+ return()
+endif()
+if("${CMAKE_MATCH_0}" MATCHES FORCE)
+ set(RunCMake_TEST_FAILED "Expected not forced BAR argument")
+ return()
+endif()
diff --git a/Tests/RunCMake/ExternalProject/CMAKE_CACHE_mix.cmake b/Tests/RunCMake/ExternalProject/CMAKE_CACHE_mix.cmake
new file mode 100644
index 0000000..2fb0705
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/CMAKE_CACHE_mix.cmake
@@ -0,0 +1,10 @@
+get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(NOT _isMultiConfig)
+ set(CMAKE_BUILD_TYPE Debug)
+endif()
+include(ExternalProject)
+
+ExternalProject_Add(FOO TMP_DIR "${CMAKE_CURRENT_BINARY_DIR}/tmp"
+ DOWNLOAD_COMMAND ""
+ CMAKE_CACHE_ARGS "-DFOO:STRING=$<1:BAR>$<0:BAD>"
+ CMAKE_CACHE_DEFAULT_ARGS "-DBAR:STRING=$<1:BAZ>$<0:BAD>")
diff --git a/Tests/RunCMake/ExternalProject/CMakeLists.txt b/Tests/RunCMake/ExternalProject/CMakeLists.txt
new file mode 100644
index 0000000..933a57a
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.18)
+project(${RunCMake_TEST} NONE)
+if(CMAKE_XCODE_BUILD_SYSTEM VERSION_GREATER_EQUAL 12 AND NOT RunCMake_TEST STREQUAL "Xcode-CMP0114")
+ cmake_policy(SET CMP0114 NEW)
+endif()
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/ExternalProject/CONFIGURE_HANDLED_BY_BUILD-rebuild-check.cmake b/Tests/RunCMake/ExternalProject/CONFIGURE_HANDLED_BY_BUILD-rebuild-check.cmake
new file mode 100644
index 0000000..887da0f
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/CONFIGURE_HANDLED_BY_BUILD-rebuild-check.cmake
@@ -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()
diff --git a/Tests/RunCMake/ExternalProject/CONFIGURE_HANDLED_BY_BUILD.cmake b/Tests/RunCMake/ExternalProject/CONFIGURE_HANDLED_BY_BUILD.cmake
new file mode 100644
index 0000000..6dbf0f4
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/CONFIGURE_HANDLED_BY_BUILD.cmake
@@ -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.125
+ 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.125
+ INSTALL_COMMAND ""
+ CONFIGURE_HANDLED_BY_BUILD ON
+ DEPENDS proj1
+ STAMP_DIR "stamp"
+)
diff --git a/Tests/RunCMake/ExternalProject/DownloadInactivityResume.cmake b/Tests/RunCMake/ExternalProject/DownloadInactivityResume.cmake
new file mode 100644
index 0000000..d34482d
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/DownloadInactivityResume.cmake
@@ -0,0 +1,5 @@
+include(ExternalProject)
+ExternalProject_Add(MyProj URL ${SERVER_URL} INACTIVITY_TIMEOUT 2 DOWNLOAD_NO_EXTRACT TRUE
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND "")
diff --git a/Tests/RunCMake/ExternalProject/DownloadInactivityTimeout-build-result.txt b/Tests/RunCMake/ExternalProject/DownloadInactivityTimeout-build-result.txt
new file mode 100644
index 0000000..d197c91
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/DownloadInactivityTimeout-build-result.txt
@@ -0,0 +1 @@
+[^0]
diff --git a/Tests/RunCMake/ExternalProject/DownloadInactivityTimeout-build-stdout.txt b/Tests/RunCMake/ExternalProject/DownloadInactivityTimeout-build-stdout.txt
new file mode 100644
index 0000000..3238147
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/DownloadInactivityTimeout-build-stdout.txt
@@ -0,0 +1 @@
+(Timeout was reached)?
diff --git a/Tests/RunCMake/ExternalProject/DownloadInactivityTimeout.cmake b/Tests/RunCMake/ExternalProject/DownloadInactivityTimeout.cmake
new file mode 100644
index 0000000..d34482d
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/DownloadInactivityTimeout.cmake
@@ -0,0 +1,5 @@
+include(ExternalProject)
+ExternalProject_Add(MyProj URL ${SERVER_URL} INACTIVITY_TIMEOUT 2 DOWNLOAD_NO_EXTRACT TRUE
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND "")
diff --git a/Tests/RunCMake/ExternalProject/DownloadServer.py b/Tests/RunCMake/ExternalProject/DownloadServer.py
new file mode 100644
index 0000000..63b7fa7
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/DownloadServer.py
@@ -0,0 +1,53 @@
+from http.server import HTTPServer, BaseHTTPRequestHandler
+import argparse
+import time
+import subprocess
+import sys
+import os
+import threading
+args = None
+outerthread = None
+
+barrier = threading.Barrier(2)
+
+class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
+ def do_GET(self):
+ barrier.wait()
+ self.send_response(200)
+ self.end_headers()
+ data = b'D'
+
+ if args.speed_limit:
+ slow_deadline = time.time()+args.limit_duration
+
+ while time.time() < slow_deadline:
+ self.wfile.write(data)
+ if args.speed_limit:
+ time.sleep(1.1)
+
+ data = data * 100
+ self.wfile.write(data)
+ self.close_connection = True
+
+def runServer(fileName):
+ httpd = HTTPServer(('localhost', 0), SimpleHTTPRequestHandler)
+ with open(fileName,"w") as f:
+ f.write('http://localhost:{}/test'.format(httpd.socket.getsockname()[1]))
+ httpd.handle_request()
+ os.remove(fileName)
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--speed_limit', help='transfer rate limitation', action='store_true',default=False)
+ parser.add_argument('--limit_duration', help='duration of the transfer rate limitation',default=1, type=float)
+ parser.add_argument('--file', help='file to write the url to connect to')
+ parser.add_argument('--subprocess', action='store_true')
+ args = parser.parse_args()
+ if not args.subprocess:
+ subprocess.Popen([sys.executable]+sys.argv+['--subprocess'],stdin=subprocess.DEVNULL, stderr=subprocess.DEVNULL,stdout=subprocess.DEVNULL)
+ else:
+ serverThread = threading.Thread(target=runServer,args=(args.file,))
+ serverThread.daemon = True
+ serverThread.start()
+ barrier.wait(60)
+ serverThread.join(20)
diff --git a/Tests/RunCMake/ExternalProject/DownloadTimeout-build-result.txt b/Tests/RunCMake/ExternalProject/DownloadTimeout-build-result.txt
new file mode 100644
index 0000000..c20fd86
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/DownloadTimeout-build-result.txt
@@ -0,0 +1 @@
+^[^0]
diff --git a/Tests/RunCMake/ExternalProject/DownloadTimeout-build-stderr.txt b/Tests/RunCMake/ExternalProject/DownloadTimeout-build-stderr.txt
new file mode 100644
index 0000000..8d98f9d
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/DownloadTimeout-build-stderr.txt
@@ -0,0 +1 @@
+.*
diff --git a/Tests/RunCMake/ExternalProject/DownloadTimeout.cmake b/Tests/RunCMake/ExternalProject/DownloadTimeout.cmake
new file mode 100644
index 0000000..c90b4ba
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/DownloadTimeout.cmake
@@ -0,0 +1,5 @@
+include(ExternalProject)
+set(source_dir "${CMAKE_CURRENT_BINARY_DIR}/DownloadTimeout")
+file(REMOVE_RECURSE "${source_dir}")
+file(MAKE_DIRECTORY "${source_dir}")
+ExternalProject_Add(MyProj URL "http://cmake.org/invalid_file.tar.gz")
diff --git a/Tests/RunCMake/ExternalProject/FetchGitTags.cmake b/Tests/RunCMake/ExternalProject/FetchGitTags.cmake
new file mode 100644
index 0000000..37d1b40
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/FetchGitTags.cmake
@@ -0,0 +1,67 @@
+find_package(Git QUIET REQUIRED)
+
+include(ExternalProject)
+
+set(srcRepo ${CMAKE_CURRENT_BINARY_DIR}/srcRepo)
+set(srcDir ${CMAKE_CURRENT_BINARY_DIR}/src)
+set(binDir ${CMAKE_CURRENT_BINARY_DIR}/build)
+file(MAKE_DIRECTORY ${srcRepo})
+file(MAKE_DIRECTORY ${srcDir})
+
+file(GLOB entries ${srcRepo}/*)
+file(REMOVE_RECURSE ${entries} ${binDir})
+file(TOUCH ${srcRepo}/firstFile.txt)
+configure_file(${CMAKE_CURRENT_LIST_DIR}/FetchGitTags/CMakeLists.txt
+ ${srcDir}/CMakeLists.txt COPYONLY)
+
+function(execGitCommand)
+ execute_process(
+ WORKING_DIRECTORY ${srcRepo}
+ COMMAND ${GIT_EXECUTABLE} ${ARGN}
+ COMMAND_ECHO STDOUT
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+endfunction()
+
+function(configureAndBuild tag)
+ execute_process(COMMAND ${CMAKE_COMMAND}
+ -G ${CMAKE_GENERATOR} -T "${CMAKE_GENERATOR_TOOLSET}"
+ -A "${CMAKE_GENERATOR_PLATFORM}"
+ -D repoDir:PATH=${srcRepo}
+ -D gitTag:STRING=${tag}
+ -B ${binDir}
+ -S ${srcDir}
+ COMMAND_ECHO STDOUT
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+
+ execute_process(COMMAND ${CMAKE_COMMAND} --build ${binDir} --target fetcher
+ WORKING_DIRECTORY ${binDir}
+ COMMAND_ECHO STDOUT
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+endfunction()
+
+# Setup a fresh source repo with a predictable default branch across all
+# git versions
+execGitCommand(-c init.defaultBranch=master init)
+execGitCommand(config --add user.email "testauthor@cmake.org")
+execGitCommand(config --add user.name testauthor)
+
+# Create the initial repo structure
+execGitCommand(add firstFile.txt)
+execGitCommand(commit -m "First file")
+
+message(STATUS "First configure-and-build")
+configureAndBuild(master)
+
+# Create a tagged commit that is not on any branch. With git 2.20 or later,
+# this commit won't be fetched without the --tags option.
+file(TOUCH ${srcRepo}/secondFile.txt)
+execGitCommand(add secondFile.txt)
+execGitCommand(commit -m "Second file")
+execGitCommand(tag -a -m "Adding tag" tag_of_interest)
+execGitCommand(reset --hard HEAD~1)
+
+message(STATUS "Second configure-and-build")
+configureAndBuild(tag_of_interest)
diff --git a/Tests/RunCMake/ExternalProject/FetchGitTags/CMakeLists.txt b/Tests/RunCMake/ExternalProject/FetchGitTags/CMakeLists.txt
new file mode 100644
index 0000000..d9a380c
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/FetchGitTags/CMakeLists.txt
@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 3.19)
+project(FetchTags LANGUAGES NONE)
+
+include(ExternalProject)
+
+# repoDir and gitTag are expected to be set as cache variables
+
+ExternalProject_Add(fetcher
+ GIT_REPOSITORY ${repoDir}
+ GIT_TAG ${gitTag}
+ GIT_REMOTE_UPDATE_STRATEGY CHECKOUT
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+)
diff --git a/Tests/RunCMake/ExternalProject/LogOutputOnFailure-build-result.txt b/Tests/RunCMake/ExternalProject/LogOutputOnFailure-build-result.txt
new file mode 100644
index 0000000..c20fd86
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/LogOutputOnFailure-build-result.txt
@@ -0,0 +1 @@
+^[^0]
diff --git a/Tests/RunCMake/ExternalProject/LogOutputOnFailure-build-stderr.txt b/Tests/RunCMake/ExternalProject/LogOutputOnFailure-build-stderr.txt
new file mode 100644
index 0000000..8d98f9d
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/LogOutputOnFailure-build-stderr.txt
@@ -0,0 +1 @@
+.*
diff --git a/Tests/RunCMake/ExternalProject/LogOutputOnFailure-build-stdout.txt b/Tests/RunCMake/ExternalProject/LogOutputOnFailure-build-stdout.txt
new file mode 100644
index 0000000..87e5384
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/LogOutputOnFailure-build-stdout.txt
@@ -0,0 +1,8 @@
+( )?-- stdout output is:
+( )?This is some dummy output with some long lines to ensure formatting is preserved
+( )? Including lines with leading spaces
+( )?
+( )?And also blank lines[
+ ]+
+( )?-- stderr output is:
+( )?cmake -E env: no command given
diff --git a/Tests/RunCMake/ExternalProject/LogOutputOnFailure.cmake b/Tests/RunCMake/ExternalProject/LogOutputOnFailure.cmake
new file mode 100644
index 0000000..863bbef
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/LogOutputOnFailure.cmake
@@ -0,0 +1,20 @@
+include(ExternalProject)
+
+set(dummyOutput [[
+This is some dummy output with some long lines to ensure formatting is preserved
+ Including lines with leading spaces
+
+And also blank lines
+]])
+
+ExternalProject_Add(FailsWithOutput
+ SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ${CMAKE_COMMAND} -E echo ${dummyOutput}
+ COMMAND ${CMAKE_COMMAND} -E env # missing command, forces fail
+ TEST_COMMAND ""
+ INSTALL_COMMAND ""
+ LOG_BUILD YES
+ LOG_OUTPUT_ON_FAILURE YES
+ USES_TERMINAL_BUILD YES
+)
diff --git a/Tests/RunCMake/ExternalProject/LogOutputOnFailureMerged-build-result.txt b/Tests/RunCMake/ExternalProject/LogOutputOnFailureMerged-build-result.txt
new file mode 100644
index 0000000..c20fd86
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/LogOutputOnFailureMerged-build-result.txt
@@ -0,0 +1 @@
+^[^0]
diff --git a/Tests/RunCMake/ExternalProject/LogOutputOnFailureMerged-build-stderr.txt b/Tests/RunCMake/ExternalProject/LogOutputOnFailureMerged-build-stderr.txt
new file mode 100644
index 0000000..8d98f9d
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/LogOutputOnFailureMerged-build-stderr.txt
@@ -0,0 +1 @@
+.*
diff --git a/Tests/RunCMake/ExternalProject/LogOutputOnFailureMerged-build-stdout.txt b/Tests/RunCMake/ExternalProject/LogOutputOnFailureMerged-build-stdout.txt
new file mode 100644
index 0000000..11c7317
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/LogOutputOnFailureMerged-build-stdout.txt
@@ -0,0 +1,7 @@
+( )?-- Log output is:
+( )?This is some dummy output with some long lines to ensure formatting is preserved
+( )? Including lines with leading spaces
+( )?
+( )?And also blank lines[
+ ]+
+( )?cmake -E env: no command given
diff --git a/Tests/RunCMake/ExternalProject/LogOutputOnFailureMerged.cmake b/Tests/RunCMake/ExternalProject/LogOutputOnFailureMerged.cmake
new file mode 100644
index 0000000..116448b
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/LogOutputOnFailureMerged.cmake
@@ -0,0 +1,21 @@
+include(ExternalProject)
+
+set(dummyOutput [[
+This is some dummy output with some long lines to ensure formatting is preserved
+ Including lines with leading spaces
+
+And also blank lines
+]])
+
+ExternalProject_Add(FailsWithOutput
+ SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ${CMAKE_COMMAND} -E echo ${dummyOutput}
+ COMMAND ${CMAKE_COMMAND} -E env # missing command, forces fail
+ TEST_COMMAND ""
+ INSTALL_COMMAND ""
+ LOG_BUILD YES
+ LOG_OUTPUT_ON_FAILURE YES
+ LOG_MERGED_STDOUTERR YES
+ USES_TERMINAL_BUILD YES
+)
diff --git a/Tests/RunCMake/ExternalProject/MultiCommand-build-stdout.txt b/Tests/RunCMake/ExternalProject/MultiCommand-build-stdout.txt
new file mode 100644
index 0000000..30ebc7d
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/MultiCommand-build-stdout.txt
@@ -0,0 +1,15 @@
+.* *download 1
+.* *download 2
+.* *update 1
+.* *update 2
+.* *patch 1
+.* *patch 2
+.* *configure 1
+.* *configure 2
+.* *build 1
+.* *build 2
+.* *install 1
+.* *install 2
+.* *test 1
+.* *test 2
+.*
diff --git a/Tests/RunCMake/ExternalProject/MultiCommand.cmake b/Tests/RunCMake/ExternalProject/MultiCommand.cmake
new file mode 100644
index 0000000..dbf67eb
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/MultiCommand.cmake
@@ -0,0 +1,24 @@
+include(ExternalProject)
+
+# Verify COMMAND keyword is recognised after various *_COMMAND options
+ExternalProject_Add(multiCommand
+ DOWNLOAD_COMMAND "${CMAKE_COMMAND}" -E echo "download 1"
+ COMMAND "${CMAKE_COMMAND}" -E echo "download 2"
+ UPDATE_COMMAND "${CMAKE_COMMAND}" -E echo "update 1"
+ COMMAND "${CMAKE_COMMAND}" -E echo "update 2"
+ PATCH_COMMAND "${CMAKE_COMMAND}" -E echo "patch 1"
+ COMMAND "${CMAKE_COMMAND}" -E echo "patch 2"
+ CONFIGURE_COMMAND "${CMAKE_COMMAND}" -E echo "configure 1"
+ COMMAND "${CMAKE_COMMAND}" -E echo "configure 2"
+ BUILD_COMMAND "${CMAKE_COMMAND}" -E echo "build 1"
+ COMMAND "${CMAKE_COMMAND}" -E echo "build 2"
+ TEST_COMMAND "${CMAKE_COMMAND}" -E echo "test 1"
+ COMMAND "${CMAKE_COMMAND}" -E echo "test 2"
+ INSTALL_COMMAND "${CMAKE_COMMAND}" -E echo "install 1"
+ COMMAND "${CMAKE_COMMAND}" -E echo "install 2"
+)
+
+# Force all steps to be re-run by removing timestamps from any previous run
+ExternalProject_Get_Property(multiCommand STAMP_DIR)
+file(REMOVE_RECURSE "${STAMP_DIR}")
+file(MAKE_DIRECTORY "${STAMP_DIR}")
diff --git a/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-Common.cmake b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-Common.cmake
new file mode 100644
index 0000000..176e28b
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-Common.cmake
@@ -0,0 +1,17 @@
+
+include(ExternalProject RESULT_VARIABLE GOO)
+
+set_property(DIRECTORY PROPERTY EP_INDEPENDENT_STEP_TARGETS download patch update configure build)
+
+ExternalProject_Add(FOO
+ URL https://example.org/foo.tar.gz)
+
+ExternalProject_Add(BAR
+ URL https://example.org/bar.tar.gz
+ TEST_COMMAND echo test
+ INDEPENDENT_STEP_TARGETS install)
+# This one should not give a warning
+ExternalProject_Add_Step(BAR bar
+ COMMAND echo bar)
+
+ExternalProject_Add_StepTargets(BAR NO_DEPENDS test bar)
diff --git a/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-Direct-result.txt b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-Direct-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-Direct-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-Direct-stderr.txt b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-Direct-stderr.txt
new file mode 100644
index 0000000..c6bf767
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-Direct-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ The 'NO_DEPENDS' option is no longer allowed. It has been superseded by
+ the per-step 'INDEPENDENT' option. See policy CMP0114.
+Call Stack \(most recent call first\):
+ NO_DEPENDS-CMP0114-NEW-Direct.cmake:[0-9]+ \(ExternalProject_Add_StepTargets\)
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-Direct.cmake b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-Direct.cmake
new file mode 100644
index 0000000..7ec1a00
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-Direct.cmake
@@ -0,0 +1,4 @@
+cmake_policy(SET CMP0114 NEW)
+include(ExternalProject)
+ExternalProject_Add(BAR SOURCE_DIR . TEST_COMMAND echo test)
+ExternalProject_Add_StepTargets(BAR NO_DEPENDS test)
diff --git a/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-result.txt b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-stderr.txt b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-stderr.txt
new file mode 100644
index 0000000..5a5ba89
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-stderr.txt
@@ -0,0 +1,16 @@
+^CMake Error at [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ ExternalProject 'FOO' option 'INDEPENDENT_STEP_TARGETS' is set to
+
+ download;patch;update;configure;build
+
+ but the option is no longer allowed. It has been superseded by the
+ per-step 'INDEPENDENT' option. See policy CMP0114.
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(ExternalProject_Add_Step\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_mkdir_command\)
+ NO_DEPENDS-CMP0114-Common.cmake:[0-9]+ \(ExternalProject_Add\)
+ NO_DEPENDS-CMP0114-NEW.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW.cmake b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW.cmake
new file mode 100644
index 0000000..9622a60
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0114 NEW)
+include(NO_DEPENDS-CMP0114-Common.cmake)
diff --git a/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-OLD-stderr.txt b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-OLD-stderr.txt
new file mode 100644
index 0000000..2b0feb6
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-OLD-stderr.txt
@@ -0,0 +1,61 @@
+^CMake Warning \(dev\) at [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ Using NO_DEPENDS for "configure" step might break parallel builds
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_step_add_target\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+:EVAL:2 \(ExternalProject_Add_Step\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(cmake_language\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_configure_command\)
+ NO_DEPENDS-CMP0114-Common.cmake:[0-9]+ \(ExternalProject_Add\)
+ NO_DEPENDS-CMP0114-OLD.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
++
+CMake Warning \(dev\) at [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ Using NO_DEPENDS for "build" step might break parallel builds
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_step_add_target\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+:EVAL:2 \(ExternalProject_Add_Step\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(cmake_language\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_build_command\)
+ NO_DEPENDS-CMP0114-Common.cmake:[0-9]+ \(ExternalProject_Add\)
+ NO_DEPENDS-CMP0114-OLD.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
++
+CMake Warning \(dev\) at [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ Using NO_DEPENDS for "install" step might break parallel builds
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_step_add_target\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+:EVAL:2 \(ExternalProject_Add_Step\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(cmake_language\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_install_command\)
+ NO_DEPENDS-CMP0114-Common.cmake:[0-9]+ \(ExternalProject_Add\)
+ NO_DEPENDS-CMP0114-OLD.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
++
+CMake Warning \(dev\) at [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ Using NO_DEPENDS for "test" step might break parallel builds
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_step_add_target\)
+ NO_DEPENDS-CMP0114-Common.cmake:[0-9]+ \(ExternalProject_Add_StepTargets\)
+ NO_DEPENDS-CMP0114-OLD.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.$
diff --git a/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-OLD.cmake b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-OLD.cmake
new file mode 100644
index 0000000..c20d443
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0114 OLD)
+include(NO_DEPENDS-CMP0114-Common.cmake)
diff --git a/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-WARN-stderr.txt b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-WARN-stderr.txt
new file mode 100644
index 0000000..bbf7178
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-WARN-stderr.txt
@@ -0,0 +1,119 @@
+^CMake Warning \(dev\) at [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ Policy CMP0114 is not set: ExternalProject step targets fully adopt their
+ steps. Run "cmake --help-policy CMP0114" for policy details. Use the
+ cmake_policy command to set the policy and suppress this warning.
+
+ ExternalProject 'FOO' option INDEPENDENT_STEP_TARGETS is set to
+
+ download;patch;update;configure;build
+
+ but the option is deprecated in favor of policy CMP0114.
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(ExternalProject_Add_Step\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_mkdir_command\)
+ NO_DEPENDS-CMP0114-Common.cmake:[0-9]+ \(ExternalProject_Add\)
+ NO_DEPENDS-CMP0114-WARN.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
++
+CMake Warning \(dev\) at [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ Using NO_DEPENDS for "configure" step might break parallel builds
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_step_add_target\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+:EVAL:2 \(ExternalProject_Add_Step\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(cmake_language\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_configure_command\)
+ NO_DEPENDS-CMP0114-Common.cmake:[0-9]+ \(ExternalProject_Add\)
+ NO_DEPENDS-CMP0114-WARN.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
++
+CMake Warning \(dev\) at [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ Using NO_DEPENDS for "build" step might break parallel builds
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_step_add_target\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+:EVAL:2 \(ExternalProject_Add_Step\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(cmake_language\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_build_command\)
+ NO_DEPENDS-CMP0114-Common.cmake:[0-9]+ \(ExternalProject_Add\)
+ NO_DEPENDS-CMP0114-WARN.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
++
+CMake Warning \(dev\) at [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ Policy CMP0114 is not set: ExternalProject step targets fully adopt their
+ steps. Run "cmake --help-policy CMP0114" for policy details. Use the
+ cmake_policy command to set the policy and suppress this warning.
+
+ ExternalProject 'BAR' option INDEPENDENT_STEP_TARGETS is set to
+
+ install
+
+ but the option is deprecated in favor of policy CMP0114.
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(ExternalProject_Add_Step\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_mkdir_command\)
+ NO_DEPENDS-CMP0114-Common.cmake:[0-9]+ \(ExternalProject_Add\)
+ NO_DEPENDS-CMP0114-WARN.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
++
+CMake Warning \(dev\) at [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ Using NO_DEPENDS for "install" step might break parallel builds
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_step_add_target\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+:EVAL:2 \(ExternalProject_Add_Step\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(cmake_language\)
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_install_command\)
+ NO_DEPENDS-CMP0114-Common.cmake:[0-9]+ \(ExternalProject_Add\)
+ NO_DEPENDS-CMP0114-WARN.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
++
+CMake Warning \(dev\) at [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ Policy CMP0114 is not set: ExternalProject step targets fully adopt their
+ steps. Run "cmake --help-policy CMP0114" for policy details. Use the
+ cmake_policy command to set the policy and suppress this warning.
+
+ ExternalProject target 'BAR' would depend on the targets for step\(s\)
+ 'test;bar' under policy CMP0114, but this is being left out for
+ compatibility since the policy is not set. Also, the NO_DEPENDS option is
+ deprecated in favor of policy CMP0114.
+Call Stack \(most recent call first\):
+ NO_DEPENDS-CMP0114-Common.cmake:[0-9]+ \(ExternalProject_Add_StepTargets\)
+ NO_DEPENDS-CMP0114-WARN.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
++
+CMake Warning \(dev\) at [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ Using NO_DEPENDS for "test" step might break parallel builds
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_step_add_target\)
+ NO_DEPENDS-CMP0114-Common.cmake:[0-9]+ \(ExternalProject_Add_StepTargets\)
+ NO_DEPENDS-CMP0114-WARN.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.$
diff --git a/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-WARN.cmake b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-WARN.cmake
new file mode 100644
index 0000000..3d9642d
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-WARN.cmake
@@ -0,0 +1,2 @@
+# Policy CMP0114 not set.
+include(NO_DEPENDS-CMP0114-Common.cmake)
diff --git a/Tests/RunCMake/ExternalProject/NoOptions-result.txt b/Tests/RunCMake/ExternalProject/NoOptions-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/NoOptions-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalProject/NoOptions-stderr.txt b/Tests/RunCMake/ExternalProject/NoOptions-stderr.txt
new file mode 100644
index 0000000..2fc7d29
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/NoOptions-stderr.txt
@@ -0,0 +1,18 @@
+^CMake Error at .*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ No download info given for 'MyProj' and its source directory:
+
+ .*/Tests/RunCMake/ExternalProject/NoOptions-build/MyProj-prefix/src/MyProj
+
+ is not an existing non-empty directory. Please specify one of:
+
+ \* SOURCE_DIR with an existing non-empty directory
+ \* DOWNLOAD_COMMAND
+ \* URL
+ \* GIT_REPOSITORY
+ \* SVN_REPOSITORY
+ \* HG_REPOSITORY
+ \* CVS_REPOSITORY and CVS_MODULE
+Call Stack \(most recent call first\):
+ .*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_download_command\)
+ NoOptions.cmake:[0-9]+ \(ExternalProject_Add\)
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ExternalProject/NoOptions.cmake b/Tests/RunCMake/ExternalProject/NoOptions.cmake
new file mode 100644
index 0000000..7613c15
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/NoOptions.cmake
@@ -0,0 +1,2 @@
+include(ExternalProject)
+ExternalProject_Add(MyProj)
diff --git a/Tests/RunCMake/ExternalProject/PreserveEmptyArgs-build-stdout.txt b/Tests/RunCMake/ExternalProject/PreserveEmptyArgs-build-stdout.txt
new file mode 100644
index 0000000..0e21b8f
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/PreserveEmptyArgs-build-stdout.txt
@@ -0,0 +1,21 @@
+.*-- Number of arguments for download: 6
+.*-- download argument 4: ''
+.*-- download argument 5: 'after'
+.*-- Number of arguments for update: 6
+.*-- update argument 4: ''
+.*-- update argument 5: 'after'
+.*-- Number of arguments for patch: 6
+.*-- patch argument 4: ''
+.*-- patch argument 5: 'after'
+.*-- Number of arguments for configure: 6
+.*-- configure argument 4: ''
+.*-- configure argument 5: 'after'
+.*-- Number of arguments for build: 6
+.*-- build argument 4: ''
+.*-- build argument 5: 'after'
+.*-- Number of arguments for install: 6
+.*-- install argument 4: ''
+.*-- install argument 5: 'after'
+.*-- Number of arguments for test: 6
+.*-- test argument 4: ''
+.*-- test argument 5: 'after'
diff --git a/Tests/RunCMake/ExternalProject/PreserveEmptyArgs.cmake b/Tests/RunCMake/ExternalProject/PreserveEmptyArgs.cmake
new file mode 100644
index 0000000..ded1000
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/PreserveEmptyArgs.cmake
@@ -0,0 +1,13 @@
+include(ExternalProject)
+
+set(script "${CMAKE_CURRENT_LIST_DIR}/countArgs.cmake")
+ExternalProject_Add(
+ blankChecker
+ DOWNLOAD_COMMAND ${CMAKE_COMMAND} -P "${script}" download "" after
+ UPDATE_COMMAND ${CMAKE_COMMAND} -P "${script}" update "" after
+ PATCH_COMMAND ${CMAKE_COMMAND} -P "${script}" patch "" after
+ CONFIGURE_COMMAND ${CMAKE_COMMAND} -P "${script}" configure "" after
+ BUILD_COMMAND ${CMAKE_COMMAND} -P "${script}" build "" after
+ INSTALL_COMMAND ${CMAKE_COMMAND} -P "${script}" install "" after
+ TEST_COMMAND ${CMAKE_COMMAND} -P "${script}" test "" after
+)
diff --git a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
new file mode 100644
index 0000000..3205dd5
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
@@ -0,0 +1,190 @@
+cmake_minimum_required(VERSION 3.12)
+include(RunCMake)
+
+# We do not contact any remote URLs, but may use a local one.
+# Remove any proxy configuration that may change behavior.
+unset(ENV{http_proxy})
+unset(ENV{https_proxy})
+
+run_cmake(BadIndependentStep1)
+run_cmake(BadIndependentStep2)
+run_cmake(NoOptions)
+run_cmake(SourceEmpty)
+run_cmake(SourceMissing)
+run_cmake(CMAKE_CACHE_ARGS)
+run_cmake(CMAKE_CACHE_DEFAULT_ARGS)
+run_cmake(CMAKE_CACHE_mix)
+if(NOT XCODE_VERSION OR XCODE_VERSION VERSION_LESS 12)
+ run_cmake(NO_DEPENDS-CMP0114-WARN)
+ run_cmake(NO_DEPENDS-CMP0114-OLD)
+endif()
+run_cmake(NO_DEPENDS-CMP0114-NEW)
+run_cmake(NO_DEPENDS-CMP0114-NEW-Direct)
+run_cmake(Add_StepDependencies)
+run_cmake(Add_StepDependencies_iface)
+run_cmake(Add_StepDependencies_iface_step)
+run_cmake(Add_StepDependencies_no_target)
+run_cmake(UsesTerminal)
+if(XCODE_VERSION AND XCODE_VERSION VERSION_GREATER_EQUAL 12)
+ run_cmake(Xcode-CMP0114)
+endif()
+
+macro(check_steps_missing proj)
+ set(steps "${ARGN}")
+ foreach(step ${steps})
+ if(EXISTS ${RunCMake_TEST_BINARY_DIR}/${proj}-${step}-mark)
+ string(APPEND RunCMake_TEST_FAILED "${proj} '${step}' step ran but should not have\n")
+ endif()
+ endforeach()
+endmacro()
+
+macro(check_steps_present proj)
+ set(steps "${ARGN}")
+ foreach(step ${steps})
+ if(NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/${proj}-${step}-mark)
+ string(APPEND RunCMake_TEST_FAILED "${proj} '${step}' step did not run but should have\n")
+ endif()
+ endforeach()
+endmacro()
+
+function(run_steps_CMP0114 val)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Steps-CMP0114-${val}-build)
+ run_cmake(Steps-CMP0114-${val})
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(Steps-CMP0114-${val}-build-download ${CMAKE_COMMAND} --build . --target proj1-download)
+ run_cmake_command(Steps-CMP0114-${val}-build-update ${CMAKE_COMMAND} --build . --target proj1-update)
+ run_cmake_command(Steps-CMP0114-${val}-build-install ${CMAKE_COMMAND} --build . --target proj1-install)
+ run_cmake_command(Steps-CMP0114-${val}-build-test ${CMAKE_COMMAND} --build . --target proj1-test)
+endfunction()
+if(NOT XCODE_VERSION OR XCODE_VERSION VERSION_LESS 12)
+ run_steps_CMP0114(OLD)
+endif()
+run_steps_CMP0114(NEW)
+
+# Run both cmake and build steps. We always do a clean before the
+# build to ensure that the download step re-runs each time.
+function(__ep_test_with_build testName)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${testName}-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ run_cmake(${testName})
+ run_cmake_command(${testName}-clean ${CMAKE_COMMAND} --build . --target clean)
+ run_cmake_command(${testName}-build ${CMAKE_COMMAND} --build .)
+endfunction()
+
+find_package(Python3)
+function(__ep_test_with_build_with_server testName)
+ if(NOT Python3_EXECUTABLE)
+ return()
+ endif()
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${testName}-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ set(RunCMake_TEST_TIMEOUT 20)
+ set(RunCMake_TEST_OUTPUT_MERGE TRUE)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ set(URL_FILE ${RunCMake_BINARY_DIR}/${testName}.url)
+ if(EXISTS "${URL_FILE}")
+ file(REMOVE "${URL_FILE}")
+ endif()
+ execute_process(
+ COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/DownloadServer.py --file "${URL_FILE}" ${ARGN}
+ OUTPUT_FILE ${RunCMake_BINARY_DIR}/${testName}-python.txt
+ ERROR_FILE ${RunCMake_BINARY_DIR}/${testName}-python.txt
+ RESULT_VARIABLE result
+ TIMEOUT 30
+ )
+ if(NOT result EQUAL 0)
+ message(FATAL_ERROR "Failed to start download server:\n ${result}")
+ endif()
+
+ foreach(i RANGE 1 8)
+ if(EXISTS ${URL_FILE})
+ break()
+ endif()
+ execute_process(COMMAND ${CMAKE_COMMAND} -E sleep ${i})
+ endforeach()
+
+ if(NOT EXISTS ${URL_FILE})
+ message(FATAL_ERROR "Failed to load download server URL from:\n ${URL_FILE}")
+ endif()
+
+ file(READ ${URL_FILE} SERVER_URL)
+ message(STATUS "URL : ${URL_FILE} - ${SERVER_URL}")
+ run_cmake_with_options(${testName} ${CMAKE_COMMAND} -DSERVER_URL=${SERVER_URL} )
+ run_cmake_command(${testName}-clean ${CMAKE_COMMAND} --build . --target clean)
+ run_cmake_command(${testName}-build ${CMAKE_COMMAND} --build .)
+endfunction()
+
+__ep_test_with_build(MultiCommand)
+
+set(RunCMake_TEST_OUTPUT_MERGE 1)
+__ep_test_with_build(PreserveEmptyArgs)
+set(RunCMake_TEST_OUTPUT_MERGE 0)
+
+# Output is not predictable enough to be able to verify it reliably
+# when using the various different Visual Studio generators
+if(NOT RunCMake_GENERATOR MATCHES "Visual Studio")
+ __ep_test_with_build(LogOutputOnFailure)
+ __ep_test_with_build(LogOutputOnFailureMerged)
+ __ep_test_with_build(DownloadTimeout)
+ __ep_test_with_build_with_server(DownloadInactivityTimeout --speed_limit --limit_duration 40)
+ __ep_test_with_build_with_server(DownloadInactivityResume --speed_limit --limit_duration 1)
+endif()
+
+# We can't test the substitution when using the old MSYS due to
+# make/sh mangling the paths (substitution is performed correctly,
+# but the mangling means we can't reliably test the output).
+# There is no such issue when using the newer MSYS though. Therefore,
+# we need to bypass the substitution test if using old MSYS.
+# See merge request 1537 for discussion.
+set(doSubstitutionTest YES)
+if(RunCMake_GENERATOR STREQUAL "MSYS Makefiles")
+ execute_process(COMMAND uname OUTPUT_VARIABLE uname)
+ if(uname MATCHES "^MINGW32_NT")
+ set(doSubstitutionTest NO)
+ endif()
+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()
+
+find_package(Git QUIET)
+if(GIT_EXECUTABLE)
+ # Note that there appear to be differences in where git writes its output to
+ # on some platforms. It may go to stdout or stderr, so force it to be merged.
+ set(RunCMake_TEST_OUTPUT_MERGE TRUE)
+ run_cmake(FetchGitTags)
+ set(RunCMake_TEST_OUTPUT_MERGE FALSE)
+endif()
diff --git a/Tests/RunCMake/ExternalProject/SourceEmpty-result.txt b/Tests/RunCMake/ExternalProject/SourceEmpty-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/SourceEmpty-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalProject/SourceEmpty-stderr.txt b/Tests/RunCMake/ExternalProject/SourceEmpty-stderr.txt
new file mode 100644
index 0000000..07c6e87
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/SourceEmpty-stderr.txt
@@ -0,0 +1,18 @@
+^CMake Error at .*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ No download info given for 'MyProj' and its source directory:
+
+ .*/Tests/RunCMake/ExternalProject/SourceEmpty-build/SourceEmpty
+
+ is not an existing non-empty directory. Please specify one of:
+
+ \* SOURCE_DIR with an existing non-empty directory
+ \* DOWNLOAD_COMMAND
+ \* URL
+ \* GIT_REPOSITORY
+ \* SVN_REPOSITORY
+ \* HG_REPOSITORY
+ \* CVS_REPOSITORY and CVS_MODULE
+Call Stack \(most recent call first\):
+ .*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_download_command\)
+ SourceEmpty.cmake:[0-9]+ \(ExternalProject_Add\)
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ExternalProject/SourceEmpty.cmake b/Tests/RunCMake/ExternalProject/SourceEmpty.cmake
new file mode 100644
index 0000000..db746e9
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/SourceEmpty.cmake
@@ -0,0 +1,5 @@
+include(ExternalProject)
+set(source_dir "${CMAKE_CURRENT_BINARY_DIR}/SourceEmpty")
+file(REMOVE_RECURSE "${source_dir}")
+file(MAKE_DIRECTORY "${source_dir}")
+ExternalProject_Add(MyProj SOURCE_DIR "${source_dir}")
diff --git a/Tests/RunCMake/ExternalProject/SourceMissing-result.txt b/Tests/RunCMake/ExternalProject/SourceMissing-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/SourceMissing-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalProject/SourceMissing-stderr.txt b/Tests/RunCMake/ExternalProject/SourceMissing-stderr.txt
new file mode 100644
index 0000000..373f6e3
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/SourceMissing-stderr.txt
@@ -0,0 +1,18 @@
+^CMake Error at .*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ No download info given for 'MyProj' and its source directory:
+
+ .*/Tests/RunCMake/ExternalProject/SourceMissing-build/SourceMissing
+
+ is not an existing non-empty directory. Please specify one of:
+
+ \* SOURCE_DIR with an existing non-empty directory
+ \* DOWNLOAD_COMMAND
+ \* URL
+ \* GIT_REPOSITORY
+ \* SVN_REPOSITORY
+ \* HG_REPOSITORY
+ \* CVS_REPOSITORY and CVS_MODULE
+Call Stack \(most recent call first\):
+ .*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_download_command\)
+ SourceMissing.cmake:[0-9]+ \(ExternalProject_Add\)
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ExternalProject/SourceMissing.cmake b/Tests/RunCMake/ExternalProject/SourceMissing.cmake
new file mode 100644
index 0000000..8f369d4
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/SourceMissing.cmake
@@ -0,0 +1,2 @@
+include(ExternalProject)
+ExternalProject_Add(MyProj SOURCE_DIR SourceMissing)
diff --git a/Tests/RunCMake/ExternalProject/Steps-CMP0114-Common.cmake b/Tests/RunCMake/ExternalProject/Steps-CMP0114-Common.cmake
new file mode 100644
index 0000000..210edb1
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Steps-CMP0114-Common.cmake
@@ -0,0 +1,34 @@
+include(ExternalProject)
+
+ExternalProject_Add(proj0
+ SOURCE_DIR "."
+ DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/proj0-download-mark
+ CONFIGURE_COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/proj0-configure-mark
+ BUILD_COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/proj0-build-mark
+ INSTALL_COMMAND ""
+ )
+
+cmake_policy(GET CMP0114 cmp0114)
+if(cmp0114 STREQUAL "NEW")
+ set(step_targets "update;test")
+ set(independent_step_targets "")
+else()
+ set(step_targets "install;test")
+ set(independent_step_targets "download;update")
+endif()
+
+ExternalProject_Add(proj1
+ DEPENDS proj0
+ SOURCE_DIR "."
+ DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/proj1-download-mark
+ UPDATE_COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/proj1-update-mark
+ PATCH_COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/proj1-patch-mark
+ CONFIGURE_COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/proj1-configure-mark
+ BUILD_COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/proj1-build-mark
+ INSTALL_COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/proj1-install-mark
+ TEST_COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/proj1-test-mark
+ TEST_EXCLUDE_FROM_MAIN 1 # Along with 'STEP_TARGETS test', implies 'STEP_TARGETS install'
+ UPDATE_DISCONNECTED 1 # Along with 'STEP_TARGETS update', implies 'STEP_TARGETS download'
+ STEP_TARGETS ${step_targets}
+ INDEPENDENT_STEP_TARGETS ${independent_step_targets}
+ )
diff --git a/Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW-build-download-check.cmake b/Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW-build-download-check.cmake
new file mode 100644
index 0000000..1439f02
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW-build-download-check.cmake
@@ -0,0 +1,3 @@
+check_steps_missing(proj0 download configure build)
+check_steps_present(proj1 download)
+check_steps_missing(proj1 update patch configure build install test)
diff --git a/Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW-build-install-check.cmake b/Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW-build-install-check.cmake
new file mode 100644
index 0000000..c1c9c8f
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW-build-install-check.cmake
@@ -0,0 +1,3 @@
+check_steps_present(proj0 download configure build)
+check_steps_present(proj1 download patch configure build install)
+check_steps_missing(proj1 test)
diff --git a/Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW-build-test-check.cmake b/Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW-build-test-check.cmake
new file mode 100644
index 0000000..fe256f2
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW-build-test-check.cmake
@@ -0,0 +1,2 @@
+check_steps_present(proj0 download configure build)
+check_steps_present(proj1 download patch configure build install test)
diff --git a/Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW-build-update-check.cmake b/Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW-build-update-check.cmake
new file mode 100644
index 0000000..63e2e1d
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW-build-update-check.cmake
@@ -0,0 +1,3 @@
+check_steps_missing(proj0 download configure build)
+check_steps_present(proj1 download update)
+check_steps_missing(proj1 patch configure build install test)
diff --git a/Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW.cmake b/Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW.cmake
new file mode 100644
index 0000000..9d8e99e
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Steps-CMP0114-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0114 NEW)
+include(Steps-CMP0114-Common.cmake)
diff --git a/Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD-build-download-check.cmake b/Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD-build-download-check.cmake
new file mode 100644
index 0000000..1439f02
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD-build-download-check.cmake
@@ -0,0 +1,3 @@
+check_steps_missing(proj0 download configure build)
+check_steps_present(proj1 download)
+check_steps_missing(proj1 update patch configure build install test)
diff --git a/Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD-build-install-check.cmake b/Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD-build-install-check.cmake
new file mode 100644
index 0000000..c1c9c8f
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD-build-install-check.cmake
@@ -0,0 +1,3 @@
+check_steps_present(proj0 download configure build)
+check_steps_present(proj1 download patch configure build install)
+check_steps_missing(proj1 test)
diff --git a/Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD-build-test-check.cmake b/Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD-build-test-check.cmake
new file mode 100644
index 0000000..fe256f2
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD-build-test-check.cmake
@@ -0,0 +1,2 @@
+check_steps_present(proj0 download configure build)
+check_steps_present(proj1 download patch configure build install test)
diff --git a/Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD-build-update-check.cmake b/Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD-build-update-check.cmake
new file mode 100644
index 0000000..63e2e1d
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD-build-update-check.cmake
@@ -0,0 +1,3 @@
+check_steps_missing(proj0 download configure build)
+check_steps_present(proj1 download update)
+check_steps_missing(proj1 patch configure build install test)
diff --git a/Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD.cmake b/Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD.cmake
new file mode 100644
index 0000000..0b51ad8
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Steps-CMP0114-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0114 OLD)
+include(Steps-CMP0114-Common.cmake)
diff --git a/Tests/RunCMake/ExternalProject/Substitutions-build-stdout.txt b/Tests/RunCMake/ExternalProject/Substitutions-build-stdout.txt
new file mode 100644
index 0000000..d6a823a
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Substitutions-build-stdout.txt
@@ -0,0 +1,7 @@
+.*Download dir = .*/xxxx_dwn
+.*Download file = .*/zzzz_tmp.txt
+.*Source dir = .*/xxxx_src
+.*Source subdir = /yyyy_subdir
+.*Binary dir = .*/xxxx_bin
+.*Install dir = .*/xxxx_install
+.*Tmp dir = .*/xxxx_tmp
diff --git a/Tests/RunCMake/ExternalProject/Substitutions.cmake b/Tests/RunCMake/ExternalProject/Substitutions.cmake
new file mode 100644
index 0000000..db79491
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Substitutions.cmake
@@ -0,0 +1,25 @@
+include(ExternalProject)
+
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/zzzz_tmp.txt "Dummy file")
+file(MD5 ${CMAKE_CURRENT_BINARY_DIR}/zzzz_tmp.txt md5hash)
+ExternalProject_Add(Subst
+ URL file://${CMAKE_CURRENT_BINARY_DIR}/zzzz_tmp.txt
+ URL_HASH MD5=${md5hash}
+ DOWNLOAD_NO_EXTRACT ON
+ DOWNLOAD_DIR ${CMAKE_CURRENT_BINARY_DIR}/xxxx_dwn
+ SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/xxxx_src
+ SOURCE_SUBDIR yyyy_subdir
+ BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/xxxx_bin
+ INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/xxxx_install
+ TMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/xxxx_tmp
+ CONFIGURE_COMMAND ${CMAKE_COMMAND} -E echo "Download dir = <DOWNLOAD_DIR>"
+ COMMAND ${CMAKE_COMMAND} -E echo "Download file = <DOWNLOADED_FILE>"
+ COMMAND ${CMAKE_COMMAND} -E echo "Source dir = <SOURCE_DIR>"
+ COMMAND ${CMAKE_COMMAND} -E echo "Source subdir = <SOURCE_SUBDIR>"
+ COMMAND ${CMAKE_COMMAND} -E echo "Binary dir = <BINARY_DIR>"
+ COMMAND ${CMAKE_COMMAND} -E echo "Install dir = <INSTALL_DIR>"
+ COMMAND ${CMAKE_COMMAND} -E echo "Tmp dir = <TMP_DIR>"
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ TEST_COMMAND ""
+)
diff --git a/Tests/RunCMake/ExternalProject/UsesTerminal-check.cmake b/Tests/RunCMake/ExternalProject/UsesTerminal-check.cmake
new file mode 100644
index 0000000..201d822
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/UsesTerminal-check.cmake
@@ -0,0 +1,97 @@
+cmake_minimum_required(VERSION 3.3)
+
+# If we are using the Ninja generator, we can check and verify that the
+# USES_TERMINAL option actually works by examining the Ninja build file.
+# This is the only way, since CMake doesn't offer a way to examine the
+# options on a custom command after it has been added. Furthermore,
+# there isn't an easy way to test for this by actually running Ninja.
+#
+# Other generators don't currently support USES_TERMINAL at this time.
+# This file can be improved to support them if they do. Until then, we
+# simply assume success for new generator types.
+#
+# For Ninja, there is a complication. If the Ninja generator detects a
+# version of Ninja < 1.5, it won't actually emit the console pool command,
+# because those Ninja versions don't yet support the console pool. In
+# that case, we also have to assume success.
+
+# Check Ninja build output to verify whether or not a target step is in the
+# console pool.
+macro(CheckNinjaStep _target _step _require)
+ if("${_build}" MATCHES
+" DESC = Performing ${_step} step for '${_target}'
+ pool = console"
+ )
+ if(NOT ${_require})
+ set(RunCMake_TEST_FAILED "${_target} ${_step} step is in console pool")
+ return()
+ endif()
+ else()
+ if(${_require})
+ set(RunCMake_TEST_FAILED "${_target} ${_step} step not in console pool")
+ return()
+ endif()
+ endif()
+endmacro()
+
+# Check Ninja build output to verify whether each target step is in the
+# console pool.
+macro(CheckNinjaTarget _target
+ _download _update _configure _build _test _install
+ )
+ CheckNinjaStep(${_target} download ${_download})
+ CheckNinjaStep(${_target} update ${_update})
+ CheckNinjaStep(${_target} configure ${_configure})
+ CheckNinjaStep(${_target} build ${_build})
+ CheckNinjaStep(${_target} test ${_test})
+ CheckNinjaStep(${_target} install ${_install})
+endmacro()
+
+# Load build/make file, depending on generator
+if(RunCMake_GENERATOR STREQUAL Ninja)
+ # Check the Ninja version. If < 1.5, console pool isn't supported and
+ # so the generator would not emit console pool usage. That would cause
+ # this test to fail.
+ execute_process(COMMAND ${RunCMake_MAKE_PROGRAM} --version
+ RESULT_VARIABLE _version_result
+ OUTPUT_VARIABLE _version
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ if(_version_result OR _version VERSION_EQUAL "0")
+ set(RunCMake_TEST_FAILED "Failed to get Ninja version")
+ return()
+ endif()
+ if(_version VERSION_LESS "1.5")
+ return() # console pool not supported on Ninja < 1.5
+ endif()
+
+ # Read the Ninja build file
+ set(_build_file "${RunCMake_TEST_BINARY_DIR}/build.ninja")
+
+ if(NOT EXISTS "${_build_file}")
+ set(RunCMake_TEST_FAILED "Ninja build file not created")
+ return()
+ endif()
+
+ file(READ "${_build_file}" _build)
+
+ set(_target_check_macro CheckNinjaTarget)
+elseif((RunCMake_GENERATOR STREQUAL "") OR NOT DEFINED RunCMake_GENERATOR)
+ # protection in case somebody renamed RunCMake_GENERATOR
+ set(RunCMake_TEST_FAILED "Unknown generator")
+ return()
+else()
+ # We don't yet know how to test USES_TERMINAL on this generator.
+ return()
+endif()
+
+# Actual tests:
+CheckNinjaTarget(TerminalTest1
+ true true true true true true )
+CheckNinjaTarget(TerminalTest2
+ true false true false true false)
+CheckNinjaTarget(TerminalTest3
+ false true false true false true )
+CheckNinjaTarget(TerminalTest4
+ false false false false false false)
diff --git a/Tests/RunCMake/ExternalProject/UsesTerminal.cmake b/Tests/RunCMake/ExternalProject/UsesTerminal.cmake
new file mode 100644
index 0000000..d3494fd
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/UsesTerminal.cmake
@@ -0,0 +1,46 @@
+get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(NOT _isMultiConfig)
+ set(CMAKE_BUILD_TYPE Debug)
+endif()
+include(ExternalProject)
+
+# Test various combinations of USES_TERMINAL with ExternalProject_Add.
+
+macro(DoTerminalTest _target)
+ ExternalProject_Add(${_target}
+ DOWNLOAD_COMMAND "${CMAKE_COMMAND}" -E echo "download"
+ UPDATE_COMMAND "${CMAKE_COMMAND}" -E echo "update"
+ CONFIGURE_COMMAND "${CMAKE_COMMAND}" -E echo "configure"
+ BUILD_COMMAND "${CMAKE_COMMAND}" -E echo "build"
+ TEST_COMMAND "${CMAKE_COMMAND}" -E echo "test"
+ INSTALL_COMMAND "${CMAKE_COMMAND}" -E echo "install"
+ ${ARGN}
+ )
+endmacro()
+
+# USES_TERMINAL on all steps
+DoTerminalTest(TerminalTest1
+ USES_TERMINAL_DOWNLOAD 1
+ USES_TERMINAL_UPDATE 1
+ USES_TERMINAL_CONFIGURE 1
+ USES_TERMINAL_BUILD 1
+ USES_TERMINAL_TEST 1
+ USES_TERMINAL_INSTALL 1
+ )
+
+# USES_TERMINAL on every other step, starting with download
+DoTerminalTest(TerminalTest2
+ USES_TERMINAL_DOWNLOAD 1
+ USES_TERMINAL_CONFIGURE 1
+ USES_TERMINAL_TEST 1
+ )
+
+# USES_TERMINAL on every other step, starting with update
+DoTerminalTest(TerminalTest3
+ USES_TERMINAL_UPDATE 1
+ USES_TERMINAL_BUILD 1
+ USES_TERMINAL_INSTALL 1
+ )
+
+# USES_TERMINAL on no step
+DoTerminalTest(TerminalTest4)
diff --git a/Tests/RunCMake/ExternalProject/Xcode-CMP0114-stderr.txt b/Tests/RunCMake/ExternalProject/Xcode-CMP0114-stderr.txt
new file mode 100644
index 0000000..a616185
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Xcode-CMP0114-stderr.txt
@@ -0,0 +1,11 @@
+^CMake Warning \(dev\) at .*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ Policy CMP0114 is not set to NEW. In order to support the Xcode "new build
+ system", this project must be updated to set policy CMP0114 to NEW.
+
+ Since CMake is generating for the Xcode "new build system",
+ ExternalProject_Add will use policy CMP0114's NEW behavior anyway, but the
+ generated build system may not match what the project intends.
+Call Stack \(most recent call first\):
+ Xcode-CMP0114.cmake:[0-9]+ \(ExternalProject_Add\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.$
diff --git a/Tests/RunCMake/ExternalProject/Xcode-CMP0114.cmake b/Tests/RunCMake/ExternalProject/Xcode-CMP0114.cmake
new file mode 100644
index 0000000..5039daa
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/Xcode-CMP0114.cmake
@@ -0,0 +1,2 @@
+include(ExternalProject)
+ExternalProject_Add(MyProj SOURCE_DIR .)
diff --git a/Tests/RunCMake/ExternalProject/countArgs.cmake b/Tests/RunCMake/ExternalProject/countArgs.cmake
new file mode 100644
index 0000000..ee6429a
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/countArgs.cmake
@@ -0,0 +1,5 @@
+message(STATUS "Number of arguments for ${CMAKE_ARGV3}: ${CMAKE_ARGC}")
+math(EXPR last "${CMAKE_ARGC} - 1")
+foreach(n RANGE 4 ${last})
+ message(STATUS "${CMAKE_ARGV3} argument ${n}: '${CMAKE_ARGV${n}}'")
+endforeach()