Skip to content

Commit fd67754

Browse files
committed
chore: use scikit-build-core for the build
Signed-off-by: Henry Schreiner <[email protected]>
1 parent 55b1357 commit fd67754

File tree

12 files changed

+187
-240
lines changed

12 files changed

+187
-240
lines changed

.github/workflows/format.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@ jobs:
3232
- name: Add matchers
3333
run: echo "::add-matcher::$GITHUB_WORKSPACE/.github/matchers/pylint.json"
3434
- uses: pre-commit/[email protected]
35-
with:
36-
# Slow hooks are marked with manual - slow is okay here, run them too
37-
extra_args: --hook-stage manual --all-files
3835

3936
clang-tidy:
4037
# When making changes here, please also review the "Clang-Tidy" section

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,8 @@ pybind11Targets.cmake
4444
/docs/_build/*
4545
.ipynb_checkpoints/
4646
tests/main.cpp
47+
48+
/Python
49+
/tmp*
50+
.ruby-version
51+
.*cache*/

.pre-commit-config.yaml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,15 +108,6 @@ repos:
108108
- id: rst-directive-colons
109109
- id: rst-inline-touching-normal
110110

111-
# Checks the manifest for missing files (native support)
112-
- repo: https://github.com/mgedmin/check-manifest
113-
rev: "0.50"
114-
hooks:
115-
- id: check-manifest
116-
# This is a slow hook, so only run this if --hook-stage manual is passed
117-
stages: [manual]
118-
additional_dependencies: [cmake, ninja]
119-
120111
# Check for spelling
121112
# Use tools/codespell_ignore_lines_from_errors.py
122113
# to rebuild .codespell-ignore-lines

CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
6565

6666
message(STATUS "CMake ${CMAKE_VERSION}")
6767

68+
if(DEFINED SKBUILD AND DEFINED $ENV{PYBIND11_GLOBAL_PREFIX})
69+
message(
70+
FATAL_ERROR
71+
"PYBIND11_GLOBAL_PREFIX is not supported, use nox -s build_global or a pybind11-global SDist instead."
72+
)
73+
endif()
74+
6875
if(CMAKE_CXX_STANDARD)
6976
set(CMAKE_CXX_EXTENSIONS OFF)
7077
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@@ -251,6 +258,9 @@ elseif(USE_PYTHON_INCLUDE_DIR AND DEFINED PYTHON_INCLUDE_DIR)
251258
endif()
252259

253260
if(PYBIND11_INSTALL)
261+
if(DEFINED SKBUILD_PROJECT_NAME AND SKBUILD_PROJECT_NAME STREQUAL "pybind11_global")
262+
install(DIRECTORY ${pybind11_INCLUDE_DIR}/pybind11 DESTINATION "${SKBUILD_HEADERS_DIR}")
263+
endif()
254264
install(DIRECTORY ${pybind11_INCLUDE_DIR}/pybind11 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
255265
set(PYBIND11_CMAKECONFIG_INSTALL_DIR
256266
"${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}"

MANIFEST.in

Lines changed: 0 additions & 6 deletions
This file was deleted.

docs/conf.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,10 @@
6969
# built documents.
7070

7171
# Read the listed version
72-
with open("../pybind11/_version.py") as f:
73-
code = compile(f.read(), "../pybind11/_version.py", "exec")
74-
loc = {}
72+
version_file = DIR.parent / "pybind11/_version.py"
73+
with version_file.open(encoding="utf-8") as f:
74+
code = compile(f.read(), version_file, "exec")
75+
loc = {"__file__": str(version_file)}
7576
exec(code, loc)
7677

7778
# The full version, including alpha/beta/rc tags.

noxfile.py

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,24 @@
77
from __future__ import annotations
88

99
import argparse
10+
import contextlib
11+
import os
12+
import re
13+
from pathlib import Path
14+
from typing import TYPE_CHECKING
15+
16+
if TYPE_CHECKING:
17+
from collections.abc import Generator
1018

1119
import nox
1220

1321
nox.needs_version = ">=2025.2.9"
1422
nox.options.default_venv_backend = "uv|virtualenv"
1523

24+
MARKER_PATTERN = re.compile(
25+
r"# not-in-global-start.*?# not-in-global-end\n?", re.DOTALL
26+
)
27+
1628

1729
@nox.session(reuse_venv=True)
1830
def lint(session: nox.Session) -> None:
@@ -99,13 +111,48 @@ def make_changelog(session: nox.Session) -> None:
99111
@nox.session(reuse_venv=True, default=False)
100112
def build(session: nox.Session) -> None:
101113
"""
102-
Build SDists and wheels.
114+
Build SDist and wheel.
103115
"""
104116

105117
session.install("build")
106118
session.log("Building normal files")
107119
session.run("python", "-m", "build", *session.posargs)
108-
session.log("Building pybind11-global files (PYBIND11_GLOBAL_SDIST=1)")
109-
session.run(
110-
"python", "-m", "build", *session.posargs, env={"PYBIND11_GLOBAL_SDIST": "1"}
111-
)
120+
121+
122+
@contextlib.contextmanager
123+
def preserve_file(filename: Path) -> Generator[str, None, None]:
124+
old_stat = filename.stat()
125+
old_file = filename.read_text(encoding="utf-8")
126+
try:
127+
yield old_file
128+
finally:
129+
filename.write_text(old_file, encoding="utf-8")
130+
os.utime(filename, (old_stat.st_atime, old_stat.st_mtime))
131+
132+
133+
@nox.session(reuse_venv=True)
134+
def build_global(session: nox.Session) -> None:
135+
"""
136+
Build global SDist and wheel.
137+
"""
138+
139+
installer = ["--installer=uv"] if session.venv_backend == "uv" else []
140+
session.install("build")
141+
session.log("Building pybind11-global files")
142+
pyproject = Path("pyproject.toml")
143+
with preserve_file(pyproject) as txt:
144+
new_txt = txt.replace('name = "pybind11"', 'name = "pybind11-global"')
145+
assert txt != new_txt
146+
newer_txt = MARKER_PATTERN.sub("", new_txt)
147+
assert new_txt != newer_txt
148+
149+
pyproject.write_text(newer_txt, encoding="utf-8")
150+
session.run(
151+
"python",
152+
"-m",
153+
"build",
154+
*installer,
155+
"-Cskbuild.wheel.install-dir=/data",
156+
"-Cskbuild.experimental=true",
157+
*session.posargs,
158+
)

pybind11/_version.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,28 @@
1+
# This file will be replaced in the wheel with a hard-coded version. This only
2+
# exists to allow running directly from source without installing (not
3+
# recommended, but supported).
4+
15
from __future__ import annotations
26

7+
import re
8+
from pathlib import Path
9+
10+
DIR = Path(__file__).parent.resolve()
11+
12+
input_file = DIR.parent / "include/pybind11/detail/common.h"
13+
regex = re.compile(
14+
r"""
15+
\#define \s+ PYBIND11_VERSION_MAJOR \s+ (?P<major>\d+) .*?
16+
\#define \s+ PYBIND11_VERSION_MINOR \s+ (?P<minor>\d+) .*?
17+
\#define \s+ PYBIND11_VERSION_PATCH \s+ (?P<patch>\S+)
18+
""",
19+
re.MULTILINE | re.DOTALL | re.VERBOSE,
20+
)
21+
22+
match = regex.search(input_file.read_text(encoding="utf-8"))
23+
assert match, "Unable to find version in pybind11/detail/common.h"
24+
__version__ = "{major}.{minor}.{patch}".format(**match.groupdict())
25+
326

427
def _to_int(s: str) -> int | str:
528
try:
@@ -8,5 +31,4 @@ def _to_int(s: str) -> int | str:
831
return s
932

1033

11-
__version__ = "3.0.0.dev1"
1234
version_info = tuple(_to_int(s) for s in __version__.split("."))

pyproject.toml

Lines changed: 92 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,97 @@
11
[build-system]
2-
requires = ["setuptools>=42", "cmake>=3.18", "ninja"]
3-
build-backend = "setuptools.build_meta"
2+
requires = ["scikit-build-core >=0.11.0"]
3+
build-backend = "scikit_build_core.build"
44

5-
6-
[tool.check-manifest]
7-
ignore = [
8-
"tests/**",
9-
"docs/**",
10-
"tools/**",
11-
"include/**",
12-
".*",
13-
"pybind11/include/**",
14-
"pybind11/share/**",
15-
"CMakeLists.txt",
16-
"noxfile.py",
5+
[project]
6+
name = "pybind11"
7+
description = "Seamless operability between C++11 and Python"
8+
authors = [{name = "Wenzel Jakob", email = "[email protected]"}]
9+
license = "BSD-3-Clause"
10+
license-files = ["LICENSE"]
11+
readme = "README.rst"
12+
classifiers = [
13+
"Development Status :: 5 - Production/Stable",
14+
"Intended Audience :: Developers",
15+
"Topic :: Software Development :: Libraries :: Python Modules",
16+
"Topic :: Utilities",
17+
"Programming Language :: C++",
18+
"Programming Language :: Python :: 3 :: Only",
19+
"Programming Language :: Python :: 3.8",
20+
"Programming Language :: Python :: 3.9",
21+
"Programming Language :: Python :: 3.10",
22+
"Programming Language :: Python :: 3.11",
23+
"Programming Language :: Python :: 3.12",
24+
"Programming Language :: Python :: 3.13",
25+
"Programming Language :: Python :: Implementation :: PyPy",
26+
"Programming Language :: Python :: Implementation :: CPython",
27+
"Programming Language :: C++",
28+
"Topic :: Software Development :: Libraries :: Python Modules",
1729
]
30+
keywords = [
31+
"C++11",
32+
"Python bindings",
33+
]
34+
dynamic = ["version"]
35+
requires-python = ">=3.8"
36+
37+
[project.urls]
38+
Homepage = "https://github.com/pybind/pybind11"
39+
Documentation = "https://pybind11.readthedocs.io/"
40+
"Bug Tracker" = "https://github.com/pybind/pybind11/issues"
41+
Discussions = "https://github.com/pybind/pybind11/discussions"
42+
Changelog = "https://pybind11.readthedocs.io/en/latest/changelog.html"
43+
Chat = "https://gitter.im/pybind/Lobby"
44+
45+
# not-in-global-start
46+
[project.optional-dependencies]
47+
global = ["pybind11-global"] # TODO: pin
48+
[project.scripts]
49+
pybind11-config = "pybind11.__main__:main"
50+
51+
[project.entry-points."pipx.run"]
52+
pybind11 = "pybind11.__main__:main"
53+
54+
[project.entry-points.pkg_config]
55+
pybind11 = "pybind11.share.pkgconfig"
56+
57+
[[tool.scikit-build.generate]]
58+
path = "pybind11/_version.py"
59+
template = '''
60+
from __future__ import annotations
61+
62+
63+
def _to_int(s: str) -> int | str:
64+
try:
65+
return int(s)
66+
except ValueError:
67+
return s
68+
69+
70+
__version__ = "$version"
71+
version_info = tuple(_to_int(s) for s in __version__.split("."))
72+
'''
73+
# not-in-global-end
74+
75+
76+
[tool.scikit-build]
77+
wheel.install-dir = "pybind11"
78+
wheel.platlib = false
79+
minimum-version = "build-system.requires"
80+
81+
[tool.scikit-build.cmake.define]
82+
BUILD_TESTING = false
83+
PYBIND11_NOPYTHON = true
84+
prefix_for_pc_file = "${pcfiledir}/../../"
85+
86+
[tool.scikit-build.metadata.version]
87+
provider = "scikit_build_core.metadata.regex"
88+
input = "include/pybind11/detail/common.h"
89+
regex = '''(?sx)
90+
\#define \s+ PYBIND11_VERSION_MAJOR \s+ (?P<major>\d+) .*?
91+
\#define \s+ PYBIND11_VERSION_MINOR \s+ (?P<minor>\d+) .*?
92+
\#define \s+ PYBIND11_VERSION_PATCH \s+ (?P<patch>\S+)
93+
'''
94+
result = "{major}.{minor}.{patch}"
1895

1996

2097
[tool.mypy]
@@ -42,10 +119,10 @@ messages_control.disable = [
42119
"protected-access",
43120
"missing-module-docstring",
44121
"unused-argument", # covered by Ruff ARG
122+
"consider-using-f-string", # triggers in _version.py incorrectly
45123
]
46124

47125
[tool.ruff]
48-
target-version = "py38"
49126
src = ["src"]
50127

51128
[tool.ruff.lint]

setup.cfg

Lines changed: 0 additions & 42 deletions
This file was deleted.

0 commit comments

Comments
 (0)