b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | https://bugs.python.org/issue21622 |
| 2 | |
| 3 | Based on the patch from Alpine Linux |
| 4 | https://git.alpinelinux.org/aports/tree/main/python2/musl-find_library.patch |
| 5 | |
| 6 | --- a/Lib/ctypes/util.py |
| 7 | +++ b/Lib/ctypes/util.py |
| 8 | @@ -92,6 +92,8 @@ elif sys.platform.startswith("aix"): |
| 9 | elif os.name == "posix": |
| 10 | # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump |
| 11 | import re, tempfile |
| 12 | + from glob import glob |
| 13 | + musl_ldso = glob('/lib/ld-musl-*.so.1') |
| 14 | |
| 15 | def _is_elf(filename): |
| 16 | "Return True if the given file is an ELF file" |
| 17 | @@ -265,6 +267,57 @@ elif os.name == "posix": |
| 18 | def find_library(name, is64 = False): |
| 19 | return _get_soname(_findLib_crle(name, is64) or _findLib_gcc(name)) |
| 20 | |
| 21 | + elif musl_ldso and os.path.isfile(musl_ldso[0]): |
| 22 | + |
| 23 | + def _is_elf(filepath): |
| 24 | + try: |
| 25 | + with open(filepath, 'rb') as fh: |
| 26 | + return fh.read(4) == b'\x7fELF' |
| 27 | + except: |
| 28 | + return False |
| 29 | + |
| 30 | + def find_library(name): |
| 31 | + # absolute name? |
| 32 | + if os.path.isabs(name): |
| 33 | + if _is_elf(name): |
| 34 | + return name |
| 35 | + else: |
| 36 | + return None |
| 37 | + |
| 38 | + # special case for unified standard libs |
| 39 | + stdlibs = ['libcrypt.so', 'libdl.so', 'libm.so', 'libpthread.so', 'libresolv.so', 'librt.so', 'libutil.so', 'libxnet.so'] |
| 40 | + if name in stdlibs: |
| 41 | + name = 'libc.so' |
| 42 | + elif ('lib' + name + '.so') in stdlibs: |
| 43 | + name = 'c' |
| 44 | + |
| 45 | + paths = [] |
| 46 | + # read path list from /etc/ld-musl-$(ARCH).path |
| 47 | + path_list = musl_ldso[0].replace('/lib/', '/etc/').replace('.so.1', '.path') |
| 48 | + try: |
| 49 | + with open(path_list, 'r') as fh: |
| 50 | + paths = [path for line in fh for path in line.rstrip('\n').split(':') if path] |
| 51 | + except: |
| 52 | + paths = [] |
| 53 | + # default path list if /etc/ld-musl-$(ARCH).path is empty or does not exist |
| 54 | + if not paths: |
| 55 | + paths = ['/lib', '/usr/local/lib', '/usr/lib'] |
| 56 | + |
| 57 | + # prepend paths from LD_LIBRARY_PATH |
| 58 | + if 'LD_LIBRARY_PATH' in os.environ: |
| 59 | + paths = os.environ['LD_LIBRARY_PATH'].split(':') + paths |
| 60 | + |
| 61 | + for d in paths: |
| 62 | + f = os.path.join(d, name) |
| 63 | + if _is_elf(f): |
| 64 | + return os.path.basename(f) |
| 65 | + |
| 66 | + prefix = os.path.join(d, 'lib'+name) |
| 67 | + for suffix in ['.so', '.so.*']: |
| 68 | + for f in glob('{0}{1}'.format(prefix, suffix)): |
| 69 | + if _is_elf(f): |
| 70 | + return os.path.basename(f) |
| 71 | + |
| 72 | else: |
| 73 | |
| 74 | def _findSoname_ldconfig(name): |