Skip to content

fix: Improve python lib detection #1093

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions src/scikit_build_core/builder/sysconfig.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import configparser
import itertools
import os
import sys
import sysconfig
Expand Down Expand Up @@ -44,6 +45,88 @@ def __dir__() -> list[str]:
return __all__


# Adapted from scikit-build by removing few checks that have already been earlier
# https://github.com/scikit-build/scikit-build/blob/master/skbuild/cmaker.py#L514
def _try_to_find_python_library(*, abi3: bool = False) -> Path | None:
candidate_lib_prefixes = ["", "lib"]
candidate_suffixes = [""]
candidate_implementations = ["python"]
if hasattr(sys, "pypy_version_info"):
candidate_implementations = ["pypy-c", "pypy3-c", "pypy"]
candidate_suffixes.append("-c")

candidate_extensions = [".lib", ".so", ".a"]
# On pypy + MacOS, the variable WITH_DYLD is not set. It would
# actually be possible to determine the python library there using
# LDLIBRARY + LIBDIR. As a simple fix, we check if the LDLIBRARY
# ends with .dylib and add it to the candidate matrix in this case.
with_ld = sysconfig.get_config_var("WITH_DYLD")
ld_lib = sysconfig.get_config_var("LDLIBRARY")
if with_ld or (ld_lib and ld_lib.endswith(".dylib")):
candidate_extensions.insert(0, ".dylib")

# Check the specific version first, e.g ["312", "3", ""]
candidate_versions = [
f"{sys.version_info.major}{sys.version_info.minor}",
f"{sys.version_info.major}",
"",
]

# Don't consider minor version if abi3
if abi3:
candidate_versions.pop(0)

abiflags = getattr(sys, "abiflags", "")
candidate_abiflags = [abiflags]
if abiflags:
candidate_abiflags.append("")

candidate_libdirs = []

# Look at install base if available
install_base = sysconfig.get_config_var("installed_base")
if install_base:
candidate_libdirs.append(Path.resolve(Path(install_base) / "libs"))

# Look at libdist if available
libdest = sysconfig.get_config_var("LIBDEST")
if libdest:
candidate_libdirs.append(Path.resolve(Path(install_base) / ".." / "libs"))

# Check multiarch
candidate_multiarc_libdirs = []
multiarch: str | None = sysconfig.get_config_var("MULTIARCH")
masd: str | None = sysconfig.get_config_var("multiarchsubdir")
for libdir in candidate_libdirs:
if multiarch and masd:
if masd.startswith(os.sep):
masd = masd[len(os.sep) :]
libdir_masd = libdir / masd
candidate_multiarc_libdirs.append(libdir_masd)

candidates = (
libdir / f"{pre}{impl}{ver}{abi}{suf}{ext}"
for (libdir, pre, impl, ext, ver, abi, suf) in itertools.product(
candidate_libdirs + candidate_multiarc_libdirs,
candidate_lib_prefixes,
candidate_implementations,
candidate_extensions,
candidate_versions,
candidate_abiflags,
candidate_suffixes,
)
)

python_library = None

for candidate in candidates:
if Path.exists(candidate):
python_library = candidate
break

return python_library


def get_python_library(env: Mapping[str, str], *, abi3: bool = False) -> Path | None:
# When cross-compiling, check DIST_EXTRA_CONFIG first
config_file = env.get("DIST_EXTRA_CONFIG", None)
Expand Down Expand Up @@ -108,6 +191,10 @@ def get_python_library(env: Mapping[str, str], *, abi3: bool = False) -> Path |
if libpath.is_file():
return libpath

lib_path: Path | None = _try_to_find_python_library(abi3=abi3)
if lib_path:
return lib_path

log_func(
"Can't find a Python library, got libdir={}, ldlibrary={}, multiarch={}, masd={}",
libdir,
Expand Down
Loading