arcanis.me/_posts/2015-10-17-cppcheck-and-clang-format.md
2016-02-02 00:55:13 +07:00

6.8 KiB

category type hastr layout tags title short
en paper true paper development, c++, cmake Add cppcheck and clang-format for a cmake project cppcheck-and-clang-format

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 --template="[{severity}][{id}] {message}
{callstack} (On {file}:{line})" --verbose --quiet
path/to/source/files/or/directory
  • --enable says which notifications should be enabled. I've disabled style (we will use clang-format to do it), unusedFunction which shows false-positive for some methods.
  • --std says which standard should be used.
  • --library=qt.cfg a configuration file, which describes how to check files. The developers recommend to read the following manual. I've used the ready template from /usr/share/cppcheck/cfg/.
  • --template is notification template.
  • ---verbose --quiet are two "conflicting" options. The first one enables more verbose messages, the second one disables progress reports.

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

  • You may add own directories to includes search, using -I dir option
  • You may drop files and/or directories from checking by using -i path/to/file/or/directory option.

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.)

  • -i enables files auto replace (otherwise the result will be printed to stdout).
  • -style is a style preset selection or from file (file), see below.

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

  • Configuration. You may see all options on the official site. Also you may use interactive tool to search for required options. To use the preset for your style use the following command:

    clang-format -style=LLVM -dump-config > .clang-format
    

    Then edit generated file .clang-format. To enable it you need set -style=file option, file should be placed to the any parent directory of each source file (e.g., to the project root). Also you may send required options to the command line directly, e.g. -style="{BasedOnStyle: llvm, IndentWidth: 8}"