sysconfig.py 12 KB

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