From 264ce6c0bc27d2998368b7652b1c12729f088d3a Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Mon, 5 Jun 2017 02:11:43 +0530 Subject: [PATCH] Use absolute RPATHs while linking due to a binutils bug Use -rpath-link with the absolute paths to the respective build dirs to work around a binutils bug that causes $ORIGIN to not be used while linking. Includes a unit test that manually checks the RPATH value written out to ensure that it uses $ORIGIN. See: https://sourceware.org/bugzilla/show_bug.cgi?id=16936 Closes https://github.com/mesonbuild/meson/issues/1897 --- mesonbuild/compilers.py | 7 ++++++- run_unittests.py | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 06b0a5904..595be6099 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -337,7 +337,12 @@ def build_unix_rpath_args(build_dir, from_dir, rpath_paths, install_rpath): paths = padding else: paths = paths + ':' + padding - return ['-Wl,-rpath,' + paths] + # Rpaths to use while linking must be absolute. These are not used + # while running and are not written to the binary. + # https://github.com/mesonbuild/meson/issues/1897 + # https://sourceware.org/bugzilla/show_bug.cgi?id=16936 + linkpaths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths]) + return ['-Wl,-rpath,' + paths, '-Wl,-rpath-link,' + linkpaths] class CrossNoRunException(MesonException): pass diff --git a/run_unittests.py b/run_unittests.py index 34a1a158e..6d81b00ff 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -49,6 +49,9 @@ def get_dynamic_section_entry(fname, entry): def get_soname(fname): return get_dynamic_section_entry(fname, 'soname') +def get_rpath(fname): + return get_dynamic_section_entry(fname, 'rpath') + class InternalTests(unittest.TestCase): @@ -1133,6 +1136,25 @@ int main(int argc, char **argv) { self.assertTrue(os.path.exists(distfile)) self.assertTrue(os.path.exists(checksumfile)) + def test_rpath_uses_ORIGIN(self): + ''' + Test that built targets use $ORIGIN in rpath, which ensures that they + are relocatable and ensures that builds are reproducible since the + build directory won't get embedded into the built binaries. + ''' + if is_windows() or is_cygwin(): + raise unittest.SkipTest('Windows PE/COFF binaries do not use RPATH') + testdir = os.path.join(self.common_test_dir, '46 library chain') + self.init(testdir) + self.build() + for each in ('prog', 'subdir/liblib1.so', 'subdir/subdir2/liblib2.so', + 'subdir/subdir3/liblib3.so'): + rpath = get_rpath(os.path.join(self.builddir, each)) + self.assertTrue(rpath) + for path in rpath.split(':'): + self.assertTrue(path.startswith('$ORIGIN'), msg=(each, path)) + + class WindowsTests(BasePlatformTests): ''' Tests that should run on Cygwin, MinGW, and MSVC