RunCMakeTest.cmake 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. include(RunCMake)
  2. # Detect ninja version so we know what tests can be supported.
  3. execute_process(
  4. COMMAND "${RunCMake_MAKE_PROGRAM}" --version
  5. OUTPUT_VARIABLE ninja_out
  6. ERROR_VARIABLE ninja_out
  7. RESULT_VARIABLE ninja_res
  8. OUTPUT_STRIP_TRAILING_WHITESPACE
  9. )
  10. if(ninja_res EQUAL 0 AND "x${ninja_out}" MATCHES "^x[0-9]+\\.[0-9]+")
  11. set(ninja_version "${ninja_out}")
  12. message(STATUS "ninja version: ${ninja_version}")
  13. else()
  14. message(FATAL_ERROR "'ninja --version' reported:\n${ninja_out}")
  15. endif()
  16. function(run_CMP0058 case)
  17. # Use a single build tree for a few tests without cleaning.
  18. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0058-${case}-build)
  19. set(RunCMake_TEST_NO_CLEAN 1)
  20. file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
  21. file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
  22. run_cmake(CMP0058-${case})
  23. run_cmake_command(CMP0058-${case}-build ${CMAKE_COMMAND} --build .)
  24. endfunction()
  25. run_CMP0058(OLD-no)
  26. run_CMP0058(OLD-by)
  27. run_CMP0058(WARN-no)
  28. run_CMP0058(WARN-by)
  29. run_CMP0058(NEW-no)
  30. run_CMP0058(NEW-by)
  31. run_cmake(CustomCommandDepfile)
  32. function(run_SubDir)
  33. # Use a single build tree for a few tests without cleaning.
  34. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SubDir-build)
  35. set(RunCMake_TEST_NO_CLEAN 1)
  36. file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
  37. file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
  38. run_cmake(SubDir)
  39. if(WIN32)
  40. set(SubDir_all [[SubDir\all]])
  41. set(SubDir_test [[SubDir\test]])
  42. set(SubDir_install [[SubDir\install]])
  43. else()
  44. set(SubDir_all [[SubDir/all]])
  45. set(SubDir_test [[SubDir/test]])
  46. set(SubDir_install [[SubDir/install]])
  47. endif()
  48. run_cmake_command(SubDir-build ${CMAKE_COMMAND} --build . --target ${SubDir_all})
  49. run_cmake_command(SubDir-test ${CMAKE_COMMAND} --build . --target ${SubDir_test})
  50. run_cmake_command(SubDir-install ${CMAKE_COMMAND} --build . --target ${SubDir_install})
  51. endfunction()
  52. run_SubDir()
  53. function(run_ninja dir)
  54. execute_process(
  55. COMMAND "${RunCMake_MAKE_PROGRAM}"
  56. WORKING_DIRECTORY "${dir}"
  57. OUTPUT_VARIABLE ninja_stdout
  58. ERROR_VARIABLE ninja_stderr
  59. RESULT_VARIABLE ninja_result
  60. )
  61. if(NOT ninja_result EQUAL 0)
  62. message(STATUS "
  63. ============ beginning of ninja's stdout ============
  64. ${ninja_stdout}
  65. =============== end of ninja's stdout ===============
  66. ")
  67. message(STATUS "
  68. ============ beginning of ninja's stderr ============
  69. ${ninja_stderr}
  70. =============== end of ninja's stderr ===============
  71. ")
  72. message(FATAL_ERROR
  73. "top ninja build failed exited with status ${ninja_result}")
  74. endif()
  75. endfunction(run_ninja)
  76. function(sleep delay)
  77. execute_process(
  78. COMMAND ${CMAKE_COMMAND} -E sleep ${delay}
  79. RESULT_VARIABLE result
  80. )
  81. if(NOT result EQUAL 0)
  82. message(FATAL_ERROR "failed to sleep for ${delay} second.")
  83. endif()
  84. endfunction(sleep)
  85. function(touch path)
  86. execute_process(
  87. COMMAND ${CMAKE_COMMAND} -E touch ${path}
  88. RESULT_VARIABLE result
  89. )
  90. if(NOT result EQUAL 0)
  91. message(FATAL_ERROR "failed to touch main ${path} file.")
  92. endif()
  93. endfunction(touch)
  94. macro(ninja_escape_path path out)
  95. string(REPLACE "\$ " "\$\$" "${out}" "${path}")
  96. string(REPLACE " " "\$ " "${out}" "${${out}}")
  97. string(REPLACE ":" "\$:" "${out}" "${${out}}")
  98. endmacro(ninja_escape_path)
  99. macro(shell_escape string out)
  100. string(REPLACE "\"" "\\\"" "${out}" "${string}")
  101. endmacro(shell_escape)
  102. function(run_sub_cmake test ninja_output_path_prefix)
  103. set(top_build_dir "${RunCMake_BINARY_DIR}/${test}-build/")
  104. file(REMOVE_RECURSE "${top_build_dir}")
  105. file(MAKE_DIRECTORY "${top_build_dir}")
  106. ninja_escape_path("${ninja_output_path_prefix}"
  107. escaped_ninja_output_path_prefix)
  108. # Generate top build ninja file.
  109. set(top_build_ninja "${top_build_dir}/build.ninja")
  110. shell_escape("${top_build_ninja}" escaped_top_build_ninja)
  111. set(build_ninja_dep "${top_build_dir}/build_ninja_dep")
  112. ninja_escape_path("${build_ninja_dep}" escaped_build_ninja_dep)
  113. shell_escape("${CMAKE_COMMAND}" escaped_CMAKE_COMMAND)
  114. file(WRITE "${build_ninja_dep}" "fake dependency of top build.ninja file\n")
  115. if(WIN32)
  116. set(cmd_prefix "cmd.exe /C \"")
  117. set(cmd_suffix "\"")
  118. else()
  119. set(cmd_prefix "")
  120. set(cmd_suffix "")
  121. endif()
  122. file(WRITE "${top_build_ninja}" "\
  123. subninja ${escaped_ninja_output_path_prefix}/build.ninja
  124. default ${escaped_ninja_output_path_prefix}/all
  125. # Sleep for 1 second before to regenerate to make sure the timestamp of
  126. # the top build.ninja will be strictly greater than the timestamp of the
  127. # sub/build.ninja file. We assume the system as 1 sec timestamp resolution.
  128. rule RERUN
  129. command = ${cmd_prefix}\"${escaped_CMAKE_COMMAND}\" -E sleep 1 && \"${escaped_CMAKE_COMMAND}\" -E touch \"${escaped_top_build_ninja}\"${cmd_suffix}
  130. description = Testing regeneration
  131. generator = 1
  132. build build.ninja: RERUN ${escaped_build_ninja_dep} || ${escaped_ninja_output_path_prefix}/build.ninja
  133. pool = console
  134. ")
  135. # Run sub cmake project.
  136. set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_OUTPUT_PATH_PREFIX=${ninja_output_path_prefix}")
  137. set(RunCMake_TEST_BINARY_DIR "${top_build_dir}/${ninja_output_path_prefix}")
  138. run_cmake(${test})
  139. # Check there is no 'default' statement in Ninja file generated by CMake.
  140. set(sub_build_ninja "${RunCMake_TEST_BINARY_DIR}/build.ninja")
  141. file(READ "${sub_build_ninja}" sub_build_ninja_file)
  142. if(sub_build_ninja_file MATCHES "\ndefault [^\n][^\n]*all\n")
  143. message(FATAL_ERROR
  144. "unexpected 'default' statement found in '${sub_build_ninja}'")
  145. endif()
  146. # Run ninja from the top build directory.
  147. run_ninja("${top_build_dir}")
  148. # Test regeneration rules run in order.
  149. set(main_cmakelists "${RunCMake_SOURCE_DIR}/CMakeLists.txt")
  150. sleep(1) # Assume the system as 1 sec timestamp resolution.
  151. touch("${main_cmakelists}")
  152. touch("${build_ninja_dep}")
  153. run_ninja("${top_build_dir}")
  154. file(TIMESTAMP "${main_cmakelists}" mtime_main_cmakelists UTC)
  155. file(TIMESTAMP "${sub_build_ninja}" mtime_sub_build_ninja UTC)
  156. file(TIMESTAMP "${top_build_ninja}" mtime_top_build_ninja UTC)
  157. # Check sub build.ninja is regenerated.
  158. if(mtime_main_cmakelists STRGREATER mtime_sub_build_ninja)
  159. message(FATAL_ERROR
  160. "sub build.ninja not regenerated:
  161. CMakeLists.txt = ${mtime_main_cmakelists}
  162. sub/build.ninja = ${mtime_sub_build_ninja}")
  163. endif()
  164. # Check top build.ninja is regenerated after sub build.ninja.
  165. if(NOT mtime_top_build_ninja STRGREATER mtime_sub_build_ninja)
  166. message(FATAL_ERROR
  167. "top build.ninja not regenerated strictly after sub build.ninja:
  168. sub/build.ninja = ${mtime_sub_build_ninja}
  169. build.ninja = ${mtime_top_build_ninja}")
  170. endif()
  171. endfunction(run_sub_cmake)
  172. if("${ninja_version}" VERSION_LESS 1.6)
  173. message(WARNING "Ninja is too old; skipping rest of test.")
  174. return()
  175. endif()
  176. foreach(ninja_output_path_prefix "sub space" "sub")
  177. run_sub_cmake(Executable "${ninja_output_path_prefix}")
  178. run_sub_cmake(StaticLib "${ninja_output_path_prefix}")
  179. run_sub_cmake(SharedLib "${ninja_output_path_prefix}")
  180. run_sub_cmake(TwoLibs "${ninja_output_path_prefix}")
  181. run_sub_cmake(SubDirPrefix "${ninja_output_path_prefix}")
  182. run_sub_cmake(CustomCommandWorkingDirectory "${ninja_output_path_prefix}")
  183. endforeach(ninja_output_path_prefix)