Skip to content

Commit

Permalink
bindings: python: add script to generate sdist and wheels
Browse files Browse the repository at this point in the history
Introduce a simple shell script that generates an sdist tarball and
wheels following the PEP 600 naming convention.

The wheels are generated via cibuildwheel, a tool provided by the Python
Packaging Authority (PyPA) [0]. The tool leverages toolchains within
containers maintained by PyPA to generate wheels that are runnable on
hosts that meet the requirements defined by the tag [1] [2].

The script currently creates X86_64 and AArch64 wheels for glibc and
musl libc for CPython versions 3.9-3.12.

[0]: https://cibuildwheel.pypa.io/en/stable/
[1]: https://peps.python.org/pep-0513/
[2]: https://github.com/pypa/manylinux

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
  • Loading branch information
vfazio committed May 31, 2024
1 parent b569b91 commit 1e019bd
Showing 1 changed file with 123 additions and 0 deletions.
123 changes: 123 additions & 0 deletions bindings/python/generate_pypi_artifacts.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#!/usr/bin/env sh
#
# This is a naive script to generate an sdist and wheels for publishing to PyPI.
#
# This script requires:
# * Python3 + venv or virtualenv + pip
# * Docker or Podman (https://cibuildwheel.pypa.io/en/stable/options/#container-engine)
# * binfmt support and qemu-user-static for AArch64 registered as Fixed
# (https://docs.kernel.org/admin-guide/binfmt-misc.html)
#
# On Debian based systems, AArch64 binfmt support can be checked via:
# cat /proc/sys/fs/binfmt_misc/qemu-aarch64
#
# This script can be run in a Docker container generated by:
# docker build - <<EOF
# FROM docker:26.1.3-dind-alpine3.20@sha256:76ba10a4aed708c7b2db09d45740d711edf707f7368f6808bd32a53eaed33404
# RUN apk add python3 py3-pip
# ENV XDG_CACHE_HOME=/tmp/
# EOF
#
# An example invocation would be:
# docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock \
# -v `pwd`:/work -w /work -v `pwd`:/outputs \
# <hash or label for container> \
# ./generate_pypi_artifacts.sh -v 2.1 -o /outputs
#

usage()
{
echo ""
echo "Usage: $0 [-v libgpiod_source_version] [-o output_directory]"
echo -e "\t-v Version of libgpiod sources to bundle in sdist, overrides LIBGPIOD_VERSION"
echo -e "\t-o Directory to store outputs"
echo -e "\t-s Directory with python binding sources"
exit 1
}

# Respect environment specified library version
src_version=${LIBGPIOD_VERSION}
output_dir=$(pwd)
source_dir=$(pwd)

while getopts :hv:o:s: value; do
case $value in
v)
src_version=${OPTARG}
;;
o)
output_dir=${OPTARG}
;;
s)
source_dir=${OPTARG}
;;
h | *)
usage
;;
esac
done

if [ -z ${source_dir} ] || [ ! -d ${output_dir} ]; then
echo "Invalid source directory ${source_dir}"
exit 1
fi

if [ -z ${output_dir} ] || [ ! -w ${output_dir} ]; then
echo "Output directory ${output_dir} is not writable"
exit 1
fi

if [ -z ${src_version} ]; then
echo "The libgpiod source version must be specified."
exit 1
fi

shift $((OPTIND-1))

# We don't need a specific version of python, but we do need it
if ! command -v python3 >/dev/null 2>&1; then
echo "Python3 is required to generate PyPI artifacts"
exit 1
fi

if ! $(python3 -m pip -h >/dev/null 2>&1); then
echo "pip is required to generate wheels"
exit 1
fi

# Check for a virtual environment tool
has_venv=$(python3 -m venv -h >/dev/null 2>&1 && echo 1 || echo 0)
has_virtualenv=$(python3 -m virtualenv -h >/dev/null 2>&1 && echo 1 || echo 0)

if ! ([ $has_venv -eq 1 ] || [ $has_virtualenv -eq 1 ]); then
echo "A virtual environment tool is required to generate wheels"
exit 1
fi

venv_module=$([ $has_virtualenv -eq 1 ] && echo "virtualenv" || echo "venv" )

# assume the current directory has the python binding sources
cur_dir=$(pwd)

# stage the build in a temp directory
temp_dir=$(mktemp -d)
cd $temp_dir

# setup a virtual environment with necessary build dependencies
python3 -m $venv_module .venv
venv_python="${temp_dir}/.venv/bin/python"

# cibuildwheel 2.18.1 pins the build containers to 2024-05-13-0983f6f
# This is overridable via the CIBW_{MANY,MUSL}LINUX_*_IMAGE environment variables
$venv_python -m pip install build==1.2.1 cibuildwheel==2.18.1

LIBGPIOD_VERSION=${src_version} $venv_python -m build --sdist --outdir ./dist $source_dir
sdist=$(find ./dist -name '*.tar.gz')

# by default, target only CPython
CIBW_BUILD="cp*" $venv_python -m cibuildwheel --platform linux --archs x86_64,aarch64 $sdist --output-dir dist/

cp -fa dist/ ${output_dir}/

cd $cur_dir
rm -rf $temp_dir

0 comments on commit 1e019bd

Please sign in to comment.