mirror of
https://github.com/pybind/pybind11.git
synced 2026-03-14 20:27:47 +00:00
chore: use scikit-build-core for the build (#5598)
* chore: use scikit-build-core for the build Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> * fix: support tests job Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> * refactor: use tomlkit instead of manual parsing Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> * tests: add tests for output Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> * chore: remove more unused files Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> * fix: restore global pin Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> * fix: test and fix pinning Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> --------- Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
This commit is contained in:
3
.github/workflows/format.yml
vendored
3
.github/workflows/format.yml
vendored
@@ -32,9 +32,6 @@ jobs:
|
|||||||
- name: Add matchers
|
- name: Add matchers
|
||||||
run: echo "::add-matcher::$GITHUB_WORKSPACE/.github/matchers/pylint.json"
|
run: echo "::add-matcher::$GITHUB_WORKSPACE/.github/matchers/pylint.json"
|
||||||
- uses: pre-commit/action@v3.0.1
|
- uses: pre-commit/action@v3.0.1
|
||||||
with:
|
|
||||||
# Slow hooks are marked with manual - slow is okay here, run them too
|
|
||||||
extra_args: --hook-stage manual --all-files
|
|
||||||
|
|
||||||
clang-tidy:
|
clang-tidy:
|
||||||
# When making changes here, please also review the "Clang-Tidy" section
|
# When making changes here, please also review the "Clang-Tidy" section
|
||||||
|
|||||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -45,3 +45,9 @@ pybind11Targets.cmake
|
|||||||
.ipynb_checkpoints/
|
.ipynb_checkpoints/
|
||||||
tests/main.cpp
|
tests/main.cpp
|
||||||
CMakeUserPresents.json
|
CMakeUserPresents.json
|
||||||
|
|
||||||
|
/Python
|
||||||
|
/tmp*
|
||||||
|
.ruby-version
|
||||||
|
.*cache*/
|
||||||
|
*.lock
|
||||||
|
|||||||
@@ -108,15 +108,6 @@ repos:
|
|||||||
- id: rst-directive-colons
|
- id: rst-directive-colons
|
||||||
- id: rst-inline-touching-normal
|
- id: rst-inline-touching-normal
|
||||||
|
|
||||||
# Checks the manifest for missing files (native support)
|
|
||||||
- repo: https://github.com/mgedmin/check-manifest
|
|
||||||
rev: "0.50"
|
|
||||||
hooks:
|
|
||||||
- id: check-manifest
|
|
||||||
# This is a slow hook, so only run this if --hook-stage manual is passed
|
|
||||||
stages: [manual]
|
|
||||||
additional_dependencies: [cmake, ninja]
|
|
||||||
|
|
||||||
# Check for spelling
|
# Check for spelling
|
||||||
# Use tools/codespell_ignore_lines_from_errors.py
|
# Use tools/codespell_ignore_lines_from_errors.py
|
||||||
# to rebuild .codespell-ignore-lines
|
# to rebuild .codespell-ignore-lines
|
||||||
|
|||||||
@@ -65,6 +65,13 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
|||||||
|
|
||||||
message(STATUS "CMake ${CMAKE_VERSION}")
|
message(STATUS "CMake ${CMAKE_VERSION}")
|
||||||
|
|
||||||
|
if(DEFINED SKBUILD AND DEFINED $ENV{PYBIND11_GLOBAL_PREFIX})
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"PYBIND11_GLOBAL_PREFIX is not supported, use nox -s build_global or a pybind11-global SDist instead."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CMAKE_CXX_STANDARD)
|
if(CMAKE_CXX_STANDARD)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
@@ -295,6 +302,9 @@ elseif(USE_PYTHON_INCLUDE_DIR AND DEFINED PYTHON_INCLUDE_DIR)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(PYBIND11_INSTALL)
|
if(PYBIND11_INSTALL)
|
||||||
|
if(DEFINED SKBUILD_PROJECT_NAME AND SKBUILD_PROJECT_NAME STREQUAL "pybind11_global")
|
||||||
|
install(DIRECTORY ${pybind11_INCLUDE_DIR}/pybind11 DESTINATION "${SKBUILD_HEADERS_DIR}")
|
||||||
|
endif()
|
||||||
install(DIRECTORY ${pybind11_INCLUDE_DIR}/pybind11 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
install(DIRECTORY ${pybind11_INCLUDE_DIR}/pybind11 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||||
set(PYBIND11_CMAKECONFIG_INSTALL_DIR
|
set(PYBIND11_CMAKECONFIG_INSTALL_DIR
|
||||||
"${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}"
|
"${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}"
|
||||||
@@ -361,6 +371,17 @@ if(PYBIND11_INSTALL)
|
|||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pybind11.pc"
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pybind11.pc"
|
||||||
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig/")
|
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig/")
|
||||||
|
|
||||||
|
# When building a wheel, include __init__.py's for modules
|
||||||
|
# (see https://github.com/pybind/pybind11/pull/5552)
|
||||||
|
if(DEFINED SKBUILD_PROJECT_NAME AND SKBUILD_PROJECT_NAME STREQUAL "pybind11")
|
||||||
|
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/empty")
|
||||||
|
file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/empty/__init__.py")
|
||||||
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/empty/__init__.py"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/")
|
||||||
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/empty/__init__.py"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig/")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Uninstall target
|
# Uninstall target
|
||||||
if(PYBIND11_MASTER_PROJECT)
|
if(PYBIND11_MASTER_PROJECT)
|
||||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tools/cmake_uninstall.cmake.in"
|
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tools/cmake_uninstall.cmake.in"
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
prune tests
|
|
||||||
recursive-include pybind11/include/pybind11 *.h
|
|
||||||
recursive-include pybind11 *.py
|
|
||||||
recursive-include pybind11 py.typed
|
|
||||||
include pybind11/share/cmake/pybind11/*.cmake
|
|
||||||
include LICENSE README.rst SECURITY.md pyproject.toml setup.py setup.cfg
|
|
||||||
@@ -69,9 +69,10 @@ author = "Wenzel Jakob"
|
|||||||
# built documents.
|
# built documents.
|
||||||
|
|
||||||
# Read the listed version
|
# Read the listed version
|
||||||
with open("../pybind11/_version.py") as f:
|
version_file = DIR.parent / "pybind11/_version.py"
|
||||||
code = compile(f.read(), "../pybind11/_version.py", "exec")
|
with version_file.open(encoding="utf-8") as f:
|
||||||
loc = {}
|
code = compile(f.read(), version_file, "exec")
|
||||||
|
loc = {"__file__": str(version_file)}
|
||||||
exec(code, loc)
|
exec(code, loc)
|
||||||
|
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
|
|||||||
50
noxfile.py
50
noxfile.py
@@ -7,6 +7,13 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import contextlib
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from collections.abc import Generator
|
||||||
|
|
||||||
import nox
|
import nox
|
||||||
|
|
||||||
@@ -99,13 +106,46 @@ def make_changelog(session: nox.Session) -> None:
|
|||||||
@nox.session(reuse_venv=True, default=False)
|
@nox.session(reuse_venv=True, default=False)
|
||||||
def build(session: nox.Session) -> None:
|
def build(session: nox.Session) -> None:
|
||||||
"""
|
"""
|
||||||
Build SDists and wheels.
|
Build SDist and wheel.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
session.install("build")
|
session.install("build")
|
||||||
session.log("Building normal files")
|
session.log("Building normal files")
|
||||||
session.run("python", "-m", "build", *session.posargs)
|
session.run("python", "-m", "build", *session.posargs)
|
||||||
session.log("Building pybind11-global files (PYBIND11_GLOBAL_SDIST=1)")
|
|
||||||
session.run(
|
|
||||||
"python", "-m", "build", *session.posargs, env={"PYBIND11_GLOBAL_SDIST": "1"}
|
@contextlib.contextmanager
|
||||||
)
|
def preserve_file(filename: Path) -> Generator[str, None, None]:
|
||||||
|
"""
|
||||||
|
Causes a file to be stored and preserved when the context manager exits.
|
||||||
|
"""
|
||||||
|
old_stat = filename.stat()
|
||||||
|
old_file = filename.read_text(encoding="utf-8")
|
||||||
|
try:
|
||||||
|
yield old_file
|
||||||
|
finally:
|
||||||
|
filename.write_text(old_file, encoding="utf-8")
|
||||||
|
os.utime(filename, (old_stat.st_atime, old_stat.st_mtime))
|
||||||
|
|
||||||
|
|
||||||
|
@nox.session(reuse_venv=True)
|
||||||
|
def build_global(session: nox.Session) -> None:
|
||||||
|
"""
|
||||||
|
Build global SDist and wheel.
|
||||||
|
"""
|
||||||
|
|
||||||
|
installer = ["--installer=uv"] if session.venv_backend == "uv" else []
|
||||||
|
session.install("build", "tomlkit")
|
||||||
|
session.log("Building pybind11-global files")
|
||||||
|
pyproject = Path("pyproject.toml")
|
||||||
|
with preserve_file(pyproject):
|
||||||
|
newer_txt = session.run("python", "tools/make_global.py", silent=True)
|
||||||
|
assert isinstance(newer_txt, str)
|
||||||
|
pyproject.write_text(newer_txt, encoding="utf-8")
|
||||||
|
session.run(
|
||||||
|
"python",
|
||||||
|
"-m",
|
||||||
|
"build",
|
||||||
|
*installer,
|
||||||
|
*session.posargs,
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,5 +1,28 @@
|
|||||||
|
# This file will be replaced in the wheel with a hard-coded version. This only
|
||||||
|
# exists to allow running directly from source without installing (not
|
||||||
|
# recommended, but supported).
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
DIR = Path(__file__).parent.resolve()
|
||||||
|
|
||||||
|
input_file = DIR.parent / "include/pybind11/detail/common.h"
|
||||||
|
regex = re.compile(
|
||||||
|
r"""
|
||||||
|
\#define \s+ PYBIND11_VERSION_MAJOR \s+ (?P<major>\d+) .*?
|
||||||
|
\#define \s+ PYBIND11_VERSION_MINOR \s+ (?P<minor>\d+) .*?
|
||||||
|
\#define \s+ PYBIND11_VERSION_PATCH \s+ (?P<patch>\S+)
|
||||||
|
""",
|
||||||
|
re.MULTILINE | re.DOTALL | re.VERBOSE,
|
||||||
|
)
|
||||||
|
|
||||||
|
match = regex.search(input_file.read_text(encoding="utf-8"))
|
||||||
|
assert match, "Unable to find version in pybind11/detail/common.h"
|
||||||
|
__version__ = "{major}.{minor}.{patch}".format(**match.groupdict())
|
||||||
|
|
||||||
|
|
||||||
def _to_int(s: str) -> int | str:
|
def _to_int(s: str) -> int | str:
|
||||||
try:
|
try:
|
||||||
@@ -8,5 +31,4 @@ def _to_int(s: str) -> int | str:
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
__version__ = "3.0.0.dev1"
|
|
||||||
version_info = tuple(_to_int(s) for s in __version__.split("."))
|
version_info = tuple(_to_int(s) for s in __version__.split("."))
|
||||||
|
|||||||
129
pyproject.toml
129
pyproject.toml
@@ -1,25 +1,118 @@
|
|||||||
[build-system]
|
[build-system]
|
||||||
requires = ["setuptools>=42", "cmake>=3.18", "ninja"]
|
requires = ["scikit-build-core >=0.11.2"]
|
||||||
build-backend = "setuptools.build_meta"
|
build-backend = "scikit_build_core.build"
|
||||||
|
|
||||||
|
[project]
|
||||||
[tool.check-manifest]
|
name = "pybind11"
|
||||||
ignore = [
|
description = "Seamless operability between C++11 and Python"
|
||||||
"tests/**",
|
authors = [{name = "Wenzel Jakob", email = "wenzel.jakob@epfl.ch"}]
|
||||||
"docs/**",
|
license = "BSD-3-Clause"
|
||||||
"tools/**",
|
license-files = ["LICENSE"]
|
||||||
"include/**",
|
readme = "README.rst"
|
||||||
".*",
|
classifiers = [
|
||||||
"pybind11/include/**",
|
"Development Status :: 5 - Production/Stable",
|
||||||
"pybind11/share/**",
|
"Intended Audience :: Developers",
|
||||||
"CMakeLists.txt",
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||||
"CMakePresets.json",
|
"Topic :: Utilities",
|
||||||
"noxfile.py",
|
"Programming Language :: C++",
|
||||||
|
"Programming Language :: Python :: 3 :: Only",
|
||||||
|
"Programming Language :: Python :: 3.8",
|
||||||
|
"Programming Language :: Python :: 3.9",
|
||||||
|
"Programming Language :: Python :: 3.10",
|
||||||
|
"Programming Language :: Python :: 3.11",
|
||||||
|
"Programming Language :: Python :: 3.12",
|
||||||
|
"Programming Language :: Python :: 3.13",
|
||||||
|
"Programming Language :: Python :: Implementation :: PyPy",
|
||||||
|
"Programming Language :: Python :: Implementation :: CPython",
|
||||||
|
"Programming Language :: C++",
|
||||||
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||||
]
|
]
|
||||||
|
keywords = [
|
||||||
|
"C++11",
|
||||||
|
"Python bindings",
|
||||||
|
]
|
||||||
|
dynamic = ["version", "optional-dependencies"]
|
||||||
|
requires-python = ">=3.8"
|
||||||
|
|
||||||
|
[project.urls]
|
||||||
|
Homepage = "https://github.com/pybind/pybind11"
|
||||||
|
Documentation = "https://pybind11.readthedocs.io/"
|
||||||
|
"Bug Tracker" = "https://github.com/pybind/pybind11/issues"
|
||||||
|
Discussions = "https://github.com/pybind/pybind11/discussions"
|
||||||
|
Changelog = "https://pybind11.readthedocs.io/en/latest/changelog.html"
|
||||||
|
Chat = "https://gitter.im/pybind/Lobby"
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
pybind11-config = "pybind11.__main__:main"
|
||||||
|
|
||||||
|
[project.entry-points."pipx.run"]
|
||||||
|
pybind11 = "pybind11.__main__:main"
|
||||||
|
|
||||||
|
[project.entry-points.pkg_config]
|
||||||
|
pybind11 = "pybind11.share.pkgconfig"
|
||||||
|
|
||||||
|
|
||||||
|
[dependency-groups]
|
||||||
|
test = [
|
||||||
|
"pytest",
|
||||||
|
"build",
|
||||||
|
"tomlkit",
|
||||||
|
]
|
||||||
|
dev = [{ include-group = "test" }]
|
||||||
|
|
||||||
|
|
||||||
|
[tool.scikit-build]
|
||||||
|
minimum-version = "build-system.requires"
|
||||||
|
sdist.exclude = [
|
||||||
|
"/docs/**",
|
||||||
|
"/.**",
|
||||||
|
]
|
||||||
|
wheel.install-dir = "pybind11"
|
||||||
|
wheel.platlib = false
|
||||||
|
|
||||||
|
[tool.scikit-build.cmake.define]
|
||||||
|
BUILD_TESTING = false
|
||||||
|
PYBIND11_NOPYTHON = true
|
||||||
|
prefix_for_pc_file = "${pcfiledir}/../../"
|
||||||
|
|
||||||
|
[tool.scikit-build.metadata.version]
|
||||||
|
provider = "scikit_build_core.metadata.regex"
|
||||||
|
input = "include/pybind11/detail/common.h"
|
||||||
|
regex = '''(?sx)
|
||||||
|
\#define \s+ PYBIND11_VERSION_MAJOR \s+ (?P<major>\d+) .*?
|
||||||
|
\#define \s+ PYBIND11_VERSION_MINOR \s+ (?P<minor>\d+) .*?
|
||||||
|
\#define \s+ PYBIND11_VERSION_PATCH \s+ (?P<patch>\S+)
|
||||||
|
'''
|
||||||
|
result = "{major}.{minor}.{patch}"
|
||||||
|
|
||||||
|
[tool.scikit-build.metadata.optional-dependencies]
|
||||||
|
provider = "scikit_build_core.metadata.template"
|
||||||
|
result = { global = ["pybind11-global=={project[version]}"]}
|
||||||
|
|
||||||
|
[[tool.scikit-build.generate]]
|
||||||
|
path = "pybind11/_version.py"
|
||||||
|
template = '''
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|
||||||
|
def _to_int(s: str) -> int | str:
|
||||||
|
try:
|
||||||
|
return int(s)
|
||||||
|
except ValueError:
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
__version__ = "$version"
|
||||||
|
version_info = tuple(_to_int(s) for s in __version__.split("."))
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
# Can't use tool.uv.sources with requirements.txt
|
|
||||||
[tool.uv]
|
[tool.uv]
|
||||||
|
# Can't use tool.uv.sources with requirements.txt
|
||||||
index-strategy = "unsafe-best-match"
|
index-strategy = "unsafe-best-match"
|
||||||
|
# This extra confuses uv
|
||||||
|
override-dependencies = ["pybind11-global"]
|
||||||
|
|
||||||
|
|
||||||
[tool.mypy]
|
[tool.mypy]
|
||||||
files = ["pybind11"]
|
files = ["pybind11"]
|
||||||
@@ -29,7 +122,7 @@ enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
|
|||||||
warn_unreachable = true
|
warn_unreachable = true
|
||||||
|
|
||||||
[[tool.mypy.overrides]]
|
[[tool.mypy.overrides]]
|
||||||
module = ["ghapi.*"]
|
module = ["ghapi.*", "tomlkit"] # tomlkit has types, but not very helpful
|
||||||
ignore_missing_imports = true
|
ignore_missing_imports = true
|
||||||
|
|
||||||
|
|
||||||
@@ -46,10 +139,10 @@ messages_control.disable = [
|
|||||||
"protected-access",
|
"protected-access",
|
||||||
"missing-module-docstring",
|
"missing-module-docstring",
|
||||||
"unused-argument", # covered by Ruff ARG
|
"unused-argument", # covered by Ruff ARG
|
||||||
|
"consider-using-f-string", # triggers in _version.py incorrectly
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
target-version = "py38"
|
|
||||||
src = ["src"]
|
src = ["src"]
|
||||||
|
|
||||||
[tool.ruff.lint]
|
[tool.ruff.lint]
|
||||||
|
|||||||
42
setup.cfg
42
setup.cfg
@@ -1,42 +0,0 @@
|
|||||||
[metadata]
|
|
||||||
long_description = file: README.rst
|
|
||||||
long_description_content_type = text/x-rst
|
|
||||||
description = Seamless operability between C++11 and Python
|
|
||||||
author = Wenzel Jakob
|
|
||||||
author_email = wenzel.jakob@epfl.ch
|
|
||||||
url = https://github.com/pybind/pybind11
|
|
||||||
license = BSD
|
|
||||||
|
|
||||||
classifiers =
|
|
||||||
Development Status :: 5 - Production/Stable
|
|
||||||
Intended Audience :: Developers
|
|
||||||
Topic :: Software Development :: Libraries :: Python Modules
|
|
||||||
Topic :: Utilities
|
|
||||||
Programming Language :: C++
|
|
||||||
Programming Language :: Python :: 3 :: Only
|
|
||||||
Programming Language :: Python :: 3.8
|
|
||||||
Programming Language :: Python :: 3.9
|
|
||||||
Programming Language :: Python :: 3.10
|
|
||||||
Programming Language :: Python :: 3.11
|
|
||||||
Programming Language :: Python :: 3.12
|
|
||||||
Programming Language :: Python :: 3.13
|
|
||||||
License :: OSI Approved :: BSD License
|
|
||||||
Programming Language :: Python :: Implementation :: PyPy
|
|
||||||
Programming Language :: Python :: Implementation :: CPython
|
|
||||||
Programming Language :: C++
|
|
||||||
Topic :: Software Development :: Libraries :: Python Modules
|
|
||||||
|
|
||||||
keywords =
|
|
||||||
C++11
|
|
||||||
Python bindings
|
|
||||||
|
|
||||||
project_urls =
|
|
||||||
Documentation = https://pybind11.readthedocs.io/
|
|
||||||
Bug Tracker = https://github.com/pybind/pybind11/issues
|
|
||||||
Discussions = https://github.com/pybind/pybind11/discussions
|
|
||||||
Changelog = https://pybind11.readthedocs.io/en/latest/changelog.html
|
|
||||||
Chat = https://gitter.im/pybind/Lobby
|
|
||||||
|
|
||||||
[options]
|
|
||||||
python_requires = >=3.8
|
|
||||||
zip_safe = False
|
|
||||||
153
setup.py
153
setup.py
@@ -1,153 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# Setup script for PyPI; use CMakeFile.txt to build extension modules
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import contextlib
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import shutil
|
|
||||||
import string
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
from collections.abc import Generator
|
|
||||||
from pathlib import Path
|
|
||||||
from tempfile import TemporaryDirectory
|
|
||||||
|
|
||||||
import setuptools.command.sdist
|
|
||||||
|
|
||||||
DIR = Path(__file__).parent.absolute()
|
|
||||||
VERSION_REGEX = re.compile(
|
|
||||||
r"^\s*#\s*define\s+PYBIND11_VERSION_([A-Z]+)\s+(.*)$", re.MULTILINE
|
|
||||||
)
|
|
||||||
VERSION_FILE = Path("pybind11/_version.py")
|
|
||||||
COMMON_FILE = Path("include/pybind11/detail/common.h")
|
|
||||||
|
|
||||||
|
|
||||||
def build_expected_version_hex(matches: dict[str, str]) -> str:
|
|
||||||
patch_level_serial = matches["PATCH"]
|
|
||||||
serial = None
|
|
||||||
major = int(matches["MAJOR"])
|
|
||||||
minor = int(matches["MINOR"])
|
|
||||||
flds = patch_level_serial.split(".")
|
|
||||||
if flds:
|
|
||||||
patch = int(flds[0])
|
|
||||||
if len(flds) == 1:
|
|
||||||
level = "0"
|
|
||||||
serial = 0
|
|
||||||
elif len(flds) == 2:
|
|
||||||
level_serial = flds[1]
|
|
||||||
for level in ("a", "b", "c", "dev"):
|
|
||||||
if level_serial.startswith(level):
|
|
||||||
serial = int(level_serial[len(level) :])
|
|
||||||
break
|
|
||||||
if serial is None:
|
|
||||||
msg = f'Invalid PYBIND11_VERSION_PATCH: "{patch_level_serial}"'
|
|
||||||
raise RuntimeError(msg)
|
|
||||||
version_hex_str = f"{major:02x}{minor:02x}{patch:02x}{level[:1]}{serial:x}"
|
|
||||||
return f"0x{version_hex_str.upper()}"
|
|
||||||
|
|
||||||
|
|
||||||
# PYBIND11_GLOBAL_SDIST will build a different sdist, with the python-headers
|
|
||||||
# files, and the sys.prefix files (CMake and headers).
|
|
||||||
|
|
||||||
global_sdist = os.environ.get("PYBIND11_GLOBAL_SDIST")
|
|
||||||
|
|
||||||
setup_py = Path(
|
|
||||||
"tools/setup_global.py.in" if global_sdist else "tools/setup_main.py.in"
|
|
||||||
)
|
|
||||||
extra_cmd = 'cmdclass["sdist"] = SDist\n'
|
|
||||||
|
|
||||||
to_src = (
|
|
||||||
(Path("pyproject.toml"), Path("tools/pyproject.toml")),
|
|
||||||
(Path("setup.py"), setup_py),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Read the listed version
|
|
||||||
loc: dict[str, str] = {}
|
|
||||||
code = compile(VERSION_FILE.read_text(encoding="utf-8"), "pybind11/_version.py", "exec")
|
|
||||||
exec(code, loc)
|
|
||||||
version = loc["__version__"]
|
|
||||||
|
|
||||||
# Verify that the version matches the one in C++
|
|
||||||
matches = dict(VERSION_REGEX.findall(COMMON_FILE.read_text(encoding="utf8")))
|
|
||||||
cpp_version = "{MAJOR}.{MINOR}.{PATCH}".format(**matches)
|
|
||||||
if version != cpp_version:
|
|
||||||
msg = f"Python version {version} does not match C++ version {cpp_version}!"
|
|
||||||
raise RuntimeError(msg)
|
|
||||||
|
|
||||||
version_hex = matches.get("HEX", "MISSING")
|
|
||||||
exp_version_hex = build_expected_version_hex(matches)
|
|
||||||
if version_hex != exp_version_hex:
|
|
||||||
msg = f"PYBIND11_VERSION_HEX {version_hex} does not match expected value {exp_version_hex}!"
|
|
||||||
raise RuntimeError(msg)
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: use literals & overload (typing extensions or Python 3.8)
|
|
||||||
def get_and_replace(filename: Path, binary: bool = False, **opts: str) -> bytes | str:
|
|
||||||
if binary:
|
|
||||||
contents = filename.read_bytes()
|
|
||||||
return string.Template(contents.decode()).substitute(opts).encode()
|
|
||||||
|
|
||||||
return string.Template(filename.read_text()).substitute(opts)
|
|
||||||
|
|
||||||
|
|
||||||
# Use our input files instead when making the SDist (and anything that depends
|
|
||||||
# on it, like a wheel)
|
|
||||||
class SDist(setuptools.command.sdist.sdist):
|
|
||||||
def make_release_tree(self, base_dir: str, files: list[str]) -> None:
|
|
||||||
super().make_release_tree(base_dir, files)
|
|
||||||
|
|
||||||
for to, src in to_src:
|
|
||||||
txt = get_and_replace(src, binary=True, version=version, extra_cmd="")
|
|
||||||
|
|
||||||
dest = Path(base_dir) / to
|
|
||||||
|
|
||||||
# This is normally linked, so unlink before writing!
|
|
||||||
dest.unlink()
|
|
||||||
dest.write_bytes(txt) # type: ignore[arg-type]
|
|
||||||
|
|
||||||
|
|
||||||
# Remove the CMake install directory when done
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def remove_output(*sources: str) -> Generator[None, None, None]:
|
|
||||||
try:
|
|
||||||
yield
|
|
||||||
finally:
|
|
||||||
for src in sources:
|
|
||||||
shutil.rmtree(src)
|
|
||||||
|
|
||||||
|
|
||||||
with remove_output("pybind11/include", "pybind11/share"):
|
|
||||||
# Generate the files if they are not present.
|
|
||||||
with TemporaryDirectory() as tmpdir:
|
|
||||||
cmd = ["cmake", "-S", ".", "-B", tmpdir] + [
|
|
||||||
"-DCMAKE_INSTALL_PREFIX=pybind11",
|
|
||||||
"-DBUILD_TESTING=OFF",
|
|
||||||
"-DPYBIND11_NOPYTHON=ON",
|
|
||||||
"-Dprefix_for_pc_file=${pcfiledir}/../../",
|
|
||||||
]
|
|
||||||
if "CMAKE_ARGS" in os.environ:
|
|
||||||
fcommand = [
|
|
||||||
c
|
|
||||||
for c in os.environ["CMAKE_ARGS"].split()
|
|
||||||
if "DCMAKE_INSTALL_PREFIX" not in c
|
|
||||||
]
|
|
||||||
cmd += fcommand
|
|
||||||
subprocess.run(cmd, check=True, cwd=DIR, stdout=sys.stdout, stderr=sys.stderr)
|
|
||||||
subprocess.run(
|
|
||||||
["cmake", "--install", tmpdir],
|
|
||||||
check=True,
|
|
||||||
cwd=DIR,
|
|
||||||
stdout=sys.stdout,
|
|
||||||
stderr=sys.stderr,
|
|
||||||
)
|
|
||||||
|
|
||||||
# pkgconf-pypi needs pybind11/share/pkgconfig to be importable
|
|
||||||
Path("pybind11/share/__init__.py").touch()
|
|
||||||
Path("pybind11/share/pkgconfig/__init__.py").touch()
|
|
||||||
|
|
||||||
txt = get_and_replace(setup_py, version=version, extra_cmd=extra_cmd)
|
|
||||||
code = compile(txt, setup_py, "exec")
|
|
||||||
exec(code, {"SDist": SDist})
|
|
||||||
@@ -3,16 +3,23 @@ from __future__ import annotations
|
|||||||
import contextlib
|
import contextlib
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import string
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tarfile
|
import tarfile
|
||||||
import zipfile
|
import zipfile
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Generator
|
||||||
|
|
||||||
# These tests must be run explicitly
|
# These tests must be run explicitly
|
||||||
|
|
||||||
DIR = os.path.abspath(os.path.dirname(__file__))
|
DIR = Path(__file__).parent.resolve()
|
||||||
MAIN_DIR = os.path.dirname(os.path.dirname(DIR))
|
MAIN_DIR = DIR.parent.parent
|
||||||
|
|
||||||
|
|
||||||
|
# Newer pytest has global path setting, but keeping old pytest for now
|
||||||
|
sys.path.append(str(MAIN_DIR / "tools"))
|
||||||
|
|
||||||
|
from make_global import get_global # noqa: E402
|
||||||
|
|
||||||
HAS_UV = shutil.which("uv") is not None
|
HAS_UV = shutil.which("uv") is not None
|
||||||
UV_ARGS = ["--installer=uv"] if HAS_UV else []
|
UV_ARGS = ["--installer=uv"] if HAS_UV else []
|
||||||
@@ -120,44 +127,44 @@ py_files = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
headers = main_headers | conduit_headers | detail_headers | eigen_headers | stl_headers
|
headers = main_headers | conduit_headers | detail_headers | eigen_headers | stl_headers
|
||||||
src_files = headers | cmake_files | pkgconfig_files
|
generated_files = cmake_files | pkgconfig_files
|
||||||
all_files = src_files | py_files
|
all_files = headers | generated_files | py_files
|
||||||
|
|
||||||
|
|
||||||
sdist_files = {
|
sdist_files = {
|
||||||
"pybind11",
|
|
||||||
"pybind11/include",
|
|
||||||
"pybind11/include/pybind11",
|
|
||||||
"pybind11/include/pybind11/conduit",
|
|
||||||
"pybind11/include/pybind11/detail",
|
|
||||||
"pybind11/include/pybind11/eigen",
|
|
||||||
"pybind11/include/pybind11/stl",
|
|
||||||
"pybind11/share",
|
|
||||||
"pybind11/share/cmake",
|
|
||||||
"pybind11/share/cmake/pybind11",
|
|
||||||
"pybind11/share/pkgconfig",
|
|
||||||
"pyproject.toml",
|
"pyproject.toml",
|
||||||
"setup.cfg",
|
|
||||||
"setup.py",
|
|
||||||
"LICENSE",
|
"LICENSE",
|
||||||
"MANIFEST.in",
|
|
||||||
"README.rst",
|
"README.rst",
|
||||||
"PKG-INFO",
|
"PKG-INFO",
|
||||||
"SECURITY.md",
|
"SECURITY.md",
|
||||||
}
|
}
|
||||||
|
|
||||||
local_sdist_files = {
|
|
||||||
".egg-info",
|
@contextlib.contextmanager
|
||||||
".egg-info/PKG-INFO",
|
def preserve_file(filename: Path) -> Generator[str, None, None]:
|
||||||
".egg-info/SOURCES.txt",
|
old_stat = filename.stat()
|
||||||
".egg-info/dependency_links.txt",
|
old_file = filename.read_text(encoding="utf-8")
|
||||||
".egg-info/not-zip-safe",
|
try:
|
||||||
".egg-info/top_level.txt",
|
yield old_file
|
||||||
}
|
finally:
|
||||||
|
filename.write_text(old_file, encoding="utf-8")
|
||||||
|
os.utime(filename, (old_stat.st_atime, old_stat.st_mtime))
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def build_global() -> Generator[None, None, None]:
|
||||||
|
"""
|
||||||
|
Build global SDist and wheel.
|
||||||
|
"""
|
||||||
|
|
||||||
|
pyproject = MAIN_DIR / "pyproject.toml"
|
||||||
|
with preserve_file(pyproject):
|
||||||
|
newer_txt = get_global()
|
||||||
|
pyproject.write_text(newer_txt, encoding="utf-8")
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
def read_tz_file(tar: tarfile.TarFile, name: str) -> bytes:
|
def read_tz_file(tar: tarfile.TarFile, name: str) -> bytes:
|
||||||
start = tar.getnames()[0] + "/"
|
start = tar.getnames()[0].split("/")[0] + "/"
|
||||||
inner_file = tar.extractfile(tar.getmember(f"{start}{name}"))
|
inner_file = tar.extractfile(tar.getmember(f"{start}{name}"))
|
||||||
assert inner_file
|
assert inner_file
|
||||||
with contextlib.closing(inner_file) as f:
|
with contextlib.closing(inner_file) as f:
|
||||||
@@ -177,95 +184,58 @@ def test_build_sdist(monkeypatch, tmpdir):
|
|||||||
)
|
)
|
||||||
|
|
||||||
(sdist,) = tmpdir.visit("*.tar.gz")
|
(sdist,) = tmpdir.visit("*.tar.gz")
|
||||||
|
version = sdist.basename.split("-")[1][:-7]
|
||||||
|
|
||||||
with tarfile.open(str(sdist), "r:gz") as tar:
|
with tarfile.open(str(sdist), "r:gz") as tar:
|
||||||
start = tar.getnames()[0] + "/"
|
|
||||||
version = start[9:-1]
|
|
||||||
simpler = {n.split("/", 1)[-1] for n in tar.getnames()[1:]}
|
simpler = {n.split("/", 1)[-1] for n in tar.getnames()[1:]}
|
||||||
|
(pkg_info_path,) = (n for n in simpler if n.endswith("PKG-INFO"))
|
||||||
|
|
||||||
setup_py = read_tz_file(tar, "setup.py")
|
|
||||||
pyproject_toml = read_tz_file(tar, "pyproject.toml")
|
pyproject_toml = read_tz_file(tar, "pyproject.toml")
|
||||||
pkgconfig = read_tz_file(tar, "pybind11/share/pkgconfig/pybind11.pc")
|
pkg_info = read_tz_file(tar, pkg_info_path).decode("utf-8")
|
||||||
cmake_cfg = read_tz_file(
|
|
||||||
tar, "pybind11/share/cmake/pybind11/pybind11Config.cmake"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert (
|
files = headers | sdist_files
|
||||||
'set(pybind11_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/include")'
|
assert files <= simpler
|
||||||
in cmake_cfg.decode("utf-8")
|
|
||||||
)
|
|
||||||
|
|
||||||
files = {f"pybind11/{n}" for n in all_files}
|
assert b'name = "pybind11"' in pyproject_toml
|
||||||
files |= sdist_files
|
assert "License-Expression: BSD-3-Clause" in pkg_info
|
||||||
files |= {f"pybind11{n}" for n in local_sdist_files}
|
assert "License-File: LICENSE" in pkg_info
|
||||||
files.add("pybind11.egg-info/entry_points.txt")
|
assert "Provides-Extra: global" in pkg_info
|
||||||
files.add("pybind11.egg-info/requires.txt")
|
assert f'Requires-Dist: pybind11-global=={version}; extra == "global"' in pkg_info
|
||||||
assert simpler == files
|
|
||||||
|
|
||||||
with open(os.path.join(MAIN_DIR, "tools", "setup_main.py.in"), "rb") as f:
|
|
||||||
contents = (
|
|
||||||
string.Template(f.read().decode("utf-8"))
|
|
||||||
.substitute(version=version, extra_cmd="")
|
|
||||||
.encode("utf-8")
|
|
||||||
)
|
|
||||||
assert setup_py == contents
|
|
||||||
|
|
||||||
with open(os.path.join(MAIN_DIR, "tools", "pyproject.toml"), "rb") as f:
|
|
||||||
contents = f.read()
|
|
||||||
assert pyproject_toml == contents
|
|
||||||
|
|
||||||
simple_version = ".".join(version.split(".")[:3])
|
|
||||||
pkgconfig_expected = PKGCONFIG.format(VERSION=simple_version).encode("utf-8")
|
|
||||||
assert normalize_line_endings(pkgconfig) == pkgconfig_expected
|
|
||||||
|
|
||||||
|
|
||||||
def test_build_global_dist(monkeypatch, tmpdir):
|
def test_build_global_dist(monkeypatch, tmpdir):
|
||||||
monkeypatch.chdir(MAIN_DIR)
|
monkeypatch.chdir(MAIN_DIR)
|
||||||
monkeypatch.setenv("PYBIND11_GLOBAL_SDIST", "1")
|
with build_global():
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
[sys.executable, "-m", "build", "--sdist", "--outdir", str(tmpdir), *UV_ARGS],
|
[
|
||||||
check=True,
|
sys.executable,
|
||||||
)
|
"-m",
|
||||||
|
"build",
|
||||||
|
"--sdist",
|
||||||
|
"--outdir",
|
||||||
|
str(tmpdir),
|
||||||
|
*UV_ARGS,
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
|
||||||
(sdist,) = tmpdir.visit("*.tar.gz")
|
(sdist,) = tmpdir.visit("*.tar.gz")
|
||||||
|
|
||||||
with tarfile.open(str(sdist), "r:gz") as tar:
|
with tarfile.open(str(sdist), "r:gz") as tar:
|
||||||
start = tar.getnames()[0] + "/"
|
|
||||||
version = start[16:-1]
|
|
||||||
simpler = {n.split("/", 1)[-1] for n in tar.getnames()[1:]}
|
simpler = {n.split("/", 1)[-1] for n in tar.getnames()[1:]}
|
||||||
|
(pkg_info_path,) = (n for n in simpler if n.endswith("PKG-INFO"))
|
||||||
|
|
||||||
setup_py = read_tz_file(tar, "setup.py")
|
|
||||||
pyproject_toml = read_tz_file(tar, "pyproject.toml")
|
pyproject_toml = read_tz_file(tar, "pyproject.toml")
|
||||||
pkgconfig = read_tz_file(tar, "pybind11/share/pkgconfig/pybind11.pc")
|
pkg_info = read_tz_file(tar, pkg_info_path).decode("utf-8")
|
||||||
cmake_cfg = read_tz_file(
|
|
||||||
tar, "pybind11/share/cmake/pybind11/pybind11Config.cmake"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert (
|
files = headers | sdist_files
|
||||||
'set(pybind11_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/include")'
|
assert files <= simpler
|
||||||
in cmake_cfg.decode("utf-8")
|
|
||||||
)
|
|
||||||
|
|
||||||
files = {f"pybind11/{n}" for n in all_files}
|
assert b'name = "pybind11-global"' in pyproject_toml
|
||||||
files |= sdist_files
|
assert "License-Expression: BSD-3-Clause" in pkg_info
|
||||||
files |= {f"pybind11_global{n}" for n in local_sdist_files}
|
assert "License-File: LICENSE" in pkg_info
|
||||||
assert simpler == files
|
assert "Provides-Extra: global" not in pkg_info
|
||||||
|
assert 'Requires-Dist: pybind11-global; extra == "global"' not in pkg_info
|
||||||
with open(os.path.join(MAIN_DIR, "tools", "setup_global.py.in"), "rb") as f:
|
|
||||||
contents = (
|
|
||||||
string.Template(f.read().decode())
|
|
||||||
.substitute(version=version, extra_cmd="")
|
|
||||||
.encode("utf-8")
|
|
||||||
)
|
|
||||||
assert setup_py == contents
|
|
||||||
|
|
||||||
with open(os.path.join(MAIN_DIR, "tools", "pyproject.toml"), "rb") as f:
|
|
||||||
contents = f.read()
|
|
||||||
assert pyproject_toml == contents
|
|
||||||
|
|
||||||
simple_version = ".".join(version.split(".")[:3])
|
|
||||||
pkgconfig_expected = PKGCONFIG.format(VERSION=simple_version).encode("utf-8")
|
|
||||||
assert normalize_line_endings(pkgconfig) == pkgconfig_expected
|
|
||||||
|
|
||||||
|
|
||||||
def tests_build_wheel(monkeypatch, tmpdir):
|
def tests_build_wheel(monkeypatch, tmpdir):
|
||||||
@@ -280,47 +250,94 @@ def tests_build_wheel(monkeypatch, tmpdir):
|
|||||||
|
|
||||||
files = {f"pybind11/{n}" for n in all_files}
|
files = {f"pybind11/{n}" for n in all_files}
|
||||||
files |= {
|
files |= {
|
||||||
"dist-info/LICENSE",
|
"dist-info/licenses/LICENSE",
|
||||||
"dist-info/METADATA",
|
"dist-info/METADATA",
|
||||||
"dist-info/RECORD",
|
"dist-info/RECORD",
|
||||||
"dist-info/WHEEL",
|
"dist-info/WHEEL",
|
||||||
"dist-info/entry_points.txt",
|
"dist-info/entry_points.txt",
|
||||||
"dist-info/top_level.txt",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
with zipfile.ZipFile(str(wheel)) as z:
|
with zipfile.ZipFile(str(wheel)) as z:
|
||||||
names = z.namelist()
|
names = z.namelist()
|
||||||
|
share = zipfile.Path(z, "pybind11/share")
|
||||||
|
pkgconfig = (share / "pkgconfig/pybind11.pc").read_text(encoding="utf-8")
|
||||||
|
cmakeconfig = (share / "cmake/pybind11/pybind11Config.cmake").read_text(
|
||||||
|
encoding="utf-8"
|
||||||
|
)
|
||||||
|
(pkg_info_path,) = (n for n in names if n.endswith("METADATA"))
|
||||||
|
pkg_info = zipfile.Path(z, pkg_info_path).read_text(encoding="utf-8")
|
||||||
|
|
||||||
trimmed = {n for n in names if "dist-info" not in n}
|
trimmed = {n for n in names if "dist-info" not in n}
|
||||||
trimmed |= {f"dist-info/{n.split('/', 1)[-1]}" for n in names if "dist-info" in n}
|
trimmed |= {f"dist-info/{n.split('/', 1)[-1]}" for n in names if "dist-info" in n}
|
||||||
|
|
||||||
assert files == trimmed
|
assert files == trimmed
|
||||||
|
|
||||||
|
assert 'set(pybind11_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/include")' in cmakeconfig
|
||||||
|
|
||||||
|
version = wheel.basename.split("-")[1]
|
||||||
|
simple_version = ".".join(version.split(".")[:3])
|
||||||
|
pkgconfig_expected = PKGCONFIG.format(VERSION=simple_version)
|
||||||
|
assert pkgconfig_expected == pkgconfig
|
||||||
|
|
||||||
|
assert "License-Expression: BSD-3-Clause" in pkg_info
|
||||||
|
assert "License-File: LICENSE" in pkg_info
|
||||||
|
assert "Provides-Extra: global" in pkg_info
|
||||||
|
assert f'Requires-Dist: pybind11-global=={version}; extra == "global"' in pkg_info
|
||||||
|
|
||||||
|
|
||||||
def tests_build_global_wheel(monkeypatch, tmpdir):
|
def tests_build_global_wheel(monkeypatch, tmpdir):
|
||||||
monkeypatch.chdir(MAIN_DIR)
|
monkeypatch.chdir(MAIN_DIR)
|
||||||
monkeypatch.setenv("PYBIND11_GLOBAL_SDIST", "1")
|
with build_global():
|
||||||
|
subprocess.run(
|
||||||
subprocess.run(
|
[
|
||||||
[sys.executable, "-m", "build", "--wheel", "--outdir", str(tmpdir), *UV_ARGS],
|
sys.executable,
|
||||||
check=True,
|
"-m",
|
||||||
)
|
"build",
|
||||||
|
"--wheel",
|
||||||
|
"--outdir",
|
||||||
|
str(tmpdir),
|
||||||
|
*UV_ARGS,
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
|
||||||
(wheel,) = tmpdir.visit("*.whl")
|
(wheel,) = tmpdir.visit("*.whl")
|
||||||
|
|
||||||
files = {f"data/data/{n}" for n in src_files}
|
files = {f"data/data/{n}" for n in headers}
|
||||||
files |= {f"data/headers/{n[8:]}" for n in headers}
|
files |= {f"data/headers/{n[8:]}" for n in headers}
|
||||||
|
files |= {f"data/data/{n}" for n in generated_files}
|
||||||
files |= {
|
files |= {
|
||||||
"dist-info/LICENSE",
|
"dist-info/licenses/LICENSE",
|
||||||
"dist-info/METADATA",
|
"dist-info/METADATA",
|
||||||
"dist-info/WHEEL",
|
"dist-info/WHEEL",
|
||||||
"dist-info/top_level.txt",
|
|
||||||
"dist-info/RECORD",
|
"dist-info/RECORD",
|
||||||
}
|
}
|
||||||
|
|
||||||
with zipfile.ZipFile(str(wheel)) as z:
|
with zipfile.ZipFile(str(wheel)) as z:
|
||||||
names = z.namelist()
|
names = z.namelist()
|
||||||
|
beginning = names[0].split("/", 1)[0].rsplit(".", 1)[0]
|
||||||
|
|
||||||
|
share = zipfile.Path(z, f"{beginning}.data/data/share")
|
||||||
|
pkgconfig = (share / "pkgconfig/pybind11.pc").read_text(encoding="utf-8")
|
||||||
|
cmakeconfig = (share / "cmake/pybind11/pybind11Config.cmake").read_text(
|
||||||
|
encoding="utf-8"
|
||||||
|
)
|
||||||
|
|
||||||
|
(pkg_info_path,) = (n for n in names if n.endswith("METADATA"))
|
||||||
|
pkg_info = zipfile.Path(z, pkg_info_path).read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
assert "License-Expression: BSD-3-Clause" in pkg_info
|
||||||
|
assert "License-File: LICENSE" in pkg_info
|
||||||
|
assert "Provides-Extra: global" not in pkg_info
|
||||||
|
assert 'Requires-Dist: pybind11-global; extra == "global"' not in pkg_info
|
||||||
|
|
||||||
beginning = names[0].split("/", 1)[0].rsplit(".", 1)[0]
|
|
||||||
trimmed = {n[len(beginning) + 1 :] for n in names}
|
trimmed = {n[len(beginning) + 1 :] for n in names}
|
||||||
|
|
||||||
assert files == trimmed
|
assert files == trimmed
|
||||||
|
|
||||||
|
assert 'set(pybind11_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/include")' in cmakeconfig
|
||||||
|
|
||||||
|
version = wheel.basename.split("-")[1]
|
||||||
|
simple_version = ".".join(version.split(".")[:3])
|
||||||
|
pkgconfig_expected = PKGCONFIG.format(VERSION=simple_version)
|
||||||
|
assert pkgconfig_expected == pkgconfig
|
||||||
|
|||||||
@@ -15,3 +15,4 @@ scipy~=1.5.4; platform_python_implementation=="CPython" and python_version<"3.10
|
|||||||
scipy~=1.8.0; platform_python_implementation=="CPython" and python_version=="3.10" and sys_platform!="win32"
|
scipy~=1.8.0; platform_python_implementation=="CPython" and python_version=="3.10" and sys_platform!="win32"
|
||||||
scipy~=1.11.1; platform_python_implementation=="CPython" and python_version>="3.11" and python_version<"3.13" and sys_platform!="win32"
|
scipy~=1.11.1; platform_python_implementation=="CPython" and python_version>="3.11" and python_version<"3.13" and sys_platform!="win32"
|
||||||
scipy~=1.15.2; platform_python_implementation=="CPython" and python_version=="3.13" and sys_platform!="win32"
|
scipy~=1.15.2; platform_python_implementation=="CPython" and python_version=="3.13" and sys_platform!="win32"
|
||||||
|
tomlkit
|
||||||
|
|||||||
33
tools/make_global.py
Executable file
33
tools/make_global.py
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/env -S uv run -q
|
||||||
|
|
||||||
|
# /// script
|
||||||
|
# dependencies = ["tomlkit"]
|
||||||
|
# ///
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import tomlkit
|
||||||
|
|
||||||
|
DIR = Path(__file__).parent.resolve()
|
||||||
|
PYPROJECT = DIR.parent / "pyproject.toml"
|
||||||
|
|
||||||
|
|
||||||
|
def get_global() -> str:
|
||||||
|
pyproject = tomlkit.parse(PYPROJECT.read_text())
|
||||||
|
del pyproject["tool"]["scikit-build"]["generate"]
|
||||||
|
del pyproject["project"]["entry-points"]
|
||||||
|
del pyproject["project"]["scripts"]
|
||||||
|
del pyproject["tool"]["scikit-build"]["metadata"]["optional-dependencies"]
|
||||||
|
pyproject["project"]["name"] = "pybind11-global"
|
||||||
|
pyproject["tool"]["scikit-build"]["experimental"] = True
|
||||||
|
pyproject["tool"]["scikit-build"]["wheel"]["install-dir"] = "/data"
|
||||||
|
pyproject["tool"]["scikit-build"]["wheel"]["packages"] = []
|
||||||
|
|
||||||
|
result = tomlkit.dumps(pyproject)
|
||||||
|
assert isinstance(result, str)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(get_global())
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
[build-system]
|
|
||||||
requires = ["setuptools>=42", "wheel"]
|
|
||||||
build-backend = "setuptools.build_meta"
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# Setup script for pybind11-global (in the sdist or in tools/setup_global.py in the repository)
|
|
||||||
# This package is targeted for easy use from CMake.
|
|
||||||
|
|
||||||
import glob
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
|
|
||||||
# Setuptools has to be before distutils
|
|
||||||
from setuptools import setup
|
|
||||||
|
|
||||||
from distutils.command.install_headers import install_headers
|
|
||||||
|
|
||||||
class InstallHeadersNested(install_headers):
|
|
||||||
def run(self):
|
|
||||||
headers = self.distribution.headers or []
|
|
||||||
for header in headers:
|
|
||||||
# Remove pybind11/include/
|
|
||||||
short_header = header.split("/", 2)[-1]
|
|
||||||
|
|
||||||
dst = os.path.join(self.install_dir, os.path.dirname(short_header))
|
|
||||||
self.mkpath(dst)
|
|
||||||
(out, _) = self.copy_file(header, dst)
|
|
||||||
self.outfiles.append(out)
|
|
||||||
|
|
||||||
|
|
||||||
main_headers = glob.glob("pybind11/include/pybind11/*.h")
|
|
||||||
conduit_headers = sum([glob.glob(f"pybind11/include/pybind11/conduit/*.{ext}")
|
|
||||||
for ext in ("h", "txt")], [])
|
|
||||||
detail_headers = glob.glob("pybind11/include/pybind11/detail/*.h")
|
|
||||||
eigen_headers = glob.glob("pybind11/include/pybind11/eigen/*.h")
|
|
||||||
stl_headers = glob.glob("pybind11/include/pybind11/stl/*.h")
|
|
||||||
cmake_files = glob.glob("pybind11/share/cmake/pybind11/*.cmake")
|
|
||||||
pkgconfig_files = glob.glob("pybind11/share/pkgconfig/*.pc")
|
|
||||||
headers = main_headers + conduit_headers + detail_headers + eigen_headers + stl_headers
|
|
||||||
|
|
||||||
cmdclass = {"install_headers": InstallHeadersNested}
|
|
||||||
$extra_cmd
|
|
||||||
|
|
||||||
# This will _not_ affect installing from wheels,
|
|
||||||
# only building wheels or installing from SDist.
|
|
||||||
# Primarily intended on Windows, where this is sometimes
|
|
||||||
# customized (for example, conda-forge uses Library/)
|
|
||||||
base = os.environ.get("PYBIND11_GLOBAL_PREFIX", "")
|
|
||||||
|
|
||||||
# Must have a separator
|
|
||||||
if base and not base.endswith("/"):
|
|
||||||
base += "/"
|
|
||||||
|
|
||||||
setup(
|
|
||||||
name="pybind11_global",
|
|
||||||
version="$version",
|
|
||||||
packages=[],
|
|
||||||
headers=headers,
|
|
||||||
data_files=[
|
|
||||||
(base + "share/cmake/pybind11", cmake_files),
|
|
||||||
(base + "share/pkgconfig", pkgconfig_files),
|
|
||||||
(base + "include/pybind11", main_headers),
|
|
||||||
(base + "include/pybind11/conduit", conduit_headers),
|
|
||||||
(base + "include/pybind11/detail", detail_headers),
|
|
||||||
(base + "include/pybind11/eigen", eigen_headers),
|
|
||||||
(base + "include/pybind11/stl", stl_headers),
|
|
||||||
],
|
|
||||||
cmdclass=cmdclass,
|
|
||||||
)
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# Setup script (in the sdist or in tools/setup_main.py in the repository)
|
|
||||||
|
|
||||||
from setuptools import setup
|
|
||||||
|
|
||||||
cmdclass = {}
|
|
||||||
$extra_cmd
|
|
||||||
|
|
||||||
setup(
|
|
||||||
name="pybind11",
|
|
||||||
version="$version",
|
|
||||||
download_url='https://github.com/pybind/pybind11/tarball/v$version',
|
|
||||||
packages=[
|
|
||||||
"pybind11",
|
|
||||||
"pybind11.include.pybind11",
|
|
||||||
"pybind11.include.pybind11.conduit",
|
|
||||||
"pybind11.include.pybind11.detail",
|
|
||||||
"pybind11.include.pybind11.eigen",
|
|
||||||
"pybind11.include.pybind11.stl",
|
|
||||||
"pybind11.share",
|
|
||||||
"pybind11.share.cmake.pybind11",
|
|
||||||
"pybind11.share.pkgconfig",
|
|
||||||
],
|
|
||||||
package_data={
|
|
||||||
"pybind11": ["py.typed"],
|
|
||||||
"pybind11.include.pybind11": ["*.h"],
|
|
||||||
"pybind11.include.pybind11.conduit": ["*.h", "*.txt"],
|
|
||||||
"pybind11.include.pybind11.detail": ["*.h"],
|
|
||||||
"pybind11.include.pybind11.eigen": ["*.h"],
|
|
||||||
"pybind11.include.pybind11.stl": ["*.h"],
|
|
||||||
"pybind11.share.cmake.pybind11": ["*.cmake"],
|
|
||||||
"pybind11.share.pkgconfig": ["*.pc"],
|
|
||||||
},
|
|
||||||
extras_require={
|
|
||||||
"global": ["pybind11_global==$version"]
|
|
||||||
},
|
|
||||||
entry_points={
|
|
||||||
"console_scripts": [
|
|
||||||
"pybind11-config = pybind11.__main__:main",
|
|
||||||
],
|
|
||||||
"pipx.run": [
|
|
||||||
"pybind11 = pybind11.__main__:main",
|
|
||||||
],
|
|
||||||
"pkg_config": [
|
|
||||||
"pybind11 = pybind11.share.pkgconfig",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
cmdclass=cmdclass
|
|
||||||
)
|
|
||||||
Reference in New Issue
Block a user