mirror of
https://github.com/capnproto/pycapnp.git
synced 2025-03-04 08:24:43 +01:00
Add custom build backend to support build args (#328)
This implements a custom build backend, inspired by the [solution used by Pillow.](https://github.com/python-pillow/Pillow/pull/7171) install-option is deprecated and was removed with pip 23.1. The comonly accepted solution seems to be to define a custom build backend for now https://github.com/pypa/setuptools/issues/2491#issuecomment-1589764230 This commit changes the usage from `--install-option` to `--config-settings`.
This commit is contained in:
parent
db26d60283
commit
d48ffea939
7 changed files with 77 additions and 50 deletions
37
README.md
37
README.md
|
@ -38,25 +38,27 @@ cd pycapnp
|
||||||
pip install .
|
pip install .
|
||||||
```
|
```
|
||||||
|
|
||||||
|
By default, the setup script will automatically use the locally installed Cap'n Proto.
|
||||||
|
If Cap'n Proto is not installed, it will bundle and build the matching Cap'n Proto library.
|
||||||
|
|
||||||
|
To enforce bundling, the Cap'n Proto library:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install . -C force-bundled-libcapnp=True
|
||||||
|
```
|
||||||
|
|
||||||
If you wish to install using the latest upstream C++ Cap'n Proto:
|
If you wish to install using the latest upstream C++ Cap'n Proto:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install \
|
pip install . \
|
||||||
--install-option "--libcapnp-url" \
|
-C force-bundled-libcapnp=True \
|
||||||
--install-option "https://github.com/capnproto/capnproto/archive/master.tar.gz" \
|
-C libcapnp-url="https://github.com/capnproto/capnproto/archive/master.tar.gz"
|
||||||
--install-option "--force-bundled-libcapnp" .
|
|
||||||
```
|
```
|
||||||
|
|
||||||
To force bundled python:
|
To enforce using the installed Cap'n Proto from the system:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install --install-option "--force-bundled-libcapnp" .
|
pip install . -C force-system-libcapnp=True
|
||||||
```
|
|
||||||
|
|
||||||
Slightly more prompt error messages using distutils rather than pip.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python setup.py install --force-bundled-libcapnp
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The bundling system isn't that smart so it might be necessary to clean up the bundled build when changing versions:
|
The bundling system isn't that smart so it might be necessary to clean up the bundled build when changing versions:
|
||||||
|
@ -92,19 +94,12 @@ pipenv run pytest
|
||||||
|
|
||||||
### Binary Packages
|
### Binary Packages
|
||||||
|
|
||||||
Building a dumb binary distribution:
|
Building a Python wheel distributiion
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python setup.py bdist_dumb
|
pip wheel .
|
||||||
```
|
```
|
||||||
|
|
||||||
Building a Python wheel distributiion:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python setup.py bdist_wheel
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Documentation/Example
|
## Documentation/Example
|
||||||
|
|
||||||
There is some basic documentation [here](http://capnproto.github.io/pycapnp/).
|
There is some basic documentation [here](http://capnproto.github.io/pycapnp/).
|
||||||
|
|
31
_custom_build/backend.py
Normal file
31
_custom_build/backend.py
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from setuptools.build_meta import * # noqa: F401, F403
|
||||||
|
from setuptools.build_meta import build_wheel
|
||||||
|
|
||||||
|
backend_class = build_wheel.__self__.__class__
|
||||||
|
|
||||||
|
|
||||||
|
class _CustomBuildMetaBackend(backend_class):
|
||||||
|
def run_setup(self, setup_script="setup.py"):
|
||||||
|
if self.config_settings:
|
||||||
|
flags = []
|
||||||
|
if self.config_settings.get("force-bundled-libcapnp"):
|
||||||
|
flags.append("--force-bundled-libcapnp")
|
||||||
|
if self.config_settings.get("force-system-libcapnp"):
|
||||||
|
flags.append("--force-system-libcapnp")
|
||||||
|
if self.config_settings.get("libcapnp-url"):
|
||||||
|
flags.append("--libcapnp-url")
|
||||||
|
flags.append(self.config_settings["libcapnp-url"])
|
||||||
|
if flags:
|
||||||
|
sys.argv = sys.argv[:1] + ["build_ext"] + flags + sys.argv[1:]
|
||||||
|
return super().run_setup(setup_script)
|
||||||
|
|
||||||
|
def build_wheel(
|
||||||
|
self, wheel_directory, config_settings=None, metadata_directory=None
|
||||||
|
):
|
||||||
|
self.config_settings = config_settings
|
||||||
|
return super().build_wheel(wheel_directory, config_settings, metadata_directory)
|
||||||
|
|
||||||
|
|
||||||
|
build_wheel = _CustomBuildMetaBackend().build_wheel
|
|
@ -15,8 +15,8 @@ To force rebuilding the pip package from source (you'll need requirments.txt or
|
||||||
|
|
||||||
To force bundling libcapnp (or force system libcapnp), just in case setup.py isn't doing the right thing::
|
To force bundling libcapnp (or force system libcapnp), just in case setup.py isn't doing the right thing::
|
||||||
|
|
||||||
pip install --no-binary :all: --install-option "--force-bundled-libcapnp"
|
pip install --no-binary :all: -C force-bundled-libcapnp=True
|
||||||
pip install --no-binary :all: --install-option "--force-system-libcapnp"
|
pip install --no-binary :all: -C force-system-libcapnp=True
|
||||||
|
|
||||||
If you're using an older Linux distro (e.g. CentOS 6) you many need to set `LDFLAGS="-Wl,--no-as-needed -lrt"`::
|
If you're using an older Linux distro (e.g. CentOS 6) you many need to set `LDFLAGS="-Wl,--no-as-needed -lrt"`::
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ If you're using an older Linux distro (e.g. CentOS 6) you many need to set `LDFL
|
||||||
|
|
||||||
It's also possible to specify the libcapnp url when bundling (this may not work, there be dragons)::
|
It's also possible to specify the libcapnp url when bundling (this may not work, there be dragons)::
|
||||||
|
|
||||||
pip install --no-binary :all: --install-option "--force-bundled-libcapnp" --install-option "--libcapnp-url" --install-option "https://github.com/capnproto/capnproto/archive/master.tar.gz"
|
pip install --no-binary :all: -C force-bundled-libcapnp=True -C libcapnp-url="https://github.com/capnproto/capnproto/archive/master.tar.gz"
|
||||||
|
|
||||||
From Source
|
From Source
|
||||||
-----------
|
-----------
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["setuptools", "wheel", "pkgconfig", "cython<3"]
|
requires = ["setuptools", "wheel", "pkgconfig", "cython<3"]
|
||||||
|
build-backend = "backend"
|
||||||
|
backend-path = ["_custom_build"]
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
asyncio_mode = "auto"
|
asyncio_mode = "auto"
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
[metadata]
|
[metadata]
|
||||||
description-file = README.md
|
description_file = README.md
|
||||||
license_files = LICENSE.md
|
license_files = LICENSE.md
|
||||||
|
|
46
setup.py
46
setup.py
|
@ -15,10 +15,12 @@ from distutils.command.clean import clean as _clean
|
||||||
|
|
||||||
from setuptools import setup, Extension
|
from setuptools import setup, Extension
|
||||||
|
|
||||||
|
_this_dir = os.path.dirname(__file__)
|
||||||
|
sys.path.insert(1, _this_dir)
|
||||||
|
|
||||||
from buildutils.build import build_libcapnp
|
from buildutils.build import build_libcapnp
|
||||||
from buildutils.bundle import fetch_libcapnp
|
from buildutils.bundle import fetch_libcapnp
|
||||||
|
|
||||||
_this_dir = os.path.dirname(__file__)
|
|
||||||
|
|
||||||
MAJOR = 1
|
MAJOR = 1
|
||||||
MINOR = 3
|
MINOR = 3
|
||||||
|
@ -85,26 +87,6 @@ class clean(_clean):
|
||||||
shutil.rmtree(x, ignore_errors=True)
|
shutil.rmtree(x, ignore_errors=True)
|
||||||
|
|
||||||
|
|
||||||
# hack to parse commandline arguments
|
|
||||||
force_bundled_libcapnp = "--force-bundled-libcapnp" in sys.argv
|
|
||||||
if force_bundled_libcapnp:
|
|
||||||
sys.argv.remove("--force-bundled-libcapnp")
|
|
||||||
force_system_libcapnp = "--force-system-libcapnp" in sys.argv
|
|
||||||
if force_system_libcapnp:
|
|
||||||
sys.argv.remove("--force-system-libcapnp")
|
|
||||||
force_cython = "--force-cython" in sys.argv
|
|
||||||
if force_cython:
|
|
||||||
sys.argv.remove("--force-cython")
|
|
||||||
# Always use cython, ignoring option
|
|
||||||
libcapnp_url = None
|
|
||||||
try:
|
|
||||||
libcapnp_url_index = sys.argv.index("--libcapnp-url")
|
|
||||||
libcapnp_url = sys.argv[libcapnp_url_index + 1]
|
|
||||||
sys.argv.remove("--libcapnp-url")
|
|
||||||
sys.argv.remove(libcapnp_url)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
from Cython.Distutils import build_ext as build_ext_c # noqa: E402
|
from Cython.Distutils import build_ext as build_ext_c # noqa: E402
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,13 +95,29 @@ class build_libcapnp_ext(build_ext_c):
|
||||||
Build capnproto library
|
Build capnproto library
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
user_options = build_ext_c.user_options + [
|
||||||
|
("force-bundled-libcapnp", None, "Bundle capnp library into the installer"),
|
||||||
|
("force-system-libcapnp", None, "Use system capnp library"),
|
||||||
|
("libcapnp-url=", "u", "URL to download libcapnp from (only if bundled)"),
|
||||||
|
]
|
||||||
|
|
||||||
|
def initialize_options(self):
|
||||||
|
build_ext_c.initialize_options(self)
|
||||||
|
self.force_bundled_libcapnp = None
|
||||||
|
self.force_system_libcapnp = None
|
||||||
|
self.libcapnp_url = None
|
||||||
|
|
||||||
|
def finalize_options(self):
|
||||||
|
# print('The custom option for install is ', self.custom_option)
|
||||||
|
build_ext_c.finalize_options(self)
|
||||||
|
|
||||||
def build_extension(self, ext):
|
def build_extension(self, ext):
|
||||||
build_ext_c.build_extension(self, ext)
|
build_ext_c.build_extension(self, ext)
|
||||||
|
|
||||||
def run(self): # noqa: C901
|
def run(self): # noqa: C901
|
||||||
if force_bundled_libcapnp:
|
if self.force_bundled_libcapnp:
|
||||||
need_build = True
|
need_build = True
|
||||||
elif force_system_libcapnp:
|
elif self.force_system_libcapnp:
|
||||||
need_build = False
|
need_build = False
|
||||||
else:
|
else:
|
||||||
# Try to use capnp executable to find include and lib path
|
# Try to use capnp executable to find include and lib path
|
||||||
|
@ -167,7 +165,7 @@ class build_libcapnp_ext(build_ext_c):
|
||||||
|
|
||||||
if not os.path.exists(capnp_bin):
|
if not os.path.exists(capnp_bin):
|
||||||
# Not built, fetch and build
|
# Not built, fetch and build
|
||||||
fetch_libcapnp(bundle_dir, libcapnp_url)
|
fetch_libcapnp(bundle_dir, self.libcapnp_url)
|
||||||
build_libcapnp(bundle_dir, build_dir)
|
build_libcapnp(bundle_dir, build_dir)
|
||||||
else:
|
else:
|
||||||
print("capnproto already built at {}".format(build_dir))
|
print("capnproto already built at {}".format(build_dir))
|
||||||
|
|
3
tox.ini
3
tox.ini
|
@ -7,10 +7,11 @@ deps=
|
||||||
pkgconfig
|
pkgconfig
|
||||||
Jinja2
|
Jinja2
|
||||||
pytest
|
pytest
|
||||||
|
pytest-asyncio
|
||||||
cython<3
|
cython<3
|
||||||
|
|
||||||
commands =
|
commands =
|
||||||
python setup.py install
|
pip install .
|
||||||
py.test {posargs}
|
py.test {posargs}
|
||||||
|
|
||||||
setenv =
|
setenv =
|
||||||
|
|
Loading…
Add table
Reference in a new issue