-
Notifications
You must be signed in to change notification settings - Fork 51
/
sysconfig.py
171 lines (137 loc) · 5.14 KB
/
sysconfig.py
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
from __future__ import annotations
import configparser
import os
import sys
import sysconfig
from pathlib import Path
from typing import TYPE_CHECKING
from .._logging import logger
if TYPE_CHECKING:
from collections.abc import Mapping
__all__ = [
"get_python_include_dir",
"get_python_library",
"get_cmake_platform",
"get_soabi",
"get_numpy_include_dir",
]
TARGET_TO_PLAT = {
"x86": "win32",
"x64": "win-amd64",
"arm": "win-arm32",
"arm64": "win-arm64",
}
PLAT_TO_CMAKE = {
"win32": "Win32",
"win-amd64": "x64",
"win-arm32": "ARM",
"win-arm64": "ARM64",
}
def __dir__() -> list[str]:
return __all__
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)
if config_file and Path(config_file).is_file():
cp = configparser.ConfigParser()
cp.read(config_file)
result = cp.get("build_ext", "library_dirs", fallback="")
if result:
logger.info("Reading DIST_EXTRA_CONFIG:build_ext.library_dirs={}", result)
minor = "" if abi3 else sys.version_info[1]
return Path(result) / f"python3{minor}.lib"
libdirstr = sysconfig.get_config_var("LIBDIR")
ldlibrarystr = sysconfig.get_config_var("LDLIBRARY")
libdir: Path | None = libdirstr and Path(libdirstr)
ldlibrary: Path | None = ldlibrarystr and Path(ldlibrarystr)
multiarch: str | None = sysconfig.get_config_var("MULTIARCH")
masd: str | None = sysconfig.get_config_var("multiarchsubdir")
if libdir and ldlibrary:
try:
libdir_is_dir = libdir.is_dir()
except PermissionError:
return None
if libdir_is_dir:
if multiarch and masd:
if masd.startswith(os.sep):
masd = masd[len(os.sep) :]
libdir_masd = libdir / masd
if libdir_masd.is_dir():
libdir = libdir_masd
libpath = libdir / ldlibrary
if Path(os.path.expandvars(libpath)).is_file():
return libpath
logger.warning("libdir/ldlibrary: {} is not a real file!", libpath)
else:
logger.warning("libdir: {} is not a directory", libdir)
framework_prefix = sysconfig.get_config_var("PYTHONFRAMEWORKPREFIX")
if framework_prefix and Path(framework_prefix).is_dir() and ldlibrary:
libpath = Path(framework_prefix) / ldlibrary
if libpath.is_file():
return libpath
logger.warning(
"Can't find a Python library, got libdir={}, ldlibrary={}, multiarch={}, masd={}",
libdir,
ldlibrary,
multiarch,
masd,
)
return None
def get_python_include_dir() -> Path:
return Path(sysconfig.get_path("include"))
def get_host_platform() -> str:
"""
Return a string that identifies the current platform. This mimics
setuptools get_host_platform (without 3.8 aix compat).
"""
if sys.version_info < (3, 8) and os.name == "nt":
if "(arm)" in sys.version.lower():
return "win-arm32"
if "(arm64)" in sys.version.lower():
return "win-arm64"
return sysconfig.get_platform()
def get_platform(env: Mapping[str, str] | None = None) -> str:
"""
Return the Python platform name for a platform, respecting VSCMD_ARG_TGT_ARCH.
"""
if env is None:
env = os.environ
if sysconfig.get_platform().startswith("win"):
if "VSCMD_ARG_TGT_ARCH" in env:
logger.debug(
"Selecting {} or {} due to VSCMD_ARG_TARGET_ARCH",
TARGET_TO_PLAT.get(env["VSCMD_ARG_TGT_ARCH"]),
get_host_platform(),
)
return TARGET_TO_PLAT.get(env["VSCMD_ARG_TGT_ARCH"]) or get_host_platform()
if "arm64" in env.get("SETUPTOOLS_EXT_SUFFIX", "").lower():
logger.debug("Windows ARM targeted via SETUPTOOLS_EXT_SUFFIX")
return "win-arm64"
return get_host_platform()
def get_cmake_platform(env: Mapping[str, str] | None) -> str:
"""
Return the CMake platform name for a platform, respecting VSCMD_ARG_TGT_ARCH.
"""
plat = get_platform(env)
return PLAT_TO_CMAKE.get(plat, plat)
def get_soabi(env: Mapping[str, str], *, abi3: bool = False) -> str:
if abi3:
return "" if sysconfig.get_platform().startswith("win") else "abi3"
# Cross-compile support
setuptools_ext_suffix = env.get("SETUPTOOLS_EXT_SUFFIX", "")
if setuptools_ext_suffix:
return setuptools_ext_suffix.rsplit(".", 1)[0].lstrip(".")
if sys.version_info < (3, 8, 7):
# See https://github.com/python/cpython/issues/84006
import distutils.sysconfig # pylint: disable=deprecated-module
ext_suffix = distutils.sysconfig.get_config_var("EXT_SUFFIX")
else:
ext_suffix = sysconfig.get_config_var("EXT_SUFFIX")
assert isinstance(ext_suffix, str)
return ext_suffix.rsplit(".", 1)[0].lstrip(".")
def get_numpy_include_dir() -> Path | None:
try:
import numpy as np
except ImportError:
return None
return Path(np.get_include())