8f9c263a24f5e25f20d2e6e3991a2fd996c495a0
[platform/upstream/cmake.git] / Tests / RunCMake / Ninja / RunCMakeTest.cmake
1 include(RunCMake)
2
3 set(RunCMake_GENERATOR "Ninja")
4 set(RunCMake_GENERATOR_IS_MULTI_CONFIG 0)
5
6 # Detect ninja version so we know what tests can be supported.
7 execute_process(
8   COMMAND "${RunCMake_MAKE_PROGRAM}" --version
9   OUTPUT_VARIABLE ninja_out
10   ERROR_VARIABLE ninja_out
11   RESULT_VARIABLE ninja_res
12   OUTPUT_STRIP_TRAILING_WHITESPACE
13   )
14 if(ninja_res EQUAL 0 AND "x${ninja_out}" MATCHES "^x[0-9]+\\.[0-9]+")
15   set(ninja_version "${ninja_out}")
16   message(STATUS "ninja version: ${ninja_version}")
17 else()
18   message(FATAL_ERROR "'ninja --version' reported:\n${ninja_out}")
19 endif()
20
21 if(CMAKE_HOST_WIN32)
22   run_cmake(SelectCompilerWindows)
23 else()
24   run_cmake(SelectCompilerUNIX)
25 endif()
26
27 function(run_NinjaToolMissing)
28   set(RunCMake_MAKE_PROGRAM ninja-tool-missing)
29   run_cmake(NinjaToolMissing)
30 endfunction()
31 run_NinjaToolMissing()
32
33 function(run_NoWorkToDo)
34   run_cmake(NoWorkToDo)
35   set(RunCMake_TEST_NO_CLEAN 1)
36   set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/NoWorkToDo-build)
37   run_cmake_command(NoWorkToDo-build ${CMAKE_COMMAND} --build .)
38   run_cmake_command(NoWorkToDo-nowork ${CMAKE_COMMAND} --build . -- -d explain)
39 endfunction()
40 run_NoWorkToDo()
41
42 function(run_VerboseBuild)
43   run_cmake(VerboseBuild)
44   set(RunCMake_TEST_NO_CLEAN 1)
45   set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/VerboseBuild-build)
46   run_cmake_command(VerboseBuild-build ${CMAKE_COMMAND} --build . -v --clean-first)
47   run_cmake_command(VerboseBuild-nowork ${CMAKE_COMMAND} --build . --verbose)
48 endfunction()
49 run_VerboseBuild()
50
51 function(run_CMP0058 case)
52   # Use a single build tree for a few tests without cleaning.
53   set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0058-${case}-build)
54   set(RunCMake_TEST_NO_CLEAN 1)
55   file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
56   file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
57   run_cmake(CMP0058-${case})
58   run_cmake_command(CMP0058-${case}-build ${CMAKE_COMMAND} --build .)
59 endfunction()
60
61 run_CMP0058(OLD-no)
62 run_CMP0058(OLD-by)
63 run_CMP0058(WARN-no)
64 run_CMP0058(WARN-by)
65 run_CMP0058(NEW-no)
66 run_CMP0058(NEW-by)
67
68 run_cmake(CustomCommandDepfile)
69 run_cmake(CustomCommandJobPool)
70 run_cmake(JobPoolUsesTerminal)
71
72 run_cmake(RspFileC)
73 run_cmake(RspFileCXX)
74 if(TEST_Fortran)
75   run_cmake(RspFileFortran)
76 endif()
77
78 function(run_CommandConcat)
79   set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CommandConcat-build)
80   set(RunCMake_TEST_NO_CLEAN 1)
81   file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
82   file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
83   run_cmake(CommandConcat)
84   run_cmake_command(CommandConcat-build ${CMAKE_COMMAND} --build .)
85 endfunction()
86 run_CommandConcat()
87
88 function(run_SubDir)
89   # Use a single build tree for a few tests without cleaning.
90   set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SubDir-build)
91   set(RunCMake_TEST_NO_CLEAN 1)
92   file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
93   file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
94   run_cmake(SubDir)
95   if(WIN32)
96     set(SubDir_all [[SubDir\all]])
97     set(SubDir_test [[SubDir\test]])
98     set(SubDir_install [[SubDir\install]])
99     set(SubDirBinary_test [[SubDirBinary\test]])
100     set(SubDirBinary_all [[SubDirBinary\all]])
101     set(SubDirBinary_install [[SubDirBinary\install]])
102   else()
103     set(SubDir_all [[SubDir/all]])
104     set(SubDir_test [[SubDir/test]])
105     set(SubDir_install [[SubDir/install]])
106     set(SubDirBinary_all [[SubDirBinary/all]])
107     set(SubDirBinary_test [[SubDirBinary/test]])
108     set(SubDirBinary_install [[SubDirBinary/install]])
109   endif()
110   run_cmake_command(SubDir-build ${CMAKE_COMMAND} --build . --target ${SubDir_all})
111   run_cmake_command(SubDir-test ${CMAKE_COMMAND} --build . --target ${SubDir_test})
112   run_cmake_command(SubDir-install ${CMAKE_COMMAND} --build . --target ${SubDir_install})
113   run_cmake_command(SubDirBinary-build ${CMAKE_COMMAND} --build . --target ${SubDirBinary_all})
114   run_cmake_command(SubDirBinary-test ${CMAKE_COMMAND} --build . --target ${SubDirBinary_test})
115   run_cmake_command(SubDirBinary-install ${CMAKE_COMMAND} --build . --target ${SubDirBinary_install})
116 endfunction()
117 run_SubDir()
118
119 function(run_ninja dir)
120   execute_process(
121     COMMAND "${RunCMake_MAKE_PROGRAM}" ${ARGN}
122     WORKING_DIRECTORY "${dir}"
123     OUTPUT_VARIABLE ninja_stdout
124     ERROR_VARIABLE ninja_stderr
125     RESULT_VARIABLE ninja_result
126     )
127   if(NOT ninja_result EQUAL 0)
128     message(STATUS "
129 ============ beginning of ninja's stdout ============
130 ${ninja_stdout}
131 =============== end of ninja's stdout ===============
132 ")
133     message(STATUS "
134 ============ beginning of ninja's stderr ============
135 ${ninja_stderr}
136 =============== end of ninja's stderr ===============
137 ")
138     message(FATAL_ERROR
139       "top ninja build failed exited with status ${ninja_result}")
140   endif()
141 endfunction(run_ninja)
142
143 function (run_LooseObjectDepends)
144   set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/LooseObjectDepends-build)
145   run_cmake(LooseObjectDepends)
146   run_ninja("${RunCMake_TEST_BINARY_DIR}" "CMakeFiles/top.dir/top.c${CMAKE_C_OUTPUT_EXTENSION}")
147   if (EXISTS "${RunCMake_TEST_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}dep${CMAKE_SHARED_LIBRARY_SUFFIX}")
148     message(FATAL_ERROR
149       "The `dep` library was created when requesting an object file to be "
150       "built; this should no longer be necessary.")
151   endif ()
152   if (EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/dep.dir/dep.c${CMAKE_C_OUTPUT_EXTENSION}")
153     message(FATAL_ERROR
154       "The `dep.c` object file was created when requesting an object file to "
155       "be built; this should no longer be necessary.")
156   endif ()
157 endfunction ()
158 run_LooseObjectDepends()
159
160 function (run_AssumedSources)
161   set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AssumedSources-build)
162   run_cmake(AssumedSources)
163   run_ninja("${RunCMake_TEST_BINARY_DIR}" "target.c")
164   if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/target.c")
165     message(FATAL_ERROR
166       "Dependencies for an assumed source did not hook up properly for 'target.c'.")
167   endif ()
168   run_ninja("${RunCMake_TEST_BINARY_DIR}" "target-no-depends.c")
169   if (EXISTS "${RunCMake_TEST_BINARY_DIR}/target-no-depends.c")
170     message(FATAL_ERROR
171       "Dependencies for an assumed source were magically hooked up for 'target-no-depends.c'.")
172   endif ()
173 endfunction ()
174 run_AssumedSources()
175
176 function(sleep delay)
177   execute_process(
178     COMMAND ${CMAKE_COMMAND} -E sleep ${delay}
179     RESULT_VARIABLE result
180     )
181   if(NOT result EQUAL 0)
182     message(FATAL_ERROR "failed to sleep for ${delay} second.")
183   endif()
184 endfunction(sleep)
185
186 function(touch path)
187   execute_process(
188     COMMAND ${CMAKE_COMMAND} -E touch ${path}
189     RESULT_VARIABLE result
190     )
191   if(NOT result EQUAL 0)
192     message(FATAL_ERROR "failed to touch main ${path} file.")
193   endif()
194 endfunction(touch)
195
196 macro(ninja_escape_path path out)
197   string(REPLACE "\$ " "\$\$" "${out}" "${path}")
198   string(REPLACE " " "\$ " "${out}" "${${out}}")
199   string(REPLACE ":" "\$:" "${out}" "${${out}}")
200 endmacro(ninja_escape_path)
201
202 macro(shell_escape string out)
203   string(REPLACE "\"" "\\\"" "${out}" "${string}")
204 endmacro(shell_escape)
205
206 function(run_sub_cmake test ninja_output_path_prefix)
207   set(top_build_dir "${RunCMake_BINARY_DIR}/${test}-build/")
208   file(REMOVE_RECURSE "${top_build_dir}")
209   file(MAKE_DIRECTORY "${top_build_dir}")
210
211   ninja_escape_path("${ninja_output_path_prefix}"
212     escaped_ninja_output_path_prefix)
213
214   # Generate top build ninja file.
215   set(top_build_ninja "${top_build_dir}/build.ninja")
216   shell_escape("${top_build_ninja}" escaped_top_build_ninja)
217   set(build_ninja_dep "${top_build_dir}/build_ninja_dep")
218   ninja_escape_path("${build_ninja_dep}" escaped_build_ninja_dep)
219   shell_escape("${CMAKE_COMMAND}" escaped_CMAKE_COMMAND)
220   file(WRITE "${build_ninja_dep}" "fake dependency of top build.ninja file\n")
221   if(WIN32)
222     set(cmd_prefix "cmd.exe /C \"")
223     set(cmd_suffix "\"")
224   else()
225     set(cmd_prefix "")
226     set(cmd_suffix "")
227   endif()
228   set(fs_delay 3) # We assume the system as 1 sec timestamp resolution.
229   file(WRITE "${top_build_ninja}" "\
230 subninja ${escaped_ninja_output_path_prefix}/build.ninja
231 default ${escaped_ninja_output_path_prefix}/all
232
233 # Sleep for long enough before regenerating to make sure the timestamp of
234 # the top build.ninja will be strictly greater than the timestamp of the
235 # sub/build.ninja file.
236 rule RERUN
237   command = ${cmd_prefix}\"${escaped_CMAKE_COMMAND}\" -E sleep ${fs_delay} && \"${escaped_CMAKE_COMMAND}\" -E touch \"${escaped_top_build_ninja}\"${cmd_suffix}
238   description = Testing regeneration
239   generator = 1
240
241 build build.ninja: RERUN ${escaped_build_ninja_dep} || ${escaped_ninja_output_path_prefix}/build.ninja
242   pool = console
243 ")
244
245   # Run sub cmake project.
246   set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_OUTPUT_PATH_PREFIX=${ninja_output_path_prefix}")
247   set(RunCMake_TEST_BINARY_DIR "${top_build_dir}/${ninja_output_path_prefix}")
248   run_cmake(${test})
249
250   # Check there is no 'default' statement in Ninja file generated by CMake.
251   set(sub_build_ninja "${RunCMake_TEST_BINARY_DIR}/build.ninja")
252   file(READ "${sub_build_ninja}" sub_build_ninja_file)
253   if(sub_build_ninja_file MATCHES "\ndefault [^\n][^\n]*all\n")
254     message(FATAL_ERROR
255       "unexpected 'default' statement found in '${sub_build_ninja}'")
256   endif()
257
258   # Run ninja from the top build directory.
259   run_ninja("${top_build_dir}")
260
261   # Test regeneration rules run in order.
262   set(main_cmakelists "${RunCMake_SOURCE_DIR}/CMakeLists.txt")
263   sleep(${fs_delay})
264   touch("${main_cmakelists}")
265   touch("${build_ninja_dep}")
266   run_ninja("${top_build_dir}")
267   file(TIMESTAMP "${main_cmakelists}" mtime_main_cmakelists UTC)
268   file(TIMESTAMP "${sub_build_ninja}" mtime_sub_build_ninja UTC)
269   file(TIMESTAMP "${top_build_ninja}" mtime_top_build_ninja UTC)
270
271   # Check sub build.ninja is regenerated.
272   if(mtime_main_cmakelists STRGREATER mtime_sub_build_ninja)
273     message(FATAL_ERROR
274       "sub build.ninja not regenerated:
275   CMakeLists.txt  = ${mtime_main_cmakelists}
276   sub/build.ninja = ${mtime_sub_build_ninja}")
277   endif()
278
279   # Check top build.ninja is regenerated after sub build.ninja.
280   if(NOT mtime_top_build_ninja STRGREATER mtime_sub_build_ninja)
281     message(FATAL_ERROR
282       "top build.ninja not regenerated strictly after sub build.ninja:
283   sub/build.ninja = ${mtime_sub_build_ninja}
284   build.ninja     = ${mtime_top_build_ninja}")
285   endif()
286
287 endfunction(run_sub_cmake)
288
289 if("${ninja_version}" VERSION_LESS 1.6)
290   message(WARNING "Ninja is too old; skipping rest of test.")
291   return()
292 endif()
293
294 foreach(ninja_output_path_prefix "sub space" "sub")
295   run_sub_cmake(Executable "${ninja_output_path_prefix}")
296   run_sub_cmake(StaticLib  "${ninja_output_path_prefix}")
297   run_sub_cmake(SharedLib "${ninja_output_path_prefix}")
298   run_sub_cmake(TwoLibs "${ninja_output_path_prefix}")
299   run_sub_cmake(SubDirPrefix "${ninja_output_path_prefix}")
300   run_sub_cmake(CustomCommandWorkingDirectory "${ninja_output_path_prefix}")
301 endforeach(ninja_output_path_prefix)
302
303 function (run_PreventTargetAliasesDupBuildRule)
304   set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/PreventTargetAliasesDupBuildRule-build)
305   run_cmake(PreventTargetAliasesDupBuildRule)
306   run_ninja("${RunCMake_TEST_BINARY_DIR}" -w dupbuild=err)
307 endfunction ()
308 run_PreventTargetAliasesDupBuildRule()
309
310 function (run_PreventConfigureFileDupBuildRule)
311   set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/PreventConfigureFileDupBuildRule-build)
312   run_cmake(PreventConfigureFileDupBuildRule)
313   run_ninja("${RunCMake_TEST_BINARY_DIR}" -w dupbuild=err)
314 endfunction()
315 run_PreventConfigureFileDupBuildRule()
316
317 function (run_ChangeBuildType)
318   set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ChangeBuildType-build)
319   set(RunCMake_TEST_OPTIONS "-DCMAKE_BUILD_TYPE:STRING=Debug")
320   run_cmake(ChangeBuildType)
321   unset(RunCMake_TEST_OPTIONS)
322   run_ninja("${RunCMake_TEST_BINARY_DIR}" -w dupbuild=err)
323 endfunction()
324 run_ChangeBuildType()