diff --git a/_posts/2015-10-17-cppcheck-and-clang-format.html b/_posts/2015-10-17-cppcheck-and-clang-format.html new file mode 100644 index 0000000..0b81ed0 --- /dev/null +++ b/_posts/2015-10-17-cppcheck-and-clang-format.html @@ -0,0 +1,161 @@ +--- +category: en +type: paper +hastr: true +layout: paper +tags: awesome-widgets, development, c++, cmake +title: Add cppcheck and clang-format for a cmake project +short: cppcheck-and-clang-format +description: 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:

+ +{% highlight bash %} +sources/ +|- CMakeLists.txt +|- 3rdparty/ +|- first_component/ +|- second_component/ +{% endhighlight %} + +

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:

+ +{% highlight bash %} +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 +{% endhighlight %} + + + +

cmake integration

+

cppcheck.cmake file in the project root:

+ +{% highlight cmake %} +# 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} +) +{% endhighlight %} + +

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

+ +{% highlight cmake %} +include(cppcheck.cmake) +{% endhighlight %} + +

...and run:

+ +{% highlight bash %} +cmake +make cppcheck +{% endhighlight %} + +

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

+{% highlight bash %} +clang-format -i -style=LLVM /path/to/source/files +{% endhighlight %} + +

(Unfortunately it cound not work with directories recursive.)

+ + + +

cmake integration

+

clang-format.cmake file in the project root:

+ +{% highlight cmake %} +# 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} +) +{% endhighlight %} + +

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

+ +{% highlight cmake %} +include(clang-format.cmake) +{% endhighlight %} + +

...and run:

+ +{% highlight bash %} +cmake +make clangformat +{% endhighlight %} + +

No other actions required.

+ +

Adds

+ diff --git a/ru/_posts/2015-10-17-cppcheck-and-clang-format.html b/ru/_posts/2015-10-17-cppcheck-and-clang-format.html new file mode 100644 index 0000000..d12c008 --- /dev/null +++ b/ru/_posts/2015-10-17-cppcheck-and-clang-format.html @@ -0,0 +1,161 @@ +--- +category: ru +type: paper +hastr: true +layout: paper +tags: awesome-widgets, development, c++, cmake +title: Добавляем cppcheck и clang-format для проекта на cmake +short: cppcheck-and-clang-format +description: Небольшое How-To посвященное прикручиванию автоматической проверки стиля, а также статического анализатора к проекту на C++, который использует в качестве системы сборки cmake. +--- +

Проект

+

Наш проект имеет следующую структуру:

+ +{% highlight bash %} +sources/ +|- CMakeLists.txt +|- 3rdparty/ +|- first_component/ +|- second_component/ +{% endhighlight %} + +

3rdparty - директория с различными дополнительными библиотеками, которую надо исключить из проверок (в дальнейшем соответствует переменной cmake PROJECT_TRDPARTY_DIR). Дополнительно допустим, что у нас, помимо обычных файлов исходного кода (*.cpp, *.h) есть еще какие-либо (например, *.qml).

+ +

Дополнительно используемые ниже команды можно вставить в pre-commit hook и невозбранно тролить коллег по ынтырпрайзу, не давая им закоммитить ничего, пока они не научатся читать CONTRIBUTING.md.

+ +

cppcheck

+

Коль скоро нормальных (из коробки) статических анализаторов не завезли в open source будем использовать то, что имеется. Знатоки говорят, что cppcheck при должной конфигурации будет лучше, чем любой аналог, но конфигурация его для достаточно большого проекта похожа больше на написание нового проекта. Суть добавления cppheck к проекту сводится к указанию очевидных недоработок в коде и тыканью в лужу них.

+ +

Общий пример запуска

+

Тут все, казалось бы, очень просто:

+ +{% highlight bash %} +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 +{% endhighlight %} + + + +

Интеграция с cmake

+

Файл cppcheck.cmake в корне проекта:

+ +{% highlight cmake %} +# 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} +) +{% endhighlight %} + +

cppcheck умеет рекурсивно директории проверять, однако, на моем примере, мне нужно было пропустить проверку qml-файлов, потому что open source проект, в лучших традициях, сегфолтился на некоторых из них - именно для этого используется поиск исходных файлов с дальнейшим выбрасыванием из них файлов, которые не должны проверяться.

+ +

Включаем в проект (CMakeLists.txt)...

+ +{% highlight cmake %} +include(cppcheck.cmake) +{% endhighlight %} + +

...и запускаем:

+ +{% highlight bash %} +cmake +make cppcheck +{% endhighlight %} + +

Дальше руками вносим необходимые исправления.

+ +

Дополнительно

+ + +

clang-format

+

clang-format предназначен для автоматического подгона стиля под желаемый или требуемый. Среди аналогов стоит выделить astyle, который имеет очень скромные возможности, и uncrustify, который, наоборот, имеет слишком много опций.

+ +

Общий пример запуска

+{% highlight bash %} +clang-format -i -style=LLVM /path/to/source/files +{% endhighlight %} + +

(К сожалению, он не умеет в рекурсивный обход директории.)

+ + + +

Интеграция с cmake

+

Файл clang-format.cmake в корне проекта:

+ +{% highlight cmake %} +# 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} +) +{% endhighlight %} + +

Аналогичных способ поиска исходных файлов, как и для cppcheck, поскольку clang-format не умеет в рекурсию.

+ +

Включаем в проект (CMakeLists.txt)...

+ +{% highlight cmake %} +include(clang-format.cmake) +{% endhighlight %} + +

...и запускаем:

+ +{% highlight bash %} +cmake +make clangformat +{% endhighlight %} + +

Никаких дополнительных действий не требуется.

+ +

Дополнительно

+