aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFini Jastrow <ulf.fini.jastrow@desy.de>2020-11-25 14:43:11 +0100
committerJussi Pakkanen <jpakkane@gmail.com>2021-01-20 19:00:25 +0000
commit49cde9653c904b7f3ddc6b42bb4cf1bd4646d162 (patch)
tree8a9664a95ce919567d74118a369eb472c772be17
parent3c304bbb79ac5562ad401c722801a7d9ad4de0c6 (diff)
downloadmeson-49cde9653c904b7f3ddc6b42bb4cf1bd4646d162.zip
meson-49cde9653c904b7f3ddc6b42bb4cf1bd4646d162.tar.gz
meson-49cde9653c904b7f3ddc6b42bb4cf1bd4646d162.tar.bz2
ninjabackend: Correct RPATH order
[why] If we build and test a library we need to make sure that we find the currently build library object first, before an older system installed one. This can be broken if the library in question is installed in a custom path, and another library we depend on also is installed there. [how] Just move the rpath to the current build artifacts to the front. Solves #8030. Signed-off-by: Fini Jastrow <ulf.fini.jastrow@desy.de>
-rw-r--r--mesonbuild/backend/ninjabackend.py39
-rwxr-xr-xrun_unittests.py22
-rw-r--r--test cases/unit/89 pkgconfig build rpath order/dummy.pc7
-rw-r--r--test cases/unit/89 pkgconfig build rpath order/meson.build20
-rw-r--r--test cases/unit/89 pkgconfig build rpath order/prog.c5
-rw-r--r--test cases/unit/89 pkgconfig build rpath order/prog.cc8
-rw-r--r--test cases/unit/89 pkgconfig build rpath order/sub/meson.build1
-rw-r--r--test cases/unit/89 pkgconfig build rpath order/sub/stuff.c3
8 files changed, 86 insertions, 19 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index c1c4c93..400433f 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -2904,6 +2904,26 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
# Now we will add libraries and library paths from various sources
+ # Set runtime-paths so we can run executables without needing to set
+ # LD_LIBRARY_PATH, etc in the environment. Doesn't work on Windows.
+ if has_path_sep(target.name):
+ # Target names really should not have slashes in them, but
+ # unfortunately we did not check for that and some downstream projects
+ # now have them. Once slashes are forbidden, remove this bit.
+ target_slashname_workaround_dir = os.path.join(
+ os.path.dirname(target.name),
+ self.get_target_dir(target))
+ else:
+ target_slashname_workaround_dir = self.get_target_dir(target)
+ (rpath_args, target.rpath_dirs_to_remove) = (
+ linker.build_rpath_args(self.environment,
+ self.environment.get_build_dir(),
+ target_slashname_workaround_dir,
+ self.determine_rpath_dirs(target),
+ target.build_rpath,
+ target.install_rpath))
+ commands += rpath_args
+
# Add link args to link to all internal libraries (link_with:) and
# internal dependencies needed by this target.
if linker_base == 'STATIC':
@@ -2951,25 +2971,6 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
dep_targets = []
dep_targets.extend(self.guess_external_link_dependencies(linker, target, commands, internal))
- # Set runtime-paths so we can run executables without needing to set
- # LD_LIBRARY_PATH, etc in the environment. Doesn't work on Windows.
- if has_path_sep(target.name):
- # Target names really should not have slashes in them, but
- # unfortunately we did not check for that and some downstream projects
- # now have them. Once slashes are forbidden, remove this bit.
- target_slashname_workaround_dir = os.path.join(
- os.path.dirname(target.name),
- self.get_target_dir(target))
- else:
- target_slashname_workaround_dir = self.get_target_dir(target)
- (rpath_args, target.rpath_dirs_to_remove) = (
- linker.build_rpath_args(self.environment,
- self.environment.get_build_dir(),
- target_slashname_workaround_dir,
- self.determine_rpath_dirs(target),
- target.build_rpath,
- target.install_rpath))
- commands += rpath_args
# Add libraries generated by custom targets
custom_target_libraries = self.get_custom_target_provided_libraries(target)
commands += extra_args
diff --git a/run_unittests.py b/run_unittests.py
index 3ad0a7e..ca87eec 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -6695,6 +6695,28 @@ class LinuxlikeTests(BasePlatformTests):
install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/progcxx'))
self.assertEqual(install_rpath, 'baz')
+ @skipIfNoPkgconfig
+ def test_build_rpath_pkgconfig(self):
+ '''
+ Test that current build artefacts (libs) are found first on the rpath,
+ manually specified rpath comes second and additional rpath elements (from
+ pkg-config files) come last
+ '''
+ if is_cygwin():
+ raise unittest.SkipTest('Windows PE/COFF binaries do not use RPATH')
+ testdir = os.path.join(self.unit_test_dir, '89 pkgconfig build rpath order')
+ self.init(testdir, override_envvars={'PKG_CONFIG_PATH': testdir})
+ self.build()
+ build_rpath = get_rpath(os.path.join(self.builddir, 'prog'))
+ self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar:/foo/dummy')
+ build_rpath = get_rpath(os.path.join(self.builddir, 'progcxx'))
+ self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar:/foo/dummy')
+ self.install()
+ install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/prog'))
+ self.assertEqual(install_rpath, '/baz:/foo/dummy')
+ install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/progcxx'))
+ self.assertEqual(install_rpath, 'baz:/foo/dummy')
+
def test_global_rpath(self):
if is_cygwin():
raise unittest.SkipTest('Windows PE/COFF binaries do not use RPATH')
diff --git a/test cases/unit/89 pkgconfig build rpath order/dummy.pc b/test cases/unit/89 pkgconfig build rpath order/dummy.pc
new file mode 100644
index 0000000..9e3048b
--- /dev/null
+++ b/test cases/unit/89 pkgconfig build rpath order/dummy.pc
@@ -0,0 +1,7 @@
+prefix=/foo
+libdir=${prefix}/dummy
+
+Name: dummy
+Description: Nonexisting lib but add an rpath
+Version: 1.0.0
+Libs: -Wl,-rpath,${libdir}
diff --git a/test cases/unit/89 pkgconfig build rpath order/meson.build b/test cases/unit/89 pkgconfig build rpath order/meson.build
new file mode 100644
index 0000000..76ed8de
--- /dev/null
+++ b/test cases/unit/89 pkgconfig build rpath order/meson.build
@@ -0,0 +1,20 @@
+project('build rpath', 'c', 'cpp')
+
+subdir('sub')
+pkgconf_dep = dependency('dummy')
+
+executable('prog', 'prog.c',
+ dependencies : pkgconf_dep,
+ link_with : l,
+ build_rpath : '/foo/bar',
+ install_rpath : '/baz',
+ install : true,
+ )
+
+executable('progcxx', 'prog.cc',
+ dependencies : pkgconf_dep,
+ link_with : l,
+ build_rpath : '/foo/bar',
+ install_rpath : 'baz',
+ install : true,
+ )
diff --git a/test cases/unit/89 pkgconfig build rpath order/prog.c b/test cases/unit/89 pkgconfig build rpath order/prog.c
new file mode 100644
index 0000000..45b2fa3
--- /dev/null
+++ b/test cases/unit/89 pkgconfig build rpath order/prog.c
@@ -0,0 +1,5 @@
+int get_stuff();
+
+int main(int argc, char **argv) {
+ return get_stuff();
+}
diff --git a/test cases/unit/89 pkgconfig build rpath order/prog.cc b/test cases/unit/89 pkgconfig build rpath order/prog.cc
new file mode 100644
index 0000000..c7c2123
--- /dev/null
+++ b/test cases/unit/89 pkgconfig build rpath order/prog.cc
@@ -0,0 +1,8 @@
+#include <string>
+#include <iostream>
+
+int main(int argc, char **argv) {
+ std::string* s = new std::string("Hello");
+ delete s;
+ return 0;
+}
diff --git a/test cases/unit/89 pkgconfig build rpath order/sub/meson.build b/test cases/unit/89 pkgconfig build rpath order/sub/meson.build
new file mode 100644
index 0000000..6879ec6
--- /dev/null
+++ b/test cases/unit/89 pkgconfig build rpath order/sub/meson.build
@@ -0,0 +1 @@
+l = shared_library('stuff', 'stuff.c')
diff --git a/test cases/unit/89 pkgconfig build rpath order/sub/stuff.c b/test cases/unit/89 pkgconfig build rpath order/sub/stuff.c
new file mode 100644
index 0000000..d56d8b0
--- /dev/null
+++ b/test cases/unit/89 pkgconfig build rpath order/sub/stuff.c
@@ -0,0 +1,3 @@
+int get_stuff() {
+ return 0;
+}