Hi, this is a patch that we use since some time for a quite large in-house project. The idea behind is to increase build parallelism by omitting dependencies of object file targets to the libraries they will be linked with in a later step. As this is not always the desired behaviour the default remains untouched and the setting can be changed globally and per target.
We found this functionality quite useful, especially in combination with build clusters like icecream or distcc. I recently got asked by another project to bring this upstream. Thanks for consideration! Best regards, Matthias
From da66b26a8c04132ef5f65854c1261af573e00cbe Mon Sep 17 00:00:00 2001 From: Matthias Maennich <matth...@maennich.net> Date: Tue, 15 Mar 2016 00:17:21 +0100 Subject: [PATCH] Ninja: Optionally skip library dependencies for object targets This change introduces a new target property COMPILE_DEPENDS_NO_LIB. If the property is set, all object file targets belonging to the target omit their dependencies to link libraries of type MODULE, OBJECT, STATIC and SHARED. Specifying COMPILE_DEPENDS_NO_LIB enables this behaviour for a target. The variable CMAKE_COMPILE_DEPENDS_NO_LIB can be used to enable this behaviour for all targets defined afterwards as it defines the default for new targets. --- Help/manual/cmake-properties.7.rst | 1 + Help/manual/cmake-variables.7.rst | 1 + Help/prop_tgt/COMPILE_DEPENDS_NO_LIB.rst | 45 ++++++++++++++++++++++ Help/variable/CMAKE_COMPILE_DEPENDS_NO_LIB.rst | 8 ++++ Source/cmGlobalNinjaGenerator.cxx | 17 +++++++- Source/cmGlobalNinjaGenerator.h | 3 +- Source/cmLocalNinjaGenerator.cxx | 6 ++- Source/cmLocalNinjaGenerator.h | 3 +- Source/cmNinjaTargetGenerator.cxx | 2 +- Source/cmTarget.cxx | 1 + Tests/RunCMake/CMakeLists.txt | 1 + .../RunCMake/compile_depends_no_lib/CMakeLists.txt | 3 ++ .../compile_depends_no_lib/RunCMakeTest.cmake | 16 ++++++++ .../compile_depends_no_lib/Test-dep1-stdout.txt | 3 ++ .../compile_depends_no_lib/Test-dep2-stdout.txt | 1 + .../compile_depends_no_lib/Test-dep3-stdout.txt | 1 + .../compile_depends_no_lib/Test-dep4-stdout.txt | 3 ++ Tests/RunCMake/compile_depends_no_lib/Test.cmake | 29 ++++++++++++++ 18 files changed, 137 insertions(+), 7 deletions(-) create mode 100644 Help/prop_tgt/COMPILE_DEPENDS_NO_LIB.rst create mode 100644 Help/variable/CMAKE_COMPILE_DEPENDS_NO_LIB.rst create mode 100644 Tests/RunCMake/compile_depends_no_lib/CMakeLists.txt create mode 100644 Tests/RunCMake/compile_depends_no_lib/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/compile_depends_no_lib/Test-dep1-stdout.txt create mode 100644 Tests/RunCMake/compile_depends_no_lib/Test-dep2-stdout.txt create mode 100644 Tests/RunCMake/compile_depends_no_lib/Test-dep3-stdout.txt create mode 100644 Tests/RunCMake/compile_depends_no_lib/Test-dep4-stdout.txt create mode 100644 Tests/RunCMake/compile_depends_no_lib/Test.cmake diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index d6618fe..b9cfc10 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -126,6 +126,7 @@ Properties on Targets /prop_tgt/COMPATIBLE_INTERFACE_NUMBER_MIN /prop_tgt/COMPATIBLE_INTERFACE_STRING /prop_tgt/COMPILE_DEFINITIONS + /prop_tgt/COMPILE_DEPENDS_NO_LIB /prop_tgt/COMPILE_FEATURES /prop_tgt/COMPILE_FLAGS /prop_tgt/COMPILE_OPTIONS diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index cb50051..c15f618 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -242,6 +242,7 @@ Variables that Control the Build /variable/CMAKE_AUTOUIC /variable/CMAKE_AUTOUIC_OPTIONS /variable/CMAKE_BUILD_WITH_INSTALL_RPATH + /variable/CMAKE_COMPILE_DEPENDS_NO_LIB /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG /variable/CMAKE_CONFIG_POSTFIX diff --git a/Help/prop_tgt/COMPILE_DEPENDS_NO_LIB.rst b/Help/prop_tgt/COMPILE_DEPENDS_NO_LIB.rst new file mode 100644 index 0000000..2ab8019 --- /dev/null +++ b/Help/prop_tgt/COMPILE_DEPENDS_NO_LIB.rst @@ -0,0 +1,45 @@ +COMPILE_DEPENDS_NO_LIB +---------------------- + +Ninja only: Whether object files skip dependencies on their target's link libraries. + +When set for a target the object file targets will not specify a dependency on +the target's link libraries. This way the object files can already be built even +though the target link libraries are not yet available. + +As an example consider the following snippet: + +.. code-block:: cmake + + ADD_LIBRARY(mylib lib.c) + + ADD_EXECUTABLE(myexe exe.c) + TARGET_LINK_LIBRARIES(myexe lib) + +As the target ``mylib`` might specify some more outputs (e.g. via +`ADD_CUSTOM_COMMAND`), the default behaviour is to let the compilation of +``exe.c`` depend on the completion of the target ``mylib``. If the target +property `COMPILE_DEPENDS_NO_LIB` is set for ``myexe``, either through the +global default + +.. code-block:: cmake + + SET(CMAKE_COMPILE_DEPENDS_NO_LIB) + +or through a target specific property + +.. code-block:: cmake + + SET_PROPERTY(TARGET myexe PROPERTY COMPILE_DEPENDS_NO_LIB ON) + +the dependency will be omitted and ``exe.c`` can be compiled without waiting for +the successful link of ``mylib``. + +.. note:: + If the compilation of your object files depends on a byproduct that is + produced during the creation of one of the link libraries, you have to + disable the functionality for the affected target. + +This property is initialized by the value of the variable +:variable:`CMAKE_COMPILE_DEPENDS_NO_LIB` if it is set when a target is created. + diff --git a/Help/variable/CMAKE_COMPILE_DEPENDS_NO_LIB.rst b/Help/variable/CMAKE_COMPILE_DEPENDS_NO_LIB.rst new file mode 100644 index 0000000..f72e68b --- /dev/null +++ b/Help/variable/CMAKE_COMPILE_DEPENDS_NO_LIB.rst @@ -0,0 +1,8 @@ +CMAKE_COMPILE_DEPENDS_NO_LIB +---------------------------- + +Whether to skip compile time dependencies of object files to libraries. + +This variable initializes the :prop_tgt:`COMPILE_DEPENDS_NO_LIB` property on +targets when they are created. See that target property for additional +information. diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 83422b7..bf38c09 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -982,7 +982,8 @@ cmGlobalNinjaGenerator void cmGlobalNinjaGenerator -::AppendTargetDepends(cmGeneratorTarget const* target, cmNinjaDeps& outputs) +::AppendTargetDepends(cmGeneratorTarget const* target, cmNinjaDeps& outputs, + const bool writeObjects) { if (target->GetType() == cmState::GLOBAL_TARGET) { // Global targets only depend on other utilities, which may not appear in @@ -992,10 +993,22 @@ cmGlobalNinjaGenerator } else { cmNinjaDeps outs; cmTargetDependSet const& targetDeps = this->GetTargetDirectDepends(target); + const bool noLibs = writeObjects && + target->GetPropertyAsBool("COMPILE_DEPENDS_NO_LIB"); for (cmTargetDependSet::const_iterator i = targetDeps.begin(); i != targetDeps.end(); ++i) { - if ((*i)->GetType() == cmState::INTERFACE_LIBRARY) + + const cmState::TargetType& type = (*i)->GetType(); + if (noLibs && (type == cmState::MODULE_LIBRARY || + type == cmState::SHARED_LIBRARY || + type == cmState::OBJECT_LIBRARY || + type == cmState::STATIC_LIBRARY)) + { + continue; + } + + if (type == cmState::INTERFACE_LIBRARY) { continue; } diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 8656590..65c5b83 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -295,7 +295,8 @@ public: void AppendTargetOutputs(cmGeneratorTarget const* target, cmNinjaDeps& outputs); void AppendTargetDepends(cmGeneratorTarget const* target, - cmNinjaDeps& outputs); + cmNinjaDeps& outputs, + const bool writeObjects = false); void AddDependencyToAll(cmGeneratorTarget* target); void AddDependencyToAll(const std::string& input); diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 8a68af6..713990e 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -292,9 +292,11 @@ cmLocalNinjaGenerator void cmLocalNinjaGenerator -::AppendTargetDepends(cmGeneratorTarget* target, cmNinjaDeps& outputs) +::AppendTargetDepends(cmGeneratorTarget* target, + cmNinjaDeps& outputs, const bool writeObjects) { - this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs); + this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs, + writeObjects); } void cmLocalNinjaGenerator::AppendCustomCommandDeps( diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index 5e1d6f2..bf45246 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -59,7 +59,8 @@ public: std::string BuildCommandLine(const std::vector<std::string> &cmdLines); void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs); - void AppendTargetDepends(cmGeneratorTarget* target, cmNinjaDeps& outputs); + void AppendTargetDepends(cmGeneratorTarget* target, cmNinjaDeps& outputs, + const bool writeObjects = false); void AddCustomCommandTarget(cmCustomCommand const* cc, cmGeneratorTarget* target); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 5ff4fdb..c4ceb27 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -514,7 +514,7 @@ cmNinjaTargetGenerator cmNinjaDeps orderOnlyDeps; this->GetLocalGenerator()->AppendTargetDepends(this->GeneratorTarget, - orderOnlyDeps); + orderOnlyDeps, true); // Add order-only dependencies on custom command outputs. for(std::vector<cmCustomCommand const*>::const_iterator diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 576189f..92c8581 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -137,6 +137,7 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->SetPropertyDefault("AUTOUIC_OPTIONS", 0); this->SetPropertyDefault("AUTORCC_OPTIONS", 0); this->SetPropertyDefault("LINK_DEPENDS_NO_SHARED", 0); + this->SetPropertyDefault("COMPILE_DEPENDS_NO_LIB", 0); this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", 0); this->SetPropertyDefault("WIN32_EXECUTABLE", 0); this->SetPropertyDefault("MACOSX_BUNDLE", 0); diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 588f3a1..abf2307 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -116,6 +116,7 @@ if(CMAKE_GENERATOR MATCHES "Make") endif() if(CMAKE_GENERATOR STREQUAL "Ninja") add_RunCMake_test(Ninja) + add_RunCMake_test(compile_depends_no_lib) endif() add_RunCMake_test(CTest) diff --git a/Tests/RunCMake/compile_depends_no_lib/CMakeLists.txt b/Tests/RunCMake/compile_depends_no_lib/CMakeLists.txt new file mode 100644 index 0000000..93ee9df --- /dev/null +++ b/Tests/RunCMake/compile_depends_no_lib/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.5) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/compile_depends_no_lib/RunCMakeTest.cmake b/Tests/RunCMake/compile_depends_no_lib/RunCMakeTest.cmake new file mode 100644 index 0000000..0f0ed3a --- /dev/null +++ b/Tests/RunCMake/compile_depends_no_lib/RunCMakeTest.cmake @@ -0,0 +1,16 @@ +include(RunCMake) + +set(RunCMake_TEST_NO_CLEAN 1) +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}) +MESSAGE(STATUS ${RunCMake_BINARY_DIR}) +file(REMOVE_RECURSE ${RunCMake_BINARY_DIR}) +run_cmake(Test) +file(READ ${RunCMake_BINARY_DIR}/ext ext) +run_cmake_command(Test-dep1 ${CMAKE_COMMAND} --build . --target CMakeFiles/dependent1.dir/test.c${ext}) +run_cmake_command(Test ${CMAKE_COMMAND} --build . --target clean) +run_cmake_command(Test-dep2 ${CMAKE_COMMAND} --build . --target CMakeFiles/dependent2.dir/test.c${ext}) +run_cmake_command(Test ${CMAKE_COMMAND} --build . --target clean) +run_cmake_command(Test-dep3 ${CMAKE_COMMAND} --build . --target CMakeFiles/dependent3.dir/test.c${ext}) +run_cmake_command(Test ${CMAKE_COMMAND} --build . --target clean) +run_cmake_command(Test-dep4 ${CMAKE_COMMAND} --build . --target CMakeFiles/dependent4.dir/test.c${ext}) +run_cmake_command(Test ${CMAKE_COMMAND} --build . --target clean) diff --git a/Tests/RunCMake/compile_depends_no_lib/Test-dep1-stdout.txt b/Tests/RunCMake/compile_depends_no_lib/Test-dep1-stdout.txt new file mode 100644 index 0000000..640e7d3 --- /dev/null +++ b/Tests/RunCMake/compile_depends_no_lib/Test-dep1-stdout.txt @@ -0,0 +1,3 @@ +\[1/3\] Building C object .* +\[2/3\] Linking C static library .* +\[3/3\] Building C object .* diff --git a/Tests/RunCMake/compile_depends_no_lib/Test-dep2-stdout.txt b/Tests/RunCMake/compile_depends_no_lib/Test-dep2-stdout.txt new file mode 100644 index 0000000..6fcfddc --- /dev/null +++ b/Tests/RunCMake/compile_depends_no_lib/Test-dep2-stdout.txt @@ -0,0 +1 @@ +\[1/1\] Building C object .* diff --git a/Tests/RunCMake/compile_depends_no_lib/Test-dep3-stdout.txt b/Tests/RunCMake/compile_depends_no_lib/Test-dep3-stdout.txt new file mode 100644 index 0000000..6fcfddc --- /dev/null +++ b/Tests/RunCMake/compile_depends_no_lib/Test-dep3-stdout.txt @@ -0,0 +1 @@ +\[1/1\] Building C object .* diff --git a/Tests/RunCMake/compile_depends_no_lib/Test-dep4-stdout.txt b/Tests/RunCMake/compile_depends_no_lib/Test-dep4-stdout.txt new file mode 100644 index 0000000..640e7d3 --- /dev/null +++ b/Tests/RunCMake/compile_depends_no_lib/Test-dep4-stdout.txt @@ -0,0 +1,3 @@ +\[1/3\] Building C object .* +\[2/3\] Linking C static library .* +\[3/3\] Building C object .* diff --git a/Tests/RunCMake/compile_depends_no_lib/Test.cmake b/Tests/RunCMake/compile_depends_no_lib/Test.cmake new file mode 100644 index 0000000..1308638 --- /dev/null +++ b/Tests/RunCMake/compile_depends_no_lib/Test.cmake @@ -0,0 +1,29 @@ +project(compile_depends_no_lib) +set(test_source ${CMAKE_CURRENT_BINARY_DIR}/test.c) +execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${test_source} + COMMAND ${CMAKE_COMMAND} -E touch ${test_source}) + +add_library(lib ${test_source}) + +# test case 1 : default off +add_library(dependent1 ${test_source}) +target_link_libraries(dependent1 lib) + +# test case 2 : default off, turned on per target +add_library(dependent2 ${test_source}) +target_link_libraries(dependent2 lib) +set_property(TARGET dependent2 PROPERTY COMPILE_DEPENDS_NO_LIB ON) + +set(CMAKE_COMPILE_DEPENDS_NO_LIB ON) + +# test case 3 : default on +add_library(dependent3 ${test_source}) +target_link_libraries(dependent3 lib) + +# test case 4 : default on, turned off per target +add_library(dependent4 ${test_source}) +target_link_libraries(dependent4 lib) +set_property(TARGET dependent4 PROPERTY COMPILE_DEPENDS_NO_LIB OFF) + +# persist the object file extension +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/ext ${CMAKE_C_OUTPUT_EXTENSION}) -- 2.7.3
-- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers