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
parent
023af4ab2f
commit
993dde925f
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue