astral-sh / astral-sh/python-build-standalone
Set rpath on our shared libraries, and use ORIGIN-relative dependencies for libtcl and libtk
- Dominant language
- Python
- Stars
- 4.4k
- Forks
- 314
- Avg merge
- 1d 9h
- Merged PRs (30d)
- 27
Description
As a result of #619 I added a `DT_RPATH` to bin/python3 to support third-party wheels that (incorrectly) link libpython3.x.so.1.0 and expect to be able to find it. The symbols come from bin/python3, we just needed libraries to be able to not fail when resolving dependencies by filename. In other words, we weren't actually using the `DT_RPATH` ourselves. By the same logic, I didn't add an rpath to libpython3.x.so.1.0 itself, because it didn't need to load any _other_ libraries.
In #676 I added two more shared libraries, libtcl8.6.so and libtk8.6.so. On Linux these are referenced with an unqualified name in _tkinter, and so they only work because of the `DT_RPATH` on bin/python3. That is a bug, both because we shouldn't be relying on the bin/python rpath ourselves (so we have the option to remove it later), and because it means that embedders linking libpython3 won't be able to load _tkinter properly without setting an rpath of their own. (On macOS, these are referenced through an rpath in _tkinter, so I think this works properly for embedders.)
Also, pyinstaller/pyinstaller#9204 requests that we make `ldd .../_tkinter.cpython-xxx.so` report the path of libtcl and libtk properly.
I think I want to make the following changes:
* Set `DT_RPATH` on all of our shared libraries, for consistency. Probably including `libpython3.so` (the ABI3 interface).
* On glibc, use `${ORIGIN}`-relative `DT_NEEDED` entries for the dependenci from tkinter to libtcl and libtk, so that it can still find them if the embedder is using `DT_RUNPATH`, which suppresses `DT_RPATH`.
* Add validation tests that we have rpaths on all dynamic objects and`${ORIGIN}`-relative `DT_NEEDED` entries on glibc except for things that are provided by the OS.
* Analogously on macOS, ensure we have relative `LC_LOAD_DYLIB` commands for everything not provided by the OS. (This can be `@executable_path`-relative, `@loader_path`-relative, or `@rpath`-relative if we also have an `LC_RPATH` that is executable- or loader-relative. Note that rpaths work a little differently with macOS dyld - they're not used by default, they're only used for things that are specifically loaded from `@rpath/something.dylib`.)
* Add integration tests for embedders, including an embedder that uses `DT_RUNPATH`.
* Add a specific regression test for `ldd _tkinter` for PyInstaller.
Contributor guide
Assessment
This issue has not been assessed yet.