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>
pull/8456/head
Fini Jastrow 4 years ago committed by Jussi Pakkanen
parent 3c304bbb79
commit 49cde9653c
  1. 39
      mesonbuild/backend/ninjabackend.py
  2. 22
      run_unittests.py
  3. 7
      test cases/unit/89 pkgconfig build rpath order/dummy.pc
  4. 20
      test cases/unit/89 pkgconfig build rpath order/meson.build
  5. 5
      test cases/unit/89 pkgconfig build rpath order/prog.c
  6. 8
      test cases/unit/89 pkgconfig build rpath order/prog.cc
  7. 1
      test cases/unit/89 pkgconfig build rpath order/sub/meson.build
  8. 3
      test cases/unit/89 pkgconfig build rpath order/sub/stuff.c

@ -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

@ -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')

@ -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}

@ -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,
)

@ -0,0 +1,5 @@
int get_stuff();
int main(int argc, char **argv) {
return get_stuff();
}

@ -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;
}

@ -0,0 +1 @@
l = shared_library('stuff', 'stuff.c')
Loading…
Cancel
Save