clang-blueprint
[TOC]
Build Status | |
---|---|
Travis |
Example C++11 CMake project that incorporates awesome Clang tooling, such as sanitizers, a code formatter, and code coverage reporting.
This repository is designed to be used as an example of how to set up a C++ project to use Clang tooling as well as be a template that can be copied and modified. Care has been taken to follow established C++ conventions whenever possible.
For more information about Clang, see the awesome-clang repository.
For C++ coding guidelines, see the C++ Core Guidelines.
Requirements
Ubuntu 18.04 LTS
Install required packages.
On Ubuntu 16.04 LTS, omit the
clang-tools
package, which is included in theclang
package on Ubuntu 16.04 LTS.
$ sudo apt install gcc g++ clang clang-tidy clang-tools clang-format cmake cppcheck doxygen graphviz
macOS
Install Homebrew
Install required packages
$ brew install llvm clang-format cmake cppcheck doxygen graphviz
The llvm
formula is not installed into the user's PATH
by default because it shadows
tools such as clang
that Apple provide. In order to use clang-tidy
and LLVM code
coverage tools, we need those in the PATH
when cmake
runs.
$ echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.bash_profile
CentOS 7
First install the EPEL repository.
$ sudo yum install epel-release
Next install the SCL repository.
$ sudo yum install centos-release-scl
Install required packages
$ sudo yum install gcc gcc-c++ llvm-toolset-7 llvm-toolset-7-clang-tools-extra cmake3 cppcheck doxygen graphviz
Build
Append -DCMAKE_BUILD_TYPE=Release
or -DCMAKE_BUILD_TYPE=Debug
to the cmake
command
arguments to specify release or debug builds.
GCC
$ cd build
$ cmake ..
$ make
Clang
Note: On CentOS 7, replace the cmake
command with
scl enable llvm-toolset-7 'cmake3 -DCMAKE_CXX_COMPILER=clang++ ..'
.
$ cd build
$ cmake -DCMAKE_CXX_COMPILER=clang++ ..
$ make
Treat warnings as errors
Use -DWERROR=On
option to treat compile warnings as errors.
$ cd build
$ cmake -DWERROR=On ..
$ make
/home/user/GitHub/clang-blueprint/src/danger/bad_examples.cpp:13:18: error: array index
3 is past the end of the array (which contains 2 elements)
[-Werror,-Warray-bounds]
std::cout << a[3];
^ ~
...
Run
First, perform a build as described in the Build section, then run the following
commands in the build
directory.
Application
$ ./clang-blueprint
Unit tests
Unit tests are written using the Catch2 unit testing framework.
$ ./unit_test
Build Docs
Documentation is built using Doxygen. To configure how the docs are
built, modify docs/Doxyfile
.
$ cd docs
$ doxygen
$ firefox html/index.html
Clang Tools
Note: On CentOS 7 for all of the following Clang tool instructions, replace the cmake
command with scl enable llvm-toolset-7 'cmake3 <OPTIONS> ..'
.
Clang Static Analyzer
The Clang Static Analyzer finds bugs in C/C++ programs at compile time.
Note: Not available on CentOS 7.
$ cd build
# On Ubuntu 18.04, use the specific scan-build-6.0 command.
$ scan-build cmake ..
$ scan-build make
...
scan-build: 2 bugs found.
scan-build: Run 'scan-view /var/folders/...' to examine bug reports.
# Run the scan-view command printed in the build output to view the report.
# On Ubuntu 18.04, use the specific scan-view-6.0 command.
$ scan-view /var/folders/...
Clang-Tidy
Clang-Tidy is configured using the
.clang-tidy
configuration file. Modify this file to control which checks should
be run and configure parameters for certain checks.
For real projects, you'll likely want to modify this configuration file and disable certain checks you feel are too pedantic or don't match your project needs.
$ cd build
$ cmake ..
$ make clang-tidy
Scanning dependencies of target clang-tidy
95 warnings generated.
7477 warnings generated.
/home/user/GitHub/clang-blueprint/src/main.cpp:10:28: warning:
parameter 'argc' is unused [misc-unused-parameters]
int32_t main(const int32_t argc, const char* argv[]) {
^~~~~
/*argc*/
/home/user/GitHub/clang-blueprint/src/main.
...
AddressSanitizer
AddressSanitizer is a fast memory error detector. It consists of a compiler instrumentation module and a run-time library. The tool can detect the following types of bugs:
- Out-of-bounds accesses to heap, stack and globals
- Use-after-free
- Use-after-return
- Use-after-scope
- Double-free, invalid free
- Memory leaks
It is similar in functionality to Valgrind, but runs much faster and is able to catch a wider variety of bugs.
$ cd build
$ cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=clang++ -DADDRESS_SANITIZER=On ..
$ make
$ ./unit_test
==25797==ERROR: AddressSanitizer: heap-use-after-free on address 0x61400000024c at
pc 0x000000616ecf bp 0x7ffd7aab4b30 sp 0x7ffd7aab4b28
...
UndefinedBehaviourSanitizer
The UndefinedBehaviourSanitizer modifies the program at compile-time to catch various kinds of undefined behavior during program execution, for example:
- Using misaligned or null pointer
- Signed integer overflow
- Conversion to, from, or between floating-point types which would overflow the destination
$ cd build
$ cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=clang++ -DUNDEFINED_SANITIZER=On ..
$ make
$ ./unit_test
/home/user/GitHub/clang-blueprint/test/danger/test_bad_examples.cpp:17:7:
runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'
...
Clang Code Coverage
Clang source-based code coverage provides metrics on which lines are covered by tests.
$ cd build
$ cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=clang++ -DCLANG_CODE_COVERAGE=On ..
$ make
$ ./unit_test
# On Ubuntu 18.04, use the specific llvm-profdata-6.0 command.
$ llvm-profdata merge -sparse default.profraw -o default.profdata
# On Ubuntu 18.04, use the specific llvm-cov-6.0 command.
$ llvm-cov show -format=html -o coverage ./unit_test -instr-profile=default.profdata
# View the coverage report.
$ firefox coverage/index.html
Clang-Format
Clang-Format is a tool that can automically
format your source code accordiing to a specific style guide, saving developers time. It is
configured using the .clang-format
configuration file. Modify this file to
control how source files should be formatted.
To demonstrate clang-format
in action, first modify a line from src/main.cpp
return EXIT_SUCCESS;
To
return EXIT_SUCCESS;
Next, run clang-format
on the project.
$ cd build
$ cmake ..
$ make clang-format
src/main.cpp
will be reformatted properly to
return EXIT_SUCCESS;
Cppcheck
Cppcheck is a static analysis tool for C/C++ code. To run on the project
$ cd build
$ cmake ..
$ make cppcheck
[/home/user/GitHub/clang-blueprint/src/main.cpp:14]: (error) Array 'a[2]' accessed at index 3,
which is out of bounds.
...