-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Relative rpaths are used for a pkgconfig dependency on Linux #13046
Comments
On macos what happens is that we also have a relative rpath but if I understand correctly $ otool -l build/src/meson_test/_meson_test.cpython-312-darwin.so
...
Load command 10
cmd LC_LOAD_DYLIB
cmdsize 88
name /Users/enojb/work/dev/rpath_meson/.local/lib/libgmp.10.dylib (offset 24)
time stamp 2 Thu Jan 1 01:00:02 1970
current version 16.0.0
compatibility version 16.0.0
Load command 11
cmd LC_LOAD_DYLIB
cmdsize 56
name /usr/lib/libSystem.B.dylib (offset 24)
time stamp 2 Thu Jan 1 01:00:02 1970
current version 1345.100.2
compatibility version 1.0.0
Load command 12
cmd LC_RPATH
cmdsize 48
path @loader_path/../../../.local/lib (offset 12)
... This relative rpath is also stripped out by meson install but that is okay because the binary still has an absolute path reference to libgmp: $ otool -L build-install/usr/local/lib/python3.12/site-packages/meson_test/_meson_test.cpython-312-darwin.so
build-install/usr/local/lib/python3.12/site-packages/meson_test/_meson_test.cpython-312-darwin.so:
/Users/enojb/work/dev/rpath_meson/.local/lib/libgmp.10.dylib (compatibility version 16.0.0, current version 16.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1345.100.2)
$ otool -L build/src/meson_test/_meson_test.cpython-312-darwin.so
build/src/meson_test/_meson_test.cpython-312-darwin.so:
/Users/enojb/work/dev/rpath_meson/.local/lib/libgmp.10.dylib (compatibility version 16.0.0, current version 16.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1345.100.2) |
Just tried on macOS to run the test package build (my bad, didn't read the pre-step), got:
Second time I ran it, it did work. Seems like the test installs
Had some other project where this came up recently. I'm honestly still not 100% sure what the exact rules for RPATH rewriting when running There are 4 cases at least to consider, when seeing
Expected behavior:
(3) is least clear to me. Not stripping would fix @oscarbenjamin's problem I think, but what is expected here? Not stripping would lead to installed packages that only work locally (a win!) but cannot be distributed as packages, because the path is unlikely to be portable (potential risk!). The alternative is probably to not use @eli-schwartz would you be able to clarify the rules? |
There are three sources of rpaths.
The first type is "build plus install rpaths", the second type is "install rpaths", and the third type is "build rpaths". Meson doesn't currently try to figure out what would be a good runtime RPATH via heuristics. |
I think this is only about |
Or maybe that's the missing bit here. Meson itself doesn't change anything, but somehow |
Yep indeed, I think this is why I had a hard time to reproduce the problem: it's
This is muddying the waters just slightly - it can explain why an editable install with I think I get it now. The next step is: how to actually handle the case of a library being installed into some random directory and its xref scipy/scipy#20585 (review) for pretty much the same issue. There we actually have control over the content of the |
Is the solution to use In context I only use this in a development environment. In a normal install the dependencies are either installed system wide or were vendored by auditwheel et al that fix up the rpaths themselves. It seems that meson is getting confused by the fact that |
If you've ever read the autotools libtool.m4 source code, it makes for some fascinating reading. The lengths it goes to in order to find the system library load path are... excessive. It even contains a file format parser for ld.so.conf (which doesn't actually document its file format, very fun). I have pondered teaching this to meson as well. It's a nontrivial endeavor. :( |
I'm not sure how that relates to the problem at hand. I told meson the path to the pkgconfig files and they told meson some other paths. Then meson has all the needed paths but it strips them out during the install. The question here is not finding the paths but just deciding what to do with them in context. |
And the libtool code I refer to is all about figuring out which paths are duplicates of the system lookup path (which isn't supposed to be included in installed rpaths) and which ones are outside of ld.so.conf and therefore come from third-party dependencies installed to unusual locations. |
That makes sense.
So this is not a possible solution, for two reasons: the Short of what @eli-schwartz has contemplated doing (which I believe is nontrivial indeed), I think there are multiple ways to go about this now:
I haven't actually checked, but I can believe that the behavior is currently different as @oscarbenjamin says. The meson/mesonbuild/scripts/depfixer.py Line 400 in a0ff145
So possibly a "build rpath" is not being stripped out on macOS. |
We recently fixed Darwin to align closer to what Linux does, in order to fix a bug report where Darwin was deleting many more rpaths than Linux, including some needed ones. |
Possibly related is this issue about rpath handling on macos: #2121 |
I was thinking that the conditional part would be something explicitly opted into by the person running meson like
(I'm not sure exactly what an option like this should be called or what its behaviour in full generality should be.) The option to add the rpaths could be a general meson option or a project-specific option. Then In the spin case I don't think it makes sense to remove the rpaths apart from when building a wheel. Even then I'm not sure it makes sense because the built wheel is not expected to be relocatable until you run auditwheel which will fix up the rpaths. What does make sense is that the person running |
I think that people in gh-2121 are asking for the opposite behaviour which is also why it makes sense for this to be an option under control of the person doing the installing. |
Very much related indeed, good find. It explained a few things in the discussion that I wish I had known earlier.
Back to the original reproducer in the issue description. I confirmed that my options 1-4 above work. E.g., editing
makes things work with the demo repo on Linux. The reason that things already work on macOS is that the "install name" of
Not quite the opposite. It's another thing that is also needed if (and only if) you're setting an RPATH and the external shared library being linked is built by Meson (GMP is built by Make, so it's a different case). The crucial sentence I think is this one: "MacOS has a peculiar and very unusual way of linking, namely that consumers of a library inherit a provider's So, Linux and macOS are indeed different - and that is because linking works differently on macOS vs. Linux. All Meson is doing is temporarily adding RPATH's inside the build dir and then removing them again on install. That can just have a different effect depending on platform as well as editable install vs. regular install to a destdir.
That does seem like a reasonable option to me to avoid this problem. It's pretty much a band-aid until the structural solution ("teach Meson to find the system library load paths" from @eli-schwartz's comment above) materializes (which could take a long time). |
I won't look at the
Debian is only mildly more interesting, due to Multi-Arch support:
I tried every docker container I had lying around, but didn't find anything that wasn't The man page sentence hints at the prospect of having to deal with annoying differences between platforms. But besides that being tedious, it's probably doable? Python is a lot better than M4 for writing a file parser, and it seems to be a fairly constrained problem - probably doable in <100 LoC? With a strategy of parsing all known formats to obtain the full search path list, and in case of an unknown format emitting a warning and disabling adding RPATHs (to avoid regressions), maybe this can be introduced in a safe way? |
For now at least this looks like the best option to make this work:
I presume this can be done with I presume also that |
True - if you know that the dependency is detected with pkg-config, this should work.
Agreed, seems reasonable. And then it can be done without having to add anything in Meson itself. |
I've implemented this for python-flint in flintlib/python-flint#135. I still think that it would be good for meson to have a standard option for this somehow. If you build against some local build of dependencies then at runtime after install you want to use the same local build as well. |
Only if there is no chance to fix it the right way in a reasonable time frame I think. I have too many projects I'd like to complete already, but I'm actually interested to give it a go (and have some holiday time on my hands). |
This is similar to gh-3882 but I think different because this is for dependencies found by pkgconfig. This comes from scientific-python/spin#176.
I have made a simple demo repo: https://github.com/oscarbenjamin/rpath_meson
I build gmp as an external dependency and install into a local directory and then try to make a Python extension module that links against it:
This works fine on macos but fails on Linux. More precisely what fails is that at runtime it loads the system
libgmp.so
(a different version) rather than the one in.local
so at least on this system it seems to work but is not correct.We find gmp with:
The dependency is found using pkgconfig. I give an absolute path in
PKG_CONFIG_PATH
which finds gmp.pc which also has absolute paths:However the binary built by
meson compile
uses a relative rpath:That relative rpath is stripped out by
meson install
so after install we can't findlibgmp.so
any more (actually we get the system libgmp which is not what we want):I don't see why a relative path is being used to an external dependency whose location is given as an absolute path. Certainly my intention at the end is that the binaries should reference my local build of
libgmp.so
by absolute path which is what happens when running the same on macos rather than Linux.The text was updated successfully, but these errors were encountered: