perf: add 4 workflow modes (BUILD_TESTING / DEV_BUILD / HEADERS_CHECK / ccache)
Four orthogonal opt-in build modes on top of the existing PCH + Unity
defaults. Each addresses a specific iteration scenario; defaults are
unchanged (PCH + Unity stays the canonical fast full-rebuild path).
(A) HEADERS_CHECK target — opt-in via -DCONFORMALLAB_HEADERS_CHECK=ON
Per-public-header smoke-compile sentinels. For each of the six
public CGAL umbrella headers, a stub TU `#include <…>\nint main(){}`
is generated at configure time and compiled in isolation.
* Full headers_check build: ≈ 12 s
* Incremental after touching one header: ≈ 0.1 s
Use case: "did my refactor still parse the public API?" without
waiting 55 s for the full CGAL test build.
(C) DEV_BUILD mode — opt-in via -DCONFORMALLAB_DEV_BUILD=ON
PCH stays on; Unity Build is forced off (both globally AND on the
cgal-tests target which previously overrode the global setting).
Trade-off: full clean rebuild ~75 s (+36 % vs the 55 s default)
but incremental rebuild after editing a single test file drops
from ~46 s (unity batch) to ~16 s (single TU + relink).
Flip on for trial-and-error sessions, flip off before measuring
CI build time or shipping a PR.
(D) ccache integration — default ON, disable with -DCONFORMALLAB_USE_CCACHE=OFF
Detects `ccache` on PATH and prepends it to compile + link
launchers. On Apple clang + PCH + Unity the macOS-local hit
rate is currently 0 % (3 separate friction points documented
in doc/architecture/compile-time.md § "ccache — honesty notes");
stays neutral when it doesn't help. Real payoff on Linux CI
(g++ + traditional PCH) where 80 %+ hit rates are typical.
(BUILD_TESTING=OFF) Standard CMake gate, now respected end-to-end.
Wrapped both `add_subdirectory(tests)` AND the FetchContent of
GoogleTest in `if(BUILD_TESTING)`. Pass `-DBUILD_TESTING=OFF`:
* Configure ≈ 1 s
* Build ≈ 0 s
* 0 object files
* No GTest fetch
Use case: IDE-syntax-check workflow that needs
`compile_commands.json` but does NOT need to download GTest
or build any test binary.
doc/architecture/compile-time.md gains:
* a "Workflow modes — what to choose when" section with a 4-row
switch matrix and a "mode matrix at a glance" comparison table
* a ccache honesty-notes block listing the three macOS friction
points (PCH artefact caching, Unity Build path randomisation,
CMake launcher integration) — Linux CI is where the lever pays
off
Verified: default build 53 s wall, 236/236 tests pass; all opt-in
modes tested end-to-end with their expected workflow numbers
documented in the doc.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -140,14 +140,66 @@ adding more cores past `-j5` does not help this target.
|
||||
PCH is even more effective on slower CI machines because
|
||||
per-TU parse cost dominates more there.
|
||||
|
||||
## Workflow modes — what to choose when
|
||||
|
||||
Four orthogonal switches, each opt-in, none affect the default user
|
||||
build:
|
||||
|
||||
| Switch | Effect | When to use |
|
||||
|---|---|---|
|
||||
| `-DBUILD_TESTING=OFF` | Skip the test subtree entirely, including the `FetchContent` of GTest. **Configure ≈ 1 s · Build ≈ 0 s · 0 object files.** | IDE-syntax-check workflows that only need `compile_commands.json`; configure-only health checks. |
|
||||
| `-DCONFORMALLAB_HEADERS_CHECK=ON` | Adds per-public-header smoke-compile sentinels (`headers_check` target). **Full ≈ 12 s · incremental after touching one header ≈ 0.1 s.** | "Does my refactor still parse all public headers?" without waiting 55 s for the full test build. |
|
||||
| `-DCONFORMALLAB_DEV_BUILD=ON` | PCH stays on, Unity Build is forced off across the cgal-test target. Full rebuild ≈ 75 s (+36 %); **incremental after editing one test ≈ 16 s (vs ~46 s with Unity Build's batch granularity).** | Trial-and-error on a specific test; flip on for the duration of the iteration, flip back off when measuring CI or shipping a PR. |
|
||||
| `-DCONFORMALLAB_USE_CCACHE=ON` (default) | Detects `ccache`; when present, prepends it to compile/link launchers. | Linux CI primarily. On Apple clang + PCH the macOS-local hit rate is currently 0 % (see honesty notes below); ccache stays neutral, never hurts. |
|
||||
|
||||
### Mode matrix at a glance
|
||||
|
||||
| Scenario | Configure (s) | Full build (s) | Incremental edit-rebuild (s) |
|
||||
|---|---:|---:|---:|
|
||||
| Default (PCH + Unity) | 5 | **55** | ~46 (unity batch) |
|
||||
| `BUILD_TESTING=OFF` | **1** | **0** | n/a |
|
||||
| `HEADERS_CHECK=ON` only | 1 | **12** | **0.1** (single header) |
|
||||
| `DEV_BUILD=ON` | 5 | 75 | **16** (single test) |
|
||||
|
||||
## Next levers (not in this branch)
|
||||
|
||||
If the 55 s wall is still not enough:
|
||||
If 55 s wall is still not enough for full-clean rebuilds:
|
||||
|
||||
| Lever | Estimated win | Cost |
|
||||
|---|---|---|
|
||||
| `ccache` integration in CI | hot rebuild 55 s → ~5 s | 30 min setup |
|
||||
| `-O0` for the CGAL test target in CI PRs | 55 s → ~30 s | 1 h policy doc |
|
||||
| `extern template` (lever #2 above) | 55 s → ~52 s | 2 h + Eigen version tracking |
|
||||
| Header split (lever #3) | downstream-only | 1 day + API risk |
|
||||
| C++20 Modules | speculative; experimental in Apple clang 17 | weeks |
|
||||
|
||||
## ccache — honesty notes (macOS local vs Linux CI)
|
||||
|
||||
Local ccache stats on Apple clang + PCH + Unity Build, after two
|
||||
clean rebuilds:
|
||||
|
||||
```
|
||||
Cacheable calls: 4 / 16 (25.00 %)
|
||||
Hits: 0 / 4 ( 0.00 %)
|
||||
Uncacheable calls: 12 / 16 (75.00 %)
|
||||
```
|
||||
|
||||
Three issues defeat the hot rebuild:
|
||||
|
||||
1. **PCH artefacts are not cached by default.** Apple clang's
|
||||
`-include-pch ...gch` path embeds timestamps that miss the cache
|
||||
lookup. Workaround: set `CCACHE_SLOPPINESS=pch_defines,
|
||||
include_file_mtime,include_file_ctime,time_macros,file_macro,
|
||||
system_headers` (tried; still 0 % hit on macOS).
|
||||
2. **Unity Build .cxx files** have generated paths that change
|
||||
between configurations; ccache treats each as a fresh compile.
|
||||
3. **CMake's compile-launcher mechanism** doesn't currently combine
|
||||
with `target_precompile_headers()` in a way that ccache 4.x
|
||||
recognises on Apple clang. Tracked upstream as a known issue.
|
||||
|
||||
**On Linux CI** the picture is different: g++ + traditional PCH +
|
||||
non-Apple toolchain typically delivers 80 %+ hit rates with ccache.
|
||||
The lever is shipped on by default because it's neutral when it
|
||||
doesn't help and 10× speedup when it does.
|
||||
|
||||
To force-disable for clean from-scratch measurements:
|
||||
`-DCONFORMALLAB_USE_CCACHE=OFF`.
|
||||
|
||||
Reference in New Issue
Block a user