Skip to content
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

[wip] meson: append new items to the original rpath #31228

Closed
wants to merge 2 commits into from

Conversation

jtojnar
Copy link
Contributor

@jtojnar jtojnar commented Nov 4, 2017

Motivation for this change

Some apps require an internal library, that needs to be added to rpath. In 8f95aef, we removed the rpath fixup, breaking these apps.

This commit re-adds the fixup but modifies it to keep the old rpath.

Closes: #31222

Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option build-use-sandbox in nix.conf on non-NixOS)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nox --run "nox-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Fits CONTRIBUTING.md.

Some apps require an internal library, that needs to be added to rpath.
In 8f95aef, we removed the rpath fixup,
breaking these apps.

This commit re-adds the fixup but modifies it to keep the old rpath.

Closes: NixOS#31222
@lukateras
Copy link
Member

lukateras commented Nov 4, 2017

Also see: mesonbuild/meson#314.

This will break it: https://github.com/mesonbuild/meson/blob/db34a3a7017d0096faa8d3f020efd078ad8a65e1/mesonbuild/scripts/depfixer.py#L303-L306

Can't be easily patched in Meson because they just overwrite bytes in ELF headers without much handling logic. Perhaps better approach would be to replace fix_rpathtype_entry function with patchelf?

@jtojnar jtojnar changed the title meson: append new items to the original rpath [wip] meson: append new items to the original rpath Nov 4, 2017
@jtojnar
Copy link
Contributor Author

jtojnar commented Nov 4, 2017

Hmm, you are right, it will be broken with non empty new_rpath. patchelf would be an easy fix but with a no chance for upstreaming. I will look into chrpath source code to see how they do it.

Edit: Apparently, meson does the exact same thing chrpath does. patchelf on the other hand does resize the section.

@lukateras
Copy link
Member

lukateras commented Nov 4, 2017

There is probably no upstreamable fix other than implementing a flag like -DCMAKE_SKIP_BUILD_RPATH. Even if you were to reimplement resizing logic they would not accept it as they believe they are doing the right thing: mesonbuild/meson#314 (comment)

Or perhaps they will upstream resizing logic (to handle the case when install_rpath is longer than old_rpath), but not the part that appends old_rpath to new_rpath.

By the way, see: pkgs/development/tools/build-managers/cmake/setup-hook.sh#L52

This should have the same effect as skipping rpath fixup entirely (which is what we currently do with Meson). How come CMake builds that have internal libraries aren't affected?

@jtojnar
Copy link
Contributor Author

jtojnar commented Nov 4, 2017

I tried using the patchelf approach in #31219 but now deja-dup segfaults.

@jtojnar jtojnar closed this Nov 8, 2017
Some apps require an internal library, that needs to be added to rpath.
In 8f95aef, we removed the rpath fixup,
breaking these apps.

This commit re-adds the fixup but modifies it to keep the old rpath.

Closes: NixOS#31222
@jtojnar jtojnar reopened this Nov 8, 2017
@jtojnar
Copy link
Contributor Author

jtojnar commented Nov 8, 2017

Apparently, the patchelf tool can corrupt the binary, same thing happens with GNOME Shell in #29392 (comment)

- sys.exit('File "%s" has unknown ELF endianness.' % self.bfile)
- return ptrsize, is_le
-
- def parse_header(self):
Copy link
Member

@lukateras lukateras Nov 8, 2017

Choose a reason for hiding this comment

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

When it goes into the tree, I'd suggest making the patch as small as possible so that it's not a maintenance burden. You probably already have that in mind, but just in case...

Since Python functions can be redefined, the most forward-compatible way of doing this is storing patchelf versions of self.print_soname() and self.fix_rpath() in a .py file that then will be appended to scripts/depfixer.py in patchPhase.

@lukateras
Copy link
Member

lukateras commented Nov 8, 2017

Unfortunately, sometimes it does (and it can't patch some binaries at all). Have you tried patchelfUnstable? Some in-tree packages use it because patchelf doesn't work for them.

@jtojnar
Copy link
Contributor Author

jtojnar commented Nov 8, 2017

Why does not the compiler/linker produce the correct rpath in the first place? It looks like it tries – the libraries are lib/deja-dup/lib{deja,widgets}.so and the produced rpath contains $ORIGIN/../libdeja:$ORIGIN/widgets. Why does not it produce $ORIGIN/../lib/deja-dup?

@lukateras
Copy link
Member

lukateras commented Nov 8, 2017

Because shared libraries are moved to lib/deja-dup only at install phase (more precisely, into pkglibdir). Which means linker doesn't know anything about it.

https://git.launchpad.net/deja-dup/tree/deja-dup/meson.build#n39
https://git.launchpad.net/deja-dup/tree/libdeja/meson.build#n51

I'd guess this particular case can be solved by moving stuff from lib/libdeja back to lib. But it's definitely not the only program that might want to do something like this, so patching Meson is a better solution.

By the way, I can't reproduce this problem in Nixpkgs master. It also doesn't seem to have 8f95aef...

@jtojnar
Copy link
Contributor Author

jtojnar commented Nov 8, 2017

Hmm, you are right:

/tmp/nix-build-deja-dup-36.3.drv-1
└── deja-dup-36.3
   ├── build
   │  ├── deja-dup
   │  │  ├── deja-dup
   │  │  ├── monitor
   │  │  │  └── deja-dup-monitor
   │  │  └── widgets
   │  │     └── libwidgets.so
   │  └── libdeja
   │     ├── libdeja.so
   │     └── tools
   │        └── duplicity
   │           └── libduplicity.so
   └── deja-dup
      └── // source code

Since meson does not support building in the source directory, would it make sense to modify meson to produce installable tree right in the build directory? Then the linker would use add $ORIGIN/../lib/deja-dup to the rpath correctly.

I would rather not move the internal libraries to lib, too many of moving pieces.


I see the line in master: https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/tools/build-managers/meson/default.nix#L21-L23

@jtojnar jtojnar mentioned this pull request Nov 8, 2017
71 tasks
@jtojnar
Copy link
Contributor Author

jtojnar commented Nov 8, 2017

According to @dezgeg, the issue with patchelf breaking the binaries is actually caused by strip. Indeed, this patch seems to produce working binaries with dontStrip = true. Disabling stripping in all meson-built binaries does not sound like a good idea, though.

@lukateras
Copy link
Member

lukateras commented Nov 8, 2017

I think that patching ELF is a better fit for Meson than passing anything to linker, as it is more in line with Meson behavior and thus more transparent.

I see the line in master: [...]

You are right, didn't notice it. Also, in reference to #31222: I couldn't reproduce this, even with the same Nixpkgs version. Here's what I've done:

$ git checkout 5cfd049a0304c807a2ed2f7d3cf55c23cd103305
$ nix-build ~/Projects/nixpkgs/ -A deja-dup
$ patchelf --print-rpath result/bin/.deja-dup-wrapped 
/nix/store/d9s2m4fs3m8ifngnkzmpik6li1yqy0z9-glib-2.54.1/lib:/nix/store/hn0h1dfhap9dm69ns6fjqicip05ripkh-gtk+3-3.22.24/lib:/nix/store/xy3ji59l92cnx0h7mmvdq89n8qcvrswv-gnome-online-accounts-3.24.2/lib:/nix/store/xfqarwirj8a0mhg81qmrn6sxhyrhb8c8-libpeas-1.18.0/lib:/nix/store/0dgfgx1xc7ymyicvxk85nxm7bma2kg3h-nautilus-3.24.2.1/lib:/nix/store/d6k1dpsa1f4yd8i1zsn7ymv1qpnwr0kp-libgpg-error-1.27/lib:/nix/store/jj2agpnlyv1km4p7d7gqh1z4k3lbjfsa-libsecret-0.18.5/lib:/nix/store/4pbw7113798fd5n7n1azfql3d6mcs7cm-atk-2.26.0/lib:/nix/store/m4bj2aya32k8jj93a81acj6ixwp82lh5-pango-1.40.12/lib:/nix/store/9x523zj53isj7wbnlq99z5xcn95m6p22-deja-dup-36.3/lib/deja-dup
$ result/bin/deja-dup 

** (org.gnome.DejaDup:16393): WARNING **: Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files

According to @dezdeg, the issue with patchelf breaking the binaries is actually caused by strip. Indeed, this patch seems to produce working binaries with dontStrip = true. Disabling stripping in all meson-built binaries does not sound like a good idea, though.

Well, we don't strip a lot of we could, at least not until #31025 gets merged.

I think this is the issue @dezgeg refers to: NixOS/patchelf#10. If so, it should be fixed for practical purposes in NixOS/patchelf#117. So, if you use patchelfUnstable, it should work.

@jtojnar
Copy link
Contributor Author

jtojnar commented Nov 8, 2017

I tried adding patchelfUnstable to nativeBuildInputs but it is still broken, see https://github.com/jtojnar/nixpkgs/tree/deja-dup-rpath-broken

@lukateras
Copy link
Member

lukateras commented Nov 8, 2017

I've spent an hour trying to find a workaround, to no avail. patchelfUnstable in Nixpkgs doesn't include NixOS/patchelf#117, but even after building patchelf from master and applying NixOS/patchelf#127 on top of it, expanding rpath size beyond original capacity and then stripping the binary leads to a segfault.

Cross-reference: NixOS/patchelf#10 (comment)

@lukateras
Copy link
Member

lukateras commented Nov 8, 2017

Given circumstances, I think that not stripping the binaries is OK.

However, there is a way around it: from Meson patchelf patch code, if new_rpath is longer than old_rpath, create a file with a magic filename. Then, in preFixup or similar, if that file exists, run export dontStrip=1. This should satisfy the strip hook:

if [ -z "$dontStrip" ]; then

@lukateras
Copy link
Member

I've implemented the workaround described above in #31436.

@jtojnar jtojnar closed this Nov 9, 2017
lukateras added a commit to lukateras/nixpkgs that referenced this pull request Nov 9, 2017
This is based on Jan Tojnar's work in NixOS#31228.

When patchelf has to grow rpath beyond original capacity, it sets
dontStrip, to work around NixOS/patchelf#10.
@jtojnar jtojnar deleted the meson-append-rpath branch February 24, 2018 18:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Meson produces incorrect rpath for local libraries
3 participants