From 698f75971bee336133d21260db069bb139bd3d76 Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Thu, 4 Jun 2015 15:56:56 -0400 Subject: [PATCH] Add options to launch the compiler through tools like ccache or distcc Create a _COMPILER_LAUNCHER target property (initialized by a CMAKE__COMPILER_LAUNCHER variable) to specify a compiler launcher tool. This will supersede the CMAKE__COMPILER_ARG1 approach to using such tools. The old approach set CMAKE__COMPILER to the launcher tool while the new approach leaves this variable set to the actual compiler. Implement this property for Makefile and Ninja generators. It cannot be implemented for VS or Xcode generators as the IDE build tools offer no such hooks. --- Help/manual/cmake-properties.7.rst | 1 + Help/manual/cmake-variables.7.rst | 1 + Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst | 13 +++++++++++ Help/release/dev/compiler-launcher.rst | 8 +++++++ .../variable/CMAKE_LANG_COMPILER_LAUNCHER.rst | 6 +++++ Source/cmMakefileTargetGenerator.cxx | 19 +++++++++++++++ Source/cmNinjaTargetGenerator.cxx | 20 ++++++++++++++++ Source/cmTarget.cxx | 2 ++ Tests/RunCMake/CMakeLists.txt | 1 + .../CompilerLauncher/C-Build-stdout.txt | 1 + .../C-launch-Build-stdout.txt | 1 + .../RunCMake/CompilerLauncher/C-launch.cmake | 3 +++ Tests/RunCMake/CompilerLauncher/C.cmake | 4 ++++ .../RunCMake/CompilerLauncher/CMakeLists.txt | 3 +++ .../CompilerLauncher/CXX-Build-stdout.txt | 1 + .../CXX-launch-Build-stdout.txt | 1 + .../CompilerLauncher/CXX-launch.cmake | 3 +++ Tests/RunCMake/CompilerLauncher/CXX.cmake | 4 ++++ .../CompilerLauncher/RunCMakeTest.cmake | 23 +++++++++++++++++++ Tests/RunCMake/CompilerLauncher/main.c | 3 +++ Tests/RunCMake/CompilerLauncher/main.cxx | 1 + 21 files changed, 119 insertions(+) create mode 100644 Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst create mode 100644 Help/release/dev/compiler-launcher.rst create mode 100644 Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst create mode 100644 Tests/RunCMake/CompilerLauncher/C-Build-stdout.txt create mode 100644 Tests/RunCMake/CompilerLauncher/C-launch-Build-stdout.txt create mode 100644 Tests/RunCMake/CompilerLauncher/C-launch.cmake create mode 100644 Tests/RunCMake/CompilerLauncher/C.cmake create mode 100644 Tests/RunCMake/CompilerLauncher/CMakeLists.txt create mode 100644 Tests/RunCMake/CompilerLauncher/CXX-Build-stdout.txt create mode 100644 Tests/RunCMake/CompilerLauncher/CXX-launch-Build-stdout.txt create mode 100644 Tests/RunCMake/CompilerLauncher/CXX-launch.cmake create mode 100644 Tests/RunCMake/CompilerLauncher/CXX.cmake create mode 100644 Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/CompilerLauncher/main.c create mode 100644 Tests/RunCMake/CompilerLauncher/main.cxx diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 615254e6a..9a60a103c 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -177,6 +177,7 @@ Properties on Targets /prop_tgt/JOB_POOL_COMPILE /prop_tgt/JOB_POOL_LINK /prop_tgt/LABELS + /prop_tgt/LANG_COMPILER_LAUNCHER /prop_tgt/LANG_INCLUDE_WHAT_YOU_USE /prop_tgt/LANG_VISIBILITY_PRESET /prop_tgt/LIBRARY_OUTPUT_DIRECTORY_CONFIG diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index bd02f8b8b..2b920069b 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -235,6 +235,7 @@ Variables that Control the Build /variable/CMAKE_INSTALL_NAME_DIR /variable/CMAKE_INSTALL_RPATH /variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH + /variable/CMAKE_LANG_COMPILER_LAUNCHER /variable/CMAKE_LANG_INCLUDE_WHAT_YOU_USE /variable/CMAKE_LANG_VISIBILITY_PRESET /variable/CMAKE_LIBRARY_OUTPUT_DIRECTORY diff --git a/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst b/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst new file mode 100644 index 000000000..0fe0b31e5 --- /dev/null +++ b/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst @@ -0,0 +1,13 @@ +_COMPILER_LAUNCHER +------------------------ + +This property is implemented only when ```` is ``C`` or ``CXX``. + +Specify a :ref:`;-list ` containing a command line +for a compiler launching tool. The :ref:`Makefile Generators` and the +:generator:`Ninja` generator will run this tool and pass the compiler and +its arguments to the tool. Some example tools are distcc and ccache. + +This property is initialized by the value of +the :variable:`CMAKE__COMPILER_LAUNCHER` variable if it is set +when a target is created. diff --git a/Help/release/dev/compiler-launcher.rst b/Help/release/dev/compiler-launcher.rst new file mode 100644 index 000000000..3ba692da4 --- /dev/null +++ b/Help/release/dev/compiler-launcher.rst @@ -0,0 +1,8 @@ +compiler-launcher +----------------- + +* The :ref:`Makefile Generators` and the :generator:`Ninja` generator + learned to add compiler launcher tools like distcc and ccache along with the + compiler for ``C`` and ``CXX`` languages. See the + :variable:`CMAKE__COMPILER_LAUNCHER` variable and + :prop_tgt:`_COMPILER_LAUNCHER` target property for details. diff --git a/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst b/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst new file mode 100644 index 000000000..7961f609e --- /dev/null +++ b/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst @@ -0,0 +1,6 @@ +CMAKE__COMPILER_LAUNCHER +------------------------------ + +Default value for :prop_tgt:`_COMPILER_LAUNCHER` target property. +This variable is used to initialize the property on each target as it is +created. This is done only when ```` is ``C`` or ``CXX``. diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 7b88bc7b2..481f4fee6 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -775,6 +775,25 @@ cmMakefileTargetGenerator } } + // Maybe insert a compiler launcher like ccache or distcc + if (!compileCommands.empty() && (lang == "C" || lang == "CXX")) + { + std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER"; + const char *clauncher = this->Target->GetProperty(clauncher_prop); + if (clauncher && *clauncher) + { + std::vector launcher_cmd; + cmSystemTools::ExpandListArgument(clauncher, launcher_cmd, true); + for (std::vector::iterator i = launcher_cmd.begin(), + e = launcher_cmd.end(); i != e; ++i) + { + *i = this->LocalGenerator->EscapeForShell(*i); + } + std::string const& run_launcher = cmJoin(launcher_cmd, " ") + " "; + compileCommands.front().insert(0, run_launcher); + } + } + // Expand placeholders in the commands. for(std::vector::iterator i = compileCommands.begin(); i != compileCommands.end(); ++i) diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 879d6b79e..bb75e09d2 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -22,6 +22,7 @@ #include "cmComputeLinkInformation.h" #include "cmSourceFile.h" #include "cmCustomCommandGenerator.h" +#include "cmAlgorithms.h" #include @@ -475,6 +476,25 @@ cmNinjaTargetGenerator } } + // Maybe insert a compiler launcher like ccache or distcc + if (!compileCmds.empty() && (lang == "C" || lang == "CXX")) + { + std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER"; + const char *clauncher = this->Target->GetProperty(clauncher_prop); + if (clauncher && *clauncher) + { + std::vector launcher_cmd; + cmSystemTools::ExpandListArgument(clauncher, launcher_cmd, true); + for (std::vector::iterator i = launcher_cmd.begin(), + e = launcher_cmd.end(); i != e; ++i) + { + *i = this->LocalGenerator->EscapeForShell(*i); + } + std::string const& run_launcher = cmJoin(launcher_cmd, " ") + " "; + compileCmds.front().insert(0, run_launcher); + } + } + if (!compileCmds.empty()) { compileCmds.front().insert(0, cldeps); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 70005b4fa..e20f0af8e 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -333,10 +333,12 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->SetPropertyDefault("MACOSX_BUNDLE", 0); this->SetPropertyDefault("MACOSX_RPATH", 0); this->SetPropertyDefault("NO_SYSTEM_FROM_IMPORTED", 0); + this->SetPropertyDefault("C_COMPILER_LAUNCHER", 0); this->SetPropertyDefault("C_INCLUDE_WHAT_YOU_USE", 0); this->SetPropertyDefault("C_STANDARD", 0); this->SetPropertyDefault("C_STANDARD_REQUIRED", 0); this->SetPropertyDefault("C_EXTENSIONS", 0); + this->SetPropertyDefault("CXX_COMPILER_LAUNCHER", 0); this->SetPropertyDefault("CXX_INCLUDE_WHAT_YOU_USE", 0); this->SetPropertyDefault("CXX_STANDARD", 0); this->SetPropertyDefault("CXX_STANDARD_REQUIRED", 0); diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 592b5e406..2a4108fdf 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -232,4 +232,5 @@ endif() if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") add_executable(pseudo_iwyu pseudo_iwyu.c) add_RunCMake_test(IncludeWhatYouUse -DPSEUDO_IWYU=$) + add_RunCMake_test(CompilerLauncher) endif() diff --git a/Tests/RunCMake/CompilerLauncher/C-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/C-Build-stdout.txt new file mode 100644 index 000000000..3313e31f6 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/C-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/C-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/C-launch-Build-stdout.txt new file mode 100644 index 000000000..3313e31f6 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/C-launch-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/C-launch.cmake b/Tests/RunCMake/CompilerLauncher/C-launch.cmake new file mode 100644 index 000000000..e66ca203e --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/C-launch.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(C.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/C.cmake b/Tests/RunCMake/CompilerLauncher/C.cmake new file mode 100644 index 000000000..67bf7c4ac --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/C.cmake @@ -0,0 +1,4 @@ +enable_language(C) +set(CMAKE_C_COMPILER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1") +set(CMAKE_VERBOSE_MAKEFILE TRUE) +add_executable(main main.c) diff --git a/Tests/RunCMake/CompilerLauncher/CMakeLists.txt b/Tests/RunCMake/CompilerLauncher/CMakeLists.txt new file mode 100644 index 000000000..18dfd2686 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.2) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/CXX-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/CXX-Build-stdout.txt new file mode 100644 index 000000000..3313e31f6 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/CXX-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/CXX-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/CXX-launch-Build-stdout.txt new file mode 100644 index 000000000..3313e31f6 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/CXX-launch-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/CXX-launch.cmake b/Tests/RunCMake/CompilerLauncher/CXX-launch.cmake new file mode 100644 index 000000000..3002c9d68 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/CXX-launch.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(CXX.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/CXX.cmake b/Tests/RunCMake/CompilerLauncher/CXX.cmake new file mode 100644 index 000000000..cdd347804 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/CXX.cmake @@ -0,0 +1,4 @@ +enable_language(CXX) +set(CMAKE_CXX_COMPILER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1") +set(CMAKE_VERBOSE_MAKEFILE TRUE) +add_executable(main main.cxx) diff --git a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake new file mode 100644 index 000000000..5884d5c4d --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake @@ -0,0 +1,23 @@ +include(RunCMake) + +function(run_compiler_launcher lang) + # Use a single build tree for tests without cleaning. + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${lang}-build) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + run_cmake(${lang}) + + set(RunCMake_TEST_OUTPUT_MERGE 1) + if("${RunCMake_GENERATOR}" STREQUAL "Ninja") + set(verbose_args -- -v) + endif() + run_cmake_command(${lang}-Build ${CMAKE_COMMAND} --build . ${verbose_args}) +endfunction() + +run_compiler_launcher(C) +run_compiler_launcher(CXX) +if (NOT RunCMake_GENERATOR STREQUAL "Watcom WMake") + run_compiler_launcher(C-launch) + run_compiler_launcher(CXX-launch) +endif() diff --git a/Tests/RunCMake/CompilerLauncher/main.c b/Tests/RunCMake/CompilerLauncher/main.c new file mode 100644 index 000000000..03b2213bb --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/main.c @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff --git a/Tests/RunCMake/CompilerLauncher/main.cxx b/Tests/RunCMake/CompilerLauncher/main.cxx new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/main.cxx @@ -0,0 +1 @@ +int main() { return 0; }