【问题标题】:Using clang-tidy with a header only CMake project将 clang-tidy 与仅标头的 CMake 项目一起使用
【发布时间】:2020-12-18 02:01:52
【问题描述】:

我正在开发一个只有标头的库,并希望使用 clang-tidy 来确保我遵循“C++ 核心指南”https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines

无论我尝试什么,我似乎都无法在仅标头库上工作(可能是因为在使用该库之前没有真正编译过)...但是必须有一些解决方法这工作正常。当然,其他人已经编写了一个他们想在其上使用 clang-tidy 的仅标头库。

为了尝试简化问题,我制作了一个小型测试项目来尝试使其正常工作。这个项目只有两个文件。一个 CMakeLists.txt 文件和一个头文件。

CMakeLists.txt:

cmake_minimum_required(VERSION 3.11.4)

project(my_project LANGUAGES CXX)

# This does not seem to work at all for header only libraries
# I even tried messing with the "-header-filter" parameter and had no luck
set(CMAKE_CXX_CLANG_TIDY clang-tidy;-checks=-*,cppcoreguidelines-*)

add_library(my_project INTERFACE)

target_include_directories(my_project
  INTERFACE
    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:include>
)

包括/my_project.hpp:

#include <iostream>

// I know it is bad to do this in a header file.
// This is intentional to give clang-tidy something to catch
using namespace std;

template <int N>
void print()
{
    for (int i = 0; i < N; ++i)
    {
        cout << "Hello, world!" << endl;
    }
}

当我运行 CMake 时:

mkdir build
cd build
cmake ..
cmake --build .

我没有从 clang-tidy 得到任何输出。我怎样才能使 clang-tidy 仅解析标头库并报告潜在问题?

【问题讨论】:

  • 您肯定正在为您的库编写测试,而这些测试是源文件吗?在这些上运行 clang-tidy!
  • 我已经尝试过了,它确实适用于那些 .cpp 文件,但没有一个标题被拾取。我为“--header-filter”尝试了多个不同的值,但似乎没有任何效果。 (它们都在“include/”文件夹中。)另一个问题是所有的测试文件都使用了 Catch2 并且有很多宏会引发各种整洁的警告。理想情况下,我也想忽略任何与 Catch2 相关的内容。 (或者只是在处理标头时忽略测试文件)

标签: c++ cmake llvm clang-tidy


【解决方案1】:

默认情况下,clang-tidy will not 检查您的头文件。因此,需要使用-header-filter=.* 来指定头文件的根路径。

不详细的clang-tidy 输出并不意味着它没有执行。该配置缺少-header-filter=.*,但即使使用该标志,当您执行cmake --build . 时,它也不会输出任何内容。但是,如果您使用 grep(例如)在构建路径中查找该命令,您应该会得到如下内容:

❯ grep -nrw '.' -e "clang-tidy"
./CMakeFiles/my_project.dir/build.make:63:  $(CMAKE_COMMAND) -E __run_co_compile --tidy="clang-tidy;-checks=-*,cppcoreguidelines-*;-header-filter=.*" --source=/home/markoshorro/tmp/tidy/my_project.cpp -- /usr/bin/c++  $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/my_project.dir/my_project.cpp.o -c /home/markoshorro/tmp/tidy/my_project.cpp

这意味着考虑了clang-tidy 命令。实际上,以您的示例为例:

❯ clang-tidy my_project.hpp
❯

也就是说,我什么也得不到。看看this example(尽管你的例子对我来说似乎很好);只是clang-tidy 没有什么可报告的。

【讨论】:

  • 嗯,我认为在标题中使用命名空间肯定会被认为是一个问题哈哈,我会看看你的例子并在 Windows 上使用它,看看它是否适合我。
  • 奇怪的是,如果我在 Visual Studio IDE 中编译它,它会显示带有 clang-tidy 输出的警告,但如果我从命令行编译它,我什么也得不到。
  • 无论如何,这是我试图让它工作的真正项目:github.com/tnt-coders/cpp-dsp/tree/clang-tidy 我正在使用 Visual Studio 2019 Preview 作为 IDE 来编译它,它会为所有测试生成警告仅“.cpp”文件,但没有任何标题,无论我为“-header-filter”放置什么。最终,我希望它忽略任何与“Catch2”相关的警告并显示其他所有内容,但我似乎找不到一个好方法来让它识别我的标题,更不用说忽略特定文件的特定警告了。
  • 实际上,将“-header-filter”切换为“include”似乎可以解决所有问题! ...仍然存在所有 Catch2 宏的问题,它会导致大量警告,但我想禁止这些警告,因为它不是我自己的代码。
  • 我将赏金奖励给你,因为这个答案对我帮助最大,尽管我仍然遇到一些问题。此时可能是时候联系 LLVM 开发电子邮件列表了。
【解决方案2】:

以下命令对我有用:

find . -type f \( -name "*.hpp" -o -name "*.cpp" \) \
   -exec clang-tidy -p . \
   --header-filter="/home/user/clang-tidy-include-headers/header.hpp" {} \;

它会查找头文件和 CPP 文件,并将它们传递给 clang-tidy。 参数--header-filter= 接受头文件路径的正则表达式。

你的情况是:

find . -type f \( -name "*.hpp" -o -name "*.cpp" \) \
   -exec clang-tidy -p . \
   --header-filter="include/" {} \;

【讨论】:

  • 这似乎对我不起作用。我认为这是因为我在 Windows 上构建。我尝试使用这些选项运行 clang-tidy 并明确说明要在其上运行它的文件(因为 find 命令在 Windows 上的工作方式不同)并且我收到错误“尝试加载编译数据库时出错”...查看 CMake 文档,我可以使用 -DCMAKE_EXPORT_COMPILE_COMMANDS 导出编译数据库 json 文件,但这似乎不适用于 CMake 的 Visual Studio 生成器。
  • @tjwrona1992,我从未尝试在 Windows 上运行 clang。但是,我确信有一个 Visual Studio 扩展生成编译数据库(最后它只是一个 JSON 文件,每个编译单元都有编译标志)。关于 bash 脚本,AFAIK 新版本的 Windows 支持 bash 和其他 Linux 工具。
猜你喜欢
  • 2020-07-26
  • 1970-01-01
  • 2018-10-25
  • 2022-07-12
  • 1970-01-01
  • 2018-03-30
  • 2015-11-23
  • 2019-11-26
  • 2021-06-19
相关资源
最近更新 更多