Skip to content

Build Python

Build Python #380

Workflow file for this run

name: Build Python
on:
workflow_dispatch:
inputs:
cpython_tag:
description: "CPython git tag to build (e.g. v3.12.13, v3.15.0a7)"
required: true
type: string
permissions:
contents: write
actions: write
defaults:
run:
shell: bash --noprofile --norc -euxo pipefail {0}
jobs:
build:
name: Build Python ${{ inputs.cpython_tag }}
runs-on: ubuntu-24.04-riscv
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout this repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install build dependencies
run: |
sudo apt-get update -qq
sudo apt-get install -qq -y --no-install-recommends \
build-essential \
ca-certificates \
g++-14 \
gcc-14 \
git \
libbz2-dev \
libexpat1-dev \
libffi-dev \
libgdbm-dev \
liblzma-dev \
libncursesw5-dev \
libreadline-dev \
libsqlite3-dev \
libssl-dev \
make \
patchelf \
pkg-config \
tk-dev \
uuid-dev \
wget \
xz-utils \
zlib1g-dev
# Make sure Python is built with gcc 14
echo "CC=gcc-14" >> $GITHUB_ENV
echo "CXX=g++-14" >> $GITHUB_ENV
- name: Compute normalised version
id: vars
run: |
# Make sure tag starts by v*
tag="${{ inputs.cpython_tag }}"
tag="${tag#v}"
tag="v${tag}"
# Strip leading v, expand a/b/rc suffixes
normalised="${tag#v}"
normalised="$(echo "$normalised" | sed -E 's/a([0-9]+)$/-alpha.\1/; s/b([0-9]+)$/-beta.\1/; s/rc([0-9]+)$/-rc.\1/')"
# X.Y
minor_num="$(echo "$normalised" | cut -d. -f2)"
minor="3.${minor_num}"
echo "tag=${tag}" >> "$GITHUB_OUTPUT"
echo "normalised=${normalised}" >> "$GITHUB_OUTPUT"
echo "minor=${minor}" >> "$GITHUB_OUTPUT"
echo "minor_num=${minor_num}" >> "$GITHUB_OUTPUT"
echo "archive_base=python-${normalised}-linux-24.04-riscv64" >> "$GITHUB_OUTPUT"
echo "Normalised version: ${normalised}"
echo "Python X.Y: ${minor}"
if [ "${minor_num}" -ge 13 ]; then
echo "freethreaded=true" >> "$GITHUB_OUTPUT"
fi
- name: Checkout CPython
run: git clone --depth 1 --branch "${{ steps.vars.outputs.tag }}" https://github.com/python/cpython.git src
- name: Build standard CPython
run: |
mkdir -p output
pushd src
./configure --with-ensurepip=install --enable-shared
make -j"$(nproc)" 2>&1 | tee ../build_output.txt
make install DESTDIR="$PWD/../staging-std"
popd
mkdir -p "${{ steps.vars.outputs.archive_base }}"
cp -a staging-std/usr/local/bin "${{ steps.vars.outputs.archive_base }}/"
cp -a staging-std/usr/local/include "${{ steps.vars.outputs.archive_base }}/"
cp -a staging-std/usr/local/lib "${{ steps.vars.outputs.archive_base }}/"
cp -a staging-std/usr/local/share "${{ steps.vars.outputs.archive_base }}/"
patchelf --set-rpath '/opt/hostedtoolcache/Python/${{ steps.vars.outputs.normalised }}/riscv64/lib' "${{ steps.vars.outputs.archive_base }}/bin/python${{ steps.vars.outputs.minor }}"
ln -srf "${{ steps.vars.outputs.archive_base }}/bin/python${{ steps.vars.outputs.minor }}" "${{ steps.vars.outputs.archive_base }}/bin/python"
ln -srf "${{ steps.vars.outputs.archive_base }}/bin/pip${{ steps.vars.outputs.minor }}" "${{ steps.vars.outputs.archive_base }}/bin/pip"
sed -e "s|{{__VERSION_FULL__}}|${{ steps.vars.outputs.normalised }}|g" \
-e "s|{{__ARCH__}}|riscv64|g" \
installers/nix-setup-template.sh > "${{ steps.vars.outputs.archive_base }}/setup.sh"
chmod +x "${{ steps.vars.outputs.archive_base }}/setup.sh"
mv build_output.txt "${{ steps.vars.outputs.archive_base }}/build_output.txt"
(cd "${{ steps.vars.outputs.archive_base }}" && find . \( -type f -o -type l \) | sed 's|^\./|/|') > "${{ steps.vars.outputs.archive_base }}/tools_structure.txt"
tar -czf "output/${{ steps.vars.outputs.archive_base }}.tar.gz" -C "${{ steps.vars.outputs.archive_base }}" .
rm -rf "${{ steps.vars.outputs.archive_base }}" staging-std
- name: Build free-threaded CPython
if: ${{ steps.vars.outputs.freethreaded }}
run: |
pushd src
git clean -fdx
./configure --with-ensurepip=install --enable-shared --disable-gil
make -j"$(nproc)" 2>&1 | tee ../build_output.txt
make install DESTDIR="$PWD/../staging-ft"
popd
mkdir -p "${{ steps.vars.outputs.archive_base }}-freethreaded"
cp -a staging-ft/usr/local/bin "${{ steps.vars.outputs.archive_base }}-freethreaded/"
cp -a staging-ft/usr/local/include "${{ steps.vars.outputs.archive_base }}-freethreaded/"
cp -a staging-ft/usr/local/lib "${{ steps.vars.outputs.archive_base }}-freethreaded/"
cp -a staging-ft/usr/local/share "${{ steps.vars.outputs.archive_base }}-freethreaded/"
patchelf --set-rpath '/opt/hostedtoolcache/Python/${{ steps.vars.outputs.normalised }}/riscv64-freethreaded/lib' "${{ steps.vars.outputs.archive_base }}-freethreaded/bin/python${{ steps.vars.outputs.minor }}"
ln -srf "${{ steps.vars.outputs.archive_base }}-freethreaded/bin/python${{ steps.vars.outputs.minor }}" "${{ steps.vars.outputs.archive_base }}-freethreaded/bin/python"
ln -srf "${{ steps.vars.outputs.archive_base }}-freethreaded/bin/pip${{ steps.vars.outputs.minor }}" "${{ steps.vars.outputs.archive_base }}-freethreaded/bin/pip"
sed -e "s|{{__VERSION_FULL__}}|${{ steps.vars.outputs.normalised }}|g" \
-e "s|{{__ARCH__}}|riscv64-freethreaded|g" \
installers/nix-setup-template.sh > "${{ steps.vars.outputs.archive_base }}-freethreaded/setup.sh"
chmod +x "${{ steps.vars.outputs.archive_base }}-freethreaded/setup.sh"
mv build_output.txt "${{ steps.vars.outputs.archive_base }}-freethreaded/build_output.txt"
(cd "${{ steps.vars.outputs.archive_base }}-freethreaded" && find . \( -type f -o -type l \) | sed 's|^\./|/|') > "${{ steps.vars.outputs.archive_base }}-freethreaded/tools_structure.txt"
tar -czf "output/${{ steps.vars.outputs.archive_base }}-freethreaded.tar.gz" -C "${{ steps.vars.outputs.archive_base }}-freethreaded" .
rm -rf "${{ steps.vars.outputs.archive_base }}-freethreaded" staging-ft
- name: Print tarball hashes
run: sha256sum output/*.tar.gz
- name: Publish release
run: |
TAG="${{ steps.vars.outputs.normalised }}-${GITHUB_RUN_ID}"
gh release create "$TAG" --repo "$GITHUB_REPOSITORY" \
--title "${{ steps.vars.outputs.normalised }}" \
--notes "Python ${{ steps.vars.outputs.normalised }}" \
./output/*.tar.gz
- name: Trigger manifest refresh
run: gh workflow run update-manifest.yml --repo "$GITHUB_REPOSITORY" --ref main