diff options
author | Nicolas Despres <nicolas.despres@gmail.com> | 2016-05-13 23:18:20 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2016-05-17 13:34:12 (GMT) |
commit | 8a862a4d4b852c9f61ae4ed7fc46042b00a83123 (patch) | |
tree | 591906a0300c9619e57394105455d93126dab939 /Tests/RunCMake/Ninja | |
parent | 038e7716e58e4cf79bda6ba72b92814a14978a8f (diff) | |
download | CMake-8a862a4d4b852c9f61ae4ed7fc46042b00a83123.zip CMake-8a862a4d4b852c9f61ae4ed7fc46042b00a83123.tar.gz CMake-8a862a4d4b852c9f61ae4ed7fc46042b00a83123.tar.bz2 |
Ninja: Support embedding of CMake as subninja project
Add a `CMAKE_NINJA_OUTPUT_PATH_PREFIX` variable. When it is set, CMake
generates a `build.ninja` file suitable for embedding into another ninja
project potentially generated by an alien generator.
Diffstat (limited to 'Tests/RunCMake/Ninja')
21 files changed, 308 insertions, 0 deletions
diff --git a/Tests/RunCMake/Ninja/CheckNoPrefixSubDir.cmake b/Tests/RunCMake/Ninja/CheckNoPrefixSubDir.cmake new file mode 100644 index 0000000..b845f2f --- /dev/null +++ b/Tests/RunCMake/Ninja/CheckNoPrefixSubDir.cmake @@ -0,0 +1,7 @@ +add_custom_target(check_no_prefix_sub_dir ALL + COMMAND "${CMAKE_COMMAND}" + "-DNINJA_OUTPUT_PATH_PREFIX=${CMAKE_NINJA_OUTPUT_PATH_PREFIX}" + "-DCUR_BIN_DIR=${CMAKE_CURRENT_BINARY_DIR}" + -P "${CMAKE_CURRENT_SOURCE_DIR}/CheckNoPrefixSubDirScript.cmake" + VERBATIM + ) diff --git a/Tests/RunCMake/Ninja/CheckNoPrefixSubDirScript.cmake b/Tests/RunCMake/Ninja/CheckNoPrefixSubDirScript.cmake new file mode 100644 index 0000000..5a03fcb --- /dev/null +++ b/Tests/RunCMake/Ninja/CheckNoPrefixSubDirScript.cmake @@ -0,0 +1,8 @@ +# Check that the prefix sub-directory is not repeated. + +if(EXISTS "${CUR_BIN_DIR}/${NINJA_OUTPUT_PATH_PREFIX}") + message(FATAL_ERROR + "no sub directory named after the CMAKE_NINJA_OUTPUT_PATH_PREFIX " + "should be in the binary directory." + ) +endif() diff --git a/Tests/RunCMake/Ninja/CheckOutput.cmake b/Tests/RunCMake/Ninja/CheckOutput.cmake new file mode 100644 index 0000000..ddb35a7 --- /dev/null +++ b/Tests/RunCMake/Ninja/CheckOutput.cmake @@ -0,0 +1,23 @@ +# Add rules to check the generated executable works. + +set(hello_output "${CMAKE_CURRENT_BINARY_DIR}/hello.output") +add_custom_command( + OUTPUT "${hello_output}" + COMMAND "$<TARGET_FILE:hello>" > "${hello_output}" + DEPENDS hello + VERBATIM + ) + +if(NOT DEFINED HELLO_OUTPUT_STRING) + set(HELLO_OUTPUT_STRING "Hello world!\n") +endif() + +set(hello_output_ref "${CMAKE_CURRENT_BINARY_DIR}/hello.output.ref") +file(WRITE "${hello_output_ref}" "${HELLO_OUTPUT_STRING}") + +add_custom_target(check_output ALL + COMMAND "${CMAKE_COMMAND}" -E compare_files + "${hello_output}" "${hello_output_ref}" + DEPENDS "${hello_output}" "${hello_output_ref}" + VERBATIM + ) diff --git a/Tests/RunCMake/Ninja/CustomCommandWorkingDirectory.cmake b/Tests/RunCMake/Ninja/CustomCommandWorkingDirectory.cmake new file mode 100644 index 0000000..8e01c8c --- /dev/null +++ b/Tests/RunCMake/Ninja/CustomCommandWorkingDirectory.cmake @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.5) +project(hello NONE) + +add_custom_command( + OUTPUT hello.copy.c + COMMAND "${CMAKE_COMMAND}" -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/hello.c" + hello.copy.c + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + ) +add_custom_target(copy ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/hello.copy.c") + +include(CheckNoPrefixSubDir.cmake) diff --git a/Tests/RunCMake/Ninja/Executable.cmake b/Tests/RunCMake/Ninja/Executable.cmake new file mode 100644 index 0000000..4e17d68 --- /dev/null +++ b/Tests/RunCMake/Ninja/Executable.cmake @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.5) +project(hello C) +add_executable(hello hello.c) +include(CheckOutput.cmake) +include(CheckNoPrefixSubDir.cmake) diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake index 4e06888..8160c2d 100644 --- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake +++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake @@ -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) diff --git a/Tests/RunCMake/Ninja/SharedLib.cmake b/Tests/RunCMake/Ninja/SharedLib.cmake new file mode 100644 index 0000000..1a78390 --- /dev/null +++ b/Tests/RunCMake/Ninja/SharedLib.cmake @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.5) +project(hello C) +add_library(greeting SHARED greeting.c) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +add_executable(hello hello_with_greeting.c) +target_link_libraries(hello greeting) +include(CheckOutput.cmake) +include(CheckNoPrefixSubDir.cmake) diff --git a/Tests/RunCMake/Ninja/StaticLib.cmake b/Tests/RunCMake/Ninja/StaticLib.cmake new file mode 100644 index 0000000..0f815ae --- /dev/null +++ b/Tests/RunCMake/Ninja/StaticLib.cmake @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.5) +project(hello C) +add_definitions(-DGREETING_STATIC) +add_library(greeting STATIC greeting.c) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +add_executable(hello hello_with_greeting.c) +target_link_libraries(hello greeting) +include(CheckOutput.cmake) +include(CheckNoPrefixSubDir.cmake) diff --git a/Tests/RunCMake/Ninja/SubDirPrefix.cmake b/Tests/RunCMake/Ninja/SubDirPrefix.cmake new file mode 100644 index 0000000..30ad1e6 --- /dev/null +++ b/Tests/RunCMake/Ninja/SubDirPrefix.cmake @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.5) +project(hello C) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") +add_subdirectory(SubDirPrefix) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +add_executable(hello hello_sub_greeting.c) +target_link_libraries(hello greeting) +include(CheckOutput.cmake) diff --git a/Tests/RunCMake/Ninja/SubDirPrefix/CMakeLists.txt b/Tests/RunCMake/Ninja/SubDirPrefix/CMakeLists.txt new file mode 100644 index 0000000..575597d --- /dev/null +++ b/Tests/RunCMake/Ninja/SubDirPrefix/CMakeLists.txt @@ -0,0 +1,2 @@ +add_library(greeting SHARED greeting.c) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/Tests/RunCMake/Ninja/SubDirPrefix/greeting.c b/Tests/RunCMake/Ninja/SubDirPrefix/greeting.c new file mode 100644 index 0000000..ba3e55b --- /dev/null +++ b/Tests/RunCMake/Ninja/SubDirPrefix/greeting.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +#if defined(_WIN32) && !defined(GREETING_STATIC) +__declspec(dllexport) +#endif + void greeting(void) +{ + printf("Hello world!\n"); +} diff --git a/Tests/RunCMake/Ninja/SubDirPrefix/greeting.h b/Tests/RunCMake/Ninja/SubDirPrefix/greeting.h new file mode 100644 index 0000000..ee4053e --- /dev/null +++ b/Tests/RunCMake/Ninja/SubDirPrefix/greeting.h @@ -0,0 +1,4 @@ +#if defined(_WIN32) && !defined(GREETING_STATIC) +__declspec(dllimport) +#endif + void greeting(void); diff --git a/Tests/RunCMake/Ninja/TwoLibs.cmake b/Tests/RunCMake/Ninja/TwoLibs.cmake new file mode 100644 index 0000000..666452f --- /dev/null +++ b/Tests/RunCMake/Ninja/TwoLibs.cmake @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.5) +project(hello C) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib-static") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") + +add_library(greeting SHARED greeting.c) +add_library(greeting2 STATIC greeting2.c) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +add_executable(hello hello_with_two_greetings.c) +target_link_libraries(hello greeting greeting2) + +set(HELLO_OUTPUT_STRING "Hello world!\nHello world 2!\n") +include(CheckOutput.cmake) + +include(CheckNoPrefixSubDir.cmake) diff --git a/Tests/RunCMake/Ninja/greeting.c b/Tests/RunCMake/Ninja/greeting.c new file mode 100644 index 0000000..ba3e55b --- /dev/null +++ b/Tests/RunCMake/Ninja/greeting.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +#if defined(_WIN32) && !defined(GREETING_STATIC) +__declspec(dllexport) +#endif + void greeting(void) +{ + printf("Hello world!\n"); +} diff --git a/Tests/RunCMake/Ninja/greeting.h b/Tests/RunCMake/Ninja/greeting.h new file mode 100644 index 0000000..ee4053e --- /dev/null +++ b/Tests/RunCMake/Ninja/greeting.h @@ -0,0 +1,4 @@ +#if defined(_WIN32) && !defined(GREETING_STATIC) +__declspec(dllimport) +#endif + void greeting(void); diff --git a/Tests/RunCMake/Ninja/greeting2.c b/Tests/RunCMake/Ninja/greeting2.c new file mode 100644 index 0000000..c6ed87d --- /dev/null +++ b/Tests/RunCMake/Ninja/greeting2.c @@ -0,0 +1,6 @@ +#include <stdio.h> + +void greeting2(void) +{ + printf("Hello world 2!\n"); +} diff --git a/Tests/RunCMake/Ninja/greeting2.h b/Tests/RunCMake/Ninja/greeting2.h new file mode 100644 index 0000000..c4d8f9b --- /dev/null +++ b/Tests/RunCMake/Ninja/greeting2.h @@ -0,0 +1 @@ +void greeting2(void); diff --git a/Tests/RunCMake/Ninja/hello.c b/Tests/RunCMake/Ninja/hello.c new file mode 100644 index 0000000..aac8b4e --- /dev/null +++ b/Tests/RunCMake/Ninja/hello.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(void) +{ + printf("Hello world!\n"); + return 0; +} diff --git a/Tests/RunCMake/Ninja/hello_sub_greeting.c b/Tests/RunCMake/Ninja/hello_sub_greeting.c new file mode 100644 index 0000000..fc4bd60 --- /dev/null +++ b/Tests/RunCMake/Ninja/hello_sub_greeting.c @@ -0,0 +1,7 @@ +#include <SubDirPrefix/greeting.h> + +int main(void) +{ + greeting(); + return 0; +} diff --git a/Tests/RunCMake/Ninja/hello_with_greeting.c b/Tests/RunCMake/Ninja/hello_with_greeting.c new file mode 100644 index 0000000..dbf90e3 --- /dev/null +++ b/Tests/RunCMake/Ninja/hello_with_greeting.c @@ -0,0 +1,7 @@ +#include <greeting.h> + +int main(void) +{ + greeting(); + return 0; +} diff --git a/Tests/RunCMake/Ninja/hello_with_two_greetings.c b/Tests/RunCMake/Ninja/hello_with_two_greetings.c new file mode 100644 index 0000000..cbbdaad --- /dev/null +++ b/Tests/RunCMake/Ninja/hello_with_two_greetings.c @@ -0,0 +1,9 @@ +#include <greeting.h> +#include <greeting2.h> + +int main(void) +{ + greeting(); + greeting2(); + return 0; +} |