Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,22 @@ jobs:
if: needs.build-context.outputs.run-ubuntu == 'true'
uses: ./.github/workflows/reusable-install.yml

build-ubuntu-relocatable:
name: 'Ubuntu (relocatable)'
needs: build-context
if: needs.build-context.outputs.run-ubuntu == 'true'
uses: ./.github/workflows/reusable-relocatable.yml
with:
os: ubuntu-26.04-arm

build-macos-relocatable:
name: 'macOS (relocatable)'
needs: build-context
if: needs.build-context.outputs.run-macos == 'true'
uses: ./.github/workflows/reusable-relocatable.yml
with:
os: macos-26

build-ubuntu-ssltests:
name: 'Ubuntu SSL tests'
runs-on: ${{ matrix.os }}
Expand Down Expand Up @@ -651,6 +667,8 @@ jobs:
- build-macos
- build-ubuntu
- build-ubuntu-installed
- build-ubuntu-relocatable
- build-macos-relocatable
- build-ubuntu-ssltests
- build-ios
- build-emscripten
Expand Down Expand Up @@ -696,12 +714,13 @@ jobs:
&& 'cifuzz,' ||
''
}}
${{ !fromJSON(needs.build-context.outputs.run-macos) && 'build-macos,' || '' }}
${{ !fromJSON(needs.build-context.outputs.run-macos) && 'build-macos,build-macos-relocatable,' || '' }}
${{
!fromJSON(needs.build-context.outputs.run-ubuntu)
&& '
build-ubuntu,
build-ubuntu-installed,
build-ubuntu-relocatable,
build-ubuntu-ssltests,
test-hypothesis,
build-asan,
Expand Down
134 changes: 134 additions & 0 deletions .github/workflows/reusable-relocatable.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
name: Reusable relocatable Python

on:
workflow_call:
inputs:
os:
type: string
required: true

permissions:
contents: read

env:
FORCE_COLOR: 1

jobs:
build-install-test:
name: build, relocate and test
runs-on: ${{ inputs.os }}
timeout-minutes: 60
defaults:
run:
shell: bash
env:
PYTHONSTRICTEXTENSIONBUILD: 1
HOMEBREW_NO_ANALYTICS: 1
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set build and installation directories
run: |
echo "BUILD_DIR=$RUNNER_TEMP/relocatable-build" >> "$GITHUB_ENV"
echo "INSTALL_DIR=$RUNNER_TEMP/relocatable-install" >> "$GITHUB_ENV"
- name: Install dependencies
if: runner.os == 'Linux'
run: sudo ./.github/workflows/posix-deps-apt.sh
- name: Install Homebrew dependencies
if: runner.os == 'macOS'
run: |
brew bundle --file=Misc/Brewfile
brew install make
echo "GDBM_CFLAGS=-I$(brew --prefix gdbm)/include" >> "$GITHUB_ENV"
echo "GDBM_LIBS=-L$(brew --prefix gdbm)/lib -lgdbm" >> "$GITHUB_ENV"
echo "OPENSSL_DIR=$(brew --prefix openssl@3.5)" >> "$GITHUB_ENV"
- name: Reject unsupported framework relocation
if: runner.os == 'macOS'
run: |
mkdir "$RUNNER_TEMP/framework-configure"
cd "$RUNNER_TEMP/framework-configure"
if "$GITHUB_WORKSPACE/configure" \
--enable-framework="$RUNNER_TEMP/framework-install" \
--enable-relocatable --with-openssl="$OPENSSL_DIR" > configure.log 2>&1; then
cat configure.log
exit 1
fi
cat configure.log
grep -F 'does not support framework builds yet' configure.log
- name: Configure CPython
run: |
mkdir "$BUILD_DIR"
cd "$BUILD_DIR"
configure_args=(--prefix="$INSTALL_DIR" --enable-shared --enable-relocatable)
if [ -n "${OPENSSL_DIR:-}" ]; then
configure_args+=(--with-openssl="$OPENSSL_DIR")
fi
"$GITHUB_WORKSPACE/configure" "${configure_args[@]}"
- name: Build and install CPython
working-directory: ${{ env.BUILD_DIR }}
run: |
make_command="make"
if [ "$RUNNER_OS" = macOS ]; then
make_command="gmake"
fi
"$make_command" -j4
"$make_command" install
- name: Check build-tree library selection
if: runner.os == 'Linux'
run: |
fixture="$RUNNER_TEMP/library-selection"
mkdir -p "$fixture/build" "$fixture/lib"
cp "$BUILD_DIR/python" "$BUILD_DIR/libpython"*.so.1.0 "$fixture/build/"
cat > "$fixture/wrong-library.c" <<'C'
int Py_BytesMain(int argc, char **argv) { return 79; }
C
library=$(basename "$BUILD_DIR"/libpython*.so.1.0)
cc -shared -fPIC "$fixture/wrong-library.c" \
-Wl,-soname,"$library" -o "$fixture/lib/$library"
LD_LIBRARY_PATH="$fixture/build" PYTHONHOME="$INSTALL_DIR" \
"$fixture/build/python" -c 'import sys; print(sys.version)'
- name: Move the installation and build directory
run: |
mv "$INSTALL_DIR" "${INSTALL_DIR} moved"
mv "$BUILD_DIR" "${BUILD_DIR}-unavailable"
echo "INSTALL_DIR=${INSTALL_DIR} moved" >> "$GITHUB_ENV"
- name: Run the relocated interpreter
run: |
unset LD_LIBRARY_PATH LD_PRELOAD
unset DYLD_LIBRARY_PATH DYLD_FALLBACK_LIBRARY_PATH DYLD_INSERT_LIBRARIES
installed_python="$INSTALL_DIR/bin/python3"
"$installed_python" -I - <<'PY'
import os
import subprocess
import sys
import sysconfig
import tempfile
import venv

prefix = os.path.realpath(os.environ['INSTALL_DIR'])
assert os.path.realpath(sys.prefix) == prefix, sys.prefix
assert sys.exec_prefix == sys.prefix, sys.exec_prefix
assert sysconfig.get_config_var('RELOCATABLE') == 'yes'
assert not sysconfig.is_python_build()
for entry in sys.path:
assert os.path.commonpath((prefix, os.path.realpath(entry))) == prefix, entry
for symlinks in (False, True):
with tempfile.TemporaryDirectory() as directory:
venv.EnvBuilder(symlinks=symlinks).create(directory)
subprocess.run([
os.path.join(directory, 'bin', 'python'), '-I', '-c',
'import ctypes, sys, sysconfig; '
'ctypes.CDLL(("@rpath/" if sys.platform == "darwin" else "") + '
'sysconfig.get_config_var("INSTSONAME"))',
], check=True)
PY
"$installed_python" -m test.pythoninfo
if [ "$RUNNER_OS" = Linux ]; then
xvfb-run "$installed_python" -m test --fast-ci --timeout=900
else
"$installed_python" -m test --fast-ci --timeout=900
fi
Loading