This document provides detailed explanations of the build system, commands, and configurations used in this project.
Conan is the C++ package manager used to manage dependencies (currently Google Test).
Using pipx (isolated installation):
pipx install conanAfter installation, verify Conan is available:
conan --versionExpected output:
Conan version 2.x.x
If you see Command 'conan' not found, ensure your Python scripts directory is in your PATH:
# Check where pip installed Conan
pipx list
# Add to PATH if needed (add to ~/.bashrc or ~/.zshrc)
export PATH="$HOME/.local/bin:$PATH"Detect your default Conan profile (compiler, OS, architecture):
conan profile detectExpected output:
Detecting profile...
Found cc=gcc -> /usr/bin/gcc
...
Profile detection successful
conan install . --build=missingconan install .
The . tells Conan to look in the current directory for conanfile.py. Conan then:
- Reads dependencies from the
requirements()method inconanfile.py(currentlygtest/1.14.0) - Downloads packages from Conan Center (https://conan.io/center/)
- Generates CMake integration files in the build directory:
conan_toolchain.cmake— tells CMake where to find dependencies and their headers/libraries- Package config files (e.g.,
GTestConfig.cmake) for each dependency
--build=missing
This flag tells Conan: "If a pre-built binary package isn't available for my system/compiler, build it from source."
Why it matters:
- Conan Center provides pre-built binaries for common platforms (Linux x86_64, macOS ARM64, etc.)
- If no binary exists for your exact setup (e.g., unusual compiler version), Conan would normally fail
- With
--build=missing, Conan compiles the dependency from source (first time only, then cached)
Example scenario:
# Without --build=missing (might fail)
conan install .
# ERROR: Missing binary for gtest/1.14.0
# With --build=missing (builds from source if needed)
conan install . --build=missing
# gtest/1.14.0: Building from source...
# gtest/1.14.0: Package built successfullyBy default, conan install uses Release settings. For Debug builds:
conan install . --build=missing -s build_type=DebugThe -s build_type=Debug flag tells Conan to:
- Use Debug compiler flags (
-g -O0instead of-O2 -DNDEBUG) - Download/build Debug versions of dependencies
- Generate
debugpreset instead ofrelease
# Install dependencies for Release build
conan install . --build=missing
# Install dependencies for Debug build
conan install . --build=missing -s build_type=DebugExpected output:
======== Computing dependency graph ========
Graph root
conanfile.py (cpp_executable_template/0.1.0)
Requirements
gtest/1.14.0
======== Installing packages ========
gtest/1.14.0: Already installed!
======== Generating toolchain files ========
CMakeToolchain generated: conan_toolchain.cmake
CMakeDeps generated: GTestConfig.cmake
CMake presets are predefined configuration sets that specify:
- Build directory location
- Generator (Ninja, Make, etc.)
- Compiler settings
- CMake cache variables
This project defines presets in CMakePresets.json (committed to the repository). Developers can add personal overrides in CMakeUserPresets.json (gitignored).
The following presets are defined in CMakePresets.json:
release
- Build directory:
build/release - Build type:
Release(optimizations enabled, debug symbols stripped) - Compiler flags:
-O2 -DNDEBUG
debug
- Build directory:
build/debug - Build type:
Debug(no optimizations, full debug symbols) - Compiler flags:
-g -O0
debug-sanitizers
- Inherits from:
debug - Enables: AddressSanitizer + UndefinedBehaviorSanitizer
debug-coverage
- Inherits from:
debug - Enables: Code coverage instrumentation
debug-full
- Inherits from:
debug - Enables: Sanitizers + coverage + linting
release-strict
- Inherits from:
release - Enables: Linting enforced during build
Configure with a preset:
cmake --preset releaseThis is equivalent to:
cmake -B build/release \
-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE=ReleaseBuild with a preset:
cmake --build --preset releaseThis builds everything in build/release.
Run tests with a preset:
ctest --preset releaseThis runs tests from the build/release directory.
# Configure Release build
cmake --preset release
# Expected output:
# Preset CMake variables:
# CMAKE_BUILD_TYPE=Release
# CMAKE_TOOLCHAIN_FILE=/path/to/conan_toolchain.cmake
# -- Configuring done
# -- Generating done
# -- Build files have been written to: /path/to/build/release
# Build
cmake --build --preset release
# Expected output:
# [1/3] Building CXX object src/CMakeFiles/cpp_executable_template.dir/main.cpp.o
# [2/3] Linking CXX executable cpp_executable_template
# [3/3] Built target cpp_executable_templateThe following custom presets are defined in CMakePresets.json for common development workflows:
| Preset | Description | Enabled Features |
|---|---|---|
debug-sanitizers |
Debug build with sanitizers | AddressSanitizer, UndefinedBehaviorSanitizer |
debug-coverage |
Debug build with coverage | Code coverage instrumentation |
debug-full |
Comprehensive debug build | Sanitizers + coverage + linting |
release-strict |
Release with strict linting | Linting enforced during build |
These presets inherit from debug or release and add specific CMake options.
Why CMakePresets.json and CMakeUserPresets.json?
CMakePresets.jsonis committed to the repository and defines project-wide presets that all developers useCMakeUserPresets.jsonis gitignored and can be used for personal overrides or experimental configurations- Conan's preset generation is disabled (see
conanfile.py) to avoid overwriting the committed presets
Using custom presets:
# Build with sanitizers (catches memory errors and undefined behavior)
cmake --preset debug-sanitizers
cmake --build --preset debug-sanitizers
ctest --preset debug-sanitizers
# Real example output:
# -- Sanitizers enabled (AddressSanitizer + UndefinedBehaviorSanitizer)
# -- Configuring done
# -- Generating done# Build with coverage (generates HTML coverage report)
cmake --preset debug-coverage
cmake --build --preset debug-coverage
ctest --preset debug-coverage
cmake --build --preset debug-coverage --target coverage
# Real example output:
# -- Code coverage enabled
# -- Configuring done
# -- Generating done
# [100%] Generating code coverage report...
# Coverage report generated at: build/coverage/html/index.html# Full check (sanitizers + coverage + linting)
cmake --preset debug-full
cmake --build --preset debug-full
ctest --preset debug-full
# Real example output:
# -- Sanitizers enabled (AddressSanitizer + UndefinedBehaviorSanitizer)
# -- Code coverage enabled
# -- Configuring done
# -- Generating done
# [ 50%] Checking code formatting...
# [100%] Built target cpp_executable_templateWhen to use each preset:
release: Production builds, performance testing, deploymentdebug: Daily development, debugging, running testsdebug-sanitizers: Before merging code, catching memory bugs, CI pipelinesdebug-coverage: Analyzing test coverage, finding untested code pathsdebug-full: Pre-commit checks, ensuring code quality before pushingrelease-strict: CI/CD pipelines, enforcing code standards in production builds
Release (release)
- Use when: Building for production, performance testing, deployment
- Optimizations: Enabled (
-O2) - Debug symbols: Stripped
- Assertions: Disabled (
NDEBUGdefined) - Binary size: Smaller
- Performance: Faster
Debug (debug)
- Use when: Development, debugging, testing, code coverage, sanitizers
- Optimizations: Disabled (
-O0) - Debug symbols: Full (
-g) - Assertions: Enabled
- Binary size: Larger
- Performance: Slower (but debuggable)
| Scenario | Configuration |
|---|---|
| Daily development | Debug |
| Running tests | Debug |
| Code coverage analysis | Debug |
| Sanitizer analysis | Debug |
| Performance testing | Release |
| Production deployment | Release |
| CI/CD pipelines | Both |
You can configure both Release and Debug builds side-by-side:
# Configure both
cmake --preset release
cmake --preset debug
# Build either
cmake --build --preset release
cmake --build --preset debugEach configuration lives in its own directory (build/release and build/debug), so they don't interfere with each other.
The conanfile.py uses Conan's cmake_layout(), which organizes build artifacts:
build/
├── release/ # Release build artifacts
│ ├── src/
│ │ └── cpp_executable_template # The executable
│ ├── tests/
│ │ └── cpp_executable_template_tests # Test executable
│ ├── CMakeCache.txt
│ ├── compile_commands.json # For clangd/clang-tidy
│ └── ...
│
└── debug/ # Debug build artifacts
├── src/
│ └── cpp_executable_template
├── tests/
│ └── cpp_executable_template_tests
├── CMakeCache.txt
├── compile_commands.json
└── ...
compile_commands.json
- Generated by CMake when
CMAKE_EXPORT_COMPILE_COMMANDS=ON(set in rootCMakeLists.txt) - Contains the exact compiler commands used for each source file
- Required by
clang-tidyfor linting - Used by
clangd(language server) for IDE integration
Executable location
- Release:
build/release/src/cpp_executable_template - Debug:
build/debug/src/cpp_executable_template - On Windows:
.exeextension is added automatically
# Release
./build/release/src/cpp_executable_template
# Debug
./build/debug/src/cpp_executable_templateStep 1: Install Conan (if not already installed)
pip install conan
conan profile detectStep 2: Install dependencies
conan install . --build=missingStep 3: Configure the project
cmake --preset releaseStep 4: Build
cmake --build --preset releaseStep 5: Run the executable
./build/release/src/cpp_executable_templateExpected output:
Hello, World!
# Install dependencies for Debug
conan install . --build=missing -s build_type=Debug
# Configure
cmake --preset debug
# Build
cmake --build --preset debug
# Run (with debug symbols for gdb/lldb)
gdb ./build/debug/src/cpp_executable_templateCause: Conan is not installed or not in PATH.
Solution:
pip install conan
export PATH="$HOME/.local/bin:$PATH"Cause: conan install was not run before cmake --preset.
Solution:
conan install . --build=missing
cmake --preset releaseCause: Conan did not generate CMakePresets.json.
Solution:
# Re-run conan install
conan install . --build=missing
# Verify CMakePresets.json exists
ls CMakePresets.jsonCause: Trying to build Release configuration with Debug dependencies (or vice versa).
Solution:
# Install dependencies for the correct build type
conan install . --build=missing -s build_type=Debug # for Debug
conan install . --build=missing # for Release| Command | Purpose |
|---|---|
conan install . --build=missing |
Install dependencies and generate CMake integration files |
cmake --preset release |
Configure Release build |
cmake --preset debug |
Configure Debug build |
cmake --build --preset release |
Build Release configuration |
cmake --build --preset debug |
Build Debug configuration |
ctest --preset release |
Run tests (Release) |
ctest --preset debug |
Run tests (Debug) |
For linting, testing, coverage, and sanitizers, see: