diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 2727abec8..6f6d3db0f 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 9b895c908..49025f9d4 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 2b4b1b980..7c833a6b1 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 3d3a503cd..b2bea26ae 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 e839f532f..4e89f5d0a 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 a83e22116..e7bd2807b 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 681c8164c..bf1d339a2 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 db735e7ea..f02c297ea 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 9c644297f..0be01fe75 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 5ba3a9728..a3a3eff05 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 2939b2095..d7fc221dc 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 f63399659..07fe7bb2b 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 3c311f592..06ffa0f72 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 000000000..be9beadb0 --- /dev/null +++ b/test cases/unit/76 pkgconfig prefixes/client/client.c @@ -0,0 +1,8 @@ +#include +#include + +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 000000000..491937b7b --- /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 000000000..cc63e3143 --- /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 000000000..591e52162 --- /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 000000000..6bd435eb9 --- /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 000000000..ce69481ec --- /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 000000000..d7d485730 --- /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 000000000..995023da2 --- /dev/null +++ b/test cases/unit/76 pkgconfig prefixes/val2/val2.h @@ -0,0 +1 @@ +int val2(void);