summaryrefslogtreecommitdiff
path: root/setup.py
diff options
context:
space:
mode:
Diffstat (limited to 'setup.py')
-rw-r--r--setup.py152
1 files changed, 0 insertions, 152 deletions
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 0a24682..0000000
--- a/setup.py
+++ /dev/null
@@ -1,152 +0,0 @@
-"""setup.py overrides several setuptools commands to integrate the meson-built
-libpixpat.so into the Python wheel.
-
-Layout (where things land for each workflow):
-
- meson setup build / meson compile -C build — repo-root build/, the
- C++ developer's meson dir. Python tooling never touches this.
-
- pip install -e . — DevEditableWheel
- symlinks build/libpixpat.so into pixpat-python/pixpat/_lib/.
- Requires the user to have built `build/` themselves.
-
- pip install . — MesonBuildPy invokes
- meson into pixpat-python/build/native/, copies the .so straight into
- setuptools' build_lib (pixpat-python/build/lib/pixpat/_lib/), and
- bdist_wheel zips that into the wheel. The source tree's _lib/ is
- never touched on this path, so wheel builds don't depend on (or
- pollute) it.
-
- scripts/build_wheel.sh <arch> — sets PIXPAT_TARGET_ARCH
- and runs `python -m build`; meson lands in pixpat-python/build-<arch>/
- native/, setuptools alongside.
-
-bdist_wheel: setuptools' default produces a `py3-none-any` (pure-Python) wheel
-when there's no compiled extension. We bundle a `.so` as package data, so we
-MUST tag the wheel for a specific platform — otherwise pip would
-install our x86_64 wheel on an arm64 box. Target arch is read from
-PIXPAT_TARGET_ARCH and falls back to the running machine's arch — important
-because setuptools' editable_wheel delegates wheel construction to whatever
-bdist_wheel is registered, so this class is invoked during `pip install -e .`
-too.
-"""
-
-import os
-import platform
-import shutil
-import subprocess
-from pathlib import Path
-
-from setuptools import setup
-from setuptools.command.bdist_wheel import bdist_wheel
-from setuptools.command.build import build
-from setuptools.command.build_py import build_py
-from setuptools.command.editable_wheel import editable_wheel
-
-REPO_ROOT = Path(__file__).resolve().parent
-LIB_DIR = REPO_ROOT / 'pixpat-python' / 'pixpat' / '_lib'
-
-
-def _target_arch() -> str:
- return os.environ.get('PIXPAT_TARGET_ARCH') or platform.machine()
-
-
-def _wheel_build_root() -> Path:
- """Top-level dir where setuptools and meson stage wheel-build output.
-
- Plain `pip install .` uses pixpat-python/build/. Cross-compile via
- PIXPAT_TARGET_ARCH gets a per-arch sibling so meson can keep arches
- incrementally compiled side by side.
- """
- arch = os.environ.get('PIXPAT_TARGET_ARCH')
- suffix = f'-{arch}' if arch else ''
- return REPO_ROOT / 'pixpat-python' / f'build{suffix}'
-
-
-class ImpureBdistWheel(bdist_wheel):
- def finalize_options(self):
- super().finalize_options()
- self.root_is_pure = False
-
- def get_tag(self):
- return ('py3', 'none', f'linux_{_target_arch()}')
-
-
-class WheelBuild(build):
- """Direct setuptools' staging into pixpat-python/build[-<arch>]/."""
-
- def initialize_options(self):
- super().initialize_options()
- self.build_base = str(_wheel_build_root())
-
-
-class MesonBuildPy(build_py):
- """Compile libpixpat.so via meson and stage it into build_lib for the wheel."""
-
- def run(self):
- super().run()
- # editable_mode is set by setuptools' editable_wheel command. In that
- # path DevEditableWheel has already symlinked the user's repo-root
- # build/ into the source _lib/, so meson must not run.
- if not self.editable_mode:
- self._build_native()
-
- def _build_native(self):
- meson_dir = _wheel_build_root() / 'native'
- arch = _target_arch()
- cross_args = []
- if arch != platform.machine():
- cross_file = REPO_ROOT / 'pixpat-native' / 'cross' / f'{arch}-linux-gnu.txt'
- if not cross_file.exists():
- raise SystemExit(f'no cross-file for {arch}: {cross_file}')
- cross_args = ['--cross-file', str(cross_file)]
-
- if not (meson_dir / 'meson-info').exists():
- meson_dir.parent.mkdir(parents=True, exist_ok=True)
- subprocess.check_call(
- ['meson', 'setup', str(meson_dir), '--buildtype=release', *cross_args],
- cwd=REPO_ROOT,
- )
- subprocess.check_call(['meson', 'compile', '-C', str(meson_dir)], cwd=REPO_ROOT)
-
- out_dir = Path(self.build_lib) / 'pixpat' / '_lib'
- out_dir.mkdir(parents=True, exist_ok=True)
- # follow_symlinks resolves meson's libpixpat.so -> .so.<maj> -> .so.<maj>.<min>.<patch>
- # chain into a regular file. The wheel ships only the unversioned name, so we
- # don't have to track meson's project version here.
- shutil.copy2(meson_dir / 'libpixpat.so', out_dir / 'libpixpat.so')
-
-
-class DevEditableWheel(editable_wheel):
- """Symlink the user's repo-root meson build into _lib/ before installing."""
-
- def run(self):
- build_so = REPO_ROOT / 'build' / 'libpixpat.so'
-
- if not build_so.exists():
- raise SystemExit(
- f'editable install needs {build_so}.\n'
- 'Configure and build first:\n'
- ' meson setup build\n'
- ' meson compile -C build'
- )
-
- LIB_DIR.mkdir(parents=True, exist_ok=True)
- for old in LIB_DIR.glob('libpixpat.so*'):
- old.unlink()
- # Relative path so the symlink survives moves of the source tree.
- (LIB_DIR / 'libpixpat.so').symlink_to(
- Path('..') / '..' / '..' / 'build' / 'libpixpat.so'
- )
-
- super().run()
-
-
-setup(
- cmdclass={
- 'bdist_wheel': ImpureBdistWheel,
- 'build': WheelBuild,
- 'build_py': MesonBuildPy,
- 'editable_wheel': DevEditableWheel,
- }
-)