Using clang-tidy with CMake
Clang-tidy is a C++ static analysis tool from the LLVM project that is particularly helpful when modernizing your code base or when checking your code for compliance with established guidelines and best practices.
Typically, you need to run clang-tidy
with the same options and compiler flags you use for compilation. Doing this manually can be quite a hassle.
One way to help with this is to use a compilation database. However, I always found this to be rather complicated by itself.
Luckily, if you are using CMake, there is a simpler alternative: You can directly use clang-tidy
from CMake.
You need to do two steps:
- Find and setup the
clang-tidy
command - Tell CMake to use
clang-tidy
For the first step, you only need to use CMake’s find_program()
and set the corresponding CMake variable to the command and options you want to use:
find_program(CLANG_TIDY_EXE NAMES "clang-tidy")
set(CLANG_TIDY_COMMAND "${CLANG_TIDY_EXE}" "-checks=-*,modernize-*")
In the above, I disable all default checks (-*
) and only enable checks that advocate the use of modern C++ language constructs (modernize-*
).
For the second step, you tell CMake to use clang-tidy
by setting the CXX_CLANG_TIDY
property for your build target:
set_target_properties(target PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND}")
That’s all! Run your build as usual and clang-tidy
will report suggestions for modernization as warnings.
Here’s a fully self-contained CMakeLists.txt
file for demonstration purposes:
cmake_minimum_required(VERSION 3.6)
project(clang-tidy-example)
# generate hello world file
file(
GENERATE
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/hello.cpp
CONTENT
"#include <iostream>\n int main() { std::cout << \"Hello World\" << std::endl; exit(0); }"
)
# search for clang-tidy
find_program(CLANG_TIDY_EXE NAMES "clang-tidy" REQUIRED)
# setup clang-tidy command from executable + options
set(CLANG_TIDY_COMMAND "${CLANG_TIDY_EXE}" "-checks=-*,modernize-*")
# add target using generated source file
add_executable(hello ${CMAKE_CURRENT_BINARY_DIR}/hello.cpp)
# set CXX_CLANG_TIDY property after defining the target
set_target_properties(hello PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND}")
Run this with the usual cmake build steps:
mkdir build && cd build && cmake .. && make
And you’ll see something like this:
hello.cpp:2:6: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
int main() { std::cout << "Hello World" << std::endl; exit(0); }
~~~ ^
auto -> int
I’ll leave it up to you to decide whether the advice of clang-tidy
makes sense in this particular case. ;-)
Hope this helps.