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

Reply via email to