Merge topic 'run-include-what-you-use'

ada5ffce Add options to run include-what-you-use with the compiler
67fa3da9 cmake: Add internal -E mode to run include-what-you-use with the compiler
This commit is contained in:
Brad King 2015-05-21 09:03:40 -04:00 committed by CMake Topic Stage
commit 03a65dab30
28 changed files with 207 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,13 @@
<LANG>_INCLUDE_WHAT_YOU_USE
---------------------------
This property is implemented only when ``<LANG>`` is ``C`` or ``CXX``.
Specify a :ref:`;-list <CMake Language Lists>` 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_<LANG>_INCLUDE_WHAT_YOU_USE` variable if it is set
when a target is created.

View File

@ -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_<LANG>_INCLUDE_WHAT_YOU_USE` variable and
:prop_tgt:`<LANG>_INCLUDE_WHAT_YOU_USE` target property for details.

View File

@ -0,0 +1,6 @@
CMAKE_<LANG>_INCLUDE_WHAT_YOU_USE
---------------------------------
Default value for :prop_tgt:`<LANG>_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 ``<LANG>`` is ``C`` or ``CXX``.

View File

@ -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,

View File

@ -458,6 +458,23 @@ cmNinjaTargetGenerator
std::vector<std::string> 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);

View File

@ -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);

View File

@ -211,6 +211,88 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
return 0;
}
// run include what you use command and then run the compile
// command. This is an internal undocumented option and should
// only be used by CMake itself when running iwyu.
else if (args[1] == "__run_iwyu")
{
if (args.size() < 3)
{
std::cerr << "__run_iwyu Usage: -E __run_iwyu [--iwyu=/path/iwyu]"
" -- compile command\n";
return 1;
}
bool doing_options = true;
std::vector<std::string> orig_cmd;
std::string iwyu;
for (std::string::size_type cc = 2; cc < args.size(); cc ++)
{
std::string const& arg = args[cc];
if (arg == "--")
{
doing_options = false;
}
else if (doing_options && cmHasLiteralPrefix(arg, "--iwyu="))
{
iwyu = arg.substr(7);
}
else if (doing_options)
{
std::cerr << "__run_iwyu given unknown argument: " << arg << "\n";
return 1;
}
else
{
orig_cmd.push_back(arg);
}
}
if (iwyu.empty())
{
std::cerr << "__run_iwyu missing --iwyu=\n";
return 1;
}
if (orig_cmd.empty())
{
std::cerr << "__run_iwyu missing compile command after --\n";
return 1;
}
// Construct the iwyu command line by taking what was given
// and adding all the arguments we give to the compiler.
std::vector<std::string> iwyu_cmd;
cmSystemTools::ExpandListArgument(iwyu, iwyu_cmd, true);
iwyu_cmd.insert(iwyu_cmd.end(), orig_cmd.begin()+1, orig_cmd.end());
// Run the iwyu command line. Capture its stderr and hide its stdout.
int ret = 0;
std::string stdErr;
if(!cmSystemTools::RunSingleCommand(iwyu_cmd, 0, &stdErr, &ret,
0, cmSystemTools::OUTPUT_NONE))
{
std::cerr << "Error running '" << iwyu_cmd[0] << "': "
<< stdErr << "\n";
return 1;
}
// Warn if iwyu reported anything.
if(stdErr.find("should remove these lines:") != stdErr.npos
|| stdErr.find("should add these lines:") != stdErr.npos)
{
std::cerr << "Warning: include-what-you-use reported diagnostics:\n"
<< stdErr << "\n";
}
// Now run the real compiler command and return its result value.
if(!cmSystemTools::RunSingleCommand(orig_cmd, 0, &stdErr, &ret, 0,
cmSystemTools::OUTPUT_PASSTHROUGH))
{
std::cerr << "Error running '" << orig_cmd[0] << "': "
<< stdErr << "\n";
return 1;
}
return ret;
}
// Echo string
else if (args[1] == "echo" )
{

View File

@ -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=$<TARGET_FILE:pseudo_iwyu>)
endif()

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
^Error running 'iwyu-does-not-exist': [^
]+$

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1 @@
^__run_iwyu given unknown argument: command-does-not-exist$

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1 @@
^__run_iwyu missing compile command after --$

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1 @@
^__run_iwyu missing --iwyu=$

View File

@ -12,6 +12,11 @@ run_cmake_command(E_echo_append ${CMAKE_COMMAND} -E echo_append)
run_cmake_command(E_rename-no-arg ${CMAKE_COMMAND} -E rename)
run_cmake_command(E_touch_nocreate-no-arg ${CMAKE_COMMAND} -E touch_nocreate)
run_cmake_command(E___run_iwyu-no-iwyu ${CMAKE_COMMAND} -E __run_iwyu -- command-does-not-exist)
run_cmake_command(E___run_iwyu-bad-iwyu ${CMAKE_COMMAND} -E __run_iwyu --iwyu=iwyu-does-not-exist -- command-does-not-exist)
run_cmake_command(E___run_iwyu-no--- ${CMAKE_COMMAND} -E __run_iwyu --iwyu=iwyu-does-not-exist command-does-not-exist)
run_cmake_command(E___run_iwyu-no-cc ${CMAKE_COMMAND} -E __run_iwyu --iwyu=iwyu-does-not-exist --)
run_cmake_command(G_no-arg ${CMAKE_COMMAND} -G)
run_cmake_command(G_bad-arg ${CMAKE_COMMAND} -G NoSuchGenerator)
run_cmake_command(P_no-arg ${CMAKE_COMMAND} -P)

View File

@ -0,0 +1,4 @@
Warning: include-what-you-use reported diagnostics:
should add these lines:
*
#include <\.\.\.>

View File

@ -0,0 +1,3 @@
enable_language(C)
set(CMAKE_C_INCLUDE_WHAT_YOU_USE "${PSEUDO_IWYU}" -some -args)
add_executable(main main.c)

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.2)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1,4 @@
Warning: include-what-you-use reported diagnostics:
should add these lines:
*
#include <\.\.\.>

View File

@ -0,0 +1,3 @@
enable_language(CXX)
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "${PSEUDO_IWYU}" -some -args)
add_executable(main main.cxx)

View File

@ -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)

View File

@ -0,0 +1 @@
int main(void) { return 0; }

View File

@ -0,0 +1 @@
int main() { return 0; }

View File

@ -0,0 +1,7 @@
#include <stdio.h>
int main(void)
{
fprintf(stderr, "should add these lines:\n#include <...>\n");
return 0;
}