Reusable C++20 components (async executor, timers, HTTPS and WebSocket clients) packaged as a static library for consumption via CMake FetchContent.
Stack: C++20, CMake 3.20+, Ubuntu 24.04 (GCC, clang-tidy, CMake, Git)
- Docker — for the development environment
- CMake 3.20+ — only needed if building outside Docker
- System libraries: Boost (system), OpenSSL, libcurl
Pull this repository with FetchContent and link the umbrella target:
include(FetchContent)
FetchContent_Declare(
cpp-components
GIT_REPOSITORY <repo-url>
GIT_TAG <tag-or-commit>
)
FetchContent_MakeAvailable(cpp-components)
target_link_libraries(my_app PRIVATE cpp_components::cpp_components)Include headers with the cpp_components/ prefix:
#include "cpp_components/executor/executor.h"The consumer must provide Boost, OpenSSL, and libcurl (same packages as this project's Docker image).
Docker provides a consistent build environment. Scripts live in docker/:
| Script | Purpose |
|---|---|
docker_run.sh |
Start an interactive shell (builds the image on first run) |
docker_build.sh |
Rebuild the cpp-env image |
docker_clean.sh |
Stop containers and remove the cpp-env image |
Start the environment from the project root:
./docker/docker_run.shYour project directory is mounted at /project inside the container.
Clean up when done:
./docker/docker_clean.shAs an alternative to starting Docker manually, VS Code can configure the environment automatically using the Dev Containers extension. It opens the project in the same Docker image and installs the C++ and CMake extensions.
- Open the project in VS Code
- Ctrl+Shift+P → Dev Containers: Reopen in Container
The container uses docker/Dockerfile (same as docker_run.sh).
CMake is the build system. Presets are defined in CMakePresets.json:
| Preset | Output directory | Description |
|---|---|---|
release |
build/release |
Optimized build |
relwithdebinfo |
build/relwithdebinfo |
Optimized build with debug symbols and frame pointers |
debug |
build/debug |
Unoptimized build with debug symbols |
asan |
build/asan |
Sanitizer-instrumented build |
tests |
build/tests |
Inherits asan with unit tests enabled |
coverage |
build/coverage |
Inherits debug with tests and cpp_components/ coverage instrumentation |
clang-tidy |
build/clang-tidy |
Inherits debug with static analysis on cpp_components/ |
benchmarks |
build/benchmarks |
Inherits relwithdebinfo with Google Benchmark targets enabled |
From inside the container (or locally with CMake installed):
cmake --preset release
cmake --build --preset releaseOr for a debug build with symbols:
cmake --preset debug
cmake --build --preset debugOr for AddressSanitizer:
cmake --preset asan
cmake --build --preset asanThe build product is the static library libcpp_components.a (for example under build/release/).
Clean build outputs:
rm -rf buildUnit tests use Google Test, fetched automatically by CMake. The tests preset builds in build/tests with BUILD_TESTING enabled and AddressSanitizer/UBSan instrumentation.
cmake --preset tests
cmake --build --preset tests
ctest --preset testsBenchmarks use Google Benchmark, fetched automatically by
CMake. The benchmarks preset builds in build/benchmarks with BUILD_BENCHMARKS enabled and
RelWithDebInfo (-O2 -g -fno-omit-frame-pointer) so timings stay optimized while
perf can resolve symbols and unwind stacks.
cmake --preset benchmarks
cmake --build --preset benchmarks
cmake --build --preset benchmarks-reportThe benchmarks-report preset builds any missing benchmark binaries and runs them all
(equivalent to invoking each *_benchmark executable under build/benchmarks/).
May need to disable CPU scaling:
sudo cpupower frequency-set -g performanceOptional Linux perf wrapping (may need elevated privileges):
sudo perf stat ./build/benchmarks/secure_websocket_client_benchmark
sudo perf record -g ./build/benchmarks/secure_websocket_client_benchmark
sudo perf reportThe coverage preset builds the cpp_components/ targets with GCC coverage instrumentation
(--coverage) and enables the unit tests. Coverage is scoped to cpp_components/ — the
report filters out test sources and Google Test headers.
Configure, build, and run the tests to produce coverage data, then build the
coverage-report preset. That step prints coverage summaries with lcov and
generates an HTML report with genhtml (included in the Docker image):
cmake --preset coverage
cmake --build --preset coverage
ctest --preset coverage
cmake --build --preset coverage-reportThe last step writes an HTML report to
build/coverage/coverage-report/index.html.
Static analysis uses clang-tidy with
the project .clang-tidy config. Analysis is scoped to cpp_components/ and uses
compile_commands.json from the clang-tidy preset (included in the Docker
image).
Configure, then run the clang-tidy-check build preset:
cmake --preset clang-tidy
cmake --build --preset clang-tidy-checkFiles are analyzed in parallel via run-clang-tidy. Job count defaults to the
CPU count; set it at configure time with -DCLANG_TIDY_JOBS=8:
cmake --preset clang-tidy -DCLANG_TIDY_JOBS=8
cmake --build --preset clang-tidy-check.
├── CMakeLists.txt # Root CMake project
├── CMakePresets.json # Release, debug, tests, ASan, coverage, clang-tidy, and benchmarks presets
├── cpp_components/ # Library sources and public headers
├── tests/ # Google Test unit tests
├── benchmarks/ # Google Benchmark targets
├── docker/ # Docker image and helper scripts
└── .devcontainer/ # VS Code Dev Container config
See CONTRIBUTING.md and CODE_STYLE.md.
Apache License 2.0 — see LICENSE.