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
32 changes: 27 additions & 5 deletions cpython-unix/build-cpython.sh
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ cat Makefile.extra

pushd Python-${PYTHON_VERSION}


if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_15}" ]; then
# add `--enable-relocatable`
patch -p1 -i ${ROOT}/patch-relocatable-flag.patch
# add native support for rpath
patch -p1 -i ${ROOT}/patch-relocatable-link.patch
fi

# configure doesn't support cross-compiling on Apple. Teach it.
if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then
Expand Down Expand Up @@ -157,10 +165,12 @@ fi

# The default build rule for the macOS dylib doesn't pick up libraries
# from modules / makesetup. So patch it accordingly.
if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then
patch -p1 -i ${ROOT}/patch-macos-link-extension-modules-13.patch
else
patch -p1 -i ${ROOT}/patch-macos-link-extension-modules.patch
if [ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_14}" ]; then
if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then
patch -p1 -i ${ROOT}/patch-macos-link-extension-modules-13.patch
else
patch -p1 -i ${ROOT}/patch-macos-link-extension-modules.patch
fi
fi

# Also on macOS, the `python` executable is linked against libraries defined by statically
Expand Down Expand Up @@ -369,6 +379,11 @@ if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
LDFLAGS="${LDFLAGS} -Wl,-headerpad,40"
fi


if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_15}" ]; then
EXTRA_CONFIGURE_FLAGS="${EXTRA_CONFIGURE_FLAGS} --enable-relocatable"
fi

CPPFLAGS=$CFLAGS

CONFIGURE_FLAGS="
Expand Down Expand Up @@ -676,7 +691,8 @@ fi
# If we're building a shared library hack some binaries so rpath is set.
# This ensures we can run the binary in any location without
# LD_LIBRARY_PATH pointing to the directory containing libpython.
if [ "${PYBUILD_SHARED}" = "1" ]; then
# In 3.15+, we've upstreamed this behavior
if [[ "${PYBUILD_SHARED}" = "1" && -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_14}" ]]; then
if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
# There's only 1 dylib produced on macOS and it has the binary suffix.
LIBPYTHON_SHARED_LIBRARY_BASENAME=libpython${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}.dylib
Expand Down Expand Up @@ -816,6 +832,12 @@ if [ "${PYBUILD_SHARED}" = "1" ]; then
fi
fi
fi
else
# For Python 3.15+ on Linux, we still need to define LIBPYTHON_SHARED_LIBRARY for glibc version detection
if [[ "${PYBUILD_PLATFORM}" != macos* ]]; then
LIBPYTHON_SHARED_LIBRARY_BASENAME=libpython${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}.so.1.0
LIBPYTHON_SHARED_LIBRARY=${ROOT}/out/python/install/lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME}
fi
fi

# Install setuptools and pip as they are common tools that should be in any
Expand Down
121 changes: 121 additions & 0 deletions cpython-unix/patch-relocatable-flag.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
commit 6187c3916ac1e7e6eb2bff7ca5f976c99cbe273b
Author: Zanie Blue <[email protected]>
Date: Sat Nov 15 08:47:20 2025 -0600

Add an `--enable-relocatable` configure flag

diff --git a/Makefile.pre.in b/Makefile.pre.in
index 19423c11545..6c9cba59e27 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -60,6 +60,7 @@ DSYMUTIL= @DSYMUTIL@
DSYMUTIL_PATH= @DSYMUTIL_PATH@

GNULD= @GNULD@
+RELOCATABLE= @RELOCATABLE@

# Shell used by make (some versions default to the login shell, which is bad)
SHELL= /bin/sh -e
diff --git a/configure b/configure
index 9757b3419d3..38f2d4dfbf2 100755
--- a/configure
+++ b/configure
@@ -949,6 +949,7 @@ LINK_PYTHON_DEPS
LIBRARY_DEPS
HOSTRUNNER
NODE
+RELOCATABLE
STATIC_LIBPYTHON
GNULD
EXPORTSFROM
@@ -1091,6 +1092,7 @@ with_suffix
enable_shared
with_static_libpython
enable_profiling
+enable_relocatable
enable_gil
with_pydebug
with_trace_refs
@@ -1826,6 +1828,8 @@ Optional Features:
no)
--enable-profiling enable C-level code profiling with gprof (default is
no)
+ --enable-relocatable enable build of a relocatable Python distribution
+ (default is no)
--disable-gil enable support for running without the GIL (default
is no)
--enable-pystats enable internal statistics gathering (default is no)
@@ -7673,6 +7677,31 @@ if test "x$enable_profiling" = xyes; then
LDFLAGS="-pg $LDFLAGS"
fi

+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --enable-relocatable" >&5
+printf %s "checking for --enable-relocatable... " >&6; }
+# Check whether --enable-relocatable was given.
+if test ${enable_relocatable+y}
+then :
+ enableval=$enable_relocatable;
+fi
+
+if test -z "$enable_relocatable"
+then
+ enable_relocatable="no"
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_relocatable" >&5
+printf "%s\n" "$enable_relocatable" >&6; }
+
+if test "x$enable_relocatable" = xyes; then
+
+printf "%s\n" "#define Py_ENABLE_RELOCATABLE 1" >>confdefs.h
+
+ RELOCATABLE=yes
+else
+ RELOCATABLE=no
+fi
+
+
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking LDLIBRARY" >&5
printf %s "checking LDLIBRARY... " >&6; }

diff --git a/configure.ac b/configure.ac
index f244e0b71a6..b1c859071f4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1523,6 +1523,23 @@ if test "x$enable_profiling" = xyes; then
LDFLAGS="-pg $LDFLAGS"
fi

+AC_MSG_CHECKING([for --enable-relocatable])
+AC_ARG_ENABLE([relocatable],
+ AS_HELP_STRING([--enable-relocatable], [enable build of a relocatable Python distribution (default is no)]))
+if test -z "$enable_relocatable"
+then
+ enable_relocatable="no"
+fi
+AC_MSG_RESULT([$enable_relocatable])
+
+if test "x$enable_relocatable" = xyes; then
+ AC_DEFINE([Py_ENABLE_RELOCATABLE], [1], [Define if --enable-relocatable is used])
+ RELOCATABLE=yes
+else
+ RELOCATABLE=no
+fi
+AC_SUBST([RELOCATABLE])
+
AC_MSG_CHECKING([LDLIBRARY])

# Apple framework builds need more magic. LDLIBRARY is the dynamic
diff --git a/pyconfig.h.in b/pyconfig.h.in
index 72870411bc0..76fe6a9b52c 100644
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -1733,6 +1733,9 @@
/* Define if you want to build an interpreter with many run-time checks. */
#undef Py_DEBUG

+/* Define if --enable-relocatable is used */
+#undef Py_ENABLE_RELOCATABLE
+
/* Defined if Python is built as a shared library. */
#undef Py_ENABLE_SHARED

70 changes: 70 additions & 0 deletions cpython-unix/patch-relocatable-link.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
commit 34915211b42a64082e0470ebb9a8c4f2ebb20512
Author: Zanie Blue <[email protected]>
Date: Fri Nov 21 15:44:42 2025 -0600

Set linker arguments when `--enabled-relocatable` is used

diff --git a/Makefile.pre.in b/Makefile.pre.in
index 6c9cba59e27..6c89690c35e 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -1025,10 +1025,19 @@ libpython$(LDVERSION).so: $(LIBRARY_OBJS) $(DTRACE_OBJS)
fi

libpython3.so: libpython$(LDVERSION).so
- $(BLDSHARED) $(NO_AS_NEEDED) -o $@ -Wl,-h$@ $^
+ if [ "$(RELOCATABLE)" = "yes" ]; then \
+ $(BLDSHARED) $(NO_AS_NEEDED) -o $@ -Wl,-h$@ -Wl,-rpath,'$$ORIGIN' $^; \
+ else \
+ $(BLDSHARED) $(NO_AS_NEEDED) -o $@ -Wl,-h$@ $^; \
+ fi

libpython$(LDVERSION).dylib: $(LIBRARY_OBJS)
- $(CC) -dynamiclib $(PY_CORE_LDFLAGS) -undefined dynamic_lookup -Wl,-install_name,$(prefix)/lib/libpython$(LDVERSION).dylib -Wl,-compatibility_version,$(VERSION) -Wl,-current_version,$(VERSION) -o $@ $(LIBRARY_OBJS) $(DTRACE_OBJS) $(SHLIBS) $(LIBC) $(LIBM); \
+ if [ "$(RELOCATABLE)" = "yes" ]; then \
+ install_name="@executable_path/../lib/libpython$(LDVERSION).dylib"; \
+ else \
+ install_name="$(prefix)/lib/libpython$(LDVERSION).dylib"; \
+ fi; \
+ $(CC) -dynamiclib $(PY_CORE_LDFLAGS) -undefined dynamic_lookup -Wl,-install_name,$$install_name -Wl,-compatibility_version,$(VERSION) -Wl,-current_version,$(VERSION) -o $@ $(LIBRARY_OBJS) $(DTRACE_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM);


libpython$(VERSION).sl: $(LIBRARY_OBJS)
diff --git a/configure b/configure
index 38f2d4dfbf2..9991932680e 100755
--- a/configure
+++ b/configure
@@ -13749,7 +13749,13 @@ then
LINKFORSHARED="-Wl,-E -Wl,+s";;
# LINKFORSHARED="-Wl,-E -Wl,+s -Wl,+b\$(BINLIBDEST)/lib-dynload";;
Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";;
- Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";;
+ Linux*|GNU*)
+ LINKFORSHARED="-Xlinker -export-dynamic"
+ # Add rpath for relocatable builds
+ if test "x$enable_relocatable" = xyes; then
+ LINKFORSHARED="$LINKFORSHARED -Wl,-rpath=\$ORIGIN/../lib"
+ fi
+ ;;
# -u libsys_s pulls in all symbols in libsys
Darwin/*|iOS/*)
LINKFORSHARED="$extra_undefs -framework CoreFoundation"
diff --git a/configure.ac b/configure.ac
index b1c859071f4..f75f41441e2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3613,7 +3613,13 @@ then
LINKFORSHARED="-Wl,-E -Wl,+s";;
# LINKFORSHARED="-Wl,-E -Wl,+s -Wl,+b\$(BINLIBDEST)/lib-dynload";;
Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";;
- Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";;
+ Linux*|GNU*)
+ LINKFORSHARED="-Xlinker -export-dynamic"
+ # Add rpath for relocatable builds
+ if test "x$enable_relocatable" = xyes; then
+ LINKFORSHARED="$LINKFORSHARED -Wl,-rpath=\$ORIGIN/../lib"
+ fi
+ ;;
# -u libsys_s pulls in all symbols in libsys
Darwin/*|iOS/*)
LINKFORSHARED="$extra_undefs -framework CoreFoundation"
Loading