diff --git a/Makefile.pre.in b/Makefile.pre.in index 9658bfa44b98e4..d3c812f132bfe1 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1,4 +1,4 @@ -# Top-level Makefile for Python +# Top-level Makeile for Python # # As distributed, this file is called Makefile.pre.in; it is processed # into the real Makefile by running the script ./configure, which @@ -58,6 +58,9 @@ DTRACE_HEADERS= @DTRACE_HEADERS@ DTRACE_OBJS= @DTRACE_OBJS@ DSYMUTIL= @DSYMUTIL@ DSYMUTIL_PATH= @DSYMUTIL_PATH@ +PY_RPATH_EXEC= @PY_RPATH_EXEC@ +PY_RPATH_LIB= @PY_RPATH_LIB@ +PY_RPATH_MOD= @PY_RPATH_MOD@ GNULD= @GNULD@ @@ -915,7 +918,8 @@ clinic-tests: check-clean-src $(srcdir)/Lib/test/clinic.test.c # Build the interpreter $(BUILDPYTHON): Programs/python.o $(LINK_PYTHON_DEPS) - $(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS) + $(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) $(PY_RPATH_EXEC) -o $@ Programs/python.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS) + platform: $(PYTHON_FOR_BUILD_DEPS) pybuilddir.txt $(RUNSHARED) $(PYTHON_FOR_BUILD) -c 'import sys ; from sysconfig import get_platform ; print("%s-%d.%d" % (get_platform(), *sys.version_info[:2]))' >platform @@ -945,7 +949,7 @@ $(LIBRARY): $(LIBRARY_OBJS) $(AR) $(ARFLAGS) $@ $(LIBRARY_OBJS) libpython$(LDVERSION).so: $(LIBRARY_OBJS) $(DTRACE_OBJS) - $(BLDSHARED) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) + $(BLDSHARED) -Wl,-h$(INSTSONAME) $(PY_RPATH_LIB) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) if test $(INSTSONAME) != $@; then \ $(LN) -f $(INSTSONAME) $@; \ fi diff --git a/Misc/NEWS.d/next/Build/2025-03-26-23-34-17.gh-issue-115028.-jEZA-.rst b/Misc/NEWS.d/next/Build/2025-03-26-23-34-17.gh-issue-115028.-jEZA-.rst new file mode 100644 index 00000000000000..3a4d117f87c6d8 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2025-03-26-23-34-17.gh-issue-115028.-jEZA-.rst @@ -0,0 +1,4 @@ +Add a new ``--with-relative-rpath`` configure option that sets $ORIGIN-based +RPATHs for Python binaries when enabled. This is a first step towards making +Python installations more relocatable on Linux by allowing shared libraries +to be found relative to their binary locations. Currently Linux-only. diff --git a/Modules/makesetup b/Modules/makesetup index 8bb971b152a522..b7e57c2969c198 100755 --- a/Modules/makesetup +++ b/Modules/makesetup @@ -274,7 +274,7 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | ;; esac rule="$file: $objs" - rule="$rule; \$(BLDSHARED) $objs $libs \$(LIBPYTHON) -o $file" + rule="$rule; \$(BLDSHARED) \$(PY_RPATH_MOD) $objs $libs \$(LIBPYTHON) -o $file" echo "$rule" >>$rulesf done done diff --git a/configure b/configure index a058553480ca5a..24cb5ef3dc827b 100755 --- a/configure +++ b/configure @@ -894,6 +894,9 @@ BLDSHARED LDCXXSHARED LDSHARED SHLIB_SUFFIX +PY_RPATH_MOD +PY_RPATH_LIB +PY_RPATH_EXEC DSYMUTIL_PATH DSYMUTIL UNIVERSAL_ARCH_FLAGS @@ -1100,6 +1103,7 @@ with_address_sanitizer with_memory_sanitizer with_undefined_behavior_sanitizer with_thread_sanitizer +with_relative_rpath with_hash_algorithm with_tzpath with_libs @@ -1889,6 +1893,8 @@ Optional Packages: behaviour detector, 'ubsan' (default is no) --with-thread-sanitizer enable ThreadSanitizer data race detector, 'tsan' (default is no) + --with-relative-rpath use relative rpath with $ORIGIN for binaries (Linux + only) --with-hash-algorithm=[fnv|siphash13|siphash24] select hash algorithm for use in Python/pyhash.c (default is SipHash13) @@ -13441,6 +13447,48 @@ esac fi +# Check for --with-relative-rpath +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --with-relative-rpath" >&5 +printf %s "checking for --with-relative-rpath... " >&6; } + +# Check whether --with-relative-rpath was given. +if test ${with_relative_rpath+y} +then : + withval=$with_relative_rpath; +else case e in #( + e) with_relative_rpath=no ;; +esac +fi + + +# Initialize empty RPATH variables +PY_RPATH_EXEC="" +PY_RPATH_LIB="" +PY_RPATH_MOD="" + +if test "$with_relative_rpath" = "yes"; then + if test "$ac_sys_system" = "Linux"; then + # Define the RPATH settings for each binary type + PY_RPATH_EXEC="-Wl,-rpath,\\\$\$ORIGIN/../\$(PLATLIBDIR)" + PY_RPATH_LIB="-Wl,-rpath,\\\$\$ORIGIN" + PY_RPATH_MOD="-Wl,-rpath,\\\$\$ORIGIN/../../" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no - only supported on Linux" >&5 +printf "%s\n" "no - only supported on Linux" >&6; } + with_relative_rpath=no + fi +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + +# Export these variables for the Makefile + + + + # Set info about shared libraries. diff --git a/configure.ac b/configure.ac index 23bd81ed4431b9..ebaa8c908763ed 100644 --- a/configure.ac +++ b/configure.ac @@ -3356,6 +3356,38 @@ AC_MSG_RESULT([no]) with_tsan="no" ]) +# Check for --with-relative-rpath +AC_MSG_CHECKING([for --with-relative-rpath]) +AC_ARG_WITH([relative-rpath], + [AS_HELP_STRING([--with-relative-rpath], + [use relative rpath with $ORIGIN for binaries (Linux only)])], + [], [with_relative_rpath=no]) + +# Initialize empty RPATH variables +PY_RPATH_EXEC="" +PY_RPATH_LIB="" +PY_RPATH_MOD="" + +if test "$with_relative_rpath" = "yes"; then + if test "$ac_sys_system" = "Linux"; then + # Define the RPATH settings for each binary type + PY_RPATH_EXEC="-Wl,-rpath,\\\$\$ORIGIN/../\$(PLATLIBDIR)" + PY_RPATH_LIB="-Wl,-rpath,\\\$\$ORIGIN" + PY_RPATH_MOD="-Wl,-rpath,\\\$\$ORIGIN/../../" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no - only supported on Linux]) + with_relative_rpath=no + fi +else + AC_MSG_RESULT([no]) +fi + +# Export these variables for the Makefile +AC_SUBST([PY_RPATH_EXEC]) +AC_SUBST([PY_RPATH_LIB]) +AC_SUBST([PY_RPATH_MOD]) + # Set info about shared libraries. AC_SUBST([SHLIB_SUFFIX]) AC_SUBST([LDSHARED])