From 1ce4258c219fe08b6d6eaa6aa944f27d91d054cb Mon Sep 17 00:00:00 2001 From: James Hilliard Date: Sat, 18 Jul 2020 17:01:33 -0600 Subject: [PATCH] backends: fix rpath match pattern Since -Wl,-rpath= is not the only valid rpath ldflags syntax we need to try and match all valid rpath ldflags. In addition we should prevent -Wl,--just-symbols from being used to set rpath due to inconsistent compiler support. Signed-off-by: James Hilliard --- mesonbuild/backend/backends.py | 30 ++++++++++++++++++++++++-- run_unittests.py | 39 +++++++++++++++++++++++----------- 2 files changed, 55 insertions(+), 14 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index cfd3a397fd..e053f67e6b 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -14,6 +14,7 @@ from collections import OrderedDict from functools import lru_cache +from pathlib import Path import enum import json import os @@ -455,10 +456,35 @@ def get_external_rpath_dirs(self, target): args.extend(self.environment.coredata.get_external_link_args(target.for_machine, lang)) except Exception: pass + # Match rpath formats: + # -Wl,-rpath= + # -Wl,-rpath, + rpath_regex = re.compile(r'-Wl,-rpath[=,]([^,]+)') + # Match solaris style compat runpath formats: + # -Wl,-R + # -Wl,-R, + runpath_regex = re.compile(r'-Wl,-R[,]?([^,]+)') + # Match symbols formats: + # -Wl,--just-symbols= + # -Wl,--just-symbols, + symbols_regex = re.compile(r'-Wl,--just-symbols[=,]([^,]+)') for arg in args: - if arg.startswith('-Wl,-rpath='): - for dir in arg.replace('-Wl,-rpath=','').split(':'): + rpath_match = rpath_regex.match(arg) + if rpath_match: + for dir in rpath_match.group(1).split(':'): dirs.add(dir) + runpath_match = runpath_regex.match(arg) + if runpath_match: + for dir in runpath_match.group(1).split(':'): + # The symbols arg is an rpath if the path is a directory + if Path(dir).is_dir(): + dirs.add(dir) + symbols_match = symbols_regex.match(arg) + if symbols_match: + for dir in symbols_match.group(1).split(':'): + # Prevent usage of --just-symbols to specify rpath + if Path(dir).is_dir(): + raise MesonException('Invalid arg for --just-symbols, {} is a directory.'.format(dir)) return dirs def rpaths_for_bundled_shared_libraries(self, target, exclude_system=True): diff --git a/run_unittests.py b/run_unittests.py index b5294b9f82..73131c75b7 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -6451,19 +6451,34 @@ def test_global_rpath(self): self.init(yonder_dir) self.build() self.install(use_destdir=False) - self.new_builddir() - # Build an app that uses that installed library. - # Supply the rpath to the installed library via LDFLAGS - # (as systems like buildroot and guix are wont to do) - # and verify install preserves that rpath. - env = {'LDFLAGS': '-Wl,-rpath=' + yonder_libdir, - 'PKG_CONFIG_PATH': os.path.join(yonder_libdir, 'pkgconfig')} - self.init(testdir, override_envvars=env) - self.build() - self.install(use_destdir=False) - got_rpath = get_rpath(os.path.join(yonder_prefix, 'bin/rpathified')) - self.assertEqual(got_rpath, yonder_libdir) + # Since rpath has multiple valid formats we need to + # test that they are all properly used. + rpath_formats = [ + ('-Wl,-rpath=', False), + ('-Wl,-rpath,', False), + ('-Wl,--just-symbols=', True), + ('-Wl,--just-symbols,', True), + ('-Wl,-R', False), + ('-Wl,-R,', False) + ] + for rpath_format, exception in rpath_formats: + # Build an app that uses that installed library. + # Supply the rpath to the installed library via LDFLAGS + # (as systems like buildroot and guix are wont to do) + # and verify install preserves that rpath. + self.new_builddir() + env = {'LDFLAGS': rpath_format + yonder_libdir, + 'PKG_CONFIG_PATH': os.path.join(yonder_libdir, 'pkgconfig')} + if exception: + with self.assertRaises(subprocess.CalledProcessError): + self.init(testdir, override_envvars=env) + break + self.init(testdir, override_envvars=env) + self.build() + self.install(use_destdir=False) + got_rpath = get_rpath(os.path.join(yonder_prefix, 'bin/rpathified')) + self.assertEqual(got_rpath, yonder_libdir, rpath_format) @skip_if_not_base_option('b_sanitize') def test_pch_with_address_sanitizer(self):