]> crepu.dev Git - config.git/blame - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/setuptools/_distutils/sysconfig.py
ActualizaciĆ³n de Readme
[config.git] / djavu-asus / elpy / rpc-venv / lib / python3.11 / site-packages / setuptools / _distutils / sysconfig.py
CommitLineData
53e6db90
DC
1"""Provide access to Python's configuration information. The specific
2configuration variables available depend heavily on the platform and
3configuration. The values may be retrieved using
4get_config_var(name), and the list of variables is available via
5get_config_vars().keys(). Additional convenience functions are also
6available.
7
8Written by: Fred L. Drake, Jr.
9Email: <fdrake@acm.org>
10"""
11
12import os
13import re
14import sys
15import sysconfig
16import pathlib
17
18from .errors import DistutilsPlatformError
19from . import py39compat
20from ._functools import pass_none
21
22IS_PYPY = '__pypy__' in sys.builtin_module_names
23
24# These are needed in a couple of spots, so just compute them once.
25PREFIX = os.path.normpath(sys.prefix)
26EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
27BASE_PREFIX = os.path.normpath(sys.base_prefix)
28BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
29
30# Path to the base directory of the project. On Windows the binary may
31# live in project/PCbuild/win32 or project/PCbuild/amd64.
32# set for cross builds
33if "_PYTHON_PROJECT_BASE" in os.environ:
34 project_base = os.path.abspath(os.environ["_PYTHON_PROJECT_BASE"])
35else:
36 if sys.executable:
37 project_base = os.path.dirname(os.path.abspath(sys.executable))
38 else:
39 # sys.executable can be empty if argv[0] has been changed and Python is
40 # unable to retrieve the real program name
41 project_base = os.getcwd()
42
43
44def _is_python_source_dir(d):
45 """
46 Return True if the target directory appears to point to an
47 un-installed Python.
48 """
49 modules = pathlib.Path(d).joinpath('Modules')
50 return any(modules.joinpath(fn).is_file() for fn in ('Setup', 'Setup.local'))
51
52
53_sys_home = getattr(sys, '_home', None)
54
55
56def _is_parent(dir_a, dir_b):
57 """
58 Return True if a is a parent of b.
59 """
60 return os.path.normcase(dir_a).startswith(os.path.normcase(dir_b))
61
62
63if os.name == 'nt':
64
65 @pass_none
66 def _fix_pcbuild(d):
67 # In a venv, sys._home will be inside BASE_PREFIX rather than PREFIX.
68 prefixes = PREFIX, BASE_PREFIX
69 matched = (
70 prefix
71 for prefix in prefixes
72 if _is_parent(d, os.path.join(prefix, "PCbuild"))
73 )
74 return next(matched, d)
75
76 project_base = _fix_pcbuild(project_base)
77 _sys_home = _fix_pcbuild(_sys_home)
78
79
80def _python_build():
81 if _sys_home:
82 return _is_python_source_dir(_sys_home)
83 return _is_python_source_dir(project_base)
84
85
86python_build = _python_build()
87
88
89# Calculate the build qualifier flags if they are defined. Adding the flags
90# to the include and lib directories only makes sense for an installation, not
91# an in-source build.
92build_flags = ''
93try:
94 if not python_build:
95 build_flags = sys.abiflags
96except AttributeError:
97 # It's not a configure-based build, so the sys module doesn't have
98 # this attribute, which is fine.
99 pass
100
101
102def get_python_version():
103 """Return a string containing the major and minor Python version,
104 leaving off the patchlevel. Sample return values could be '1.5'
105 or '2.2'.
106 """
107 return '%d.%d' % sys.version_info[:2]
108
109
110def get_python_inc(plat_specific=0, prefix=None):
111 """Return the directory containing installed Python header files.
112
113 If 'plat_specific' is false (the default), this is the path to the
114 non-platform-specific header files, i.e. Python.h and so on;
115 otherwise, this is the path to platform-specific header files
116 (namely pyconfig.h).
117
118 If 'prefix' is supplied, use it instead of sys.base_prefix or
119 sys.base_exec_prefix -- i.e., ignore 'plat_specific'.
120 """
121 default_prefix = BASE_EXEC_PREFIX if plat_specific else BASE_PREFIX
122 resolved_prefix = prefix if prefix is not None else default_prefix
123 try:
124 getter = globals()[f'_get_python_inc_{os.name}']
125 except KeyError:
126 raise DistutilsPlatformError(
127 "I don't know where Python installs its C header files "
128 "on platform '%s'" % os.name
129 )
130 return getter(resolved_prefix, prefix, plat_specific)
131
132
133def _get_python_inc_posix(prefix, spec_prefix, plat_specific):
134 if IS_PYPY and sys.version_info < (3, 8):
135 return os.path.join(prefix, 'include')
136 return (
137 _get_python_inc_posix_python(plat_specific)
138 or _get_python_inc_from_config(plat_specific, spec_prefix)
139 or _get_python_inc_posix_prefix(prefix)
140 )
141
142
143def _get_python_inc_posix_python(plat_specific):
144 """
145 Assume the executable is in the build directory. The
146 pyconfig.h file should be in the same directory. Since
147 the build directory may not be the source directory,
148 use "srcdir" from the makefile to find the "Include"
149 directory.
150 """
151 if not python_build:
152 return
153 if plat_specific:
154 return _sys_home or project_base
155 incdir = os.path.join(get_config_var('srcdir'), 'Include')
156 return os.path.normpath(incdir)
157
158
159def _get_python_inc_from_config(plat_specific, spec_prefix):
160 """
161 If no prefix was explicitly specified, provide the include
162 directory from the config vars. Useful when
163 cross-compiling, since the config vars may come from
164 the host
165 platform Python installation, while the current Python
166 executable is from the build platform installation.
167
168 >>> monkeypatch = getfixture('monkeypatch')
169 >>> gpifc = _get_python_inc_from_config
170 >>> monkeypatch.setitem(gpifc.__globals__, 'get_config_var', str.lower)
171 >>> gpifc(False, '/usr/bin/')
172 >>> gpifc(False, '')
173 >>> gpifc(False, None)
174 'includepy'
175 >>> gpifc(True, None)
176 'confincludepy'
177 """
178 if spec_prefix is None:
179 return get_config_var('CONF' * plat_specific + 'INCLUDEPY')
180
181
182def _get_python_inc_posix_prefix(prefix):
183 implementation = 'pypy' if IS_PYPY else 'python'
184 python_dir = implementation + get_python_version() + build_flags
185 return os.path.join(prefix, "include", python_dir)
186
187
188def _get_python_inc_nt(prefix, spec_prefix, plat_specific):
189 if python_build:
190 # Include both the include and PC dir to ensure we can find
191 # pyconfig.h
192 return (
193 os.path.join(prefix, "include")
194 + os.path.pathsep
195 + os.path.join(prefix, "PC")
196 )
197 return os.path.join(prefix, "include")
198
199
200# allow this behavior to be monkey-patched. Ref pypa/distutils#2.
201def _posix_lib(standard_lib, libpython, early_prefix, prefix):
202 if standard_lib:
203 return libpython
204 else:
205 return os.path.join(libpython, "site-packages")
206
207
208def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
209 """Return the directory containing the Python library (standard or
210 site additions).
211
212 If 'plat_specific' is true, return the directory containing
213 platform-specific modules, i.e. any module from a non-pure-Python
214 module distribution; otherwise, return the platform-shared library
215 directory. If 'standard_lib' is true, return the directory
216 containing standard Python library modules; otherwise, return the
217 directory for site-specific modules.
218
219 If 'prefix' is supplied, use it instead of sys.base_prefix or
220 sys.base_exec_prefix -- i.e., ignore 'plat_specific'.
221 """
222
223 if IS_PYPY and sys.version_info < (3, 8):
224 # PyPy-specific schema
225 if prefix is None:
226 prefix = PREFIX
227 if standard_lib:
228 return os.path.join(prefix, "lib-python", sys.version[0])
229 return os.path.join(prefix, 'site-packages')
230
231 early_prefix = prefix
232
233 if prefix is None:
234 if standard_lib:
235 prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX
236 else:
237 prefix = plat_specific and EXEC_PREFIX or PREFIX
238
239 if os.name == "posix":
240 if plat_specific or standard_lib:
241 # Platform-specific modules (any module from a non-pure-Python
242 # module distribution) or standard Python library modules.
243 libdir = getattr(sys, "platlibdir", "lib")
244 else:
245 # Pure Python
246 libdir = "lib"
247 implementation = 'pypy' if IS_PYPY else 'python'
248 libpython = os.path.join(prefix, libdir, implementation + get_python_version())
249 return _posix_lib(standard_lib, libpython, early_prefix, prefix)
250 elif os.name == "nt":
251 if standard_lib:
252 return os.path.join(prefix, "Lib")
253 else:
254 return os.path.join(prefix, "Lib", "site-packages")
255 else:
256 raise DistutilsPlatformError(
257 "I don't know where Python installs its library "
258 "on platform '%s'" % os.name
259 )
260
261
262def customize_compiler(compiler): # noqa: C901
263 """Do any platform-specific customization of a CCompiler instance.
264
265 Mainly needed on Unix, so we can plug in the information that
266 varies across Unices and is stored in Python's Makefile.
267 """
268 if compiler.compiler_type == "unix":
269 if sys.platform == "darwin":
270 # Perform first-time customization of compiler-related
271 # config vars on OS X now that we know we need a compiler.
272 # This is primarily to support Pythons from binary
273 # installers. The kind and paths to build tools on
274 # the user system may vary significantly from the system
275 # that Python itself was built on. Also the user OS
276 # version and build tools may not support the same set
277 # of CPU architectures for universal builds.
278 global _config_vars
279 # Use get_config_var() to ensure _config_vars is initialized.
280 if not get_config_var('CUSTOMIZED_OSX_COMPILER'):
281 import _osx_support
282
283 _osx_support.customize_compiler(_config_vars)
284 _config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True'
285
286 (
287 cc,
288 cxx,
289 cflags,
290 ccshared,
291 ldshared,
292 shlib_suffix,
293 ar,
294 ar_flags,
295 ) = get_config_vars(
296 'CC',
297 'CXX',
298 'CFLAGS',
299 'CCSHARED',
300 'LDSHARED',
301 'SHLIB_SUFFIX',
302 'AR',
303 'ARFLAGS',
304 )
305
306 if 'CC' in os.environ:
307 newcc = os.environ['CC']
308 if 'LDSHARED' not in os.environ and ldshared.startswith(cc):
309 # If CC is overridden, use that as the default
310 # command for LDSHARED as well
311 ldshared = newcc + ldshared[len(cc) :]
312 cc = newcc
313 if 'CXX' in os.environ:
314 cxx = os.environ['CXX']
315 if 'LDSHARED' in os.environ:
316 ldshared = os.environ['LDSHARED']
317 if 'CPP' in os.environ:
318 cpp = os.environ['CPP']
319 else:
320 cpp = cc + " -E" # not always
321 if 'LDFLAGS' in os.environ:
322 ldshared = ldshared + ' ' + os.environ['LDFLAGS']
323 if 'CFLAGS' in os.environ:
324 cflags = cflags + ' ' + os.environ['CFLAGS']
325 ldshared = ldshared + ' ' + os.environ['CFLAGS']
326 if 'CPPFLAGS' in os.environ:
327 cpp = cpp + ' ' + os.environ['CPPFLAGS']
328 cflags = cflags + ' ' + os.environ['CPPFLAGS']
329 ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
330 if 'AR' in os.environ:
331 ar = os.environ['AR']
332 if 'ARFLAGS' in os.environ:
333 archiver = ar + ' ' + os.environ['ARFLAGS']
334 else:
335 archiver = ar + ' ' + ar_flags
336
337 cc_cmd = cc + ' ' + cflags
338 compiler.set_executables(
339 preprocessor=cpp,
340 compiler=cc_cmd,
341 compiler_so=cc_cmd + ' ' + ccshared,
342 compiler_cxx=cxx,
343 linker_so=ldshared,
344 linker_exe=cc,
345 archiver=archiver,
346 )
347
348 if 'RANLIB' in os.environ and compiler.executables.get('ranlib', None):
349 compiler.set_executables(ranlib=os.environ['RANLIB'])
350
351 compiler.shared_lib_extension = shlib_suffix
352
353
354def get_config_h_filename():
355 """Return full pathname of installed pyconfig.h file."""
356 if python_build:
357 if os.name == "nt":
358 inc_dir = os.path.join(_sys_home or project_base, "PC")
359 else:
360 inc_dir = _sys_home or project_base
361 return os.path.join(inc_dir, 'pyconfig.h')
362 else:
363 return sysconfig.get_config_h_filename()
364
365
366def get_makefile_filename():
367 """Return full pathname of installed Makefile from the Python build."""
368 return sysconfig.get_makefile_filename()
369
370
371def parse_config_h(fp, g=None):
372 """Parse a config.h-style file.
373
374 A dictionary containing name/value pairs is returned. If an
375 optional dictionary is passed in as the second argument, it is
376 used instead of a new dictionary.
377 """
378 return sysconfig.parse_config_h(fp, vars=g)
379
380
381# Regexes needed for parsing Makefile (and similar syntaxes,
382# like old-style Setup files).
383_variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
384_findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
385_findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
386
387
388def parse_makefile(fn, g=None): # noqa: C901
389 """Parse a Makefile-style file.
390
391 A dictionary containing name/value pairs is returned. If an
392 optional dictionary is passed in as the second argument, it is
393 used instead of a new dictionary.
394 """
395 from distutils.text_file import TextFile
396
397 fp = TextFile(
398 fn, strip_comments=1, skip_blanks=1, join_lines=1, errors="surrogateescape"
399 )
400
401 if g is None:
402 g = {}
403 done = {}
404 notdone = {}
405
406 while True:
407 line = fp.readline()
408 if line is None: # eof
409 break
410 m = _variable_rx.match(line)
411 if m:
412 n, v = m.group(1, 2)
413 v = v.strip()
414 # `$$' is a literal `$' in make
415 tmpv = v.replace('$$', '')
416
417 if "$" in tmpv:
418 notdone[n] = v
419 else:
420 try:
421 v = int(v)
422 except ValueError:
423 # insert literal `$'
424 done[n] = v.replace('$$', '$')
425 else:
426 done[n] = v
427
428 # Variables with a 'PY_' prefix in the makefile. These need to
429 # be made available without that prefix through sysconfig.
430 # Special care is needed to ensure that variable expansion works, even
431 # if the expansion uses the name without a prefix.
432 renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
433
434 # do variable interpolation here
435 while notdone:
436 for name in list(notdone):
437 value = notdone[name]
438 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
439 if m:
440 n = m.group(1)
441 found = True
442 if n in done:
443 item = str(done[n])
444 elif n in notdone:
445 # get it on a subsequent round
446 found = False
447 elif n in os.environ:
448 # do it like make: fall back to environment
449 item = os.environ[n]
450
451 elif n in renamed_variables:
452 if name.startswith('PY_') and name[3:] in renamed_variables:
453 item = ""
454
455 elif 'PY_' + n in notdone:
456 found = False
457
458 else:
459 item = str(done['PY_' + n])
460 else:
461 done[n] = item = ""
462 if found:
463 after = value[m.end() :]
464 value = value[: m.start()] + item + after
465 if "$" in after:
466 notdone[name] = value
467 else:
468 try:
469 value = int(value)
470 except ValueError:
471 done[name] = value.strip()
472 else:
473 done[name] = value
474 del notdone[name]
475
476 if name.startswith('PY_') and name[3:] in renamed_variables:
477
478 name = name[3:]
479 if name not in done:
480 done[name] = value
481 else:
482 # bogus variable reference; just drop it since we can't deal
483 del notdone[name]
484
485 fp.close()
486
487 # strip spurious spaces
488 for k, v in done.items():
489 if isinstance(v, str):
490 done[k] = v.strip()
491
492 # save the results in the global dictionary
493 g.update(done)
494 return g
495
496
497def expand_makefile_vars(s, vars):
498 """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in
499 'string' according to 'vars' (a dictionary mapping variable names to
500 values). Variables not present in 'vars' are silently expanded to the
501 empty string. The variable values in 'vars' should not contain further
502 variable expansions; if 'vars' is the output of 'parse_makefile()',
503 you're fine. Returns a variable-expanded version of 's'.
504 """
505
506 # This algorithm does multiple expansion, so if vars['foo'] contains
507 # "${bar}", it will expand ${foo} to ${bar}, and then expand
508 # ${bar}... and so forth. This is fine as long as 'vars' comes from
509 # 'parse_makefile()', which takes care of such expansions eagerly,
510 # according to make's variable expansion semantics.
511
512 while True:
513 m = _findvar1_rx.search(s) or _findvar2_rx.search(s)
514 if m:
515 (beg, end) = m.span()
516 s = s[0:beg] + vars.get(m.group(1)) + s[end:]
517 else:
518 break
519 return s
520
521
522_config_vars = None
523
524
525def get_config_vars(*args):
526 """With no arguments, return a dictionary of all configuration
527 variables relevant for the current platform. Generally this includes
528 everything needed to build extensions and install both pure modules and
529 extensions. On Unix, this means every variable defined in Python's
530 installed Makefile; on Windows it's a much smaller set.
531
532 With arguments, return a list of values that result from looking up
533 each argument in the configuration variable dictionary.
534 """
535 global _config_vars
536 if _config_vars is None:
537 _config_vars = sysconfig.get_config_vars().copy()
538 py39compat.add_ext_suffix(_config_vars)
539
540 return [_config_vars.get(name) for name in args] if args else _config_vars
541
542
543def get_config_var(name):
544 """Return the value of a single variable using the dictionary
545 returned by 'get_config_vars()'. Equivalent to
546 get_config_vars().get(name)
547 """
548 if name == 'SO':
549 import warnings
550
551 warnings.warn('SO is deprecated, use EXT_SUFFIX', DeprecationWarning, 2)
552 return get_config_vars().get(name)