Conan and CMake presets rollout
Incremental introduction of Conan 2 as the dependency/bootstrap layer and CMake Presets as the unified configure/build interface. Conan is introduced after per-project CMake targets are largely stable (Phase 4), not as a prerequisite for initial VS→CMake translation.
Confirmed policy
- Conan 2 with
CMakeToolchainandCMakeDeps— not Conan 1.x generators - One
conanfile.pyat the superbuild root — workspace consumer recipe; subprojects undersrc/do not get separate top-level recipes unless independently released products - Linux, Windows, and macOS profiles and CI coverage are required
- Windows supports two CMake generators — Ninja (single-config) and Visual Studio (multi-config); see Windows dual-generator policy
Timing in the migration
| Phase | Conan role |
|---|---|
| 0–2 | Inventory Conan candidates; no workspace requirement |
| 3 | Keep manual/third-party linking if needed for VS parity |
| 4 | Introduce workspace Conan recipe, profiles, toolchain generation |
| 5 | Presets include Conan-generated files; standard commands |
| 6 | Retire manual lib paths as dependencies move to Conan |
Rule: Do not block Phase 3 parity on full Conan migration. Do block Phase 6 completion on unresolved manual dependencies that have Conan packages.
Where Conan lives
In the consuming superbuild repository (not in tools/ai-rules/):
workspace-root/
├── conanfile.py # Workspace consumer recipe (requires + tool_requires)
├── conan/
│ ├── profiles/
│ │ ├── linux-x86_64-gcc-debug
│ │ ├── windows-msvc-debug
│ │ └── macos-clang-release
│ └── README.md # Profile naming, local overrides
├── CMakeLists.txt
└── CMakePresets.json
Subprojects under src/ generally do not each require a separate top-level conanfile.py unless independently versioned products. Prefer a workspace recipe that aggregates shared dependencies.
Integration style: CMakeToolchain + CMakeDeps
Conan 2.x pattern (conceptual):
conan install . \
--output-folder=build/<preset-hash> \
--build=missing \
-s build_type=Debug \
-pr:h=conan/profiles/windows-msvc-debug
Generated artifacts (under output folder):
conan_toolchain.cmakeconanbuildinfo/ CMakeDeps config files for dependencies- Often
CMakePresets.jsonfragments viaCMakePresetsgenerator (Conan 2)
CMake consumer code stays Conan-agnostic at the target level:
find_package(Boost REQUIRED COMPONENTS filesystem)
target_link_libraries(mylib PRIVATE Boost::filesystem)
No CONAN_PKG:: legacy patterns in new code.
Profile strategy
| Profile | Host settings | Purpose |
|---|---|---|
linux-*-debug | os=Linux, compiler, build_type=Debug | Dev / CI debug |
linux-*-release | build_type=Release | CI release |
windows-msvc-* | os=Windows, compiler=msvc, arch, build_type | VS + CLI |
macos-* | os=Macos, compiler=apple-clang | macOS dev/CI |
Maintain parallel profiles per OS; do not overload one profile with incompatible settings.
Document in consumer AGENTS.md:
- Default profile per platform
- When to use
tool_requires(cmake, ninja, protobuf compiler, etc.)
Preset layering
Layer 1: Checked-in CMakePresets.json (version 3)
Owned by the superbuild repo. Defines logical preset names independent of Conan hash paths:
{
"version": 3,
"configurePresets": [
{
"name": "base",
"hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}"
},
{
"name": "dev-debug",
"inherits": "base",
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" }
}
]
}
Layer 2: Conan-generated presets
After conan install, Conan may emit CMakePresets.json / CMakeUserPresets.json under the build output folder. Checked-in presets should include or reference toolchain via:
"toolchainFile": "${sourceDir}/build/dev-debug/conan/build/Debug/generators/conan_toolchain.cmake"
Or use include from CMakeUserPresets.json (local, gitignored) for machine-specific output paths when hash folders vary.
Policy: Checked-in presets define names and intent; Conan supplies toolchain and dependency paths. Document the exact include mechanism in consumer AGENTS.md.
Layer 3: CMakeUserPresets.json (optional, local)
Developer-specific overrides (alternate build dir, extra cache vars). Gitignored.
Windows dual-generator policy
Migrated superbuilds support both Ninja and the Visual Studio generator on Windows. This is first-class shared policy — not a local exception.
| Platform | Generator(s) | Config model | Primary use |
|---|---|---|---|
| Linux | Ninja | Single-config | Dev, CI compile/test |
| macOS | Ninja | Single-config | Dev, CI compile/test |
| Windows | Ninja + Visual Studio | Ninja: single-config; VS: multi-config | See below |
Windows — Visual Studio generator (multi-config)
Primary for:
- Interactive debugging in Visual Studio (configuration dropdown: Debug / Release / RelWithDebInfo)
- Installer and release pipelines that expect MSBuild output from CMake-generated project files
- Packaging, signing, or post-build steps integrated with the MSBuild graph
CMake remains authoritative — MSBuild runs generated project files from cmake --preset <vs-preset>, not hand-maintained .vcxproj.
Windows — Ninja (single-config)
Primary for:
- Fast CLI iteration and agent-driven builds
- Cross-platform command parity with Linux/macOS
- Optional CI compile/test jobs where single-config simplicity helps
Preset naming (consumer-defined; document in AGENTS.md)
Use distinct preset names so binary directories never mix generators:
| Preset (example) | Generator | binaryDir (example) | Build command |
|---|---|---|---|
linux-dev-debug | Ninja | build/linux-dev-debug | cmake --build build/linux-dev-debug |
macos-dev-debug | Ninja | build/macos-dev-debug | cmake --build build/macos-dev-debug |
windows-ninja-debug | Ninja | build/windows-ninja-debug | cmake --build build/windows-ninja-debug |
windows-ninja-release | Ninja | build/windows-ninja-release | cmake --build build/windows-ninja-release |
windows-vs-dev | Visual Studio 17 2022 | build/windows-vs-dev | cmake --build build/windows-vs-dev --config Debug |
Exact VS version string and paths are consumer-specific. Policy: separate binaryDir per preset; never share one tree between Ninja and VS generator.
Example checked-in presets (illustrative)
{
"version": 3,
"configurePresets": [
{
"name": "windows-ninja-base",
"hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/windows-ninja-${presetName}"
},
{
"name": "windows-ninja-debug",
"inherits": "windows-ninja-base",
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" }
},
{
"name": "windows-vs-dev",
"generator": "Visual Studio 17 2022",
"architecture": "x64",
"binaryDir": "${sourceDir}/build/windows-vs-dev"
}
]
}
Wire toolchainFile to the Conan output folder for each preset (see preset layering above).
CI responsibilities
Document in consumer AGENTS.md which jobs gate which outcomes:
| CI job (example) | Generator | Gates |
|---|---|---|
ci-linux-debug | Ninja | Merge — compile + test |
ci-macos-debug | Ninja | Merge — compile + test |
ci-windows-ninja-debug | Ninja | Merge — Windows compile + test (optional but recommended) |
ci-windows-vs-release | Visual Studio | Installer / release — cmake --build ... --config Release + packaging |
ci-windows-vs-debug | Visual Studio | Debug parity (optional) |
Minimum for .vcxproj removal: proven local and CI CMake builds on Linux, macOS, and Windows. Windows CI must include at least the VS generator Release path if installers use MSBuild. Ninja Windows CI is recommended for cross-platform compile coverage but does not replace the VS generator installer job.
Rules
- Do not maintain hand-edited
.vcxproj/.slnas build authority — MSBuild via CMake-generated VS projects only - Do not use dual generators as an excuse for divergent CMake logic — one
CMakeLists.txttarget graph serves both - Conan profile is shared; output folder (
-of) and binaryDir differ per preset - Linux and macOS remain Ninja-only unless a documented exception exists
Single-config vs multi-config (reference)
| Platform / generator | Config model |
|---|---|
| Linux + Ninja | Single-config: CMAKE_BUILD_TYPE at configure |
| macOS + Ninja | Single-config: CMAKE_BUILD_TYPE at configure |
| Windows + Ninja | Single-config: CMAKE_BUILD_TYPE at configure |
| Windows + Visual Studio generator | Multi-config: --config Debug|Release at build |
Standard commands
Linux / macOS (Ninja, single-config):
conan install . -of build/linux-dev-debug --build=missing -pr:h=conan/profiles/linux-x86_64-gcc-debug
cmake --preset linux-dev-debug
cmake --build build/linux-dev-debug
ctest --test-dir build/linux-dev-debug
Windows — Ninja (single-config):
conan install . -of build/windows-ninja-debug --build=missing -pr:h=conan/profiles/windows-msvc-debug
cmake --preset windows-ninja-debug
cmake --build build/windows-ninja-debug
Windows — Visual Studio generator (multi-config, debug):
conan install . -of build/windows-vs-dev --build=missing -pr:h=conan/profiles/windows-msvc-debug
cmake --preset windows-vs-dev
cmake --build build/windows-vs-dev --config Debug
Windows — Visual Studio generator (installer / release):
conan install . -of build/windows-vs-dev --build=missing -pr:h=conan/profiles/windows-msvc-release -s build_type=Release
cmake --preset windows-vs-dev
cmake --build build/windows-vs-dev --config Release
# then run documented installer/packaging target or script
Incremental dependency migration
Per dependency:
- Identify manual include/lib paths in CMake and legacy
.vcxproj - Add Conan
requiresto workspaceconanfile.py - Replace paths with
find_package+ imported target link - Verify Linux, Windows, and macOS
- Remove vendored copy from
libs/only after all platforms verified
Keep a dependency migration table in consumer docs/migration/.
CMake stays agnostic
| Belongs in Conan | Belongs in CMake |
|---|---|
| Package versions | Target graph |
Compiler runtime (/MD) | target_link_libraries |
| Toolchain file generation | add_library / add_executable |
| Profile-specific options | Generator expressions for config |
Rollout steps (Phase 4 detail)
- Add minimal
conanfile.pywith one low-risk dependency (e.g. zlib) - Add one profile per OS; verify
conan installin CI - Wire one subproject to
find_packagefor that dependency - Expand
requiresincrementally - Add
tool_requiresfor build tools (cmake, ninja) if using Conan-managed toolchain - Enable preset-driven CI matrix (Linux + macOS + Windows Ninja + Windows VS Release/installer)
Failure modes
| Symptom | Likely cause |
|---|---|
find_package not found | Missing CMakeDeps; wrong CMAKE_PREFIX_PATH |
| CRT mismatch on Windows | Profile compiler.runtime vs target /MT |
| Different flags Linux vs Windows | Definitions still global, not in toolchain |
| Preset not found | Conan output path not included in preset |
Related documents
- legacy-superbuild-migration.md — full phase model
- cmake-conan-policy.md — steady-state policy
- superbuild-integration-plan.md — submodule + workflow