DEV Community

Cover image for Static analysis tooling with CMake
Batuhan Ipci
Batuhan Ipci

Posted on

Static analysis tooling with CMake

Regardless of whether I am an experienced programmer or not, it is tough to write the perfect code. Ideally, I would like to detect every potential flaw, and bug and debug them to the appropriate standard in no time! But this is a tough concept, and relying only upon your developer instincts for analyzing code is insufficient, especially if you are writing in C++.

While analyzing code yourself and self-proofing is a vital skill that every developer needs to practice, having a professional tool like clang-tidy gives me more confidence that my code adheres to C++ standards.

Setup clang-tidy ⚙️

I recently integrated clang-tidy in palpatine using CMake modules, you could browse the cmake directory of palpatine where I kept the StaticAnalyzers.cmake module.

To set this up from scratch, first install clang-tidy with brew install clang-tidy on macOS, or if you are on Linux install it with sudo apt-get install clang-tidy.

After successfully installing, I have added the most commonly used clang-tidy checks into the .clang-tidy dotfile.

Note: Notice the WarningsAsErrors: '' field in this file, it is responsible for labeling the warnings as errors. Although, currently it is not active as I haven't provided any value. But if you would like to activate it, you could replace the empty value with "*".

Power of CMake  🧰

See the directory called cmake in the root directory of palpatine.
Having cmake modules within the directory cmake is commonly used, the purpose of doing is to include() custom CMake functions to be used later in the project.

Mine looks like this -

cmake-modules-hierarchy

There are 2 files (AddGitSubmodule.cmake, StaticAnalyzers.cmake) and 2 corresponding functions palpatine uses. Our attention will be on StaticAnalyzers.cmake.

After adding the module StaticAnalyzers.cmake we need to configure it in a way that clang-tidy will always run whenever we build the project using CMake (i.e. cd build && cmake .. && make). However this might not be the "intended behavior" in every project, maybe you prefer running it at the end after you are satisfied with your implementation for reducing each CMake build time. That said, there is a neat way of setting this as an option in the file CMakeLists.txt.

Navigate to the root CMakeLists.txt file of palpatine and see in this line , I have defined a CMake option that lets me switch between weather I decide to use clang-tidy or not.

Now go back to the module StaticAnalyzers.cmake and notice the first line we are checking is if the option is turned ON or OFF (i.e. if(ENABLE_CLANG_TIDY)) If this option was set to OFF, CMake would ignore this module.

if(ENABLE_CLANG_TIDY)
    find_program(CLANG_TIDY_COMMAND NAMES clang-tidy)

    if(NOT CLANG_TIDY_COMMAND)
        message(WARNING "🔴 CMake_RUN_CLANG_TIDY is ON but clang-tidy is not found!")
        set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE)
    else()
        message(STATUS "🟢 CMake_RUN_CLANG_TIDY is ON")
        set(CLANGTIDY_EXTRA_ARGS
            "-extra-arg=-Wno-unknown-warning-option"
    )
    endif()
endif()
Enter fullscreen mode Exit fullscreen mode

The find_program() CMake command, will search for the clang-tidy that is already installed in your system. If it is unsuccessful in finding it, it will complain with big, fat, and red warning 🔴 in the terminal. Check if you indeed installed it in your system with; clang-tidy --version. If it is successful, 🟢 will indicate your CMake configured clang-tidy with no trouble.

clang-tidy in action 🚧

Run the traditional set of CMake build commands in your terminal in the root directory of palpatine.

mkdir build && cd build && cmake .. && make
Enter fullscreen mode Exit fullscreen mode

A combination of these commands is one way of creating a build folder and configuring it with CMake;

After CMake can see the command clang-tidy , finally configure it with the project.

set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND};-p=${CMAKE_BINARY_DIR};${CLANGTIDY_EXTRA_ARGS}" CACHE STRING "" FORCE)

add_custom_target(clang-tidy
    COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target ${CMAKE_PROJECT_NAME}
    COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target clang-tidy
    COMMENT "Running clang-tidy..."
    )
Enter fullscreen mode Exit fullscreen mode

Delete the existing build folder and re-run this set of commands mkdir build && cd build && cmake .. && make to test if clang-tidy produces any warnings in the terminal.

In project palpatine, the output looks like the following -

command-line-execution

There is also a vscode extension called CMake Tools from Microsoft. It provides this set of buttons that automates the CMake build progress;

status-bar-buttons

This is beneficial in a way if you want to integrate CMake and visualize the warnings in vscode before running it on CLI.

If I build palpatine using CMake Tools vscode displays the warning within the file.

example-of-editor-warning

Conclusion

C++ is developing rapidly and reviewing code is not enough to keep up with the latest standards. Using static analyzers like clang-tidy inevitably helps us to write defect-free code. You might as well learn from the warnings produced by clang-tidy.

code-style-meme

Top comments (0)