Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure clean sdist and wheel builds #25

Merged
merged 4 commits into from
Mar 28, 2024
Merged

Conversation

waveform80
Copy link
Contributor

I've finally found some time to have a look at building a clean PyPI sdist and corresponding wheels for lgpio and rgpio. There's quite a bit to unpack here, and a couple of potentially controversial decisions so I'll go through things one by one:

Python 2.x dropped

I've got no means of "cleanly" building anything for Python 2.x (I'll come onto what a "clean" build means specifically in this context a bit later on), even in container environments at this point so the first commit here (5e06193) just drops all the Python 2.x stuff. If that's still desired I can revert that change and make a best guess at what a Python 2.x compatible build would look like in setup.py but it will be just that: a guess. Someone else would have to verify it works the way it's intended to.

src symlink

One of the issues with the current packaging is that the C source is "above" the Python source in the hierarchy. Various bits of the Python packaging mechanisms expect all source to be "below" the setup.py. Thankfully this is fairly easy to fake with a "src" symlink pointing to "..", which is what the second commit (8c66cad) introduces. This is only present in the PY_LGPIO dir as PY_RGPIO doesn't require it (no C source to include).

PYTHON var in Makefile

PR #5 also intends to introduce this, but does so in a rather more invasive way (and also doesn't solve the issue of "clean" builds or static linking). The third commit here (19d287a) simply replaces the remaining python3 references in the Makefile with a PYTHON variable.

static builds

I don't want to alter the current default build setup, producing a shared object and a dynamically linked python library, as it works extremely well for the Debian/Ubuntu packaging (which I'm also responsible for). However, I do take the point that wheels uploaded to PyPI should almost certainly include a statically linked lgpio library as pip cannot ask the wider system to install things like shared libraries.

To that end, the fourth commit (46304f6) extends the lgpio setup.py to accept an environment variable hint (PYPI=1) which will cause it to build a statically linked binary. This commit also introduces a generated MANIFEST.in which includes everything that should be included in the source distribution.

The upshot is that the lgpio and rgpio modules can now be built with the pypa/build tool. This tool first builds a source distribution (tar.gz) in a clean venv, then creates a separate venv, and builds the binary wheel from the built source distribution in that clean venv. This ensures all build dependencies are correct, and also that the source distribution definitely includes everything necessary for the binary build.

Testing

The normal build procedure (make; sudo make install) should work exactly the same as it always has, producing dynamically linked artifacts.

If you wish to test building statically linked artifacts with pypa/build, please be aware that the version in Ubuntu 22.04 currently has issues (I've uploaded an SRU to fix this but that'll take a while for approval). In the meantime, the following procedure should work on Ubuntu 22.04 (using python3-virtualenv as a workaround for the aforementioned issue):

$ sudo apt update
$ sudo apt install python3-dev python3-setuptools python3-build python3-virtualenv build-essential swig
$ git clone https://github.com/waveform80/lg
$ cd lg
$ git checkout pypi
$ cd PY_LGPIO
$ PYPI=1 python3 -m build .
$ ls dist/

Assuming this passes scrutiny, and there are no strong objections, I'll be using a similar procedure to the above (with the aid of the deadsnakes PPA and some armhf/arm64 containers) to generate statically linked wheels for Python 3.9 through Python 3.12 for upload to PyPI. This should hopefully resolve the current pain around installing lgpio in a virtualenv (i.e. #24) across the vast majority of installs.

If there's demand for earlier Python versions I should be able to produce wheels back to Python 3.7 but earlier than that will be quite tricky.

waveform80 and others added 4 commits March 28, 2024 15:49
I don't have any way of testing that the build works on Python 2, and I
know pathlib doesn't exist there. Probably time to retire it.
This just makes it much easier to build the Python module; the
setuptools machinery expects everything to be "beneath" setup.py
This ensures the build can work "cleanly" with pypa/build, which checks
that the sdist produced can be used independently to produce the binary
wheel. This also introduces a PYPI=1 env-var to force a statically
linked library to be produced, for PyPI uploads.
@joan2937 joan2937 merged commit 746f0df into joan2937:master Mar 28, 2024
@waveform80
Copy link
Contributor Author

Thanks very much for the quick review! After a bit of hoop-jumping and container-fiddling today, I now have some wheels which I'll be uploading to PyPI shortly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants