diff options
author | Brad King <brad.king@kitware.com> | 2017-09-15 12:53:00 +0000 |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2017-09-15 08:54:32 -0400 |
commit | c0c5f924fe46fcf83603117689b372cb8520c4bb (patch) | |
tree | 3abb6b0d1b361ce133ecdc8df41a679e7e7e37c7 | |
parent | 3449c18c36a9acf29dfbb228ee76059cc4b9127f (diff) | |
parent | 3bbe95f58a8fb83e56ca9023ef01b9e70b391b05 (diff) | |
download | cmake-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
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"); |