diff options
author | Brad King <brad.king@kitware.com> | 2023-05-18 13:24:01 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2023-05-18 13:24:17 (GMT) |
commit | 4d5c32fa2cd0170617d1ab489b17ec7fee87b89d (patch) | |
tree | 62d181c52c9750f9dfce98765f1f029762afa277 | |
parent | b6c45d28b2e2cd45fe69fc68c6ca2f1fefe9afd9 (diff) | |
parent | 775c369420ece1500c2de46b83d5564480d05f70 (diff) | |
download | CMake-4d5c32fa2cd0170617d1ab489b17ec7fee87b89d.zip CMake-4d5c32fa2cd0170617d1ab489b17ec7fee87b89d.tar.gz CMake-4d5c32fa2cd0170617d1ab489b17ec7fee87b89d.tar.bz2 |
Merge topic 'skip-linting'
775c369420 Autogen: set SKIP_LINTING ON for generated files
b480315e0c TargetGenerator: Add SKIP_LINTING source property
993dde925f TargetGenerator: Factor out generation of code check rules
023af4ab2f Improve Const Correctness
Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: buildbot <buildbot@kitware.com>
Merge-request: !8467
32 files changed, 479 insertions, 356 deletions
diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim index aefdcee..2e83a07 100644 --- a/Auxiliary/vim/syntax/cmake.vim +++ b/Auxiliary/vim/syntax/cmake.vim @@ -329,6 +329,7 @@ syn keyword cmakeProperty contained \ SKIP_REGULAR_EXPRESSION \ SKIP_RETURN_CODE \ SKIP_UNITY_BUILD_INCLUSION + \ SKIP_LINTING \ SOURCES \ SOURCE_DIR \ SOVERSION diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 8ee5573..b8026ef 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -559,6 +559,7 @@ Properties on Source Files /prop_sf/SKIP_AUTOUIC /prop_sf/SKIP_PRECOMPILE_HEADERS /prop_sf/SKIP_UNITY_BUILD_INCLUSION + /prop_sf/SKIP_LINTING /prop_sf/Swift_DEPENDENCIES_FILE /prop_sf/Swift_DIAGNOSTICS_FILE /prop_sf/SYMBOLIC diff --git a/Help/prop_sf/SKIP_LINTING.rst b/Help/prop_sf/SKIP_LINTING.rst new file mode 100644 index 0000000..2be47cb --- /dev/null +++ b/Help/prop_sf/SKIP_LINTING.rst @@ -0,0 +1,41 @@ +SKIP_LINTING +------------ + +.. versionadded:: 3.27 + +This property allows you to exclude a specific source file +from the linting process. The linting process involves running +tools such as :prop_tgt:`<LANG>_CPPLINT`, :prop_tgt:`<LANG>_CLANG_TIDY`, +:prop_tgt:`<LANG>_CPPCHECK`, and :prop_tgt:`<LANG>_INCLUDE_WHAT_YOU_USE` +on the source files. By setting `SKIP_LINTING` on a source file, +the mentioned linting tools will not be executed for that +particular file. + +EXAMPLE +^^^^^^^ + +Consider a `C++` project that includes multiple source files, +such as `main.cpp`, `things.cpp`, and `generatedBindings.cpp`. +In this example, you want to exclude the `generatedBindings.cpp` +file from the linting process. To achieve this, you can utilize +the `SKIP_LINTING` property with the `set_source_files_properties` +command as shown below: + +.. code-block:: cmake + + add_executable(MyApp main.cpp things.cpp generatedBindings.cpp) + + set_source_files_properties(generatedBindings.cpp PROPERTIES + SKIP_LINTING ON + ) + +In the provided code snippet, the `SKIP_LINTING` property is set to `ON` +for the `generatedBindings.cpp` source file. As a result, when the linting +tools, such as :prop_tgt:`<LANG>_CPPLINT`, :prop_tgt:`<LANG>_CLANG_TIDY`, +:prop_tgt:`<LANG>_CPPCHECK`, and :prop_tgt:`<LANG>_INCLUDE_WHAT_YOU_USE`, +are executed, they will skip analyzing the `generatedBindings.cpp` file. + +By using the `SKIP_LINTING` property, you can selectively exclude specific +source files from the linting process. This allows you to focus the +linting tools on the relevant parts of your project, enhancing the efficiency +and effectiveness of the linting workflow. diff --git a/Help/prop_tgt/LANG_CLANG_TIDY.rst b/Help/prop_tgt/LANG_CLANG_TIDY.rst index 1e10933..0e46643 100644 --- a/Help/prop_tgt/LANG_CLANG_TIDY.rst +++ b/Help/prop_tgt/LANG_CLANG_TIDY.rst @@ -30,3 +30,10 @@ when a target is created. This property supports :manual:`generator expressions <cmake-generator-expressions(7)>`. + + :prop_sf:`SKIP_LINTING` can be set on individual source files to exclude + them from the linting process, which includes tools like + :prop_tgt:`<LANG>_CPPLINT`, :prop_tgt:`<LANG>_CLANG_TIDY`, + :prop_tgt:`<LANG>_CPPCHECK`, and :prop_tgt:`<LANG>_INCLUDE_WHAT_YOU_USE`. + When :prop_sf:`SKIP_LINTING` is set on a source file, the mentioned tools + will not be run on that specific file. diff --git a/Help/prop_tgt/LANG_CPPCHECK.rst b/Help/prop_tgt/LANG_CPPCHECK.rst index 0b2dee6..3ab2b58 100644 --- a/Help/prop_tgt/LANG_CPPCHECK.rst +++ b/Help/prop_tgt/LANG_CPPCHECK.rst @@ -20,3 +20,10 @@ created. This property supports :manual:`generator expressions <cmake-generator-expressions(7)>`. + + :prop_sf:`SKIP_LINTING` can be set on individual source files to exclude + them from the linting process, which includes tools like + :prop_tgt:`<LANG>_CPPLINT`, :prop_tgt:`<LANG>_CLANG_TIDY`, + :prop_tgt:`<LANG>_CPPCHECK`, and :prop_tgt:`<LANG>_INCLUDE_WHAT_YOU_USE`. + When :prop_sf:`SKIP_LINTING` is set on a source file, the mentioned tools + will not be run on that specific file. diff --git a/Help/prop_tgt/LANG_CPPLINT.rst b/Help/prop_tgt/LANG_CPPLINT.rst index 38a1669..cb230d3 100644 --- a/Help/prop_tgt/LANG_CPPLINT.rst +++ b/Help/prop_tgt/LANG_CPPLINT.rst @@ -18,3 +18,10 @@ created. This property supports :manual:`generator expressions <cmake-generator-expressions(7)>`. + + :prop_sf:`SKIP_LINTING` can be set on individual source files to exclude + them from the linting process, which includes tools like + :prop_tgt:`<LANG>_CPPLINT`, :prop_tgt:`<LANG>_CLANG_TIDY`, + :prop_tgt:`<LANG>_CPPCHECK`, and :prop_tgt:`<LANG>_INCLUDE_WHAT_YOU_USE`. + When :prop_sf:`SKIP_LINTING` is set on a source file, the mentioned tools + will not be run on that specific file. diff --git a/Help/prop_tgt/LANG_INCLUDE_WHAT_YOU_USE.rst b/Help/prop_tgt/LANG_INCLUDE_WHAT_YOU_USE.rst index 19b97f7..8fbe84a 100644 --- a/Help/prop_tgt/LANG_INCLUDE_WHAT_YOU_USE.rst +++ b/Help/prop_tgt/LANG_INCLUDE_WHAT_YOU_USE.rst @@ -18,3 +18,10 @@ when a target is created. This property supports :manual:`generator expressions <cmake-generator-expressions(7)>`. + + :prop_sf:`SKIP_LINTING` can be set on individual source files to exclude + them from the linting process, which includes tools like + :prop_tgt:`<LANG>_CPPLINT`, :prop_tgt:`<LANG>_CLANG_TIDY`, + :prop_tgt:`<LANG>_CPPCHECK`, and :prop_tgt:`<LANG>_INCLUDE_WHAT_YOU_USE`. + When :prop_sf:`SKIP_LINTING` is set on a source file, the mentioned tools + will not be run on that specific file. diff --git a/Help/release/dev/skip-linting.rst b/Help/release/dev/skip-linting.rst new file mode 100644 index 0000000..199571c --- /dev/null +++ b/Help/release/dev/skip-linting.rst @@ -0,0 +1,5 @@ +skip-linting +------------ + +* The :prop_sf:`SKIP_LINTING` source file property was added to suppress + target-wide code checks on specific sources. 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<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) { 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 <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; 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<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; } diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 02cdf57..c915e26 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" @@ -420,7 +419,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() this->GeneratorTarget->HasLinkDependencyFile(this->GetConfigName()); if (compilerGenerateDeps || linkerGenerateDeps || ccGenerateDeps) { - std::string compilerDependFile = + std::string const compilerDependFile = cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.make"); *this->BuildFileStream << "# Include any dependencies generated by the " "compiler for this target.\n" @@ -613,17 +612,17 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( } // Use compiler to generate dependencies, if supported. - bool compilerGenerateDeps = + bool const compilerGenerateDeps = this->GlobalGenerator->SupportsCompilerDependencies() && cmIsOn(this->Makefile->GetDefinition( cmStrCat("CMAKE_", lang, "_DEPENDS_USE_COMPILER"))); - auto scanner = compilerGenerateDeps ? cmDependencyScannerKind::Compiler - : cmDependencyScannerKind::CMake; + auto const scanner = compilerGenerateDeps ? cmDependencyScannerKind::Compiler + : cmDependencyScannerKind::CMake; // Get the full path name of the object file. std::string const& objectName = this->GeneratorTarget->GetObjectName(&source); - std::string obj = + std::string const obj = cmStrCat(this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), '/', objectName); @@ -642,7 +641,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // Create the directory containing the object file. This may be a // subdirectory under the target's directory. { - std::string dir = cmSystemTools::GetFilenamePath(obj); + std::string const dir = cmSystemTools::GetFilenamePath(obj); cmSystemTools::MakeDirectory(this->LocalGenerator->ConvertToFullPath(dir)); } @@ -656,7 +655,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::string objFullPath = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/', obj); objFullPath = cmSystemTools::CollapseFullPath(objFullPath); - std::string srcFullPath = + std::string const srcFullPath = cmSystemTools::CollapseFullPath(source.GetFullPath()); this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, lang, objFullPath, srcFullPath, scanner); @@ -669,8 +668,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // generate the depend scanning rule this->WriteObjectDependRules(source, depends); - std::string config = this->GetConfigName(); - std::string configUpper = cmSystemTools::UpperCase(config); + std::string const config = this->GetConfigName(); + std::string const configUpper = cmSystemTools::UpperCase(config); // Add precompile headers dependencies std::vector<std::string> architectures = @@ -726,7 +725,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( this->GeneratorTarget->AddExplicitLanguageFlags(flags, source); // Add language-specific flags. - std::string langFlags = cmStrCat("$(", lang, "_FLAGS", filterArch, ")"); + std::string const langFlags = + cmStrCat("$(", lang, "_FLAGS", filterArch, ")"); this->LocalGenerator->AppendFlags(flags, langFlags); cmGeneratorExpressionInterpreter genexInterpreter( @@ -745,7 +745,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( cmSystemTools::GetFilenameWithoutLastExtension(objectName); ispcSource = cmSystemTools::GetFilenameWithoutLastExtension(ispcSource); - cmValue ispcSuffixProp = + cmValue const ispcSuffixProp = this->GeneratorTarget->GetProperty("ISPC_HEADER_SUFFIX"); assert(ispcSuffixProp); @@ -784,7 +784,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // Add precompile headers compile options. if (!pchSources.empty() && !source.GetProperty("SKIP_PRECOMPILE_HEADERS")) { std::string pchOptions; - auto pchIt = pchSources.find(source.GetFullPath()); + auto const pchIt = pchSources.find(source.GetFullPath()); if (pchIt != pchSources.end()) { pchOptions = this->GeneratorTarget->GetPchCreateCompileOptions( config, lang, pchIt->second); @@ -830,7 +830,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( << "_DEFINES = " << evaluatedDefs << "\n" << "\n"; } - std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper); + std::string const defPropName = + cmStrCat("COMPILE_DEFINITIONS_", configUpper); if (cmValue config_compile_defs = source.GetProperty(defPropName)) { const std::string& evaluatedDefs = genexInterpreter.Evaluate(*config_compile_defs, COMPILE_DEFINITIONS); @@ -841,7 +842,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( } // Get the output paths for source and object files. - std::string sourceFile = this->LocalGenerator->ConvertToOutputFormat( + std::string const sourceFile = this->LocalGenerator->ConvertToOutputFormat( source.GetFullPath(), cmOutputConverter::SHELL); // Construct the build message. @@ -897,7 +898,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( targetOutPathCompilePDB.back() = '/'; } - std::string compilePdbOutputPath = + std::string const compilePdbOutputPath = this->GeneratorTarget->GetCompilePDBDirectory(this->GetConfigName()); cmSystemTools::MakeDirectory(compilePdbOutputPath); } @@ -910,7 +911,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( vars.TargetPDB = targetOutPathPDB.c_str(); vars.TargetCompilePDB = targetOutPathCompilePDB.c_str(); vars.Source = sourceFile.c_str(); - std::string shellObj = + std::string const shellObj = this->LocalGenerator->ConvertToOutputFormat(obj, cmOutputConverter::SHELL); vars.Object = shellObj.c_str(); std::string objectDir = this->GeneratorTarget->GetSupportDirectory(); @@ -960,7 +961,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // At the moment, it is assumed that C, C++, Fortran, and CUDA have both // assembly and preprocessor capabilities. The same is true for the // ability to export compile commands - bool lang_has_preprocessor = + bool const lang_has_preprocessor = ((lang == "C") || (lang == "CXX") || (lang == "OBJC") || (lang == "OBJCXX") || (lang == "Fortran") || (lang == "CUDA") || lang == "ISPC" || lang == "HIP" || lang == "ASM"); @@ -1016,31 +1017,31 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // no launcher for CMAKE_EXPORT_COMPILE_COMMANDS rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, compileCommand, vars); - std::string workingDirectory = + std::string const workingDirectory = this->LocalGenerator->GetCurrentBinaryDirectory(); std::string::size_type lfPos = compileCommand.find(langFlags); if (lfPos != std::string::npos) { compileCommand.replace(lfPos, langFlags.size(), this->GetFlags(lang, this->GetConfigName())); } - std::string langDefines = std::string("$(") + lang + "_DEFINES)"; - std::string::size_type ldPos = compileCommand.find(langDefines); + std::string const langDefines = std::string("$(") + lang + "_DEFINES)"; + std::string::size_type const ldPos = compileCommand.find(langDefines); if (ldPos != std::string::npos) { compileCommand.replace(ldPos, langDefines.size(), this->GetDefines(lang, this->GetConfigName())); } - std::string langIncludes = std::string("$(") + lang + "_INCLUDES)"; - std::string::size_type liPos = compileCommand.find(langIncludes); + std::string const langIncludes = std::string("$(") + lang + "_INCLUDES)"; + std::string::size_type const liPos = compileCommand.find(langIncludes); if (liPos != std::string::npos) { compileCommand.replace(liPos, langIncludes.size(), this->GetIncludes(lang, this->GetConfigName())); } - cmValue eliminate[] = { + cmValue const eliminate[] = { this->Makefile->GetDefinition("CMAKE_START_TEMP_FILE"), this->Makefile->GetDefinition("CMAKE_END_TEMP_FILE") }; - for (cmValue el : eliminate) { + for (cmValue const& el : eliminate) { if (el) { cmSystemTools::ReplaceString(compileCommand, *el, ""); } @@ -1052,150 +1053,16 @@ 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); + cmValue const skipCodeCheck = source.GetProperty("SKIP_LINTING"); + if (!skipCodeCheck.IsOn()) { + std::string const codeCheck = this->GenerateCodeCheckRules( + source, compilerLauncher, "$(CMAKE_COMMAND)", config, nullptr); + if (!codeCheck.empty()) { + compileCommands.front().insert(0, codeCheck); } } @@ -1330,8 +1197,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( if (do_preprocess_rules) { commands.clear(); - std::string relativeObjI = relativeObjBase + ".i"; - std::string objI = objBase + ".i"; + std::string const relativeObjI = relativeObjBase + ".i"; + std::string const objI = objBase + ".i"; std::string preprocessEcho = cmStrCat("Preprocessing ", lang, " source to ", objI); @@ -1423,7 +1290,7 @@ void cmMakefileTargetGenerator::WriteTargetCleanRules() std::vector<std::string> commands; // Construct the clean target name. - std::string cleanTarget = cmStrCat( + std::string const cleanTarget = cmStrCat( this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget), "/clean"); @@ -1451,7 +1318,7 @@ bool cmMakefileTargetGenerator::WriteMakeRule( } // Check whether we need to bother checking for a symbolic output. - bool need_symbolic = this->GlobalGenerator->GetNeedSymbolicMark(); + bool const need_symbolic = this->GlobalGenerator->GetNeedSymbolicMark(); // Check whether the first output is marked as symbolic. if (need_symbolic) { @@ -1481,7 +1348,7 @@ bool cmMakefileTargetGenerator::WriteMakeRule( bool o_symbolic = false; if (need_symbolic) { - if (cmSourceFile* sf = this->Makefile->GetSource(output)) { + if (cmSourceFile const* sf = this->Makefile->GetSource(output)) { o_symbolic = sf->GetPropertyAsBool("SYMBOLIC"); } } @@ -1517,6 +1384,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() { @@ -1559,7 +1443,7 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() "# Targets to which this target links which contain Fortran sources.\n" "set(CMAKE_Fortran_TARGET_LINKED_INFO_FILES\n"; /* clang-format on */ - std::vector<std::string> dirs = + std::vector<std::string> const dirs = this->GetLinkedTargetDirectories("Fortran", this->GetConfigName()); for (std::string const& d : dirs) { *this->InfoFileStream << " \"" << d << "/DependInfo.cmake\"\n"; @@ -1591,7 +1475,7 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() std::vector<std::string> commands; // Construct the name of the dependency generation target. - std::string depTarget = cmStrCat( + std::string const depTarget = cmStrCat( this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget), "/depend"); @@ -1701,7 +1585,7 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule( deps.emplace_back(cmStrCat(relPath, obj)); } - std::unordered_set<std::string> depsSet(deps.begin(), deps.end()); + std::unordered_set<std::string> const depsSet(deps.begin(), deps.end()); deps.clear(); std::copy(depsSet.begin(), depsSet.end(), std::back_inserter(deps)); return deps; @@ -1785,7 +1669,7 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule( this->GetDeviceLinkFlags(linkFlags, "CUDA"); vars.LinkFlags = linkFlags.c_str(); - std::string flags = this->GetFlags("CUDA", this->GetConfigName()); + std::string const flags = this->GetFlags("CUDA", this->GetConfigName()); vars.Flags = flags.c_str(); std::string compileCmd = this->GetLinkRule("CMAKE_CUDA_DEVICE_LINK_COMPILE"); @@ -1839,8 +1723,8 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile( // Write the rule. const std::vector<std::string>& outputs = ccg.GetOutputs(); - bool symbolic = this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs, - depends, commands); + bool const symbolic = this->WriteMakeRule(*this->BuildFileStream, nullptr, + outputs, depends, commands); // Symbolic inputs are not expected to exist, so add dummy rules. if (this->CMP0113New && !depends.empty()) { @@ -2328,7 +2212,7 @@ void cmMakefileTargetGenerator::CreateObjectLists( useWatcomQuote); if (useResponseFile) { // MSVC response files cannot exceed 128K. - std::string::size_type const responseFileLimit = 131000; + std::string::size_type constexpr responseFileLimit = 131000; // Construct the individual object list strings. std::vector<std::string> object_strings; @@ -2461,7 +2345,8 @@ std::string cmMakefileTargetGenerator::GetResponseFlag( std::string responseFlag = "@"; std::string responseFlagVar; - auto lang = this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); + auto const lang = + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); if (mode == cmMakefileTargetGenerator::ResponseFlagFor::Link) { responseFlagVar = cmStrCat("CMAKE_", lang, "_RESPONSE_FILE_LINK_FLAG"); } else if (mode == cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink) { 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..25e00d3 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=<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()) { @@ -1374,6 +1220,33 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( vars["DEFINES"] = this->ComputeDefines(source, language, config); vars["INCLUDES"] = this->ComputeIncludes(source, language, config); + auto compilerLauncher = this->GetCompilerLauncher(language, config); + + cmValue const skipCodeCheck = source->GetProperty("SKIP_LINTING"); + if (!skipCodeCheck.IsOn()) { + auto const cmakeCmd = this->GetLocalGenerator()->ConvertToOutputFormat( + cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); + vars["CODE_CHECK"] = + this->GenerateCodeCheckRules(*source, compilerLauncher, cmakeCmd, config, + [this](const std::string& 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) { bool replaceExt(false); @@ -1397,18 +1270,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, diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index d897f0e..76bb0cd 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -1834,6 +1834,7 @@ cmSourceFile* cmQtAutoGenInitializer::RegisterGeneratedSource( cmSourceFile* gFile = this->Makefile->GetOrCreateSource(filename, true); gFile->MarkAsGenerated(); gFile->SetProperty("SKIP_AUTOGEN", "1"); + gFile->SetProperty("SKIP_LINTING", "ON"); return gFile; } diff --git a/Tests/RunCMake/Autogen/AutogenSkipLinting-build-stderr.txt b/Tests/RunCMake/Autogen/AutogenSkipLinting-build-stderr.txt new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/Tests/RunCMake/Autogen/AutogenSkipLinting-build-stderr.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/Autogen/AutogenSkipLinting.cmake b/Tests/RunCMake/Autogen/AutogenSkipLinting.cmake new file mode 100644 index 0000000..3ce2092 --- /dev/null +++ b/Tests/RunCMake/Autogen/AutogenSkipLinting.cmake @@ -0,0 +1,16 @@ +enable_language(CXX) + +find_package(Qt${with_qt_version} REQUIRED COMPONENTS Core Widgets Gui) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "$<1:${PSEUDO_IWYU}>" -some -args) +set(CMAKE_CXX_CLANG_TIDY "$<1:${PSEUDO_TIDY}>" -bad) +set(CMAKE_CXX_CPPLINT "$<1:${PSEUDO_CPPLINT}>" --error) +set(CMAKE_CXX_CPPCHECK "$<1:${PSEUDO_CPPCHECK}>" -error) + +add_executable(SkipLinting SkipLinting.cxx SkipLinting.h) +set_source_files_properties(SkipLinting.cxx PROPERTIES SKIP_LINTING TRUE) + +target_link_libraries(SkipLinting Qt${with_qt_version}::Core + Qt${with_qt_version}::Widgets + Qt${with_qt_version}::Gui) diff --git a/Tests/RunCMake/Autogen/RunCMakeTest.cmake b/Tests/RunCMake/Autogen/RunCMakeTest.cmake index 4505132..97b64ed 100644 --- a/Tests/RunCMake/Autogen/RunCMakeTest.cmake +++ b/Tests/RunCMake/Autogen/RunCMakeTest.cmake @@ -87,5 +87,20 @@ if (DEFINED with_qt_version) message(STATUS "RunCMake_TEST_EXPECT_stdout: ${RunCMake_TEST_EXPECT_stdout}") run_cmake_command(AutogenUseSystemIncludeOff ${CMAKE_COMMAND} --build . --config Debug --verbose) endblock() + + if(RunCMake_GENERATOR MATCHES "Make|Ninja") + block() + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AutogenSkipLinting-build) + list(APPEND RunCMake_TEST_OPTIONS + "-DPSEUDO_CPPCHECK=${PSEUDO_CPPCHECK}" + "-DPSEUDO_CPPLINT=${PSEUDO_CPPLINT}" + "-DPSEUDO_IWYU=${PSEUDO_IWYU}" + "-DPSEUDO_TIDY=${PSEUDO_TIDY}") + + run_cmake(AutogenSkipLinting) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(AutogenSkipLinting-build ${CMAKE_COMMAND} --build . --config Debug --verbose) + endblock() + endif() endif() endif () diff --git a/Tests/RunCMake/Autogen/SkipLinting.cxx b/Tests/RunCMake/Autogen/SkipLinting.cxx new file mode 100644 index 0000000..9e09b27 --- /dev/null +++ b/Tests/RunCMake/Autogen/SkipLinting.cxx @@ -0,0 +1,6 @@ +#include "SkipLinting.h" + +int main() +{ + return 0; +} diff --git a/Tests/RunCMake/Autogen/SkipLinting.h b/Tests/RunCMake/Autogen/SkipLinting.h new file mode 100644 index 0000000..def56a0 --- /dev/null +++ b/Tests/RunCMake/Autogen/SkipLinting.h @@ -0,0 +1,11 @@ +#ifndef SKIP_LINTING_H +#define SKIP_LINTING_H + +#include <QObject> + +class SkipMe : public QObject +{ + Q_OBJECT +}; + +#endif diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index e87239e..3997a74 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -266,6 +266,10 @@ if(CMake_TEST_Qt6 AND Qt6Widgets_FOUND) -Dwith_qt_version=6 "-DQt6_DIR:PATH=${Qt6_DIR}" "-DCMAKE_PREFIX_PATH:STRING=${base_dir}" + -DPSEUDO_TIDY=$<TARGET_FILE:pseudo_tidy> + -DPSEUDO_IWYU=$<TARGET_FILE:pseudo_iwyu> + -DPSEUDO_CPPLINT=$<TARGET_FILE:pseudo_cpplint> + -DPSEUDO_CPPCHECK=$<TARGET_FILE:pseudo_cppcheck> ) set(want_NoQt_test FALSE) endif () diff --git a/Tests/RunCMake/MultiLint/C-launch_skip_linting_ON.cmake b/Tests/RunCMake/MultiLint/C-launch_skip_linting_ON.cmake new file mode 100644 index 0000000..d0d9866 --- /dev/null +++ b/Tests/RunCMake/MultiLint/C-launch_skip_linting_ON.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(C_skip_linting_ON.cmake) diff --git a/Tests/RunCMake/MultiLint/CMakeLists copy.txt b/Tests/RunCMake/MultiLint/CMakeLists copy.txt new file mode 100644 index 0000000..93ee9df --- /dev/null +++ b/Tests/RunCMake/MultiLint/CMakeLists copy.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.5) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/MultiLint/CXX-launch_skip_linting_ON.cmake b/Tests/RunCMake/MultiLint/CXX-launch_skip_linting_ON.cmake new file mode 100644 index 0000000..6347e60 --- /dev/null +++ b/Tests/RunCMake/MultiLint/CXX-launch_skip_linting_ON.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(CXX_skip_linting_ON.cmake) diff --git a/Tests/RunCMake/MultiLint/CXX_skip_linting_OFF-Build-result.txt b/Tests/RunCMake/MultiLint/CXX_skip_linting_OFF-Build-result.txt new file mode 100644 index 0000000..3beecb0 --- /dev/null +++ b/Tests/RunCMake/MultiLint/CXX_skip_linting_OFF-Build-result.txt @@ -0,0 +1 @@ +(1|2) diff --git a/Tests/RunCMake/MultiLint/CXX_skip_linting_OFF.cmake b/Tests/RunCMake/MultiLint/CXX_skip_linting_OFF.cmake new file mode 100644 index 0000000..a0311a6 --- /dev/null +++ b/Tests/RunCMake/MultiLint/CXX_skip_linting_OFF.cmake @@ -0,0 +1,7 @@ +enable_language(CXX) +set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "$<1:${PSEUDO_IWYU}>" -some -args) +set(CMAKE_CXX_CLANG_TIDY "$<1:${PSEUDO_TIDY}>" -bad) +set(CMAKE_CXX_CPPLINT "$<1:${PSEUDO_CPPLINT}>" --error) +set(CMAKE_CXX_CPPCHECK "$<1:${PSEUDO_CPPCHECK}>" -error) +add_executable(main main.cxx) +set_source_files_properties(main.cxx PROPERTIES SKIP_LINTING OFF) diff --git a/Tests/RunCMake/MultiLint/CXX_skip_linting_ON.cmake b/Tests/RunCMake/MultiLint/CXX_skip_linting_ON.cmake new file mode 100644 index 0000000..39cfe87 --- /dev/null +++ b/Tests/RunCMake/MultiLint/CXX_skip_linting_ON.cmake @@ -0,0 +1,7 @@ +enable_language(CXX) +set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "$<1:${PSEUDO_IWYU}>" -some -args) +set(CMAKE_CXX_CLANG_TIDY "$<1:${PSEUDO_TIDY}>" -bad) +set(CMAKE_CXX_CPPLINT "$<1:${PSEUDO_CPPLINT}>" --error) +set(CMAKE_CXX_CPPCHECK "$<1:${PSEUDO_CPPCHECK}>" -error) +add_executable(main main.cxx) +set_source_files_properties(main.cxx PROPERTIES SKIP_LINTING ON) diff --git a/Tests/RunCMake/MultiLint/C_skip_linting_OFF-Build-result.txt b/Tests/RunCMake/MultiLint/C_skip_linting_OFF-Build-result.txt new file mode 100644 index 0000000..3beecb0 --- /dev/null +++ b/Tests/RunCMake/MultiLint/C_skip_linting_OFF-Build-result.txt @@ -0,0 +1 @@ +(1|2) diff --git a/Tests/RunCMake/MultiLint/C_skip_linting_OFF.cmake b/Tests/RunCMake/MultiLint/C_skip_linting_OFF.cmake new file mode 100644 index 0000000..2968a21 --- /dev/null +++ b/Tests/RunCMake/MultiLint/C_skip_linting_OFF.cmake @@ -0,0 +1,7 @@ +enable_language(C) +set(CMAKE_C_INCLUDE_WHAT_YOU_USE "${PSEUDO_IWYU}" -some -args) +set(CMAKE_C_CLANG_TIDY "${PSEUDO_TIDY}" -bad) +set(CMAKE_C_CPPLINT "${PSEUDO_CPPLINT}" --error) +set(CMAKE_C_CPPCHECK "${PSEUDO_CPPCHECK}" -error) +add_executable(main main.c) +set_source_files_properties(main.c PROPERTIES SKIP_LINTING OFF) diff --git a/Tests/RunCMake/MultiLint/C_skip_linting_ON.cmake b/Tests/RunCMake/MultiLint/C_skip_linting_ON.cmake new file mode 100644 index 0000000..09fc761 --- /dev/null +++ b/Tests/RunCMake/MultiLint/C_skip_linting_ON.cmake @@ -0,0 +1,7 @@ +enable_language(C) +set(CMAKE_C_INCLUDE_WHAT_YOU_USE "${PSEUDO_IWYU}" -some -args) +set(CMAKE_C_CLANG_TIDY "${PSEUDO_TIDY}" -bad) +set(CMAKE_C_CPPLINT "${PSEUDO_CPPLINT}" --error) +set(CMAKE_C_CPPCHECK "${PSEUDO_CPPCHECK}" -error) +add_executable(main main.c) +set_source_files_properties(main.c PROPERTIES SKIP_LINTING ON) diff --git a/Tests/RunCMake/MultiLint/RunCMakeTest.cmake b/Tests/RunCMake/MultiLint/RunCMakeTest.cmake index afd98fd..9b7a6a9 100644 --- a/Tests/RunCMake/MultiLint/RunCMakeTest.cmake +++ b/Tests/RunCMake/MultiLint/RunCMakeTest.cmake @@ -25,3 +25,22 @@ if(NOT RunCMake_GENERATOR STREQUAL "Watcom WMake") run_multilint(C-launch) run_multilint(CXX-launch) endif() + +function(run_skip_linting test_name) + set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${test_name}-build") + set(RunCMake_TEST_NO_CLEAN 1) + + run_cmake(${test_name}) + set(RunCMake_TEST_OUTPUT_MERGE 1) + run_cmake_command(${test_name}-Build ${CMAKE_COMMAND} --build .) +endfunction() + +run_skip_linting(C_skip_linting_ON) +run_skip_linting(CXX_skip_linting_ON) +run_skip_linting(C_skip_linting_OFF) +run_skip_linting(CXX_skip_linting_OFF) + +if(NOT RunCMake_GENERATOR STREQUAL "Watcom WMake") + run_skip_linting(C-launch_skip_linting_ON) + run_skip_linting(CXX-launch_skip_linting_ON) +endif() |