Skip to content

15. _Build Distribution #10

15. _Build Distribution

15. _Build Distribution #10

Workflow file for this run

name: 15. _Build Distribution
on:
workflow_call:
inputs:
os_json:
description: 'JSON string of OS to build on'
required: false
type: string
default: '["ubuntu-latest", "macos-latest", "macos-15-intel", "windows-latest"]'
python_json:
description: 'JSON string of Python versions'
required: false
type: string
default: '["3.9", "3.10", "3.11", "3.12"]'
workflow_dispatch:
inputs:
os_json:
description: 'JSON string of OS to build on'
required: false
default: '["ubuntu-latest", "macos-latest", "macos-15-intel", "windows-latest"]'
python_json:
description: 'JSON string of Python versions'
required: false
default: '["3.9", "3.10", "3.11", "3.12"]'
jobs:
build-linux:
name: Build distribution on Linux (glibc 2.31) py${{ matrix.python-version }}
# Only run if inputs.os_json contains 'ubuntu' or 'linux'
if: contains(inputs.os_json, 'ubuntu') || contains(inputs.os_json, 'linux')
runs-on: ubuntu-latest
container: ubuntu:20.04
env:
DEBIAN_FRONTEND: noninteractive
TZ: Etc/UTC
strategy:
fail-fast: false
matrix:
python-version: ${{ fromJson(inputs.python_json) }}
steps:
- name: Install system dependencies (Linux)
run: |
# Replace archive.ubuntu.com with azure.archive.ubuntu.com for better stability in GH Actions
sed -i 's/http:\/\/archive.ubuntu.com\/ubuntu\//http:\/\/azure.archive.ubuntu.com\/ubuntu\//g' /etc/apt/sources.list
# Retry apt-get update
for i in 1 2 3 4 5; do apt-get update && break || sleep 5; done
apt-get install -y \
git ca-certificates cmake build-essential tzdata curl \
libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \
libffi-dev liblzma-dev libgdbm-dev libnss3-dev libncurses5-dev \
libncursesw5-dev tk-dev uuid-dev libexpat1-dev
ln -fs /usr/share/zoneinfo/Etc/UTC /etc/localtime
dpkg-reconfigure -f noninteractive tzdata
- uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0 # Required for setuptools_scm to detect version from git tags
- name: Build CPython (Dynamic Selection)
run: |
# Map short version to full version for our specific build environment
PYTHON_VERSION="${{ matrix.python-version }}"
case "$PYTHON_VERSION" in
"3.9") PYTHON_FULL="3.9.18" ;;
"3.10") PYTHON_FULL="3.10.13" ;;
"3.11") PYTHON_FULL="3.11.8" ;;
"3.12") PYTHON_FULL="3.12.2" ;;
*)
echo "Error: Unknown python version $PYTHON_VERSION"
exit 1
;;
esac
PYTHON_PREFIX="/opt/python/${PYTHON_FULL}"
PYTHON_BIN="${PYTHON_PREFIX}/bin/python${{ matrix.python-version }}"
if [ ! -x "$PYTHON_BIN" ]; then
curl -fsSL -o /tmp/Python-${PYTHON_FULL}.tgz \
https://www.python.org/ftp/python/${PYTHON_FULL}/Python-${PYTHON_FULL}.tgz
tar -xzf /tmp/Python-${PYTHON_FULL}.tgz -C /tmp
cd /tmp/Python-${PYTHON_FULL}
CFLAGS="-fPIC" \
./configure --prefix="${PYTHON_PREFIX}" --with-ensurepip=install --enable-shared
make -j"$(nproc)"
make install
fi
echo "PYTHON_BIN=${PYTHON_BIN}" >> "$GITHUB_ENV"
echo "LD_LIBRARY_PATH=${PYTHON_PREFIX}/lib:${LD_LIBRARY_PATH}" >> "$GITHUB_ENV"
export LD_LIBRARY_PATH="${PYTHON_PREFIX}/lib:${LD_LIBRARY_PATH}"
"$PYTHON_BIN" -V
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: '1.25.1'
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- name: Create venv (Linux)
run: uv venv --python "$PYTHON_BIN"
- name: Seed pip (Linux)
run: uv run python -m ensurepip --upgrade
- name: Install dependencies
run: uv sync
- name: Install build dependencies
run: uv pip install setuptools setuptools_scm pybind11 cmake wheel build
- name: Build package
run: uv run python -m build
- name: Install patchelf (Linux)
run: |
PATCHELF_VERSION=0.18.0
curl -fsSL -o /tmp/patchelf-${PATCHELF_VERSION}.tar.gz \
https://github.com/NixOS/patchelf/releases/download/${PATCHELF_VERSION}/patchelf-${PATCHELF_VERSION}.tar.gz
tar -xzf /tmp/patchelf-${PATCHELF_VERSION}.tar.gz -C /tmp
cd /tmp/patchelf-${PATCHELF_VERSION}
./configure
make -j"$(nproc)"
make install
patchelf --version
- name: Repair wheels (Linux)
run: |
uv pip install auditwheel
# Repair wheels and output to a temporary directory
uv run auditwheel repair dist/*.whl -w dist_fixed
# Remove original non-compliant wheels
rm dist/*.whl
# Move repaired wheels back to dist
mv dist_fixed/*.whl dist/
rmdir dist_fixed
- name: Store the distribution packages
uses: actions/upload-artifact@v4
with:
name: python-package-distributions-linux-${{ matrix.python-version }}
path: dist/
build-other:
name: Build distribution on ${{ matrix.os }}
# Filter out ubuntu-latest from this job since it's handled by build-linux
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: ${{ fromJson(inputs.os_json) }}
python-version: ${{ fromJson(inputs.python_json) }}
# Exclude ubuntu-latest from this matrix if it was passed in inputs
exclude:
- os: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0 # Required for setuptools_scm to detect version from git tags
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: '1.25.1'
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- name: Install system dependencies (macOS)
if: runner.os == 'macOS'
run: brew install cmake
- name: Install system dependencies (Windows)
if: runner.os == 'Windows'
run: |
choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System'
choco install mingw
- name: Install dependencies
run: uv sync
- name: Install build dependencies
run: uv pip install setuptools setuptools_scm pybind11 cmake wheel build
- name: Build package
run: uv run python -m build
- name: Store the distribution packages
uses: actions/upload-artifact@v4
with:
name: python-package-distributions-${{ matrix.os }}-${{ matrix.python-version }}
path: dist/