Skip to main content

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 CMakeToolchain and CMakeDeps — not Conan 1.x generators
  • One conanfile.py at the superbuild root — workspace consumer recipe; subprojects under src/ 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

PhaseConan role
0–2Inventory Conan candidates; no workspace requirement
3Keep manual/third-party linking if needed for VS parity
4Introduce workspace Conan recipe, profiles, toolchain generation
5Presets include Conan-generated files; standard commands
6Retire 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.cmake
  • conanbuildinfo / CMakeDeps config files for dependencies
  • Often CMakePresets.json fragments via CMakePresets generator (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

ProfileHost settingsPurpose
linux-*-debugos=Linux, compiler, build_type=DebugDev / CI debug
linux-*-releasebuild_type=ReleaseCI release
windows-msvc-*os=Windows, compiler=msvc, arch, build_typeVS + CLI
macos-*os=Macos, compiler=apple-clangmacOS 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.

PlatformGenerator(s)Config modelPrimary use
LinuxNinjaSingle-configDev, CI compile/test
macOSNinjaSingle-configDev, CI compile/test
WindowsNinja + Visual StudioNinja: single-config; VS: multi-configSee 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)GeneratorbinaryDir (example)Build command
linux-dev-debugNinjabuild/linux-dev-debugcmake --build build/linux-dev-debug
macos-dev-debugNinjabuild/macos-dev-debugcmake --build build/macos-dev-debug
windows-ninja-debugNinjabuild/windows-ninja-debugcmake --build build/windows-ninja-debug
windows-ninja-releaseNinjabuild/windows-ninja-releasecmake --build build/windows-ninja-release
windows-vs-devVisual Studio 17 2022build/windows-vs-devcmake --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)GeneratorGates
ci-linux-debugNinjaMerge — compile + test
ci-macos-debugNinjaMerge — compile + test
ci-windows-ninja-debugNinjaMerge — Windows compile + test (optional but recommended)
ci-windows-vs-releaseVisual StudioInstaller / releasecmake --build ... --config Release + packaging
ci-windows-vs-debugVisual StudioDebug 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 / .sln as build authority — MSBuild via CMake-generated VS projects only
  • Do not use dual generators as an excuse for divergent CMake logic — one CMakeLists.txt target 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 / generatorConfig model
Linux + NinjaSingle-config: CMAKE_BUILD_TYPE at configure
macOS + NinjaSingle-config: CMAKE_BUILD_TYPE at configure
Windows + NinjaSingle-config: CMAKE_BUILD_TYPE at configure
Windows + Visual Studio generatorMulti-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:

  1. Identify manual include/lib paths in CMake and legacy .vcxproj
  2. Add Conan requires to workspace conanfile.py
  3. Replace paths with find_package + imported target link
  4. Verify Linux, Windows, and macOS
  5. Remove vendored copy from libs/ only after all platforms verified

Keep a dependency migration table in consumer docs/migration/.

CMake stays agnostic

Belongs in ConanBelongs in CMake
Package versionsTarget graph
Compiler runtime (/MD)target_link_libraries
Toolchain file generationadd_library / add_executable
Profile-specific optionsGenerator expressions for config

Rollout steps (Phase 4 detail)

  1. Add minimal conanfile.py with one low-risk dependency (e.g. zlib)
  2. Add one profile per OS; verify conan install in CI
  3. Wire one subproject to find_package for that dependency
  4. Expand requires incrementally
  5. Add tool_requires for build tools (cmake, ninja) if using Conan-managed toolchain
  6. Enable preset-driven CI matrix (Linux + macOS + Windows Ninja + Windows VS Release/installer)

Failure modes

SymptomLikely cause
find_package not foundMissing CMakeDeps; wrong CMAKE_PREFIX_PATH
CRT mismatch on WindowsProfile compiler.runtime vs target /MT
Different flags Linux vs WindowsDefinitions still global, not in toolchain
Preset not foundConan output path not included in preset