Skip to content

Commit 23456cb

Browse files
committed
Revert "Add an rpath to bin/python3 on glibc platforms to fix #619 (#621)"
This reverts commit 482a9bc.
1 parent 482a9bc commit 23456cb

File tree

1 file changed

+23
-83
lines changed

1 file changed

+23
-83
lines changed

cpython-unix/build-cpython.sh

Lines changed: 23 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -688,105 +688,45 @@ if [ "${PYBUILD_SHARED}" = "1" ]; then
688688
-change /install/lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME} @executable_path/../lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME} \
689689
${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}
690690
fi
691-
else # (not macos)
691+
else
692692
LIBPYTHON_SHARED_LIBRARY_BASENAME=libpython${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}.so.1.0
693693
LIBPYTHON_SHARED_LIBRARY=${ROOT}/out/python/install/lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME}
694694

695-
# Although we are statically linking libpython, some extension
696-
# modules link against libpython.so even though they are not
697-
# supposed to do that. If you try to import them on an
698-
# interpreter statically linking libpython, all the symbols they
699-
# need are resolved from the main program (because neither glibc
700-
# nor musl has two-level namespaces), so there is hopefully no
701-
# correctness risk, but they need to be able to successfully
702-
# find libpython.so in order to load the module. To allow such
703-
# extensions to load, we set an rpath to point at our lib
704-
# directory, so that if anyone ever tries to find a libpython,
705-
# they successfully find one. See
706-
# https://github.com/astral-sh/python-build-standalone/issues/619
707-
# for some reports of extensions that need this workaround.
708-
#
709-
# Note that this matches the behavior of Debian/Ubuntu/etc.'s
710-
# interpreter (if package libpython3.x is installed, which it
711-
# usually is thanks to gdb, vim, etc.), because libpython is in
712-
# the system lib directory, as well as the behavior in practice
713-
# on conda-forge miniconda and probably other Conda-family
714-
# Python distributions, which too set an rpath.
715-
#
716-
# There is a downside of making this libpython locatable: some user
717-
# code might do e.g.
718-
# ctypes.CDLL(f"libpython3.{sys.version_info.minor}.so.1.0")
719-
# to get at things in the CPython API not exposed to pure
720-
# Python. This code may _silently misbehave_ on a
721-
# static-libpython interpreter, because you are actually using
722-
# the second copy of libpython. For loading static data or using
723-
# accessors, you might get lucky and things will work, with the
724-
# full set of dangers of C undefined behavior being possible.
725-
# However, there are a few reasons we think this risk is
726-
# tolerable. First, we can't actually fix it by not setting the
727-
# rpath - user code may well find a system libpython3.x.so or
728-
# something which is even more likely to break. Second, this
729-
# exact problem happens with Debian, Conda, etc., so it is very
730-
# unlikely (compared to the extension modules case above) that
731-
# any widely-used code has this problem; the risk is largely
732-
# backwards incompatibility of our own builds. Also, it's quite
733-
# easy for users to fix: simply do
734-
# ctypes.CDLL(None)
735-
# (i.e., dlopen(NULL)), to use symbols already in the process;
736-
# this will work reliably on all interpreters regardless of
737-
# whether they statically or dynamically link libpython. Finally,
738-
# we can (and should, at some point) add a warning, error, or
739-
# silent fix to ctypes for user code that does this, which will
740-
# also cover the case of other libpython3.x.so files on the
741-
# library search path that we cannot suppress.
742-
#
743-
# In the past, when we dynamically linked libpython, we avoided
744-
# using an rpath and instead used a DT_NEEDED entry with
745-
# $ORIGIN/../lib/libpython.so, because LD_LIBRARY_PATH takes
746-
# precedence over DT_RUNPATH, and it's not uncommon to have an
747-
# LD_LIBRARY_PATH that points to some sort of unwanted libpython
748-
# (e.g., actions/setup-python does this as of May 2025).
749-
# Now, though, because we're not actually using code from the
750-
# libpython that's loaded and just need _any_ file of that name
751-
# to satisfy the link, that's not a problem. (This also implies
752-
# another approach to the problem: ensure that libraries find an
753-
# empty dummy libpython.so, which allows the link to succeed but
754-
# ensures they do not use any unwanted symbols. That might be
755-
# worth doing at some point.)
756-
patchelf --set-rpath "\$ORIGIN/../lib" \
757-
${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}
758-
759-
if [ -n "${PYTHON_BINARY_SUFFIX}" ]; then
695+
if [ "${CC}" == "musl-clang" ]; then
696+
# musl does not support $ORIGIN in DT_NEEDED, so we use RPATH instead. This could be
697+
# problematic, i.e., we could load the shared library from the wrong location if
698+
# `LD_LIBRARY_PATH` is set, but there's not a clear alternative at this time. The
699+
# long term solution is probably to statically link to libpython instead.
760700
patchelf --set-rpath "\$ORIGIN/../lib" \
761-
${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}
762-
fi
701+
${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}
763702

764-
# For libpython3.so (the ABI3 library for embedders), we do
765-
# still dynamically link libpython3.x.so.1.0 (the
766-
# version-specific library), because there is no particular
767-
# speedup/benefit in statically linking libpython into
768-
# libpython3.so, and we'd just be shipping a third copy of the
769-
# libpython code. Therefore we use the old logic for that and
770-
# set an $ORIGIN-relative DT_NEEDED, at least for glibc.
771-
# Unfortunately, musl does not (as of May 2025) support $ORIGIN
772-
# in DT_NEEDED, only in DT_RUNPATH/RPATH, so we did set an rpath
773-
# for bin/python3, and still do for libpython3.so. In both
774-
# cases, we have no concerns/need no workarounds for code
775-
# referencing libpython3.x.so.1.0, because we are actually
776-
# dynamically linking it and so all code will get the real
777-
# libpython3.x.so.1.0 that they want.
778-
if [ "${CC}" == "musl-clang" ]; then
779703
# libpython3.so isn't present in debug builds.
780704
if [ -z "${CPYTHON_DEBUG}" ]; then
781705
patchelf --set-rpath "\$ORIGIN/../lib" \
782706
${ROOT}/out/python/install/lib/libpython3.so
783707
fi
708+
709+
if [ -n "${PYTHON_BINARY_SUFFIX}" ]; then
710+
patchelf --set-rpath "\$ORIGIN/../lib" \
711+
${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}
712+
fi
784713
else
714+
# If we simply set DT_RUNPATH via --set-rpath, LD_LIBRARY_PATH would be used before
715+
# DT_RUNPATH, which could result in confusion at run-time. But if DT_NEEDED contains a
716+
# slash, the explicit path is used.
717+
patchelf --replace-needed ${LIBPYTHON_SHARED_LIBRARY_BASENAME} "\$ORIGIN/../lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME}" \
718+
${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}
719+
785720
# libpython3.so isn't present in debug builds.
786721
if [ -z "${CPYTHON_DEBUG}" ]; then
787722
patchelf --replace-needed ${LIBPYTHON_SHARED_LIBRARY_BASENAME} "\$ORIGIN/../lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME}" \
788723
${ROOT}/out/python/install/lib/libpython3.so
789724
fi
725+
726+
if [ -n "${PYTHON_BINARY_SUFFIX}" ]; then
727+
patchelf --replace-needed ${LIBPYTHON_SHARED_LIBRARY_BASENAME} "\$ORIGIN/../lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME}" \
728+
${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}
729+
fi
790730
fi
791731
fi
792732
fi

0 commit comments

Comments
 (0)