janba / GEL

A library of geometry processing tools for computer graphics
95 stars 23 forks source link

Reproducible Build for Linux Distros w/older GLIBC (feat. Rootless Containers) #73

Closed so-rose closed 7 months ago

so-rose commented 9 months ago

The Bug

On Linux, the PyPi wheel for PyGEL3D compiles GEL against the latest Ubuntu. As a result, PyGEL will never work on any distribution with an older GLIBC than the latest Ubuntu - for example, just after the release of a new Ubuntu LTS, re-uploading PyGEL would break it for everybody still using the existing Ubuntu LTS.

Workaround

One can, of course, compile this oneself. This is a bit of a hassle; however, it can be done in a one-liner using the magic of rootless containers, even on my more-and-more ancient Debian 11 (now oldstable).

To run this script, podman (https://podman.io/) must be installed. With podman installed, the build process is 100% identical regardless of OS.

IMAGE="debian"  ## Corresponds to distro
TAG="bullseye-slim"  ## Corresponds to distro version
# Reference of Images (w/Tags) for Common Distros:
# - Ubuntu: https://hub.docker.com/_/ubuntu
# - Debian: https://hub.docker.com/_/debian
# - Fedora: https://hub.docker.com/_/fedora
# - CentOS: https://hub.docker.com/_/centos

####################
# - Build in Container
####################
podman run --rm -it \
    --volume .:/src \
    --workdir /src \
    ${IMAGE}:${TAG} \
    bash -xuc """ \
apt-get update && \
apt-get install -y gcc g++ cmake libglu1 libgl1 libglu1-mesa-dev git libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev python3 python3-setuptools python3-wheel && \
mkdir -p build && \
cd build && \
cmake .. && \
make -j 8 && \
cd .. && \
python3 setup.py bdist_wheel
"""

# PyGEL3D is now built w/Symlinks compatible with the given distro version.

# To install w/Python, simply run:
# $ pip install dist/PyGEL3D-*.whl  ## Build the Wheel

# In a requirements.txt file, you can also add:
# PyGEL3D @ file:///abs/path/to/GEL/dist/PyGEL3D-0.4.3-py3-none-any.whl

In principle, running an analogue of this script on Podman for MacOS/Windows should also generate a Linux wheel - since the podman runtime runs on a Linux kernel within a VM.

Caveats

As indicated, one must find the precise Linux distribution + image tag that one wants PyGEL to work with, and modify the variables at the top. Since I use Debian 11, I use:

IMAGE="debian"  ## Corresponds to distro
TAG="bullseye-slim"  ## Corresponds to distro version

Choosing the wrong IMAGE:TAG will result in broken symbolic links.

Also, one must still manually apt install libglu1 libgl1 for full functionality.

This build is also a rather heavy process due to needing to apt install a bunch of stuff (including a complete compiler toolchain); a base image with the dependencies preinstalled could greatly speedup rebuilds to near-bare-metal speed, at the cost of complexity.

I believe there is some kind of more "universal Linux binary image" in the Python ecosystem. I'm unsure, however. The ecosystem is a mess. Still, this may be worth investigating.

janba commented 9 months ago

It is a good point, but the build process works quite well, so I am hesitant to make dramatic changes. However, I have switched from Ubuntu latest to 20.04. You should be able to download the build result here:

https://github.com/janba/GEL/actions/runs/7732911498

I would appreciate it if you could put the compiled version of libPyGEL.so into a wheel on your machine and check if it works. If it does indeed have greater compatibility, I will just move to that version.