kmcmake-Generated CMakePresets.json: Flexible, Unlocked Configuration for Build Variants
The default CMakePresets.json generated by kmcmake is a lightweight yet highly extensible foundation
for managing build configurations—aligning perfectly with your "present or not" design philosophy: it provides
sensible defaults out of the box, while remaining completely unopinionated and unlocked for user customization.
No lock-in to specific package managers (kmpkg/vcpkg) or toolchains—users retain full control to adapt it to their
workflow.
Core Design: Minimal Defaults + Unlimited Flexibility
Default Generated Preset (Recap)
{
"version": 2,
"configurePresets": [
{
"name": "default",
"generator": "Unix Makefiles",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "$env{KMPKG_CMAKE}"
}
}
]
}
This default preset is intentionally minimal:
- Uses
Unix Makefiles(universal for Linux/macOS) as the generator. - Fixes the build directory to
build/(consistent with kmcmake’s directory convention). - References
KMPKG_CMAKEenvironment variable for toolchain files (supports kmpkg by default, but easy to replace).
Key Strength: "Unlocked" by Design
The preset avoids hardcoding toolchains, package managers, or build flags—embracing your "users can customize everything" principle:
- No forced dependency on kmpkg/vcpkg: Users can replace
CMAKE_TOOLCHAIN_FILEwith any toolchain (e.g., custom cross- compile scripts, vcpkg’sscripts/buildsystems/vcpkg.cmake). - No locked generators: Switch from
Unix MakefilestoNinja,Visual Studio 17 2022, orXcodewith a single line change. - No hidden logic: All configuration is explicit in the JSON file—users don’t need to learn kmcmake-specific syntax to modify it.
Practical Customization Examples
Users can extend the default preset to support multiple build variants, toolchains, and package managers—all while retaining compatibility with kmcmake’s core workflow. Below are common, production-grade customizations:
Example 1: Add Multiple Build Types (Debug/Release/RelWithDebInfo)
Add presets for different build types (reusing the default base configuration via inherits):
{
"version": 2,
"configurePresets": [
{
"name": "base",
"hidden": true, // Hidden base preset (reused by others)
"generator": "Unix Makefiles",
"binaryDir": "${sourceDir}/build/${presetName}", // Per-preset build directory
"cacheVariables": {
"CMAKE_BUILD_TYPE": "$env{CMAKE_BUILD_TYPE}",
"CMAKE_TOOLCHAIN_FILE": "$env{KMPKG_CMAKE}" // Fallback to kmpkg, overrideable
}
},
{
"name": "debug",
"inherits": "base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"KMCMAKE_BUILD_TEST": "ON" // Enable tests by default for Debug
}
},
{
"name": "release",
"inherits": "base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"KMCMAKE_BUILD_BENCHMARK": "ON" // Enable benchmarks for Release
}
},
{
"name": "relwithdebinfo",
"inherits": "base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo" // Debug symbols + optimizations
}
}
]
}
Usage:
# Configure Debug build
cmake --preset debug
# Configure Release build
cmake --preset release
- Build directories are isolated (
build/debug/,build/release/) to avoid conflicts. - kmcmake flags (e.g.,
KMCMAKE_BUILD_TEST) are integrated directly into presets for one-click configuration.
Example 2: Support Multiple Toolchains (kmpkg/vcpkg/Custom)
Extend the base preset to support different package managers/toolchains—users can choose via presets:
{
"version": 2,
"configurePresets": [
{
"name": "base",
"hidden": true,
"generator": "Unix Makefiles",
"binaryDir": "${sourceDir}/build/${presetName}"
},
// kmpkg toolchain (default)
{
"name": "kmpkg-release",
"inherits": "base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_TOOLCHAIN_FILE": "$env{KMPKG_CMAKE}"
}
},
// vcpkg toolchain
{
"name": "vcpkg-debug",
"inherits": "base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
}
},
// Custom cross-compile toolchain (e.g., ARM)
{
"name": "arm-cross-release",
"inherits": "base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/arm-linux-gnueabihf.cmake"
}
}
]
}
Usage:
# Use vcpkg for Debug build
cmake --preset vcpkg-debug
# Use custom ARM toolchain for Release build
cmake --preset arm-cross-release
- No lock-in: Users can add/remove toolchains without modifying kmcmake’s core.
- Environment variables (
KMPKG_CMAKE,VCPKG_ROOT) keep the preset portable across machines.
Example 3: Windows-Specific Preset (Visual Studio Generator)
Add cross-platform presets to support Windows (Visual Studio) alongside Linux/macOS:
{
"version": 2,
"configurePresets": [
{
"name": "windows-vs2022-release",
"generator": "Visual Studio 17 2022",
"architecture": "x64",
"binaryDir": "${sourceDir}/build/windows-vs2022-release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" // vcpkg on Windows
}
}
]
}
Usage (Windows PowerShell):
cmake --preset windows-vs2022-release
cmake --build build/windows-vs2022-release --config Release
- Aligns with kmcmake’s cross-platform design—presets handle generator/architecture differences.
Key Design Merits (Aligning with Your "Present or Not" Philosophy)
1. Zero Lock-In, Full User Control
- No hardcoded toolchains/package managers: Users can replace
CMAKE_TOOLCHAIN_FILEwith any value (kmpkg/vcpkg/custom). - No mandatory presets: The default
defaultpreset is a starting point—users can delete, modify, or add presets without breaking kmcmake. - Compatible with native CMake workflows: Presets are a standard CMake feature, not kmcmake-specific—users familiar with CMake can adapt immediately.
2. Consistency + Flexibility Balance
- Reuse via
inherits: Thebasepreset pattern reduces duplication—users can define common settings once and extend them. - Isolated build directories: Each preset uses its own
binaryDir, avoiding conflicts between build types/toolchains. - Explicit configuration: All build settings (build type, kmcmake flags, toolchains) are visible in the JSON file—no hidden magic.
3. Portable + Collaborative
- Environment variables: References to
$env{KMPKG_CMAKE},$env{VCPKG_ROOT}make presets portable across machines (no hardcoded paths). - Shared configuration: Teams can commit customized presets to Git—ensuring all developers use consistent build settings (e.g., "debug with tests", "release with benchmarks").
4. Minimal Learning Curve
- Follows CMake’s standard
CMakePresets.jsonschema: No kmcmake-specific extensions—users can leverage existing CMake knowledge. - Default preset works out of the box: New users can run
cmake --preset defaultwithout modification (if kmpkg is set up), while advanced users can extend it.
Critical Best Practices for Users
- Commit Custom Presets to Git: Share presets (e.g.,
debug,release,vcpkg-debug) with your team to ensure consistency. - Use
inheritsto Avoid Duplication: Define abasepreset with common settings (generator, binaryDir structure) and inherit from it—easier to maintain. - Keep Toolchains External: Store custom toolchain files (e.g.,
arm-linux-gnueabihf.cmake) incmake/toolchains/—presets reference them via relative paths. - Avoid Hardcoded Paths: Use environment variables (e.g.,
$env{VCPKG_ROOT}) instead of absolute paths to keep presets portable.
Final Evaluation of the Preset Template
The default CMakePresets.json is a perfect embodiment of your "present or not" design:
- It’s "present" to provide a sensible, zero-configuration starting point (run
cmake --preset defaultand go). - It’s "not" to avoid imposing restrictions—users can customize every aspect (toolchains, build types, generators) without fighting kmcmake.
As a complement to kmcmake’s core template, it solves the problem of "managing multiple build variants" in a standard, portable way—without adding kmcmake-specific complexity. It’s lightweight enough for small projects, yet powerful enough for large cross-platform teams. The best part: it aligns with CMake’s native ecosystem, so users aren’t locked into kmcmake—they can take their presets and project structure elsewhere if needed.