utils.cmake 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. function(run_make_program dir)
  2. execute_process(
  3. COMMAND "${RunCMake_MAKE_PROGRAM}" ${ARGN}
  4. WORKING_DIRECTORY "${dir}"
  5. OUTPUT_VARIABLE make_program_stdout
  6. ERROR_VARIABLE make_program_stderr
  7. RESULT_VARIABLE make_program_result
  8. )
  9. if (NOT DEFINED RunMakeProgram_expected_result)
  10. set(RunMakeProgram_expected_result 0)
  11. endif()
  12. if(NOT "${make_program_result}" MATCHES "${RunMakeProgram_expected_result}")
  13. message(STATUS "
  14. ============ beginning of ${RunCMake_MAKE_PROGRAM}'s stdout ============
  15. ${make_program_stdout}
  16. =============== end of ${RunCMake_MAKE_PROGRAM}'s stdout ===============
  17. ")
  18. message(STATUS "
  19. ============ beginning of ${RunCMake_MAKE_PROGRAM}'s stderr ============
  20. ${make_program_stderr}
  21. =============== end of ${RunCMake_MAKE_PROGRAM}'s stderr ===============
  22. ")
  23. message(FATAL_ERROR
  24. "top ${RunCMake_MAKE_PROGRAM} build failed exited with status ${make_program_result}")
  25. endif()
  26. set(make_program_stdout "${make_program_stdout}" PARENT_SCOPE)
  27. endfunction(run_make_program)
  28. function(count_substring STRING SUBSTRING COUNT_VAR)
  29. string(LENGTH "${STRING}" STRING_LENGTH)
  30. string(LENGTH "${SUBSTRING}" SUBSTRING_LENGTH)
  31. if (SUBSTRING_LENGTH EQUAL 0)
  32. message(FATAL_ERROR "SUBSTRING_LENGTH is 0")
  33. endif()
  34. if (STRING_LENGTH EQUAL 0)
  35. message(FATAL_ERROR "STRING_LENGTH is 0")
  36. endif()
  37. if (STRING_LENGTH LESS SUBSTRING_LENGTH)
  38. message(FATAL_ERROR "STRING_LENGTH is less than SUBSTRING_LENGTH")
  39. endif()
  40. set(COUNT 0)
  41. string(FIND "${STRING}" "${SUBSTRING}" SUBSTRING_START)
  42. while(SUBSTRING_START GREATER_EQUAL 0)
  43. math(EXPR COUNT "${COUNT} + 1")
  44. math(EXPR SUBSTRING_START "${SUBSTRING_START} + ${SUBSTRING_LENGTH}")
  45. string(SUBSTRING "${STRING}" ${SUBSTRING_START} -1 STRING)
  46. string(FIND "${STRING}" "${SUBSTRING}" SUBSTRING_START)
  47. endwhile()
  48. set(${COUNT_VAR} ${COUNT} PARENT_SCOPE)
  49. endfunction()
  50. function(not_expect make_program_stdout unexpected_output test_name)
  51. count_substring("${make_program_stdout}" "${unexpected_output}" count)
  52. if(NOT count EQUAL 0)
  53. message(STATUS "${test_name}-not_expect - FAILED")
  54. message(FATAL_ERROR "Expected to find ${unexpected_output} exactly 0 times in ${make_program_stdout} but found ${count} occurrences of ${unexpected_output}")
  55. else()
  56. message(STATUS "${test_name}-not_expect - PASSED")
  57. endif()
  58. endfunction()
  59. function(expect_only_once make_program_stdout expected_output test_name)
  60. count_substring("${make_program_stdout}" "${expected_output}" count)
  61. if(NOT count EQUAL 1)
  62. message(STATUS "${test_name}-expect_only_once - FAILED")
  63. message(FATAL_ERROR "Expected to find ${expected_output} exactly once in ${make_program_stdout} but found ${count} occurrences of ${expected_output}")
  64. else()
  65. message(STATUS "${test_name}-expect_only_once - PASSED")
  66. endif()
  67. endfunction()
  68. function(expect_n_times string_to_check expected_output expected_count test_name)
  69. count_substring("${string_to_check}" "${expected_output}" count)
  70. if(NOT count EQUAL ${expected_count})
  71. message(STATUS "${test_name}-expect_${expected_count}_times - FAILED")
  72. message(FATAL_ERROR "Expected to find ${expected_output} exactly ${expected_count} times in ${string_to_check} but found ${count} occurrences of ${expected_output}")
  73. else()
  74. message(STATUS "${test_name}-expect_${expected_count}_times - PASSED")
  75. endif()
  76. endfunction()
  77. function(autogen_executable_test exe)
  78. if (QtCore_VERSION VERSION_GREATER_EQUAL 5.15.0)
  79. if(RunCMake_GENERATOR MATCHES "Ninja Multi-Config")
  80. block()
  81. set(RunCMake_TEST_VARIANT_DESCRIPTION "-CMake-configure")
  82. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Auto${exe}ExecutableConfig-multi-config-build)
  83. run_cmake_with_options(Auto${exe}ExecutableConfig ${RunCMake_TEST_OPTIONS} -DCMAKE_AUTOGEN_VERBOSE=ON -DCMAKE_AUTOGEN_BETTER_GRAPH_MULTI_CONFIG=ON)
  84. unset(RunCMake_TEST_VARIANT_DESCRIPTION)
  85. set(RunCMake_TEST_NO_CLEAN 1)
  86. foreach(config IN ITEMS Debug Release RelWithDebInfo)
  87. block()
  88. set(RunCMake_TEST_EXPECT_stdout ".*running_exe_${config}*")
  89. set(RunCMake_TEST_VARIANT_DESCRIPTION "-${config}-expect_running_exe_${config}")
  90. run_cmake_command(Auto${exe}ExecutableConfig-multi-config-build ${CMAKE_COMMAND} --build . --config ${config})
  91. endblock()
  92. endforeach()
  93. set(RunCMake_TEST_EXPECT_stdout "ninja: no work to do")
  94. foreach(config IN ITEMS Debug Release RelWithDebInfo)
  95. block()
  96. set(RunCMake_TEST_VARIANT_DESCRIPTION "-${config}-expect_no_work_to_do")
  97. run_cmake_command(Auto${exe}ExecutableConfig-multi-config-build ${CMAKE_COMMAND} --build . --config ${config})
  98. endblock()
  99. endforeach()
  100. endblock()
  101. block()
  102. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Auto${exe}ExecutableConfig-build)
  103. run_cmake_with_options(Auto${exe}ExecutableConfig ${RunCMake_TEST_OPTIONS} -DCMAKE_AUTOGEN_VERBOSE=ON -DCMAKE_AUTOGEN_BETTER_GRAPH_MULTI_CONFIG=ON)
  104. foreach(config IN ITEMS Debug Release RelWithDebInfo)
  105. block()
  106. run_make_program(${RunCMake_TEST_BINARY_DIR} --verbose -f build-${config}.ninja)
  107. set(expected_output "running_exe_${config}")
  108. expect_only_once("${make_program_stdout}" "${expected_output}" "Auto${exe}ExecutableConfig-${config}-${expected_output}")
  109. foreach(sub_config IN ITEMS Debug Release RelWithDebInfo)
  110. if(NOT sub_config STREQUAL config)
  111. set(unexpected_output "running_exe_${sub_config}")
  112. not_expect("${make_program_stdout}" "${unexpected_output}" "Auto${exe}ExecutableConfig-${config}-${unexpected_output}")
  113. endif()
  114. endforeach()
  115. if (exe STREQUAL "Moc" OR exe STREQUAL "Uic")
  116. set(expected_output "cmake_autogen")
  117. else()
  118. set(expected_output "cmake_autorcc")
  119. endif()
  120. expect_only_once("${make_program_stdout}" "${expected_output}" "Auto${exe}ExecutableConfig-${config}-${expected_output}")
  121. endblock()
  122. endforeach()
  123. endblock()
  124. block()
  125. foreach(ninja_config IN ITEMS Debug Release RelWithDebInfo)
  126. foreach(target_config IN ITEMS Debug Release RelWithDebInfo)
  127. block()
  128. set(TEST_SUFFIX "-CrossConfig-${ninja_config}-${target_config}")
  129. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Auto${exe}ExecutableConfig${TEST_SUFFIX}-build)
  130. set(RunCMake_TEST_VARIANT_DESCRIPTION ${TEST_SUFFIX})
  131. run_cmake_with_options(Auto${exe}ExecutableConfig ${RunCMake_TEST_OPTIONS} -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=${ninja_config} -DCMAKE_AUTOGEN_BETTER_GRAPH_MULTI_CONFIG=ON)
  132. unset(RunCMake_TEST_VARIANT_DESCRIPTION)
  133. run_make_program(${RunCMake_TEST_BINARY_DIR} --verbose -f build-${ninja_config}.ninja dummy:${target_config})
  134. set(expected_output "running_exe_${ninja_config}")
  135. expect_only_once("${make_program_stdout}" "${expected_output}" "Auto${exe}ExecutableConfig${TEST_SUFFIX}-${expected_output}")
  136. foreach(sub_config IN ITEMS Debug Release RelWithDebInfo)
  137. if(NOT sub_config STREQUAL ninja_config)
  138. set(unexpected_output "running_exe_${sub_config}")
  139. not_expect("${make_program_stdout}" "${unexpected_output}" "Auto${exe}ExecutableConfig${TEST_SUFFIX}-${unexpected_output}")
  140. endif()
  141. endforeach()
  142. if (exe STREQUAL "Moc" OR exe STREQUAL "Uic")
  143. set(expected_output "cmake_autogen")
  144. else()
  145. set(expected_output "cmake_autorcc")
  146. endif()
  147. expect_only_once("${make_program_stdout}" "${expected_output}" "Auto${exe}ExecutableConfig${TEST_SUFFIX}-${expected_output}")
  148. endblock()
  149. endforeach()
  150. endforeach()
  151. endblock()
  152. block()
  153. foreach(ninja_config IN ITEMS Debug Release RelWithDebInfo)
  154. set(TEST_SUFFIX "-CrossConfig-${ninja_config}-all-all")
  155. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Auto${exe}ExecutableConfig${TEST_SUFFIX}-build)
  156. set(RunCMake_TEST_VARIANT_DESCRIPTION ${TEST_SUFFIX})
  157. run_cmake_with_options(Auto${exe}ExecutableConfig ${RunCMake_TEST_OPTIONS} -DCMAKE_CROSS_CONFIGS=all -DCMAKE_AUTOGEN_BETTER_GRAPH_MULTI_CONFIG=ON)
  158. unset(RunCMake_TEST_VARIANT_DESCRIPTION)
  159. run_make_program(${RunCMake_TEST_BINARY_DIR} --verbose -f build-${ninja_config}.ninja all:all)
  160. endforeach()
  161. endblock()
  162. elseif (RunCMake_GENERATOR MATCHES "Ninja|Make")
  163. block()
  164. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Auto${exe}ExecutableConfig-build)
  165. foreach(config IN ITEMS Debug Release RelWithDebInfo)
  166. block()
  167. set(RunCMake_TEST_VARIANT_DESCRIPTION "-${config}")
  168. run_cmake_with_options(Auto${exe}ExecutableConfig ${RunCMake_TEST_OPTIONS} -DCMAKE_BUILD_TYPE=${config} -DCMAKE_AUTOGEN_VERBOSE=ON)
  169. unset(RunCMake_TEST_VARIANT_DESCRIPTION)
  170. set(RunCMake_TEST_NO_CLEAN 1)
  171. set(RunCMake_TEST_EXPECT_stdout ".*running_exe_${config}*")
  172. run_cmake_command(Auto${exe}ExecutableConfig-${config}-build ${CMAKE_COMMAND} --build .)
  173. endblock()
  174. endforeach()
  175. endblock()
  176. endif()
  177. endif()
  178. # Visual Studio specific dependency tests
  179. if (RunCMake_GENERATOR MATCHES "Visual Studio")
  180. block()
  181. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${exe}Example-build)
  182. set(RunCMake_TEST_VARIANT_DESCRIPTION "-CMake-configure")
  183. run_cmake_with_options(${exe}Example ${RunCMake_TEST_OPTIONS} -DCMAKE_AUTOGEN_VERBOSE=ON)
  184. unset(RunCMake_TEST_VARIANT_DESCRIPTION)
  185. set(RunCMake_TEST_NO_CLEAN 1)
  186. foreach(config IN ITEMS Debug Release RelWithDebInfo)
  187. block()
  188. set(RunCMake_TEST_VARIANT_DESCRIPTION "-${config}-first-build")
  189. run_cmake_command(${exe}Example-build ${CMAKE_COMMAND} --build . --config ${config})
  190. endblock()
  191. endforeach()
  192. foreach(config IN ITEMS Debug Release RelWithDebInfo)
  193. block()
  194. if (exe STREQUAL "Moc" OR exe STREQUAL "Uic")
  195. set(RunCMake_TEST_NOT_EXPECT_stdout "Auto${exe}")
  196. set(not_expect_description "Auto${exe}")
  197. else ()
  198. set(RunCMake_TEST_NOT_EXPECT_stdout "Auto${exe}")
  199. set(not_expect_description "Auto${exe}")
  200. endif()
  201. set(RunCMake_TEST_VARIANT_DESCRIPTION "-second-build-${config}_expect_no_${not_expect_description}")
  202. run_cmake_command(${exe}Example-build ${CMAKE_COMMAND} --build . --config ${config})
  203. endblock()
  204. endforeach()
  205. endblock()
  206. endif()
  207. if (RunCMake_GENERATOR MATCHES "Xcode")
  208. block()
  209. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${exe}Example-build)
  210. set(RunCMake_TEST_VARIANT_DESCRIPTION "-CMake-configure")
  211. set(RunCMake_TEST_EXPECT_stderr ".*")
  212. run_cmake_with_options(${exe}Example ${RunCMake_TEST_OPTIONS} -DCMAKE_AUTOGEN_VERBOSE=ON)
  213. set(RunCMake_TEST_NO_CLEAN 1)
  214. set(RunCMake_MAKE_PROGRAM ${CMAKE_COMMAND})
  215. run_make_program(${RunCMake_TEST_BINARY_DIR} --build . --config Debug)
  216. if (exe STREQUAL "Moc")
  217. set(expected_count 4)
  218. elseif (exe STREQUAL "Uic")
  219. set(expected_count 1)
  220. else()
  221. set(expected_count 12)
  222. endif()
  223. expect_n_times("${make_program_stdout}" "Auto${exe}:" ${expected_count} "${exe}Example-build-Auto${exe}")
  224. if (exe STREQUAL "Moc" OR exe STREQUAL "Uic")
  225. expect_n_times("${make_program_stdout}" "AutoGen:" 5 "${exe}Example-build-AutoGen:")
  226. endif()
  227. foreach(config IN ITEMS Release RelWithDebInfo)
  228. block()
  229. # Note: We expect to see Auto${exe} or AutoGen in the output for
  230. # moc and uic because they should be triggered per configuration.
  231. # For rcc, we don't expect to see Auto${exe} or AutoGen in the output
  232. # because all configurations trigger with the first configuration.
  233. run_make_program(${RunCMake_TEST_BINARY_DIR} --build . --config ${config})
  234. if (exe STREQUAL "Moc" OR exe STREQUAL "Uic")
  235. expect_n_times("${make_program_stdout}" "Auto${exe}:" ${expected_count} "${exe}Example-build-${config}-Auto${exe}")
  236. expect_n_times("${make_program_stdout}" "AutoGen" 5 "${exe}Example-build-${config}-AutoGen:")
  237. else()
  238. not_expect("${make_program_stdout}" "Auto${exe}" "${exe}Example-build-${config}_Auto${exe}")
  239. not_expect("${make_program_stdout}" "AutoGen" "${exe}Example-build-${config}_AutoGen")
  240. endif()
  241. endblock()
  242. endforeach()
  243. endblock()
  244. endif()
  245. endfunction()