mirror of
https://github.com/arcan1s/arcanis.me.git
synced 2025-07-14 05:35:47 +00:00
add paper about cppcheck and clang-format
This commit is contained in:
161
_posts/2015-10-17-cppcheck-and-clang-format.html
Normal file
161
_posts/2015-10-17-cppcheck-and-clang-format.html
Normal file
@ -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 <code>C++</code> which uses <code>cmake</code> as a build system.
|
||||
---
|
||||
<h2><a href="#project" class="anchor" id="project"><span class="octicon octicon-link"></span></a>Project</h2>
|
||||
<p>The project has the following structure:</p>
|
||||
|
||||
{% highlight bash %}
|
||||
sources/
|
||||
|- CMakeLists.txt
|
||||
|- 3rdparty/
|
||||
|- first_component/
|
||||
|- second_component/
|
||||
{% endhighlight %}
|
||||
|
||||
<p><b>3rdparty</b> is a directory which contains additional libraries and which should be excluded from checking (<code>PROJECT_TRDPARTY_DIR</code> cmake variable is used to indicate path to this directory). Also let's assume that we have additional files (e.g. <code>*.qml</code>) in addition to common source files (<code>*.cpp</code>, <code>*.h</code>).</p>
|
||||
|
||||
<p>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 <code>CONTRIBUTING.md</code>.</p>
|
||||
|
||||
<h2><a href="#cppcheck" class="anchor" id="cppcheck"><span class="octicon octicon-link"></span></a>cppcheck</h2>
|
||||
<p>As far as there are no good (out-of-box) static analysers in open source we will use it. Knowledgeable people say that <a href="//cppcheck.sourceforge.net/" title="cppcheck site">cppcheck</a> in case of good configuration it is better than the any alternative, but its configuration is the same that the new project creation. <code>cppcheck</code> shows obvious errors and recommend to fix them.</p>
|
||||
|
||||
<h3><a href="#cppcheck-run" class="anchor" id="cppcheck-run"><span class="octicon octicon-link"></span></a>Example of run</h3>
|
||||
<p>Here it is:</p>
|
||||
|
||||
{% 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 %}
|
||||
|
||||
<ul>
|
||||
<li><code>--enable</code> says which notifications should be enabled. I've disabled <code>style</code> (we will use <code>clang-format</code> to do it), <code>unusedFunction</code> which shows false-positive for some methods.</li>
|
||||
<li><code>--std</code> says which standard should be used.</li>
|
||||
<li><code>--library=qt.cfg</code> a configuration file, which describes how to check files. The developers recommend to read the following <a href="//cppcheck.sourceforge.net/manual.pdf" title="cppcheck manual">manual</a>. I've used the ready template from <code>/usr/share/cppcheck/cfg/</code>.</li>
|
||||
<li><code>--template</code> is notification template.</li>
|
||||
<li><code>---verbose --quiet</code> are two "conflicting" options. The first one enables more verbose messages, the second one disables progress reports.</li>
|
||||
</ul>
|
||||
|
||||
<h3><a href="#cppcheck-cmake" class="anchor" id="cppcheck-cmake"><span class="octicon octicon-link"></span></a>cmake integration</h3>
|
||||
<p><code>cppcheck.cmake</code> file in the project root:</p>
|
||||
|
||||
{% 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 %}
|
||||
|
||||
<p><code>cppcheck</code> may work with directories recursive, but I need to skip qml-files checking in my example, because this <code>cppcheck</code> will segfault on some of them. To do it source files search is used followed by the ejection of unnecessary files.</p>
|
||||
|
||||
<p>Include to the project (<code>CMakeLists.txt</code>)...</p>
|
||||
|
||||
{% highlight cmake %}
|
||||
include(cppcheck.cmake)
|
||||
{% endhighlight %}
|
||||
|
||||
<p>...and run:</p>
|
||||
|
||||
{% highlight bash %}
|
||||
cmake
|
||||
make cppcheck
|
||||
{% endhighlight %}
|
||||
|
||||
<p>Then edit files to avoid warnings in the future.</p>
|
||||
|
||||
<h3><a href="#cppcheck-adds" class="anchor" id="cppcheck-adds"><span class="octicon octicon-link"></span></a>Adds</h3>
|
||||
<ul>
|
||||
<li>You may add own directories to includes search, using <code>-I dir</code> option</li>
|
||||
<li>You may drop files and/or directories from checking by using <code>-i path/to/file/or/directory</code> option.</li>
|
||||
</ul>
|
||||
|
||||
<h2><a href="#clang" class="anchor" id="clang"><span class="octicon octicon-link"></span></a>clang-format</h2>
|
||||
<p><a href="//clang.llvm.org/docs/ClangFormat.html" title="clang-format site">clang-format</a> is used to automatic code style checking and correction. <a href="//astyle.sourceforge.net/" title="astyle site">astyle</a>, which has a very modest capabilities, and <a href="//uncrustify.sourceforge.net/" title="uncrustify site">uncrustify</a>, which on the contrary has too many options, should be mentioned from analogues.</p>
|
||||
|
||||
<h3><a href="#clang-run" class="anchor" id="clang-run"><span class="octicon octicon-link"></span></a>Example of run</h3>
|
||||
{% highlight bash %}
|
||||
clang-format -i -style=LLVM /path/to/source/files
|
||||
{% endhighlight %}
|
||||
|
||||
<p>(Unfortunately it <b>cound not</b> work with directories recursive.)</p>
|
||||
|
||||
<ul>
|
||||
<li><code>-i</code> enables files auto replace (otherwise the result will be printed to stdout).</li>
|
||||
<li><code>-style</code> is a style preset selection or from file (<code>file</code>), see below.</li>
|
||||
</ul>
|
||||
|
||||
<h3><a href="#clang-cmake" class="anchor" id="clang-cmake"><span class="octicon octicon-link"></span></a>cmake integration</h3>
|
||||
<p><code>clang-format.cmake</code> file in the project root:</p>
|
||||
|
||||
{% 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 %}
|
||||
|
||||
<p>There is the same method to get source files list as for <code>cppcheck</code>, because <code>clang-format</code> doesn't support recursive directory search.</p>
|
||||
|
||||
<p>Include to the project (<code>CMakeLists.txt</code>)...</p>
|
||||
|
||||
{% highlight cmake %}
|
||||
include(clang-format.cmake)
|
||||
{% endhighlight %}
|
||||
|
||||
<p>...and run:</p>
|
||||
|
||||
{% highlight bash %}
|
||||
cmake
|
||||
make clangformat
|
||||
{% endhighlight %}
|
||||
|
||||
<p>No other actions required.</p>
|
||||
|
||||
<h3><a href="#clang-adds" class="anchor" id="clang-adds"><span class="octicon octicon-link"></span></a>Adds</h3>
|
||||
<ul>
|
||||
<li>Configuration. You may see all options on the <a href="//clang.llvm.org/docs/ClangFormat.html" title="clang-format site">official site</a>. Also you may use <a href="//clangformat.com/" title="Site">interactive tool</a> to search for required options. To use the preset for your style use the following command:
|
||||
|
||||
{% highlight bash %}
|
||||
clang-format -style=LLVM -dump-config > .clang-format
|
||||
{% endhighlight %}
|
||||
|
||||
Then edit generated file <code>.clang-format</code>. To enable it you need set <code>-style=file</code> 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. <code>-style="{BasedOnStyle: llvm, IndentWidth: 8}"</code></li>
|
||||
</ul>
|
Reference in New Issue
Block a user