Skip to content

Built Python prefers system packaged libpython when installed; local install should be built with rpath? #784

Closed

Description

@ianw

Hello,

If you happen to pull in the libpython package from the base distro into a container with the same version of Python, the built python will end up using the libpython shared-library from the system-installed package; e.g.

$ sudo docker run -it --network=host python:3.9-bullseye /bin/bash

# ldd /usr/local/bin/python3.9
	linux-vdso.so.1 (0x0000ffff9cc6a000)
	libpython3.9.so.1.0 => /usr/local/lib/libpython3.9.so.1.0 (0x0000ffff9c89a000)
        ...

# apt-get update
...

# apt-get install -y python3.9-dev
...
The following additional packages will be installed:
  libpython3.9 libpython3.9-dev
The following NEW packages will be installed:
  libpython3.9 libpython3.9-dev python3.9-dev
...

# ldd /usr/local/bin/python3.9
	linux-vdso.so.1 (0x0000ffff82c39000)
	libpython3.9.so.1.0 => /usr/lib/aarch64-linux-gnu/libpython3.9.so.1.0 (0x0000ffff82663000)
        ...

AFAICS, --enable-shared as been there basically forever (4faf7f1). From prior comments (#777 (comment)) I believe the intent here is for the /usr/local/bin/python to be strongly isolated from any packaged python.

One option to avoid this might to be to build twice, a bit like the Debian package does, so that /usr/local/bin/python3.X is self-contained, and then copy back the .so library in a second step?

The other option seems to be to add rpath linker flags to ensure that the /usr/local/bin version finds its version first. The binary could be patched post-build; I tried that, e.g. (in the same container as above)

# apt-get install patchelf
...

# patchelf --set-rpath '$ORIGIN/../lib' /usr/local/bin/python3.9

# ldd /usr/local/bin/python3.9
	linux-vdso.so.1 (0x0000ffff873dc000)
	libpython3.9.so.1.0 => /usr/local/bin/../lib/libpython3.9.so.1.0 (0x0000ffff86ffd000)
        ...

Probably that would take some thought on what other bits need patching like that.

I think the other option is to build with LDFLAGS=-Wl,-rpath='$ORIGIN/../lib'? I feel like that should ensure that everything looks relative to itself for libraries.

For full context on this -- I actually found this with Python 3.11 containers, where we had enabled unstable repos since we needed some updated packages in the container. It seems that unstable has had 3.11 packages committed recently, and we managed to pull in libpython3.11. Suddenly /usr/local/bin/python3.11 had a sys.path that only had dist-packages (not site-packages). This led me to finding that the built interpreter was using the .so from the packaged Python.

Activity

  1. yosifkit commented on Jan 13, 2023

    @yosifkit
    Member

    ❤️ Thanks for the detailed issue. Yeah, this definitely looks worth fixing. 🚀 I'll work up a PR shortly.

  2. added a commit that references this issue on Feb 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions