Autoformatting
Some IDEs recognize the .clang-format file located in the root directory of the project and autoformat the code upon saving, according to the style and rules specified in the file. However, the clang-format tool is also integrated in the CMake script of this project, in the module cmake/clang-format.cmake, so it is possible to autoformat the entire source code by calling the format target, such as:
cmake --build . --target format
# or, if using make:
make format
The current script is set to format all the source files with the following extensions: .h, .hpp, .c, .cpp.
Static analysis
With Clang Static Analyzer:
scan-build cmake .. -G "Ninja"
scan-build ninja
With clang-tidy:
# Using a CMake preset:
cmake .. --preset tidy
# Uses a CMake variable and the .clang-tidy file:
cmake .. -DCMAKE_CXX_CLANG_TIDY="clang-tidy"
# Appends globs to the 'Checks' option in the .clang-tidy file:
cmake .. -DCMAKE_CXX_CLANG_TIDY="clang-tidy;-checks=cppcore*,-cppcoreguidelines-owning-memory"
cmake --build .
With cppcheck:
# Using a CMake preset:
cmake .. --preset cppcheck
# Using a CMake variable:
cmake .. -DCMAKE_CXX_CPPCHECK="cppcheck;--enable=all;--force;--inline-suppr;--suppressions-list=../CppCheckSuppressions.txt;--library=wxwidgets"
cmake --build .
Testing
Using a multi-config generator:
cd build
cmake .. -G "Ninja Multi-Config"
cmake --build . --config Debug
ctest -C Debug #-j10
ctest -C Debug -T memcheck
Coverage
GCC / Clang
cd build
cmake .. -G "Ninja" -DCMAKE_BUILD_TYPE=Coverage
cmake --build .
ctest
ctest -T coverage
# or,
# ctest -T Test -T Coverage
Coverage info can be found in cpp-project-template/build/Testing/.
You can also use your IDE's viewer. For VSCode I found the Gcov Viewer extension to be quite good. After running CTest, press Ctrl+Shift+P and type "GCov Viewer: Load" to load the report. Then press Ctrl+Shift+P and type "GCov Viewer: Show" to show the result.
Generate lcov HTML report:
cmake --build .
cmake --build . --target lcov_html
Report can be found in cpp-project-template/build/lcov/.
Generate gcovr HTML report:
After running CTest, do:
cmake --build .
cmake --build . --target gcovr_html
Report can be found in cpp-project-template/build/gcovr/.
MSVC
cd build
cmake .. -DCMAKE_BUILD_TYPE:STRING=Coverage -DCMAKE_TOOLCHAIN_FILE=<project_root>/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows -DVCPKG_HOST_TRIPLET=x64-windows
cmake --build . --config Debug
ctest -C Debug
cmake --build . --target projectlib_gtest_coverage
Dynamic analysis
Valgrind
ctest -T memcheck
# or
cmake --build . --target test_memcheck
# or, if using make
make test_memcheck
Sanitizers
If using Clang, customize SanitizerBlacklist.txt at your will.
# Using gcc:
cmake .. -DCMAKE_CXX_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer"
# Using clang:
cmake .. -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer -fsanitize-blacklist=/full/path/to/SanitizerBlacklist.txt"
# Executing wxWidgets project with lsan suppressions:
ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=suppressions=../src/projectwx/wx_lsan_suppressions.txt ./bin/projectwx
More about sanitizers:
CDash
CDash Dashboard: https://my.cdash.org/index.php?project=cpp-project-template
cmake -S . -B build -G "Ninja" -DCMAKE_BUILD_TYPE=Coverage
cmake --build build
ctest --test-dir build -D Experimental -T Test -T Coverage -T memcheck
CMake tips
- Check the available targets with:
cmake --build . --target help
- List available presets with:
Doxygen tips
- Files are considered private by default. Having a file command will have documentation be generated for it. See: https://linux.m2osw.com/doxygen-does-not-generate-documentation-my-c-functions-or-any-global-function
- Documenting the namespace is necessary for references to work. See: https://stackoverflow.com/q/46845369/3049315
- The main page of doxygen is set with the \mainpage command. See: https://www.doxygen.nl/manual/commands.html#cmdmainpage
But it is possible to set an MD file as the main page. See: https://stackoverflow.com/a/26244558/3049315
Adding libraries
Adding libraries to the project requires modifying the vcpkg.json file if you use one, the CI/CD workflow files, the docs/install.md file, the CMakeLists.txt file of the project that you are adding the library to, and the .devcontainer/Dockerfile.
Windows XP
For MSVC see here. For MinGW see here. For Clang see here.
Naturally, the Windows API has evolved since Windows XP and modern features will not work with this OS.
GitHub Actions tips
- GitHub Actions uses the latest runners available and for this reason may need maintenance.
- CI/CD scripts should be made executable, like so:
git update-index --chmod=+x ./.github/scripts/*.cmake
- virustotal.com shows that more security vendors flag the program as malicious when compiled with LLVM, few security vendors flag the program as malicious when compiled with MinGW, and no security vendors flag the program as malicious when compiled with MSVC. Using the latest version of some compilers (e.g. LLVM) can make Windows Defender flag the program as malicious and remove it from the user's file system.
Releases
A release is created when creating and pushing a tag that starts with v. For example:
git add .
git commit -m "Ready for release."
# Create an annotated tag:
git tag -a v0.0.1 -m "release v0.0.1"
# Push to branch main and to tag simultaneously:
git push --atomic origin main v0.0.1
Deleting a tag in case of mistake:
# Delete locally:
git tag -d v0.0.1
# Delete remotely:
git push --delete origin v0.0.1
The release can be deleted manually or with GitHub CLI.
GitLab tips
Change the path of the CI/CD configuration file in your GitLab project's Settings -> CI/CD to .gitlab/.gitlab-ci.yml.
Custom Docker images
Tutorial: https://cylab.be/blog/8/using-custom-docker-images-with-gitlab
With the GitLab Container Registry, every project can have its own space to store its Docker images. More Information
This project's container registry: https://gitlab.com/MangaD/cpp-project-template/container_registry
You can manually add an image to your registry with the following commands:
sudo systemctl start docker
# If you are not already logged in, you need to authenticate to the
# Container Registry by using your GitLab username and password.
# If you have Two-Factor Authentication enabled, use a Personal Access
# Token instead of a password.
sudo docker login registry.gitlab.com
# Run the following commands in the directory where the Dockerfile is
# located. Replace the registry url with your own.
sudo docker build -t registry.gitlab.com/mangad/cpp-project-template .
# Replace the registry url with your own.
sudo docker push registry.gitlab.com/mangad/cpp-project-template
Tutorial links
C++
CMake
Testing
Coverage
Profiling
Debuging
Documentation
- For Sphinx instructions, see:
Versioning
Licenses
Signing
GitHub
GitLab
Docker