unofficial mirror of guix-patches@gnu.org 
 help / color / mirror / code / Atom feed
blob 3c03dba218ba67e7de77fba4552b30c4853989c7 7561 bytes (raw)
name: gnu/packages/patches/gobject-introspection-absolute-shlib-path.patch 	 # note: path name is non-authoritative(*)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
 
From 8471367e35e122fb6e661c243810df92c69440b4 Mon Sep 17 00:00:00 2001
From: Raghav Gururajan <rg@raghavgururajan.name>
Date: Tue, 7 Sep 2021 17:15:18 -0400
Subject: Names of libraries included in typelib files are opened
 by dlopen. Here we add the full path.

This patch was provided by Luca Bruno <lucabru@src.gnome.org>,
for 'gobject-introspection' 1.40.0 in Nix.

It has since been updated to work with newer versions of
gobject-introspection.
---
 giscanner/scannermain.py     | 37 ++++++++++++++++++++++++++++++++++++
 giscanner/shlibs.py          | 30 ++++++++++++++++++++---------
 giscanner/utils.py           | 15 +++++----------
 tests/scanner/test_shlibs.py |  3 ++-
 4 files changed, 65 insertions(+), 20 deletions(-)

diff --git a/giscanner/scannermain.py b/giscanner/scannermain.py
index 957ba0b7..78f9b11b 100644
--- a/giscanner/scannermain.py
+++ b/giscanner/scannermain.py
@@ -95,6 +95,39 @@ def get_windows_option_group(parser):
     return group
 
 
+def _get_default_fallback_libpath():
+    # Newer multiple-output-optimized stdenv has an environment variable
+    # $outputLib which in turn specifies another variable which then is used as
+    # the destination for the library contents (${!outputLib}/lib).
+    store_path = os.environ.get(os.environ.get("outputLib")) if "outputLib" in os.environ else None
+    if store_path is None:
+        outputs = os.environ.get("outputs", "out").split()
+        if "lib" in outputs:
+            # For multiple output derivations let's try whether there is a $lib
+            # environment variable and use that as the base store path.
+            store_path = os.environ.get("lib")
+        elif "out" in outputs:
+            # Otherwise we have a single output derivation, so the libraries
+            # most certainly will end up in "$out/lib".
+            store_path = os.environ.get("out")
+
+    if store_path is not None:
+        # Even if we have a $lib as output, there still should be a $lib/lib
+        # directory.
+        return os.path.join(store_path, 'lib')
+    else:
+        # If we haven't found a possible scenario, let's return an empty string
+        # so that the shared library won't be prepended with a path.
+        #
+        # Note that this doesn't mean that all hope is lost, because after all
+        # we can still use --fallback-library-path to set one.
+        #
+        # Also, we're not returning None, because that would make it very
+        # difficult to disable adding fallback paths altogether using something
+        # like: --fallback-library-path=""
+        return ""
+
+
 def _get_option_parser():
     parser = optparse.OptionParser('%prog [options] sources',
                                    version='%prog ' + giscanner.__version__)
@@ -214,6 +247,10 @@ match the namespace prefix.""")
     parser.add_option("", "--filelist",
                       action="store", dest="filelist", default=[],
                       help="file containing headers and sources to be scanned")
+    parser.add_option("", "--fallback-library-path",
+                      action="store", dest="fallback_libpath",
+                      default=_get_default_fallback_libpath(),
+                      help="Path to prepend to unknown shared libraries")
 
     group = get_preprocessor_option_group(parser)
     parser.add_option_group(group)
diff --git a/giscanner/shlibs.py b/giscanner/shlibs.py
index 9f8ab5df..8aa37c99 100644
--- a/giscanner/shlibs.py
+++ b/giscanner/shlibs.py
@@ -57,6 +57,14 @@ def _ldd_library_pattern(library_name):
     $""" % re.escape(library_name), re.VERBOSE)
 
 
+def _ldd_library_guix_pattern(library_name):
+    store_dir = re.escape(
+      os.environ.get("NIX_STORE", default="/gnu/store")
+    )
+    pattern = r'(%s(?:/[^/]*)+lib%s[^A-Za-z0-9_-][^\s\(\)]*)'
+    return re.compile(pattern % (store_dir, re.escape(library_name)))
+
+
 # This is a what we do for non-la files. We assume that we are on an
 # ELF-like system where ldd exists and the soname extracted with ldd is
 # a filename that can be opened with dlopen().
@@ -108,7 +116,8 @@ def _resolve_non_libtool(options, binary, libraries):
             output = output.decode("utf-8", "replace")
 
         shlibs = resolve_from_ldd_output(libraries, output)
-        return list(map(sanitize_shlib_path, shlibs))
+        fallback_libpath = options.fallback_libpath or "";
+        return list(map(lambda p: os.path.join(fallback_libpath, p), map(sanitize_shlib_path, shlibs)))
 
 
 def sanitize_shlib_path(lib):
@@ -117,19 +126,18 @@ def sanitize_shlib_path(lib):
     # 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:
+
+    # Always use absolute paths if available
+    if not os.path.isabs(lib):
         return os.path.basename(lib)
+    return lib
 
 
 def resolve_from_ldd_output(libraries, output):
     patterns = {}
     for library in libraries:
         if not os.path.isfile(library):
-            patterns[library] = _ldd_library_pattern(library)
+            patterns[library] = (_ldd_library_pattern(library), _ldd_library_guix_pattern(library))
     if len(patterns) == 0:
         return []
 
@@ -141,8 +149,12 @@ def resolve_from_ldd_output(libraries, output):
         if line.endswith(':'):
             continue
         for word in line.split():
-            for library, pattern in patterns.items():
-                m = pattern.match(word)
+            for library, (pattern, guix_pattern) in patterns.items():
+                store_dir = os.environ.get("NIX_STORE", default="/gnu/store")
+                if line.find(store_dir) != -1:
+                    m = guix_pattern.match(word)
+                else:
+                    m = pattern.match(word)
                 if m:
                     del patterns[library]
                     shlibs.append(m.group())
diff --git a/giscanner/utils.py b/giscanner/utils.py
index 45807f17..8a319cd1 100644
--- a/giscanner/utils.py
+++ b/giscanner/utils.py
@@ -113,16 +113,11 @@ def extract_libtool_shlib(la_file):
     if dlname is None:
         return None
 
-    # Darwin uses absolute paths where possible; since the libtool files never
-    # contain absolute paths, use the libdir field
-    if platform.system() == 'Darwin':
-        dlbasename = os.path.basename(dlname)
-        libdir = _extract_libdir_field(la_file)
-        if libdir is None:
-            return dlbasename
-        return libdir + '/' + dlbasename
-    # Older libtools had a path rather than the raw dlname
-    return os.path.basename(dlname)
+    dlbasename = os.path.basename(dlname)
+    libdir = _extract_libdir_field(la_file)
+    if libdir is None:
+        return dlbasename
+    return libdir + '/' + dlbasename
 
 
 # Returns arguments for invoking libtool, if applicable, otherwise None
diff --git a/tests/scanner/test_shlibs.py b/tests/scanner/test_shlibs.py
index a8337c60..7f123103 100644
--- a/tests/scanner/test_shlibs.py
+++ b/tests/scanner/test_shlibs.py
@@ -40,7 +40,8 @@ class TestLddParser(unittest.TestCase):
 
         self.assertEqual(
             sanitize_shlib_path('/foo/bar'),
-            '/foo/bar' if sys.platform == 'darwin' else 'bar')
+            # Always use an absolute filename for Guix
+            '/foo/bar')
 
     def test_unresolved_library(self):
         output = ''
-- 
2.33.0


debug log:

solving 3c03dba218 ...
found 3c03dba218 in https://git.savannah.gnu.org/cgit/guix.git

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).