A modern, production-ready C++23 application template with modular architecture, testing infrastructure, and DevContainer support.
- Modern C++23 with strict warnings and error checking
- Modular structure: Separate directories for apps, libraries, and tests
- CMake presets for reproducible builds (debug, release, CI)
- vcpkg manifest mode for hermetic dependency management
- GoogleTest integration for unit and integration testing
- DevContainer with automatic vcpkg bootstrap
- Quality tooling: clang-format, clang-tidy
- Interface + Factory pattern for clean encapsulation
cpp-app-template/
├── external/ # Third-party dependencies (submodules only)
│ └── vcpkg/ # vcpkg submodule (dependency manager)
├── app/ # Application entry points
│ └── sampleApp/
│ ├── CMakeLists.txt
│ └── src/
│ └── main.cpp # Composition root
├── lib/ # Modular libraries
│ └── logger/
│ ├── CMakeLists.txt
│ ├── include/ # Public API (interfaces + factories)
│ │ └── logger/
│ └── src/ # Private implementation
├── test/ # Tests
│ ├── unit/ # Unit tests (library-level)
│ │ └── loggerUnitTest/
│ └── int/ # Integration tests (scenario-based)
│ └── appIntTest/
├── doc/ # Documentation
│ └── ARCHITECTURE.md # Architecture guide
├── script/ # Helper scripts
│ ├── clang-format-all.sh
│ └── clang-tidy-all.sh
├── vcpkg/ # Project vcpkg configuration
│ ├── cache/ # Binary cache (not committed)
│ └── triplets/ # Overlay triplets for custom toolchain
└── CMakePresets.json # Build configuration presets
- Linux (Ubuntu 24.04 LTS or similar)
- VS Code with DevContainer support (recommended)
- CMake 3.28.3 or later
- C++23-capable compiler (GCC 13+ or Clang 17+)
- Open the repository in VS Code
- Accept the prompt to reopen in DevContainer
- vcpkg will bootstrap automatically
-
Bootstrap vcpkg:
git submodule update --init --recursive ./external/vcpkg/bootstrap-vcpkg.sh -disableMetrics
Or use the convenience script:
./script/vcpkg-bootstrap.sh
-
Configure the project:
cmake --preset debug
-
Build:
cmake --build --preset debug-build
-
Run tests:
ctest --preset debug-test --output-on-failure
-
Run the sample application:
./build/debug/app/sampleApp/sampleApp
| Preset | Description |
|---|---|
lint |
Linting build with clang-tidy |
debug |
Debug build with symbols |
release |
Optimised release build with LTO |
ci |
CI/CD preset (release + tests enabled) |
| Preset | Description |
|---|---|
lint-build |
Build linting configuration |
lint-rebuild |
Clean rebuild (lint) |
debug-build |
Build debug configuration |
debug-rebuild |
Clean rebuild (debug) |
release-build |
Build release configuration |
ci-build |
Build CI configuration |
| Preset | Description |
|---|---|
debug-test |
Run tests in debug mode |
release-test |
Run tests in release mode |
ci-test |
Run CI tests |
Workflows chain configure → build → test → package:
cmake --workflow --preset debug-workflow
cmake --workflow --preset release-workflow
cmake --workflow --preset ci-workflowThis template includes both unit and integration tests using GoogleTest.
Located in test/unit/, unit tests verify individual library components in isolation.
Example:
# Run all tests
ctest --preset debug-test --output-on-failure
# Run specific test
./build/debug/test/unit/loggerUnitTest/loggerUnitTest --gtest_filter=LoggerFactoryTest.*Located in test/int/, integration tests verify interactions between multiple components.
See the existing tests in test/unit/loggerUnitTest/src/LoggerFactoryTest.cpp and test/int/appIntTest/src/AppIntTest.cpp for examples.
Format all C++ files:
./script/clang-format-all.shLint all C++ files:
./script/clang-tidy-all.shOr build with clang-tidy enabled:
cmake --preset lint
cmake --build --preset lint-build-
Create directory structure:
mkdir -p lib/mylib/include/mylib mkdir -p lib/mylib/src
-
Define public interface in
lib/mylib/include/mylib/IMyLib.hpp -
Define factory in
lib/mylib/include/mylib/MyLibFactory.hpp -
Implement privately in
lib/mylib/src/ -
Create
lib/mylib/CMakeLists.txt(followlib/logger/CMakeLists.txtpattern) -
Add to root
CMakeLists.txt:add_subdirectory(lib/mylib)
See doc/ARCHITECTURE.md for detailed guidance.
- Unit tests: Create
test/unit/mylibUnitTest/followingtest/unit/loggerUnitTest/pattern - Integration tests: Create
test/int/mycomponentIntTest/followingtest/int/appIntTest/pattern for cross-component testing - Wire into root
CMakeLists.txtinside theif(BUILD_TESTING)block
This template follows modern C++ design principles:
- Interface + Factory pattern for encapsulation
- Composition root (in
main.cpp) for dependency wiring - Dependency Injection for testability
- SOLID principles throughout
See doc/ARCHITECTURE.md for the complete architecture guide.
This project uses vcpkg as a git submodule to ensure reproducible builds.
Initialise the submodule after cloning:
git clone <repo-url>
cd cpp-app-template
git submodule update --init --recursiveOr clone with submodules in one step:
git clone --recurse-submodules <repo-url>To update vcpkg to a newer commit:
cd external/vcpkg
git checkout master
git pull
cd ../..
git add external/vcpkg
git commit -m "Update vcpkg to latest master"Check the current submodule state:
git submodule statusThe project currently supports ARM64 Linux as the primary tested platform:
- ARM64 (default, tested):
cmake --preset debugorcmake --preset debug-arm64 - x64 (untested, planned):
cmake --preset debug-x64
Note: x64 presets are provided for future compatibility but have not been tested on x64 hardware.
Managed via vcpkg manifest mode with pinned baseline.
Current dependencies:
- fmt: String formatting library
- GoogleTest: Testing framework
To add a new dependency:
-
Edit
vcpkg.json:{ "dependencies": [ "fmt", "gtest", "your-package" ] } -
Update your
CMakeLists.txt:find_package(YourPackage CONFIG REQUIRED) target_link_libraries(yourTarget PRIVATE YourPackage::YourPackage)
-
Reconfigure:
cmake --preset debug
Generate distributable packages:
# Debug package
cpack --preset debug-package
# Release package
cpack --preset release-packagePackages are created in build/<preset>/package/ as .tar.gz archives.
rm -rf vcpkg/cache/
./external/vcpkg/bootstrap-vcpkg.sh -disableMetrics
# Or:
./script/vcpkg-bootstrap.shrm -rf build/
cmake --preset debugEnsure BUILD_TESTING is enabled (default ON):
cmake --preset debug -DBUILD_TESTING=ONUpdate to latest baseline or disable specific checks in .clang-tidy:
Checks: '-modernize-use-trailing-return-type'Linux only. This template targets Linux (Ubuntu 24.04 LTS) and uses GNU toolchain (arm64-linux-gnu triplet). Support for other platforms is not provided.
- Architecture Guide - Design patterns and principles
MIT (or specify your licence)
Template Version: 2.0.0 Last Updated: 2026-01-01