about summary refs log tree commit diff
path: root/nixpkgs/pkgs/development/interpreters/python/cpython/2.7/find_library-gcc10.patch
blob: 4627baf119c17f51b02f108b4d5f463d08e0b45f (plain) (blame)
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
Backport https://github.com/python/cpython/commit/82df3b3071bb003247c33eac4670775e9883c994
and https://github.com/python/cpython/commit/27ac19cca2c639caaf6fedf3632fe6beb265f24f

Fixes the check phase of python2Packages.cffi.

--- a/Lib/ctypes/util.py
+++ b/Lib/ctypes/util.py
@@ -87,6 +87,12 @@ elif os.name == "posix":
     # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump
     import re, tempfile, errno
 
+    def _is_elf(filename):
+        "Return True if the given file is an ELF file"
+        elf_header = b'\x7fELF'
+        with open(filename, 'rb') as thefile:
+            return thefile.read(4) == elf_header
+
     def _findLib_gcc(name):
         # Run GCC's linker with the -t (aka --trace) option and examine the
         # library name it prints out. The GCC command will fail because we
@@ -110,10 +116,17 @@ elif os.name == "posix":
                 # the normal behaviour of GCC if linking fails
                 if e.errno != errno.ENOENT:
                     raise
-        res = re.search(expr, trace)
+        res = re.findall(expr, trace)
         if not res:
             return None
-        return res.group(0)
+
+        for file in res:
+            # Check if the given file is an elf file: gcc can report
+            # some files that are linker scripts and not actual
+            # shared objects. See bpo-41976 for more details
+            if not _is_elf(file):
+                continue
+            return file
 
 
     if sys.platform == "sunos5":
@@ -237,8 +250,37 @@ elif os.name == "posix":
         def _findSoname_ldconfig(name):
             return None
 
+        def _findLib_ld(name):
+            # See issue #9998 for why this is needed
+            expr = r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)
+            cmd = ['ld', '-t']
+            libpath = os.environ.get('LD_LIBRARY_PATH')
+            if libpath:
+                for d in libpath.split(':'):
+                    cmd.extend(['-L', d])
+            cmd.extend(['-o', os.devnull, '-l%s' % name])
+            result = None
+            try:
+                p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+                                     stderr=subprocess.PIPE,
+                                     universal_newlines=True)
+                out, _ = p.communicate()
+                res = re.findall(expr, out)
+                for file in res:
+                    # Check if the given file is an elf file: gcc can report
+                    # some files that are linker scripts and not actual
+                    # shared objects. See bpo-41976 for more details
+                    if not _is_elf(file):
+                        continue
+                    return file
+            except Exception:
+                pass  # result will be None
+            return result
+
         def find_library(name):
-            return _findSoname_ldconfig(name) or _get_soname(_findLib_gcc(name))
+            # See issue #9998
+            return _findSoname_ldconfig(name) or \
+                   _get_soname(_findLib_gcc(name)) or _get_soname(_findLib_ld(name))
 
 ################################################################
 # test code