8

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?

2
  • Surely you're writing tests for your library, and these tests are source files? Run clang-tidy on those! Commented Dec 20, 2020 at 22:17
  • I have tried that, and it does work on those .cpp files, but none of the headers get picked up. I tried multiple different values for "--header-filter" and nothing seemed to work. (They are all in an "include/" folder.) The other issue is that all of the test files use Catch2 and have lots of macros that set off all kinds of clang-tidy warnings. Ideally I'd like to ignore anything Catch2 related as well. (Or just ignore the test files while still processing the headers) Commented Dec 20, 2020 at 22:32

2 Answers 2

6
+50

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
❯

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

Sign up to request clarification or add additional context in comments.

7 Comments

Hmm I assumed using a namespace in a header would definitely be picked up as an issue haha, I will take a look at your example and play around with it on Windows to see if it works for me.
Oddly if I compile this within the Visual Studio IDE it does show warnings with clang-tidy output, but if I compile it from the command line I get nothing.
Anyway, this is the real project I am trying to get this to work on: github.com/tnt-coders/cpp-dsp/tree/clang-tidy I am using Visual Studio 2019 Preview as an IDE to compile it and it generates warnings for all of the test ".cpp" files only but none of the headers no matter what I put for the "-header-filter". Ultimately I want it to ignore any "Catch2" related warnings and show everything else but I can't seem to find a good way to even get it to recognize my headers let alone ignore specific warnings for specific files.
Actually, switching "-header-filter" to just "include" seemed to pick up everything! ...There's still the issue of all of the Catch2 macros causing a large number of warnings that I would like to suppress though since it is not my own code.
I am awarding the bounty to you because this answer has helped me the most, although I am still running into some problems. At this point it may be time to just reach out to the LLVM dev email list.
|
0

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/" {} \;

2 Comments

This doesn't seem to work for me. I think it is because I am building on Windows. I tried running clang-tidy with those options and explicitly stating the files to run it on (since the find command doesn't work the same on Windows) and I get an error "Error while trying to load a compilation database"... Looking at the CMake documentation I can export a compilation database json file using -DCMAKE_EXPORT_COMPILE_COMMANDS but that doesn't seem to work with the Visual Studio generator for CMake.
@tjwrona1992, I have never tried to run clang on Windows. However, I am sure there is a Visual Studio extension generating the compilation database(in the end it is just a JSON file with compilation flags for each compilation unit). Regarding the bash script, AFAIK new versions of Windows support bash and other Linux tools.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.