TargetGenerator: Factor out generation of code check rules

De-duplicate code check rule generation in Ninja and Makefile generators
by moving their implementation to `cmCommonTargetGenerator`.

Previously Ninja was generating code check rules per language.
It was changed to generate code check rules for each source file.
stage/master/nightly/2023/05/19
Orkun Tokdemir 2023-05-12 16:40:28 +02:00 committed by Brad King
parent 023af4ab2f
commit 993dde925f
7 changed files with 245 additions and 320 deletions

View File

@ -26,6 +26,7 @@
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"
cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt)
@ -291,6 +292,170 @@ void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags,
}
}
std::string cmCommonTargetGenerator::GetCompilerLauncher(
std::string const& lang, std::string const& config)
{
std::string compilerLauncher;
if (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" ||
lang == "HIP" || lang == "ISPC" || lang == "OBJC" || lang == "OBJCXX") {
std::string const clauncher_prop = cmStrCat(lang, "_COMPILER_LAUNCHER");
cmValue clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
std::string const evaluatedClauncher = cmGeneratorExpression::Evaluate(
*clauncher, this->GeneratorTarget->GetLocalGenerator(), config,
this->GeneratorTarget, nullptr, this->GeneratorTarget, lang);
if (!evaluatedClauncher.empty()) {
compilerLauncher = evaluatedClauncher;
}
}
return compilerLauncher;
}
std::string cmCommonTargetGenerator::GenerateCodeCheckRules(
cmSourceFile const& source, std::string& compilerLauncher,
std::string const& cmakeCmd, std::string const& config,
std::function<std::string(std::string const&)> const& pathConverter)
{
auto const lang = source.GetLanguage();
std::string tidy;
std::string iwyu;
std::string cpplint;
std::string cppcheck;
auto evaluateProp = [&](std::string const& prop) -> std::string {
auto const value = this->GeneratorTarget->GetProperty(prop);
if (!value) {
return std::string{};
}
auto evaluatedProp = cmGeneratorExpression::Evaluate(
*value, this->GeneratorTarget->GetLocalGenerator(), config,
this->GeneratorTarget, nullptr, this->GeneratorTarget, lang);
if (!evaluatedProp.empty()) {
return evaluatedProp;
}
return *value;
};
std::string const tidy_prop = cmStrCat(lang, "_CLANG_TIDY");
tidy = evaluateProp(tidy_prop);
if (lang == "C" || lang == "CXX") {
std::string const iwyu_prop = cmStrCat(lang, "_INCLUDE_WHAT_YOU_USE");
iwyu = evaluateProp(iwyu_prop);
std::string const cpplint_prop = cmStrCat(lang, "_CPPLINT");
cpplint = evaluateProp(cpplint_prop);
std::string const cppcheck_prop = cmStrCat(lang, "_CPPCHECK");
cppcheck = evaluateProp(cppcheck_prop);
}
if (cmNonempty(iwyu) || cmNonempty(tidy) || cmNonempty(cpplint) ||
cmNonempty(cppcheck)) {
std::string code_check = cmakeCmd + " -E __run_co_compile";
if (!compilerLauncher.empty()) {
// In __run_co_compile case the launcher command is supplied
// via --launcher=<maybe-list> and consumed
code_check += " --launcher=";
code_check += this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(
compilerLauncher);
compilerLauncher.clear();
}
if (cmNonempty(iwyu)) {
code_check += " --iwyu=";
// Only add --driver-mode if it is not already specified, as adding
// it unconditionally might override a user-specified driver-mode
if (iwyu.find("--driver-mode=") == std::string::npos) {
cmValue const p = this->Makefile->GetDefinition(
cmStrCat("CMAKE_", lang, "_INCLUDE_WHAT_YOU_USE_DRIVER_MODE"));
std::string driverMode;
if (cmNonempty(p)) {
driverMode = *p;
} else {
driverMode = lang == "C" ? "gcc" : "g++";
}
code_check +=
this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(
cmStrCat(iwyu, ";--driver-mode=", driverMode));
} else {
code_check +=
this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(iwyu);
}
}
if (cmNonempty(tidy)) {
code_check += " --tidy=";
cmValue const p = this->Makefile->GetDefinition(
"CMAKE_" + lang + "_CLANG_TIDY_DRIVER_MODE");
std::string driverMode;
if (cmNonempty(p)) {
driverMode = *p;
} else {
driverMode = lang == "C" ? "gcc" : "g++";
}
auto const generatorName = this->GeneratorTarget->GetLocalGenerator()
->GetGlobalGenerator()
->GetName();
auto const clangTidyExportFixedDir =
this->GeneratorTarget->GetClangTidyExportFixesDirectory(lang);
auto fixesFile = this->GetClangTidyReplacementsFilePath(
clangTidyExportFixedDir, source, config);
std::string exportFixes;
if (!clangTidyExportFixedDir.empty()) {
this->GlobalCommonGenerator->AddClangTidyExportFixesDir(
clangTidyExportFixedDir);
}
if (generatorName.find("Make") != std::string::npos) {
if (!clangTidyExportFixedDir.empty()) {
this->GlobalCommonGenerator->AddClangTidyExportFixesFile(fixesFile);
cmSystemTools::MakeDirectory(
cmSystemTools::GetFilenamePath(fixesFile));
fixesFile = this->GeneratorTarget->GetLocalGenerator()
->MaybeRelativeToCurBinDir(fixesFile);
exportFixes = cmStrCat(";--export-fixes=", fixesFile);
}
code_check +=
this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(
cmStrCat(tidy, ";--extra-arg-before=--driver-mode=", driverMode,
exportFixes));
} else if (generatorName.find("Ninja") != std::string::npos) {
if (!clangTidyExportFixedDir.empty()) {
this->GlobalCommonGenerator->AddClangTidyExportFixesFile(fixesFile);
cmSystemTools::MakeDirectory(
cmSystemTools::GetFilenamePath(fixesFile));
if (!pathConverter) {
fixesFile = pathConverter(fixesFile);
}
exportFixes = cmStrCat(";--export-fixes=", fixesFile);
}
code_check +=
this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(
cmStrCat(tidy, ";--extra-arg-before=--driver-mode=", driverMode,
exportFixes));
}
}
if (cmNonempty(cpplint)) {
code_check += " --cpplint=";
code_check +=
this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(cpplint);
}
if (cmNonempty(cppcheck)) {
code_check += " --cppcheck=";
code_check +=
this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(cppcheck);
}
if (cmNonempty(tidy) || (cmNonempty(cpplint)) || (cmNonempty(cppcheck))) {
code_check += " --source=";
code_check +=
this->GeneratorTarget->GetLocalGenerator()->ConvertToOutputFormat(
source.GetFullPath(), cmOutputConverter::SHELL);
}
code_check += " -- ";
return code_check;
}
return "";
}
std::string cmCommonTargetGenerator::GetLinkerLauncher(
const std::string& config)
{

View File

@ -4,6 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <functional>
#include <map>
#include <set>
#include <string>
@ -53,6 +54,9 @@ protected:
virtual void AddIncludeFlags(std::string& flags, std::string const& lang,
const std::string& config) = 0;
virtual std::string GetClangTidyReplacementsFilePath(
std::string const& directory, cmSourceFile const& source,
std::string const& config) const = 0;
void AppendOSXVerFlag(std::string& flags, const std::string& lang,
const char* name, bool so);
@ -63,7 +67,13 @@ protected:
std::string GetIncludes(std::string const& l, const std::string& config);
std::string GetManifests(const std::string& config);
std::string GetAIXExports(std::string const& config);
std::string GenerateCodeCheckRules(
cmSourceFile const& source, std::string& compilerLauncher,
std::string const& cmakeCmd, std::string const& config,
std::function<std::string(std::string const&)> const& pathConverter);
std::string GetCompilerLauncher(std::string const& lang,
std::string const& config);
std::vector<std::string> GetLinkedTargetDirectories(
const std::string& lang, const std::string& config) const;
std::string ComputeTargetCompilePDB(const std::string& config) const;

View File

@ -507,8 +507,18 @@ void cmGlobalNinjaGenerator::WriteVariable(std::ostream& os,
return;
}
std::string val;
static std::unordered_set<std::string> const variablesShouldNotBeTrimmed = {
"CODE_CHECK", "LAUNCHER"
};
if (variablesShouldNotBeTrimmed.find(name) ==
variablesShouldNotBeTrimmed.end()) {
val = cmTrimWhitespace(value);
} else {
val = value;
}
// Do not add a variable if the value is empty.
std::string val = cmTrimWhitespace(value);
if (val.empty()) {
return;
}

View File

@ -26,7 +26,6 @@
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLinkLineComputer.h" // IWYU pragma: keep
#include "cmList.h"
@ -1054,151 +1053,14 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
// See if we need to use a compiler launcher like ccache or distcc
std::string compilerLauncher;
if (!compileCommands.empty() &&
(lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" ||
lang == "HIP" || lang == "ISPC" || lang == "OBJC" ||
lang == "OBJCXX")) {
std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
cmValue clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
std::string evaluatedClauncher = cmGeneratorExpression::Evaluate(
*clauncher, this->LocalGenerator, config, this->GeneratorTarget,
nullptr, this->GeneratorTarget, lang);
if (!evaluatedClauncher.empty()) {
compilerLauncher = evaluatedClauncher;
}
if (!compileCommands.empty()) {
compilerLauncher = GetCompilerLauncher(lang, config);
}
// Maybe insert an include-what-you-use runner.
if (!compileCommands.empty() &&
(lang == "C" || lang == "CXX" || lang == "OBJC" || lang == "OBJCXX")) {
cmValue tidy = nullptr;
cmValue iwyu = nullptr;
cmValue cpplint = nullptr;
cmValue cppcheck = nullptr;
std::string evaluatedTIDY;
std::string evaluatedIWYU;
std::string evaluatedCPPlint;
std::string evaluatedCPPcheck;
std::string const tidy_prop = cmStrCat(lang, "_CLANG_TIDY");
tidy = this->GeneratorTarget->GetProperty(tidy_prop);
evaluatedTIDY = cmGeneratorExpression::Evaluate(
*tidy, this->LocalGenerator, config, this->GeneratorTarget, nullptr,
this->GeneratorTarget, lang);
if (!evaluatedTIDY.empty()) {
tidy = cmValue(&evaluatedTIDY);
}
if (lang == "C" || lang == "CXX") {
std::string const iwyu_prop = cmStrCat(lang, "_INCLUDE_WHAT_YOU_USE");
iwyu = this->GeneratorTarget->GetProperty(iwyu_prop);
evaluatedIWYU = cmGeneratorExpression::Evaluate(
*iwyu, this->LocalGenerator, config, this->GeneratorTarget, nullptr,
this->GeneratorTarget, lang);
if (!evaluatedIWYU.empty()) {
iwyu = cmValue(&evaluatedIWYU);
}
std::string const cpplint_prop = cmStrCat(lang, "_CPPLINT");
cpplint = this->GeneratorTarget->GetProperty(cpplint_prop);
evaluatedCPPlint = cmGeneratorExpression::Evaluate(
*cpplint, this->LocalGenerator, config, this->GeneratorTarget,
nullptr, this->GeneratorTarget, lang);
if (!evaluatedCPPlint.empty()) {
cpplint = cmValue(&evaluatedCPPlint);
}
std::string const cppcheck_prop = cmStrCat(lang, "_CPPCHECK");
cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop);
evaluatedCPPcheck = cmGeneratorExpression::Evaluate(
*cppcheck, this->LocalGenerator, config, this->GeneratorTarget,
nullptr, this->GeneratorTarget, lang);
if (!evaluatedCPPcheck.empty()) {
cppcheck = cmValue(&evaluatedCPPcheck);
}
}
if (cmNonempty(iwyu) || cmNonempty(tidy) || cmNonempty(cpplint) ||
cmNonempty(cppcheck)) {
std::string run_iwyu = "$(CMAKE_COMMAND) -E __run_co_compile";
if (!compilerLauncher.empty()) {
// In __run_co_compile case the launcher command is supplied
// via --launcher=<maybe-list> and consumed
run_iwyu += " --launcher=";
run_iwyu += this->LocalGenerator->EscapeForShell(compilerLauncher);
compilerLauncher.clear();
}
if (cmNonempty(iwyu)) {
run_iwyu += " --iwyu=";
// Only add --driver-mode if it is not already specified, as adding
// it unconditionally might override a user-specified driver-mode
if (iwyu.Get()->find("--driver-mode=") == std::string::npos) {
cmValue p = this->Makefile->GetDefinition(
cmStrCat("CMAKE_", lang, "_INCLUDE_WHAT_YOU_USE_DRIVER_MODE"));
std::string driverMode;
if (cmNonempty(p)) {
driverMode = *p;
} else {
driverMode = lang == "C" ? "gcc" : "g++";
}
run_iwyu += this->LocalGenerator->EscapeForShell(
cmStrCat(*iwyu, ";--driver-mode=", driverMode));
} else {
run_iwyu += this->LocalGenerator->EscapeForShell(*iwyu);
}
}
if (cmNonempty(tidy)) {
run_iwyu += " --tidy=";
cmValue p = this->Makefile->GetDefinition("CMAKE_" + lang +
"_CLANG_TIDY_DRIVER_MODE");
std::string driverMode;
if (cmNonempty(p)) {
driverMode = *p;
} else {
driverMode = lang == "C" ? "gcc" : "g++";
}
std::string d =
this->GeneratorTarget->GetClangTidyExportFixesDirectory(lang);
std::string exportFixes;
if (!d.empty()) {
this->GlobalCommonGenerator->AddClangTidyExportFixesDir(d);
std::string fixesFile = cmSystemTools::CollapseFullPath(cmStrCat(
d, '/',
this->LocalGenerator->MaybeRelativeToTopBinDir(cmStrCat(
this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
this->LocalGenerator->GetTargetDirectory(
this->GeneratorTarget),
'/', objectName, ".yaml"))));
this->GlobalCommonGenerator->AddClangTidyExportFixesFile(
fixesFile);
cmSystemTools::MakeDirectory(
cmSystemTools::GetFilenamePath(fixesFile));
fixesFile =
this->LocalGenerator->MaybeRelativeToCurBinDir(fixesFile);
exportFixes = cmStrCat(";--export-fixes=", fixesFile);
}
run_iwyu += this->LocalGenerator->EscapeForShell(
cmStrCat(*tidy, ";--extra-arg-before=--driver-mode=", driverMode,
exportFixes));
}
if (cmNonempty(cpplint)) {
run_iwyu += " --cpplint=";
run_iwyu += this->LocalGenerator->EscapeForShell(*cpplint);
}
if (cmNonempty(cppcheck)) {
run_iwyu += " --cppcheck=";
run_iwyu += this->LocalGenerator->EscapeForShell(*cppcheck);
}
if (cmNonempty(tidy) || (cmNonempty(cpplint)) ||
(cmNonempty(cppcheck))) {
run_iwyu += " --source=";
run_iwyu += sourceFile;
}
run_iwyu += " -- ";
compileCommands.front().insert(0, run_iwyu);
}
std::string const codeCheck = this->GenerateCodeCheckRules(
source, compilerLauncher, "$(CMAKE_COMMAND)", config, nullptr);
if (!codeCheck.empty()) {
compileCommands.front().insert(0, codeCheck);
}
// If compiler launcher was specified and not consumed above, it
@ -1519,6 +1381,23 @@ void cmMakefileTargetGenerator::WriteTargetLinkDependRules()
this->GeneratorTarget->GetFullPath(this->GetConfigName()), depFile,
cmDependencyScannerKind::Compiler);
}
std::string cmMakefileTargetGenerator::GetClangTidyReplacementsFilePath(
std::string const& directory, cmSourceFile const& source,
std::string const& config) const
{
(void)config;
auto const& objectName = this->GeneratorTarget->GetObjectName(&source);
auto fixesFile = cmSystemTools::CollapseFullPath(cmStrCat(
directory, '/',
this->GeneratorTarget->GetLocalGenerator()->MaybeRelativeToTopBinDir(
cmStrCat(this->GeneratorTarget->GetLocalGenerator()
->GetCurrentBinaryDirectory(),
'/',
this->GeneratorTarget->GetLocalGenerator()->GetTargetDirectory(
this->GeneratorTarget),
'/', objectName, ".yaml"))));
return fixesFile;
}
void cmMakefileTargetGenerator::WriteTargetDependRules()
{

View File

@ -82,6 +82,10 @@ protected:
// write the depend rules for this target
void WriteTargetDependRules();
std::string GetClangTidyReplacementsFilePath(
std::string const& directory, cmSourceFile const& source,
std::string const& config) const override;
// write rules for macOS Application Bundle content.
struct MacOSXContentGeneratorType
: cmOSXBundleGenerator::MacOSXContentGeneratorType

View File

@ -29,7 +29,6 @@
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
#include "cmGlobalNinjaGenerator.h"
#include "cmList.h"
#include "cmLocalGenerator.h"
@ -399,15 +398,15 @@ std::string cmNinjaTargetGenerator::GetObjectFilePath(
}
std::string cmNinjaTargetGenerator::GetClangTidyReplacementsFilePath(
const std::string& directory, cmSourceFile const* source,
const std::string& config) const
std::string const& directory, cmSourceFile const& source,
std::string const& config) const
{
std::string path = this->LocalGenerator->GetHomeRelativeOutputPath();
auto path = this->LocalGenerator->GetHomeRelativeOutputPath();
if (!path.empty()) {
path += '/';
}
path = cmStrCat(directory, '/', path);
std::string const& objectName = this->GeneratorTarget->GetObjectName(source);
auto const& objectName = this->GeneratorTarget->GetObjectName(&source);
path =
cmStrCat(std::move(path),
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget),
@ -890,162 +889,9 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
const std::string& compileCmd = mf->GetRequiredDefinition(cmdVar);
cmList compileCmds(compileCmd);
// See if we need to use a compiler launcher like ccache or distcc
std::string compilerLauncher;
if (!compileCmds.empty() &&
(lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" ||
lang == "HIP" || lang == "ISPC" || lang == "OBJC" ||
lang == "OBJCXX")) {
std::string const clauncher_prop = cmStrCat(lang, "_COMPILER_LAUNCHER");
cmValue clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
std::string evaluatedClauncher = cmGeneratorExpression::Evaluate(
*clauncher, this->LocalGenerator, config, this->GeneratorTarget, nullptr,
this->GeneratorTarget, lang);
if (!evaluatedClauncher.empty()) {
compilerLauncher = evaluatedClauncher;
}
}
// Maybe insert an include-what-you-use runner.
if (!compileCmds.empty() &&
(lang == "C" || lang == "CXX" || lang == "OBJC" || lang == "OBJCXX")) {
cmValue tidy = nullptr;
cmValue iwyu = nullptr;
cmValue cpplint = nullptr;
cmValue cppcheck = nullptr;
std::string evaluatedTIDY;
std::string evaluatedIWYU;
std::string evaluatedCPPlint;
std::string evaluatedCPPcheck;
std::string const tidy_prop = cmStrCat(lang, "_CLANG_TIDY");
tidy = this->GeneratorTarget->GetProperty(tidy_prop);
evaluatedTIDY = cmGeneratorExpression::Evaluate(
*tidy, this->LocalGenerator, config, this->GeneratorTarget, nullptr,
this->GeneratorTarget, lang);
if (!evaluatedTIDY.empty()) {
tidy = cmValue(&evaluatedTIDY);
}
if (lang == "C" || lang == "CXX") {
std::string const iwyu_prop = cmStrCat(lang, "_INCLUDE_WHAT_YOU_USE");
iwyu = this->GeneratorTarget->GetProperty(iwyu_prop);
evaluatedIWYU = cmGeneratorExpression::Evaluate(
*iwyu, this->LocalGenerator, config, this->GeneratorTarget, nullptr,
this->GeneratorTarget, lang);
if (!evaluatedIWYU.empty()) {
iwyu = cmValue(&evaluatedIWYU);
}
std::string const cpplint_prop = cmStrCat(lang, "_CPPLINT");
cpplint = this->GeneratorTarget->GetProperty(cpplint_prop);
evaluatedCPPlint = cmGeneratorExpression::Evaluate(
*cpplint, this->LocalGenerator, config, this->GeneratorTarget, nullptr,
this->GeneratorTarget, lang);
if (!evaluatedCPPlint.empty()) {
cpplint = cmValue(&evaluatedCPPlint);
}
std::string const cppcheck_prop = cmStrCat(lang, "_CPPCHECK");
cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop);
evaluatedCPPcheck = cmGeneratorExpression::Evaluate(
*cppcheck, this->LocalGenerator, config, this->GeneratorTarget,
nullptr, this->GeneratorTarget, lang);
if (!evaluatedCPPcheck.empty()) {
cppcheck = cmValue(&evaluatedCPPcheck);
}
}
if (cmNonempty(iwyu) || cmNonempty(tidy) || cmNonempty(cpplint) ||
cmNonempty(cppcheck)) {
std::string run_iwyu = cmStrCat(cmakeCmd, " -E __run_co_compile");
if (!compilerLauncher.empty()) {
// In __run_co_compile case the launcher command is supplied
// via --launcher=<maybe-list> and consumed
run_iwyu +=
cmStrCat(" --launcher=",
this->LocalGenerator->EscapeForShell(compilerLauncher));
compilerLauncher.clear();
}
if (cmNonempty(iwyu)) {
run_iwyu += " --iwyu=";
// Only add --driver-mode if it is not already specified, as adding
// it unconditionally might override a user-specified driver-mode
if (iwyu.Get()->find("--driver-mode=") == std::string::npos) {
cmValue p = this->Makefile->GetDefinition(
cmStrCat("CMAKE_", lang, "_INCLUDE_WHAT_YOU_USE_DRIVER_MODE"));
std::string driverMode;
if (cmNonempty(p)) {
driverMode = *p;
} else {
driverMode = lang == "C" ? "gcc" : "g++";
}
run_iwyu += this->LocalGenerator->EscapeForShell(
cmStrCat(*iwyu, ";--driver-mode=", driverMode));
} else {
run_iwyu += this->LocalGenerator->EscapeForShell(*iwyu);
}
}
if (cmNonempty(tidy)) {
run_iwyu += " --tidy=";
cmValue p = this->Makefile->GetDefinition(
cmStrCat("CMAKE_", lang, "_CLANG_TIDY_DRIVER_MODE"));
std::string driverMode;
if (cmNonempty(p)) {
driverMode = *p;
} else {
driverMode = lang == "C" ? "gcc" : "g++";
}
const bool haveClangTidyExportFixesDir =
!this->GeneratorTarget->GetClangTidyExportFixesDirectory(lang)
.empty();
std::string exportFixes;
if (haveClangTidyExportFixesDir) {
exportFixes = ";--export-fixes=$CLANG_TIDY_EXPORT_FIXES";
}
run_iwyu += this->GetLocalGenerator()->EscapeForShell(
cmStrCat(*tidy, ";--extra-arg-before=--driver-mode=", driverMode,
exportFixes));
if (haveClangTidyExportFixesDir) {
std::string search = cmStrCat(
this->GetLocalGenerator()->GetState()->UseWindowsShell() ? ""
: "\\",
"$$CLANG_TIDY_EXPORT_FIXES");
auto loc = run_iwyu.rfind(search);
run_iwyu.replace(loc, search.length(), "$CLANG_TIDY_EXPORT_FIXES");
}
}
if (cmNonempty(cpplint)) {
run_iwyu += cmStrCat(
" --cpplint=", this->GetLocalGenerator()->EscapeForShell(*cpplint));
}
if (cmNonempty(cppcheck)) {
run_iwyu +=
cmStrCat(" --cppcheck=",
this->GetLocalGenerator()->EscapeForShell(*cppcheck));
}
if (cmNonempty(tidy) || cmNonempty(cpplint) || cmNonempty(cppcheck)) {
run_iwyu += " --source=$in";
}
run_iwyu += " -- ";
compileCmds.front().insert(0, run_iwyu);
}
}
// If compiler launcher was specified and not consumed above, it
// goes to the beginning of the command line.
if (!compileCmds.empty() && !compilerLauncher.empty()) {
cmList args{ compilerLauncher, cmList::EmptyElements::Yes };
if (!args.empty()) {
args[0] = this->LocalGenerator->ConvertToOutputFormat(
args[0], cmOutputConverter::SHELL);
for (std::string& i : cmMakeRange(args.begin() + 1, args.end())) {
i = this->LocalGenerator->EscapeForShell(i);
}
}
compileCmds.front().insert(0, cmStrCat(args.join(" "), ' '));
if (!compileCmds.empty()) {
compileCmds.front().insert(0, "${CODE_CHECK}");
compileCmds.front().insert(0, "${LAUNCHER}");
}
if (!compileCmds.empty()) {
@ -1373,6 +1219,29 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
vars["FLAGS"] = this->ComputeFlagsForObject(source, language, config);
vars["DEFINES"] = this->ComputeDefines(source, language, config);
vars["INCLUDES"] = this->ComputeIncludes(source, language, config);
auto const cmakeCmd = this->GetLocalGenerator()->ConvertToOutputFormat(
cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
auto compilerLauncher = this->GetCompilerLauncher(language, config);
vars["CODE_CHECK"] =
this->GenerateCodeCheckRules(*source, compilerLauncher, cmakeCmd, config,
[this](std::string const& path) {
return this->ConvertToNinjaPath(path);
});
// If compiler launcher was specified and not consumed above, it
// goes to the beginning of the command line.
if (!compilerLauncher.empty()) {
cmList args{ compilerLauncher, cmList::EmptyElements::Yes };
if (!args.empty()) {
args[0] = this->LocalGenerator->ConvertToOutputFormat(
args[0], cmOutputConverter::SHELL);
for (std::string& i : cmMakeRange(args.begin() + 1, args.end())) {
i = this->LocalGenerator->EscapeForShell(i);
}
vars["LAUNCHER"] = args.join(" ") + " ";
}
}
if (this->GetMakefile()->GetSafeDefinition(
cmStrCat("CMAKE_", language, "_DEPFILE_FORMAT")) != "msvc"_s) {
@ -1397,18 +1266,6 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
}
}
std::string d =
this->GeneratorTarget->GetClangTidyExportFixesDirectory(language);
if (!d.empty()) {
this->GlobalCommonGenerator->AddClangTidyExportFixesDir(d);
std::string fixesFile =
this->GetClangTidyReplacementsFilePath(d, source, config);
this->GlobalCommonGenerator->AddClangTidyExportFixesFile(fixesFile);
cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(fixesFile));
fixesFile = this->ConvertToNinjaPath(fixesFile);
vars["CLANG_TIDY_EXPORT_FIXES"] = fixesFile;
}
if (firstForConfig) {
this->ExportObjectCompileCommand(
language, sourceFilePath, objectDir, objectFileName, objectFileDir,

View File

@ -136,8 +136,8 @@ protected:
/// @return the clang-tidy replacements file path for the given @a source.
std::string GetClangTidyReplacementsFilePath(
const std::string& directory, cmSourceFile const* source,
const std::string& config) const;
std::string const& directory, cmSourceFile const& source,
std::string const& config) const override;
/// @return the dyndep file path for this target.
std::string GetDyndepFilePath(std::string const& lang,