From 993dde925f208d98c68edcd451b0d6979e0abdd4 Mon Sep 17 00:00:00 2001 From: Orkun Tokdemir Date: Fri, 12 May 2023 16:40:28 +0200 Subject: 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. --- Source/cmCommonTargetGenerator.cxx | 165 ++++++++++++++++++++++++++++ Source/cmCommonTargetGenerator.h | 10 ++ Source/cmGlobalNinjaGenerator.cxx | 12 ++- Source/cmMakefileTargetGenerator.cxx | 167 ++++------------------------ Source/cmMakefileTargetGenerator.h | 4 + Source/cmNinjaTargetGenerator.cxx | 203 ++++++----------------------------- Source/cmNinjaTargetGenerator.h | 4 +- 7 files changed, 245 insertions(+), 320 deletions(-) diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 1cb62b3..2615494 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -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 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= 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) { diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index 2d23037..c9886d0 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -4,6 +4,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include #include #include #include @@ -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 const& pathConverter); + std::string GetCompilerLauncher(std::string const& lang, + std::string const& config); std::vector GetLinkedTargetDirectories( const std::string& lang, const std::string& config) const; std::string ComputeTargetCompilePDB(const std::string& config) const; diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 7626fa3..b598c9b 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -507,8 +507,18 @@ void cmGlobalNinjaGenerator::WriteVariable(std::ostream& os, return; } + std::string val; + static std::unordered_set 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; } diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index cf09d09..1cf3b8b 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -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= 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() { diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index ef7a60f..08d6945 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -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 diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 5bf6a2b..cad4bf4 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -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= 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, diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 8f4a764..8c38499 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -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, -- cgit v0.12