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: <[email protected]> 10""" 11 12import _imp 13import os 14import re 15import sys 16import warnings 17 18from functools import partial 19 20from .errors import DistutilsPlatformError 21 22from sysconfig import ( 23 _PREFIX as PREFIX, 24 _BASE_PREFIX as BASE_PREFIX, 25 _EXEC_PREFIX as EXEC_PREFIX, 26 _BASE_EXEC_PREFIX as BASE_EXEC_PREFIX, 27 _PROJECT_BASE as project_base, 28 _PYTHON_BUILD as python_build, 29 _init_posix as sysconfig_init_posix, 30 parse_config_h as sysconfig_parse_config_h, 31 32 _init_non_posix, 33 34 _variable_rx, 35 _findvar1_rx, 36 _findvar2_rx, 37 38 expand_makefile_vars, 39 is_python_build, 40 get_config_h_filename, 41 get_config_var, 42 get_config_vars, 43 get_makefile_filename, 44 get_python_version, 45) 46 47# This is better than 48# from sysconfig import _CONFIG_VARS as _config_vars 49# because it makes sure that the global dictionary is initialized 50# which might not be true in the time of import. 51_config_vars = get_config_vars() 52 53warnings.warn( 54 'The distutils.sysconfig module is deprecated, use sysconfig instead', 55 DeprecationWarning, 56 stacklevel=2 57) 58 59 60# Following functions are the same as in sysconfig but with different API 61def parse_config_h(fp, g=None): 62 return sysconfig_parse_config_h(fp, vars=g) 63 64 65_python_build = partial(is_python_build, check_home=True) 66_init_posix = partial(sysconfig_init_posix, _config_vars) 67_init_nt = partial(_init_non_posix, _config_vars) 68 69 70# Similar function is also implemented in sysconfig as _parse_makefile 71# but without the parsing capabilities of distutils.text_file.TextFile. 72def parse_makefile(fn, g=None): 73 """Parse a Makefile-style file. 74 A dictionary containing name/value pairs is returned. If an 75 optional dictionary is passed in as the second argument, it is 76 used instead of a new dictionary. 77 """ 78 from distutils.text_file import TextFile 79 fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1, errors="surrogateescape") 80 81 if g is None: 82 g = {} 83 done = {} 84 notdone = {} 85 86 while True: 87 line = fp.readline() 88 if line is None: # eof 89 break 90 m = re.match(_variable_rx, line) 91 if m: 92 n, v = m.group(1, 2) 93 v = v.strip() 94 # `$$' is a literal `$' in make 95 tmpv = v.replace('$$', '') 96 97 if "$" in tmpv: 98 notdone[n] = v 99 else: 100 try: 101 v = int(v) 102 except ValueError: 103 # insert literal `$' 104 done[n] = v.replace('$$', '$') 105 else: 106 done[n] = v 107 108 # Variables with a 'PY_' prefix in the makefile. These need to 109 # be made available without that prefix through sysconfig. 110 # Special care is needed to ensure that variable expansion works, even 111 # if the expansion uses the name without a prefix. 112 renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS') 113 114 # do variable interpolation here 115 while notdone: 116 for name in list(notdone): 117 value = notdone[name] 118 m = re.search(_findvar1_rx, value) or re.search(_findvar2_rx, value) 119 if m: 120 n = m.group(1) 121 found = True 122 if n in done: 123 item = str(done[n]) 124 elif n in notdone: 125 # get it on a subsequent round 126 found = False 127 elif n in os.environ: 128 # do it like make: fall back to environment 129 item = os.environ[n] 130 131 elif n in renamed_variables: 132 if name.startswith('PY_') and name[3:] in renamed_variables: 133 item = "" 134 135 elif 'PY_' + n in notdone: 136 found = False 137 138 else: 139 item = str(done['PY_' + n]) 140 else: 141 done[n] = item = "" 142 if found: 143 after = value[m.end():] 144 value = value[:m.start()] + item + after 145 if "$" in after: 146 notdone[name] = value 147 else: 148 try: value = int(value) 149 except ValueError: 150 done[name] = value.strip() 151 else: 152 done[name] = value 153 del notdone[name] 154 155 if name.startswith('PY_') \ 156 and name[3:] in renamed_variables: 157 158 name = name[3:] 159 if name not in done: 160 done[name] = value 161 else: 162 # bogus variable reference; just drop it since we can't deal 163 del notdone[name] 164 165 fp.close() 166 167 # strip spurious spaces 168 for k, v in done.items(): 169 if isinstance(v, str): 170 done[k] = v.strip() 171 172 # save the results in the global dictionary 173 g.update(done) 174 return g 175 176 177# Following functions are deprecated together with this module and they 178# have no direct replacement 179 180# Calculate the build qualifier flags if they are defined. Adding the flags 181# to the include and lib directories only makes sense for an installation, not 182# an in-source build. 183build_flags = '' 184try: 185 if not python_build: 186 build_flags = sys.abiflags 187except AttributeError: 188 # It's not a configure-based build, so the sys module doesn't have 189 # this attribute, which is fine. 190 pass 191 192 193def customize_compiler(compiler): 194 """Do any platform-specific customization of a CCompiler instance. 195 196 Mainly needed on Unix, so we can plug in the information that 197 varies across Unices and is stored in Python's Makefile. 198 """ 199 if compiler.compiler_type == "unix": 200 if sys.platform == "darwin": 201 # Perform first-time customization of compiler-related 202 # config vars on OS X now that we know we need a compiler. 203 # This is primarily to support Pythons from binary 204 # installers. The kind and paths to build tools on 205 # the user system may vary significantly from the system 206 # that Python itself was built on. Also the user OS 207 # version and build tools may not support the same set 208 # of CPU architectures for universal builds. 209 if not _config_vars.get('CUSTOMIZED_OSX_COMPILER'): 210 import _osx_support 211 _osx_support.customize_compiler(_config_vars) 212 _config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True' 213 214 (cc, cxx, cflags, ccshared, ldshared, shlib_suffix, ar, ar_flags) = \ 215 get_config_vars('CC', 'CXX', 'CFLAGS', 216 'CCSHARED', 'LDSHARED', 'SHLIB_SUFFIX', 'AR', 'ARFLAGS') 217 218 if 'CC' in os.environ: 219 newcc = os.environ['CC'] 220 if (sys.platform == 'darwin' 221 and 'LDSHARED' not in os.environ 222 and ldshared.startswith(cc)): 223 # On OS X, if CC is overridden, use that as the default 224 # command for LDSHARED as well 225 ldshared = newcc + ldshared[len(cc):] 226 cc = newcc 227 if 'CXX' in os.environ: 228 cxx = os.environ['CXX'] 229 if 'LDSHARED' in os.environ: 230 ldshared = os.environ['LDSHARED'] 231 if 'CPP' in os.environ: 232 cpp = os.environ['CPP'] 233 else: 234 cpp = cc + " -E" # not always 235 if 'LDFLAGS' in os.environ: 236 ldshared = ldshared + ' ' + os.environ['LDFLAGS'] 237 if 'CFLAGS' in os.environ: 238 cflags = cflags + ' ' + os.environ['CFLAGS'] 239 ldshared = ldshared + ' ' + os.environ['CFLAGS'] 240 if 'CPPFLAGS' in os.environ: 241 cpp = cpp + ' ' + os.environ['CPPFLAGS'] 242 cflags = cflags + ' ' + os.environ['CPPFLAGS'] 243 ldshared = ldshared + ' ' + os.environ['CPPFLAGS'] 244 if 'AR' in os.environ: 245 ar = os.environ['AR'] 246 if 'ARFLAGS' in os.environ: 247 archiver = ar + ' ' + os.environ['ARFLAGS'] 248 else: 249 archiver = ar + ' ' + ar_flags 250 251 cc_cmd = cc + ' ' + cflags 252 compiler.set_executables( 253 preprocessor=cpp, 254 compiler=cc_cmd, 255 compiler_so=cc_cmd + ' ' + ccshared, 256 compiler_cxx=cxx, 257 linker_so=ldshared, 258 linker_exe=cc, 259 archiver=archiver) 260 261 compiler.shared_lib_extension = shlib_suffix 262 263 264def get_python_inc(plat_specific=0, prefix=None): 265 """Return the directory containing installed Python header files. 266 267 If 'plat_specific' is false (the default), this is the path to the 268 non-platform-specific header files, i.e. Python.h and so on; 269 otherwise, this is the path to platform-specific header files 270 (namely pyconfig.h). 271 272 If 'prefix' is supplied, use it instead of sys.base_prefix or 273 sys.base_exec_prefix -- i.e., ignore 'plat_specific'. 274 """ 275 if prefix is None: 276 prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX 277 if os.name == "posix": 278 if python_build: 279 # Assume the executable is in the build directory. The 280 # pyconfig.h file should be in the same directory. Since 281 # the build directory may not be the source directory, we 282 # must use "srcdir" from the makefile to find the "Include" 283 # directory. 284 if plat_specific: 285 return project_base 286 else: 287 incdir = os.path.join(get_config_var('srcdir'), 'Include') 288 return os.path.normpath(incdir) 289 python_dir = 'python' + get_python_version() + build_flags 290 return os.path.join(prefix, "include", python_dir) 291 elif os.name == "nt": 292 if python_build: 293 # Include both the include and PC dir to ensure we can find 294 # pyconfig.h 295 return (os.path.join(prefix, "include") + os.path.pathsep + 296 os.path.join(prefix, "PC")) 297 return os.path.join(prefix, "include") 298 else: 299 raise DistutilsPlatformError( 300 "I don't know where Python installs its C header files " 301 "on platform '%s'" % os.name) 302 303 304def get_python_lib(plat_specific=0, standard_lib=0, prefix=None): 305 """Return the directory containing the Python library (standard or 306 site additions). 307 308 If 'plat_specific' is true, return the directory containing 309 platform-specific modules, i.e. any module from a non-pure-Python 310 module distribution; otherwise, return the platform-shared library 311 directory. If 'standard_lib' is true, return the directory 312 containing standard Python library modules; otherwise, return the 313 directory for site-specific modules. 314 315 If 'prefix' is supplied, use it instead of sys.base_prefix or 316 sys.base_exec_prefix -- i.e., ignore 'plat_specific'. 317 """ 318 if prefix is None: 319 if standard_lib: 320 prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX 321 else: 322 prefix = plat_specific and EXEC_PREFIX or PREFIX 323 324 if os.name == "posix": 325 if plat_specific or standard_lib: 326 # Platform-specific modules (any module from a non-pure-Python 327 # module distribution) or standard Python library modules. 328 libdir = sys.platlibdir 329 else: 330 # Pure Python 331 libdir = "lib" 332 libpython = os.path.join(prefix, libdir, 333 "python" + get_python_version()) 334 if standard_lib: 335 return libpython 336 else: 337 return os.path.join(libpython, "site-packages") 338 elif os.name == "nt": 339 if standard_lib: 340 return os.path.join(prefix, "Lib") 341 else: 342 return os.path.join(prefix, "Lib", "site-packages") 343 else: 344 raise DistutilsPlatformError( 345 "I don't know where Python installs its library " 346 "on platform '%s'" % os.name) 347