CMake Presets¶
CMakePresets.json at the repository root holds solvcon’s build
configuration: the generator, the build type, the cache variables, and the run
environment. It is checked in, so every contributor and every continuous
integration job configures the same way, and both supported IDEs read it
directly.
List what the file offers on this host, then configure and build:
cmake --list-presets
cmake --preset <name>
cmake --build --preset <name>
A preset that names a toolchain the current host cannot run carries a
condition, so it does not appear in the listing there. On Linux and macOS
the make targets described in Build solvcon remain the entry
point every contributor uses, and they configure through these presets: the
Makefile adds the ABI-tagged build directory, the generator, and whatever
make VAR=value sets, and nothing else.
Configure preset |
Host |
What it configures |
|---|---|---|
|
Linux, macOS |
optimized module and pilot, symbols |
|
Linux, macOS |
optimized module and pilot, no symbols |
|
Linux, macOS |
debuggable module and pilot |
|
Linux, macOS |
optimized module, no pilot |
|
Windows |
optimized module and pilot, symbols, MSVC |
|
Windows |
optimized module and pilot, no symbols, MSVC |
|
Windows |
debuggable module and pilot, MSVC |
The reldbg presets configure RelWithDebInfo and are the default a make
build selects; the rel ones configure Release, which drops the debug
symbols and picks up the pybind11 extras, link-time optimization and a strip
of the extension module. See Build solvcon for which to pick.
Each configure preset comes with three build presets, one per thing that is actually built:
Build preset |
Targets |
|---|---|
|
the extension module and the pilot |
|
the extension module alone |
|
the C++ gtest binary |
cmake --build --preset <name> therefore needs no --target argument. The
dev-noqt preset has no pilot to build, so it has only the plain and -gtest
entries.
The build tree is build/<configure preset>, named through the
${presetName} macro so that a preset inheriting another gets its own tree
rather than writing into its parent’s. It is one tree per preset, which is
what both IDEs assume, and it is not the Makefile’s build/reldbg<pyvminor>,
so a preset build and a make build never share a cache. They do share where
the extension module lands, solvcon/ and the repository root, so whichever
built last is the one Python imports.
Test presets run the suites CTest has registered. There is one per configure
preset, plus label-filtered ones on dev-reldbg:
ctest --preset dev-reldbg # every suite
ctest --preset dev-reldbg-cpp # the C++ cases alone
ctest --preset dev-reldbg-python # the Python suite alone
ctest --preset dev-reldbg-pilot # the Python suite inside the pilot binary
The C++ cases come from gtest_discover_tests, which enumerates them by
running the built binary, and the plain build preset does not build it. Build
<preset>-gtest before a run that includes them, or CTest reports the single
placeholder case test_nopython_NOT_BUILT and fails:
cmake --preset dev-reldbg
cmake --build --preset dev-reldbg
cmake --build --preset dev-reldbg-gtest
ctest --preset dev-reldbg
CLion reads no test presets, so a CLion user reaches the same suites through
its CTest integration against the configured build tree. That works because
the suites are registered with add_test(), not because a preset names them.
Workflow presets chain configure, build, and test into one command:
cmake --workflow --preset ci-win-rel
They exist for CI. The ci- presets are what the Windows jobs name instead
of spelling out a cmake command line, and the two values a runner owns, the
pybind11 package directory and the MKL paths, reach them through $env{}
rather than being written into the file. A preset that a command line names
cannot be hidden, so the ci- presets do appear in the preset pickers; the
prefix and their descriptions are what say to pick something else. CLion does
not show workflow presets at all.
One consequence is worth knowing. _solvcon is an ABI-tagged extension and
PYTHON_EXECUTABLE is a cache variable, so pointing the same preset at a
different interpreter reuses a stale cache. Reconfigure with --fresh after
switching interpreters:
cmake --preset dev-reldbg --fresh
Machine paths belong in CMakeUserPresets.json¶
Three cache variables name directories that exist on one machine only:
Variable |
What it names |
|---|---|
|
the interpreter the extension is built against |
|
the pybind11 CMake package directory for that Python |
|
the dependency prefix holding Qt6, PySide6, and so on |
They must not be checked in, which is what CMakeUserPresets.json is for.
CMake reads it automatically, it implicitly includes CMakePresets.json, and
it is gitignored. Both VS Code and CLion pick it up with no IDE settings at
all, which is the only way a dependency prefix reaches an IDE build: there is
no wrapper script to fall back on there.
The file provides the information that can be used by the IDE, and its presets
are named ide-*. A shell build has no use for it, because an activated
environment already exports CMAKE_PREFIX_PATH and make forwards it onto a
checked-in preset. Build from a shell with make, or with
make CMAKE_PRESET=<name> to pick another checked-in preset.
There is one template per host family, because the checked-in presets a user preset builds on are themselves split by host. Copy the one for your host and edit the three paths:
# Linux and macOS
cp contrib/cmake/CMakeUserPresets.example.json CMakeUserPresets.json
# Windows
cp contrib/cmake/CMakeUserPresets.win-example.json CMakeUserPresets.json
Each defines a configure preset named ide-local-reldbg that inherits a
checked-in preset and adds the three variables, plus the three build presets
that go with it:
{
"version": 10,
"configurePresets": [
{
"name": "ide-local-reldbg",
"inherits": "dev-reldbg",
"displayName": "IDE or manual use: local prefix",
"cacheVariables": {
"PYTHON_EXECUTABLE": {
"type": "FILEPATH",
"value": "/path/to/prefix/bin/python3"
},
"pybind11_path": "/path/to/prefix/lib/python3.14/site-packages/pybind11/share/cmake/pybind11",
"CMAKE_PREFIX_PATH": "/path/to/prefix"
}
}
],
"buildPresets": [
{ "name": "ide-local-reldbg", "inherits": "dev-reldbg",
"configurePreset": "ide-local-reldbg" }
]
}
Every inherits in the file names a preset of one host family, and they have
to stay a matched set. A dev- build preset carries a condition that
disables it on Windows and a win- one carries the opposite, so an
ide-local-reldbg that inherits a win- configure preset and dev- build
presets configures and then refuses to build. Change them together, or start
from the template for the family you want.
pybind11_path names the directory holding pybind11Config.cmake, which is
what python3 -m pybind11 --cmakedir prints for the interpreter named above
it. After that, ide-local-reldbg appears in the IDE preset pickers alongside
the checked-in presets.
In CLion the enablePythonIntegration key in the jetbrains.com/clion vendor
map, already set in the checked-in presets, hands the IDE’s selected
interpreter to the configure step. A CLion user can therefore drop the
PYTHON_EXECUTABLE line and keep only the other two.
CMakeUserPresets.scdv.json and CMakeUserPresets.win-scdv.json sit beside
the two templates above for a prefix that build-scdv.sh built (see
Build Dependencies). Their configure preset is ide-scdv-reldbg, and it
names that prefix once rather than repeating it in three literal paths, so
installing one substitutes a single value instead of editing three. The
ide-user-presets skill under .claude/skills/ states the substitution and
what has to hold for it.
IDE notes¶
Nothing else needs to be configured, and a few things must not be.
VS Code CMake Tools turns preset mode on by itself once
CMakePresets.jsonexists. In that mode it ignorescmake.buildDirectory,cmake.generator, andcmake.configureSettingsinsettings.json, and it disables kit selection, so a settings file that restates any of those only causes confusion.CLion imports the presets as read-only profiles and leaves a newly seen one disabled until it is enabled in the CMake settings.
CLion reads configure and build presets only. Anything expressed solely as a test or workflow preset is invisible there, so the configure and build presets stay self-sufficient.
Code navigation works from
compile_commands.json, which the presets export.