1# Autodetecting setup.py script for building the Python extensions 2 3import argparse 4import importlib._bootstrap 5import importlib.machinery 6import importlib.util 7import logging 8import os 9import re 10import shlex 11import sys 12import sysconfig 13import warnings 14from glob import glob, escape 15import _osx_support 16 17 18try: 19 import subprocess 20 del subprocess 21 SUBPROCESS_BOOTSTRAP = False 22except ImportError: 23 # Bootstrap Python: distutils.spawn uses subprocess to build C extensions, 24 # subprocess requires C extensions built by setup.py like _posixsubprocess. 25 # 26 # Use _bootsubprocess which only uses the os module. 27 # 28 # It is dropped from sys.modules as soon as all C extension modules 29 # are built. 30 import _bootsubprocess 31 sys.modules['subprocess'] = _bootsubprocess 32 del _bootsubprocess 33 SUBPROCESS_BOOTSTRAP = True 34 35 36with warnings.catch_warnings(): 37 # bpo-41282 (PEP 632) deprecated distutils but setup.py still uses it 38 warnings.filterwarnings( 39 "ignore", 40 "The distutils package is deprecated", 41 DeprecationWarning 42 ) 43 warnings.filterwarnings( 44 "ignore", 45 "The distutils.sysconfig module is deprecated, use sysconfig instead", 46 DeprecationWarning 47 ) 48 49 from distutils.command.build_ext import build_ext 50 from distutils.command.build_scripts import build_scripts 51 from distutils.command.install import install 52 from distutils.command.install_lib import install_lib 53 from distutils.core import Extension, setup 54 from distutils.errors import CCompilerError, DistutilsError 55 from distutils.spawn import find_executable 56 57 58# This global variable is used to hold the list of modules to be disabled. 59DISABLED_MODULE_LIST = [] 60 61# --list-module-names option used by Tools/scripts/generate_module_names.py 62LIST_MODULE_NAMES = False 63 64 65logging.basicConfig(format='%(message)s', level=logging.INFO) 66log = logging.getLogger('setup') 67 68 69def get_platform(): 70 # Cross compiling 71 if "_PYTHON_HOST_PLATFORM" in os.environ: 72 return os.environ["_PYTHON_HOST_PLATFORM"] 73 74 # Get value of sys.platform 75 if sys.platform.startswith('osf1'): 76 return 'osf1' 77 return sys.platform 78 79 80CROSS_COMPILING = ("_PYTHON_HOST_PLATFORM" in os.environ) 81HOST_PLATFORM = get_platform() 82MS_WINDOWS = (HOST_PLATFORM == 'win32') 83CYGWIN = (HOST_PLATFORM == 'cygwin') 84MACOS = (HOST_PLATFORM == 'darwin') 85AIX = (HOST_PLATFORM.startswith('aix')) 86VXWORKS = ('vxworks' in HOST_PLATFORM) 87EMSCRIPTEN = HOST_PLATFORM == 'emscripten-wasm32' 88CC = os.environ.get("CC") 89if not CC: 90 CC = sysconfig.get_config_var("CC") 91 92if EMSCRIPTEN: 93 # emcc is a Python script from a different Python interpreter. 94 os.environ.pop("PYTHONPATH", None) 95 96 97SUMMARY = """ 98Python is an interpreted, interactive, object-oriented programming 99language. It is often compared to Tcl, Perl, Scheme or Java. 100 101Python combines remarkable power with very clear syntax. It has 102modules, classes, exceptions, very high level dynamic data types, and 103dynamic typing. There are interfaces to many system calls and 104libraries, as well as to various windowing systems (X11, Motif, Tk, 105Mac, MFC). New built-in modules are easily written in C or C++. Python 106is also usable as an extension language for applications that need a 107programmable interface. 108 109The Python implementation is portable: it runs on many brands of UNIX, 110on Windows, DOS, Mac, Amiga... If your favorite system isn't 111listed here, it may still be supported, if there's a C compiler for 112it. Ask around on comp.lang.python -- or just try compiling Python 113yourself. 114""" 115 116CLASSIFIERS = """ 117Development Status :: 6 - Mature 118License :: OSI Approved :: Python Software Foundation License 119Natural Language :: English 120Programming Language :: C 121Programming Language :: Python 122Topic :: Software Development 123""" 124 125 126def run_command(cmd): 127 status = os.system(cmd) 128 return os.waitstatus_to_exitcode(status) 129 130 131# Set common compiler and linker flags derived from the Makefile, 132# reserved for building the interpreter and the stdlib modules. 133# See bpo-21121 and bpo-35257 134def set_compiler_flags(compiler_flags, compiler_py_flags_nodist): 135 flags = sysconfig.get_config_var(compiler_flags) 136 py_flags_nodist = sysconfig.get_config_var(compiler_py_flags_nodist) 137 sysconfig.get_config_vars()[compiler_flags] = flags + ' ' + py_flags_nodist 138 139 140def add_dir_to_list(dirlist, dir): 141 """Add the directory 'dir' to the list 'dirlist' (after any relative 142 directories) if: 143 144 1) 'dir' is not already in 'dirlist' 145 2) 'dir' actually exists, and is a directory. 146 """ 147 if dir is None or not os.path.isdir(dir) or dir in dirlist: 148 return 149 for i, path in enumerate(dirlist): 150 if not os.path.isabs(path): 151 dirlist.insert(i + 1, dir) 152 return 153 dirlist.insert(0, dir) 154 155 156def sysroot_paths(make_vars, subdirs): 157 """Get the paths of sysroot sub-directories. 158 159 * make_vars: a sequence of names of variables of the Makefile where 160 sysroot may be set. 161 * subdirs: a sequence of names of subdirectories used as the location for 162 headers or libraries. 163 """ 164 165 dirs = [] 166 for var_name in make_vars: 167 var = sysconfig.get_config_var(var_name) 168 if var is not None: 169 m = re.search(r'--sysroot=([^"]\S*|"[^"]+")', var) 170 if m is not None: 171 sysroot = m.group(1).strip('"') 172 for subdir in subdirs: 173 if os.path.isabs(subdir): 174 subdir = subdir[1:] 175 path = os.path.join(sysroot, subdir) 176 if os.path.isdir(path): 177 dirs.append(path) 178 break 179 return dirs 180 181 182MACOS_SDK_ROOT = None 183MACOS_SDK_SPECIFIED = None 184 185def macosx_sdk_root(): 186 """Return the directory of the current macOS SDK. 187 188 If no SDK was explicitly configured, call the compiler to find which 189 include files paths are being searched by default. Use '/' if the 190 compiler is searching /usr/include (meaning system header files are 191 installed) or use the root of an SDK if that is being searched. 192 (The SDK may be supplied via Xcode or via the Command Line Tools). 193 The SDK paths used by Apple-supplied tool chains depend on the 194 setting of various variables; see the xcrun man page for more info. 195 Also sets MACOS_SDK_SPECIFIED for use by macosx_sdk_specified(). 196 """ 197 global MACOS_SDK_ROOT, MACOS_SDK_SPECIFIED 198 199 # If already called, return cached result. 200 if MACOS_SDK_ROOT: 201 return MACOS_SDK_ROOT 202 203 cflags = sysconfig.get_config_var('CFLAGS') 204 m = re.search(r'-isysroot\s*(\S+)', cflags) 205 if m is not None: 206 MACOS_SDK_ROOT = m.group(1) 207 MACOS_SDK_SPECIFIED = MACOS_SDK_ROOT != '/' 208 else: 209 MACOS_SDK_ROOT = _osx_support._default_sysroot( 210 sysconfig.get_config_var('CC')) 211 MACOS_SDK_SPECIFIED = False 212 213 return MACOS_SDK_ROOT 214 215 216def is_macosx_sdk_path(path): 217 """ 218 Returns True if 'path' can be located in a macOS SDK 219 """ 220 return ( (path.startswith('/usr/') and not path.startswith('/usr/local')) 221 or path.startswith('/System/Library') 222 or path.startswith('/System/iOSSupport') ) 223 224 225def grep_headers_for(function, headers): 226 for header in headers: 227 with open(header, 'r', errors='surrogateescape') as f: 228 if function in f.read(): 229 return True 230 return False 231 232 233def find_file(filename, std_dirs, paths): 234 """Searches for the directory where a given file is located, 235 and returns a possibly-empty list of additional directories, or None 236 if the file couldn't be found at all. 237 238 'filename' is the name of a file, such as readline.h or libcrypto.a. 239 'std_dirs' is the list of standard system directories; if the 240 file is found in one of them, no additional directives are needed. 241 'paths' is a list of additional locations to check; if the file is 242 found in one of them, the resulting list will contain the directory. 243 """ 244 if MACOS: 245 # Honor the MacOSX SDK setting when one was specified. 246 # An SDK is a directory with the same structure as a real 247 # system, but with only header files and libraries. 248 sysroot = macosx_sdk_root() 249 250 # Check the standard locations 251 for dir_ in std_dirs: 252 f = os.path.join(dir_, filename) 253 254 if MACOS and is_macosx_sdk_path(dir_): 255 f = os.path.join(sysroot, dir_[1:], filename) 256 257 if os.path.exists(f): return [] 258 259 # Check the additional directories 260 for dir_ in paths: 261 f = os.path.join(dir_, filename) 262 263 if MACOS and is_macosx_sdk_path(dir_): 264 f = os.path.join(sysroot, dir_[1:], filename) 265 266 if os.path.exists(f): 267 return [dir_] 268 269 # Not found anywhere 270 return None 271 272 273def validate_tzpath(): 274 base_tzpath = sysconfig.get_config_var('TZPATH') 275 if not base_tzpath: 276 return 277 278 tzpaths = base_tzpath.split(os.pathsep) 279 bad_paths = [tzpath for tzpath in tzpaths if not os.path.isabs(tzpath)] 280 if bad_paths: 281 raise ValueError('TZPATH must contain only absolute paths, ' 282 + f'found:\n{tzpaths!r}\nwith invalid paths:\n' 283 + f'{bad_paths!r}') 284 285 286def find_module_file(module, dirlist): 287 """Find a module in a set of possible folders. If it is not found 288 return the unadorned filename""" 289 dirs = find_file(module, [], dirlist) 290 if not dirs: 291 return module 292 if len(dirs) > 1: 293 log.info(f"WARNING: multiple copies of {module} found") 294 return os.path.abspath(os.path.join(dirs[0], module)) 295 296 297class PyBuildExt(build_ext): 298 299 def __init__(self, dist): 300 build_ext.__init__(self, dist) 301 self.srcdir = None 302 self.lib_dirs = None 303 self.inc_dirs = None 304 self.config_h_vars = None 305 self.failed = [] 306 self.failed_on_import = [] 307 self.missing = [] 308 self.disabled_configure = [] 309 if '-j' in os.environ.get('MAKEFLAGS', ''): 310 self.parallel = True 311 312 def add(self, ext): 313 self.extensions.append(ext) 314 315 def addext(self, ext, *, update_flags=True): 316 """Add extension with Makefile MODULE_{name} support 317 """ 318 if update_flags: 319 self.update_extension_flags(ext) 320 321 state = sysconfig.get_config_var(f"MODULE_{ext.name.upper()}_STATE") 322 if state == "yes": 323 self.extensions.append(ext) 324 elif state == "disabled": 325 self.disabled_configure.append(ext.name) 326 elif state == "missing": 327 self.missing.append(ext.name) 328 elif state == "n/a": 329 # not available on current platform 330 pass 331 else: 332 # not migrated to MODULE_{name}_STATE yet. 333 self.announce( 334 f'WARNING: Makefile is missing module variable for "{ext.name}"', 335 level=2 336 ) 337 self.extensions.append(ext) 338 339 def update_extension_flags(self, ext): 340 """Update extension flags with module CFLAGS and LDFLAGS 341 342 Reads MODULE_{name}_CFLAGS and _LDFLAGS 343 344 Distutils appends extra args to the compiler arguments. Some flags like 345 -I must appear earlier, otherwise the pre-processor picks up files 346 from system include directories. 347 """ 348 upper_name = ext.name.upper() 349 # Parse compiler flags (-I, -D, -U, extra args) 350 cflags = sysconfig.get_config_var(f"MODULE_{upper_name}_CFLAGS") 351 if cflags: 352 for token in shlex.split(cflags): 353 switch = token[0:2] 354 value = token[2:] 355 if switch == '-I': 356 ext.include_dirs.append(value) 357 elif switch == '-D': 358 key, _, val = value.partition("=") 359 if not val: 360 val = None 361 ext.define_macros.append((key, val)) 362 elif switch == '-U': 363 ext.undef_macros.append(value) 364 else: 365 ext.extra_compile_args.append(token) 366 367 # Parse linker flags (-L, -l, extra objects, extra args) 368 ldflags = sysconfig.get_config_var(f"MODULE_{upper_name}_LDFLAGS") 369 if ldflags: 370 for token in shlex.split(ldflags): 371 switch = token[0:2] 372 value = token[2:] 373 if switch == '-L': 374 ext.library_dirs.append(value) 375 elif switch == '-l': 376 ext.libraries.append(value) 377 elif ( 378 token[0] != '-' and 379 token.endswith(('.a', '.o', '.so', '.sl', '.dylib')) 380 ): 381 ext.extra_objects.append(token) 382 else: 383 ext.extra_link_args.append(token) 384 385 return ext 386 387 def set_srcdir(self): 388 self.srcdir = sysconfig.get_config_var('srcdir') 389 if not self.srcdir: 390 # Maybe running on Windows but not using CYGWIN? 391 raise ValueError("No source directory; cannot proceed.") 392 self.srcdir = os.path.abspath(self.srcdir) 393 394 def remove_disabled(self): 395 # Remove modules that are present on the disabled list 396 extensions = [ext for ext in self.extensions 397 if ext.name not in DISABLED_MODULE_LIST] 398 # move ctypes to the end, it depends on other modules 399 ext_map = dict((ext.name, i) for i, ext in enumerate(extensions)) 400 if "_ctypes" in ext_map: 401 ctypes = extensions.pop(ext_map["_ctypes"]) 402 extensions.append(ctypes) 403 self.extensions = extensions 404 405 def update_sources_depends(self): 406 # Fix up the autodetected modules, prefixing all the source files 407 # with Modules/. 408 # Add dependencies from MODULE_{name}_DEPS variable 409 moddirlist = [ 410 # files in Modules/ directory 411 os.path.join(self.srcdir, 'Modules'), 412 # files relative to build base, e.g. libmpdec.a, libexpat.a 413 os.getcwd() 414 ] 415 416 # Fix up the paths for scripts, too 417 self.distribution.scripts = [os.path.join(self.srcdir, filename) 418 for filename in self.distribution.scripts] 419 420 # Python header files 421 include_dir = escape(sysconfig.get_path('include')) 422 headers = [sysconfig.get_config_h_filename()] 423 headers.extend(glob(os.path.join(include_dir, "*.h"))) 424 headers.extend(glob(os.path.join(include_dir, "cpython", "*.h"))) 425 headers.extend(glob(os.path.join(include_dir, "internal", "*.h"))) 426 427 for ext in self.extensions: 428 ext.sources = [ find_module_file(filename, moddirlist) 429 for filename in ext.sources ] 430 # Update dependencies from Makefile 431 makedeps = sysconfig.get_config_var(f"MODULE_{ext.name.upper()}_DEPS") 432 if makedeps: 433 # remove backslashes from line break continuations 434 ext.depends.extend( 435 dep for dep in makedeps.split() if dep != "\\" 436 ) 437 ext.depends = [ 438 find_module_file(filename, moddirlist) for filename in ext.depends 439 ] 440 # re-compile extensions if a header file has been changed 441 ext.depends.extend(headers) 442 443 def handle_configured_extensions(self): 444 # The sysconfig variables built by makesetup that list the already 445 # built modules and the disabled modules as configured by the Setup 446 # files. 447 sysconf_built = set(sysconfig.get_config_var('MODBUILT_NAMES').split()) 448 sysconf_shared = set(sysconfig.get_config_var('MODSHARED_NAMES').split()) 449 sysconf_dis = set(sysconfig.get_config_var('MODDISABLED_NAMES').split()) 450 451 mods_built = [] 452 mods_disabled = [] 453 for ext in self.extensions: 454 # If a module has already been built or has been disabled in the 455 # Setup files, don't build it here. 456 if ext.name in sysconf_built: 457 mods_built.append(ext) 458 if ext.name in sysconf_dis: 459 mods_disabled.append(ext) 460 461 mods_configured = mods_built + mods_disabled 462 if mods_configured: 463 self.extensions = [x for x in self.extensions if x not in 464 mods_configured] 465 # Remove the shared libraries built by a previous build. 466 for ext in mods_configured: 467 # Don't remove shared extensions which have been built 468 # by Modules/Setup 469 if ext.name in sysconf_shared: 470 continue 471 fullpath = self.get_ext_fullpath(ext.name) 472 if os.path.lexists(fullpath): 473 os.unlink(fullpath) 474 475 return mods_built, mods_disabled 476 477 def set_compiler_executables(self): 478 # When you run "make CC=altcc" or something similar, you really want 479 # those environment variables passed into the setup.py phase. Here's 480 # a small set of useful ones. 481 compiler = os.environ.get('CC') 482 args = {} 483 # unfortunately, distutils doesn't let us provide separate C and C++ 484 # compilers 485 if compiler is not None: 486 (ccshared,cflags) = sysconfig.get_config_vars('CCSHARED','CFLAGS') 487 args['compiler_so'] = compiler + ' ' + ccshared + ' ' + cflags 488 self.compiler.set_executables(**args) 489 490 def build_extensions(self): 491 self.set_srcdir() 492 self.set_compiler_executables() 493 self.configure_compiler() 494 self.init_inc_lib_dirs() 495 496 # Detect which modules should be compiled 497 self.detect_modules() 498 499 if not LIST_MODULE_NAMES: 500 self.remove_disabled() 501 502 self.update_sources_depends() 503 mods_built, mods_disabled = self.handle_configured_extensions() 504 505 if LIST_MODULE_NAMES: 506 for ext in self.extensions: 507 print(ext.name) 508 for name in self.missing: 509 print(name) 510 return 511 512 build_ext.build_extensions(self) 513 514 if SUBPROCESS_BOOTSTRAP: 515 # Drop our custom subprocess module: 516 # use the newly built subprocess module 517 del sys.modules['subprocess'] 518 519 for ext in self.extensions: 520 self.check_extension_import(ext) 521 522 self.summary(mods_built, mods_disabled) 523 524 def summary(self, mods_built, mods_disabled): 525 longest = max([len(e.name) for e in self.extensions], default=0) 526 if self.failed or self.failed_on_import: 527 all_failed = self.failed + self.failed_on_import 528 longest = max(longest, max([len(name) for name in all_failed])) 529 530 def print_three_column(lst): 531 lst.sort(key=str.lower) 532 # guarantee zip() doesn't drop anything 533 while len(lst) % 3: 534 lst.append("") 535 for e, f, g in zip(lst[::3], lst[1::3], lst[2::3]): 536 print("%-*s %-*s %-*s" % (longest, e, longest, f, 537 longest, g)) 538 539 if self.missing: 540 print() 541 print("The necessary bits to build these optional modules were not " 542 "found:") 543 print_three_column(self.missing) 544 print("To find the necessary bits, look in setup.py in" 545 " detect_modules() for the module's name.") 546 print() 547 548 if mods_built: 549 print() 550 print("The following modules found by detect_modules() in" 551 " setup.py, have been") 552 print("built by the Makefile instead, as configured by the" 553 " Setup files:") 554 print_three_column([ext.name for ext in mods_built]) 555 print() 556 557 if mods_disabled: 558 print() 559 print("The following modules found by detect_modules() in" 560 " setup.py have not") 561 print("been built, they are *disabled* in the Setup files:") 562 print_three_column([ext.name for ext in mods_disabled]) 563 print() 564 565 if self.disabled_configure: 566 print() 567 print("The following modules found by detect_modules() in" 568 " setup.py have not") 569 print("been built, they are *disabled* by configure:") 570 print_three_column(self.disabled_configure) 571 print() 572 573 if self.failed: 574 failed = self.failed[:] 575 print() 576 print("Failed to build these modules:") 577 print_three_column(failed) 578 print() 579 580 if self.failed_on_import: 581 failed = self.failed_on_import[:] 582 print() 583 print("Following modules built successfully" 584 " but were removed because they could not be imported:") 585 print_three_column(failed) 586 print() 587 588 if any('_ssl' in l 589 for l in (self.missing, self.failed, self.failed_on_import)): 590 print() 591 print("Could not build the ssl module!") 592 print("Python requires a OpenSSL 1.1.1 or newer") 593 if sysconfig.get_config_var("OPENSSL_LDFLAGS"): 594 print("Custom linker flags may require --with-openssl-rpath=auto") 595 print() 596 597 if os.environ.get("PYTHONSTRICTEXTENSIONBUILD") and ( 598 self.failed or self.failed_on_import or self.missing 599 ): 600 raise RuntimeError("Failed to build some stdlib modules") 601 602 def build_extension(self, ext): 603 604 if ext.name == '_ctypes': 605 if not self.configure_ctypes(ext): 606 self.failed.append(ext.name) 607 return 608 609 try: 610 build_ext.build_extension(self, ext) 611 except (CCompilerError, DistutilsError) as why: 612 self.announce('WARNING: building of extension "%s" failed: %s' % 613 (ext.name, why)) 614 self.failed.append(ext.name) 615 return 616 617 def check_extension_import(self, ext): 618 # Don't try to import an extension that has failed to compile 619 if ext.name in self.failed: 620 self.announce( 621 'WARNING: skipping import check for failed build "%s"' % 622 ext.name, level=1) 623 return 624 625 # Workaround for Mac OS X: The Carbon-based modules cannot be 626 # reliably imported into a command-line Python 627 if 'Carbon' in ext.extra_link_args: 628 self.announce( 629 'WARNING: skipping import check for Carbon-based "%s"' % 630 ext.name) 631 return 632 633 if MACOS and ( 634 sys.maxsize > 2**32 and '-arch' in ext.extra_link_args): 635 # Don't bother doing an import check when an extension was 636 # build with an explicit '-arch' flag on OSX. That's currently 637 # only used to build 32-bit only extensions in a 4-way 638 # universal build and loading 32-bit code into a 64-bit 639 # process will fail. 640 self.announce( 641 'WARNING: skipping import check for "%s"' % 642 ext.name) 643 return 644 645 # Workaround for Cygwin: Cygwin currently has fork issues when many 646 # modules have been imported 647 if CYGWIN: 648 self.announce('WARNING: skipping import check for Cygwin-based "%s"' 649 % ext.name) 650 return 651 ext_filename = os.path.join( 652 self.build_lib, 653 self.get_ext_filename(self.get_ext_fullname(ext.name))) 654 655 # If the build directory didn't exist when setup.py was 656 # started, sys.path_importer_cache has a negative result 657 # cached. Clear that cache before trying to import. 658 sys.path_importer_cache.clear() 659 660 # Don't try to load extensions for cross builds 661 if CROSS_COMPILING: 662 return 663 664 loader = importlib.machinery.ExtensionFileLoader(ext.name, ext_filename) 665 spec = importlib.util.spec_from_file_location(ext.name, ext_filename, 666 loader=loader) 667 try: 668 importlib._bootstrap._load(spec) 669 except ImportError as why: 670 self.failed_on_import.append(ext.name) 671 self.announce('*** WARNING: renaming "%s" since importing it' 672 ' failed: %s' % (ext.name, why), level=3) 673 assert not self.inplace 674 basename, tail = os.path.splitext(ext_filename) 675 newname = basename + "_failed" + tail 676 if os.path.exists(newname): 677 os.remove(newname) 678 os.rename(ext_filename, newname) 679 680 except: 681 exc_type, why, tb = sys.exc_info() 682 self.announce('*** WARNING: importing extension "%s" ' 683 'failed with %s: %s' % (ext.name, exc_type, why), 684 level=3) 685 self.failed.append(ext.name) 686 687 def add_multiarch_paths(self): 688 # Debian/Ubuntu multiarch support. 689 # https://wiki.ubuntu.com/MultiarchSpec 690 tmpfile = os.path.join(self.build_temp, 'multiarch') 691 if not os.path.exists(self.build_temp): 692 os.makedirs(self.build_temp) 693 ret = run_command( 694 '%s -print-multiarch > %s 2> /dev/null' % (CC, tmpfile)) 695 multiarch_path_component = '' 696 try: 697 if ret == 0: 698 with open(tmpfile) as fp: 699 multiarch_path_component = fp.readline().strip() 700 finally: 701 os.unlink(tmpfile) 702 703 if multiarch_path_component != '': 704 add_dir_to_list(self.compiler.library_dirs, 705 '/usr/lib/' + multiarch_path_component) 706 add_dir_to_list(self.compiler.include_dirs, 707 '/usr/include/' + multiarch_path_component) 708 return 709 710 if not find_executable('dpkg-architecture'): 711 return 712 opt = '' 713 if CROSS_COMPILING: 714 opt = '-t' + sysconfig.get_config_var('HOST_GNU_TYPE') 715 tmpfile = os.path.join(self.build_temp, 'multiarch') 716 if not os.path.exists(self.build_temp): 717 os.makedirs(self.build_temp) 718 ret = run_command( 719 'dpkg-architecture %s -qDEB_HOST_MULTIARCH > %s 2> /dev/null' % 720 (opt, tmpfile)) 721 try: 722 if ret == 0: 723 with open(tmpfile) as fp: 724 multiarch_path_component = fp.readline().strip() 725 add_dir_to_list(self.compiler.library_dirs, 726 '/usr/lib/' + multiarch_path_component) 727 add_dir_to_list(self.compiler.include_dirs, 728 '/usr/include/' + multiarch_path_component) 729 finally: 730 os.unlink(tmpfile) 731 732 def add_wrcc_search_dirs(self): 733 # add library search path by wr-cc, the compiler wrapper 734 735 def convert_mixed_path(path): 736 # convert path like C:\folder1\folder2/folder3/folder4 737 # to msys style /c/folder1/folder2/folder3/folder4 738 drive = path[0].lower() 739 left = path[2:].replace("\\", "/") 740 return "/" + drive + left 741 742 def add_search_path(line): 743 # On Windows building machine, VxWorks does 744 # cross builds under msys2 environment. 745 pathsep = (";" if sys.platform == "msys" else ":") 746 for d in line.strip().split("=")[1].split(pathsep): 747 d = d.strip() 748 if sys.platform == "msys": 749 # On Windows building machine, compiler 750 # returns mixed style path like: 751 # C:\folder1\folder2/folder3/folder4 752 d = convert_mixed_path(d) 753 d = os.path.normpath(d) 754 add_dir_to_list(self.compiler.library_dirs, d) 755 756 tmpfile = os.path.join(self.build_temp, 'wrccpaths') 757 os.makedirs(self.build_temp, exist_ok=True) 758 try: 759 ret = run_command('%s --print-search-dirs >%s' % (CC, tmpfile)) 760 if ret: 761 return 762 with open(tmpfile) as fp: 763 # Parse paths in libraries line. The line is like: 764 # On Linux, "libraries: = path1:path2:path3" 765 # On Windows, "libraries: = path1;path2;path3" 766 for line in fp: 767 if not line.startswith("libraries"): 768 continue 769 add_search_path(line) 770 finally: 771 try: 772 os.unlink(tmpfile) 773 except OSError: 774 pass 775 776 def add_cross_compiling_paths(self): 777 tmpfile = os.path.join(self.build_temp, 'ccpaths') 778 if not os.path.exists(self.build_temp): 779 os.makedirs(self.build_temp) 780 # bpo-38472: With a German locale, GCC returns "gcc-Version 9.1.0 781 # (GCC)", whereas it returns "gcc version 9.1.0" with the C locale. 782 ret = run_command('LC_ALL=C %s -E -v - </dev/null 2>%s 1>/dev/null' % (CC, tmpfile)) 783 is_gcc = False 784 is_clang = False 785 in_incdirs = False 786 try: 787 if ret == 0: 788 with open(tmpfile) as fp: 789 for line in fp.readlines(): 790 if line.startswith("gcc version"): 791 is_gcc = True 792 elif line.startswith("clang version"): 793 is_clang = True 794 elif line.startswith("#include <...>"): 795 in_incdirs = True 796 elif line.startswith("End of search list"): 797 in_incdirs = False 798 elif (is_gcc or is_clang) and line.startswith("LIBRARY_PATH"): 799 for d in line.strip().split("=")[1].split(":"): 800 d = os.path.normpath(d) 801 if '/gcc/' not in d: 802 add_dir_to_list(self.compiler.library_dirs, 803 d) 804 elif (is_gcc or is_clang) and in_incdirs and '/gcc/' not in line and '/clang/' not in line: 805 add_dir_to_list(self.compiler.include_dirs, 806 line.strip()) 807 finally: 808 os.unlink(tmpfile) 809 810 if VXWORKS: 811 self.add_wrcc_search_dirs() 812 813 def add_ldflags_cppflags(self): 814 # Add paths specified in the environment variables LDFLAGS and 815 # CPPFLAGS for header and library files. 816 # We must get the values from the Makefile and not the environment 817 # directly since an inconsistently reproducible issue comes up where 818 # the environment variable is not set even though the value were passed 819 # into configure and stored in the Makefile (issue found on OS X 10.3). 820 for env_var, arg_name, dir_list in ( 821 ('LDFLAGS', '-R', self.compiler.runtime_library_dirs), 822 ('LDFLAGS', '-L', self.compiler.library_dirs), 823 ('CPPFLAGS', '-I', self.compiler.include_dirs)): 824 env_val = sysconfig.get_config_var(env_var) 825 if env_val: 826 parser = argparse.ArgumentParser() 827 parser.add_argument(arg_name, dest="dirs", action="append") 828 829 # To prevent argparse from raising an exception about any 830 # options in env_val that it mistakes for known option, we 831 # strip out all double dashes and any dashes followed by a 832 # character that is not for the option we are dealing with. 833 # 834 # Please note that order of the regex is important! We must 835 # strip out double-dashes first so that we don't end up with 836 # substituting "--Long" to "-Long" and thus lead to "ong" being 837 # used for a library directory. 838 env_val = re.sub(r'(^|\s+)-(-|(?!%s))' % arg_name[1], 839 ' ', env_val) 840 options, _ = parser.parse_known_args(env_val.split()) 841 if options.dirs: 842 for directory in reversed(options.dirs): 843 add_dir_to_list(dir_list, directory) 844 845 def configure_compiler(self): 846 # Ensure that /usr/local is always used, but the local build 847 # directories (i.e. '.' and 'Include') must be first. See issue 848 # 10520. 849 if not CROSS_COMPILING: 850 add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib') 851 add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') 852 # only change this for cross builds for 3.3, issues on Mageia 853 if CROSS_COMPILING: 854 self.add_cross_compiling_paths() 855 self.add_multiarch_paths() 856 self.add_ldflags_cppflags() 857 858 def init_inc_lib_dirs(self): 859 if (not CROSS_COMPILING and 860 os.path.normpath(sys.base_prefix) != '/usr' and 861 not sysconfig.get_config_var('PYTHONFRAMEWORK')): 862 # OSX note: Don't add LIBDIR and INCLUDEDIR to building a framework 863 # (PYTHONFRAMEWORK is set) to avoid # linking problems when 864 # building a framework with different architectures than 865 # the one that is currently installed (issue #7473) 866 add_dir_to_list(self.compiler.library_dirs, 867 sysconfig.get_config_var("LIBDIR")) 868 add_dir_to_list(self.compiler.include_dirs, 869 sysconfig.get_config_var("INCLUDEDIR")) 870 871 system_lib_dirs = ['/lib64', '/usr/lib64', '/lib', '/usr/lib'] 872 system_include_dirs = ['/usr/include'] 873 # lib_dirs and inc_dirs are used to search for files; 874 # if a file is found in one of those directories, it can 875 # be assumed that no additional -I,-L directives are needed. 876 if not CROSS_COMPILING: 877 self.lib_dirs = self.compiler.library_dirs + system_lib_dirs 878 self.inc_dirs = self.compiler.include_dirs + system_include_dirs 879 else: 880 # Add the sysroot paths. 'sysroot' is a compiler option used to 881 # set the logical path of the standard system headers and 882 # libraries. 883 self.lib_dirs = (self.compiler.library_dirs + 884 sysroot_paths(('LDFLAGS', 'CC'), system_lib_dirs)) 885 self.inc_dirs = (self.compiler.include_dirs + 886 sysroot_paths(('CPPFLAGS', 'CFLAGS', 'CC'), 887 system_include_dirs)) 888 889 config_h = sysconfig.get_config_h_filename() 890 with open(config_h) as file: 891 self.config_h_vars = sysconfig.parse_config_h(file) 892 893 # OSF/1 and Unixware have some stuff in /usr/ccs/lib (like -ldb) 894 if HOST_PLATFORM in ['osf1', 'unixware7', 'openunix8']: 895 self.lib_dirs += ['/usr/ccs/lib'] 896 897 # HP-UX11iv3 keeps files in lib/hpux folders. 898 if HOST_PLATFORM == 'hp-ux11': 899 self.lib_dirs += ['/usr/lib/hpux64', '/usr/lib/hpux32'] 900 901 if MACOS: 902 # This should work on any unixy platform ;-) 903 # If the user has bothered specifying additional -I and -L flags 904 # in OPT and LDFLAGS we might as well use them here. 905 # 906 # NOTE: using shlex.split would technically be more correct, but 907 # also gives a bootstrap problem. Let's hope nobody uses 908 # directories with whitespace in the name to store libraries. 909 cflags, ldflags = sysconfig.get_config_vars( 910 'CFLAGS', 'LDFLAGS') 911 for item in cflags.split(): 912 if item.startswith('-I'): 913 self.inc_dirs.append(item[2:]) 914 915 for item in ldflags.split(): 916 if item.startswith('-L'): 917 self.lib_dirs.append(item[2:]) 918 919 def detect_simple_extensions(self): 920 # 921 # The following modules are all pretty straightforward, and compile 922 # on pretty much any POSIXish platform. 923 # 924 925 # array objects 926 self.addext(Extension('array', ['arraymodule.c'])) 927 928 # Context Variables 929 self.addext(Extension('_contextvars', ['_contextvarsmodule.c'])) 930 931 # math library functions, e.g. sin() 932 self.addext(Extension('math', ['mathmodule.c'])) 933 934 # complex math library functions 935 self.addext(Extension('cmath', ['cmathmodule.c'])) 936 937 # libm is needed by delta_new() that uses round() and by accum() that 938 # uses modf(). 939 self.addext(Extension('_datetime', ['_datetimemodule.c'])) 940 self.addext(Extension('_zoneinfo', ['_zoneinfo.c'])) 941 # random number generator implemented in C 942 self.addext(Extension("_random", ["_randommodule.c"])) 943 self.addext(Extension("_bisect", ["_bisectmodule.c"])) 944 self.addext(Extension("_heapq", ["_heapqmodule.c"])) 945 # C-optimized pickle replacement 946 self.addext(Extension("_pickle", ["_pickle.c"])) 947 # _json speedups 948 self.addext(Extension("_json", ["_json.c"])) 949 950 # profiler (_lsprof is for cProfile.py) 951 self.addext(Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c'])) 952 # static Unicode character database 953 self.addext(Extension('unicodedata', ['unicodedata.c'])) 954 self.addext(Extension('_opcode', ['_opcode.c'])) 955 956 # asyncio speedups 957 self.addext(Extension("_asyncio", ["_asynciomodule.c"])) 958 959 self.addext(Extension("_queue", ["_queuemodule.c"])) 960 self.addext(Extension("_statistics", ["_statisticsmodule.c"])) 961 self.addext(Extension("_struct", ["_struct.c"])) 962 self.addext(Extension("_typing", ["_typingmodule.c"])) 963 964 # Modules with some UNIX dependencies -- on by default: 965 # (If you have a really backward UNIX, select and socket may not be 966 # supported...) 967 968 # fcntl(2) and ioctl(2) 969 self.addext(Extension('fcntl', ['fcntlmodule.c'])) 970 # grp(3) 971 self.addext(Extension('grp', ['grpmodule.c'])) 972 973 self.addext(Extension('_socket', ['socketmodule.c'])) 974 self.addext(Extension('spwd', ['spwdmodule.c'])) 975 976 # select(2); not on ancient System V 977 self.addext(Extension('select', ['selectmodule.c'])) 978 979 # Memory-mapped files (also works on Win32). 980 self.addext(Extension('mmap', ['mmapmodule.c'])) 981 982 # Lance Ellinghaus's syslog module 983 # syslog daemon interface 984 self.addext(Extension('syslog', ['syslogmodule.c'])) 985 986 # Python interface to subinterpreter C-API. 987 self.addext(Extension('_xxsubinterpreters', ['_xxsubinterpretersmodule.c'])) 988 989 # 990 # Here ends the simple stuff. From here on, modules need certain 991 # libraries, are platform-specific, or present other surprises. 992 # 993 994 # Multimedia modules 995 # These don't work for 64-bit platforms!!! 996 # These represent audio samples or images as strings: 997 # 998 # Operations on audio samples 999 # According to #993173, this one should actually work fine on 1000 # 64-bit platforms. 1001 # 1002 # audioop needs libm for floor() in multiple functions. 1003 self.addext(Extension('audioop', ['audioop.c'])) 1004 1005 # CSV files 1006 self.addext(Extension('_csv', ['_csv.c'])) 1007 1008 # POSIX subprocess module helper. 1009 self.addext(Extension('_posixsubprocess', ['_posixsubprocess.c'])) 1010 1011 def detect_test_extensions(self): 1012 # Python C API test module 1013 self.addext(Extension('_testcapi', ['_testcapimodule.c'])) 1014 1015 # Python Argument Clinc functional test module 1016 self.addext(Extension('_testclinic', ['_testclinic.c'])) 1017 1018 # Python Internal C API test module 1019 self.addext(Extension('_testinternalcapi', ['_testinternalcapi.c'])) 1020 1021 # Python PEP-3118 (buffer protocol) test module 1022 self.addext(Extension('_testbuffer', ['_testbuffer.c'])) 1023 1024 # Test loading multiple modules from one compiled file (https://bugs.python.org/issue16421) 1025 self.addext(Extension('_testimportmultiple', ['_testimportmultiple.c'])) 1026 1027 # Test multi-phase extension module init (PEP 489) 1028 self.addext(Extension('_testmultiphase', ['_testmultiphase.c'])) 1029 1030 # Fuzz tests. 1031 self.addext(Extension( 1032 '_xxtestfuzz', 1033 ['_xxtestfuzz/_xxtestfuzz.c', '_xxtestfuzz/fuzzer.c'] 1034 )) 1035 1036 def detect_readline_curses(self): 1037 # readline 1038 readline_termcap_library = "" 1039 curses_library = "" 1040 # Cannot use os.popen here in py3k. 1041 tmpfile = os.path.join(self.build_temp, 'readline_termcap_lib') 1042 if not os.path.exists(self.build_temp): 1043 os.makedirs(self.build_temp) 1044 # Determine if readline is already linked against curses or tinfo. 1045 if sysconfig.get_config_var('HAVE_LIBREADLINE'): 1046 if sysconfig.get_config_var('WITH_EDITLINE'): 1047 readline_lib = 'edit' 1048 else: 1049 readline_lib = 'readline' 1050 do_readline = self.compiler.find_library_file(self.lib_dirs, 1051 readline_lib) 1052 if CROSS_COMPILING: 1053 ret = run_command("%s -d %s | grep '(NEEDED)' > %s" 1054 % (sysconfig.get_config_var('READELF'), 1055 do_readline, tmpfile)) 1056 elif find_executable('ldd'): 1057 ret = run_command("ldd %s > %s" % (do_readline, tmpfile)) 1058 else: 1059 ret = 1 1060 if ret == 0: 1061 with open(tmpfile) as fp: 1062 for ln in fp: 1063 if 'curses' in ln: 1064 readline_termcap_library = re.sub( 1065 r'.*lib(n?cursesw?)\.so.*', r'\1', ln 1066 ).rstrip() 1067 break 1068 # termcap interface split out from ncurses 1069 if 'tinfo' in ln: 1070 readline_termcap_library = 'tinfo' 1071 break 1072 if os.path.exists(tmpfile): 1073 os.unlink(tmpfile) 1074 else: 1075 do_readline = False 1076 # Issue 7384: If readline is already linked against curses, 1077 # use the same library for the readline and curses modules. 1078 if 'curses' in readline_termcap_library: 1079 curses_library = readline_termcap_library 1080 elif self.compiler.find_library_file(self.lib_dirs, 'ncursesw'): 1081 curses_library = 'ncursesw' 1082 # Issue 36210: OSS provided ncurses does not link on AIX 1083 # Use IBM supplied 'curses' for successful build of _curses 1084 elif AIX and self.compiler.find_library_file(self.lib_dirs, 'curses'): 1085 curses_library = 'curses' 1086 elif self.compiler.find_library_file(self.lib_dirs, 'ncurses'): 1087 curses_library = 'ncurses' 1088 elif self.compiler.find_library_file(self.lib_dirs, 'curses'): 1089 curses_library = 'curses' 1090 1091 if MACOS: 1092 os_release = int(os.uname()[2].split('.')[0]) 1093 dep_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') 1094 if (dep_target and 1095 (tuple(int(n) for n in dep_target.split('.')[0:2]) 1096 < (10, 5) ) ): 1097 os_release = 8 1098 if os_release < 9: 1099 # MacOSX 10.4 has a broken readline. Don't try to build 1100 # the readline module unless the user has installed a fixed 1101 # readline package 1102 if find_file('readline/rlconf.h', self.inc_dirs, []) is None: 1103 do_readline = False 1104 if do_readline: 1105 readline_libs = [readline_lib] 1106 if readline_termcap_library: 1107 pass # Issue 7384: Already linked against curses or tinfo. 1108 elif curses_library: 1109 readline_libs.append(curses_library) 1110 elif self.compiler.find_library_file(self.lib_dirs + 1111 ['/usr/lib/termcap'], 1112 'termcap'): 1113 readline_libs.append('termcap') 1114 self.add(Extension('readline', ['readline.c'], 1115 library_dirs=['/usr/lib/termcap'], 1116 libraries=readline_libs)) 1117 else: 1118 self.missing.append('readline') 1119 1120 # Curses support, requiring the System V version of curses, often 1121 # provided by the ncurses library. 1122 curses_defines = [] 1123 curses_includes = [] 1124 panel_library = 'panel' 1125 if curses_library == 'ncursesw': 1126 curses_defines.append(('HAVE_NCURSESW', '1')) 1127 if not CROSS_COMPILING: 1128 curses_includes.append('/usr/include/ncursesw') 1129 # Bug 1464056: If _curses.so links with ncursesw, 1130 # _curses_panel.so must link with panelw. 1131 panel_library = 'panelw' 1132 if MACOS: 1133 # On OS X, there is no separate /usr/lib/libncursesw nor 1134 # libpanelw. If we are here, we found a locally-supplied 1135 # version of libncursesw. There should also be a 1136 # libpanelw. _XOPEN_SOURCE defines are usually excluded 1137 # for OS X but we need _XOPEN_SOURCE_EXTENDED here for 1138 # ncurses wide char support 1139 curses_defines.append(('_XOPEN_SOURCE_EXTENDED', '1')) 1140 elif MACOS and curses_library == 'ncurses': 1141 # Building with the system-suppied combined libncurses/libpanel 1142 curses_defines.append(('HAVE_NCURSESW', '1')) 1143 curses_defines.append(('_XOPEN_SOURCE_EXTENDED', '1')) 1144 1145 curses_enabled = True 1146 if curses_library.startswith('ncurses'): 1147 curses_libs = [curses_library] 1148 self.add(Extension('_curses', ['_cursesmodule.c'], 1149 include_dirs=curses_includes, 1150 define_macros=curses_defines, 1151 libraries=curses_libs)) 1152 elif curses_library == 'curses' and not MACOS: 1153 # OSX has an old Berkeley curses, not good enough for 1154 # the _curses module. 1155 if (self.compiler.find_library_file(self.lib_dirs, 'terminfo')): 1156 curses_libs = ['curses', 'terminfo'] 1157 elif (self.compiler.find_library_file(self.lib_dirs, 'termcap')): 1158 curses_libs = ['curses', 'termcap'] 1159 else: 1160 curses_libs = ['curses'] 1161 1162 self.add(Extension('_curses', ['_cursesmodule.c'], 1163 define_macros=curses_defines, 1164 libraries=curses_libs)) 1165 else: 1166 curses_enabled = False 1167 self.missing.append('_curses') 1168 1169 # If the curses module is enabled, check for the panel module 1170 # _curses_panel needs some form of ncurses 1171 skip_curses_panel = True if AIX else False 1172 if (curses_enabled and not skip_curses_panel and 1173 self.compiler.find_library_file(self.lib_dirs, panel_library)): 1174 self.add(Extension('_curses_panel', ['_curses_panel.c'], 1175 include_dirs=curses_includes, 1176 define_macros=curses_defines, 1177 libraries=[panel_library, *curses_libs])) 1178 elif not skip_curses_panel: 1179 self.missing.append('_curses_panel') 1180 1181 def detect_crypt(self): 1182 self.addext(Extension('_crypt', ['_cryptmodule.c'])) 1183 1184 def detect_dbm_gdbm(self): 1185 # Modules that provide persistent dictionary-like semantics. You will 1186 # probably want to arrange for at least one of them to be available on 1187 # your machine, though none are defined by default because of library 1188 # dependencies. The Python module dbm/__init__.py provides an 1189 # implementation independent wrapper for these; dbm/dumb.py provides 1190 # similar functionality (but slower of course) implemented in Python. 1191 1192 dbm_setup_debug = False # verbose debug prints from this script? 1193 dbm_order = ['gdbm'] 1194 1195 # libdb, gdbm and ndbm headers and libraries 1196 have_ndbm_h = sysconfig.get_config_var("HAVE_NDBM_H") 1197 have_gdbm_ndbm_h = sysconfig.get_config_var("HAVE_GDBM_NDBM_H") 1198 have_gdbm_dash_ndbm_h = sysconfig.get_config_var("HAVE_GDBM_DASH_NDBM_H") 1199 have_libndbm = sysconfig.get_config_var("HAVE_LIBNDBM") 1200 have_libgdbm_compat = sysconfig.get_config_var("HAVE_LIBGDBM_COMPAT") 1201 have_libdb = sysconfig.get_config_var("HAVE_LIBDB") 1202 1203 # The standard Unix dbm module: 1204 if not CYGWIN: 1205 config_args = [arg.strip("'") 1206 for arg in sysconfig.get_config_var("CONFIG_ARGS").split()] 1207 dbm_args = [arg for arg in config_args 1208 if arg.startswith('--with-dbmliborder=')] 1209 if dbm_args: 1210 dbm_order = [arg.split('=')[-1] for arg in dbm_args][-1].split(":") 1211 else: 1212 dbm_order = "gdbm:ndbm:bdb".split(":") 1213 dbmext = None 1214 for cand in dbm_order: 1215 if cand == "ndbm": 1216 if have_ndbm_h: 1217 # Some systems have -lndbm, others have -lgdbm_compat, 1218 # others don't have either 1219 if have_libndbm: 1220 ndbm_libs = ['ndbm'] 1221 elif have_libgdbm_compat: 1222 ndbm_libs = ['gdbm_compat'] 1223 else: 1224 ndbm_libs = [] 1225 if dbm_setup_debug: print("building dbm using ndbm") 1226 dbmext = Extension( 1227 '_dbm', ['_dbmmodule.c'], 1228 define_macros=[('USE_NDBM', None)], 1229 libraries=ndbm_libs 1230 ) 1231 break 1232 elif cand == "gdbm": 1233 # dbm_open() is provided by libgdbm_compat, which wraps libgdbm 1234 if have_libgdbm_compat and (have_gdbm_ndbm_h or have_gdbm_dash_ndbm_h): 1235 if dbm_setup_debug: print("building dbm using gdbm") 1236 dbmext = Extension( 1237 '_dbm', ['_dbmmodule.c'], 1238 define_macros=[('USE_GDBM_COMPAT', None)], 1239 libraries=['gdbm_compat'] 1240 ) 1241 break 1242 elif cand == "bdb": 1243 if have_libdb: 1244 if dbm_setup_debug: print("building dbm using bdb") 1245 dbmext = Extension( 1246 '_dbm', ['_dbmmodule.c'], 1247 define_macros=[('USE_BERKDB', None)], 1248 libraries=['db'] 1249 ) 1250 break 1251 if dbmext is not None: 1252 self.add(dbmext) 1253 else: 1254 self.missing.append('_dbm') 1255 1256 # Anthony Baxter's gdbm module. GNU dbm(3) will require -lgdbm: 1257 self.addext(Extension('_gdbm', ['_gdbmmodule.c'])) 1258 1259 def detect_sqlite(self): 1260 sources = [ 1261 "_sqlite/blob.c", 1262 "_sqlite/connection.c", 1263 "_sqlite/cursor.c", 1264 "_sqlite/microprotocols.c", 1265 "_sqlite/module.c", 1266 "_sqlite/prepare_protocol.c", 1267 "_sqlite/row.c", 1268 "_sqlite/statement.c", 1269 "_sqlite/util.c", 1270 ] 1271 self.addext(Extension("_sqlite3", sources=sources)) 1272 1273 def detect_platform_specific_exts(self): 1274 # Unix-only modules 1275 # Steen Lumholt's termios module 1276 self.addext(Extension('termios', ['termios.c'])) 1277 # Jeremy Hylton's rlimit interface 1278 self.addext(Extension('resource', ['resource.c'])) 1279 # linux/soundcard.h or sys/soundcard.h 1280 self.addext(Extension('ossaudiodev', ['ossaudiodev.c'])) 1281 1282 # macOS-only, needs SystemConfiguration and CoreFoundation framework 1283 self.addext(Extension('_scproxy', ['_scproxy.c'])) 1284 1285 def detect_compress_exts(self): 1286 # Andrew Kuchling's zlib module. 1287 self.addext(Extension('zlib', ['zlibmodule.c'])) 1288 1289 # Helper module for various ascii-encoders. Uses zlib for an optimized 1290 # crc32 if we have it. Otherwise binascii uses its own. 1291 self.addext(Extension('binascii', ['binascii.c'])) 1292 1293 # Gustavo Niemeyer's bz2 module. 1294 self.addext(Extension('_bz2', ['_bz2module.c'])) 1295 1296 # LZMA compression support. 1297 self.addext(Extension('_lzma', ['_lzmamodule.c'])) 1298 1299 def detect_expat_elementtree(self): 1300 # Interface to the Expat XML parser 1301 # 1302 # Expat was written by James Clark and is now maintained by a group of 1303 # developers on SourceForge; see www.libexpat.org for more information. 1304 # The pyexpat module was written by Paul Prescod after a prototype by 1305 # Jack Jansen. The Expat source is included in Modules/expat/. Usage 1306 # of a system shared libexpat.so is possible with --with-system-expat 1307 # configure option. 1308 # 1309 # More information on Expat can be found at www.libexpat.org. 1310 # 1311 self.addext(Extension('pyexpat', sources=['pyexpat.c'])) 1312 1313 # Fredrik Lundh's cElementTree module. Note that this also 1314 # uses expat (via the CAPI hook in pyexpat). 1315 self.addext(Extension('_elementtree', sources=['_elementtree.c'])) 1316 1317 def detect_multibytecodecs(self): 1318 # Hye-Shik Chang's CJKCodecs modules. 1319 self.addext(Extension('_multibytecodec', 1320 ['cjkcodecs/multibytecodec.c'])) 1321 for loc in ('kr', 'jp', 'cn', 'tw', 'hk', 'iso2022'): 1322 self.addext(Extension( 1323 f'_codecs_{loc}', [f'cjkcodecs/_codecs_{loc}.c'] 1324 )) 1325 1326 def detect_multiprocessing(self): 1327 # Richard Oudkerk's multiprocessing module 1328 multiprocessing_srcs = ['_multiprocessing/multiprocessing.c'] 1329 if ( 1330 sysconfig.get_config_var('HAVE_SEM_OPEN') and not 1331 sysconfig.get_config_var('POSIX_SEMAPHORES_NOT_ENABLED') 1332 ): 1333 multiprocessing_srcs.append('_multiprocessing/semaphore.c') 1334 self.addext(Extension('_multiprocessing', multiprocessing_srcs)) 1335 self.addext(Extension('_posixshmem', ['_multiprocessing/posixshmem.c'])) 1336 1337 def detect_uuid(self): 1338 # Build the _uuid module if possible 1339 self.addext(Extension('_uuid', ['_uuidmodule.c'])) 1340 1341 def detect_modules(self): 1342 # remove dummy extension 1343 self.extensions = [] 1344 1345 # Some C extensions are built by entries in Modules/Setup.bootstrap. 1346 # These are extensions are required to bootstrap the interpreter or 1347 # build process. 1348 self.detect_simple_extensions() 1349 self.detect_test_extensions() 1350 self.detect_readline_curses() 1351 self.detect_crypt() 1352 self.detect_openssl_hashlib() 1353 self.detect_hash_builtins() 1354 self.detect_dbm_gdbm() 1355 self.detect_sqlite() 1356 self.detect_platform_specific_exts() 1357 self.detect_nis() 1358 self.detect_compress_exts() 1359 self.detect_expat_elementtree() 1360 self.detect_multibytecodecs() 1361 self.detect_decimal() 1362 self.detect_ctypes() 1363 self.detect_multiprocessing() 1364 self.detect_tkinter() 1365 self.detect_uuid() 1366 1367 # Uncomment the next line if you want to play with xxmodule.c 1368# self.add(Extension('xx', ['xxmodule.c'])) 1369 1370 self.addext(Extension('xxlimited', ['xxlimited.c'])) 1371 self.addext(Extension('xxlimited_35', ['xxlimited_35.c'])) 1372 1373 def detect_tkinter(self): 1374 self.addext(Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'])) 1375 1376 def configure_ctypes(self, ext): 1377 return True 1378 1379 def detect_ctypes(self): 1380 # Thomas Heller's _ctypes module 1381 1382 if (not sysconfig.get_config_var("LIBFFI_INCLUDEDIR") and MACOS): 1383 self.use_system_libffi = True 1384 else: 1385 self.use_system_libffi = '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS") 1386 1387 include_dirs = [] 1388 extra_compile_args = [] 1389 extra_link_args = [] 1390 sources = ['_ctypes/_ctypes.c', 1391 '_ctypes/callbacks.c', 1392 '_ctypes/callproc.c', 1393 '_ctypes/stgdict.c', 1394 '_ctypes/cfield.c'] 1395 1396 if MACOS: 1397 sources.append('_ctypes/malloc_closure.c') 1398 extra_compile_args.append('-DUSING_MALLOC_CLOSURE_DOT_C=1') 1399 extra_compile_args.append('-DMACOSX') 1400 include_dirs.append('_ctypes/darwin') 1401 1402 elif HOST_PLATFORM == 'sunos5': 1403 # XXX This shouldn't be necessary; it appears that some 1404 # of the assembler code is non-PIC (i.e. it has relocations 1405 # when it shouldn't. The proper fix would be to rewrite 1406 # the assembler code to be PIC. 1407 # This only works with GCC; the Sun compiler likely refuses 1408 # this option. If you want to compile ctypes with the Sun 1409 # compiler, please research a proper solution, instead of 1410 # finding some -z option for the Sun compiler. 1411 extra_link_args.append('-mimpure-text') 1412 1413 ext = Extension('_ctypes', 1414 include_dirs=include_dirs, 1415 extra_compile_args=extra_compile_args, 1416 extra_link_args=extra_link_args, 1417 libraries=[], 1418 sources=sources) 1419 self.add(ext) 1420 # function my_sqrt() needs libm for sqrt() 1421 self.addext(Extension('_ctypes_test', ['_ctypes/_ctypes_test.c'])) 1422 1423 ffi_inc = sysconfig.get_config_var("LIBFFI_INCLUDEDIR") 1424 ffi_lib = None 1425 1426 ffi_inc_dirs = self.inc_dirs.copy() 1427 if MACOS: 1428 ffi_in_sdk = os.path.join(macosx_sdk_root(), "usr/include/ffi") 1429 1430 if not ffi_inc: 1431 if os.path.exists(ffi_in_sdk): 1432 ext.extra_compile_args.append("-DUSING_APPLE_OS_LIBFFI=1") 1433 ffi_inc = ffi_in_sdk 1434 ffi_lib = 'ffi' 1435 else: 1436 # OS X 10.5 comes with libffi.dylib; the include files are 1437 # in /usr/include/ffi 1438 ffi_inc_dirs.append('/usr/include/ffi') 1439 1440 if not ffi_inc: 1441 found = find_file('ffi.h', [], ffi_inc_dirs) 1442 if found: 1443 ffi_inc = found[0] 1444 if ffi_inc: 1445 ffi_h = ffi_inc + '/ffi.h' 1446 if not os.path.exists(ffi_h): 1447 ffi_inc = None 1448 print('Header file {} does not exist'.format(ffi_h)) 1449 if ffi_lib is None and ffi_inc: 1450 for lib_name in ('ffi', 'ffi_pic'): 1451 if (self.compiler.find_library_file(self.lib_dirs, lib_name)): 1452 ffi_lib = lib_name 1453 break 1454 1455 if ffi_inc and ffi_lib: 1456 ffi_headers = glob(os.path.join(ffi_inc, '*.h')) 1457 if grep_headers_for('ffi_prep_cif_var', ffi_headers): 1458 ext.extra_compile_args.append("-DHAVE_FFI_PREP_CIF_VAR=1") 1459 if grep_headers_for('ffi_prep_closure_loc', ffi_headers): 1460 ext.extra_compile_args.append("-DHAVE_FFI_PREP_CLOSURE_LOC=1") 1461 if grep_headers_for('ffi_closure_alloc', ffi_headers): 1462 ext.extra_compile_args.append("-DHAVE_FFI_CLOSURE_ALLOC=1") 1463 1464 ext.include_dirs.append(ffi_inc) 1465 ext.libraries.append(ffi_lib) 1466 self.use_system_libffi = True 1467 1468 if sysconfig.get_config_var('HAVE_LIBDL'): 1469 # for dlopen, see bpo-32647 1470 ext.libraries.append('dl') 1471 1472 def detect_decimal(self): 1473 # Stefan Krah's _decimal module 1474 self.addext( 1475 Extension( 1476 '_decimal', 1477 ['_decimal/_decimal.c'], 1478 # Uncomment for extra functionality: 1479 # define_macros=[('EXTRA_FUNCTIONALITY', 1)] 1480 ) 1481 ) 1482 1483 def detect_openssl_hashlib(self): 1484 self.addext(Extension('_ssl', ['_ssl.c'])) 1485 self.addext(Extension('_hashlib', ['_hashopenssl.c'])) 1486 1487 def detect_hash_builtins(self): 1488 # By default we always compile these even when OpenSSL is available 1489 # (issue #14693). It's harmless and the object code is tiny 1490 # (40-50 KiB per module, only loaded when actually used). Modules can 1491 # be disabled via the --with-builtin-hashlib-hashes configure flag. 1492 1493 self.addext(Extension('_md5', ['md5module.c'])) 1494 self.addext(Extension('_sha1', ['sha1module.c'])) 1495 self.addext(Extension('_sha256', ['sha256module.c'])) 1496 self.addext(Extension('_sha512', ['sha512module.c'])) 1497 self.addext(Extension('_sha3', ['_sha3/sha3module.c'])) 1498 self.addext(Extension('_blake2', 1499 [ 1500 '_blake2/blake2module.c', 1501 '_blake2/blake2b_impl.c', 1502 '_blake2/blake2s_impl.c' 1503 ] 1504 )) 1505 1506 def detect_nis(self): 1507 self.addext(Extension('nis', ['nismodule.c'])) 1508 1509 1510class PyBuildInstall(install): 1511 # Suppress the warning about installation into the lib_dynload 1512 # directory, which is not in sys.path when running Python during 1513 # installation: 1514 def initialize_options (self): 1515 install.initialize_options(self) 1516 self.warn_dir=0 1517 1518 # Customize subcommands to not install an egg-info file for Python 1519 sub_commands = [('install_lib', install.has_lib), 1520 ('install_headers', install.has_headers), 1521 ('install_scripts', install.has_scripts), 1522 ('install_data', install.has_data)] 1523 1524 1525class PyBuildInstallLib(install_lib): 1526 # Do exactly what install_lib does but make sure correct access modes get 1527 # set on installed directories and files. All installed files with get 1528 # mode 644 unless they are a shared library in which case they will get 1529 # mode 755. All installed directories will get mode 755. 1530 1531 # this is works for EXT_SUFFIX too, which ends with SHLIB_SUFFIX 1532 shlib_suffix = sysconfig.get_config_var("SHLIB_SUFFIX") 1533 1534 def install(self): 1535 outfiles = install_lib.install(self) 1536 self.set_file_modes(outfiles, 0o644, 0o755) 1537 self.set_dir_modes(self.install_dir, 0o755) 1538 return outfiles 1539 1540 def set_file_modes(self, files, defaultMode, sharedLibMode): 1541 if not files: return 1542 1543 for filename in files: 1544 if os.path.islink(filename): continue 1545 mode = defaultMode 1546 if filename.endswith(self.shlib_suffix): mode = sharedLibMode 1547 log.info("changing mode of %s to %o", filename, mode) 1548 if not self.dry_run: os.chmod(filename, mode) 1549 1550 def set_dir_modes(self, dirname, mode): 1551 for dirpath, dirnames, fnames in os.walk(dirname): 1552 if os.path.islink(dirpath): 1553 continue 1554 log.info("changing mode of %s to %o", dirpath, mode) 1555 if not self.dry_run: os.chmod(dirpath, mode) 1556 1557 1558class PyBuildScripts(build_scripts): 1559 def copy_scripts(self): 1560 outfiles, updated_files = build_scripts.copy_scripts(self) 1561 fullversion = '-{0[0]}.{0[1]}'.format(sys.version_info) 1562 minoronly = '.{0[1]}'.format(sys.version_info) 1563 newoutfiles = [] 1564 newupdated_files = [] 1565 for filename in outfiles: 1566 if filename.endswith('2to3'): 1567 newfilename = filename + fullversion 1568 else: 1569 newfilename = filename + minoronly 1570 log.info(f'renaming {filename} to {newfilename}') 1571 os.rename(filename, newfilename) 1572 newoutfiles.append(newfilename) 1573 if filename in updated_files: 1574 newupdated_files.append(newfilename) 1575 return newoutfiles, newupdated_files 1576 1577 1578def main(): 1579 global LIST_MODULE_NAMES 1580 1581 if "--list-module-names" in sys.argv: 1582 LIST_MODULE_NAMES = True 1583 sys.argv.remove("--list-module-names") 1584 1585 set_compiler_flags('CFLAGS', 'PY_CFLAGS_NODIST') 1586 set_compiler_flags('LDFLAGS', 'PY_LDFLAGS_NODIST') 1587 1588 class DummyProcess: 1589 """Hack for parallel build""" 1590 ProcessPoolExecutor = None 1591 1592 sys.modules['concurrent.futures.process'] = DummyProcess 1593 validate_tzpath() 1594 1595 # turn off warnings when deprecated modules are imported 1596 import warnings 1597 warnings.filterwarnings("ignore",category=DeprecationWarning) 1598 setup(# PyPI Metadata (PEP 301) 1599 name = "Python", 1600 version = sys.version.split()[0], 1601 url = "https://www.python.org/%d.%d" % sys.version_info[:2], 1602 maintainer = "Guido van Rossum and the Python community", 1603 maintainer_email = "[email protected]", 1604 description = "A high-level object-oriented programming language", 1605 long_description = SUMMARY.strip(), 1606 license = "PSF license", 1607 classifiers = [x for x in CLASSIFIERS.split("\n") if x], 1608 platforms = ["Many"], 1609 1610 # Build info 1611 cmdclass = {'build_ext': PyBuildExt, 1612 'build_scripts': PyBuildScripts, 1613 'install': PyBuildInstall, 1614 'install_lib': PyBuildInstallLib}, 1615 # A dummy module is defined here, because build_ext won't be 1616 # called unless there's at least one extension module defined. 1617 ext_modules=[Extension('_dummy', ['_dummy.c'])], 1618 1619 # If you change the scripts installed here, you also need to 1620 # check the PyBuildScripts command above, and change the links 1621 # created by the bininstall target in Makefile.pre.in 1622 scripts = ["Tools/scripts/pydoc3", "Tools/scripts/idle3", 1623 "Tools/scripts/2to3"] 1624 ) 1625 1626# --install-platlib 1627if __name__ == '__main__': 1628 main() 1629