Skip to content

Fixes relative to RPATH handling - #788

Merged
rgommers merged 17 commits into
mesonbuild:mainfrom
dnicolodi:rpath-fixes
Sep 25, 2026
Merged

rgommers merged 17 commits into
mesonbuild:mainfrom
dnicolodi:rpath-fixes

Conversation

@dnicolodi

@dnicolodi dnicolodi commented Aug 10, 2025 •

Copy link
Copy Markdown
Member

Builds on top of #783 and replaces #724

Fixes #711
Fixes #813

@dnicolodi
dnicolodi force-pushed the rpath-fixes branch 5 times, most recently from 3c3bcf5 to f84c84f Compare August 10, 2025 15:54
@dnicolodi
dnicolodi marked this pull request as draft August 10, 2025 16:22
@dnicolodi
dnicolodi force-pushed the rpath-fixes branch 16 times, most recently from 54c1583 to 21c079d Compare June 27, 2026 22:27
@dnicolodi
dnicolodi marked this pull request as ready for review June 27, 2026 22:37
@dnicolodi

Copy link
Copy Markdown
Member Author

This should fix RPATH handling for good.

The only thing not included is automatic translation of the $ORIGIN anchor in install_rpath arguments to @loader_path on macOS. It would not be hard to implement, however, it would be a deviation from what Meson implements. I am not sure it is a good idea to implement it.

There is one case in which this may break projects that work now: when libraries or modules require setting an RPATH to dynamically link to a library installed in the Python install path (with something like install_dir: py.get_install_dir() / 'package') and that work now for how because meson-python does not remove build RPATH entries added by Meson and the source layout matches the install layout. This was the case for example for SciPy 1.15, see #724 (comment) and previous discussion. The comments there indicated that, for what SciPy is concerned, it should be fine to break this now. Note that SciPy 1.15 used install_rpath arguments that are implemented here, thus it would be fine, but it uses the $ORIGIN anchor on macOS too, and that does not work. See above. The behavior changes only with Meson 1.9.0 or later (older Meson versions did not export the required metadata), thus projects that pin the Meson version are fine.

@rgommers I think I added test cases for all scenarios we discussed. It would be great if you could test with packages that may be affected and that do not pin the meson-python version to any released version.

@dnicolodi
dnicolodi force-pushed the rpath-fixes branch 2 times, most recently from 87b4cee to 1fa120b Compare June 29, 2026 18:27
@dnicolodi dnicolodi changed the title Fixes relative to RPATH handfling Fixes relative to RPATH handling Jul 5, 2026
@dnicolodi

Copy link
Copy Markdown
Member Author

TL;DR: rpath entries from link_args always come before install_rpath entries.

At a closer look, I found that on install, Meson prepends install_rpath entries to existing entries. Obviously meson-python should do the same. This fixes the issue!

dnicolodi added a commit to dnicolodi/meson-python that referenced this pull request Sep 22, 2026
Emit a warning when this is done. This is required to keep some
backward compatibility with packages that relied on the incomplete
RPATH handling behavior before mesonbuild#788 to work.
dnicolodi added a commit to dnicolodi/meson-python that referenced this pull request Sep 22, 2026
Emit a warning when this is done. This is required to keep some
backward compatibility with packages that relied on the incomplete
RPATH handling behavior before mesonbuild#788 to work.
@dnicolodi
dnicolodi force-pushed the rpath-fixes branch 2 times, most recently from e4aca5f to 7120ea2 Compare September 22, 2026 21:07
@dnicolodi

Copy link
Copy Markdown
Member Author

At a closer look, I found that on install, Meson prepends install_rpath entries to existing entries. Obviously meson-python should do the same. This fixes the issue!

Fixed

@dnicolodi
dnicolodi force-pushed the rpath-fixes branch 2 times, most recently from fde50f8 to 412e465 Compare September 22, 2026 21:31
@dnicolodi

Copy link
Copy Markdown
Member Author

4. Transitive RPATH lookup (extmodule -> middle -> leaf): the test also fails on main, so this is not a demonstrated regression for this package. The PR converts RPATH to RUNPATH, which breaks indirect dependency lookup on glibc. This could affect real packages, and we’ve had issues with the distinction before, but I’m happy for this to be left for a follow-up if it turns out to not be a simple fix.

This is the only thing discussed here that remains to be addressed. I pulled in the test, which fails as expected. However, I do not understand what the expectations are, nor how it would be possible to support this use case.

dnicolodi and others added 12 commits September 23, 2026 08:55
This shows that build RPATHs are not correctly stripped.
Update typing annotation while there.  This does not introduce any
functional changes, except removing duplicates entries from RPATH.

Fixes mesonbuild#813.
There is no need to perform the check for every native file installed.
for packages using internal shared libraries relocated by meson-python.

Fixes mesonbuild#711.
Revise tests to exercise support when executed with Meson > 1.6
Requires Meson 1.9.0.  Extend some tests to strictly check that only
the expected RPATH entries remain.  This is complicated by the need to
account for additional RPATH entries required by the Python runtime.
Emit a warning when this is done. This is required to keep some
backward compatibility with packages that relied on the incomplete
RPATH handling behavior before mesonbuild#788 to work.
The tests package builds an extension module that links with two
libraries, one installed alongside the extension module, and another
installed in a sub-directory. The location of both libraries needs to
be added to the RPATH.

The test requires install_rpath support and thus Meson version 1.6 or
later for install_rpath to be recorded in the metadata.

Ignore the warning emitted building the package on macOS due to the
'$ORIGIN' to '@loader_path' translation.
Warn that the translation of $ORIGIN into @loader_path on macOS is
provided only for backward compatibility and it is discouraged to rely
on it.
@dnicolodi

dnicolodi commented Sep 23, 2026 •

Copy link
Copy Markdown
Member Author

4. Transitive RPATH lookup (extmodule -> middle -> leaf): the test also fails on main, so this is not a demonstrated regression for this package. The PR converts RPATH to RUNPATH, which breaks indirect dependency lookup on glibc. This could affect real packages, and we’ve had issues with the distinction before, but I’m happy for this to be left for a follow-up if it turns out to not be a simple fix.

I spent a bit more time on this and I have a better understanding. The test package builds a chain extension module that links with a middle shared library, is installed in $platlib/chainhead/ and has install rpath set to $ORIGIN/lib and linker arguments forcing the use of DT_RPATH instead of DT_RUNPATH. The middle shared library links with a leaf shared library and is installed in $platlib/chainhead/lib/. The leaf shared library is also installed in $platlib/chainhead/lib/.

The use of DT_RPATH in the chain extension module should propagate the shared library search path along the chain, thus the middle shared library does not need to set an RPATH to find the leaf shared library.

This breaks because patchelf converts DT_RPATH entries into DT_RUNPATH entries and the latter do not propagate.

patchelf has --force-rpath command line flag that forces the use of DT_RPATH instead of DT_RUNPATH https://manpages.debian.org/unstable/patchelf/patchelf.1.en.html#force-rpath. However, this is not what we need because converting DT_RUNPATH to DT_RPATH is not recommended either. We need a way to preserve the type of tag already present. I don't think there is a way to do this with current patchelf.

Relevant patchelf code:
https://github.com/NixOS/patchelf/blob/7688b17c18d16f67fa8d5a82a2404c2e3a18648d/src/patchelf.cc#L3124-L3137 and https://github.com/NixOS/patchelf/blob/7688b17c18d16f67fa8d5a82a2404c2e3a18648d/src/patchelf.cc#L1835-L1845

@dnicolodi

Copy link
Copy Markdown
Member Author

Moved TST: exercise transitive RPATH lookup with a shared library chain to #905.

@rgommers I think all issues and comments have been addressed and this is ready to be merged.

@rgommers

Copy link
Copy Markdown
Contributor

We need a way to preserve the type of tag already present. I don't think there is a way to do this with current patchelf.

I guess this should be possible if we know the type of the original entry, and updating them one by one. But agree with deferral to gh-905.

@rgommers I think all issues and comments have been addressed and this is ready to be merged.

Having another look now - seems like it's all happy.

@rgommers rgommers left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All seems happy in CI and local testing; of the extra test packages I created, fixes for cases 1, 2, and 3 looks good; case 4 we deferred, and case 5 we descoped as not realistic enough. So all good, in it goes.

Thanks again @dnicolodi!

@rgommers

Copy link
Copy Markdown
Contributor

WDYT about releasing this immediately as 0.22.0? Would be good to get some feedback quickly in case anything is still off (seems unlikely, but hard to be sure), and I like the idea of a release with just this change in it.

@dnicolodi

Copy link
Copy Markdown
Member Author

WDYT about releasing this immediately as 0.22.0?

Seems like a good idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Duplicate entries in RPATH RPATH goes missing when using both install_rpath and an internal shared library dependency

3 participants