17 Oct 2015

Tags: development,c++,cmake

Related posts:
FFXIV Astrologian guide
How to upload screenshots to S3 from linux

Add cppcheck and clang-format for a cmake project

A small How-To which describes how to add automatic code style checking and static analyser to a project on C++ which uses cmake as a build system.

Project

The project has the following structure:

sources/
|- CMakeLists.txt
|- 3rdparty/
|- first_component/
|- second_component/

3rdparty is a directory which contains additional libraries and which should be excluded from checking (PROJECT_TRDPARTY_DIR cmake variable is used to indicate path to this directory). Also let’s assume that we have additional files (e.g. *.qml) in addition to common source files (*.cpp, *.h).

In addition the described below commands may be inserted to pre-commit hook; it allows us to troll colleagues which will be able to commit nothing till they read CONTRIBUTING.md.

cppcheck

As far as there are no good (out-of-box) static analysers in open source we will use it. Knowledgeable people say that cppcheck in case of good configuration it is better than the any alternative, but its configuration is the same that the new project creation. cppcheck shows obvious errors and recommend to fix them.

Example of run

Here it is:

cppcheck --enable=warning,performance,portability,information,missingInclude \
         --std=c++11 --library=qt.cfg --verbose --quiet \
         --template="[{severity}][{id}] {message} {callstack} (On {file}:{line})" \
         path/to/source/files/or/directory

cmake integration

cppcheck.cmake file in the project root:

# additional target to perform cppcheck run, requires cppcheck

# get all project files
# HACK this workaround is required to avoid qml files checking ^_^
file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h)
foreach (SOURCE_FILE ${ALL_SOURCE_FILES})
    string(FIND ${SOURCE_FILE} ${PROJECT_TRDPARTY_DIR} PROJECT_TRDPARTY_DIR_FOUND)
    if (NOT ${PROJECT_TRDPARTY_DIR_FOUND} EQUAL -1)
        list(REMOVE_ITEM ALL_SOURCE_FILES ${SOURCE_FILE})
    endif ()
endforeach ()

add_custom_target(
        cppcheck
        COMMAND /usr/bin/cppcheck
        --enable=warning,performance,portability,information,missingInclude
        --std=c++11
        --library=qt.cfg
        --template="[{severity}][{id}] {message} {callstack} \(On {file}:{line}\)"
        --verbose
        --quiet
        ${ALL_SOURCE_FILES}
)

cppcheck may work with directories recursive, but I need to skip qml-files checking in my example, because this cppcheck will segfault on some of them. To do it source files search is used followed by the ejection of unnecessary files.

Include to the project (CMakeLists.txt)…

include(cppcheck.cmake)

…and run:

cmake
make cppcheck

Then edit files to avoid warnings in the future.

Adds

clang-format

clang-format is used to automatic code style checking and correction. astyle, which has a very modest capabilities, and uncrustify, which on the contrary has too many options, should be mentioned from analogues.

Example of run

clang-format -i -style=LLVM /path/to/source/files

(Unfortunately it could not work with directories recursive.)

cmake integration

clang-format.cmake file in the project root:

# additional target to perform clang-format run, requires clang-format

# get all project files
file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h)
foreach (SOURCE_FILE ${ALL_SOURCE_FILES})
    string(FIND ${SOURCE_FILE} ${PROJECT_TRDPARTY_DIR} PROJECT_TRDPARTY_DIR_FOUND)
    if (NOT ${PROJECT_TRDPARTY_DIR_FOUND} EQUAL -1)
        list(REMOVE_ITEM ALL_SOURCE_FILES ${SOURCE_FILE})
    endif ()
endforeach ()

add_custom_target(
        clangformat
        COMMAND /usr/bin/clang-format
        -style=LLVM
        -i
        ${ALL_SOURCE_FILES}
)

There is the same method to get source files list as for cppcheck, because clang-format doesn’t support recursive directory search.

Include to the project (CMakeLists.txt)…

include(clang-format.cmake)

…and run:

cmake
make clangformat

No other actions required.

Adds