CI: publish Apple Silicon macOS binaries (#3556)

* pyenv-binary: relocate macOS text paths
* CI: publish Apple Silicon macOS binaries
* pyenv-binary: preserve unrelated bytecode
* CI: stabilize macOS binary package names
This commit is contained in:
Ayush 2026-09-22 03:42:32 +05:30 committed by GitHub
parent 7db7714ff7
commit 249f8d888e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 69 additions and 9 deletions

View File

@ -7,26 +7,42 @@ on:
description: A CPython version accepted by `pyenv install`
required: true
type: string
platform:
description: Platform to build on
required: true
type: choice
default: ubuntu-24.04
options:
- ubuntu-24.04
- macos-15
permissions:
contents: read
jobs:
publish_ubuntu:
runs-on: ubuntu-24.04
publish:
runs-on: ${{ inputs.platform }}
env:
PYENV_ROOT: ${{ github.workspace }}
VERSION: ${{ inputs.version }}
steps:
- uses: actions/checkout@v7
- name: Install build prerequisites
- name: Install Ubuntu build prerequisites
if: runner.os == 'Linux'
run: ./bin/pyenv install-prerequisites
- name: Install macOS build prerequisites
if: runner.os == 'macOS'
run: brew install openssl readline sqlite3 xz tcl-tk@8 libb2 zstd
- name: Build package
env:
PYTHON_CONFIGURE_OPTS: --enable-optimizations
run: |
VERSION="${VERSION%%:*}"
entry="$(./bin/pyenv binary package-name "$VERSION")"
if [ "$RUNNER_OS" = "macOS" ]; then
entry="${VERSION}-${{ inputs.platform }}-$(uname -m)"
else
entry="$(./bin/pyenv binary package-name "$VERSION")"
fi
echo "entry=$entry" >> "$GITHUB_ENV"
mkdir dist
cd dist

View File

@ -100,6 +100,22 @@ if [ "$(uname -s)" = "Darwin" ]; then
while IFS= read -r so; do
relocate_macho "$so" '@loader_path/../..'
done < <(find "$prefix" -type f -path '*/lib/python*/lib-dynload/*.so')
# CPython records its installation prefix in generated scripts and build
# metadata. Bytecode can also retain source filenames from the build tree.
build_prefix_pattern="$(printf '%s\n' "$build_prefix" | sed 's/[][\\.^$*|]/\\&/g')"
prefix_replacement="$(printf '%s\n' "$prefix" | sed 's/[\\&|]/\\&/g')"
while IFS= read -r file; do
if LC_ALL=C grep -IqF "$build_prefix" "$file"; then
sed -i.bak "s|${build_prefix_pattern}|${prefix_replacement}|g" "$file"
rm -f "${file}.bak"
fi
done < <(find "$prefix" -type f ! -name '*.pyc' ! -name '*.pyo')
while IFS= read -r file; do
if LC_ALL=C grep -aqF "$build_prefix" "$file"; then
rm -f "$file"
fi
done < <(find "$prefix" -type f \( -name '*.pyc' -o -name '*.pyo' \))
exit
fi

View File

@ -23,11 +23,25 @@ create_interpreter() {
}
create_macos_tree() {
local prefix="${BATS_TEST_TMPDIR}/prefix"
local prefix="${BATS_TEST_TMPDIR}/prefix&target"
local lib="${prefix}/lib/python3.12"
mkdir -p "${prefix}/bin" "${lib}/lib-dynload" "${lib}/site-packages/numpy"
local old="/build prefix/3.12.7"
mkdir -p \
"${prefix}/bin" \
"${prefix}/lib/pkgconfig" \
"${lib}/__pycache__" \
"${lib}/lib-dynload" \
"${lib}/site-packages/numpy"
printf '#!/bin/sh\n' > "${prefix}/bin/python3.12"
chmod +x "${prefix}/bin/python3.12"
printf '#!%s/bin/python3.12\n' "$old" > "${prefix}/bin/pip3"
chmod +x "${prefix}/bin/pip3"
printf 'prefix=%s\n' "$old" > "${prefix}/lib/pkgconfig/python-3.12.pc"
printf 'prefix=/build prefix/3x12x7\n' > "${prefix}/lib/pkgconfig/unrelated.pc"
printf 'prefix = "%s"\n' "$old" > "${lib}/_sysconfigdata.py"
printf '\0bytecode:%s/module.py\n' "$old" > "${lib}/__pycache__/module.cpython-312.pyc"
printf '\0bytecode:%s/legacy.py\n' "$old" > "${lib}/legacy.pyo"
printf '\0sourceless bytecode\n' > "${lib}/sourceless.pyc"
touch "${prefix}/lib/libpython3.12.dylib"
touch "${lib}/lib-dynload/_ssl.cpython-312-darwin.so"
touch "${lib}/site-packages/numpy/_multiarray.so"
@ -45,6 +59,9 @@ case "$1" in
-L )
echo "${file}:"
case "$file" in
*/bin/pip3 )
exit 1
;;
*/bin/python3.12 )
if [ -n "$OTOOL_RELOCATED" ]; then
echo " @rpath/libpython3.12.dylib (compatibility version 3.12.0, current version 3.12.0)"
@ -179,7 +196,7 @@ STUB
}
@test "relocates macOS load commands without changing unrelated entries" {
local prefix="${BATS_TEST_TMPDIR}/prefix"
local prefix="${BATS_TEST_TMPDIR}/prefix&target"
local old="/build prefix/3.12.7"
local lib="${prefix}/lib/python3.12"
create_macos_tree
@ -197,10 +214,21 @@ STUB
EOF
run grep -F "${lib}/site-packages/numpy/_multiarray.so" "${BATS_TEST_TMPDIR}/otool.log"
assert_failure
run head -n 1 "${prefix}/bin/pip3"
assert_output "#!${prefix}/bin/python3.12"
run cat "${prefix}/lib/pkgconfig/python-3.12.pc"
assert_output "prefix=${prefix}"
run cat "${prefix}/lib/pkgconfig/unrelated.pc"
assert_output "prefix=/build prefix/3x12x7"
run cat "${lib}/_sysconfigdata.py"
assert_output "prefix = \"${prefix}\""
assert [ ! -e "${lib}/__pycache__/module.cpython-312.pyc" ]
assert [ ! -e "${lib}/legacy.pyo" ]
assert [ -e "${lib}/sourceless.pyc" ]
}
@test "skips already relocated macOS load commands" {
local prefix="${BATS_TEST_TMPDIR}/prefix"
local prefix="${BATS_TEST_TMPDIR}/prefix&target"
create_macos_tree
stub_macos_tools
export OTOOL_RELOCATED=1
@ -211,7 +239,7 @@ EOF
}
@test "fails when install_name_tool cannot modify a selected file" {
local prefix="${BATS_TEST_TMPDIR}/prefix"
local prefix="${BATS_TEST_TMPDIR}/prefix&target"
create_macos_tree
stub_macos_tools
create_path_executable install_name_tool 'exit 1'