From 8443deaacccb8e7e33eb4b5c881418ce33d8ffe1 Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Sat, 15 Nov 2025 08:52:53 -0600 Subject: [PATCH 1/4] Add `--enable-relocatable` patch for 3.15+ --- cpython-unix/build-cpython.sh | 11 ++ cpython-unix/patch-relocatable-flag.patch | 121 ++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 cpython-unix/patch-relocatable-flag.patch diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh index 9c65394e..d7f43015 100755 --- a/cpython-unix/build-cpython.sh +++ b/cpython-unix/build-cpython.sh @@ -58,6 +58,12 @@ cat Makefile.extra pushd Python-${PYTHON_VERSION} + +# add `--enable-relocatable` +if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_15}" ]; then + patch -p1 -i ${ROOT}/patch-reloctable-flag.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 @@ -369,6 +375,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=" diff --git a/cpython-unix/patch-relocatable-flag.patch b/cpython-unix/patch-relocatable-flag.patch new file mode 100644 index 00000000..96688a8a --- /dev/null +++ b/cpython-unix/patch-relocatable-flag.patch @@ -0,0 +1,121 @@ +commit 6187c3916ac1e7e6eb2bff7ca5f976c99cbe273b +Author: Zanie Blue +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 + From 8cc2387b27af65ad7cf6d861907fee69c43e15ae Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Thu, 20 Nov 2025 18:05:13 -0600 Subject: [PATCH 2/4] Make the relocatable flag do something --- cpython-unix/build-cpython.sh | 19 ++++-- cpython-unix/patch-relocatable-link.patch | 78 +++++++++++++++++++++++ 2 files changed, 90 insertions(+), 7 deletions(-) create mode 100644 cpython-unix/patch-relocatable-link.patch diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh index d7f43015..683ab875 100755 --- a/cpython-unix/build-cpython.sh +++ b/cpython-unix/build-cpython.sh @@ -59,9 +59,11 @@ cat Makefile.extra pushd Python-${PYTHON_VERSION} -# add `--enable-relocatable` if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_15}" ]; then - patch -p1 -i ${ROOT}/patch-reloctable-flag.patch + # 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. @@ -163,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 @@ -687,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 diff --git a/cpython-unix/patch-relocatable-link.patch b/cpython-unix/patch-relocatable-link.patch new file mode 100644 index 00000000..8eba58d5 --- /dev/null +++ b/cpython-unix/patch-relocatable-link.patch @@ -0,0 +1,78 @@ +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 6c9cba59e27..39fc2e911d0 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -1028,7 +1028,12 @@ libpython3.so: libpython$(LDVERSION).so + $(BLDSHARED) $(NO_AS_NEEDED) -o $@ -Wl,-h$@ $^ + + 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..153add6ac12 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" +@@ -13774,6 +13780,10 @@ printf "%s\n" "#define THREAD_STACK_SIZE 0x$stack_size" >>confdefs.h + if test "$enable_framework"; then + LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' + fi ++ # Add rpath for relocatable builds ++ if test "x$enable_relocatable" = xyes; then ++ LINKFORSHARED="$LINKFORSHARED -Wl,-rpath,@executable_path/../lib" ++ fi + LINKFORSHARED="$LINKFORSHARED" + elif test $ac_sys_system = "iOS"; then + LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)' +diff --git a/configure.ac b/configure.ac +index b1c859071f4..a40d279ebab 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" +@@ -3638,6 +3644,10 @@ then + if test "$enable_framework"; then + LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' + fi ++ # Add rpath for relocatable builds ++ if test "x$enable_relocatable" = xyes; then ++ LINKFORSHARED="$LINKFORSHARED -Wl,-rpath,@executable_path/../lib" ++ fi + LINKFORSHARED="$LINKFORSHARED" + elif test $ac_sys_system = "iOS"; then + LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)' From a30ce17759078384af3366fae65f87a1b8f5745d Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Fri, 21 Nov 2025 10:26:17 -0600 Subject: [PATCH 3/4] Retain `LIBPYTHON_SHARED_LIBRARY=` on Linux? --- cpython-unix/build-cpython.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh index 683ab875..2080a200 100755 --- a/cpython-unix/build-cpython.sh +++ b/cpython-unix/build-cpython.sh @@ -832,6 +832,12 @@ if [[ "${PYBUILD_SHARED}" = "1" && -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_14}" ]] 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 From d715fa391de2e7fef815ba8e11bf3da90d511d12 Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Fri, 21 Nov 2025 12:41:24 -0600 Subject: [PATCH 4/4] Add rpath for `libpython3.so` --- cpython-unix/patch-relocatable-link.patch | 46 ++++++++++------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/cpython-unix/patch-relocatable-link.patch b/cpython-unix/patch-relocatable-link.patch index 8eba58d5..5863d9c2 100644 --- a/cpython-unix/patch-relocatable-link.patch +++ b/cpython-unix/patch-relocatable-link.patch @@ -1,9 +1,23 @@ +commit 34915211b42a64082e0470ebb9a8c4f2ebb20512 +Author: Zanie Blue +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..39fc2e911d0 100644 +index 6c9cba59e27..6c89690c35e 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in -@@ -1028,7 +1028,12 @@ libpython3.so: libpython$(LDVERSION).so - $(BLDSHARED) $(NO_AS_NEEDED) -o $@ -Wl,-h$@ $^ +@@ -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); \ @@ -17,7 +31,7 @@ index 6c9cba59e27..39fc2e911d0 100644 libpython$(VERSION).sl: $(LIBRARY_OBJS) diff --git a/configure b/configure -index 38f2d4dfbf2..153add6ac12 100755 +index 38f2d4dfbf2..9991932680e 100755 --- a/configure +++ b/configure @@ -13749,7 +13749,13 @@ then @@ -35,19 +49,8 @@ index 38f2d4dfbf2..153add6ac12 100755 # -u libsys_s pulls in all symbols in libsys Darwin/*|iOS/*) LINKFORSHARED="$extra_undefs -framework CoreFoundation" -@@ -13774,6 +13780,10 @@ printf "%s\n" "#define THREAD_STACK_SIZE 0x$stack_size" >>confdefs.h - if test "$enable_framework"; then - LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' - fi -+ # Add rpath for relocatable builds -+ if test "x$enable_relocatable" = xyes; then -+ LINKFORSHARED="$LINKFORSHARED -Wl,-rpath,@executable_path/../lib" -+ fi - LINKFORSHARED="$LINKFORSHARED" - elif test $ac_sys_system = "iOS"; then - LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)' diff --git a/configure.ac b/configure.ac -index b1c859071f4..a40d279ebab 100644 +index b1c859071f4..f75f41441e2 100644 --- a/configure.ac +++ b/configure.ac @@ -3613,7 +3613,13 @@ then @@ -65,14 +68,3 @@ index b1c859071f4..a40d279ebab 100644 # -u libsys_s pulls in all symbols in libsys Darwin/*|iOS/*) LINKFORSHARED="$extra_undefs -framework CoreFoundation" -@@ -3638,6 +3644,10 @@ then - if test "$enable_framework"; then - LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' - fi -+ # Add rpath for relocatable builds -+ if test "x$enable_relocatable" = xyes; then -+ LINKFORSHARED="$LINKFORSHARED -Wl,-rpath,@executable_path/../lib" -+ fi - LINKFORSHARED="$LINKFORSHARED" - elif test $ac_sys_system = "iOS"; then - LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)'