clang-tidy: add <LANG>_CLANG_TIDY_EXPORT_FIXES_DIR property

Fixes: #21362
This commit is contained in:
Kyle Edwards
2022-12-06 10:39:29 -05:00
parent 7ea665b74d
commit 232467eb1c
28 changed files with 397 additions and 2 deletions
+1
View File
@@ -301,6 +301,7 @@ Properties on Targets
/prop_tgt/JOB_POOL_PRECOMPILE_HEADER
/prop_tgt/LABELS
/prop_tgt/LANG_CLANG_TIDY
/prop_tgt/LANG_CLANG_TIDY_EXPORT_FIXES_DIR
/prop_tgt/LANG_COMPILER_LAUNCHER
/prop_tgt/LANG_CPPCHECK
/prop_tgt/LANG_CPPLINT
+1
View File
@@ -450,6 +450,7 @@ Variables that Control the Build
/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION_CONFIG
/variable/CMAKE_IOS_INSTALL_COMBINED
/variable/CMAKE_LANG_CLANG_TIDY
/variable/CMAKE_LANG_CLANG_TIDY_EXPORT_FIXES_DIR
/variable/CMAKE_LANG_COMPILER_LAUNCHER
/variable/CMAKE_LANG_CPPCHECK
/variable/CMAKE_LANG_CPPLINT
@@ -0,0 +1,29 @@
<LANG>_CLANG_TIDY_EXPORT_FIXES_DIR
----------------------------------
.. versionadded:: 3.26
This property is implemented only when ``<LANG>`` is ``C``, ``CXX``, ``OBJC``
or ``OBJCXX``, and only has an effect when :prop_tgt:`<LANG>_CLANG_TIDY` is
set.
Specify a directory for the ``clang-tidy`` tool to put ``.yaml`` files
containing its suggested changes in. This can be used for automated mass
refactoring by ``clang-tidy``. Each object file that gets compiled will have a
corresponding ``.yaml`` file in this directory. After the build is completed,
you can run ``clang-apply-replacements`` on this directory to simultaneously
apply all suggested changes to the code base. If this property is not an
absolute directory, it is assumed to be relative to the target's binary
directory. This property should be preferred over adding an ``--export-fixes``
or ``--fix`` argument directly to the :prop_tgt:`<LANG>_CLANG_TIDY` property.
At generate-time, in order to avoid passing stale fixes from old code to
``clang-apply-replacements``, CMake will search the directory for any ``.yaml``
files that won't be generated by ``clang-tidy`` during the build, and delete
them. In addition, just before running ``clang-tidy`` on a file, CMake will
delete that file's corresponding ``.yaml`` file in case ``clang-tidy`` doesn't
produce any fixes.
This property is initialized by the value of
the :variable:`CMAKE_<LANG>_CLANG_TIDY_EXPORT_FIXES_DIR` variable if it is set
when a target is created.
@@ -0,0 +1,8 @@
clang-tidy-export-fixes-dir
---------------------------
* A new :prop_tgt:`<LANG>_CLANG_TIDY_EXPORT_FIXES_DIR` target property was
created to allow the ``clang-tidy`` tool to export its suggested fixes to a
set of ``.yaml`` files. A new
:variable:`CMAKE_<LANG>_CLANG_TIDY_EXPORT_FIXES_DIR` variable was created to
initialize this property.
@@ -0,0 +1,15 @@
CMAKE_<LANG>_CLANG_TIDY_EXPORT_FIXES_DIR
----------------------------------------
.. versionadded:: 3.26
Default value for :prop_tgt:`<LANG>_CLANG_TIDY_EXPORT_FIXES_DIR` target
property when ``<LANG>`` is ``C``, ``CXX``, ``OBJC`` or ``OBJCXX``.
This variable is used to initialize the property on each target as it is
created. For example:
.. code-block:: cmake
set(CMAKE_CXX_CLANG_TIDY_EXPORT_FIXES_DIR clang-tidy-fixes)
add_executable(foo foo.cxx)
+18
View File
@@ -3726,6 +3726,24 @@ std::string cmGeneratorTarget::GetCreateRuleVariable(
return "";
}
//----------------------------------------------------------------------------
std::string cmGeneratorTarget::GetClangTidyExportFixesDirectory(
const std::string& lang) const
{
cmValue val =
this->GetProperty(cmStrCat(lang, "_CLANG_TIDY_EXPORT_FIXES_DIR"));
if (!cmNonempty(val)) {
return {};
}
std::string path = *val;
if (!cmSystemTools::FileIsFullPath(path)) {
path =
cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/', path);
}
return cmSystemTools::CollapseFullPath(path);
}
namespace {
void processIncludeDirectories(cmGeneratorTarget const* tgt,
EvaluatedTargetPropertyEntries& entries,
+2
View File
@@ -490,6 +490,8 @@ public:
std::string GetCreateRuleVariable(std::string const& lang,
std::string const& config) const;
std::string GetClangTidyExportFixesDirectory(const std::string& lang) const;
private:
using ConfigAndLanguage = std::pair<std::string, std::string>;
using ConfigAndLanguageToBTStrings =
+24
View File
@@ -2,11 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalCommonGenerator.h"
#include <algorithm>
#include <memory>
#include <utility>
#include <cmext/algorithm>
#include <cmsys/Glob.hxx>
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmLocalGenerator.h"
@@ -14,6 +17,7 @@
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"
#include "cmake.h"
@@ -124,3 +128,23 @@ std::string cmGlobalCommonGenerator::GetEditCacheCommand() const
cmValue edit_cmd = cm->GetCacheDefinition("CMAKE_EDIT_COMMAND");
return edit_cmd ? *edit_cmd : std::string();
}
void cmGlobalCommonGenerator::RemoveUnknownClangTidyExportFixesFiles() const
{
for (auto const& dir : this->ClangTidyExportFixesDirs) {
cmsys::Glob g;
g.SetRecurse(true);
g.SetListDirs(false);
g.FindFiles(cmStrCat(dir, "/*.yaml"));
for (auto const& file : g.GetFiles()) {
if (!this->ClangTidyExportFixesFiles.count(file) &&
!std::any_of(this->ClangTidyExportFixesFiles.begin(),
this->ClangTidyExportFixesFiles.end(),
[&file](const std::string& knownFile) -> bool {
return cmSystemTools::SameFile(file, knownFile);
})) {
cmSystemTools::RemoveFile(file);
}
}
}
}
+13
View File
@@ -5,6 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
#include <set>
#include <string>
#include <vector>
@@ -42,9 +43,21 @@ public:
std::map<std::string, DirectoryTarget> ComputeDirectoryTargets() const;
bool IsExcludedFromAllInConfig(const DirectoryTarget::Target& t,
const std::string& config);
void AddClangTidyExportFixesDir(const std::string& dir)
{
this->ClangTidyExportFixesDirs.insert(dir);
}
void AddClangTidyExportFixesFile(const std::string& file)
{
this->ClangTidyExportFixesFiles.insert(file);
}
protected:
virtual bool SupportsDirectConsole() const { return true; }
const char* GetEditCacheTargetName() const override { return "edit_cache"; }
std::string GetEditCacheCommand() const override;
std::set<std::string> ClangTidyExportFixesDirs;
std::set<std::string> ClangTidyExportFixesFiles;
void RemoveUnknownClangTidyExportFixesFiles() const;
};
+4
View File
@@ -592,6 +592,8 @@ void cmGlobalNinjaGenerator::Generate()
this->CMakeCacheFile = this->NinjaOutputPath("CMakeCache.txt");
this->DisableCleandead = false;
this->DiagnosedCxxModuleNinjaSupport = false;
this->ClangTidyExportFixesDirs.clear();
this->ClangTidyExportFixesFiles.clear();
this->PolicyCMP0058 =
this->LocalGenerators[0]->GetMakefile()->GetPolicyStatus(
@@ -632,6 +634,8 @@ void cmGlobalNinjaGenerator::Generate()
{
this->CleanMetaData();
}
this->RemoveUnknownClangTidyExportFixesFiles();
}
void cmGlobalNinjaGenerator::CleanMetaData()
@@ -102,6 +102,9 @@ void cmGlobalUnixMakefileGenerator3::Configure()
void cmGlobalUnixMakefileGenerator3::Generate()
{
this->ClangTidyExportFixesDirs.clear();
this->ClangTidyExportFixesFiles.clear();
// first do superclass method
this->cmGlobalGenerator::Generate();
@@ -137,6 +140,8 @@ void cmGlobalUnixMakefileGenerator3::Generate()
*this->CommandDatabase << "\n]";
this->CommandDatabase.reset();
}
this->RemoveUnknownClangTidyExportFixesFiles();
}
void cmGlobalUnixMakefileGenerator3::AddCXXCompileCommand(
+23 -1
View File
@@ -25,6 +25,7 @@
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLinkLineComputer.h" // IWYU pragma: keep
#include "cmLocalCommonGenerator.h"
@@ -1107,8 +1108,29 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
} 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));
cmStrCat(*tidy, ";--extra-arg-before=--driver-mode=", driverMode,
exportFixes));
}
if (cmNonempty(cpplint)) {
run_iwyu += " --cpplint=";
+48 -1
View File
@@ -27,6 +27,7 @@
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
#include "cmGlobalNinjaGenerator.h"
#include "cmLocalGenerator.h"
#include "cmLocalNinjaGenerator.h"
@@ -394,6 +395,24 @@ std::string cmNinjaTargetGenerator::GetObjectFilePath(
return path;
}
std::string cmNinjaTargetGenerator::GetClangTidyReplacementsFilePath(
const std::string& directory, cmSourceFile const* source,
const std::string& config) const
{
std::string path = this->LocalGenerator->GetHomeRelativeOutputPath();
if (!path.empty()) {
path += '/';
}
path = cmStrCat(directory, '/', path);
std::string const& objectName = this->GeneratorTarget->GetObjectName(source);
path =
cmStrCat(std::move(path),
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget),
this->GetGlobalGenerator()->ConfigDirectory(config), '/',
objectName, ".yaml");
return path;
}
std::string cmNinjaTargetGenerator::GetPreprocessedFilePath(
cmSourceFile const* source, const std::string& config) const
{
@@ -932,8 +951,24 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
} 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));
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(
@@ -1314,6 +1349,18 @@ 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,
+5
View File
@@ -134,6 +134,11 @@ protected:
std::string GetPreprocessedFilePath(cmSourceFile const* source,
const std::string& config) const;
/// @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;
/// @return the dyndep file path for this target.
std::string GetDyndepFilePath(std::string const& lang,
const std::string& config) const;
+4
View File
@@ -573,12 +573,14 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("NO_SYSTEM_FROM_IMPORTED");
initProp("BUILD_WITH_INSTALL_NAME_DIR");
initProp("C_CLANG_TIDY");
initProp("C_CLANG_TIDY_EXPORT_FIXES_DIR");
initProp("C_CPPLINT");
initProp("C_CPPCHECK");
initProp("C_INCLUDE_WHAT_YOU_USE");
initProp("C_LINKER_LAUNCHER");
initProp("LINK_WHAT_YOU_USE");
initProp("CXX_CLANG_TIDY");
initProp("CXX_CLANG_TIDY_EXPORT_FIXES_DIR");
initProp("CXX_CPPLINT");
initProp("CXX_CPPCHECK");
initProp("CXX_INCLUDE_WHAT_YOU_USE");
@@ -600,8 +602,10 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("LINK_SEARCH_START_STATIC");
initProp("LINK_SEARCH_END_STATIC");
initProp("OBJC_CLANG_TIDY");
initProp("OBJC_CLANG_TIDY_EXPORT_FIXES_DIR");
initProp("OBJC_LINKER_LAUNCHER");
initProp("OBJCXX_CLANG_TIDY");
initProp("OBJCXX_CLANG_TIDY_EXPORT_FIXES_DIR");
initProp("OBJCXX_LINKER_LAUNCHER");
initProp("Swift_LANGUAGE_VERSION");
initProp("Swift_MODULE_DIRECTORY");
+6
View File
@@ -367,6 +367,12 @@ int HandleTidy(const std::string& runCmd, const std::string& sourceFile,
std::vector<std::string> tidy_cmd = cmExpandedList(runCmd, true);
tidy_cmd.push_back(sourceFile);
for (auto const& arg : tidy_cmd) {
if (cmHasLiteralPrefix(arg, "--export-fixes=")) {
cmSystemTools::RemoveFile(arg.substr(cmStrLen("--export-fixes=")));
}
}
// clang-tidy supports working out the compile commands from a
// compile_commands.json file in a directory given by a "-p" option, or by
// passing the compiler command line arguments after --. When the latter
@@ -0,0 +1,35 @@
if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
assert_any_file_exists(
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/Debug/main.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/Debug/main.c.obj.yaml"
)
assert_any_file_exists(
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/Debug/extra.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/Debug/extra.c.obj.yaml"
)
assert_any_file_exists(
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/Debug/__/main.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/Debug/__/main.c.obj.yaml"
)
assert_any_file_exists(
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/Debug/__/extra.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/Debug/__/extra.c.obj.yaml"
)
else()
assert_any_file_exists(
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/main.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/main.c.obj.yaml"
)
assert_any_file_exists(
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/extra.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/extra.c.obj.yaml"
)
assert_any_file_exists(
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/__/main.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/__/main.c.obj.yaml"
)
assert_any_file_exists(
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/__/extra.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/__/extra.c.obj.yaml"
)
endif()
@@ -0,0 +1,6 @@
enable_language(C)
set(CMAKE_C_CLANG_TIDY "${PSEUDO_TIDY}" -some -args)
set(CMAKE_C_CLANG_TIDY_EXPORT_FIXES_DIR clang-tidy)
set(files ${CMAKE_CURRENT_SOURCE_DIR}/main.c ${CMAKE_CURRENT_SOURCE_DIR}/extra.c)
add_executable(main ${files})
add_subdirectory(export_fixes_subdir)
@@ -0,0 +1,35 @@
if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
assert_any_file_exists(
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/Debug/main.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/Debug/main.c.obj.yaml"
)
assert_no_file_exists(
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/Debug/extra.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/Debug/extra.c.obj.yaml"
)
assert_any_file_exists(
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/Debug/__/main.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/Debug/__/main.c.obj.yaml"
)
assert_no_file_exists(
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/Debug/__/extra.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/Debug/__/extra.c.obj.yaml"
)
else()
assert_any_file_exists(
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/main.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/main.c.obj.yaml"
)
assert_no_file_exists(
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/extra.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/extra.c.obj.yaml"
)
assert_any_file_exists(
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/__/main.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/__/main.c.obj.yaml"
)
assert_no_file_exists(
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/__/extra.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/__/extra.c.obj.yaml"
)
endif()
@@ -0,0 +1,35 @@
if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
assert_any_file_exists(
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/Debug/main.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/Debug/main.c.obj.yaml"
)
assert_no_file_exists(
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/Debug/extra.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/Debug/extra.c.obj.yaml"
)
assert_any_file_exists(
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/Debug/__/main.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/Debug/__/main.c.obj.yaml"
)
assert_no_file_exists(
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/Debug/__/extra.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/Debug/__/extra.c.obj.yaml"
)
else()
assert_any_file_exists(
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/main.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/main.c.obj.yaml"
)
assert_no_file_exists(
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/extra.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/clang-tidy/CMakeFiles/main.dir/extra.c.obj.yaml"
)
assert_any_file_exists(
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/__/main.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/__/main.c.obj.yaml"
)
assert_no_file_exists(
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/__/extra.c.o.yaml"
"${RunCMake_TEST_BINARY_DIR}/export_fixes_subdir/clang-tidy/export_fixes_subdir/CMakeFiles/subdir.dir/__/extra.c.obj.yaml"
)
endif()
@@ -0,0 +1,6 @@
enable_language(C)
set(CMAKE_C_CLANG_TIDY "${PSEUDO_TIDY}" -some -args)
set(CMAKE_C_CLANG_TIDY_EXPORT_FIXES_DIR clang-tidy)
set(files ${CMAKE_CURRENT_SOURCE_DIR}/main.c)
add_executable(main ${files})
add_subdirectory(export_fixes_subdir)
@@ -30,3 +30,55 @@ if (NOT RunCMake_GENERATOR STREQUAL "Watcom WMake")
endif()
run_tidy(C-bad)
run_tidy(compdb)
function(any_file_exists varname)
foreach(filename IN LISTS ARGN)
if(EXISTS "${filename}")
set("${varname}" 1 PARENT_SCOPE)
return()
endif()
endforeach()
set("${varname}" 0 PARENT_SCOPE)
endfunction()
function(assert_any_file_exists)
any_file_exists(exists ${ARGN})
if(NOT exists)
string(APPEND RunCMake_TEST_FAILED "Expected one of the following files to exist but they do not:\n")
foreach(filename IN LISTS ARGN)
string(APPEND RunCMake_TEST_FAILED " ${filename}\n")
endforeach()
set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
endif()
endfunction()
function(assert_no_file_exists)
any_file_exists(exists ${ARGN})
if(exists)
string(APPEND RunCMake_TEST_FAILED "Expected none of the following files to exist but one of them does:\n")
foreach(filename IN LISTS ARGN)
string(APPEND RunCMake_TEST_FAILED " ${filename}\n")
endforeach()
set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
endif()
endfunction()
function(run_tidy_export_fixes)
# Use a single build tree for tests without cleaning.
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ExportFixesDir-build)
set(RunCMake_TEST_NO_CLEAN 1)
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
run_cmake(ExportFixesDir)
set(RunCMake_TEST_OUTPUT_MERGE 1)
run_cmake_command(ExportFixesDir-Build ${CMAKE_COMMAND} --build . --config Debug)
unset(RunCMake_TEST_OUTPUT_MERGE)
run_cmake(ExportFixesDir2)
set(RunCMake_TEST_OUTPUT_MERGE 1)
run_cmake_command(ExportFixesDir2-Build ${CMAKE_COMMAND} --build . --config Debug)
unset(RunCMake_TEST_OUTPUT_MERGE)
endfunction()
run_tidy_export_fixes()
@@ -0,0 +1 @@
add_executable(subdir ${files})
+3
View File
@@ -0,0 +1,3 @@
void extra(void)
{
}
@@ -0,0 +1,3 @@
if(EXISTS "${RunCMake_BINARY_DIR}/tidy-fixes.yaml")
string(APPEND RunCMake_TEST_FAILED "Expected ${RunCMake_BINARY_DIR}/tidy-fixes.yaml not to exist but it does")
endif()
@@ -0,0 +1 @@
file(TOUCH "${RunCMake_BINARY_DIR}/tidy-fixes.yaml")
@@ -47,6 +47,7 @@ run_cmake_command(E___run_co_compile-no-iwyu ${CMAKE_COMMAND} -E __run_co_compil
run_cmake_command(E___run_co_compile-bad-iwyu ${CMAKE_COMMAND} -E __run_co_compile --iwyu=iwyu-does-not-exist -- command-does-not-exist)
run_cmake_command(E___run_co_compile-no--- ${CMAKE_COMMAND} -E __run_co_compile --iwyu=iwyu-does-not-exist command-does-not-exist)
run_cmake_command(E___run_co_compile-no-cc ${CMAKE_COMMAND} -E __run_co_compile --iwyu=iwyu-does-not-exist --)
run_cmake_command(E___run_co_compile-tidy-remove-fixes ${CMAKE_COMMAND} -E __run_co_compile "--tidy=${CMAKE_COMMAND}\\;-E\\;true\\;--export-fixes=${RunCMake_BINARY_DIR}/tidy-fixes.yaml" -- ${CMAKE_COMMAND} -E true)
run_cmake_command(G_no-arg ${CMAKE_COMMAND} -B DummyBuildDir -G)
run_cmake_command(G_bad-arg ${CMAKE_COMMAND} -B DummyBuildDir -G NoSuchGenerator)
+13
View File
@@ -1,8 +1,13 @@
#ifndef _CRT_SECURE_NO_WARNINGS
# define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{
FILE* f;
int i;
for (i = 1; i < argc; ++i) {
if (strcmp(argv[i], "-p") == 0) {
@@ -20,6 +25,14 @@ int main(int argc, char* argv[])
fprintf(stderr, "stderr from bad command line arg '-bad'\n");
return 1;
}
if (strncmp(argv[i], "--export-fixes=", 15) == 0) {
f = fopen(argv[i] + 15, "w");
if (!f) {
fprintf(stderr, "Error opening %s for writing\n", argv[i] + 15);
return 1;
}
fclose(f);
}
if (argv[i][0] != '-') {
fprintf(stdout, "%s:0:0: warning: message [checker]\n", argv[i]);
break;