C++#

This is a “sub-pipeline” for building, testing and linting new changes that have been made to C++ files of a specific GitLab project.

Build & Test

A document which covers all CI jobs responsible for building and testing C++ code.

Linters

A document which covers all CI jobs responsible for linting C++ code.

Limitations#

Unlike other “sub-pipeline” like CMake, Python or Shell ones, current implementation of C++ “sub-pipeline” is hard to use as a template because it has a few significant limitations.

Core packages#

Everything here is built using CMake build system and Conan package manager.

It’s still possible to integrate other build systems (like Bazel, b2, Meson and Premake) and package managers (like CPM and vcpkg)! However as of now I have no plans to do that because I use nothing from that and that will require a significant amount of work.

CMake modules#

Most jobs heavily relay on CMOPTS and CppDoc CMake modules.

Those modules do all the heavy lifting like a seamless integration of sanitizes, linters and other useful tools, hence are essential for this “sub-pipeline”.

Pre-build Docker images#

Due to the fact that all “sub-pipeline”s (this one is not an exception) try to utilizes pre-build docker images as much as possible, this will be the rock on which we split in most of the cases.

There is no easy way to add new conan packages to mentioned docker images so you need either to use GitLab caching mechanism to some degree or fork the project to handle that.

Project structure#

Most jobs, from the current implementation of the C++ “sub-pipeline”, heavily relay on a certain C++ project structure that is shown below.

green - is an optional file or directory.
red - is a mandatory file or directory.

my-app/
├── 3rd-party/ <- code here is ignored by linters.
│   ├── 3rd-party-cpp-project-1/
│   │   └── ...
│   ├── 3rd-party-cpp-project-2/
│   │   └── ...
│   └── CMakeLists.txt
├── docs/ <- docs job looks for changes here.
│   ├── .gitignore
│   ├── CMakeLists.txt
│   └── index.rst
├── project/ (issue) <- 'check:cpp:format' formats code only here.
│   ├── module-1/
│   │   ├── docs/ <- docs job looks for changes here.
│   │   │   ├── api.rst
│   │   │   ├── developer_notes.rst
│   │   │   └── index.rst
│   │   ├── include/ <- docs job looks for changes here.
│   │   │   └── module-1/
│   │   │       ├── module-1-api-header-1.hpp
│   │   │       └── ...
│   │   ├── mocks/
│   │   │   └── misc-project-1/
│   │   │       ├── module-1-mock-header-1.hpp
│   │   │       └── ...
│   │   ├── src/
│   │   │   └── ...
│   │   ├── tests/
│   │   │   └── ...
│   │   └── CMakeLists.txt
│   ├── module-2/
│   │   └── ...
│   ├── misc/ (issue) <- 'check:cpp:include_guards' handles this folder in a special way.
│   │   ├── misc-module-1/
│   │   │   └── ...
│   │   ├── mist-project-2/
│   │   │   └── ...
│   │   └── CMakeLists.txt
│   └── CMakeLists.txt
├── tools/ <- sanitizers look for files with suppressions only here.
│   ├── lsan.supp
│   └── valgrind.supp
├── .gitignore
├── .gitlab-ci.yml
├── CMakeLists.txt <- most jobs expect this file to be here.
├── conanfile.{py,txt} <- most jobs will use it if exists.
├── README.md
└── requirements.txt

Triggers#

Most of jobs from C++ “sub-pipeline” stages are triggered only on merge requests and only if changes have been made to C++ files. Right now such files are detected by these patterns:

  • project/**/*.cpp,

  • project/**/*.hpp,

  • project/**/*.ipp.

Usage#

In order to use this “sub-pipeline” you need to add the following code to your .gitlab-ci.yml:

include:
  - project: 'bproto/cicd'
    ref: main
    file:
      - '/.gitlab/ci/external/cpp.yml'