mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-03 21:00:01 -05:00
cmcmd: Restore support for running multiple lint tools
Refactoring in commit v3.10.0-rc1~115^2 (Clean up iwyu code to not be one big if statement, 2017-08-28) incorrectly changed the logic to run only one lint tool at a time. Restore support for running all tools specified on the command-line.
This commit is contained in:
+65
-55
@@ -33,15 +33,13 @@
|
|||||||
#include "cmsys/Process.h"
|
#include "cmsys/Process.h"
|
||||||
#include "cmsys/Terminal.h"
|
#include "cmsys/Terminal.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <map>
|
|
||||||
#include <memory> // IWYU pragma: keep
|
#include <memory> // IWYU pragma: keep
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
class cmConnection;
|
class cmConnection;
|
||||||
|
|
||||||
@@ -328,35 +326,41 @@ static int HandleCppCheck(const std::string& runCmd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef int (*CoCompileHandler)(const std::string&, const std::string&,
|
||||||
|
const std::vector<std::string>&);
|
||||||
|
|
||||||
|
struct CoCompiler
|
||||||
|
{
|
||||||
|
const char* Option;
|
||||||
|
CoCompileHandler Handler;
|
||||||
|
bool NoOriginalCommand;
|
||||||
|
};
|
||||||
|
|
||||||
|
static CoCompiler CoCompilers[] = { // Table of options and handlers.
|
||||||
|
{ "--cppcheck=", HandleCppCheck, false },
|
||||||
|
{ "--cpplint=", HandleCppLint, false },
|
||||||
|
{ "--iwyu=", HandleIWYU, false },
|
||||||
|
{ "--lwyu=", HandleLWYU, true },
|
||||||
|
{ "--tidy=", HandleTidy, false }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CoCompileJob
|
||||||
|
{
|
||||||
|
std::string Command;
|
||||||
|
CoCompileHandler Handler;
|
||||||
|
};
|
||||||
|
|
||||||
// called when args[0] == "__run_co_compile"
|
// called when args[0] == "__run_co_compile"
|
||||||
int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args)
|
int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args)
|
||||||
{
|
{
|
||||||
// initialize a map from command option to handler function
|
std::vector<CoCompileJob> jobs;
|
||||||
std::map<std::string,
|
std::string sourceFile; // store --source=
|
||||||
std::function<int(const std::string&, const std::string&,
|
|
||||||
const std::vector<std::string>&)>>
|
// Default is to run the original command found after -- if the option
|
||||||
coCompileTypes;
|
// does not need to do that, it should be specified here, currently only
|
||||||
auto a1 = std::placeholders::_1;
|
// lwyu does that.
|
||||||
auto a2 = std::placeholders::_2;
|
bool runOriginalCmd = true;
|
||||||
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(&HandleIWYU, a1, a2, a3);
|
|
||||||
coCompileTypes["--tidy="] = std::bind(&HandleTidy, a1, a2, a3);
|
|
||||||
coCompileTypes["--lwyu="] = std::bind(&HandleLWYU, a1, a2, a3);
|
|
||||||
coCompileTypes["--cpplint="] = std::bind(&HandleCppLint, a1, a2, a3);
|
|
||||||
coCompileTypes["--cppcheck="] = std::bind(&HandleCppCheck, a1, a2, a3);
|
|
||||||
// copy the command options to a vector of strings
|
|
||||||
std::vector<std::string> commandOptions;
|
|
||||||
commandOptions.reserve(coCompileTypes.size());
|
|
||||||
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;
|
std::vector<std::string> orig_cmd;
|
||||||
bool doing_options = true;
|
bool doing_options = true;
|
||||||
for (std::string::size_type i = 2; i < args.size(); ++i) {
|
for (std::string::size_type i = 2; i < args.size(); ++i) {
|
||||||
@@ -367,20 +371,25 @@ int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args)
|
|||||||
doing_options = false;
|
doing_options = false;
|
||||||
} else if (doing_options) {
|
} else if (doing_options) {
|
||||||
bool optionFound = false;
|
bool optionFound = false;
|
||||||
// check arg against all the commandOptions
|
for (CoCompiler const* cc = cmArrayBegin(CoCompilers);
|
||||||
for (auto const& command : commandOptions) {
|
cc != cmArrayEnd(CoCompilers); ++cc) {
|
||||||
if (arg.compare(0, command.size(), command) == 0) {
|
size_t optionLen = strlen(cc->Option);
|
||||||
|
if (arg.compare(0, optionLen, cc->Option) == 0) {
|
||||||
optionFound = true;
|
optionFound = true;
|
||||||
runCmd = arg.substr(command.size());
|
CoCompileJob job;
|
||||||
commandFound = command;
|
job.Command = arg.substr(optionLen);
|
||||||
|
job.Handler = cc->Handler;
|
||||||
|
jobs.push_back(std::move(job));
|
||||||
|
if (cc->NoOriginalCommand) {
|
||||||
|
runOriginalCmd = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check arg with --source=
|
|
||||||
if (cmHasLiteralPrefix(arg, "--source=")) {
|
if (cmHasLiteralPrefix(arg, "--source=")) {
|
||||||
sourceFile = arg.substr(9);
|
sourceFile = arg.substr(9);
|
||||||
optionFound = true;
|
optionFound = true;
|
||||||
}
|
}
|
||||||
// if it was not a commandOptions or --source then error
|
// if it was not a co-compiler or --source then error
|
||||||
if (!optionFound) {
|
if (!optionFound) {
|
||||||
std::cerr << "__run_co_compile given unknown argument: " << arg
|
std::cerr << "__run_co_compile given unknown argument: " << arg
|
||||||
<< "\n";
|
<< "\n";
|
||||||
@@ -390,39 +399,40 @@ int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args)
|
|||||||
orig_cmd.push_back(arg);
|
orig_cmd.push_back(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (commandFound.empty()) {
|
if (jobs.empty()) {
|
||||||
std::cerr << "__run_co_compile missing command to run. Looking for one of "
|
std::cerr << "__run_co_compile missing command to run. "
|
||||||
"the following:\n";
|
"Looking for one or more of the following:\n";
|
||||||
for (const auto& i : commandOptions) {
|
for (CoCompiler const* cc = cmArrayBegin(CoCompilers);
|
||||||
std::cerr << i << "\n";
|
cc != cmArrayEnd(CoCompilers); ++cc) {
|
||||||
|
std::cerr << cc->Option << "\n";
|
||||||
}
|
}
|
||||||
return 1;
|
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()) {
|
if (runOriginalCmd && orig_cmd.empty()) {
|
||||||
std::cerr << "__run_co_compile missing compile command after --\n";
|
std::cerr << "__run_co_compile missing compile command after --\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// call the command handler here
|
for (CoCompileJob const& job : jobs) {
|
||||||
int ret = coCompileTypes[commandFound](runCmd, sourceFile, orig_cmd);
|
// call the command handler here
|
||||||
// if the command returns non-zero then return and fail.
|
int ret = job.Handler(job.Command, sourceFile, orig_cmd);
|
||||||
// for commands that do not want to break the build, they should return
|
|
||||||
// 0 no matter what.
|
// if the command returns non-zero then return and fail.
|
||||||
if (ret != 0) {
|
// for commands that do not want to break the build, they should return
|
||||||
return ret;
|
// 0 no matter what.
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if there is no original command to run return now
|
// if there is no original command to run return now
|
||||||
if (!runOriginalCmd) {
|
if (!runOriginalCmd) {
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now run the real compiler command and return its result value
|
// Now run the real compiler command and return its result value
|
||||||
|
int ret;
|
||||||
if (!cmSystemTools::RunSingleCommand(orig_cmd, nullptr, nullptr, &ret,
|
if (!cmSystemTools::RunSingleCommand(orig_cmd, nullptr, nullptr, &ret,
|
||||||
nullptr,
|
nullptr,
|
||||||
cmSystemTools::OUTPUT_PASSTHROUGH)) {
|
cmSystemTools::OUTPUT_PASSTHROUGH)) {
|
||||||
|
|||||||
@@ -370,6 +370,12 @@ if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
|
|||||||
add_RunCMake_test(IncludeWhatYouUse -DPSEUDO_IWYU=$<TARGET_FILE:pseudo_iwyu>)
|
add_RunCMake_test(IncludeWhatYouUse -DPSEUDO_IWYU=$<TARGET_FILE:pseudo_iwyu>)
|
||||||
add_RunCMake_test(Cpplint -DPSEUDO_CPPLINT=$<TARGET_FILE:pseudo_cpplint>)
|
add_RunCMake_test(Cpplint -DPSEUDO_CPPLINT=$<TARGET_FILE:pseudo_cpplint>)
|
||||||
add_RunCMake_test(Cppcheck -DPSEUDO_CPPCHECK=$<TARGET_FILE:pseudo_cppcheck>)
|
add_RunCMake_test(Cppcheck -DPSEUDO_CPPCHECK=$<TARGET_FILE:pseudo_cppcheck>)
|
||||||
|
add_RunCMake_test(MultiLint
|
||||||
|
-DPSEUDO_TIDY=$<TARGET_FILE:pseudo_tidy>
|
||||||
|
-DPSEUDO_IWYU=$<TARGET_FILE:pseudo_iwyu>
|
||||||
|
-DPSEUDO_CPPLINT=$<TARGET_FILE:pseudo_cpplint>
|
||||||
|
-DPSEUDO_CPPCHECK=$<TARGET_FILE:pseudo_cppcheck>
|
||||||
|
)
|
||||||
if(DEFINED CMake_TEST_CUDA)
|
if(DEFINED CMake_TEST_CUDA)
|
||||||
list(APPEND CompilerLauncher_ARGS -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
|
list(APPEND CompilerLauncher_ARGS -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
^__run_co_compile missing command to run. Looking for one of the following:
|
^__run_co_compile missing command to run. Looking for one or more of the following:
|
||||||
.*--cppcheck=
|
--cppcheck=
|
||||||
.*--cpplint=
|
--cpplint=
|
||||||
.*--iwyu=
|
--iwyu=
|
||||||
.*--tidy=
|
--lwyu=
|
||||||
|
--tidy=
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
Warning: include-what-you-use reported diagnostics:
|
||||||
|
should add these lines:
|
||||||
|
*
|
||||||
|
#include <\.\.\.>
|
||||||
|
+
|
||||||
|
.*Tests[/\]RunCMake[/\]MultiLint[/\]main\.c:0:0: warning: message \[checker\].*
|
||||||
|
Total errors found: 0
|
||||||
|
.*Warning: cppcheck reported diagnostics.*error.*warning.*style.*performance.*information.*
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
Warning: include-what-you-use reported diagnostics:
|
||||||
|
should add these lines:
|
||||||
|
*
|
||||||
|
#include <\.\.\.>
|
||||||
|
+
|
||||||
|
.*Tests[/\]RunCMake[/\]MultiLint[/\]main\.c:0:0: warning: message \[checker\].*
|
||||||
|
Total errors found: 0
|
||||||
|
.*Warning: cppcheck reported diagnostics.*error.*warning.*style.*performance.*information.*
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
set(CTEST_USE_LAUNCHERS 1)
|
||||||
|
include(CTestUseLaunchers)
|
||||||
|
include(C.cmake)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
enable_language(C)
|
||||||
|
set(CMAKE_C_INCLUDE_WHAT_YOU_USE "${PSEUDO_IWYU}" -some -args)
|
||||||
|
set(CMAKE_C_CLANG_TIDY "${PSEUDO_TIDY}" -some -args)
|
||||||
|
set(CMAKE_C_CPPLINT "${PSEUDO_CPPLINT}" --verbose=0 --linelength=80)
|
||||||
|
set(CMAKE_C_CPPCHECK "${PSEUDO_CPPCHECK}")
|
||||||
|
add_executable(main main.c)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
project(${RunCMake_TEST} NONE)
|
||||||
|
include(${RunCMake_TEST}.cmake)
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
Warning: include-what-you-use reported diagnostics:
|
||||||
|
should add these lines:
|
||||||
|
*
|
||||||
|
#include <\.\.\.>
|
||||||
|
+
|
||||||
|
.*Tests[/\]RunCMake[/\]MultiLint[/\]main\.cxx:0:0: warning: message \[checker\].*
|
||||||
|
Total errors found: 0
|
||||||
|
.*Warning: cppcheck reported diagnostics.*error.*warning.*style.*performance.*information.*
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
Warning: include-what-you-use reported diagnostics:
|
||||||
|
should add these lines:
|
||||||
|
*
|
||||||
|
#include <\.\.\.>
|
||||||
|
+
|
||||||
|
.*Tests[/\]RunCMake[/\]MultiLint[/\]main\.cxx:0:0: warning: message \[checker\].*
|
||||||
|
Total errors found: 0
|
||||||
|
.*Warning: cppcheck reported diagnostics.*error.*warning.*style.*performance.*information.*
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
set(CTEST_USE_LAUNCHERS 1)
|
||||||
|
include(CTestUseLaunchers)
|
||||||
|
include(CXX.cmake)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
enable_language(CXX)
|
||||||
|
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "${PSEUDO_IWYU}" -some -args)
|
||||||
|
set(CMAKE_CXX_CLANG_TIDY "${PSEUDO_TIDY}" -some -args)
|
||||||
|
set(CMAKE_CXX_CPPLINT "${PSEUDO_CPPLINT}" --verbose=0 --linelength=80)
|
||||||
|
set(CMAKE_CXX_CPPCHECK "${PSEUDO_CPPCHECK}")
|
||||||
|
add_executable(main main.cxx)
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
include(RunCMake)
|
||||||
|
|
||||||
|
set(RunCMake_TEST_OPTIONS
|
||||||
|
"-DPSEUDO_CPPCHECK=${PSEUDO_CPPCHECK}"
|
||||||
|
"-DPSEUDO_CPPLINT=${PSEUDO_CPPLINT}"
|
||||||
|
"-DPSEUDO_IWYU=${PSEUDO_IWYU}"
|
||||||
|
"-DPSEUDO_TIDY=${PSEUDO_TIDY}"
|
||||||
|
)
|
||||||
|
|
||||||
|
function(run_multilint 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_multilint(C)
|
||||||
|
run_multilint(CXX)
|
||||||
|
|
||||||
|
if(NOT RunCMake_GENERATOR STREQUAL "Watcom WMake")
|
||||||
|
run_multilint(C-launch)
|
||||||
|
run_multilint(CXX-launch)
|
||||||
|
endif()
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
int main()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user