python,python3: Fix ctypes.util.find_library()
authorJeffery To <jeffery.to@gmail.com>
Sun, 21 Jul 2019 20:42:54 +0000 (04:42 +0800)
committerJeffery To <jeffery.to@gmail.com>
Mon, 22 Jul 2019 13:38:08 +0000 (21:38 +0800)
Python's ctypes.util.find_library() function currently doesn't work for
musl libraries/systems[1].

This adds a patch to fix this function, based on a patch from Alpine
Linux[2].

Fixes #9448.

[1]: https://bugs.python.org/issue21622
[2]: https://git.alpinelinux.org/aports/tree/main/python2/musl-find_library.patch

Signed-off-by: Jeffery To <jeffery.to@gmail.com>
lang/python/python/Makefile
lang/python/python/patches/024-musl-find_library.patch [new file with mode: 0644]
lang/python/python3/Makefile
lang/python/python3/patches/024-musl-find_library.patch [new file with mode: 0644]

index fd6dac3425616644c50071779f4f48ee36c9c04b..b590e2f12adb1cb339c31ec90e005f89e97ef992 100644 (file)
@@ -12,7 +12,7 @@ include ../python-version.mk
 
 PKG_NAME:=python
 PKG_VERSION:=$(PYTHON_VERSION).$(PYTHON_VERSION_MICRO)
-PKG_RELEASE:=1
+PKG_RELEASE:=2
 
 PKG_SOURCE:=Python-$(PKG_VERSION).tar.xz
 PKG_SOURCE_URL:=https://www.python.org/ftp/python/$(PKG_VERSION)
diff --git a/lang/python/python/patches/024-musl-find_library.patch b/lang/python/python/patches/024-musl-find_library.patch
new file mode 100644 (file)
index 0000000..70b5159
--- /dev/null
@@ -0,0 +1,74 @@
+https://bugs.python.org/issue21622
+
+Based on the patch from Alpine Linux
+https://git.alpinelinux.org/aports/tree/main/python2/musl-find_library.patch
+
+--- a/Lib/ctypes/util.py
++++ b/Lib/ctypes/util.py
+@@ -86,6 +86,8 @@ if os.name == "posix" and sys.platform =
+ elif os.name == "posix":
+     # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump
+     import re, tempfile, errno
++    from glob import glob
++    musl_ldso = glob('/lib/ld-musl-*.so.1')
+     def _findLib_gcc(name):
+         # Run GCC's linker with the -t (aka --trace) option and examine the
+@@ -232,6 +234,57 @@ elif os.name == "posix":
+         def find_library(name, is64 = False):
+             return _get_soname(_findLib_crle(name, is64) or _findLib_gcc(name))
++    elif musl_ldso and os.path.isfile(musl_ldso[0]):
++
++        def _is_elf(filepath):
++            try:
++                with open(filepath, 'rb') as fh:
++                    return fh.read(4) == b'\x7fELF'
++            except:
++                return False
++
++        def find_library(name):
++            # absolute name?
++            if os.path.isabs(name):
++                if _is_elf(name):
++                    return name
++                else:
++                    return None
++
++            # special case for unified standard libs
++            stdlibs = ['libcrypt.so', 'libdl.so', 'libm.so', 'libpthread.so', 'libresolv.so', 'librt.so', 'libutil.so', 'libxnet.so']
++            if name in stdlibs:
++                name = 'libc.so'
++            elif ('lib' + name + '.so') in stdlibs:
++                name = 'c'
++
++            paths = []
++            # read path list from /etc/ld-musl-$(ARCH).path
++            path_list = musl_ldso[0].replace('/lib/', '/etc/').replace('.so.1', '.path')
++            try:
++                with open(path_list, 'r') as fh:
++                    paths = [path for line in fh for path in line.rstrip('\n').split(':') if path]
++            except:
++                paths = []
++            # default path list if /etc/ld-musl-$(ARCH).path is empty or does not exist
++            if not paths:
++                paths = ['/lib', '/usr/local/lib', '/usr/lib']
++
++            # prepend paths from LD_LIBRARY_PATH
++            if 'LD_LIBRARY_PATH' in os.environ:
++                paths = os.environ['LD_LIBRARY_PATH'].split(':') + paths
++
++            for d in paths:
++                f = os.path.join(d, name)
++                if _is_elf(f):
++                    return os.path.basename(f)
++
++                prefix = os.path.join(d, 'lib'+name)
++                for suffix in ['.so', '.so.*']:
++                    for f in glob('{0}{1}'.format(prefix, suffix)):
++                        if _is_elf(f):
++                            return os.path.basename(f)
++
+     else:
+         def _findSoname_ldconfig(name):
index be7e29e6288a1be29ef015f6fe045e2e5b95c5eb..9fbb6923e53a9d4f70c218066ef0e7b19d77745d 100644 (file)
@@ -14,7 +14,7 @@ PYTHON_VERSION:=$(PYTHON3_VERSION)
 PYTHON_VERSION_MICRO:=$(PYTHON3_VERSION_MICRO)
 
 PKG_NAME:=python3
-PKG_RELEASE:=1
+PKG_RELEASE:=2
 PKG_VERSION:=$(PYTHON_VERSION).$(PYTHON_VERSION_MICRO)
 
 PKG_SOURCE:=Python-$(PKG_VERSION).tar.xz
diff --git a/lang/python/python3/patches/024-musl-find_library.patch b/lang/python/python3/patches/024-musl-find_library.patch
new file mode 100644 (file)
index 0000000..351b918
--- /dev/null
@@ -0,0 +1,74 @@
+https://bugs.python.org/issue21622
+
+Based on the patch from Alpine Linux
+https://git.alpinelinux.org/aports/tree/main/python2/musl-find_library.patch
+
+--- a/Lib/ctypes/util.py
++++ b/Lib/ctypes/util.py
+@@ -83,6 +83,8 @@ if os.name == "posix" and sys.platform =
+ elif os.name == "posix":
+     # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump
+     import re, tempfile
++    from glob import glob
++    musl_ldso = glob('/lib/ld-musl-*.so.1')
+     def _findLib_gcc(name):
+         # Run GCC's linker with the -t (aka --trace) option and examine the
+@@ -243,6 +245,57 @@ elif os.name == "posix":
+         def find_library(name, is64 = False):
+             return _get_soname(_findLib_crle(name, is64) or _findLib_gcc(name))
++    elif musl_ldso and os.path.isfile(musl_ldso[0]):
++
++        def _is_elf(filepath):
++            try:
++                with open(filepath, 'rb') as fh:
++                    return fh.read(4) == b'\x7fELF'
++            except:
++                return False
++
++        def find_library(name):
++            # absolute name?
++            if os.path.isabs(name):
++                if _is_elf(name):
++                    return name
++                else:
++                    return None
++
++            # special case for unified standard libs
++            stdlibs = ['libcrypt.so', 'libdl.so', 'libm.so', 'libpthread.so', 'libresolv.so', 'librt.so', 'libutil.so', 'libxnet.so']
++            if name in stdlibs:
++                name = 'libc.so'
++            elif ('lib' + name + '.so') in stdlibs:
++                name = 'c'
++
++            paths = []
++            # read path list from /etc/ld-musl-$(ARCH).path
++            path_list = musl_ldso[0].replace('/lib/', '/etc/').replace('.so.1', '.path')
++            try:
++                with open(path_list, 'r') as fh:
++                    paths = [path for line in fh for path in line.rstrip('\n').split(':') if path]
++            except:
++                paths = []
++            # default path list if /etc/ld-musl-$(ARCH).path is empty or does not exist
++            if not paths:
++                paths = ['/lib', '/usr/local/lib', '/usr/lib']
++
++            # prepend paths from LD_LIBRARY_PATH
++            if 'LD_LIBRARY_PATH' in os.environ:
++                paths = os.environ['LD_LIBRARY_PATH'].split(':') + paths
++
++            for d in paths:
++                f = os.path.join(d, name)
++                if _is_elf(f):
++                    return os.path.basename(f)
++
++                prefix = os.path.join(d, 'lib'+name)
++                for suffix in ['.so', '.so.*']:
++                    for f in glob('{0}{1}'.format(prefix, suffix)):
++                        if _is_elf(f):
++                            return os.path.basename(f)
++
+     else:
+         def _findSoname_ldconfig(name):