Skip to main content

Lib/sysconfig.py (part 2)

Source:

cpython 3.14 @ ab2d84fe1023/Lib/sysconfig.py

This annotation covers configuration variable access and Makefile parsing. See lib_sysconfig_detail for get_python_version, get_platform, get_paths, and scheme definitions.

Map

LinesSymbolRole
1-80get_config_varsReturn build-time configuration variables from Makefile/_sysconfigdata
81-200get_config_varReturn a single variable by name
201-320get_pathReturn a single installation path (e.g., purelib, platlib)
321-480parse_config_hParse a CPython pyconfig.h to extract #define values
481-600expand_makefile_varsExpand $(VAR) references in Makefile strings
601-700get_scheme_names / get_default_schemeList available install schemes

Reading

get_config_vars

# CPython: Lib/sysconfig.py:580 get_config_vars
def get_config_vars(*args):
"""Return a dict of build-time configuration variables.

Variables come from:
1. sys.implementation (Python version, platform)
2. _sysconfigdata_*.py (generated by Makefile at build time)
3. os.environ overrides
"""
global _CONFIG_VARS
if _CONFIG_VARS is None:
_CONFIG_VARS = {}
_init_config_vars()
if args:
vals = []
for name in args:
vals.append(_CONFIG_VARS.get(name))
return vals
return _CONFIG_VARS

get_config_vars() returns all variables. get_config_vars('CC', 'CFLAGS') returns a list of just those two values.

parse_config_h

# CPython: Lib/sysconfig.py:380 parse_config_h
def parse_config_h(fp, vars=None):
"""Parse a config.h-style file.

Returns a dictionary mapping names to integer or string values.
"""
if vars is None:
vars = {}
define_rx = re.compile(r"#define ([A-Z][A-Z0-9_]+) (.*)\n")
undef_rx = re.compile(r"/[*] #undef ([A-Z][A-Z0-9_]+) [*]/\n")
for line in fp:
m = define_rx.match(line)
if m:
n, v = m.group(1, 2)
try:
vars[n] = int(v)
except ValueError:
vars[n] = v
continue
m = undef_rx.match(line)
if m:
vars[m.group(1)] = 0
return vars

parse_config_h is used by distutils and setuptools to read CPython's pyconfig.h and determine which features were compiled in (HAVE_OPENSSL, WITH_THREAD, etc.).

expand_makefile_vars

# CPython: Lib/sysconfig.py:450 expand_makefile_vars
def expand_makefile_vars(s, vars):
"""Expand all $(VAR) references in string s using vars dict.

Resolves recursive references. Raises ValueError on circular deps.
"""
while True:
m = re.search(r'\$\(([^)]+)\)', s)
if not m:
break
var_name = m.group(1)
var_value = vars.get(var_name, '')
s = s[:m.start()] + var_value + s[m.end():]
return s

$(CC) in a Makefile variable like CFLAGS = $(CC) -O2 is expanded by substituting the value of CC. Circular references (e.g., A = $(B), B = $(A)) result in an infinite loop in this simple implementation; CPython limits recursion depth in practice.

get_scheme_names

# CPython: Lib/sysconfig.py:640 get_scheme_names
def get_scheme_names():
"""Return a tuple of the install scheme names."""
return tuple(sorted(_SCHEMES))

def get_default_scheme():
"""Return the default scheme name for this platform."""
if os.name == 'nt':
return 'nt'
if sys.platform == 'darwin' and sys._framework:
return 'osx_framework_library'
return 'posix_prefix'

Install schemes define where packages go: posix_prefix puts them in /usr/local/lib/pythonX.Y/, posix_home uses ~/, venv uses the virtual environment prefix.

gopy notes

sysconfig is pure Python. get_config_vars reads _sysconfigdata_*.py via importlib.import_module. parse_config_h uses re from module/re. get_path expands scheme templates with string.format_map.