From ada5ffce7bad40c56e5d0dd76b9a7b30c96a9e92 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 18 May 2015 14:39:25 -0400 Subject: [PATCH] Add options to run include-what-you-use with the compiler Create a _INCLUDE_WHAT_YOU_USE target property (initialized by a CMAKE__INCLUDE_WHAT_YOU_USE variable) to specify an IWYU command line to be run along with the compiler. --- Help/manual/cmake-properties.7.rst | 1 + Help/manual/cmake-variables.7.rst | 1 + Help/prop_tgt/LANG_INCLUDE_WHAT_YOU_USE.rst | 13 +++++++++++++ Help/release/dev/run-include-what-you-use.rst | 8 ++++++++ .../CMAKE_LANG_INCLUDE_WHAT_YOU_USE.rst | 6 ++++++ Source/cmMakefileTargetGenerator.cxx | 14 ++++++++++++++ Source/cmNinjaTargetGenerator.cxx | 17 +++++++++++++++++ Source/cmTarget.cxx | 2 ++ Tests/RunCMake/CMakeLists.txt | 5 +++++ .../IncludeWhatYouUse/C-Build-stdout.txt | 4 ++++ Tests/RunCMake/IncludeWhatYouUse/C.cmake | 3 +++ .../RunCMake/IncludeWhatYouUse/CMakeLists.txt | 3 +++ .../IncludeWhatYouUse/CXX-Build-stdout.txt | 4 ++++ Tests/RunCMake/IncludeWhatYouUse/CXX.cmake | 3 +++ .../IncludeWhatYouUse/RunCMakeTest.cmake | 18 ++++++++++++++++++ Tests/RunCMake/IncludeWhatYouUse/main.c | 1 + Tests/RunCMake/IncludeWhatYouUse/main.cxx | 1 + Tests/RunCMake/pseudo_iwyu.c | 7 +++++++ 18 files changed, 111 insertions(+) create mode 100644 Help/prop_tgt/LANG_INCLUDE_WHAT_YOU_USE.rst create mode 100644 Help/release/dev/run-include-what-you-use.rst create mode 100644 Help/variable/CMAKE_LANG_INCLUDE_WHAT_YOU_USE.rst create mode 100644 Tests/RunCMake/IncludeWhatYouUse/C-Build-stdout.txt create mode 100644 Tests/RunCMake/IncludeWhatYouUse/C.cmake create mode 100644 Tests/RunCMake/IncludeWhatYouUse/CMakeLists.txt create mode 100644 Tests/RunCMake/IncludeWhatYouUse/CXX-Build-stdout.txt create mode 100644 Tests/RunCMake/IncludeWhatYouUse/CXX.cmake create mode 100644 Tests/RunCMake/IncludeWhatYouUse/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/IncludeWhatYouUse/main.c create mode 100644 Tests/RunCMake/IncludeWhatYouUse/main.cxx create mode 100644 Tests/RunCMake/pseudo_iwyu.c diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 02d164b5c..615254e6a 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_INCLUDE_WHAT_YOU_USE /prop_tgt/LANG_VISIBILITY_PRESET /prop_tgt/LIBRARY_OUTPUT_DIRECTORY_CONFIG /prop_tgt/LIBRARY_OUTPUT_DIRECTORY diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index e6c966b8b..bd02f8b8b 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_INCLUDE_WHAT_YOU_USE /variable/CMAKE_LANG_VISIBILITY_PRESET /variable/CMAKE_LIBRARY_OUTPUT_DIRECTORY /variable/CMAKE_LIBRARY_OUTPUT_DIRECTORY_CONFIG diff --git a/Help/prop_tgt/LANG_INCLUDE_WHAT_YOU_USE.rst b/Help/prop_tgt/LANG_INCLUDE_WHAT_YOU_USE.rst new file mode 100644 index 000000000..26f6d1671 --- /dev/null +++ b/Help/prop_tgt/LANG_INCLUDE_WHAT_YOU_USE.rst @@ -0,0 +1,13 @@ +_INCLUDE_WHAT_YOU_USE +--------------------------- + +This property is implemented only when ```` is ``C`` or ``CXX``. + +Specify a :ref:`;-list ` containing a command +line for the ``include-what-you-use`` tool. The :ref:`Makefile Generators` +and the :generator:`Ninja` generator will run this tool along with the +compiler and report a warning if the tool reports any problems. + +This property is initialized by the value of +the :variable:`CMAKE__INCLUDE_WHAT_YOU_USE` variable if it is set +when a target is created. diff --git a/Help/release/dev/run-include-what-you-use.rst b/Help/release/dev/run-include-what-you-use.rst new file mode 100644 index 000000000..baac21ffa --- /dev/null +++ b/Help/release/dev/run-include-what-you-use.rst @@ -0,0 +1,8 @@ +run-include-what-you-use +------------------------ + +* The :ref:`Makefile Generators` and the :generator:`Ninja` generator + learned to optionally run ``include-what-you-use`` along with the + compiler for ``C`` and ``CXX`` languages. See the + :variable:`CMAKE__INCLUDE_WHAT_YOU_USE` variable and + :prop_tgt:`_INCLUDE_WHAT_YOU_USE` target property for details. diff --git a/Help/variable/CMAKE_LANG_INCLUDE_WHAT_YOU_USE.rst b/Help/variable/CMAKE_LANG_INCLUDE_WHAT_YOU_USE.rst new file mode 100644 index 000000000..2c8028a60 --- /dev/null +++ b/Help/variable/CMAKE_LANG_INCLUDE_WHAT_YOU_USE.rst @@ -0,0 +1,6 @@ +CMAKE__INCLUDE_WHAT_YOU_USE +--------------------------------- + +Default value for :prop_tgt:`_INCLUDE_WHAT_YOU_USE` 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 2ee23d18a..893b70d0d 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -768,6 +768,20 @@ cmMakefileTargetGenerator this->LocalGenerator->ExpandRuleVariables(*i, vars); } + // Maybe insert an include-what-you-use runner. + if (!compileCommands.empty() && (lang == "C" || lang == "CXX")) + { + std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE"; + const char *iwyu = this->Target->GetProperty(iwyu_prop); + if (iwyu && *iwyu) + { + std::string run_iwyu = "$(CMAKE_COMMAND) -E __run_iwyu --iwyu="; + run_iwyu += this->LocalGenerator->EscapeForShell(iwyu); + run_iwyu += " -- "; + compileCommands.front().insert(0, run_iwyu); + } + } + // Change the command working directory to the local build tree. this->LocalGenerator->CreateCDCommand (compileCommands, diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index cdc9cc8c7..879d6b79e 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -458,6 +458,23 @@ cmNinjaTargetGenerator std::vector compileCmds; cmSystemTools::ExpandListArgument(compileCmd, compileCmds); + // Maybe insert an include-what-you-use runner. + if (!compileCmds.empty() && (lang == "C" || lang == "CXX")) + { + std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE"; + const char *iwyu = this->Target->GetProperty(iwyu_prop); + if (iwyu && *iwyu) + { + std::string run_iwyu = + this->GetLocalGenerator()->ConvertToOutputFormat( + cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); + run_iwyu += " -E __run_iwyu --iwyu="; + run_iwyu += this->GetLocalGenerator()->EscapeForShell(iwyu); + run_iwyu += " -- "; + compileCmds.front().insert(0, run_iwyu); + } + } + if (!compileCmds.empty()) { compileCmds.front().insert(0, cldeps); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 8a8c163a2..7d0d21698 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -333,9 +333,11 @@ 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_INCLUDE_WHAT_YOU_USE", 0); this->SetPropertyDefault("C_STANDARD", 0); this->SetPropertyDefault("C_STANDARD_REQUIRED", 0); this->SetPropertyDefault("C_EXTENSIONS", 0); + this->SetPropertyDefault("CXX_INCLUDE_WHAT_YOU_USE", 0); this->SetPropertyDefault("CXX_STANDARD", 0); this->SetPropertyDefault("CXX_STANDARD_REQUIRED", 0); this->SetPropertyDefault("CXX_EXTENSIONS", 0); diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 16fb05605..2100b5598 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -241,3 +241,8 @@ if(CMAKE_OSX_ARCHITECTURES AND XCODE AND NOT "${XCODE_VERSION}" MATCHES "^[^12]" PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CFG_INTDIR}" ) endif() + +if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") + add_executable(pseudo_iwyu pseudo_iwyu.c) + add_RunCMake_test(IncludeWhatYouUse -DPSEUDO_IWYU=$) +endif() diff --git a/Tests/RunCMake/IncludeWhatYouUse/C-Build-stdout.txt b/Tests/RunCMake/IncludeWhatYouUse/C-Build-stdout.txt new file mode 100644 index 000000000..cb7467705 --- /dev/null +++ b/Tests/RunCMake/IncludeWhatYouUse/C-Build-stdout.txt @@ -0,0 +1,4 @@ +Warning: include-what-you-use reported diagnostics: +should add these lines: +* +#include <\.\.\.> diff --git a/Tests/RunCMake/IncludeWhatYouUse/C.cmake b/Tests/RunCMake/IncludeWhatYouUse/C.cmake new file mode 100644 index 000000000..f400e861f --- /dev/null +++ b/Tests/RunCMake/IncludeWhatYouUse/C.cmake @@ -0,0 +1,3 @@ +enable_language(C) +set(CMAKE_C_INCLUDE_WHAT_YOU_USE "${PSEUDO_IWYU}" -some -args) +add_executable(main main.c) diff --git a/Tests/RunCMake/IncludeWhatYouUse/CMakeLists.txt b/Tests/RunCMake/IncludeWhatYouUse/CMakeLists.txt new file mode 100644 index 000000000..18dfd2686 --- /dev/null +++ b/Tests/RunCMake/IncludeWhatYouUse/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/IncludeWhatYouUse/CXX-Build-stdout.txt b/Tests/RunCMake/IncludeWhatYouUse/CXX-Build-stdout.txt new file mode 100644 index 000000000..cb7467705 --- /dev/null +++ b/Tests/RunCMake/IncludeWhatYouUse/CXX-Build-stdout.txt @@ -0,0 +1,4 @@ +Warning: include-what-you-use reported diagnostics: +should add these lines: +* +#include <\.\.\.> diff --git a/Tests/RunCMake/IncludeWhatYouUse/CXX.cmake b/Tests/RunCMake/IncludeWhatYouUse/CXX.cmake new file mode 100644 index 000000000..896930c16 --- /dev/null +++ b/Tests/RunCMake/IncludeWhatYouUse/CXX.cmake @@ -0,0 +1,3 @@ +enable_language(CXX) +set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "${PSEUDO_IWYU}" -some -args) +add_executable(main main.cxx) diff --git a/Tests/RunCMake/IncludeWhatYouUse/RunCMakeTest.cmake b/Tests/RunCMake/IncludeWhatYouUse/RunCMakeTest.cmake new file mode 100644 index 000000000..68c6bd7d0 --- /dev/null +++ b/Tests/RunCMake/IncludeWhatYouUse/RunCMakeTest.cmake @@ -0,0 +1,18 @@ +include(RunCMake) + +set(RunCMake_TEST_OPTIONS "-DPSEUDO_IWYU=${PSEUDO_IWYU}") + +function(run_iwyu 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) + run_cmake_command(${lang}-Build ${CMAKE_COMMAND} --build .) +endfunction() + +run_iwyu(C) +run_iwyu(CXX) diff --git a/Tests/RunCMake/IncludeWhatYouUse/main.c b/Tests/RunCMake/IncludeWhatYouUse/main.c new file mode 100644 index 000000000..78f2de106 --- /dev/null +++ b/Tests/RunCMake/IncludeWhatYouUse/main.c @@ -0,0 +1 @@ +int main(void) { return 0; } diff --git a/Tests/RunCMake/IncludeWhatYouUse/main.cxx b/Tests/RunCMake/IncludeWhatYouUse/main.cxx new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/Tests/RunCMake/IncludeWhatYouUse/main.cxx @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/Tests/RunCMake/pseudo_iwyu.c b/Tests/RunCMake/pseudo_iwyu.c new file mode 100644 index 000000000..1e25de74c --- /dev/null +++ b/Tests/RunCMake/pseudo_iwyu.c @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + fprintf(stderr, "should add these lines:\n#include <...>\n"); + return 0; +}