[[TOC]]
This is a template project for a Linux C/C++ library and/or application. It includes support for the following:
- CMake build configurations
- Formatting of source code for standards compliance with
clang-format
- Built-in static analysis with
clang-tidy
- Style checking with
cpplint
in accordance with the Google C++ Style Guide - Analysis of
#include
statements byinclude-what-you-use
- Cyclomatic complexity checks per-function by
pmccabe
- Testing using CMake's
ctest
and thegoogletest
framework - Documentation generation with
doxygen
- VS Code IDE support
The CMake project configuration works best utilizing the native host environment toolchain (i.e., not cross-compiling). Instead of cross-compiling, it's recommended to use the remote-ssh capabilities of VS Code (or your IDE of choice) to build and debug on the target directly.
This description should be modified when creating a new project based on this template.
Checks are included in this project template to adhere to the following code standards and guidelines, which the developer should review and be familiar with:
- CPP Core Guidelines
- Autosar C++14 Guidelines (See "General")
- Cert C++ Coding Standard
- Google C++ Style Guide
By extension from Autosar C++14, the following standards should also be reviewed:
- MISRA C++:2008
- Joint Strike Fighter Air Vehicle C++ Coding Standards
- High Integrity C++ Coding Standard Version 4.0
The following naming conventions are used throughout this project:
- Library source code implementation files are placed in
src/
- Library header interface files are placed in
include/<library-name>/
- In
#include
directives, always specify library name (e.g.#include "library-name/header.h"
)
- In
- Application source code and headers are placed in
app-src/
(delete this folder when project is library-only) - Source code file names are all lowercase, separated by underscores (e.g.
my_file.h
ormy_impl.c
)- C++ implementation files use extension
.cpp
- C++-only header files use extension
.hpp
- C implementation files use extension
.c
- C header files, and header files intended to be shared between C++ and C,
use extension
.h
- C++ implementation files use extension
- Target names are all lowercase; whenever possible, keep names to one word
(e.g.
mylib
ormyapp
), but if separation is needed, use dashes (-
) (e.g.my-lib
ormy-app
)- Folder subdirectories for library includes should match the target name
(e.g.
include/libname/
orinclude/my-lib/
)
- Folder subdirectories for library includes should match the target name
(e.g.
The following tools should be installed on the host machine prior to building:
- CMake (version 3.12 or later is required)
ccache
clang-format
clang-tidy
cpplint
include-what-you-use
doxygen
pmccabe
- Python 3
gcov
lcov
Optionally, you may also install the ninja
build tool which can be used in
leiu of make
for slightly speedier builds.
Assuming you have Homebrew installed:
$ brew install ccache cmake cpplint doxygen graphviz include-what-you-use llvm pmccabe python
$ python3 -m pip install lcov_cobertura pre-commit
$ pre-commit install
You must then symlink the extra clang tools from the llvm
installation:
$ ln -s "$(brew --prefix llvm)/bin/clang-format" "$(brew --prefix)/bin/clang-format"
$ ln -s "$(brew --prefix llvm)/bin/clang-tidy" "$(brew --prefix)/bin/clang-tidy"
$ ln -s "$(brew --prefix llvm)/bin/clang-apply-replacements" "$(brew --prefix)/bin/clang-apply-replacements"
Note: LLVM version 13 is installed for the clang-extra tools including clang-tidy and clang-format. The default packages in Debian are too old (at version 7 as of this writing) so a newer version is installed below.
$ sudo apt update
$ sudo apt install build-essential doxygen graphviz gdb git ccache iwyu lcov ninja-build pmccabe python3-pip
$ wget https://github.com/Kitware/CMake/releases/download/v3.19.7/cmake-3.19.7.tar.gz
$ tar -xzf cmake-3.19.7.tar.gz
$ ./bootstrap -- -DCMAKE_BUILD_TYPE:STRING=Release
$ make
$ make install
$ rm -rf ./cmake-3.19.7*
$ wget https://apt.llvm.org/llvm.sh
$ chmod +x llvm.sh
$ sudo ./llvm.sh 13
$ sudo apt install clang-tidy-13 clang-format-13
$ sudo ln -sf $(which clang-tidy-13) /usr/local/bin/clang-tidy
$ sudo ln -sf $(which clang-format-13) /usr/local/bin/clang-format
$ sudo python3 -m pip install cpplint lcov_cobertura pre-commit
$ pre-commit install
Note: need to become root to run the installation commands. Also, IWYU is not immediately available on Alpine.
$ su -
# apk update
# apk add alpine-sdk gdb git ccache cmake clang-extra-tools ninja py3-pip
# pip3 install cpplint lcov_cobertura pre-commit
# exit
$ pre-commit install
The usual CMake configuration procedure can be used from the project top-level.
To use the recommended approach for configuration (that is, out-of-source builds
within an unversioned build
directory), run the following from the project
top-level:
$ mkdir build
$ cd build
$ cmake ..
ninja
may be used instead of make
by using the following cmake
command
when configuring:
$ cmake -GNinja ..
The following configuration options can be added to the cmake
command (prepend
each option with -D
):
CMAKE_BUILD_TYPE=Debug|Release|RelWithDebInfo|MinSizeRel
(defaultDebug
)CMAKE_<LANG>_CLANG_TIDY=clang-tidy
(where<LANG>
isC
orCXX
, for integrated static analysis,clang-tidy
must be inPATH
)CMAKE_<LANG>_CPPLINT=cpplint
(where<LANG>
isC
orCXX
, for integrated style checking,cpplint
must be inPATH
)CMAKE_<LANG>_INCLUDE_WHAT_YOU_USE
(where<LANG>
isC
orCXX
,include-what-you-use
must be inPATH
)CODE_COVERAGE=ON|OFF
(defaultOFF
) - compute Code Coverage using gcov and lcov. See note on Code Coverage below.CMAKE_INSTALL_PREFIX
- set to the desired installation location
To build, run the following from the build
directory:
cmake --build .
To run tests, run the following from the build
directory:
ctest
To install, run the following from the build
directory:
cmake --install .
By default, the installation prefix will be an unversioned install/
directory
at the project top-level. To customize this, set CMAKE_INSTALL_PREFIX
when
configuring.
Code coverage can be computed by passing the CODE_COVERAGE=ON
option during
CMake configuration. Code coverage may NOT be enabled simultaneously with static
analysis (namely, clang-tidy
checks), because certain compilation options
conflict between GCC and Clang. So if you want to compute code coverage, make a
separate build directory just for coverage like so:
mkdir build_coverage && cd build_coverage
cmake -DCODE_COVERAGE=ON -DCMAKE_BUILD_TYPE=Debug -GNinja ..
cmake --build . --target ctest_coverage
Coverage should only be configured using the Debug
build type. The commands
above will configure coverage, and execute the test suite to determine runtime
coverage. The HTML reports will be output to build_coverage/ctest_coverage
and
can be viewed by opening index.html
in a web browser.
The top-level file .clang-tidy
configures the rules that are checked or
skipped by clang-tidy
. A default set of rules is provided. Customize them by
reviewing the available Clang-Tidy
Checks and setting
the appropriate options in the .clang-tidy
file following the
instructions.
Included in this project are configurations for editing, building and debugging using Microsoft VS Code.
At a minimum, you should install the following VS Code Extensions in order for the configure/build/debug commands to work seemlessly:
If you've cloned the project in WSL, open the project in VS Code from the WSL terminal by running the following from the project top-level:
code .
The first time this is run, VS Code server will install in the WSL environment, which will take some time on the initial launch. Subsequent launches will be faster.
Select the "kit" to be used, which defines the compilation toolchain for your target.
Open Command (Command+Shift+P), type CMake, select CMake: Scan for Kits
and
select one
Open Command (Command+Shift+P), type CMake, select CMake: Select Variant
and
select your desired build variant (Recommended: select Debug + Static Analysis and Style Checks + IWYU
)
Note on Alpine Linux: IWYU is not available, so be sure to select one of the
variants that says No IWYU
.
Open Command (Command+Shift+P), type CMake, select CMake: Configure
Open Command (Command+Shift+P), type CMake, select CMake: Build
Click the Run button in the VS Code sidebar (or Command+Shift+D) and run the Launch configuration.
Or, open Command (Command+Shift+P), type CMake, select CMake: Debug
(make sure
you first set a breakpoint somewhere, like main()
)
Open Command (Command+Shift+P), type CMake, select CMake: Run Tests
Open Command (Command+Shift+P), type CMake, select desired command