简体   繁体   中英

Using clang-tidy with a header only CMake project

I am working on a header only library and would like to use clang-tidy to make sure I am following the "C++ Core Guidelines" https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines

No matter what I try I can't seem to get clang-tidy to work on a header only library (probably because nothing is really compiled until the library is used)... But there has to be some workaround to make this work correctly. Surely someone else has written a header only library that they wanted to use clang-tidy on.

To try and simplify the issue I made a small test project to try and get it to work. This project is just two files. A CMakeLists.txt file and a header file.

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>
)

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;
    }
}

When I run CMake with:

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

I get no output from clang-tidy. How can I make clang-tidy parse header only libraries and report potential issues?

By default, clang-tidy will not check your header files. Thus, it is necessary to use -header-filter=.* , in order to specify the root path for header files.

Not verbose clang-tidy output does not mean it is not executing. That configuration is missing -header-filter=.* , but even with that flag, when you execute cmake --build. , it does not output anything. However, if you look for that command in the build path with grep (for instance), you should get something like:

❯ 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

Which means that the clang-tidy command is considered. Actually, with your example:

❯ clang-tidy my_project.hpp
❯

Ie, I get nothing. Take a look at this example (even though your example seems fine to me); just clang-tidy has nothing to report.

The following command worked for me:

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

It looks for header and CPP files, passes them to clang-tidy. The parameter --header-filter= accepts a regex for header file paths.

In your case it will be:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM