Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 18 additions & 20 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,43 +25,35 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4

- name: Cache Conan packages
uses: actions/cache@v4
with:
path: ~/.conan2
key: conan-${{ matrix.os }}-${{ matrix.compiler }}-${{ matrix.preset }}-${{ hashFiles('conanfile.*') }}

Comment on lines +28 to +33
- name: Install Conan
run: pipx install conan

- name: Configure Conan profile
run: conan profile detect --force
env:
CC: ${{ matrix.compiler == 'gcc' && 'gcc' || 'clang' }}
CXX: ${{ matrix.compiler == 'gcc' && 'g++' || 'clang++' }}
Comment on lines +39 to +41

- name: Install dependencies
run: |
BUILD_TYPE=$(echo "${{ matrix.preset }}" | grep -q "release" && echo "Release" || echo "Debug")
conan install . --build=missing -s build_type=$BUILD_TYPE -s compiler.cppstd=23
env:
CC: ${{ matrix.compiler == 'gcc' && 'gcc' || 'clang' }}
CXX: ${{ matrix.compiler == 'gcc' && 'g++' || 'clang++' }}

- name: Configure CMake
run: cmake --preset ${{ matrix.preset }}
env:
CC: ${{ matrix.compiler == 'gcc' && 'gcc' || 'clang' }}
CXX: ${{ matrix.compiler == 'gcc' && 'g++' || 'clang++' }}

- name: Verify C++23 standard
run: |
echo "=== Compiler Information ==="
${{ matrix.compiler == 'gcc' && 'g++' || 'clang++' }} --version
echo ""
echo "=== Checking C++ standard in compile commands ==="
if [ -f "build/${{ matrix.preset }}/compile_commands.json" ]; then
# Extract and display C++ standard flags
grep -o '\-std=[^ " ]*' "build/${{ matrix.preset }}/compile_commands.json" | sort -u || echo "No -std flag found"
# Verify C++23 is being used
if grep -q '\-std=c++2[3b]' "build/${{ matrix.preset }}/compile_commands.json"; then
echo "✓ C++23 standard verified"
else
echo "✗ C++23 standard NOT found in compile commands"
exit 1
fi
else
echo "Warning: compile_commands.json not found"
fi

- name: Build
run: cmake --build --preset ${{ matrix.preset }}

Expand All @@ -76,6 +68,12 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4

- name: Cache Conan packages
uses: actions/cache@v4
with:
path: ~/.conan2
key: conan-ubuntu-latest-gcc-debug-coverage-${{ hashFiles('conanfile.*') }}
Comment on lines +71 to +75

- name: Install Conan
run: pipx install conan

Expand Down
49 changes: 49 additions & 0 deletions docs/CI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# CI Compiler Configuration

This document explains how compilers are configured in the CI pipeline.

---

## What are CC and CXX?

**CC** and **CXX** are standard environment variables that tell build tools which compilers to use:

- **CC** — Path to the C compiler (e.g., `gcc`, `clang`)
- **CXX** — Path to the C++ compiler (e.g., `g++`, `clang++`)

These variables are recognized by:
- CMake
- Make
- Conan
- Most Unix-based build systems

---

## How This Project Uses CC/CXX

The CI matrix tests multiple compilers across different operating systems:

| OS | Compiler | CC | CXX |
|---|---|---|---|
| ubuntu-latest | gcc | gcc | g++ |
| ubuntu-latest | clang | clang | clang++ |
| macos-latest | clang | clang | clang++ |

The workflow sets these variables for all build steps:

```yaml
env:
CC: ${{ matrix.compiler == 'gcc' && 'gcc' || 'clang' }}
CXX: ${{ matrix.compiler == 'gcc' && 'g++' || 'clang++' }}
```

---

## Why This Matters

Setting CC/CXX ensures:
1. **Consistent compiler selection** — All tools (Conan, CMake, etc.) use the same compiler
2. **Correct cache segmentation** — Dependencies are built with the intended compiler
3. **Reproducible builds** — Same inputs produce same outputs regardless of system defaults

For more information on caching, see [CI Caching Guide](CI_CACHING.md).
89 changes: 89 additions & 0 deletions docs/CI_CACHING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# CI Caching Guide

This document explains how GitHub Actions caching works in this project's CI pipeline.

---

## How CI Jobs Run

Each CI job starts on a **fresh virtual machine** with:
- No previous build artifacts
- No installed tools (except GitHub-provided defaults)
- No cached data in the filesystem

Data only persists between runs through:
- **Caches** (dependency caching)
- **Artifacts** (explicit upload/download)
- **External storage** (GitHub Packages, etc.)

---

## Conan Dependency Caching

This project caches Conan packages (`~/.conan2`) to speed up builds.

### Cache Key Structure

The cache key includes:
- **OS** (e.g., `ubuntu-latest`, `macos-latest`)
- **Compiler** (e.g., `gcc`, `clang`)
- **Preset** (e.g., `release-strict`, `debug-sanitizers`)
- **Conanfile hash** (automatically invalidates when dependencies change)

Example: `conan-ubuntu-latest-gcc-release-strict-<hash>`

### Cache Behavior

- **Persistence:** 7 days after last access
- **Scope:** Repository and branch (main branch caches are available to PRs)
- **Invalidation:** Automatic when `conanfile.txt` or `conanfile.py` changes

### Why CC/CXX Must Be Passed to Conan

The cache key includes the compiler (gcc/clang), so Conan must actually use that compiler when building packages. Without setting `CC` and `CXX`:

- Conan detects the system default compiler (usually gcc on Ubuntu)
- Both gcc and clang cache keys end up storing identical gcc-built packages
- You waste cache storage and risk compiler mismatches

By setting `CC`/`CXX` for Conan steps, each cache key contains packages built with the correct compiler, keeping the cache segmentation accurate and meaningful.

See [CI Compiler Configuration](CI.md) for details on CC/CXX.

---

## Cache Hit Scenarios

### Best Scenarios (High Hit Rate)

1. **Frequent commits without dependency changes** — Every build hits the cache
2. **PRs targeting main** — Reuse caches created by main branch builds
3. **Stable dependency periods** — Weeks without updating dependencies

### Worst Scenarios (Cache Misses)

- Modifying `conanfile.txt` or `conanfile.py`
- First build on a new branch that diverged before dependencies were cached
- After 7 days of inactivity (cache expires)

---

## Benefits

- **Time savings:** 1-5+ minutes per job (skips downloading/building dependencies)
- **Cost reduction:** Fewer CI minutes consumed
- **Network efficiency:** Reduced external API calls

---

## Summary

| Aspect | Behavior |
|---|---|
| Cache persistence | 7 days after last access |
| Cache scope | Repository + branch |
| Invalidation | Automatic on conanfile changes |
| Best use case | Stable dependencies with frequent builds |
| Time saved | 1-5+ minutes per job |

For more information on the CI pipeline, see `.github/workflows/ci.yml`.
Loading