|
|
@@ -32,3 +32,148 @@ function(run_SubDir)
|
|
|
run_cmake_command(SubDir-build ${CMAKE_COMMAND} --build . --target ${SubDir_all})
|
|
|
endfunction()
|
|
|
run_SubDir()
|
|
|
+
|
|
|
+function(run_ninja dir)
|
|
|
+ execute_process(
|
|
|
+ COMMAND "${RunCMake_MAKE_PROGRAM}"
|
|
|
+ WORKING_DIRECTORY "${dir}"
|
|
|
+ OUTPUT_VARIABLE ninja_stdout
|
|
|
+ ERROR_VARIABLE ninja_stderr
|
|
|
+ RESULT_VARIABLE ninja_result
|
|
|
+ )
|
|
|
+ if(NOT ninja_result EQUAL 0)
|
|
|
+ message(STATUS "
|
|
|
+============ beginning of ninja's stdout ============
|
|
|
+${ninja_stdout}
|
|
|
+=============== end of ninja's stdout ===============
|
|
|
+")
|
|
|
+ message(STATUS "
|
|
|
+============ beginning of ninja's stderr ============
|
|
|
+${ninja_stderr}
|
|
|
+=============== end of ninja's stderr ===============
|
|
|
+")
|
|
|
+ message(FATAL_ERROR
|
|
|
+ "top ninja build failed exited with status ${ninja_result}")
|
|
|
+ endif()
|
|
|
+endfunction(run_ninja)
|
|
|
+
|
|
|
+function(sleep delay)
|
|
|
+ execute_process(
|
|
|
+ COMMAND ${CMAKE_COMMAND} -E sleep ${delay}
|
|
|
+ RESULT_VARIABLE result
|
|
|
+ )
|
|
|
+ if(NOT result EQUAL 0)
|
|
|
+ message(FATAL_ERROR "failed to sleep for ${delay} second.")
|
|
|
+ endif()
|
|
|
+endfunction(sleep)
|
|
|
+
|
|
|
+function(touch path)
|
|
|
+ execute_process(
|
|
|
+ COMMAND ${CMAKE_COMMAND} -E touch ${path}
|
|
|
+ RESULT_VARIABLE result
|
|
|
+ )
|
|
|
+ if(NOT result EQUAL 0)
|
|
|
+ message(FATAL_ERROR "failed to touch main ${path} file.")
|
|
|
+ endif()
|
|
|
+endfunction(touch)
|
|
|
+
|
|
|
+macro(ninja_escape_path path out)
|
|
|
+ string(REPLACE "\$ " "\$\$" "${out}" "${path}")
|
|
|
+ string(REPLACE " " "\$ " "${out}" "${${out}}")
|
|
|
+ string(REPLACE ":" "\$:" "${out}" "${${out}}")
|
|
|
+endmacro(ninja_escape_path)
|
|
|
+
|
|
|
+macro(shell_escape string out)
|
|
|
+ string(REPLACE "\"" "\\\"" "${out}" "${string}")
|
|
|
+endmacro(shell_escape)
|
|
|
+
|
|
|
+function(run_sub_cmake test ninja_output_path_prefix)
|
|
|
+ set(top_build_dir "${RunCMake_BINARY_DIR}/${test}-build/")
|
|
|
+ file(REMOVE_RECURSE "${top_build_dir}")
|
|
|
+ file(MAKE_DIRECTORY "${top_build_dir}")
|
|
|
+
|
|
|
+ ninja_escape_path("${ninja_output_path_prefix}"
|
|
|
+ escaped_ninja_output_path_prefix)
|
|
|
+
|
|
|
+ # Generate top build ninja file.
|
|
|
+ set(top_build_ninja "${top_build_dir}/build.ninja")
|
|
|
+ shell_escape("${top_build_ninja}" escaped_top_build_ninja)
|
|
|
+ set(build_ninja_dep "${top_build_dir}/build_ninja_dep")
|
|
|
+ ninja_escape_path("${build_ninja_dep}" escaped_build_ninja_dep)
|
|
|
+ shell_escape("${CMAKE_COMMAND}" escaped_CMAKE_COMMAND)
|
|
|
+ file(WRITE "${build_ninja_dep}" "fake dependency of top build.ninja file\n")
|
|
|
+ if(WIN32)
|
|
|
+ set(cmd_prefix "cmd.exe /C \"")
|
|
|
+ set(cmd_suffix "\"")
|
|
|
+ else()
|
|
|
+ set(cmd_prefix "")
|
|
|
+ set(cmd_suffix "")
|
|
|
+ endif()
|
|
|
+ file(WRITE "${top_build_ninja}" "\
|
|
|
+subninja ${escaped_ninja_output_path_prefix}/build.ninja
|
|
|
+default ${escaped_ninja_output_path_prefix}/all
|
|
|
+
|
|
|
+# Sleep for 1 second before to regenerate to make sure the timestamp of
|
|
|
+# the top build.ninja will be strictly greater than the timestamp of the
|
|
|
+# sub/build.ninja file. We assume the system as 1 sec timestamp resolution.
|
|
|
+rule RERUN
|
|
|
+ command = ${cmd_prefix}\"${escaped_CMAKE_COMMAND}\" -E sleep 1 && \"${escaped_CMAKE_COMMAND}\" -E touch \"${escaped_top_build_ninja}\"${cmd_suffix}
|
|
|
+ description = Testing regeneration
|
|
|
+ generator = 1
|
|
|
+
|
|
|
+build build.ninja: RERUN ${escaped_build_ninja_dep} || ${escaped_ninja_output_path_prefix}/build.ninja
|
|
|
+ pool = console
|
|
|
+")
|
|
|
+
|
|
|
+ # Run sub cmake project.
|
|
|
+ set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_OUTPUT_PATH_PREFIX=${ninja_output_path_prefix}")
|
|
|
+ set(RunCMake_TEST_BINARY_DIR "${top_build_dir}/${ninja_output_path_prefix}")
|
|
|
+ run_cmake(${test})
|
|
|
+
|
|
|
+ # Check there is no 'default' statement in Ninja file generated by CMake.
|
|
|
+ set(sub_build_ninja "${RunCMake_TEST_BINARY_DIR}/build.ninja")
|
|
|
+ file(READ "${sub_build_ninja}" sub_build_ninja_file)
|
|
|
+ if(sub_build_ninja_file MATCHES "\ndefault [^\n][^\n]*all\n")
|
|
|
+ message(FATAL_ERROR
|
|
|
+ "unexpected 'default' statement found in '${sub_build_ninja}'")
|
|
|
+ endif()
|
|
|
+
|
|
|
+ # Run ninja from the top build directory.
|
|
|
+ run_ninja("${top_build_dir}")
|
|
|
+
|
|
|
+ # Test regeneration rules run in order.
|
|
|
+ set(main_cmakelists "${RunCMake_SOURCE_DIR}/CMakeLists.txt")
|
|
|
+ sleep(1) # Assume the system as 1 sec timestamp resolution.
|
|
|
+ touch("${main_cmakelists}")
|
|
|
+ touch("${build_ninja_dep}")
|
|
|
+ run_ninja("${top_build_dir}")
|
|
|
+ file(TIMESTAMP "${main_cmakelists}" mtime_main_cmakelists UTC)
|
|
|
+ file(TIMESTAMP "${sub_build_ninja}" mtime_sub_build_ninja UTC)
|
|
|
+ file(TIMESTAMP "${top_build_ninja}" mtime_top_build_ninja UTC)
|
|
|
+
|
|
|
+ # Check sub build.ninja is regenerated.
|
|
|
+ if(mtime_main_cmakelists STRGREATER mtime_sub_build_ninja)
|
|
|
+ message(FATAL_ERROR
|
|
|
+ "sub build.ninja not regenerated:
|
|
|
+ CMakeLists.txt = ${mtime_main_cmakelists}
|
|
|
+ sub/build.ninja = ${mtime_sub_build_ninja}")
|
|
|
+ endif()
|
|
|
+
|
|
|
+ # Check top build.ninja is regenerated after sub build.ninja.
|
|
|
+ if(NOT mtime_top_build_ninja STRGREATER mtime_sub_build_ninja)
|
|
|
+ message(FATAL_ERROR
|
|
|
+ "top build.ninja not regenerated strictly after sub build.ninja:
|
|
|
+ sub/build.ninja = ${mtime_sub_build_ninja}
|
|
|
+ build.ninja = ${mtime_top_build_ninja}")
|
|
|
+ endif()
|
|
|
+
|
|
|
+endfunction(run_sub_cmake)
|
|
|
+
|
|
|
+foreach(ninja_output_path_prefix "sub space" "sub")
|
|
|
+ run_sub_cmake(Executable "${ninja_output_path_prefix}")
|
|
|
+ run_sub_cmake(StaticLib "${ninja_output_path_prefix}")
|
|
|
+ run_sub_cmake(SharedLib "${ninja_output_path_prefix}")
|
|
|
+ run_sub_cmake(TwoLibs "${ninja_output_path_prefix}")
|
|
|
+ run_sub_cmake(SubDirPrefix "${ninja_output_path_prefix}")
|
|
|
+ run_sub_cmake(CustomCommandWorkingDirectory "${ninja_output_path_prefix}")
|
|
|
+endforeach(ninja_output_path_prefix)
|