[gobject-introspection/gnome-3-32] shlibs: fall back to basename on macOS for relative paths. Fixes #222



commit 2079bad007d7d0c11e9267efde175fb03a63b828
Author: Christoph Reiter <reiter christoph gmail com>
Date:   Sun Mar 24 19:28:52 2019 +0100

    shlibs: fall back to basename on macOS for relative paths. Fixes #222
    
    On macOS we ideally want to write the final absolute path of the library
    into the gir and typelib. Up until now we inferred the install path from
    the .la file in case we used libtool and through otool in case we weren't
    using libtool hoping that the install_name was matching the install path.
    
    meson currently sets the install_name of libraries to "@rpath/foo.dylib"
    and adds rpaths to the executables in the build dir. Only during install does
    it change the install_name to the absolute target path in all places.
    
    Since we get called during build time we only get the @rpath from otool,
    which then makes things fail at runtime since the executables don't have
    the matching rpath set.
    
    To make this somewhat work just fall back to the basename for relative
    paths, so we dlopen "foo.dylib" and depend on things being in /usr/local/lib
    or DYLD_FALLBACK_LIBRARY_PATH including the lib path (see man dlopen)

 giscanner/shlibs.py          | 25 ++++++++++++++++++-------
 tests/scanner/test_shlibs.py | 31 ++++++++++++++++++++++++++-----
 2 files changed, 44 insertions(+), 12 deletions(-)
---
diff --git a/giscanner/shlibs.py b/giscanner/shlibs.py
index 2c61f2f7..e6de7bb6 100644
--- a/giscanner/shlibs.py
+++ b/giscanner/shlibs.py
@@ -19,6 +19,7 @@
 #
 
 import os
+import sys
 import platform
 import re
 import subprocess
@@ -104,13 +105,25 @@ def _resolve_non_libtool(options, binary, libraries):
         if isinstance(output, bytes):
             output = output.decode("utf-8", "replace")
 
-        # Use absolute paths on OS X to conform to how libraries are usually
-        # referenced on OS X systems, and file names everywhere else.
-        basename = platform.system() != 'Darwin'
-        return resolve_from_ldd_output(libraries, output, basename=basename)
+        shlibs = resolve_from_ldd_output(libraries, output)
+        return list(map(sanitize_shlib_path, shlibs))
 
 
-def resolve_from_ldd_output(libraries, output, basename=False):
+def sanitize_shlib_path(lib):
+    # Use absolute paths on OS X to conform to how libraries are usually
+    # referenced on OS X systems, and file names everywhere else.
+    # In case we get relative paths on macOS (like @rpath) then we fall
+    # back to the basename as well:
+    # https://gitlab.gnome.org/GNOME/gobject-introspection/issues/222
+    if sys.platform == "darwin":
+        if not os.path.isabs(lib):
+            return os.path.basename(lib)
+        return lib
+    else:
+        return os.path.basename(lib)
+
+
+def resolve_from_ldd_output(libraries, output):
     patterns = {}
     for library in libraries:
         if not os.path.isfile(library):
@@ -138,8 +151,6 @@ def resolve_from_ldd_output(libraries, output, basename=False):
             "ERROR: can't resolve libraries to shared libraries: " +
             ", ".join(patterns.keys()))
 
-    if basename:
-        shlibs = list(map(os.path.basename, shlibs))
     return shlibs
 
 
diff --git a/tests/scanner/test_shlibs.py b/tests/scanner/test_shlibs.py
index f3fb0d2e..a8337c60 100644
--- a/tests/scanner/test_shlibs.py
+++ b/tests/scanner/test_shlibs.py
@@ -1,6 +1,8 @@
 import unittest
+import sys
+import os
 
-from giscanner.shlibs import resolve_from_ldd_output
+from giscanner.shlibs import resolve_from_ldd_output, sanitize_shlib_path
 
 
 class TestLddParser(unittest.TestCase):
@@ -18,6 +20,28 @@ class TestLddParser(unittest.TestCase):
             ['libglib-2.0.so.0', 'libgtk-3.so.0', 'libpango-1.0.so.0'],
             resolve_from_ldd_output(libraries, output))
 
+    @unittest.skipUnless(os.name == "posix", "posix only")
+    def test_resolve_from_ldd_output_macos_rpath(self):
+        output = '''\
+            @rpath/libbarapp-1.0.dylib (compatibility version 0.0.0, current version 0.0.0)
+            /foo/libgio-2.0.0.dylib (compatibility version 5801.0.0, current version 5801.3.0)
+            /foo/libgmodule-2.0.0.dylib (compatibility version 5801.0.0, current version 5801.3.0)'''
+
+        libraries = ['barapp-1.0']
+        shlibs = resolve_from_ldd_output(libraries, output)
+        self.assertEqual(shlibs, ['@rpath/libbarapp-1.0.dylib'])
+        self.assertEqual(sanitize_shlib_path(shlibs[0]), 'libbarapp-1.0.dylib')
+
+    @unittest.skipUnless(os.name == "posix", "posix only")
+    def test_sanitize_shlib_path(self):
+        self.assertEqual(
+            sanitize_shlib_path('@rpath/libbarapp-1.0.dylib'),
+            'libbarapp-1.0.dylib')
+
+        self.assertEqual(
+            sanitize_shlib_path('/foo/bar'),
+            '/foo/bar' if sys.platform == 'darwin' else 'bar')
+
     def test_unresolved_library(self):
         output = ''
         libraries = ['foo']
@@ -87,10 +111,7 @@ class TestLddParser(unittest.TestCase):
 
         self.assertEqual(
             ['/usr/lib/libfoo.so'],
-            resolve_from_ldd_output(['foo'], output, basename=False))
-        self.assertEqual(
-            ['libfoo.so'],
-            resolve_from_ldd_output(['foo'], output, basename=True))
+            resolve_from_ldd_output(['foo'], output))
 
 
 if __name__ == '__main__':


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]