Skip to content

Commit 9d3b66e

Browse files
authored
feat(setuptools): adding cmake_args (#314)
Adds cmake_args, can be combined with `[build_cmake] cmake_args` and other ways to set it. Signed-off-by: Henry Schreiner <[email protected]>
1 parent a09a9a0 commit 9d3b66e

File tree

7 files changed

+72
-13
lines changed

7 files changed

+72
-13
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ Examples = "https://github.com/scikit-build/scikit-build-core/tree/main/tests/pa
8888
[project.entry-points]
8989
"distutils.commands".build_cmake = "scikit_build_core.setuptools.build_cmake:BuildCMake"
9090
"distutils.setup_keywords".cmake_source_dir = "scikit_build_core.setuptools.build_cmake:cmake_source_dir"
91+
"distutils.setup_keywords".cmake_args = "scikit_build_core.setuptools.build_cmake:cmake_args"
9192
"setuptools.finalize_distribution_options".scikit_build_entry = "scikit_build_core.setuptools.build_cmake:finalize_distribution_options"
9293

9394
[tool.hatch]

src/scikit_build_core/builder/builder.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import re
55
import sys
66
import sysconfig
7-
from collections.abc import Mapping, Sequence
7+
from collections.abc import Iterable, Mapping, Sequence
88
from pathlib import Path
99

1010
from packaging.version import Version
@@ -83,6 +83,7 @@ def configure(
8383
name: str | None = None,
8484
version: Version | None = None,
8585
limited_abi: bool | None = None,
86+
configure_args: Iterable[str] = (),
8687
) -> None:
8788
cmake_defines = dict(defines)
8889

@@ -181,7 +182,7 @@ def configure(
181182

182183
self.config.configure(
183184
defines=cmake_defines,
184-
cmake_args=self.get_cmake_args(),
185+
cmake_args=[*self.get_cmake_args(), *configure_args],
185186
)
186187

187188
def build(self, build_args: list[str]) -> None:

src/scikit_build_core/setuptools/build_cmake.py

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from pathlib import Path
77

88
import setuptools
9+
import setuptools.errors
910
from packaging.version import Version
1011
from setuptools.dist import Distribution
1112

@@ -38,6 +39,7 @@ def _validate_settings() -> None:
3839

3940
class BuildCMake(setuptools.Command):
4041
source_dir: str | None = None
42+
cmake_args: list[str] | str | None = None
4143

4244
build_lib: str | None
4345
build_temp: str | None
@@ -52,6 +54,8 @@ class BuildCMake(setuptools.Command):
5254
("plat-name=", "p", "platform name to cross-compile for, if supported "),
5355
("debug", "g", "compile/link with debugging information"),
5456
("parallel=", "j", "number of parallel build jobs"),
57+
("source-dir=", "j", "directory with CMakeLists.txt"),
58+
("cmake-args=", "a", "extra arguments for CMake"),
5559
]
5660

5761
def initialize_options(self) -> None:
@@ -61,6 +65,8 @@ def initialize_options(self) -> None:
6165
self.editable_mode = False
6266
self.parallel = None
6367
self.plat_name = None
68+
self.source_dir = None
69+
self.cmake_args = None
6470

6571
def finalize_options(self) -> None:
6672
self.set_undefined_options(
@@ -72,8 +78,12 @@ def finalize_options(self) -> None:
7278
("plat_name", "plat_name"),
7379
)
7480

81+
if isinstance(self.cmake_args, str):
82+
self.cmake_args = [
83+
b.strip() for a in self.cmake_args.split() for b in a.split(";")
84+
]
85+
7586
def run(self) -> None:
76-
assert self.source_dir is not None
7787
assert self.build_lib is not None
7888
assert self.build_temp is not None
7989
assert self.plat_name is not None
@@ -84,6 +94,14 @@ def run(self) -> None:
8494
build_temp = build_tmp_folder / "_skbuild" # TODO: include python platform
8595

8696
dist = self.distribution
97+
dist_source_dir = getattr(self.distribution, "cmake_source_dir", None)
98+
source_dir = self.source_dir if dist_source_dir is None else dist_source_dir
99+
assert source_dir is not None, "This should not be reachable"
100+
101+
configure_args = self.cmake_args or []
102+
assert isinstance(configure_args, list)
103+
dist_cmake_args = getattr(self.distribution, "cmake_args", None)
104+
configure_args.extend(dist_cmake_args or [])
87105

88106
bdist_wheel = dist.get_command_obj("bdist_wheel")
89107
assert bdist_wheel is not None
@@ -101,7 +119,7 @@ def run(self) -> None:
101119

102120
config = CMaker(
103121
cmake,
104-
source_dir=Path(self.source_dir),
122+
source_dir=Path(source_dir),
105123
build_dir=build_temp,
106124
build_type=settings.cmake.build_type,
107125
)
@@ -126,6 +144,7 @@ def run(self) -> None:
126144
version=Version(dist.get_version()),
127145
defines={},
128146
limited_abi=limited_api,
147+
configure_args=configure_args,
129148
)
130149

131150
# Set CMAKE_BUILD_PARALLEL_LEVEL to control the parallel build level
@@ -153,7 +172,10 @@ def run(self) -> None:
153172
def _has_cmake(dist: Distribution) -> bool:
154173
build_cmake = dist.get_command_obj("build_cmake")
155174
assert isinstance(build_cmake, BuildCMake)
156-
return build_cmake.source_dir is not None
175+
return (
176+
build_cmake.source_dir is not None
177+
or getattr(dist, "cmake_source_dir", None) is not None
178+
)
157179

158180

159181
def _prepare_extension_detection(dist: Distribution) -> None:
@@ -181,16 +203,22 @@ def _prepare_build_cmake_command(dist: Distribution) -> None:
181203
)
182204

183205

184-
def cmake_source_dir(
185-
dist: Distribution, attr: Literal["cmake_source_dir"], value: str
206+
def cmake_args(
207+
_dist: Distribution, attr: Literal["cmake_args"], value: list[str]
186208
) -> None:
187-
assert attr == "cmake_source_dir"
188-
assert Path(value).is_dir()
209+
assert attr == "cmake_args"
210+
if not isinstance(value, list):
211+
msg = "cmake_args must be a list"
212+
raise setuptools.errors.SetupError(msg)
189213

190-
build_cmake = dist.get_command_obj("build_cmake")
191-
assert isinstance(build_cmake, BuildCMake)
192214

193-
build_cmake.source_dir = value
215+
def cmake_source_dir(
216+
_dist: Distribution, attr: Literal["cmake_source_dir"], value: str
217+
) -> None:
218+
assert attr == "cmake_source_dir"
219+
if not Path(value).is_dir():
220+
msg = "cmake_source_dir must be an existing directory"
221+
raise setuptools.errors.SetupError(msg)
194222

195223

196224
def finalize_distribution_options(dist: Distribution) -> None:

tests/packages/mixed_setuptools/CMakeLists.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,26 @@
11
cmake_minimum_required(VERSION 3.15...3.26)
22
project("${SKBUILD_PROJECT_NAME}" LANGUAGES CXX)
33

4+
if(NOT EXAMPLE_DEFINE1 EQUAL 1)
5+
message(FATAL_ERROR "Example define 1 is not set")
6+
endif()
7+
8+
if(NOT EXAMPLE_DEFINE2 EQUAL 2)
9+
message(FATAL_ERROR "Example define 2 is not set")
10+
endif()
11+
12+
if(NOT EXAMPLE_DEFINE3 EQUAL 3)
13+
message(FATAL_ERROR "Example define 3 is not set")
14+
endif()
15+
16+
if(NOT EXAMPLE_DEFINE4 EQUAL 4)
17+
message(FATAL_ERROR "Example define 4 is not set")
18+
endif()
19+
20+
if(NOT EXAMPLE_DEFINE5 EQUAL 5)
21+
message(FATAL_ERROR "Example define 5 is not set")
22+
endif()
23+
424
find_package(pybind11 CONFIG REQUIRED)
525
pybind11_add_module(_core src/main.cpp)
626

tests/packages/mixed_setuptools/pyproject.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,9 @@ requires = [
55
"pybind11",
66
]
77
build-backend = "scikit_build_core.setuptools.build_meta"
8+
9+
[tool.scikit-build]
10+
cmake.args = ["-DEXAMPLE_DEFINE3=3"]
11+
12+
[tool.scikit-build.cmake.define]
13+
EXAMPLE_DEFINE4 = "4"

tests/packages/mixed_setuptools/setup.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,6 @@ where = src
1414

1515
[build_cmake]
1616
source_dir = .
17+
cmake_args =
18+
-DEXAMPLE_DEFINE1=1
19+
-DEXAMPLE_DEFINE2=2
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
from setuptools import setup
22

3-
setup()
3+
setup(cmake_args=["-DEXAMPLE_DEFINE5=5"])

0 commit comments

Comments
 (0)