summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2017-09-15 12:53:00 +0000
committerKitware Robot <kwrobot@kitware.com>2017-09-15 08:54:32 -0400
commitc0c5f924fe46fcf83603117689b372cb8520c4bb (patch)
tree3abb6b0d1b361ce133ecdc8df41a679e7e7e37c7
parent3449c18c36a9acf29dfbb228ee76059cc4b9127f (diff)
parent3bbe95f58a8fb83e56ca9023ef01b9e70b391b05 (diff)
downloadcmake-c0c5f924fe46fcf83603117689b372cb8520c4bb.tar.gz
Merge topic 'refactor-iwyu-code'
3bbe95f5 Clean up iwyu code to not be one big if statement. Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !1247
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx2
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx2
-rw-r--r--Source/cmMakefileTargetGenerator.cxx2
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx2
-rw-r--r--Source/cmNinjaTargetGenerator.cxx2
-rw-r--r--Source/cmcmd.cxx507
-rw-r--r--Source/cmcmd.h19
-rw-r--r--Tests/RunCMake/CommandLine/E___run_co_compile-bad-iwyu-result.txt (renamed from Tests/RunCMake/CommandLine/E___run_iwyu-bad-iwyu-result.txt)0
-rw-r--r--Tests/RunCMake/CommandLine/E___run_co_compile-bad-iwyu-stderr.txt (renamed from Tests/RunCMake/CommandLine/E___run_iwyu-bad-iwyu-stderr.txt)0
-rw-r--r--Tests/RunCMake/CommandLine/E___run_co_compile-no----result.txt (renamed from Tests/RunCMake/CommandLine/E___run_iwyu-no----result.txt)0
-rw-r--r--Tests/RunCMake/CommandLine/E___run_co_compile-no----stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E___run_co_compile-no-cc-result.txt (renamed from Tests/RunCMake/CommandLine/E___run_iwyu-no-cc-result.txt)0
-rw-r--r--Tests/RunCMake/CommandLine/E___run_co_compile-no-cc-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E___run_co_compile-no-iwyu-result.txt (renamed from Tests/RunCMake/CommandLine/E___run_iwyu-no-iwyu-result.txt)0
-rw-r--r--Tests/RunCMake/CommandLine/E___run_co_compile-no-iwyu-stderr.txt5
-rw-r--r--Tests/RunCMake/CommandLine/E___run_iwyu-no----stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E___run_iwyu-no-cc-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E___run_iwyu-no-iwyu-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/RunCMakeTest.cmake8
-rw-r--r--Tests/RunCMake/Cppcheck/C-bad-Build-result.txt1
-rw-r--r--Tests/RunCMake/Cppcheck/C-bad-Build-stdout.txt2
-rw-r--r--Tests/RunCMake/Cppcheck/C-bad.cmake3
-rw-r--r--Tests/RunCMake/Cppcheck/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/pseudo_cppcheck.c13
24 files changed, 333 insertions, 241 deletions
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index e1745bd8c1..ebc8e300a0 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -618,7 +618,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
std::string cmakeCommand = this->LocalGenerator->ConvertToOutputFormat(
cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
- cmakeCommand += " -E __run_iwyu --lwyu=";
+ cmakeCommand += " -E __run_co_compile --lwyu=";
cmakeCommand += targetOutPathReal;
real_link_commands.push_back(cmakeCommand);
}
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 34c285c09e..68d73d47da 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -932,7 +932,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
(this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY)) {
std::string cmakeCommand = this->LocalGenerator->ConvertToOutputFormat(
cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
- cmakeCommand += " -E __run_iwyu --lwyu=";
+ cmakeCommand += " -E __run_co_compile --lwyu=";
cmakeCommand += targetOutPathReal;
real_link_commands.push_back(cmakeCommand);
}
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 2acd57a1bb..1e4e02e6a1 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -629,7 +629,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
const char* cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop);
if ((iwyu && *iwyu) || (tidy && *tidy) || (cpplint && *cpplint) ||
(cppcheck && *cppcheck)) {
- std::string run_iwyu = "$(CMAKE_COMMAND) -E __run_iwyu";
+ std::string run_iwyu = "$(CMAKE_COMMAND) -E __run_co_compile";
if (iwyu && *iwyu) {
run_iwyu += " --iwyu=";
run_iwyu += this->LocalGenerator->EscapeForShell(iwyu);
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 32377f8db7..8b331d5072 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -495,7 +495,7 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
std::string cmakeCommand =
this->GetLocalGenerator()->ConvertToOutputFormat(
cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
- cmakeCommand += " -E __run_iwyu --lwyu=";
+ cmakeCommand += " -E __run_co_compile --lwyu=";
cmGeneratorTarget& gt = *this->GetGeneratorTarget();
const std::string cfgName = this->GetConfigName();
std::string targetOutput = ConvertToNinjaPath(gt.GetFullPath(cfgName));
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 3760fc1c2b..3c1463ad3c 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -619,7 +619,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
(cppcheck && *cppcheck)) {
std::string run_iwyu = this->GetLocalGenerator()->ConvertToOutputFormat(
cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
- run_iwyu += " -E __run_iwyu";
+ run_iwyu += " -E __run_co_compile";
if (iwyu && *iwyu) {
run_iwyu += " --iwyu=";
run_iwyu += this->GetLocalGenerator()->EscapeForShell(iwyu);
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 91c229cc79..26868bc5b4 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -34,11 +34,14 @@
#include "cmsys/Process.h"
#include "cmsys/Terminal.h"
#include <algorithm>
+#include <functional>
#include <iostream>
+#include <map>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
+#include <utility>
class cmConnection;
@@ -157,6 +160,280 @@ static bool cmTarFilesFrom(std::string const& file,
return true;
}
+int cmcmd::HandleIWYU(const std::string& runCmd, const std::string&,
+ const std::vector<std::string>& orig_cmd)
+{
+ // 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(runCmd, 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.
+ // Ignore its return code because the tool always returns non-zero.
+ std::string stdErr;
+ int ret;
+ if (!cmSystemTools::RunSingleCommand(iwyu_cmd, nullptr, &stdErr, &ret,
+ nullptr, 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:") != std::string::npos ||
+ stdErr.find("should add these lines:") != std::string::npos) {
+ std::cerr << "Warning: include-what-you-use reported diagnostics:\n"
+ << stdErr << "\n";
+ }
+ // always return 0 we don't want to break the compile
+ return 0;
+}
+
+int cmcmd::HandleTidy(const std::string& runCmd, const std::string& sourceFile,
+ const std::vector<std::string>& orig_cmd)
+{
+ // Construct the clang-tidy command line by taking what was given
+ // and adding our compiler command line. The clang-tidy tool will
+ // automatically skip over the compiler itself and extract the
+ // options.
+ int ret;
+ std::vector<std::string> tidy_cmd;
+ cmSystemTools::ExpandListArgument(runCmd, tidy_cmd, true);
+ tidy_cmd.push_back(sourceFile);
+ tidy_cmd.push_back("--");
+ tidy_cmd.insert(tidy_cmd.end(), orig_cmd.begin(), orig_cmd.end());
+
+ // Run the tidy command line. Capture its stdout and hide its stderr.
+ std::string stdOut;
+ std::string stdErr;
+ if (!cmSystemTools::RunSingleCommand(tidy_cmd, &stdOut, &stdErr, &ret,
+ nullptr, cmSystemTools::OUTPUT_NONE)) {
+ std::cerr << "Error running '" << tidy_cmd[0] << "': " << stdErr << "\n";
+ return 1;
+ }
+ // Output the stdout from clang-tidy to stderr
+ std::cerr << stdOut;
+ // If clang-tidy exited with an error do the same.
+ if (ret != 0) {
+ std::cerr << stdErr;
+ }
+ return ret;
+}
+
+int cmcmd::HandleLWYU(const std::string& runCmd, const std::string&,
+ const std::vector<std::string>&)
+{
+ // Construct the ldd -r -u (link what you use lwyu) command line
+ // ldd -u -r lwuy target
+ std::vector<std::string> lwyu_cmd;
+ lwyu_cmd.push_back("ldd");
+ lwyu_cmd.push_back("-u");
+ lwyu_cmd.push_back("-r");
+ lwyu_cmd.push_back(runCmd);
+
+ // Run the ldd -u -r command line.
+ // Capture its stdout and hide its stderr.
+ // Ignore its return code because the tool always returns non-zero
+ // if there are any warnings, but we just want to warn.
+ std::string stdOut;
+ std::string stdErr;
+ int ret;
+ if (!cmSystemTools::RunSingleCommand(lwyu_cmd, &stdOut, &stdErr, &ret,
+ nullptr, cmSystemTools::OUTPUT_NONE)) {
+ std::cerr << "Error running '" << lwyu_cmd[0] << "': " << stdErr << "\n";
+ return 1;
+ }
+
+ // Output the stdout from ldd -r -u to stderr
+ // Warn if lwyu reported anything.
+ if (stdOut.find("Unused direct dependencies:") != std::string::npos) {
+ std::cerr << "Warning: " << stdOut;
+ }
+ return 0;
+}
+
+int cmcmd::HandleCppLint(const std::string& runCmd,
+ const std::string& sourceFile,
+ const std::vector<std::string>&)
+{
+ // Construct the cpplint command line.
+ std::vector<std::string> cpplint_cmd;
+ cmSystemTools::ExpandListArgument(runCmd, cpplint_cmd, true);
+ cpplint_cmd.push_back(sourceFile);
+
+ // Run the cpplint command line. Capture its output.
+ std::string stdOut;
+ int ret;
+ if (!cmSystemTools::RunSingleCommand(cpplint_cmd, &stdOut, &stdOut, &ret,
+ nullptr, cmSystemTools::OUTPUT_NONE)) {
+ std::cerr << "Error running '" << cpplint_cmd[0] << "': " << stdOut
+ << "\n";
+ return 1;
+ }
+
+ // Output the output from cpplint to stderr
+ std::cerr << stdOut;
+ return ret;
+}
+
+int cmcmd::HandleCppCheck(const std::string& runCmd,
+ const std::string& sourceFile,
+ const std::vector<std::string>& orig_cmd)
+{
+ // Construct the cpplint command line.
+ std::vector<std::string> cppcheck_cmd;
+ cmSystemTools::ExpandListArgument(runCmd, cppcheck_cmd, true);
+ // extract all the -D, -U, and -I options from the compile line
+ for (size_t i = 0; i < orig_cmd.size(); i++) {
+ const std::string& opt = orig_cmd[i];
+ if (opt.size() > 2) {
+ if ((opt[0] == '-') &&
+ ((opt[1] == 'D') || (opt[1] == 'I') || (opt[1] == 'U'))) {
+ cppcheck_cmd.push_back(opt);
+// convert cl / options to - options if needed
+#if defined(_WIN32)
+ } else if ((opt[0] == '/') &&
+ ((opt[1] == 'D') || (opt[1] == 'I') || (opt[1] == 'U'))) {
+ std::string optcopy = opt;
+ optcopy[0] = '-';
+ cppcheck_cmd.push_back(optcopy);
+#endif
+ }
+ }
+ }
+ // add the source file
+ cppcheck_cmd.push_back(sourceFile);
+
+ // Run the cpplint command line. Capture its output.
+ std::string stdOut;
+ std::string stdErr;
+ int ret;
+ if (!cmSystemTools::RunSingleCommand(cppcheck_cmd, &stdOut, &stdErr, &ret,
+ nullptr, cmSystemTools::OUTPUT_NONE)) {
+ std::cerr << "Error running '" << cppcheck_cmd[0] << "': " << stdOut
+ << "\n";
+ return 1;
+ }
+ std::cerr << stdOut;
+ // Output the output from cpplint to stderr
+ if (stdErr.find("(error)") != std::string::npos ||
+ stdErr.find("(warning)") != std::string::npos ||
+ stdErr.find("(style)") != std::string::npos ||
+ stdErr.find("(performance)") != std::string::npos ||
+ stdErr.find("(portability)") != std::string::npos ||
+ stdErr.find("(information)") != std::string::npos) {
+ std::cerr << "Warning: cppcheck reported diagnostics:\n";
+ }
+ std::cerr << stdErr;
+ // ignore errors so build continues
+ return 0;
+}
+
+// called when args[0] == "__run_co_compile"
+int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args)
+{
+ // initialize a map from command option to handler function
+ std::map<std::string,
+ std::function<int(const std::string&, const std::string&,
+ const std::vector<std::string>&)>>
+ coCompileTypes;
+ auto a1 = std::placeholders::_1;
+ auto a2 = std::placeholders::_2;
+ auto a3 = std::placeholders::_3;
+ // create a map from option to handler function for option
+ // if the option does not call the original command then it will need
+ // to set runOriginalCmd to false later in this function
+ coCompileTypes["--iwyu="] = std::bind(&cmcmd::HandleIWYU, a1, a2, a3);
+ coCompileTypes["--tidy="] = std::bind(&cmcmd::HandleTidy, a1, a2, a3);
+ coCompileTypes["--lwyu="] = std::bind(&cmcmd::HandleLWYU, a1, a2, a3);
+ coCompileTypes["--cpplint="] = std::bind(&cmcmd::HandleCppLint, a1, a2, a3);
+ coCompileTypes["--cppcheck="] =
+ std::bind(&cmcmd::HandleCppCheck, a1, a2, a3);
+ // copy the command options to a vector of strings
+ std::vector<std::string> commandOptions;
+ for (const auto& i : coCompileTypes) {
+ commandOptions.push_back(i.first);
+ }
+
+ std::string runCmd; // command to be run from --thing=command
+ std::string sourceFile; // store --source=
+ std::string commandFound; // the command that was in the args list
+ std::vector<std::string> orig_cmd;
+ bool doing_options = true;
+ for (std::string::size_type cc = 2; cc < args.size(); cc++) {
+ std::string const& arg = args[cc];
+ // if the arg is -- then the rest of the args after
+ // go into orig_cmd
+ if (arg == "--") {
+ doing_options = false;
+ } else if (doing_options) {
+ bool optionFound = false;
+ // check arg against all the commandOptions
+ for (std::vector<std::string>::size_type i = 0;
+ i < commandOptions.size(); ++i) {
+ const std::string& command = commandOptions[i];
+ if (arg.compare(0, command.size(), command) == 0) {
+ optionFound = true;
+ runCmd = arg.substr(command.size());
+ commandFound = command;
+ }
+ }
+ // check arg with --source=
+ if (cmHasLiteralPrefix(arg, "--source=")) {
+ sourceFile = arg.substr(9);
+ optionFound = true;
+ }
+ // if it was not a commandOptions or --source then error
+ if (!optionFound) {
+ std::cerr << "__run_co_compile given unknown argument: " << arg
+ << "\n";
+ return 1;
+ }
+ } else { // if not doing_options then push to orig_cmd
+ orig_cmd.push_back(arg);
+ }
+ }
+ if (commandFound.empty()) {
+ std::cerr << "__run_co_compile missing command to run. Looking for one of "
+ "the following:\n";
+ for (const auto& i : commandOptions) {
+ std::cerr << i << "\n";
+ }
+ return 1;
+ }
+ // Default is to run the original command found after -- if the option
+ // does not need to do that, it should be specified here, currently only
+ // lwyu does that.
+ bool runOriginalCmd = true;
+ if (commandFound == "--lwyu=") {
+ runOriginalCmd = false;
+ }
+ if (runOriginalCmd && orig_cmd.empty()) {
+ std::cerr << "__run_co_compile missing compile command after --\n";
+ return 1;
+ }
+
+ // call the command handler here
+ int ret = coCompileTypes[commandFound](runCmd, sourceFile, orig_cmd);
+ // if the command returns non-zero then return and fail.
+ // for commands that do not want to break the build, they should return
+ // 0 no matter what.
+ if (ret != 0) {
+ return ret;
+ }
+ // if there is no original command to run return now
+ if (!runOriginalCmd) {
+ return ret;
+ }
+ // Now run the real compiler command and return its result value
+ if (!cmSystemTools::RunSingleCommand(orig_cmd, nullptr, nullptr, &ret,
+ nullptr,
+ cmSystemTools::OUTPUT_PASSTHROUGH)) {
+ std::cerr << "Error running '" << orig_cmd[0] << "'\n";
+ return 1;
+ }
+ // return the return value from the original compiler command
+ return ret;
+}
+
int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
{
// IF YOU ADD A NEW COMMAND, DOCUMENT IT ABOVE and in cmakemain.cxx
@@ -280,234 +557,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
return 0;
}
#endif
- // 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.
- if (args[1] == "__run_iwyu") {
- if (args.size() < 3) {
- std::cerr << "__run_iwyu Usage: -E __run_iwyu [--iwyu=/path/iwyu]"
- " [--cpplint=/path/cpplint] [--tidy=/path/tidy]"
- " -- compile command\n";
- return 1;
- }
- bool doing_options = true;
- std::vector<std::string> orig_cmd;
- std::string iwyu;
- std::string tidy;
- std::string sourceFile;
- std::string lwyu;
- std::string cpplint;
- std::string cppcheck;
- 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 && cmHasLiteralPrefix(arg, "--tidy=")) {
- tidy = arg.substr(7);
- } else if (doing_options && cmHasLiteralPrefix(arg, "--source=")) {
- sourceFile = arg.substr(9);
- } else if (doing_options && cmHasLiteralPrefix(arg, "--lwyu=")) {
- lwyu = arg.substr(7);
- } else if (doing_options && cmHasLiteralPrefix(arg, "--cpplint=")) {
- cpplint = arg.substr(10);
- } else if (doing_options && cmHasLiteralPrefix(arg, "--cppcheck=")) {
- cppcheck = arg.substr(11);
- } else if (doing_options) {
- std::cerr << "__run_iwyu given unknown argument: " << arg << "\n";
- return 1;
- } else {
- orig_cmd.push_back(arg);
- }
- }
- if (tidy.empty() && iwyu.empty() && lwyu.empty() && cpplint.empty() &&
- cppcheck.empty()) {
- std::cerr << "__run_iwyu missing --cpplint=, --iwyu=, --lwyu=, "
- "--cppcheck= and/or --tidy=\n";
- return 1;
- }
- if ((!cpplint.empty() || !tidy.empty() || !cppcheck.empty()) &&
- sourceFile.empty()) {
- std::cerr << "__run_iwyu --cpplint=, __run_iwyu --tidy="
- ", __run_iwyu --cppcheck require --source=\n";
- return 1;
- }
- if (orig_cmd.empty() && lwyu.empty()) {
- std::cerr << "__run_iwyu missing compile command after --\n";
- return 1;
- }
-
- int ret = 0;
-
- if (!iwyu.empty()) {
- // 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.
- // Ignore its return code because the tool always returns non-zero.
- std::string stdErr;
- if (!cmSystemTools::RunSingleCommand(iwyu_cmd, nullptr, &stdErr, &ret,
- nullptr,
- 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:") != std::string::npos ||
- stdErr.find("should add these lines:") != std::string::npos) {
- std::cerr << "Warning: include-what-you-use reported diagnostics:\n"
- << stdErr << "\n";
- }
- }
-
- if (!tidy.empty()) {
- // Construct the clang-tidy command line by taking what was given
- // and adding our compiler command line. The clang-tidy tool will
- // automatically skip over the compiler itself and extract the
- // options.
- std::vector<std::string> tidy_cmd;
- cmSystemTools::ExpandListArgument(tidy, tidy_cmd, true);
- tidy_cmd.push_back(sourceFile);
- tidy_cmd.push_back("--");
- tidy_cmd.insert(tidy_cmd.end(), orig_cmd.begin(), orig_cmd.end());
-
- // Run the tidy command line. Capture its stdout and hide its stderr.
- std::string stdOut;
- std::string stdErr;
- if (!cmSystemTools::RunSingleCommand(tidy_cmd, &stdOut, &stdErr, &ret,
- nullptr,
- cmSystemTools::OUTPUT_NONE)) {
- std::cerr << "Error running '" << tidy_cmd[0] << "': " << stdErr
- << "\n";
- return 1;
- }
- // Output the stdout from clang-tidy to stderr
- std::cerr << stdOut;
- // If clang-tidy exited with an error do the same.
- if (ret != 0) {
- std::cerr << stdErr;
- return ret;
- }
- }
- if (!lwyu.empty()) {
- // Construct the ldd -r -u (link what you use lwyu) command line
- // ldd -u -r lwuy target
- std::vector<std::string> lwyu_cmd;
- lwyu_cmd.push_back("ldd");
- lwyu_cmd.push_back("-u");
- lwyu_cmd.push_back("-r");
- lwyu_cmd.push_back(lwyu);
-
- // Run the ldd -u -r command line.
- // Capture its stdout and hide its stderr.
- // Ignore its return code because the tool always returns non-zero
- // if there are any warnings, but we just want to warn.
- std::string stdOut;
- std::string stdErr;
- if (!cmSystemTools::RunSingleCommand(lwyu_cmd, &stdOut, &stdErr, &ret,
- nullptr,
- cmSystemTools::OUTPUT_NONE)) {
- std::cerr << "Error running '" << lwyu_cmd[0] << "': " << stdErr
- << "\n";
- return 1;
- }
-
- // Output the stdout from ldd -r -u to stderr
- // Warn if lwyu reported anything.
- if (stdOut.find("Unused direct dependencies:") != std::string::npos) {
- std::cerr << "Warning: " << stdOut;
- }
- }
-
- if (!cpplint.empty()) {
- // Construct the cpplint command line.
- std::vector<std::string> cpplint_cmd;
- cmSystemTools::ExpandListArgument(cpplint, cpplint_cmd, true);
- cpplint_cmd.push_back(sourceFile);
-
- // Run the cpplint command line. Capture its output.
- std::string stdOut;
- if (!cmSystemTools::RunSingleCommand(cpplint_cmd, &stdOut, &stdOut,
- &ret, nullptr,
- cmSystemTools::OUTPUT_NONE)) {
- std::cerr << "Error running '" << cpplint_cmd[0] << "': " << stdOut
- << "\n";
- return 1;
- }
-
- // Output the output from cpplint to stderr
- std::cerr << stdOut;
-
- // If cpplint exited with an error do the same.
- if (ret != 0) {
- return ret;
- }
- }
-
- if (!cppcheck.empty()) {
- // Construct the cpplint command line.
- std::vector<std::string> cppcheck_cmd;
- cmSystemTools::ExpandListArgument(cppcheck, cppcheck_cmd, true);
- // extract all the -D, -U, and -I options from the compile line
- for (size_t i = 0; i < orig_cmd.size(); i++) {
- std::string& opt = orig_cmd[i];
- if (opt.size() > 2) {
- if ((opt[0] == '-') &&
- ((opt[1] == 'D') || (opt[1] == 'I') || (opt[1] == 'U'))) {
- cppcheck_cmd.push_back(opt);
-#if defined(_WIN32)
- } else if ((opt[0] == '/') &&
- ((opt[1] == 'D') || (opt[1] == 'I') ||
- (opt[1] == 'U'))) {
- std::string optcopy = opt;
- optcopy[0] = '-';
- cppcheck_cmd.push_back(optcopy);
-#endif
- }
- }
- }
- // add the source file
- cppcheck_cmd.push_back(sourceFile);
-
- // Run the cpplint command line. Capture its output.
- std::string stdOut;
- if (!cmSystemTools::RunSingleCommand(cppcheck_cmd, &stdOut, &stdOut,
- &ret, nullptr,
- cmSystemTools::OUTPUT_NONE)) {
- std::cerr << "Error running '" << cppcheck_cmd[0] << "': " << stdOut
- << "\n";
- return 1;
- }
- // Output the output from cpplint to stderr
- if (stdOut.find("(error)") != std::string::npos ||
- stdOut.find("(warning)") != std::string::npos ||
- stdOut.find("(style)") != std::string::npos ||
- stdOut.find("(performance)") != std::string::npos ||
- stdOut.find("(portability)") != std::string::npos ||
- stdOut.find("(information)") != std::string::npos) {
- std::cerr << "Warning: cppcheck reported diagnostics:\n";
- }
- std::cerr << stdOut;
- }
- // ignore the cppcheck error code because it is likely to have them
- // from bad -D stuff
- ret = 0;
- // Now run the real compiler command and return its result value
- // unless we are lwyu
- if (lwyu.empty() &&
- !cmSystemTools::RunSingleCommand(
- orig_cmd, nullptr, nullptr, &ret, nullptr,
- cmSystemTools::OUTPUT_PASSTHROUGH)) {
- std::cerr << "Error running '" << orig_cmd[0] << "'\n";
- return 1;
- }
- return ret;
+ if (args[1] == "__run_co_compile") {
+ return cmcmd::HandleCoCompileCommands(args);
}
// Echo string
diff --git a/Source/cmcmd.h b/Source/cmcmd.h
index 457b760ef5..090ca084a0 100644
--- a/Source/cmcmd.h
+++ b/Source/cmcmd.h
@@ -18,7 +18,26 @@ public:
*/
static int ExecuteCMakeCommand(std::vector<std::string>&);
+ // define co-compile command handlers they must be public
+ // because they are used in a std::function map
+ static int HandleIWYU(const std::string& runCmd,
+ const std::string& sourceFile,
+ const std::vector<std::string>& orig_cmd);
+ static int HandleTidy(const std::string& runCmd,
+ const std::string& sourceFile,
+ const std::vector<std::string>& orig_cmd);
+ static int HandleLWYU(const std::string& runCmd,
+ const std::string& sourceFile,
+ const std::vector<std::string>& orig_cmd);
+ static int HandleCppLint(const std::string& runCmd,
+ const std::string& sourceFile,
+ const std::vector<std::string>& orig_cmd);
+ static int HandleCppCheck(const std::string& runCmd,
+ const std::string& sourceFile,
+ const std::vector<std::string>& orig_cmd);
+
protected:
+ static int HandleCoCompileCommands(std::vector<std::string>& args);
static int HashSumFile(std::vector<std::string>& args,
cmCryptoHash::Algo algo);
static int SymlinkLibrary(std::vector<std::string>& args);
diff --git a/Tests/RunCMake/CommandLine/E___run_iwyu-bad-iwyu-result.txt b/Tests/RunCMake/CommandLine/E___run_co_compile-bad-iwyu-result.txt
index d00491fd7e..d00491fd7e 100644
--- a/Tests/RunCMake/CommandLine/E___run_iwyu-bad-iwyu-result.txt
+++ b/Tests/RunCMake/CommandLine/E___run_co_compile-bad-iwyu-result.txt
diff --git a/Tests/RunCMake/CommandLine/E___run_iwyu-bad-iwyu-stderr.txt b/Tests/RunCMake/CommandLine/E___run_co_compile-bad-iwyu-stderr.txt
index 338f7c4e6f..338f7c4e6f 100644
--- a/Tests/RunCMake/CommandLine/E___run_iwyu-bad-iwyu-stderr.txt
+++ b/Tests/RunCMake/CommandLine/E___run_co_compile-bad-iwyu-stderr.txt
diff --git a/Tests/RunCMake/CommandLine/E___run_iwyu-no----result.txt b/Tests/RunCMake/CommandLine/E___run_co_compile-no----result.txt
index d00491fd7e..d00491fd7e 100644
--- a/Tests/RunCMake/CommandLine/E___run_iwyu-no----result.txt
+++ b/Tests/RunCMake/CommandLine/E___run_co_compile-no----result.txt
diff --git a/Tests/RunCMake/CommandLine/E___run_co_compile-no----stderr.txt b/Tests/RunCMake/CommandLine/E___run_co_compile-no----stderr.txt
new file mode 100644
index 0000000000..f0597d2cfb
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E___run_co_compile-no----stderr.txt
@@ -0,0 +1 @@
+^__run_co_compile given unknown argument: command-does-not-exist$
diff --git a/Tests/RunCMake/CommandLine/E___run_iwyu-no-cc-result.txt b/Tests/RunCMake/CommandLine/E___run_co_compile-no-cc-result.txt
index d00491fd7e..d00491fd7e 100644
--- a/Tests/RunCMake/CommandLine/E___run_iwyu-no-cc-result.txt
+++ b/Tests/RunCMake/CommandLine/E___run_co_compile-no-cc-result.txt
diff --git a/Tests/RunCMake/CommandLine/E___run_co_compile-no-cc-stderr.txt b/Tests/RunCMake/CommandLine/E___run_co_compile-no-cc-stderr.txt
new file mode 100644
index 0000000000..bba846e412
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E___run_co_compile-no-cc-stderr.txt
@@ -0,0 +1 @@
+^__run_co_compile missing compile command after --$
diff --git a/Tests/RunCMake/CommandLine/E___run_iwyu-no-iwyu-result.txt b/Tests/RunCMake/CommandLine/E___run_co_compile-no-iwyu-result.txt
index d00491fd7e..d00491fd7e 100644
--- a/Tests/RunCMake/CommandLine/E___run_iwyu-no-iwyu-result.txt
+++ b/Tests/RunCMake/CommandLine/E___run_co_compile-no-iwyu-result.txt
diff --git a/Tests/RunCMake/CommandLine/E___run_co_compile-no-iwyu-stderr.txt b/Tests/RunCMake/CommandLine/E___run_co_compile-no-iwyu-stderr.txt
new file mode 100644
index 0000000000..ffa1da8ba9
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E___run_co_compile-no-iwyu-stderr.txt
@@ -0,0 +1,5 @@
+^__run_co_compile missing command to run. Looking for one of the following:
+.*--cppcheck=
+.*--cpplint=
+.*--iwyu=
+.*--tidy=
diff --git a/Tests/RunCMake/CommandLine/E___run_iwyu-no----stderr.txt b/Tests/RunCMake/CommandLine/E___run_iwyu-no----stderr.txt
deleted file mode 100644
index c251adf00c..0000000000
--- a/Tests/RunCMake/CommandLine/E___run_iwyu-no----stderr.txt
+++ /dev/null
@@ -1 +0,0 @@
-^__run_iwyu given unknown argument: command-does-not-exist$
diff --git a/Tests/RunCMake/CommandLine/E___run_iwyu-no-cc-stderr.txt b/Tests/RunCMake/CommandLine/E___run_iwyu-no-cc-stderr.txt
deleted file mode 100644
index 1998abb22d..0000000000
--- a/Tests/RunCMake/CommandLine/E___run_iwyu-no-cc-stderr.txt
+++ /dev/null
@@ -1 +0,0 @@
-^__run_iwyu missing compile command after --$
diff --git a/Tests/RunCMake/CommandLine/E___run_iwyu-no-iwyu-stderr.txt b/Tests/RunCMake/CommandLine/E___run_iwyu-no-iwyu-stderr.txt
deleted file mode 100644
index 9db95f8ac8..0000000000
--- a/Tests/RunCMake/CommandLine/E___run_iwyu-no-iwyu-stderr.txt
+++ /dev/null
@@ -1 +0,0 @@
-^__run_iwyu missing --cpplint=, --iwyu=, --lwyu=, --cppcheck= and/or --tidy=$
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index 6efcc1218b..55eac5ec2f 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -21,10 +21,10 @@ run_cmake_command(E_touch_nocreate-no-arg ${CMAKE_COMMAND} -E touch_nocreate)
run_cmake_command(E_time ${CMAKE_COMMAND} -E time ${CMAKE_COMMAND} -E echo "hello world")
run_cmake_command(E_time-no-arg ${CMAKE_COMMAND} -E time)
-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(E___run_co_compile-no-iwyu ${CMAKE_COMMAND} -E __run_co_compile -- command-does-not-exist)
+run_cmake_command(E___run_co_compile-bad-iwyu ${CMAKE_COMMAND} -E __run_co_compile --iwyu=iwyu-does-not-exist -- command-does-not-exist)
+run_cmake_command(E___run_co_compile-no--- ${CMAKE_COMMAND} -E __run_co_compile --iwyu=iwyu-does-not-exist command-does-not-exist)
+run_cmake_command(E___run_co_compile-no-cc ${CMAKE_COMMAND} -E __run_co_compile --iwyu=iwyu-does-not-exist --)
run_cmake_command(G_no-arg ${CMAKE_COMMAND} -G)
run_cmake_command(G_bad-arg ${CMAKE_COMMAND} -G NoSuchGenerator)
diff --git a/Tests/RunCMake/Cppcheck/C-bad-Build-result.txt b/Tests/RunCMake/Cppcheck/C-bad-Build-result.txt
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/Tests/RunCMake/Cppcheck/C-bad-Build-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/Cppcheck/C-bad-Build-stdout.txt b/Tests/RunCMake/Cppcheck/C-bad-Build-stdout.txt
new file mode 100644
index 0000000000..2370ce1c13
--- /dev/null
+++ b/Tests/RunCMake/Cppcheck/C-bad-Build-stdout.txt
@@ -0,0 +1,2 @@
+stdout from bad command line arg '-bad'
+stderr from bad command line arg '-bad'
diff --git a/Tests/RunCMake/Cppcheck/C-bad.cmake b/Tests/RunCMake/Cppcheck/C-bad.cmake
new file mode 100644
index 0000000000..920e4b4bc5
--- /dev/null
+++ b/Tests/RunCMake/Cppcheck/C-bad.cmake
@@ -0,0 +1,3 @@
+enable_language(C)
+set(CMAKE_C_CPPCHECK "${PSEUDO_CPPCHECK}" -bad)
+add_executable(main main.c)
diff --git a/Tests/RunCMake/Cppcheck/RunCMakeTest.cmake b/Tests/RunCMake/Cppcheck/RunCMakeTest.cmake
index ae14f8c2ae..5fd4ead139 100644
--- a/Tests/RunCMake/Cppcheck/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Cppcheck/RunCMakeTest.cmake
@@ -15,6 +15,7 @@ endfunction()
run_cppcheck(C)
run_cppcheck(CXX)
+run_cppcheck(C-bad)
if(NOT RunCMake_GENERATOR STREQUAL "Watcom WMake")
run_cppcheck(C-launch)
diff --git a/Tests/RunCMake/pseudo_cppcheck.c b/Tests/RunCMake/pseudo_cppcheck.c
index 32e6e28445..8667e5e4ab 100644
--- a/Tests/RunCMake/pseudo_cppcheck.c
+++ b/Tests/RunCMake/pseudo_cppcheck.c
@@ -1,7 +1,18 @@
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
-int main(void)
+int main(int argc, char* argv[])
{
+ int i;
+ for (i = 1; i < argc; ++i) {
+ if (strcmp(argv[i], "-bad") == 0)
+ if (strcmp(argv[i], "-bad") == 0) {
+ fprintf(stdout, "stdout from bad command line arg '-bad'\n");
+ fprintf(stderr, "stderr from bad command line arg '-bad'\n");
+ return 1;
+ }
+ }
fprintf(stderr,
"[/foo/bar.c:2]: (error) Array 'abc[10]' accessed at index 12,"
" which is out of bounds.\n");