RunCMakeTest.cmake 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. cmake_minimum_required(VERSION 3.12)
  2. include(RunCMake)
  3. # We do not contact any remote URLs, but may use a local one.
  4. # Remove any proxy configuration that may change behavior.
  5. unset(ENV{http_proxy})
  6. unset(ENV{https_proxy})
  7. if(RunCMake_GENERATOR STREQUAL "Borland Makefiles" OR
  8. RunCMake_GENERATOR STREQUAL "Watcom WMake")
  9. set(fs_delay 3)
  10. else()
  11. set(fs_delay 1.125)
  12. endif()
  13. run_cmake(BadIndependentStep1)
  14. run_cmake(BadIndependentStep2)
  15. run_cmake(NoOptions)
  16. run_cmake(SourceEmpty)
  17. run_cmake(SourceMissing)
  18. run_cmake(SourceDirExisting)
  19. run_cmake(CMAKE_CACHE_ARGS)
  20. run_cmake(CMAKE_CACHE_DEFAULT_ARGS)
  21. run_cmake(CMAKE_CACHE_mix)
  22. if(NOT XCODE_VERSION OR XCODE_VERSION VERSION_LESS 12)
  23. run_cmake(NO_DEPENDS-CMP0114-WARN)
  24. run_cmake(NO_DEPENDS-CMP0114-OLD)
  25. endif()
  26. run_cmake(NO_DEPENDS-CMP0114-NEW)
  27. run_cmake(NO_DEPENDS-CMP0114-NEW-Direct)
  28. run_cmake(Add_StepDependencies)
  29. run_cmake(Add_StepDependencies_iface)
  30. run_cmake(Add_StepDependencies_iface_step)
  31. run_cmake(Add_StepDependencies_no_target)
  32. run_cmake(UsesTerminal)
  33. if(XCODE_VERSION AND XCODE_VERSION VERSION_GREATER_EQUAL 12)
  34. run_cmake(Xcode-CMP0114)
  35. endif()
  36. macro(check_steps_missing proj)
  37. set(steps "${ARGN}")
  38. foreach(step ${steps})
  39. if(EXISTS ${RunCMake_TEST_BINARY_DIR}/${proj}-${step}-mark)
  40. string(APPEND RunCMake_TEST_FAILED "${proj} '${step}' step ran but should not have\n")
  41. endif()
  42. endforeach()
  43. endmacro()
  44. macro(check_steps_present proj)
  45. set(steps "${ARGN}")
  46. foreach(step ${steps})
  47. if(NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/${proj}-${step}-mark)
  48. string(APPEND RunCMake_TEST_FAILED "${proj} '${step}' step did not run but should have\n")
  49. endif()
  50. endforeach()
  51. endmacro()
  52. function(run_steps_CMP0114 val)
  53. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Steps-CMP0114-${val}-build)
  54. run_cmake(Steps-CMP0114-${val})
  55. set(RunCMake_TEST_NO_CLEAN 1)
  56. run_cmake_command(Steps-CMP0114-${val}-build-download ${CMAKE_COMMAND} --build . --target proj1-download)
  57. run_cmake_command(Steps-CMP0114-${val}-build-update ${CMAKE_COMMAND} --build . --target proj1-update)
  58. run_cmake_command(Steps-CMP0114-${val}-build-install ${CMAKE_COMMAND} --build . --target proj1-install)
  59. run_cmake_command(Steps-CMP0114-${val}-build-test ${CMAKE_COMMAND} --build . --target proj1-test)
  60. endfunction()
  61. if(NOT XCODE_VERSION OR XCODE_VERSION VERSION_LESS 12)
  62. run_steps_CMP0114(OLD)
  63. endif()
  64. run_steps_CMP0114(NEW)
  65. function(__ep_test_source_dir_change)
  66. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SourceDirChange-build)
  67. set(RunCMake_TEST_NO_CLEAN 1)
  68. file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
  69. file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
  70. run_cmake(SourceDirChange)
  71. run_cmake_command(SourceDirChange-build1 ${CMAKE_COMMAND} --build .)
  72. # Because some file systems have timestamps with only one second resolution,
  73. # we have to ensure we don't re-run the configure stage too quickly after the
  74. # first build. Otherwise, the modified RepositoryInfo.txt files the next
  75. # configure writes might still have the same timestamp as the previous one.
  76. execute_process(COMMAND ${CMAKE_COMMAND} -E sleep ${fs_delay})
  77. run_cmake_command(SourceDirChange-change ${CMAKE_COMMAND} -DSOURCE_DIR_CHANGE=YES .)
  78. run_cmake_command(SourceDirChange-build2 ${CMAKE_COMMAND} --build .)
  79. endfunction()
  80. __ep_test_source_dir_change()
  81. # Run both cmake and build steps. We always do a clean before the
  82. # build to ensure that the download step re-runs each time.
  83. function(__ep_test_with_build testName)
  84. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${testName}-build)
  85. set(RunCMake_TEST_NO_CLEAN 1)
  86. file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
  87. file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
  88. run_cmake(${testName})
  89. run_cmake_command(${testName}-clean ${CMAKE_COMMAND} --build . --target clean)
  90. run_cmake_command(${testName}-build ${CMAKE_COMMAND} --build .)
  91. endfunction()
  92. find_package(Python3)
  93. function(__ep_test_with_build_with_server testName)
  94. if(NOT Python3_EXECUTABLE)
  95. return()
  96. endif()
  97. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${testName}-build)
  98. set(RunCMake_TEST_NO_CLEAN 1)
  99. set(RunCMake_TEST_TIMEOUT 20)
  100. set(RunCMake_TEST_OUTPUT_MERGE TRUE)
  101. file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
  102. file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
  103. set(URL_FILE ${RunCMake_BINARY_DIR}/${testName}.url)
  104. if(EXISTS "${URL_FILE}")
  105. file(REMOVE "${URL_FILE}")
  106. endif()
  107. if(NOT DOWNLOAD_SERVER_TIMEOUT)
  108. set(DOWNLOAD_SERVER_TIMEOUT 30)
  109. endif()
  110. execute_process(
  111. COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/DownloadServer.py --file "${URL_FILE}" ${ARGN}
  112. OUTPUT_FILE ${RunCMake_BINARY_DIR}/${testName}-python.txt
  113. ERROR_FILE ${RunCMake_BINARY_DIR}/${testName}-python.txt
  114. RESULT_VARIABLE result
  115. TIMEOUT "${DOWNLOAD_SERVER_TIMEOUT}"
  116. )
  117. if(NOT result EQUAL 0)
  118. message(FATAL_ERROR "Failed to start download server:\n ${result}")
  119. endif()
  120. foreach(i RANGE 1 8)
  121. if(EXISTS ${URL_FILE})
  122. break()
  123. endif()
  124. execute_process(COMMAND ${CMAKE_COMMAND} -E sleep ${i})
  125. endforeach()
  126. if(NOT EXISTS ${URL_FILE})
  127. message(FATAL_ERROR "Failed to load download server URL from:\n ${URL_FILE}")
  128. endif()
  129. file(READ ${URL_FILE} SERVER_URL)
  130. message(STATUS "URL : ${URL_FILE} - ${SERVER_URL}")
  131. run_cmake_with_options(${testName} -DSERVER_URL=${SERVER_URL})
  132. run_cmake_command(${testName}-clean ${CMAKE_COMMAND} --build . --target clean)
  133. run_cmake_command(${testName}-build ${CMAKE_COMMAND} --build .)
  134. endfunction()
  135. if(RunCMake_GENERATOR MATCHES "(MSYS|MinGW|Unix) Makefiles")
  136. __ep_test_with_build(GNUMakeJobServerAware)
  137. endif()
  138. function(__ep_test_jobserver)
  139. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/DetectJobServer-build)
  140. set(RunCMake_TEST_NO_CLEAN 1)
  141. file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
  142. file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
  143. run_cmake_with_options(DetectJobServer -DDETECT_JOBSERVER=${DETECT_JOBSERVER})
  144. run_cmake_command(DetectJobServer-clean ${CMAKE_COMMAND} --build . --target clean)
  145. run_cmake_command(DetectJobServer-build ${CMAKE_COMMAND} --build . -j4)
  146. endfunction()
  147. if(RunCMake_GENERATOR MATCHES "(MinGW|Unix) Makefiles")
  148. __ep_test_jobserver()
  149. endif()
  150. __ep_test_with_build(MultiCommand)
  151. set(RunCMake_TEST_OUTPUT_MERGE 1)
  152. __ep_test_with_build(InstallBuilds)
  153. __ep_test_with_build(PreserveEmptyArgs)
  154. set(RunCMake_TEST_OUTPUT_MERGE 0)
  155. # Output is not predictable enough to be able to verify it reliably
  156. # when using the various different Visual Studio generators
  157. if(NOT RunCMake_GENERATOR MATCHES "Visual Studio")
  158. __ep_test_with_build(LogOutputOnFailure)
  159. __ep_test_with_build(LogOutputOnFailureMerged)
  160. __ep_test_with_build(DownloadTimeout)
  161. __ep_test_with_build_with_server(DownloadInactivityTimeout --speed_limit --limit_duration 40)
  162. __ep_test_with_build_with_server(DownloadInactivityResume --speed_limit --limit_duration 1)
  163. endif()
  164. # We can't test the substitution when using the old MSYS due to
  165. # make/sh mangling the paths (substitution is performed correctly,
  166. # but the mangling means we can't reliably test the output).
  167. # There is no such issue when using the newer MSYS though. Therefore,
  168. # we need to bypass the substitution test if using old MSYS.
  169. # See merge request 1537 for discussion.
  170. set(doSubstitutionTest YES)
  171. if(RunCMake_GENERATOR STREQUAL "MSYS Makefiles")
  172. execute_process(COMMAND uname OUTPUT_VARIABLE uname)
  173. if(uname MATCHES "^MINGW32_NT")
  174. set(doSubstitutionTest NO)
  175. endif()
  176. endif()
  177. if(doSubstitutionTest)
  178. __ep_test_with_build(Substitutions)
  179. endif()
  180. function(__ep_test_BUILD_ALWAYS)
  181. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/BUILD_ALWAYS-build)
  182. run_cmake(BUILD_ALWAYS)
  183. set(RunCMake_TEST_NO_CLEAN 1)
  184. file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-configure.cmake" [[message(STATUS "once: configure")]])
  185. file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-build.cmake" [[message(STATUS "once: build")]])
  186. file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-install.cmake" [[message(STATUS "once: install")]])
  187. file(WRITE "${RunCMake_TEST_BINARY_DIR}/always-configure.cmake" [[message(STATUS "always: configure")]])
  188. file(WRITE "${RunCMake_TEST_BINARY_DIR}/always-build.cmake" [[message(STATUS "always: build")]])
  189. file(WRITE "${RunCMake_TEST_BINARY_DIR}/always-install.cmake" [[message(STATUS "always: install")]])
  190. run_cmake_command(BUILD_ALWAYS-build1 ${CMAKE_COMMAND} --build . --target always)
  191. file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-configure.cmake" [[message(FATAL_ERROR "once: configure should not run again")]])
  192. file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-build.cmake" [[message(FATAL_ERROR "once: build should not run again")]])
  193. file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-install.cmake" [[message(FATAL_ERROR "once: install should not run again")]])
  194. if(NOT RunCMake_GENERATOR STREQUAL "Xcode")
  195. # The Xcode and VS 9 build systems decide to run this every time.
  196. file(WRITE "${RunCMake_TEST_BINARY_DIR}/always-configure.cmake" [[message(FATAL_ERROR "always: configure should not run again")]])
  197. endif()
  198. run_cmake_command(BUILD_ALWAYS-build2 ${CMAKE_COMMAND} --build . --target always)
  199. endfunction()
  200. __ep_test_BUILD_ALWAYS()
  201. function(__ep_test_CONFIGURE_HANDLED_BY_BUILD)
  202. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CONFIGURE_HANDLED_BY_BUILD-build)
  203. run_cmake(CONFIGURE_HANDLED_BY_BUILD)
  204. if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
  205. set(BUILD_CONFIG --config Debug)
  206. set(STAMP_DIR "${RunCMake_TEST_BINARY_DIR}/stamp/Debug")
  207. else()
  208. set(BUILD_CONFIG "")
  209. set(STAMP_DIR "${RunCMake_TEST_BINARY_DIR}/stamp")
  210. endif()
  211. set(RunCMake_TEST_NO_CLEAN 1)
  212. run_cmake_command(CONFIGURE_HANDLED_BY_BUILD-build ${CMAKE_COMMAND} --build . ${BUILD_CONFIG})
  213. # Calculate timestamps before rebuilding so we can compare before and after in
  214. # CONFIGURE_HANDLED_BY_BUILD-rebuild-check.cmake
  215. file(TIMESTAMP "${STAMP_DIR}/proj1-configure" PROJ1_CONFIGURE_TIMESTAMP_BEFORE "%s")
  216. # When BUILD_ALWAYS is set, the build stamp is never created.
  217. file(TIMESTAMP "${STAMP_DIR}/proj2-configure" PROJ2_CONFIGURE_TIMESTAMP_BEFORE "%s")
  218. file(TIMESTAMP "${STAMP_DIR}/proj2-build" PROJ2_BUILD_TIMESTAMP_BEFORE "%s")
  219. run_cmake_command(CONFIGURE_HANDLED_BY_BUILD-rebuild ${CMAKE_COMMAND} --build . ${BUILD_CONFIG})
  220. endfunction()
  221. __ep_test_CONFIGURE_HANDLED_BY_BUILD()
  222. find_package(Git QUIET)
  223. if(GIT_EXECUTABLE)
  224. # Note that there appear to be differences in where git writes its output to
  225. # on some platforms. It may go to stdout or stderr, so force it to be merged.
  226. set(RunCMake_TEST_OUTPUT_MERGE TRUE)
  227. run_cmake(FetchGitRefs)
  228. unset(RunCMake_TEST_OUTPUT_MERGE)
  229. run_cmake(TLSVersionBadArg)
  230. run_cmake(TLSVersionBadVar)
  231. run_cmake(TLSVersionBadEnv)
  232. endif()
  233. set(RunCMake_TEST_OUTPUT_MERGE 1)
  234. __ep_test_with_build(EnvVars)
  235. unset(RunCMake_TEST_OUTPUT_MERGE)
  236. run_cmake(InvalidEnvModification)