Overview
I am trying to run clang-tidy against my c++ codebase, which is built using cmake.
I am generating a compilation database as part of the build and passing this via the -p
flag to clang-tidy
- however, clang-tidy
complains with error: 'static_1.h' file not found [clang-diagnostic-error]
. This causes clang-tidy
to exit with status 2, which fails my build.
I would like clang-tidy
to be able to find all header files that are used as part of the build - ideally without using any additional tools other than CMake, or changing any INTERFACE
targets to STATIC
or SHARED
.
Details
I have the following directory structure:
.
├── ignored
│ ├── include
│ │ └── ignored.h
│ ├── CMakeLists.txt
│ └── ignored.cpp
├── interface_1
│ ├── include
│ │ └── interface_1.h
│ └── CMakeLists.txt
├── static_1
│ ├── include
│ │ └── static_1.h
│ ├── CMakeLists.txt
│ └── static_1.cpp
├── CMakeLists.txt
└── main.cpp
And my CMake configuration looks like this:
When I build the project using the following commands:
$ mkdir build
$ cmake -DCMAKE_BUILD_TYPE=Debug -G "Unix Makefiles" -S . -B build
$ cd build
$ cmake --build . -- -j
The project compiles successfully, and there is the following compile_commands.json
file inside build
:
[
{
"directory": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/build",
"command": "/usr/bin/c++ -I/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/interface_1/include -I/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/static_1/include -g -o CMakeFiles/example.dir/main.cpp.o -c /tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/main.cpp",
"file": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/main.cpp"
},
{
"directory": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/build/ignored",
"command": "/usr/bin/c++ -I/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/ignored/include -g -o CMakeFiles/ignored.dir/ignored.cpp.o -c /tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/ignored/ignored.cpp",
"file": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/ignored/ignored.cpp"
},
{
"directory": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/build/static_1",
"command": "/usr/bin/c++ -I/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/static_1/include -g -o CMakeFiles/static_1.dir/static_1.cpp.o -c /tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/static_1/static_1.cpp",
"file": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/static_1/static_1.cpp"
}
]
However, when I run clang-tidy
:
$ clang-tidy -p build main.cpp static_1/include/static_1.h static_1/static_1.cpp interface_1/include/interface_1.h
I get the following error:
/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/interface_1/include/interface_1.h:4:10: error: 'static_1.h' file not found [clang-diagnostic-error]
#include <static_1.h>
^~~~~~~~~~~~
Minimal example
Root directory
# CMakeLists.txt
cmake_minimum_required(VERSION 3.25.1)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(example)
add_subdirectory(ignored)
add_subdirectory(interface_1)
add_subdirectory(static_1)
add_executable(example main.cpp)
target_link_libraries(example PRIVATE interface_1)
// main.cpp
#include <interface_1.h>
int main() {
return 0;
}
static_1
# static_1/CMakeLists.txt
add_library(static_1 STATIC static_1.cpp)
target_include_directories(static_1 PUBLIC include)
// static_1/static_1.cpp
#include <static_1.h>
// static_1/include/static_1.h
#ifndef STATIC_1_H
#define STATIC_1_H
#endif // STATIC_1_H
interface_1
# interface_1/CMakeLists.txt
add_library(interface_1 INTERFACE)
target_include_directories(interface_1 INTERFACE include)
target_link_libraries(interface_1 INTERFACE static_1)
// interface_1/include/interface_1.h
#ifndef INTERFACE_1_H
#define INTERFACE_1_H
#include <static_1.h>
#endif // INTERFACE_1_H
ignored
# ignored/CMakeLists.txt
add_library(ignored STATIC ignored.cpp)
target_include_directories(ignored PUBLIC include)
// ignored/ignored.cpp
#include <ignored.h>
// ignored/include/ignored.h
#ifndef IGNORED_H
#define IGNORED_H
#endif // IGNORED_H
What did I find / try?
I have found a few links that are along similar lines, but not exactly the same as my question:
- These answers suggest:
- using plain compiler includes, which does work - but I don't want to have to manually configure
clang-tidy
for this, I want it to derive the files automatically - using a compilation database, which I am already doing
- disabling response files, which I tried but there was no change in output
- using plain compiler includes, which does work - but I don't want to have to manually configure
- These answers suggest:
- using
--header-filter
- I tried--header-filter="*.h"
with no effect
- using
I also found these issues / MRs. They seem slightly related but I'm not sure they are the cause of the issue:
- Headers files inside compile_commands.json
- Add target to verify that all headers in header sets can be compiled independently
I have also found the tool compdb, which seems designed for this purpose. However, if possible, I would like to find a solution that only uses CMake, as I'm relying on the dependencies for my project being already packaged in Debian.
The confusing case of the ignored
target
For extra information - I noticed the following, which unfortunately confused me even more.
Remove ignored
target
There is the ignored
folder above - when I delete this folder, the error disappears. Additionally, the compilation database becomes:
[
{
"directory": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/build",
"command": "/usr/bin/c++ -I/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/interface_1/include -I/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/static_1/include -g -o CMakeFiles/example.dir/main.cpp.o -c /tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/main.cpp",
"file": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/main.cpp"
},
{
"directory": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/build/static_1",
"command": "/usr/bin/c++ -I/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/static_1/include -g -o CMakeFiles/static_1.dir/static_1.cpp.o -c /tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/static_1/static_1.cpp",
"file": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/static_1/static_1.cpp"
}
]
Rename ignored
target
Additionally, if I rename ignored
to not_used
throughout the codebase, the error also disappears.
[
{
"directory": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/build",
"command": "/usr/bin/c++ -I/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/interface_1/include -I/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/static_1/include -g -o CMakeFiles/example.dir/main.cpp.o -c /tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/main.cpp",
"file": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/main.cpp"
},
{
"directory": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/build/not_used",
"command": "/usr/bin/c++ -I/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/not_used/include -g -o CMakeFiles/not_used.dir/not_used.cpp.o -c /tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/not_used/not_used.cpp",
"file": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/not_used/not_used.cpp"
},
{
"directory": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/build/static_1",
"command": "/usr/bin/c++ -I/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/static_1/include -g -o CMakeFiles/static_1.dir/static_1.cpp.o -c /tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/static_1/static_1.cpp",
"file": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/static_1/static_1.cpp"
}
]
Make ignored
an INTERFACE
target
Finally, if I remove ignored.cpp
and turn ignored
into an INTERFACE
target, the error also disappears.
[
{
"directory": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/build",
"command": "/usr/bin/c++ -I/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/interface_1/include -I/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/static_1/include -g -o CMakeFiles/example.dir/main.cpp.o -c /tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/main.cpp",
"file": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/main.cpp"
},
{
"directory": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/build/static_1",
"command": "/usr/bin/c++ -I/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/static_1/include -g -o CMakeFiles/static_1.dir/static_1.cpp.o -c /tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/static_1/static_1.cpp",
"file": "/tmp/tmp.XkimKdDJyo/clang-tidy-so-issue/static_1/static_1.cpp"
}
]
I presume these are all the results of interactions with the compilation database. However, I'm confused how this interaction would remove the error.
Versions
I am using the following versions:
Debian GNU/Linux 12 (bookworm)
cmake version 3.25.1
g++ (Debian 12.2.0-14) 12.2.0
Debian LLVM version 14.0.6 # (clang-tidy)