|
1 | 1 | from __future__ import annotations
|
2 | 2 |
|
3 | 3 | import configparser
|
| 4 | +import itertools |
4 | 5 | import os
|
5 | 6 | import sys
|
6 | 7 | import sysconfig
|
@@ -44,6 +45,84 @@ def __dir__() -> list[str]:
|
44 | 45 | return __all__
|
45 | 46 |
|
46 | 47 |
|
| 48 | +# Adapted from scikit-build by removing few checks that have already been earlier |
| 49 | +# https://github.com/scikit-build/scikit-build/blob/master/skbuild/cmaker.py#L514 |
| 50 | +def _try_to_find_python_library() -> Path | None: |
| 51 | + candidate_lib_prefixes = ["", "lib"] |
| 52 | + candidate_suffixes = [""] |
| 53 | + candidate_implementations = ["python"] |
| 54 | + if hasattr(sys, "pypy_version_info"): |
| 55 | + candidate_implementations = ["pypy-c", "pypy3-c", "pypy"] |
| 56 | + candidate_suffixes.append("-c") |
| 57 | + |
| 58 | + candidate_extensions = [".lib", ".so", ".a"] |
| 59 | + # On pypy + MacOS, the variable WITH_DYLD is not set. It would |
| 60 | + # actually be possible to determine the python library there using |
| 61 | + # LDLIBRARY + LIBDIR. As a simple fix, we check if the LDLIBRARY |
| 62 | + # ends with .dylib and add it to the candidate matrix in this case. |
| 63 | + with_ld = sysconfig.get_config_var("WITH_DYLD") |
| 64 | + ld_lib = sysconfig.get_config_var("LDLIBRARY") |
| 65 | + if with_ld or (ld_lib and ld_lib.endswith(".dylib")): |
| 66 | + candidate_extensions.insert(0, ".dylib") |
| 67 | + |
| 68 | + # Check the specific version first, e.g ["312", "3", ""] |
| 69 | + candidate_versions = [ |
| 70 | + f"{sys.version_info.major}{sys.version_info.minor}", |
| 71 | + f"{sys.version_info.major}", |
| 72 | + "", |
| 73 | + ] |
| 74 | + |
| 75 | + abiflags = getattr(sys, "abiflags", "") |
| 76 | + candidate_abiflags = [abiflags] |
| 77 | + if abiflags: |
| 78 | + candidate_abiflags.append("") |
| 79 | + |
| 80 | + candidate_libdirs = [] |
| 81 | + |
| 82 | + # Look at install base if available |
| 83 | + install_base = sysconfig.get_config_var("installed_base") |
| 84 | + if install_base: |
| 85 | + candidate_libdirs.append(Path.resolve(Path(install_base) / "libs")) |
| 86 | + |
| 87 | + # Look at libdist if available |
| 88 | + libdest = sysconfig.get_config_var("LIBDEST") |
| 89 | + if libdest: |
| 90 | + candidate_libdirs.append(Path.resolve(Path(install_base) / ".." / "libs")) |
| 91 | + |
| 92 | + # Check multiarch |
| 93 | + candidate_multiarc_libdirs = [] |
| 94 | + multiarch: str | None = sysconfig.get_config_var("MULTIARCH") |
| 95 | + masd: str | None = sysconfig.get_config_var("multiarchsubdir") |
| 96 | + for libdir in candidate_libdirs: |
| 97 | + if multiarch and masd: |
| 98 | + if masd.startswith(os.sep): |
| 99 | + masd = masd[len(os.sep) :] |
| 100 | + libdir_masd = libdir / masd |
| 101 | + candidate_multiarc_libdirs.append(libdir_masd) |
| 102 | + |
| 103 | + candidates = ( |
| 104 | + libdir / f"{pre}{impl}{ver}{abi}{suf}{ext}" |
| 105 | + for (libdir, pre, impl, ext, ver, abi, suf) in itertools.product( |
| 106 | + candidate_libdirs + candidate_multiarc_libdirs, |
| 107 | + candidate_lib_prefixes, |
| 108 | + candidate_implementations, |
| 109 | + candidate_extensions, |
| 110 | + candidate_versions, |
| 111 | + candidate_abiflags, |
| 112 | + candidate_suffixes, |
| 113 | + ) |
| 114 | + ) |
| 115 | + |
| 116 | + python_library = None |
| 117 | + |
| 118 | + for candidate in candidates: |
| 119 | + if Path.exists(candidate): |
| 120 | + python_library = candidate |
| 121 | + break |
| 122 | + |
| 123 | + return python_library |
| 124 | + |
| 125 | + |
47 | 126 | def get_python_library(env: Mapping[str, str], *, abi3: bool = False) -> Path | None:
|
48 | 127 | # When cross-compiling, check DIST_EXTRA_CONFIG first
|
49 | 128 | config_file = env.get("DIST_EXTRA_CONFIG", None)
|
@@ -108,6 +187,10 @@ def get_python_library(env: Mapping[str, str], *, abi3: bool = False) -> Path |
|
108 | 187 | if libpath.is_file():
|
109 | 188 | return libpath
|
110 | 189 |
|
| 190 | + lib_path: Path | None = _try_to_find_python_library() |
| 191 | + if lib_path: |
| 192 | + return lib_path |
| 193 | + |
111 | 194 | log_func(
|
112 | 195 | "Can't find a Python library, got libdir={}, ldlibrary={}, multiarch={}, masd={}",
|
113 | 196 | libdir,
|
|
0 commit comments