aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/backend/backends.py15
-rw-r--r--mesonbuild/backend/ninjabackend.py7
-rw-r--r--mesonbuild/build.py2
-rw-r--r--mesonbuild/compilers/compilers.py2
-rw-r--r--mesonbuild/compilers/cuda.py7
-rw-r--r--mesonbuild/compilers/d.py9
-rw-r--r--mesonbuild/compilers/mixins/islinker.py4
-rw-r--r--mesonbuild/linkers.py49
-rw-r--r--mesonbuild/minstall.py2
-rw-r--r--mesonbuild/scripts/depfixer.py32
-rwxr-xr-xrun_unittests.py59
-rw-r--r--test cases/unit/40 external, internal library rpath/built library/meson.build5
-rw-r--r--test cases/unit/40 external, internal library rpath/external library/meson.build6
-rw-r--r--test cases/unit/76 pkgconfig prefixes/client/client.c8
-rw-r--r--test cases/unit/76 pkgconfig prefixes/client/meson.build3
-rw-r--r--test cases/unit/76 pkgconfig prefixes/val1/meson.build5
-rw-r--r--test cases/unit/76 pkgconfig prefixes/val1/val1.c3
-rw-r--r--test cases/unit/76 pkgconfig prefixes/val1/val1.h1
-rw-r--r--test cases/unit/76 pkgconfig prefixes/val2/meson.build8
-rw-r--r--test cases/unit/76 pkgconfig prefixes/val2/val2.c4
-rw-r--r--test cases/unit/76 pkgconfig prefixes/val2/val2.h1
21 files changed, 177 insertions, 55 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 2727abe..6f6d3db 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -90,12 +90,13 @@ class InstallData:
self.mesonintrospect = mesonintrospect
class TargetInstallData:
- def __init__(self, fname, outdir, aliases, strip, install_name_mappings, install_rpath, install_mode, optional=False):
+ def __init__(self, fname, outdir, aliases, strip, install_name_mappings, rpath_dirs_to_remove, install_rpath, install_mode, optional=False):
self.fname = fname
self.outdir = outdir
self.aliases = aliases
self.strip = strip
self.install_name_mappings = install_name_mappings
+ self.rpath_dirs_to_remove = rpath_dirs_to_remove
self.install_rpath = install_rpath
self.install_mode = install_mode
self.optional = optional
@@ -476,6 +477,7 @@ class Backend:
result = OrderedSet()
result.add('meson-out')
result.update(self.rpaths_for_bundled_shared_libraries(target))
+ target.rpath_dirs_to_remove.update([d.encode('utf8') for d in result])
return tuple(result)
def object_filename_from_source(self, target, source):
@@ -1140,6 +1142,7 @@ class Backend:
mappings = t.get_link_deps_mapping(d.prefix, self.environment)
i = TargetInstallData(self.get_target_filename(t), outdirs[0],
t.get_aliases(), should_strip, mappings,
+ t.rpath_dirs_to_remove,
t.install_rpath, install_mode)
d.targets.append(i)
@@ -1157,14 +1160,14 @@ class Backend:
implib_install_dir = self.environment.get_import_lib_dir()
# Install the import library; may not exist for shared modules
i = TargetInstallData(self.get_target_filename_for_linking(t),
- implib_install_dir, {}, False, {}, '', install_mode,
+ implib_install_dir, {}, False, {}, set(), '', install_mode,
optional=isinstance(t, build.SharedModule))
d.targets.append(i)
if not should_strip and t.get_debug_filename():
debug_file = os.path.join(self.get_target_dir(t), t.get_debug_filename())
i = TargetInstallData(debug_file, outdirs[0],
- {}, False, {}, '',
+ {}, False, {}, set(), '',
install_mode, optional=True)
d.targets.append(i)
# Install secondary outputs. Only used for Vala right now.
@@ -1174,7 +1177,7 @@ class Backend:
if outdir is False:
continue
f = os.path.join(self.get_target_dir(t), output)
- i = TargetInstallData(f, outdir, {}, False, {}, None, install_mode)
+ i = TargetInstallData(f, outdir, {}, False, {}, set(), None, install_mode)
d.targets.append(i)
elif isinstance(t, build.CustomTarget):
# If only one install_dir is specified, assume that all
@@ -1187,7 +1190,7 @@ class Backend:
if num_outdirs == 1 and num_out > 1:
for output in t.get_outputs():
f = os.path.join(self.get_target_dir(t), output)
- i = TargetInstallData(f, outdirs[0], {}, False, {}, None, install_mode,
+ i = TargetInstallData(f, outdirs[0], {}, False, {}, set(), None, install_mode,
optional=not t.build_by_default)
d.targets.append(i)
else:
@@ -1196,7 +1199,7 @@ class Backend:
if outdir is False:
continue
f = os.path.join(self.get_target_dir(t), output)
- i = TargetInstallData(f, outdir, {}, False, {}, None, install_mode,
+ i = TargetInstallData(f, outdir, {}, False, {}, set(), None, install_mode,
optional=not t.build_by_default)
d.targets.append(i)
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 9b895c9..49025f9 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1348,7 +1348,8 @@ int dummy;
self.get_target_dir(target))
else:
target_slashname_workaround_dir = self.get_target_dir(target)
- rpath_args = rustc.build_rpath_args(self.environment,
+ (rpath_args, target.rpath_dirs_to_remove) = \
+ rustc.build_rpath_args(self.environment,
self.environment.get_build_dir(),
target_slashname_workaround_dir,
self.determine_rpath_dirs(target),
@@ -2580,12 +2581,14 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
self.get_target_dir(target))
else:
target_slashname_workaround_dir = self.get_target_dir(target)
- commands += linker.build_rpath_args(self.environment,
+ (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/mesonbuild/build.py b/mesonbuild/build.py
index 2b4b1b9..7c833a6 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -511,6 +511,8 @@ class BuildTarget(Target):
self.d_features = {}
self.pic = False
self.pie = False
+ # Track build_rpath entries so we can remove them at install time
+ self.rpath_dirs_to_remove = set()
# Sources can be:
# 1. Pre-existing source files in the source tree
# 2. Pre-existing sources generated by configure_file in the build tree
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 3d3a503..b2bea26 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -1077,7 +1077,7 @@ class Compiler:
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
return self.linker.build_rpath_args(
env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py
index e839f53..4e89f5d 100644
--- a/mesonbuild/compilers/cuda.py
+++ b/mesonbuild/compilers/cuda.py
@@ -271,9 +271,10 @@ class CudaCompiler(Compiler):
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
- return self._cook_link_args(self.host_compiler.build_rpath_args(
- env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath))
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+ (rpath_args, rpath_dirs_to_remove) = self.host_compiler.build_rpath_args(
+ env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
+ return (self._cook_link_args(rpath_args), rpath_dirs_to_remove)
def linker_to_compiler_args(self, args):
return args
diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py
index a83e221..e7bd280 100644
--- a/mesonbuild/compilers/d.py
+++ b/mesonbuild/compilers/d.py
@@ -220,7 +220,7 @@ class DmdLikeCompilerMixin:
def build_rpath_args(self, env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
if self.info.is_windows():
- return []
+ return ([], set())
# GNU ld, solaris ld, and lld acting like GNU ld
if self.linker.id.startswith('ld'):
@@ -228,15 +228,16 @@ class DmdLikeCompilerMixin:
# do directly, each argument -rpath and the value to rpath, need to be
# split into two separate arguments both prefaced with the -L=.
args = []
- for r in super().build_rpath_args(
- env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
+ (rpath_args, rpath_dirs_to_remove) = super().build_rpath_args(
+ env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
+ for r in rpath_args:
if ',' in r:
a, b = r.split(',', maxsplit=1)
args.append(a)
args.append(self.LINKER_PREFIX + b)
else:
args.append(r)
- return args
+ return (args, rpath_dirs_to_remove)
return super().build_rpath_args(
env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
diff --git a/mesonbuild/compilers/mixins/islinker.py b/mesonbuild/compilers/mixins/islinker.py
index 681c816..bf1d339 100644
--- a/mesonbuild/compilers/mixins/islinker.py
+++ b/mesonbuild/compilers/mixins/islinker.py
@@ -107,8 +107,8 @@ class BasicLinkerIsCompilerMixin:
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
- return []
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+ return ([], set())
def get_linker_debug_crt_args(self) -> T.List[str]:
return []
diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py
index db735e7..f02c297 100644
--- a/mesonbuild/linkers.py
+++ b/mesonbuild/linkers.py
@@ -56,8 +56,8 @@ class StaticLinker:
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
- return []
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+ return ([], set())
def thread_link_flags(self, env: 'Environment') -> T.List[str]:
return []
@@ -444,8 +444,8 @@ class DynamicLinker(LinkerEnvVarsMixin, metaclass=abc.ABCMeta):
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
- return []
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+ return ([], set())
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
@@ -551,12 +551,12 @@ class GnuLikeDynamicLinkerMixin:
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
m = env.machines[self.for_machine]
if m.is_windows() or m.is_cygwin():
- return []
+ return ([], set())
if not rpath_paths and not install_rpath and not build_rpath:
- return []
+ return ([], set())
args = []
origin_placeholder = '$ORIGIN'
processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
@@ -564,9 +564,14 @@ class GnuLikeDynamicLinkerMixin:
# is *very* allergic to duplicate -delete_rpath arguments
# when calling depfixer on installation.
all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths])
+ rpath_dirs_to_remove = set()
+ for p in all_paths:
+ rpath_dirs_to_remove.add(p.encode('utf8'))
# Build_rpath is used as-is (it is usually absolute).
if build_rpath != '':
all_paths.add(build_rpath)
+ for p in build_rpath.split(':'):
+ rpath_dirs_to_remove.add(p.encode('utf8'))
# TODO: should this actually be "for (dragonfly|open)bsd"?
if mesonlib.is_dragonflybsd() or mesonlib.is_openbsd():
@@ -590,7 +595,7 @@ class GnuLikeDynamicLinkerMixin:
# TODO: should this actually be "for solaris/sunos"?
if mesonlib.is_sunos():
- return args
+ return (args, rpath_dirs_to_remove)
# Rpaths to use while linking must be absolute. These are not
# written to the binary. Needed only with GNU ld:
@@ -610,7 +615,7 @@ class GnuLikeDynamicLinkerMixin:
for p in rpath_paths:
args.extend(self._apply_prefix('-rpath-link,' + os.path.join(build_dir, p)))
- return args
+ return (args, rpath_dirs_to_remove)
class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
@@ -676,9 +681,9 @@ class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
if not rpath_paths and not install_rpath and not build_rpath:
- return []
+ return ([], set())
# Ensure that there is enough space for install_name_tool in-place
# editing of large RPATHs
args = self._apply_prefix('-headerpad_max_install_names')
@@ -692,7 +697,7 @@ class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
for rp in all_paths:
args.extend(self._apply_prefix('-rpath,' + rp))
- return args
+ return (args, set())
class GnuDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker):
@@ -763,8 +768,8 @@ class WASMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, Dyna
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
- return []
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+ return ([], set())
class CcrxDynamicLinker(DynamicLinker):
@@ -839,8 +844,8 @@ class Xc16DynamicLinker(DynamicLinker):
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
- return []
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+ return ([], set())
class C2000DynamicLinker(DynamicLinker):
@@ -938,10 +943,10 @@ class PGIDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
if not env.machines[self.for_machine].is_windows():
- return ['-R' + os.path.join(build_dir, p) for p in rpath_paths]
- return []
+ return (['-R' + os.path.join(build_dir, p) for p in rpath_paths], set())
+ return ([], set())
class PGIStaticLinker(StaticLinker):
@@ -1091,9 +1096,9 @@ class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
if not rpath_paths and not install_rpath and not build_rpath:
- return []
+ return ([], set())
processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
all_paths = mesonlib.OrderedSet([os.path.join('$ORIGIN', p) for p in processed_rpaths])
if build_rpath != '':
@@ -1108,7 +1113,7 @@ class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
paths = padding
else:
paths = paths + ':' + padding
- return self._apply_prefix('-rpath,{}'.format(paths))
+ return (self._apply_prefix('-rpath,{}'.format(paths)), set())
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py
index 9c64429..0be01fe 100644
--- a/mesonbuild/minstall.py
+++ b/mesonbuild/minstall.py
@@ -512,7 +512,7 @@ class Installer:
if file_copied:
self.did_install_something = True
try:
- depfixer.fix_rpath(outname, install_rpath, final_path,
+ depfixer.fix_rpath(outname, t.rpath_dirs_to_remove, install_rpath, final_path,
install_name_mappings, verbose=False)
except SystemExit as e:
if isinstance(e.code, int) and e.code == 0:
diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py
index 5ba3a97..a3a3eff 100644
--- a/mesonbuild/scripts/depfixer.py
+++ b/mesonbuild/scripts/depfixer.py
@@ -290,13 +290,13 @@ class Elf(DataSizes):
self.bf.seek(offset)
self.bf.write(newname)
- def fix_rpath(self, new_rpath):
+ def fix_rpath(self, rpath_dirs_to_remove, new_rpath):
# The path to search for can be either rpath or runpath.
# Fix both of them to be sure.
- self.fix_rpathtype_entry(new_rpath, DT_RPATH)
- self.fix_rpathtype_entry(new_rpath, DT_RUNPATH)
+ self.fix_rpathtype_entry(rpath_dirs_to_remove, new_rpath, DT_RPATH)
+ self.fix_rpathtype_entry(rpath_dirs_to_remove, new_rpath, DT_RUNPATH)
- def fix_rpathtype_entry(self, new_rpath, entrynum):
+ def fix_rpathtype_entry(self, rpath_dirs_to_remove, new_rpath, entrynum):
if isinstance(new_rpath, str):
new_rpath = new_rpath.encode('utf8')
rp_off = self.get_entry_offset(entrynum)
@@ -305,7 +305,23 @@ class Elf(DataSizes):
print('File does not have rpath. It should be a fully static executable.')
return
self.bf.seek(rp_off)
+
old_rpath = self.read_str()
+ new_rpaths = []
+ if new_rpath:
+ new_rpaths.append(new_rpath)
+ if old_rpath:
+ # Filter out build-only rpath entries
+ # added by get_link_dep_subdirs() or
+ # specified by user with build_rpath.
+ for dir in old_rpath.split(b':'):
+ if not (dir in rpath_dirs_to_remove or
+ dir == (b'X' * len(dir))):
+ new_rpaths.append(dir)
+
+ # Prepend user-specified new entries while preserving the ones that came from pkgconfig etc.
+ new_rpath = b':'.join(new_rpaths)
+
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
@@ -343,13 +359,13 @@ class Elf(DataSizes):
entry.write(self.bf)
return None
-def fix_elf(fname, new_rpath, verbose=True):
+def fix_elf(fname, rpath_dirs_to_remove, new_rpath, verbose=True):
with Elf(fname, verbose) as e:
if new_rpath is None:
e.print_rpath()
e.print_runpath()
else:
- e.fix_rpath(new_rpath)
+ e.fix_rpath(rpath_dirs_to_remove, new_rpath)
def get_darwin_rpaths_to_remove(fname):
out = subprocess.check_output(['otool', '-l', fname],
@@ -430,7 +446,7 @@ def fix_jar(fname):
f.truncate()
subprocess.check_call(['jar', 'ufm', fname, 'META-INF/MANIFEST.MF'])
-def fix_rpath(fname, new_rpath, final_path, install_name_mappings, verbose=True):
+def fix_rpath(fname, rpath_dirs_to_remove, new_rpath, final_path, install_name_mappings, verbose=True):
global INSTALL_NAME_TOOL
# Static libraries, import libraries, debug information, headers, etc
# never have rpaths
@@ -441,7 +457,7 @@ def fix_rpath(fname, new_rpath, final_path, install_name_mappings, verbose=True)
if fname.endswith('.jar'):
fix_jar(fname)
return
- fix_elf(fname, new_rpath, verbose)
+ fix_elf(fname, rpath_dirs_to_remove, new_rpath, verbose)
return
except SystemExit as e:
if isinstance(e.code, int) and e.code == 0:
diff --git a/run_unittests.py b/run_unittests.py
index 2939b20..d7fc221 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -56,7 +56,7 @@ from mesonbuild.mesonlib import (
BuildDirLock, LibType, MachineChoice, PerMachine, Version, is_windows,
is_osx, is_cygwin, is_dragonflybsd, is_openbsd, is_haiku, is_sunos,
windows_proof_rmtree, python_command, version_compare, split_args,
- quote_arg, relpath
+ quote_arg, relpath, is_linux
)
from mesonbuild.environment import detect_ninja
from mesonbuild.mesonlib import MesonException, EnvironmentException
@@ -6390,13 +6390,15 @@ class LinuxlikeTests(BasePlatformTests):
self.build(override_envvars=env)
# test uninstalled
self.run_tests(override_envvars=env)
- if not is_osx():
- # Rest of the workflow only works on macOS
+ if not (is_osx() or is_linux()):
return
# test running after installation
self.install(use_destdir=False)
prog = os.path.join(self.installdir, 'bin', 'prog')
self._run([prog])
+ if not is_osx():
+ # Rest of the workflow only works on macOS
+ return
out = self._run(['otool', '-L', prog])
self.assertNotIn('@rpath', out)
## New builddir for testing that DESTDIR is not added to install_name
@@ -6413,6 +6415,57 @@ class LinuxlikeTests(BasePlatformTests):
# Ensure that the otool output does not contain self.installdir
self.assertNotRegex(out, self.installdir + '.*dylib ')
+ @skipIfNoPkgconfig
+ def test_usage_pkgconfig_prefixes(self):
+ '''
+ Build and install two external libraries, to different prefixes,
+ then build and install a client program that finds them via pkgconfig,
+ and verify the installed client program runs.
+ '''
+ oldinstalldir = self.installdir
+
+ # Build and install both external libraries without DESTDIR
+ val1dir = os.path.join(self.unit_test_dir, '76 pkgconfig prefixes', 'val1')
+ val1prefix = os.path.join(oldinstalldir, 'val1')
+ self.prefix = val1prefix
+ self.installdir = val1prefix
+ self.init(val1dir)
+ self.build()
+ self.install(use_destdir=False)
+ self.new_builddir()
+
+ env1 = {}
+ env1['PKG_CONFIG_PATH'] = os.path.join(val1prefix, self.libdir, 'pkgconfig')
+ val2dir = os.path.join(self.unit_test_dir, '76 pkgconfig prefixes', 'val2')
+ val2prefix = os.path.join(oldinstalldir, 'val2')
+ self.prefix = val2prefix
+ self.installdir = val2prefix
+ self.init(val2dir, override_envvars=env1)
+ self.build()
+ self.install(use_destdir=False)
+ self.new_builddir()
+
+ # Build, install, and run the client program
+ env2 = {}
+ env2['PKG_CONFIG_PATH'] = os.path.join(val2prefix, self.libdir, 'pkgconfig')
+ testdir = os.path.join(self.unit_test_dir, '76 pkgconfig prefixes', 'client')
+ testprefix = os.path.join(oldinstalldir, 'client')
+ self.prefix = testprefix
+ self.installdir = testprefix
+ self.init(testdir, override_envvars=env2)
+ self.build()
+ self.install(use_destdir=False)
+ prog = os.path.join(self.installdir, 'bin', 'client')
+ env3 = {}
+ if is_cygwin():
+ env3['PATH'] = os.path.join(val1prefix, 'bin') + \
+ os.pathsep + \
+ os.path.join(val2prefix, 'bin') + \
+ os.pathsep + os.environ['PATH']
+ out = self._run([prog], override_envvars=env3).strip()
+ # Expected output is val1 + val2 = 3
+ self.assertEqual(out, '3')
+
def install_subdir_invalid_symlinks(self, testdir, subdir_path):
'''
Test that installation of broken symlinks works fine.
diff --git a/test cases/unit/40 external, internal library rpath/built library/meson.build b/test cases/unit/40 external, internal library rpath/built library/meson.build
index f633996..07fe7bb 100644
--- a/test cases/unit/40 external, internal library rpath/built library/meson.build
+++ b/test cases/unit/40 external, internal library rpath/built library/meson.build
@@ -18,4 +18,9 @@ l = shared_library('bar_built', 'bar.c',
if host_machine.system() == 'darwin'
e = executable('prog', 'prog.c', link_with: l, install: true)
test('testprog', e)
+elif host_machine.system() == 'linux'
+ e = executable('prog', 'prog.c', link_with: l, install: true,
+ install_rpath: '$ORIGIN/..' / get_option('libdir'),
+ )
+ test('testprog', e)
endif
diff --git a/test cases/unit/40 external, internal library rpath/external library/meson.build b/test cases/unit/40 external, internal library rpath/external library/meson.build
index 3c311f5..06ffa0f 100644
--- a/test cases/unit/40 external, internal library rpath/external library/meson.build
+++ b/test cases/unit/40 external, internal library rpath/external library/meson.build
@@ -4,16 +4,16 @@ shared_library('foo_in_system', 'foo.c', install : true)
l = shared_library('faa_pkg', 'faa.c', install: true)
if host_machine.system() == 'darwin'
- frameworks = ['-framework', 'CoreFoundation', '-framework', 'CoreMedia']
+ ldflags = ['-framework', 'CoreFoundation', '-framework', 'CoreMedia']
allow_undef_args = ['-Wl,-undefined,dynamic_lookup']
else
- frameworks = []
+ ldflags = ['-Wl,-rpath,${libdir}']
allow_undef_args = []
endif
pkg = import('pkgconfig')
pkg.generate(name: 'faa_pkg',
- libraries: [l] + frameworks,
+ libraries: [l] + ldflags,
description: 'FAA, a pkg-config test library')
# cygwin DLLs can't have undefined symbols
diff --git a/test cases/unit/76 pkgconfig prefixes/client/client.c b/test cases/unit/76 pkgconfig prefixes/client/client.c
new file mode 100644
index 0000000..be9bead
--- /dev/null
+++ b/test cases/unit/76 pkgconfig prefixes/client/client.c
@@ -0,0 +1,8 @@
+#include <val2.h>
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+ printf("%d\n", val2());
+ return 0;
+}
diff --git a/test cases/unit/76 pkgconfig prefixes/client/meson.build b/test cases/unit/76 pkgconfig prefixes/client/meson.build
new file mode 100644
index 0000000..491937b
--- /dev/null
+++ b/test cases/unit/76 pkgconfig prefixes/client/meson.build
@@ -0,0 +1,3 @@
+project('client', 'c')
+val2_dep = dependency('val2')
+executable('client', 'client.c', dependencies : [val2_dep], install: true)
diff --git a/test cases/unit/76 pkgconfig prefixes/val1/meson.build b/test cases/unit/76 pkgconfig prefixes/val1/meson.build
new file mode 100644
index 0000000..cc63e31
--- /dev/null
+++ b/test cases/unit/76 pkgconfig prefixes/val1/meson.build
@@ -0,0 +1,5 @@
+project('val1', 'c')
+val1 = shared_library('val1', 'val1.c', install: true)
+install_headers('val1.h')
+pkgconfig = import('pkgconfig')
+pkgconfig.generate(val1, libraries : ['-Wl,-rpath,${libdir}'])
diff --git a/test cases/unit/76 pkgconfig prefixes/val1/val1.c b/test cases/unit/76 pkgconfig prefixes/val1/val1.c
new file mode 100644
index 0000000..591e521
--- /dev/null
+++ b/test cases/unit/76 pkgconfig prefixes/val1/val1.c
@@ -0,0 +1,3 @@
+#include "val1.h"
+
+int val1(void) { return 1; }
diff --git a/test cases/unit/76 pkgconfig prefixes/val1/val1.h b/test cases/unit/76 pkgconfig prefixes/val1/val1.h
new file mode 100644
index 0000000..6bd435e
--- /dev/null
+++ b/test cases/unit/76 pkgconfig prefixes/val1/val1.h
@@ -0,0 +1 @@
+int val1(void);
diff --git a/test cases/unit/76 pkgconfig prefixes/val2/meson.build b/test cases/unit/76 pkgconfig prefixes/val2/meson.build
new file mode 100644
index 0000000..ce69481
--- /dev/null
+++ b/test cases/unit/76 pkgconfig prefixes/val2/meson.build
@@ -0,0 +1,8 @@
+project('val2', 'c')
+val1_dep = dependency('val1')
+val2 = shared_library('val2', 'val2.c',
+ dependencies : [val1_dep],
+ install: true)
+install_headers('val2.h')
+pkgconfig = import('pkgconfig')
+pkgconfig.generate(val2, libraries : ['-Wl,-rpath,${libdir}'])
diff --git a/test cases/unit/76 pkgconfig prefixes/val2/val2.c b/test cases/unit/76 pkgconfig prefixes/val2/val2.c
new file mode 100644
index 0000000..d7d4857
--- /dev/null
+++ b/test cases/unit/76 pkgconfig prefixes/val2/val2.c
@@ -0,0 +1,4 @@
+#include "val1.h"
+#include "val2.h"
+
+int val2(void) { return val1() + 2; }
diff --git a/test cases/unit/76 pkgconfig prefixes/val2/val2.h b/test cases/unit/76 pkgconfig prefixes/val2/val2.h
new file mode 100644
index 0000000..995023d
--- /dev/null
+++ b/test cases/unit/76 pkgconfig prefixes/val2/val2.h
@@ -0,0 +1 @@
+int val2(void);