-
-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Meson produces incorrect rpath for local libraries #31222
Comments
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
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
@yegortimoshenko I found where those X’s come from. Could we maybe do something like this instead? diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 3f088b0f..a2661240 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -834,12 +834,11 @@ class Compiler:
# Build_rpath is used as-is (it is usually absolute).
if build_rpath != '':
paths += ':' + build_rpath
- if len(paths) < len(install_rpath):
- padding = 'X' * (len(install_rpath) - len(paths))
- if not paths:
- paths = padding
- else:
- paths = paths + ':' + padding
+ padding = 'X' * len(install_rpath)
+ if not paths:
+ paths = padding
+ else:
+ paths = paths + ':' + padding
args = ['-Wl,-rpath,' + paths]
if get_compiler_is_linuxlike(self):
# Rpaths to use while linking must be absolute. These are not
diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py
index ee63147d..85f81506 100644
--- a/mesonbuild/scripts/depfixer.py
+++ b/mesonbuild/scripts/depfixer.py
@@ -300,19 +300,8 @@ class Elf(DataSizes):
return
self.bf.seek(rp_off)
old_rpath = self.read_str()
- if len(old_rpath) < len(new_rpath):
- sys.exit("New rpath must not be longer than the old one.")
- # The linker does read-only string deduplication. If there is a
- # string that shares a suffix with the rpath, they might get
- # dedupped. This means changing the rpath string might break something
- # completely unrelated. This has already happened once with X.org.
- # Thus we want to keep this change as small as possible to minimize
- # the chance of obliterating other strings. It might still happen
- # but our behavior is identical to what chrpath does and it has
- # been in use for ages so based on that this should be rare.
- if not new_rpath:
- self.remove_rpath_entry(entrynum)
- else:
+ if new_rpath:
+ new_rpath = old_rpath.replace('X' * len(new_rpath), new_rpath)
self.bf.seek(rp_off)
self.bf.write(new_rpath)
self.bf.write(b'\0') |
Or even better, skip the X nonsense: diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 3f088b0f..71a5fe8e 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -834,12 +834,10 @@ class Compiler:
# Build_rpath is used as-is (it is usually absolute).
if build_rpath != '':
paths += ':' + build_rpath
- if len(paths) < len(install_rpath):
- padding = 'X' * (len(install_rpath) - len(paths))
- if not paths:
- paths = padding
- else:
- paths = paths + ':' + padding
+ if not paths:
+ paths = install_rpath
+ else:
+ paths = paths + ':' + install_rpath
args = ['-Wl,-rpath,' + paths]
if get_compiler_is_linuxlike(self):
# Rpaths to use while linking must be absolute. These are not
diff --git a/mesonbuild/scripts/meson_install.py b/mesonbuild/scripts/meson_install.py
index 985b0e94..665f523b 100644
--- a/mesonbuild/scripts/meson_install.py
+++ b/mesonbuild/scripts/meson_install.py
@@ -353,7 +353,6 @@ def install_targets(d):
if is_elf_platform() and os.path.isfile(outname):
try:
e = depfixer.Elf(outname, False)
- e.fix_rpath(install_rpath)
except SystemExit as e:
if isinstance(e.code, int) and e.code == 0:
pass |
As I understand it, the whole X business is to ensure the |
@jtojnar Thanks for explaining, makes sense. Your patch is way better than mine, and I've completely overlooked rpath templating (I shouldn't have: I've wondered why upstream version of |
I asked about the patch in the meson issue mesonbuild/meson#314 (comment) |
@yegortimoshenko The problem with this patch is that it will pollute the |
@yegortimoshenko What we actually want is a hybrid of the two variants: this patch plus |
@yegortimoshenko Well our We would need something like: --- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -834,12 +834,10 @@ class Compiler:
# Build_rpath is used as-is (it is usually absolute).
if build_rpath != '':
paths += ':' + build_rpath
- if len(paths) < len(install_rpath):
- padding = 'X' * (len(install_rpath) - len(paths))
- if not paths:
- paths = padding
- else:
- paths = paths + ':' + padding
+ if not paths:
+ paths = install_rpath
+ else:
+ paths = paths + ':' + install_rpath
args = ['-Wl,-rpath,' + paths]
if get_compiler_is_linuxlike(self):
# Rpaths to use while linking must be absolute. These are not
--- a/mesonbuild/scripts/meson_install.py
+++ b/mesonbuild/scripts/meson_install.py
@@ -353,7 +353,6 @@ def install_targets(d):
if is_elf_platform() and os.path.isfile(outname):
try:
- e = depfixer.Elf(outname, False)
- e.fix_rpath(install_rpath)
+ subprocess.call(['patchelf', '--strip-rpath', outname], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except SystemExit as e:
if isinstance(e.code, int) and e.code == 0:
pass We could add the stripping to the |
Weird, the epiphany no longer finds |
The issue is that |
The epiphany issue was fixed in c95491c. |
As I understand it, the whole
For third-party libraries this is fairly straight-forward – we add their locations to the rpath (or link them using absolute path on Darwin) and it will work in both scenarios. Once we want to link against an internal library, however, it will get ugly. If we do not want to fiddle with environment variables, we will need to use absolute paths for linking. Unfortunately, the package is built in a different location than it is installed to, so we do not have a single path to use. Instead, we could use origin-relative paths ( Obviously, a single path is not enough – we will need to add both paths to
This is actually, what meson does except it removes too much – the whole The ideal patch would remove only the development links and insert the P.S.: On Darwin, there is something similar with |
@yegortimoshenko Here is another draft based on the previous comment: --- a/pkgs/development/tools/build-managers/meson/default.nix
+++ b/pkgs/development/tools/build-managers/meson/default.nix
@@ -25,11 +25,14 @@
# We patch Meson to add a --fallback-library-path argument with
# library install_dir to g-ir-scanner.
./gir-fallback-path.patch
- ];
- postPatch = ''
- sed -i -e 's|e.fix_rpath(install_rpath)||' mesonbuild/scripts/meson_install.py
- '';
+ # In common distributions, RPATH is only needed for internal libraries so
+ # meson removes everything else. With Nix, the locations of libraries
+ # are not as predictable, therefore we need to keep them in the RPATH.
+ # At the moment we are keeping the paths starting with /nix/store.
+ # https://github.com/NixOS/nixpkgs/issues/31222#issuecomment-365811634
+ ./fix-rpath.patch
+ ];
setupHook = ./setup-hook.sh;
--- /dev/null
+++ b/pkgs/development/tools/build-managers/meson/fix-rpath.patch
@@ -0,0 +1,45 @@
+--- a/mesonbuild/compilers/compilers.py
++++ b/mesonbuild/compilers/compilers.py
+@@ -828,6 +828,8 @@
+ return args
+
+ def build_unix_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
++ print(f'************* build_dir="{build_dir}", from_dir="{from_dir}", rpath_paths="{rpath_paths}", build_rpath="{build_rpath}", install_rpath="{install_rpath}"')
++
+ if not rpath_paths and not install_rpath and not build_rpath:
+ return []
+ # The rpaths we write must be relative, because otherwise
+@@ -846,8 +848,12 @@
+ if paths != '':
+ paths += ':'
+ paths += build_rpath
+- if len(paths) < len(install_rpath):
+- padding = 'X' * (len(install_rpath) - len(paths))
++ print(f'------------- paths="{paths}"')
++
++ store_paths = ':'.join(filter(lambda path: path.startswith('/nix/store'), paths.split(':')))
++ extra_space_needed = len(install_rpath + (':' if install_rpath and store_paths else '') + store_paths) - len(paths)
++ if extra_space_needed > 0:
++ padding = 'X' * extra_space_needed
+ if not paths:
+ paths = padding
+ else:
+--- a/mesonbuild/scripts/depfixer.py
++++ b/mesonbuild/scripts/depfixer.py
+@@ -300,6 +300,16 @@
+ return
+ self.bf.seek(rp_off)
+ old_rpath = self.read_str()
++
++ print(f'+++++++++++++ old_rpath="{old_rpath}", new_rpath="{new_rpath}"')
++
++ if new_rpath:
++ new_rpath += b':'
++ else:
++ new_rpath = b''
++
++ new_rpath += b':'.join(filter(lambda path: path.startswith(b'/nix/store'), old_rpath.split(b':')))
++
+ if len(old_rpath) < len(new_rpath):
+ sys.exit("New rpath must not be longer than the old one.")
+ # The linker does read-only string deduplication. If there is a But apparently Meson is not aware of libraries added to rpath:
Where do they come from? Edit: Apparently from |
In common distributions, RPATH is only needed for internal libraries so meson removes everything else. With Nix, the locations of libraries are not as predictable, therefore we need to keep them in the RPATH. [1] Previously we have just kept the RPATH produced by the linker, patching meson not to remove it. This deprived us of potentially replacing it with install_rpath provided by project so we had to re-add it manually, and also introduced a vulnerability of keeping build paths in RPATH. This commit restores the clean-up but modifies it so the items starting with /nix/store are retained. This should be relatively safe since the store is immutable, however, there might be some unwanted retainment of build_rpath [2] if it contains paths from Nix store. [1]: #31222 (comment) [2]: http://mesonbuild.com/Release-notes-for-0-42-0.html#added-build_rpath-keyword-argument
In common distributions, RPATH is only needed for internal libraries so meson removes everything else. With Nix, the locations of libraries are not as predictable, therefore we need to keep them in the RPATH. [1] Previously we have just kept the RPATH produced by the linker, patching meson not to remove it. This deprived us of potentially replacing it with install_rpath provided by project so we had to re-add it manually, and also introduced a vulnerability of keeping build paths in RPATH. This commit restores the clean-up but modifies it so the items starting with /nix/store are retained. This should be relatively safe since the store is immutable, however, there might be some unwanted retainment of build_rpath [2] if it contains paths from Nix store. [1]: #31222 (comment) [2]: http://mesonbuild.com/Release-notes-for-0-42-0.html#added-build_rpath-keyword-argument
In common distributions, RPATH is only needed for internal libraries so meson removes everything else. With Nix, the locations of libraries are not as predictable, therefore we need to keep them in the RPATH. [1] Previously we have just kept the RPATH produced by the linker, patching meson not to remove it. This deprived us of potentially replacing it with install_rpath provided by project so we had to re-add it manually, and also introduced a vulnerability of keeping build paths in RPATH. This commit restores the clean-up but modifies it so the items starting with /nix/store are retained. This should be relatively safe since the store is immutable, however, there might be some unwanted retainment of build_rpath [2] if it contains paths from Nix store. [1]: #31222 (comment) [2]: http://mesonbuild.com/Release-notes-for-0-42-0.html#added-build_rpath-keyword-argument
In common distributions, RPATH is only needed for internal libraries so meson removes everything else. With Nix, the locations of libraries are not as predictable, therefore we need to keep them in the RPATH. [1] Previously we have just kept the RPATH produced by the linker, patching meson not to remove it. This deprived us of potentially replacing it with install_rpath provided by project so we had to re-add it manually, and also introduced a vulnerability of keeping build paths in RPATH. This commit restores the clean-up but modifies it so the items starting with /nix/store are retained. This should be relatively safe since the store is immutable, however, there might be some unwanted retainment of build_rpath [2] if it contains paths from Nix store. [1]: #31222 (comment) [2]: http://mesonbuild.com/Release-notes-for-0-42-0.html#added-build_rpath-keyword-argument
In common distributions, RPATH is only needed for internal libraries so meson removes everything else. With Nix, the locations of libraries are not as predictable, therefore we need to keep them in the RPATH. [1] Previously we have just kept the RPATH produced by the linker, patching meson not to remove it. This deprived us of potentially replacing it with install_rpath provided by project so we had to re-add it manually, and also introduced a vulnerability of keeping build paths in RPATH. This commit restores the clean-up but modifies it so the items starting with /nix/store are retained. This should be relatively safe since the store is immutable, however, there might be some unwanted retainment of build_rpath [2] if it contains paths from Nix store. [1]: #31222 (comment) [2]: http://mesonbuild.com/Release-notes-for-0-42-0.html#added-build_rpath-keyword-argument
In common distributions, RPATH is only needed for internal libraries so meson removes everything else. With Nix, the locations of libraries are not as predictable, therefore we need to keep them in the RPATH. [1] Previously we have just kept the RPATH produced by the linker, patching meson not to remove it. This deprived us of potentially replacing it with install_rpath provided by project so we had to re-add it manually, and also introduced a vulnerability of keeping build paths in RPATH. This commit restores the clean-up but modifies it so the items starting with /nix/store are retained. This should be relatively safe since the store is immutable, however, there might be some unwanted retainment of build_rpath [2] if it contains paths from Nix store. [1]: NixOS#31222 (comment) [2]: http://mesonbuild.com/Release-notes-for-0-42-0.html#added-build_rpath-keyword-argument
In common distributions, RPATH is only needed for internal libraries so meson removes everything else. With Nix, the locations of libraries are not as predictable, therefore we need to keep them in the RPATH. [1] Previously we have just kept the RPATH produced by the linker, patching meson not to remove it. This deprived us of potentially replacing it with install_rpath provided by project so we had to re-add it manually, and also introduced a vulnerability of keeping build paths in RPATH. This commit restores the clean-up but modifies it so the items starting with /nix/store are retained. This should be relatively safe since the store is immutable, however, there might be some unwanted retainment of build_rpath [2] if it contains paths from Nix store. [1]: NixOS#31222 (comment) [2]: http://mesonbuild.com/Release-notes-for-0-42-0.html#added-build_rpath-keyword-argument (cherry picked from commit de910a0)
Issue description
Dejà dup requires a custom library in
$ORIGIN/../lib/deja-dup
but meson, for some reason, adds$ORIGIN/../libdeja
to therpath
:If I remove the
postPatch
attribute, the path to the custom library is inrpath
but then we do not have the global ones:Steps to reproduce
Technical details
The text was updated successfully, but these errors were encountered: