up
This commit is contained in:
@@ -9,30 +9,15 @@ Written by: Fred L. Drake, Jr.
|
||||
Email: <fdrake@acm.org>
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import functools
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
import sys
|
||||
import sysconfig
|
||||
from typing import TYPE_CHECKING, Literal, overload
|
||||
import pathlib
|
||||
|
||||
from jaraco.functools import pass_none
|
||||
|
||||
from .ccompiler import CCompiler
|
||||
from .compat import py39
|
||||
from .errors import DistutilsPlatformError
|
||||
from .util import is_mingw
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing_extensions import deprecated
|
||||
else:
|
||||
|
||||
def deprecated(message):
|
||||
return lambda fn: fn
|
||||
|
||||
from . import py39compat
|
||||
from ._functools import pass_none
|
||||
|
||||
IS_PYPY = '__pypy__' in sys.builtin_module_names
|
||||
|
||||
@@ -119,10 +104,10 @@ def get_python_version():
|
||||
leaving off the patchlevel. Sample return values could be '1.5'
|
||||
or '2.2'.
|
||||
"""
|
||||
return f'{sys.version_info.major}.{sys.version_info.minor}'
|
||||
return '%d.%d' % sys.version_info[:2]
|
||||
|
||||
|
||||
def get_python_inc(plat_specific: bool = False, prefix: str | None = None) -> str:
|
||||
def get_python_inc(plat_specific=0, prefix=None):
|
||||
"""Return the directory containing installed Python header files.
|
||||
|
||||
If 'plat_specific' is false (the default), this is the path to the
|
||||
@@ -135,30 +120,22 @@ def get_python_inc(plat_specific: bool = False, prefix: str | None = None) -> st
|
||||
"""
|
||||
default_prefix = BASE_EXEC_PREFIX if plat_specific else BASE_PREFIX
|
||||
resolved_prefix = prefix if prefix is not None else default_prefix
|
||||
# MinGW imitates posix like layout, but os.name != posix
|
||||
os_name = "posix" if is_mingw() else os.name
|
||||
try:
|
||||
getter = globals()[f'_get_python_inc_{os_name}']
|
||||
getter = globals()[f'_get_python_inc_{os.name}']
|
||||
except KeyError:
|
||||
raise DistutilsPlatformError(
|
||||
"I don't know where Python installs its C header files "
|
||||
f"on platform '{os.name}'"
|
||||
"on platform '%s'" % os.name
|
||||
)
|
||||
return getter(resolved_prefix, prefix, plat_specific)
|
||||
|
||||
|
||||
@pass_none
|
||||
def _extant(path):
|
||||
"""
|
||||
Replace path with None if it doesn't exist.
|
||||
"""
|
||||
return path if os.path.exists(path) else None
|
||||
|
||||
|
||||
def _get_python_inc_posix(prefix, spec_prefix, plat_specific):
|
||||
if IS_PYPY and sys.version_info < (3, 8):
|
||||
return os.path.join(prefix, 'include')
|
||||
return (
|
||||
_get_python_inc_posix_python(plat_specific)
|
||||
or _extant(_get_python_inc_from_config(plat_specific, spec_prefix))
|
||||
or _get_python_inc_from_config(plat_specific, spec_prefix)
|
||||
or _get_python_inc_posix_prefix(prefix)
|
||||
)
|
||||
|
||||
@@ -210,11 +187,12 @@ def _get_python_inc_posix_prefix(prefix):
|
||||
|
||||
def _get_python_inc_nt(prefix, spec_prefix, plat_specific):
|
||||
if python_build:
|
||||
# Include both include dirs to ensure we can find pyconfig.h
|
||||
# Include both the include and PC dir to ensure we can find
|
||||
# pyconfig.h
|
||||
return (
|
||||
os.path.join(prefix, "include")
|
||||
+ os.path.pathsep
|
||||
+ os.path.dirname(sysconfig.get_config_h_filename())
|
||||
+ os.path.join(prefix, "PC")
|
||||
)
|
||||
return os.path.join(prefix, "include")
|
||||
|
||||
@@ -227,9 +205,7 @@ def _posix_lib(standard_lib, libpython, early_prefix, prefix):
|
||||
return os.path.join(libpython, "site-packages")
|
||||
|
||||
|
||||
def get_python_lib(
|
||||
plat_specific: bool = False, standard_lib: bool = False, prefix: str | None = None
|
||||
) -> str:
|
||||
def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
|
||||
"""Return the directory containing the Python library (standard or
|
||||
site additions).
|
||||
|
||||
@@ -244,6 +220,14 @@ def get_python_lib(
|
||||
sys.base_exec_prefix -- i.e., ignore 'plat_specific'.
|
||||
"""
|
||||
|
||||
if IS_PYPY and sys.version_info < (3, 8):
|
||||
# PyPy-specific schema
|
||||
if prefix is None:
|
||||
prefix = PREFIX
|
||||
if standard_lib:
|
||||
return os.path.join(prefix, "lib-python", sys.version[0])
|
||||
return os.path.join(prefix, 'site-packages')
|
||||
|
||||
early_prefix = prefix
|
||||
|
||||
if prefix is None:
|
||||
@@ -252,7 +236,7 @@ def get_python_lib(
|
||||
else:
|
||||
prefix = plat_specific and EXEC_PREFIX or PREFIX
|
||||
|
||||
if os.name == "posix" or is_mingw():
|
||||
if os.name == "posix":
|
||||
if plat_specific or standard_lib:
|
||||
# Platform-specific modules (any module from a non-pure-Python
|
||||
# module distribution) or standard Python library modules.
|
||||
@@ -270,38 +254,34 @@ def get_python_lib(
|
||||
return os.path.join(prefix, "Lib", "site-packages")
|
||||
else:
|
||||
raise DistutilsPlatformError(
|
||||
f"I don't know where Python installs its library on platform '{os.name}'"
|
||||
"I don't know where Python installs its library "
|
||||
"on platform '%s'" % os.name
|
||||
)
|
||||
|
||||
|
||||
@functools.lru_cache
|
||||
def _customize_macos():
|
||||
"""
|
||||
Perform first-time customization of compiler-related
|
||||
config vars on macOS. Use after a compiler is known
|
||||
to be needed. This customization exists primarily to support Pythons
|
||||
from binary installers. The kind and paths to build tools on
|
||||
the user system may vary significantly from the system
|
||||
that Python itself was built on. Also the user OS
|
||||
version and build tools may not support the same set
|
||||
of CPU architectures for universal builds.
|
||||
"""
|
||||
|
||||
sys.platform == "darwin" and __import__('_osx_support').customize_compiler(
|
||||
get_config_vars()
|
||||
)
|
||||
|
||||
|
||||
def customize_compiler(compiler: CCompiler) -> None:
|
||||
def customize_compiler(compiler): # noqa: C901
|
||||
"""Do any platform-specific customization of a CCompiler instance.
|
||||
|
||||
Mainly needed on Unix, so we can plug in the information that
|
||||
varies across Unices and is stored in Python's Makefile.
|
||||
"""
|
||||
if compiler.compiler_type in ["unix", "cygwin"] or (
|
||||
compiler.compiler_type == "mingw32" and is_mingw()
|
||||
):
|
||||
_customize_macos()
|
||||
if compiler.compiler_type == "unix":
|
||||
if sys.platform == "darwin":
|
||||
# Perform first-time customization of compiler-related
|
||||
# config vars on OS X now that we know we need a compiler.
|
||||
# This is primarily to support Pythons from binary
|
||||
# installers. The kind and paths to build tools on
|
||||
# the user system may vary significantly from the system
|
||||
# that Python itself was built on. Also the user OS
|
||||
# version and build tools may not support the same set
|
||||
# of CPU architectures for universal builds.
|
||||
global _config_vars
|
||||
# Use get_config_var() to ensure _config_vars is initialized.
|
||||
if not get_config_var('CUSTOMIZED_OSX_COMPILER'):
|
||||
import _osx_support
|
||||
|
||||
_osx_support.customize_compiler(_config_vars)
|
||||
_config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True'
|
||||
|
||||
(
|
||||
cc,
|
||||
@@ -309,7 +289,6 @@ def customize_compiler(compiler: CCompiler) -> None:
|
||||
cflags,
|
||||
ccshared,
|
||||
ldshared,
|
||||
ldcxxshared,
|
||||
shlib_suffix,
|
||||
ar,
|
||||
ar_flags,
|
||||
@@ -319,14 +298,11 @@ def customize_compiler(compiler: CCompiler) -> None:
|
||||
'CFLAGS',
|
||||
'CCSHARED',
|
||||
'LDSHARED',
|
||||
'LDCXXSHARED',
|
||||
'SHLIB_SUFFIX',
|
||||
'AR',
|
||||
'ARFLAGS',
|
||||
)
|
||||
|
||||
cxxflags = cflags
|
||||
|
||||
if 'CC' in os.environ:
|
||||
newcc = os.environ['CC']
|
||||
if 'LDSHARED' not in os.environ and ldshared.startswith(cc):
|
||||
@@ -334,42 +310,38 @@ def customize_compiler(compiler: CCompiler) -> None:
|
||||
# command for LDSHARED as well
|
||||
ldshared = newcc + ldshared[len(cc) :]
|
||||
cc = newcc
|
||||
cxx = os.environ.get('CXX', cxx)
|
||||
ldshared = os.environ.get('LDSHARED', ldshared)
|
||||
ldcxxshared = os.environ.get('LDCXXSHARED', ldcxxshared)
|
||||
cpp = os.environ.get(
|
||||
'CPP',
|
||||
cc + " -E", # not always
|
||||
)
|
||||
if 'CXX' in os.environ:
|
||||
cxx = os.environ['CXX']
|
||||
if 'LDSHARED' in os.environ:
|
||||
ldshared = os.environ['LDSHARED']
|
||||
if 'CPP' in os.environ:
|
||||
cpp = os.environ['CPP']
|
||||
else:
|
||||
cpp = cc + " -E" # not always
|
||||
if 'LDFLAGS' in os.environ:
|
||||
ldshared = ldshared + ' ' + os.environ['LDFLAGS']
|
||||
if 'CFLAGS' in os.environ:
|
||||
cflags = cflags + ' ' + os.environ['CFLAGS']
|
||||
ldshared = ldshared + ' ' + os.environ['CFLAGS']
|
||||
if 'CPPFLAGS' in os.environ:
|
||||
cpp = cpp + ' ' + os.environ['CPPFLAGS']
|
||||
cflags = cflags + ' ' + os.environ['CPPFLAGS']
|
||||
ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
|
||||
if 'AR' in os.environ:
|
||||
ar = os.environ['AR']
|
||||
if 'ARFLAGS' in os.environ:
|
||||
archiver = ar + ' ' + os.environ['ARFLAGS']
|
||||
else:
|
||||
archiver = ar + ' ' + ar_flags
|
||||
|
||||
ldshared = _add_flags(ldshared, 'LD')
|
||||
ldcxxshared = _add_flags(ldcxxshared, 'LD')
|
||||
cflags = os.environ.get('CFLAGS', cflags)
|
||||
ldshared = _add_flags(ldshared, 'C')
|
||||
cxxflags = os.environ.get('CXXFLAGS', cxxflags)
|
||||
ldcxxshared = _add_flags(ldcxxshared, 'CXX')
|
||||
cpp = _add_flags(cpp, 'CPP')
|
||||
cflags = _add_flags(cflags, 'CPP')
|
||||
cxxflags = _add_flags(cxxflags, 'CPP')
|
||||
ldshared = _add_flags(ldshared, 'CPP')
|
||||
ldcxxshared = _add_flags(ldcxxshared, 'CPP')
|
||||
|
||||
ar = os.environ.get('AR', ar)
|
||||
|
||||
archiver = ar + ' ' + os.environ.get('ARFLAGS', ar_flags)
|
||||
cc_cmd = cc + ' ' + cflags
|
||||
cxx_cmd = cxx + ' ' + cxxflags
|
||||
|
||||
compiler.set_executables(
|
||||
preprocessor=cpp,
|
||||
compiler=cc_cmd,
|
||||
compiler_so=cc_cmd + ' ' + ccshared,
|
||||
compiler_cxx=cxx_cmd,
|
||||
compiler_so_cxx=cxx_cmd + ' ' + ccshared,
|
||||
compiler_cxx=cxx,
|
||||
linker_so=ldshared,
|
||||
linker_so_cxx=ldcxxshared,
|
||||
linker_exe=cc,
|
||||
linker_exe_cxx=cxx,
|
||||
archiver=archiver,
|
||||
)
|
||||
|
||||
@@ -379,12 +351,19 @@ def customize_compiler(compiler: CCompiler) -> None:
|
||||
compiler.shared_lib_extension = shlib_suffix
|
||||
|
||||
|
||||
def get_config_h_filename() -> str:
|
||||
def get_config_h_filename():
|
||||
"""Return full pathname of installed pyconfig.h file."""
|
||||
return sysconfig.get_config_h_filename()
|
||||
if python_build:
|
||||
if os.name == "nt":
|
||||
inc_dir = os.path.join(_sys_home or project_base, "PC")
|
||||
else:
|
||||
inc_dir = _sys_home or project_base
|
||||
return os.path.join(inc_dir, 'pyconfig.h')
|
||||
else:
|
||||
return sysconfig.get_config_h_filename()
|
||||
|
||||
|
||||
def get_makefile_filename() -> str:
|
||||
def get_makefile_filename():
|
||||
"""Return full pathname of installed Makefile from the Python build."""
|
||||
return sysconfig.get_makefile_filename()
|
||||
|
||||
@@ -416,11 +395,7 @@ def parse_makefile(fn, g=None): # noqa: C901
|
||||
from distutils.text_file import TextFile
|
||||
|
||||
fp = TextFile(
|
||||
fn,
|
||||
strip_comments=True,
|
||||
skip_blanks=True,
|
||||
join_lines=True,
|
||||
errors="surrogateescape",
|
||||
fn, strip_comments=1, skip_blanks=1, join_lines=1, errors="surrogateescape"
|
||||
)
|
||||
|
||||
if g is None:
|
||||
@@ -499,6 +474,7 @@ def parse_makefile(fn, g=None): # noqa: C901
|
||||
del notdone[name]
|
||||
|
||||
if name.startswith('PY_') and name[3:] in renamed_variables:
|
||||
|
||||
name = name[3:]
|
||||
if name not in done:
|
||||
done[name] = value
|
||||
@@ -546,11 +522,7 @@ def expand_makefile_vars(s, vars):
|
||||
_config_vars = None
|
||||
|
||||
|
||||
@overload
|
||||
def get_config_vars() -> dict[str, str | int]: ...
|
||||
@overload
|
||||
def get_config_vars(arg: str, /, *args: str) -> list[str | int]: ...
|
||||
def get_config_vars(*args: str) -> list[str | int] | dict[str, str | int]:
|
||||
def get_config_vars(*args):
|
||||
"""With no arguments, return a dictionary of all configuration
|
||||
variables relevant for the current platform. Generally this includes
|
||||
everything needed to build extensions and install both pure modules and
|
||||
@@ -563,19 +535,18 @@ def get_config_vars(*args: str) -> list[str | int] | dict[str, str | int]:
|
||||
global _config_vars
|
||||
if _config_vars is None:
|
||||
_config_vars = sysconfig.get_config_vars().copy()
|
||||
py39.add_ext_suffix(_config_vars)
|
||||
py39compat.add_ext_suffix(_config_vars)
|
||||
|
||||
return [_config_vars.get(name) for name in args] if args else _config_vars
|
||||
if args:
|
||||
vals = []
|
||||
for name in args:
|
||||
vals.append(_config_vars.get(name))
|
||||
return vals
|
||||
else:
|
||||
return _config_vars
|
||||
|
||||
|
||||
@overload
|
||||
@deprecated(
|
||||
"SO is deprecated, use EXT_SUFFIX. Support will be removed when this module is synchronized with stdlib Python 3.11"
|
||||
)
|
||||
def get_config_var(name: Literal["SO"]) -> int | str | None: ...
|
||||
@overload
|
||||
def get_config_var(name: str) -> int | str | None: ...
|
||||
def get_config_var(name: str) -> int | str | None:
|
||||
def get_config_var(name):
|
||||
"""Return the value of a single variable using the dictionary
|
||||
returned by 'get_config_vars()'. Equivalent to
|
||||
get_config_vars().get(name)
|
||||
@@ -585,14 +556,3 @@ def get_config_var(name: str) -> int | str | None:
|
||||
|
||||
warnings.warn('SO is deprecated, use EXT_SUFFIX', DeprecationWarning, 2)
|
||||
return get_config_vars().get(name)
|
||||
|
||||
|
||||
@pass_none
|
||||
def _add_flags(value: str, type: str) -> str:
|
||||
"""
|
||||
Add any flags from the environment for the given type.
|
||||
|
||||
type is the prefix to FLAGS in the environment key (e.g. "C" for "CFLAGS").
|
||||
"""
|
||||
flags = os.environ.get(f'{type}FLAGS')
|
||||
return f'{value} {flags}' if flags else value
|
||||
|
||||
Reference in New Issue
Block a user