Skip to content

Commit 9f9b879

Browse files
committed
Initial support for cmake.preset
1 parent b3b955e commit 9f9b879

12 files changed

+82
-4
lines changed

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ cmake.source-dir = "."
181181
# DEPRECATED in 0.10; use build.targets instead.
182182
cmake.targets = ""
183183

184+
# Configure preset to use. ``cmake.source-dir`` must still be appropriately
185+
# defined and it must contain a ``CMake(User)Presets.json``. The preset's
186+
# ``binaryDir`` is ignored and is always overwritten by the ``build-dir``
187+
# defined by scikit-build-core. ``cmake.define``, generator values are still
188+
# passed if defined and take precedence over preset's value according to CMake
189+
# logic.
190+
cmake.preset = ""
191+
184192
# The versions of Ninja to allow. If Ninja is not present on the system or does
185193
# not pass this specifier, it will be downloaded via PyPI if possible. An empty
186194
# string will disable this check.

src/scikit_build_core/builder/builder.py

+1
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ def configure(
256256
cmake_defines.update(self.settings.cmake.define)
257257

258258
self.config.configure(
259+
preset=self.settings.cmake.preset,
259260
defines=cmake_defines,
260261
cmake_args=[*self.get_cmake_args(), *configure_args],
261262
)

src/scikit_build_core/builder/generator.py

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ def set_environment_for_gen(
9090
9191
If gen is not None, then that will be the target generator.
9292
"""
93+
# TODO: How does make_fallback interact when `preset` is set?
9394
allow_make_fallback = ninja_settings.make_fallback
9495

9596
if generator:

src/scikit_build_core/cmake.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,23 @@
1212
from pathlib import Path
1313
from typing import TYPE_CHECKING, Any
1414

15+
from packaging.version import Version
16+
1517
from . import __version__
1618
from ._logging import logger
1719
from ._shutil import Run
18-
from .errors import CMakeConfigError, CMakeNotFoundError, FailedLiveProcessError
20+
from .errors import (
21+
CMakeConfigError,
22+
CMakeNotFoundError,
23+
CMakeVersionError,
24+
FailedLiveProcessError,
25+
)
1926
from .program_search import Program, best_program, get_cmake_program, get_cmake_programs
2027

2128
if TYPE_CHECKING:
2229
from collections.abc import Generator, Iterable, Mapping, Sequence
2330

2431
from packaging.specifiers import SpecifierSet
25-
from packaging.version import Version
2632

2733
from ._compat.typing import Self
2834

@@ -222,12 +228,19 @@ def get_generator(self, *args: str) -> str | None:
222228
def configure(
223229
self,
224230
*,
231+
preset: str | None = None,
225232
defines: Mapping[str, str | os.PathLike[str] | bool] | None = None,
226233
cmake_args: Sequence[str] = (),
227234
) -> None:
228235
_cmake_args = self._compute_cmake_args(defines or {})
229236
all_args = [*_cmake_args, *cmake_args]
230237

238+
if preset:
239+
if self.cmake.version < Version("3.19"):
240+
msg = f"CMake version ({self.cmake.version}) is too old to support presets."
241+
raise CMakeVersionError(msg)
242+
all_args.append(f"--preset={preset}")
243+
231244
gen = self.get_generator(*all_args)
232245
if gen:
233246
self.single_config = gen == "Ninja" or "Makefiles" in gen

src/scikit_build_core/resources/scikit-build.schema.json

+4
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@
102102
},
103103
"description": "DEPRECATED in 0.10; use build.targets instead.",
104104
"deprecated": true
105+
},
106+
"preset": {
107+
"type": "string",
108+
"description": "Configure preset to use. ``cmake.source-dir`` must still be appropriately defined and it must contain a ``CMake(User)Presets.json``. The preset's ``binaryDir`` is ignored and is always overwritten by the ``build-dir`` defined by scikit-build-core. ``cmake.define``, generator values are still passed if defined and take precedence over preset's value according to CMake logic."
105109
}
106110
}
107111
},

src/scikit_build_core/settings/skbuild_model.py

+9
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,15 @@ class CMakeSettings:
102102
DEPRECATED in 0.10; use build.targets instead.
103103
"""
104104

105+
preset: Optional[str] = None
106+
"""
107+
Configure preset to use. ``cmake.source-dir`` must still be appropriately defined
108+
and it must contain a ``CMake(User)Presets.json``. The preset's ``binaryDir`` is
109+
ignored and is always overwritten by the ``build-dir`` defined by scikit-build-core.
110+
``cmake.define``, generator values are still passed if defined and take precedence
111+
over preset's value according to CMake logic.
112+
"""
113+
105114

106115
@dataclasses.dataclass
107116
class NinjaSettings:

src/scikit_build_core/settings/skbuild_read_settings.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,12 @@ def __init__(
273273
new_min_cmake = "3.15"
274274
self.settings.cmake.version = SpecifierSet(f">={new_min_cmake}")
275275

276+
default_cmake_minimum = "3.15"
277+
if self.settings.cmake.preset:
278+
default_cmake_minimum = "3.19"
279+
276280
_handle_minimum_version(
277-
self.settings.cmake, self.settings.minimum_version, "3.15"
281+
self.settings.cmake, self.settings.minimum_version, default_cmake_minimum
278282
)
279283
_handle_minimum_version(self.settings.ninja, self.settings.minimum_version)
280284

tests/packages/cmake_defines/CMakeLists.txt

+9
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,19 @@ set(ONE_LEVEL_LIST
77
set(NESTED_LIST
88
""
99
CACHE STRING "")
10+
set(PRESET_ONLY_VAR
11+
""
12+
CACHE STRING "")
13+
set(OVERWRITTEN_VAR
14+
""
15+
CACHE STRING "")
1016

1117
set(out_file "${CMAKE_CURRENT_BINARY_DIR}/log.txt")
1218
file(WRITE "${out_file}" "")
1319

20+
file(APPEND "${out_file}" "PRESET_ONLY_VAR=${PRESET_ONLY_VAR}\n")
21+
file(APPEND "${out_file}" "OVERWRITTEN_VAR=${OVERWRITTEN_VAR}\n")
22+
1423
foreach(list IN ITEMS ONE_LEVEL_LIST NESTED_LIST)
1524
list(LENGTH ${list} length)
1625
file(APPEND "${out_file}" "${list}.LENGTH = ${length}\n")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"version": 4,
3+
"configurePresets": [
4+
{
5+
"name": "scikit",
6+
"cacheVariables": {
7+
"PRESET_ONLY_VAR": "defined",
8+
"OVERWRITTEN_VAR": "original"
9+
},
10+
"binaryDir": "/dev/null"
11+
}
12+
]
13+
}

tests/packages/cmake_defines/pyproject.toml

+5
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,8 @@ ONE_LEVEL_LIST = [
99
"Baz",
1010
]
1111
NESTED_LIST = [ "Apple", "Lemon;Lime", "Banana" ]
12+
OVERWRITTEN_VAR = "overwritten"
13+
14+
[[tool.scikit-build.overrides]]
15+
if.env.WITH_PRESET = true
16+
cmake.preset = "scikit"

tests/test_cmake_config.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,14 @@ def test_cmake_paths(
204204
assert len(fp.calls) == 2
205205

206206

207+
@pytest.mark.parametrize("with_preset", [True, False])
207208
@pytest.mark.configure
208209
def test_cmake_defines(
210+
monkeypatch,
209211
tmp_path: Path,
212+
with_preset: bool,
210213
):
214+
monkeypatch.setenv("WITH_PRESET", f"{with_preset}")
211215
source_dir = DIR / "packages" / "cmake_defines"
212216
binary_dir = tmp_path / "build"
213217

@@ -224,8 +228,14 @@ def test_cmake_defines(
224228
builder.configure(defines={})
225229

226230
configure_log = Path.read_text(binary_dir / "log.txt")
231+
232+
# This var is always overwritten
233+
overwritten_var = "overwritten"
234+
preset_only_var = "defined" if with_preset else ""
227235
assert configure_log == dedent(
228-
"""\
236+
f"""\
237+
PRESET_ONLY_VAR={preset_only_var}
238+
OVERWRITTEN_VAR={overwritten_var}
229239
ONE_LEVEL_LIST.LENGTH = 4
230240
Foo
231241
Bar

tests/test_skbuild_settings.py

+1
Original file line numberDiff line numberDiff line change
@@ -764,4 +764,5 @@ def test_skbuild_settings_cmake_define_list():
764764
assert settings.cmake.define == {
765765
"NESTED_LIST": r"Apple;Lemon\;Lime;Banana",
766766
"ONE_LEVEL_LIST": "Foo;Bar;ExceptionallyLargeListEntryThatWouldOverflowTheLine;Baz",
767+
"OVERWRITTEN_VAR": "overwritten",
767768
}

0 commit comments

Comments
 (0)