codekingpro/portable-devtools
114k
1"""distutils.ccompiler2 3Contains CCompiler, an abstract base class that defines the interface4for the Distutils compiler abstraction model."""5 6import os7import re8import sys9import warnings10 11from ._itertools import always_iterable12from ._log import log13from ._modified import newer_group14from .dir_util import mkpath15from .errors import (16 CompileError,17 DistutilsModuleError,18 DistutilsPlatformError,19 LinkError,20 UnknownFileError,21)22from .file_util import move_file23from .spawn import spawn24from .util import execute, split_quoted25 26 27class CCompiler:28 """Abstract base class to define the interface that must be implemented29 by real compiler classes. Also has some utility methods used by30 several compiler classes.31 32 The basic idea behind a compiler abstraction class is that each33 instance can be used for all the compile/link steps in building a34 single project. Thus, attributes common to all of those compile and35 link steps -- include directories, macros to define, libraries to link36 against, etc. -- are attributes of the compiler instance. To allow for37 variability in how individual files are treated, most of those38 attributes may be varied on a per-compilation or per-link basis.39 """40 41 # 'compiler_type' is a class attribute that identifies this class. It42 # keeps code that wants to know what kind of compiler it's dealing with43 # from having to import all possible compiler classes just to do an44 # 'isinstance'. In concrete CCompiler subclasses, 'compiler_type'45 # should really, really be one of the keys of the 'compiler_class'46 # dictionary (see below -- used by the 'new_compiler()' factory47 # function) -- authors of new compiler interface classes are48 # responsible for updating 'compiler_class'!49 compiler_type = None50 51 # XXX things not handled by this compiler abstraction model:52 # * client can't provide additional options for a compiler,53 # e.g. warning, optimization, debugging flags. Perhaps this54 # should be the domain of concrete compiler abstraction classes55 # (UnixCCompiler, MSVCCompiler, etc.) -- or perhaps the base56 # class should have methods for the common ones.57 # * can't completely override the include or library searchg58 # path, ie. no "cc -I -Idir1 -Idir2" or "cc -L -Ldir1 -Ldir2".59 # I'm not sure how widely supported this is even by Unix60 # compilers, much less on other platforms. And I'm even less61 # sure how useful it is; maybe for cross-compiling, but62 # support for that is a ways off. (And anyways, cross63 # compilers probably have a dedicated binary with the64 # right paths compiled in. I hope.)65 # * can't do really freaky things with the library list/library66 # dirs, e.g. "-Ldir1 -lfoo -Ldir2 -lfoo" to link against67 # different versions of libfoo.a in different locations. I68 # think this is useless without the ability to null out the69 # library search path anyways.70 71 # Subclasses that rely on the standard filename generation methods72 # implemented below should override these; see the comment near73 # those methods ('object_filenames()' et. al.) for details:74 src_extensions = None # list of strings75 obj_extension = None # string76 static_lib_extension = None77 shared_lib_extension = None # string78 static_lib_format = None # format string79 shared_lib_format = None # prob. same as static_lib_format80 exe_extension = None # string81 82 # Default language settings. language_map is used to detect a source83 # file or Extension target language, checking source filenames.84 # language_order is used to detect the language precedence, when deciding85 # what language to use when mixing source types. For example, if some86 # extension has two files with ".c" extension, and one with ".cpp", it87 # is still linked as c++.88 language_map = {89 ".c": "c",90 ".cc": "c++",91 ".cpp": "c++",92 ".cxx": "c++",93 ".m": "objc",94 }95 language_order = ["c++", "objc", "c"]96 97 include_dirs = []98 """99 include dirs specific to this compiler class100 """101 102 library_dirs = []103 """104 library dirs specific to this compiler class105 """106 107 def __init__(self, verbose=0, dry_run=0, force=0):108 self.dry_run = dry_run109 self.force = force110 self.verbose = verbose111 112 # 'output_dir': a common output directory for object, library,113 # shared object, and shared library files114 self.output_dir = None115 116 # 'macros': a list of macro definitions (or undefinitions). A117 # macro definition is a 2-tuple (name, value), where the value is118 # either a string or None (no explicit value). A macro119 # undefinition is a 1-tuple (name,).120 self.macros = []121 122 # 'include_dirs': a list of directories to search for include files123 self.include_dirs = []124 125 # 'libraries': a list of libraries to include in any link126 # (library names, not filenames: eg. "foo" not "libfoo.a")127 self.libraries = []128 129 # 'library_dirs': a list of directories to search for libraries130 self.library_dirs = []131 132 # 'runtime_library_dirs': a list of directories to search for133 # shared libraries/objects at runtime134 self.runtime_library_dirs = []135 136 # 'objects': a list of object files (or similar, such as explicitly137 # named library files) to include on any link138 self.objects = []139 140 for key in self.executables.keys():141 self.set_executable(key, self.executables[key])142 143 def set_executables(self, **kwargs):144 """Define the executables (and options for them) that will be run145 to perform the various stages of compilation. The exact set of146 executables that may be specified here depends on the compiler147 class (via the 'executables' class attribute), but most will have:148 compiler the C/C++ compiler149 linker_so linker used to create shared objects and libraries150 linker_exe linker used to create binary executables151 archiver static library creator152 153 On platforms with a command-line (Unix, DOS/Windows), each of these154 is a string that will be split into executable name and (optional)155 list of arguments. (Splitting the string is done similarly to how156 Unix shells operate: words are delimited by spaces, but quotes and157 backslashes can override this. See158 'distutils.util.split_quoted()'.)159 """160 161 # Note that some CCompiler implementation classes will define class162 # attributes 'cpp', 'cc', etc. with hard-coded executable names;163 # this is appropriate when a compiler class is for exactly one164 # compiler/OS combination (eg. MSVCCompiler). Other compiler165 # classes (UnixCCompiler, in particular) are driven by information166 # discovered at run-time, since there are many different ways to do167 # basically the same things with Unix C compilers.168 169 for key in kwargs:170 if key not in self.executables:171 raise ValueError(172 f"unknown executable '{key}' for class {self.__class__.__name__}"173 )174 self.set_executable(key, kwargs[key])175 176 def set_executable(self, key, value):177 if isinstance(value, str):178 setattr(self, key, split_quoted(value))179 else:180 setattr(self, key, value)181 182 def _find_macro(self, name):183 i = 0184 for defn in self.macros:185 if defn[0] == name:186 return i187 i += 1188 return None189 190 def _check_macro_definitions(self, definitions):191 """Ensures that every element of 'definitions' is a valid macro192 definition, ie. either (name,value) 2-tuple or a (name,) tuple. Do193 nothing if all definitions are OK, raise TypeError otherwise.194 """195 for defn in definitions:196 if not (197 isinstance(defn, tuple)198 and (199 len(defn) in (1, 2)200 and (isinstance(defn[1], str) or defn[1] is None)201 )202 and isinstance(defn[0], str)203 ):204 raise TypeError(205 ("invalid macro definition '%s': " % defn)206 + "must be tuple (string,), (string, string), or "207 + "(string, None)"208 )209 210 # -- Bookkeeping methods -------------------------------------------211 212 def define_macro(self, name, value=None):213 """Define a preprocessor macro for all compilations driven by this214 compiler object. The optional parameter 'value' should be a215 string; if it is not supplied, then the macro will be defined216 without an explicit value and the exact outcome depends on the217 compiler used (XXX true? does ANSI say anything about this?)218 """219 # Delete from the list of macro definitions/undefinitions if220 # already there (so that this one will take precedence).221 i = self._find_macro(name)222 if i is not None:223 del self.macros[i]224 225 self.macros.append((name, value))226 227 def undefine_macro(self, name):228 """Undefine a preprocessor macro for all compilations driven by229 this compiler object. If the same macro is defined by230 'define_macro()' and undefined by 'undefine_macro()' the last call231 takes precedence (including multiple redefinitions or232 undefinitions). If the macro is redefined/undefined on a233 per-compilation basis (ie. in the call to 'compile()'), then that234 takes precedence.235 """236 # Delete from the list of macro definitions/undefinitions if237 # already there (so that this one will take precedence).238 i = self._find_macro(name)239 if i is not None:240 del self.macros[i]241 242 undefn = (name,)243 self.macros.append(undefn)244 245 def add_include_dir(self, dir):246 """Add 'dir' to the list of directories that will be searched for247 header files. The compiler is instructed to search directories in248 the order in which they are supplied by successive calls to249 'add_include_dir()'.250 """251 self.include_dirs.append(dir)252 253 def set_include_dirs(self, dirs):254 """Set the list of directories that will be searched to 'dirs' (a255 list of strings). Overrides any preceding calls to256 'add_include_dir()'; subsequence calls to 'add_include_dir()' add257 to the list passed to 'set_include_dirs()'. This does not affect258 any list of standard include directories that the compiler may259 search by default.260 """261 self.include_dirs = dirs[:]262 263 def add_library(self, libname):264 """Add 'libname' to the list of libraries that will be included in265 all links driven by this compiler object. Note that 'libname'266 should *not* be the name of a file containing a library, but the267 name of the library itself: the actual filename will be inferred by268 the linker, the compiler, or the compiler class (depending on the269 platform).270 271 The linker will be instructed to link against libraries in the272 order they were supplied to 'add_library()' and/or273 'set_libraries()'. It is perfectly valid to duplicate library274 names; the linker will be instructed to link against libraries as275 many times as they are mentioned.276 """277 self.libraries.append(libname)278 279 def set_libraries(self, libnames):280 """Set the list of libraries to be included in all links driven by281 this compiler object to 'libnames' (a list of strings). This does282 not affect any standard system libraries that the linker may283 include by default.284 """285 self.libraries = libnames[:]286 287 def add_library_dir(self, dir):288 """Add 'dir' to the list of directories that will be searched for289 libraries specified to 'add_library()' and 'set_libraries()'. The290 linker will be instructed to search for libraries in the order they291 are supplied to 'add_library_dir()' and/or 'set_library_dirs()'.292 """293 self.library_dirs.append(dir)294 295 def set_library_dirs(self, dirs):296 """Set the list of library search directories to 'dirs' (a list of297 strings). This does not affect any standard library search path298 that the linker may search by default.299 """300 self.library_dirs = dirs[:]301 302 def add_runtime_library_dir(self, dir):303 """Add 'dir' to the list of directories that will be searched for304 shared libraries at runtime.305 """306 self.runtime_library_dirs.append(dir)307 308 def set_runtime_library_dirs(self, dirs):309 """Set the list of directories to search for shared libraries at310 runtime to 'dirs' (a list of strings). This does not affect any311 standard search path that the runtime linker may search by312 default.313 """314 self.runtime_library_dirs = dirs[:]315 316 def add_link_object(self, object):317 """Add 'object' to the list of object files (or analogues, such as318 explicitly named library files or the output of "resource319 compilers") to be included in every link driven by this compiler320 object.321 """322 self.objects.append(object)323 324 def set_link_objects(self, objects):325 """Set the list of object files (or analogues) to be included in326 every link to 'objects'. This does not affect any standard object327 files that the linker may include by default (such as system328 libraries).329 """330 self.objects = objects[:]331 332 # -- Private utility methods --------------------------------------333 # (here for the convenience of subclasses)334 335 # Helper method to prep compiler in subclass compile() methods336 337 def _setup_compile(self, outdir, macros, incdirs, sources, depends, extra):338 """Process arguments and decide which source files to compile."""339 outdir, macros, incdirs = self._fix_compile_args(outdir, macros, incdirs)340 341 if extra is None:342 extra = []343 344 # Get the list of expected output (object) files345 objects = self.object_filenames(sources, strip_dir=0, output_dir=outdir)346 assert len(objects) == len(sources)347 348 pp_opts = gen_preprocess_options(macros, incdirs)349 350 build = {}351 for i in range(len(sources)):352 src = sources[i]353 obj = objects[i]354 ext = os.path.splitext(src)[1]355 self.mkpath(os.path.dirname(obj))356 build[obj] = (src, ext)357 358 return macros, objects, extra, pp_opts, build359 360 def _get_cc_args(self, pp_opts, debug, before):361 # works for unixccompiler, cygwinccompiler362 cc_args = pp_opts + ['-c']363 if debug:364 cc_args[:0] = ['-g']365 if before:366 cc_args[:0] = before367 return cc_args368 369 def _fix_compile_args(self, output_dir, macros, include_dirs):370 """Typecheck and fix-up some of the arguments to the 'compile()'371 method, and return fixed-up values. Specifically: if 'output_dir'372 is None, replaces it with 'self.output_dir'; ensures that 'macros'373 is a list, and augments it with 'self.macros'; ensures that374 'include_dirs' is a list, and augments it with 'self.include_dirs'.375 Guarantees that the returned values are of the correct type,376 i.e. for 'output_dir' either string or None, and for 'macros' and377 'include_dirs' either list or None.378 """379 if output_dir is None:380 output_dir = self.output_dir381 elif not isinstance(output_dir, str):382 raise TypeError("'output_dir' must be a string or None")383 384 if macros is None:385 macros = list(self.macros)386 elif isinstance(macros, list):387 macros = macros + (self.macros or [])388 else:389 raise TypeError("'macros' (if supplied) must be a list of tuples")390 391 if include_dirs is None:392 include_dirs = list(self.include_dirs)393 elif isinstance(include_dirs, (list, tuple)):394 include_dirs = list(include_dirs) + (self.include_dirs or [])395 else:396 raise TypeError("'include_dirs' (if supplied) must be a list of strings")397 398 # add include dirs for class399 include_dirs += self.__class__.include_dirs400 401 return output_dir, macros, include_dirs402 403 def _prep_compile(self, sources, output_dir, depends=None):404 """Decide which source files must be recompiled.405 406 Determine the list of object files corresponding to 'sources',407 and figure out which ones really need to be recompiled.408 Return a list of all object files and a dictionary telling409 which source files can be skipped.410 """411 # Get the list of expected output (object) files412 objects = self.object_filenames(sources, output_dir=output_dir)413 assert len(objects) == len(sources)414 415 # Return an empty dict for the "which source files can be skipped"416 # return value to preserve API compatibility.417 return objects, {}418 419 def _fix_object_args(self, objects, output_dir):420 """Typecheck and fix up some arguments supplied to various methods.421 Specifically: ensure that 'objects' is a list; if output_dir is422 None, replace with self.output_dir. Return fixed versions of423 'objects' and 'output_dir'.424 """425 if not isinstance(objects, (list, tuple)):426 raise TypeError("'objects' must be a list or tuple of strings")427 objects = list(objects)428 429 if output_dir is None:430 output_dir = self.output_dir431 elif not isinstance(output_dir, str):432 raise TypeError("'output_dir' must be a string or None")433 434 return (objects, output_dir)435 436 def _fix_lib_args(self, libraries, library_dirs, runtime_library_dirs):437 """Typecheck and fix up some of the arguments supplied to the438 'link_*' methods. Specifically: ensure that all arguments are439 lists, and augment them with their permanent versions440 (eg. 'self.libraries' augments 'libraries'). Return a tuple with441 fixed versions of all arguments.442 """443 if libraries is None:444 libraries = list(self.libraries)445 elif isinstance(libraries, (list, tuple)):446 libraries = list(libraries) + (self.libraries or [])447 else:448 raise TypeError("'libraries' (if supplied) must be a list of strings")449 450 if library_dirs is None:451 library_dirs = list(self.library_dirs)452 elif isinstance(library_dirs, (list, tuple)):453 library_dirs = list(library_dirs) + (self.library_dirs or [])454 else:455 raise TypeError("'library_dirs' (if supplied) must be a list of strings")456 457 # add library dirs for class458 library_dirs += self.__class__.library_dirs459 460 if runtime_library_dirs is None:461 runtime_library_dirs = list(self.runtime_library_dirs)462 elif isinstance(runtime_library_dirs, (list, tuple)):463 runtime_library_dirs = list(runtime_library_dirs) + (464 self.runtime_library_dirs or []465 )466 else:467 raise TypeError(468 "'runtime_library_dirs' (if supplied) must be a list of strings"469 )470 471 return (libraries, library_dirs, runtime_library_dirs)472 473 def _need_link(self, objects, output_file):474 """Return true if we need to relink the files listed in 'objects'475 to recreate 'output_file'.476 """477 if self.force:478 return True479 else:480 if self.dry_run:481 newer = newer_group(objects, output_file, missing='newer')482 else:483 newer = newer_group(objects, output_file)484 return newer485 486 def detect_language(self, sources):487 """Detect the language of a given file, or list of files. Uses488 language_map, and language_order to do the job.489 """490 if not isinstance(sources, list):491 sources = [sources]492 lang = None493 index = len(self.language_order)494 for source in sources:495 base, ext = os.path.splitext(source)496 extlang = self.language_map.get(ext)497 try:498 extindex = self.language_order.index(extlang)499 if extindex < index:500 lang = extlang501 index = extindex502 except ValueError:503 pass504 return lang505 506 # -- Worker methods ------------------------------------------------507 # (must be implemented by subclasses)508 509 def preprocess(510 self,511 source,512 output_file=None,513 macros=None,514 include_dirs=None,515 extra_preargs=None,516 extra_postargs=None,517 ):518 """Preprocess a single C/C++ source file, named in 'source'.519 Output will be written to file named 'output_file', or stdout if520 'output_file' not supplied. 'macros' is a list of macro521 definitions as for 'compile()', which will augment the macros set522 with 'define_macro()' and 'undefine_macro()'. 'include_dirs' is a523 list of directory names that will be added to the default list.524 525 Raises PreprocessError on failure.526 """527 pass528 529 def compile(530 self,531 sources,532 output_dir=None,533 macros=None,534 include_dirs=None,535 debug=0,536 extra_preargs=None,537 extra_postargs=None,538 depends=None,539 ):540 """Compile one or more source files.541 542 'sources' must be a list of filenames, most likely C/C++543 files, but in reality anything that can be handled by a544 particular compiler and compiler class (eg. MSVCCompiler can545 handle resource files in 'sources'). Return a list of object546 filenames, one per source filename in 'sources'. Depending on547 the implementation, not all source files will necessarily be548 compiled, but all corresponding object filenames will be549 returned.550 551 If 'output_dir' is given, object files will be put under it, while552 retaining their original path component. That is, "foo/bar.c"553 normally compiles to "foo/bar.o" (for a Unix implementation); if554 'output_dir' is "build", then it would compile to555 "build/foo/bar.o".556 557 'macros', if given, must be a list of macro definitions. A macro558 definition is either a (name, value) 2-tuple or a (name,) 1-tuple.559 The former defines a macro; if the value is None, the macro is560 defined without an explicit value. The 1-tuple case undefines a561 macro. Later definitions/redefinitions/ undefinitions take562 precedence.563 564 'include_dirs', if given, must be a list of strings, the565 directories to add to the default include file search path for this566 compilation only.567 568 'debug' is a boolean; if true, the compiler will be instructed to569 output debug symbols in (or alongside) the object file(s).570 571 'extra_preargs' and 'extra_postargs' are implementation- dependent.572 On platforms that have the notion of a command-line (e.g. Unix,573 DOS/Windows), they are most likely lists of strings: extra574 command-line arguments to prepend/append to the compiler command575 line. On other platforms, consult the implementation class576 documentation. In any event, they are intended as an escape hatch577 for those occasions when the abstract compiler framework doesn't578 cut the mustard.579 580 'depends', if given, is a list of filenames that all targets581 depend on. If a source file is older than any file in582 depends, then the source file will be recompiled. This583 supports dependency tracking, but only at a coarse584 granularity.585 586 Raises CompileError on failure.587 """588 # A concrete compiler class can either override this method589 # entirely or implement _compile().590 macros, objects, extra_postargs, pp_opts, build = self._setup_compile(591 output_dir, macros, include_dirs, sources, depends, extra_postargs592 )593 cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)594 595 for obj in objects:596 try:597 src, ext = build[obj]598 except KeyError:599 continue600 self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)601 602 # Return *all* object filenames, not just the ones we just built.603 return objects604 605 def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):606 """Compile 'src' to product 'obj'."""607 # A concrete compiler class that does not override compile()608 # should implement _compile().609 pass610 611 def create_static_lib(612 self, objects, output_libname, output_dir=None, debug=0, target_lang=None613 ):614 """Link a bunch of stuff together to create a static library file.615 The "bunch of stuff" consists of the list of object files supplied616 as 'objects', the extra object files supplied to617 'add_link_object()' and/or 'set_link_objects()', the libraries618 supplied to 'add_library()' and/or 'set_libraries()', and the619 libraries supplied as 'libraries' (if any).620 621 'output_libname' should be a library name, not a filename; the622 filename will be inferred from the library name. 'output_dir' is623 the directory where the library file will be put.624 625 'debug' is a boolean; if true, debugging information will be626 included in the library (note that on most platforms, it is the627 compile step where this matters: the 'debug' flag is included here628 just for consistency).629 630 'target_lang' is the target language for which the given objects631 are being compiled. This allows specific linkage time treatment of632 certain languages.633 634 Raises LibError on failure.635 """636 pass637 638 # values for target_desc parameter in link()639 SHARED_OBJECT = "shared_object"640 SHARED_LIBRARY = "shared_library"641 EXECUTABLE = "executable"642 643 def link(644 self,645 target_desc,646 objects,647 output_filename,648 output_dir=None,649 libraries=None,650 library_dirs=None,651 runtime_library_dirs=None,652 export_symbols=None,653 debug=0,654 extra_preargs=None,655 extra_postargs=None,656 build_temp=None,657 target_lang=None,658 ):659 """Link a bunch of stuff together to create an executable or660 shared library file.661 662 The "bunch of stuff" consists of the list of object files supplied663 as 'objects'. 'output_filename' should be a filename. If664 'output_dir' is supplied, 'output_filename' is relative to it665 (i.e. 'output_filename' can provide directory components if666 needed).667 668 'libraries' is a list of libraries to link against. These are669 library names, not filenames, since they're translated into670 filenames in a platform-specific way (eg. "foo" becomes "libfoo.a"671 on Unix and "foo.lib" on DOS/Windows). However, they can include a672 directory component, which means the linker will look in that673 specific directory rather than searching all the normal locations.674 675 'library_dirs', if supplied, should be a list of directories to676 search for libraries that were specified as bare library names677 (ie. no directory component). These are on top of the system678 default and those supplied to 'add_library_dir()' and/or679 'set_library_dirs()'. 'runtime_library_dirs' is a list of680 directories that will be embedded into the shared library and used681 to search for other shared libraries that *it* depends on at682 run-time. (This may only be relevant on Unix.)683 684 'export_symbols' is a list of symbols that the shared library will685 export. (This appears to be relevant only on Windows.)686 687 'debug' is as for 'compile()' and 'create_static_lib()', with the688 slight distinction that it actually matters on most platforms (as689 opposed to 'create_static_lib()', which includes a 'debug' flag690 mostly for form's sake).691 692 'extra_preargs' and 'extra_postargs' are as for 'compile()' (except693 of course that they supply command-line arguments for the694 particular linker being used).695 696 'target_lang' is the target language for which the given objects697 are being compiled. This allows specific linkage time treatment of698 certain languages.699 700 Raises LinkError on failure.701 """702 raise NotImplementedError703 704 # Old 'link_*()' methods, rewritten to use the new 'link()' method.705 706 def link_shared_lib(707 self,708 objects,709 output_libname,710 output_dir=None,711 libraries=None,712 library_dirs=None,713 runtime_library_dirs=None,714 export_symbols=None,715 debug=0,716 extra_preargs=None,717 extra_postargs=None,718 build_temp=None,719 target_lang=None,720 ):721 self.link(722 CCompiler.SHARED_LIBRARY,723 objects,724 self.library_filename(output_libname, lib_type='shared'),725 output_dir,726 libraries,727 library_dirs,728 runtime_library_dirs,729 export_symbols,730 debug,731 extra_preargs,732 extra_postargs,733 build_temp,734 target_lang,735 )736 737 def link_shared_object(738 self,739 objects,740 output_filename,741 output_dir=None,742 libraries=None,743 library_dirs=None,744 runtime_library_dirs=None,745 export_symbols=None,746 debug=0,747 extra_preargs=None,748 extra_postargs=None,749 build_temp=None,750 target_lang=None,751 ):752 self.link(753 CCompiler.SHARED_OBJECT,754 objects,755 output_filename,756 output_dir,757 libraries,758 library_dirs,759 runtime_library_dirs,760 export_symbols,761 debug,762 extra_preargs,763 extra_postargs,764 build_temp,765 target_lang,766 )767 768 def link_executable(769 self,770 objects,771 output_progname,772 output_dir=None,773 libraries=None,774 library_dirs=None,775 runtime_library_dirs=None,776 debug=0,777 extra_preargs=None,778 extra_postargs=None,779 target_lang=None,780 ):781 self.link(782 CCompiler.EXECUTABLE,783 objects,784 self.executable_filename(output_progname),785 output_dir,786 libraries,787 library_dirs,788 runtime_library_dirs,789 None,790 debug,791 extra_preargs,792 extra_postargs,793 None,794 target_lang,795 )796 797 # -- Miscellaneous methods -----------------------------------------798 # These are all used by the 'gen_lib_options() function; there is799 # no appropriate default implementation so subclasses should800 # implement all of these.801 802 def library_dir_option(self, dir):803 """Return the compiler option to add 'dir' to the list of804 directories searched for libraries.805 """806 raise NotImplementedError807 808 def runtime_library_dir_option(self, dir):809 """Return the compiler option to add 'dir' to the list of810 directories searched for runtime libraries.811 """812 raise NotImplementedError813 814 def library_option(self, lib):815 """Return the compiler option to add 'lib' to the list of libraries816 linked into the shared library or executable.817 """818 raise NotImplementedError819 820 def has_function( # noqa: C901821 self,822 funcname,823 includes=None,824 include_dirs=None,825 libraries=None,826 library_dirs=None,827 ):828 """Return a boolean indicating whether funcname is provided as829 a symbol on the current platform. The optional arguments can830 be used to augment the compilation environment.831 832 The libraries argument is a list of flags to be passed to the833 linker to make additional symbol definitions available for834 linking.835 836 The includes and include_dirs arguments are deprecated.837 Usually, supplying include files with function declarations838 will cause function detection to fail even in cases where the839 symbol is available for linking.840 841 """842 # this can't be included at module scope because it tries to843 # import math which might not be available at that point - maybe844 # the necessary logic should just be inlined?845 import tempfile846 847 if includes is None:848 includes = []849 else:850 warnings.warn("includes is deprecated", DeprecationWarning)851 if include_dirs is None:852 include_dirs = []853 else:854 warnings.warn("include_dirs is deprecated", DeprecationWarning)855 if libraries is None:856 libraries = []857 if library_dirs is None:858 library_dirs = []859 fd, fname = tempfile.mkstemp(".c", funcname, text=True)860 with os.fdopen(fd, "w", encoding='utf-8') as f:861 for incl in includes:862 f.write("""#include "%s"\n""" % incl)863 if not includes:864 # Use "char func(void);" as the prototype to follow865 # what autoconf does. This prototype does not match866 # any well-known function the compiler might recognize867 # as a builtin, so this ends up as a true link test.868 # Without a fake prototype, the test would need to869 # know the exact argument types, and the has_function870 # interface does not provide that level of information.871 f.write(872 """\873#ifdef __cplusplus874extern "C"875#endif876char %s(void);877"""878 % funcname879 )880 f.write(881 """\882int main (int argc, char **argv) {883 %s();884 return 0;885}886"""887 % funcname888 )889 890 try:891 objects = self.compile([fname], include_dirs=include_dirs)892 except CompileError:893 return False894 finally:895 os.remove(fname)896 897 try:898 self.link_executable(899 objects, "a.out", libraries=libraries, library_dirs=library_dirs900 )901 except (LinkError, TypeError):902 return False903 else:904 os.remove(905 self.executable_filename("a.out", output_dir=self.output_dir or '')906 )907 finally:908 for fn in objects:909 os.remove(fn)910 return True911 912 def find_library_file(self, dirs, lib, debug=0):913 """Search the specified list of directories for a static or shared914 library file 'lib' and return the full path to that file. If915 'debug' true, look for a debugging version (if that makes sense on916 the current platform). Return None if 'lib' wasn't found in any of917 the specified directories.918 """919 raise NotImplementedError920 921 # -- Filename generation methods -----------------------------------922 923 # The default implementation of the filename generating methods are924 # prejudiced towards the Unix/DOS/Windows view of the world:925 # * object files are named by replacing the source file extension926 # (eg. .c/.cpp -> .o/.obj)927 # * library files (shared or static) are named by plugging the928 # library name and extension into a format string, eg.929 # "lib%s.%s" % (lib_name, ".a") for Unix static libraries930 # * executables are named by appending an extension (possibly931 # empty) to the program name: eg. progname + ".exe" for932 # Windows933 #934 # To reduce redundant code, these methods expect to find935 # several attributes in the current object (presumably defined936 # as class attributes):937 # * src_extensions -938 # list of C/C++ source file extensions, eg. ['.c', '.cpp']939 # * obj_extension -940 # object file extension, eg. '.o' or '.obj'941 # * static_lib_extension -942 # extension for static library files, eg. '.a' or '.lib'943 # * shared_lib_extension -944 # extension for shared library/object files, eg. '.so', '.dll'945 # * static_lib_format -946 # format string for generating static library filenames,947 # eg. 'lib%s.%s' or '%s.%s'948 # * shared_lib_format949 # format string for generating shared library filenames950 # (probably same as static_lib_format, since the extension951 # is one of the intended parameters to the format string)952 # * exe_extension -953 # extension for executable files, eg. '' or '.exe'954 955 def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):956 if output_dir is None:957 output_dir = ''958 return list(959 self._make_out_path(output_dir, strip_dir, src_name)960 for src_name in source_filenames961 )962 963 @property964 def out_extensions(self):965 return dict.fromkeys(self.src_extensions, self.obj_extension)966 967 def _make_out_path(self, output_dir, strip_dir, src_name):968 base, ext = os.path.splitext(src_name)969 base = self._make_relative(base)970 try:971 new_ext = self.out_extensions[ext]972 except LookupError:973 raise UnknownFileError(f"unknown file type '{ext}' (from '{src_name}')")974 if strip_dir:975 base = os.path.basename(base)976 return os.path.join(output_dir, base + new_ext)977 978 @staticmethod979 def _make_relative(base):980 """981 In order to ensure that a filename always honors the982 indicated output_dir, make sure it's relative.983 Ref python/cpython#37775.984 """985 # Chop off the drive986 no_drive = os.path.splitdrive(base)[1]987 # If abs, chop off leading /988 return no_drive[os.path.isabs(no_drive) :]989 990 def shared_object_filename(self, basename, strip_dir=0, output_dir=''):991 assert output_dir is not None992 if strip_dir:993 basename = os.path.basename(basename)994 return os.path.join(output_dir, basename + self.shared_lib_extension)995 996 def executable_filename(self, basename, strip_dir=0, output_dir=''):997 assert output_dir is not None998 if strip_dir:999 basename = os.path.basename(basename)1000 return os.path.join(output_dir, basename + (self.exe_extension or ''))1001 1002 def library_filename(1003 self,1004 libname,1005 lib_type='static',1006 strip_dir=0,1007 output_dir='', # or 'shared'1008 ):1009 assert output_dir is not None1010 expected = '"static", "shared", "dylib", "xcode_stub"'1011 if lib_type not in eval(expected):1012 raise ValueError(f"'lib_type' must be {expected}")1013 fmt = getattr(self, lib_type + "_lib_format")1014 ext = getattr(self, lib_type + "_lib_extension")1015 1016 dir, base = os.path.split(libname)1017 filename = fmt % (base, ext)1018 if strip_dir:1019 dir = ''1020 1021 return os.path.join(output_dir, dir, filename)1022 1023 # -- Utility methods -----------------------------------------------1024 1025 def announce(self, msg, level=1):1026 log.debug(msg)1027 1028 def debug_print(self, msg):1029 from distutils.debug import DEBUG1030 1031 if DEBUG:1032 print(msg)1033 1034 def warn(self, msg):1035 sys.stderr.write("warning: %s\n" % msg)1036 1037 def execute(self, func, args, msg=None, level=1):1038 execute(func, args, msg, self.dry_run)1039 1040 def spawn(self, cmd, **kwargs):1041 spawn(cmd, dry_run=self.dry_run, **kwargs)1042 1043 def move_file(self, src, dst):1044 return move_file(src, dst, dry_run=self.dry_run)1045 1046 def mkpath(self, name, mode=0o777):1047 mkpath(name, mode, dry_run=self.dry_run)1048 1049 1050# Map a sys.platform/os.name ('posix', 'nt') to the default compiler1051# type for that platform. Keys are interpreted as re match1052# patterns. Order is important; platform mappings are preferred over1053# OS names.1054_default_compilers = (1055 # Platform string mappings1056 # on a cygwin built python we can use gcc like an ordinary UNIXish1057 # compiler1058 ('cygwin.*', 'unix'),1059 ('zos', 'zos'),1060 # OS name mappings1061 ('posix', 'unix'),1062 ('nt', 'msvc'),1063)1064 1065 1066def get_default_compiler(osname=None, platform=None):1067 """Determine the default compiler to use for the given platform.1068 1069 osname should be one of the standard Python OS names (i.e. the1070 ones returned by os.name) and platform the common value1071 returned by sys.platform for the platform in question.1072 1073 The default values are os.name and sys.platform in case the1074 parameters are not given.1075 """1076 if osname is None:1077 osname = os.name1078 if platform is None:1079 platform = sys.platform1080 for pattern, compiler in _default_compilers:1081 if (1082 re.match(pattern, platform) is not None1083 or re.match(pattern, osname) is not None1084 ):1085 return compiler1086 # Default to Unix compiler1087 return 'unix'1088 1089 1090# Map compiler types to (module_name, class_name) pairs -- ie. where to1091# find the code that implements an interface to this compiler. (The module1092# is assumed to be in the 'distutils' package.)1093compiler_class = {1094 'unix': ('unixccompiler', 'UnixCCompiler', "standard UNIX-style compiler"),1095 'msvc': ('_msvccompiler', 'MSVCCompiler', "Microsoft Visual C++"),1096 'cygwin': (1097 'cygwinccompiler',1098 'CygwinCCompiler',1099 "Cygwin port of GNU C Compiler for Win32",1100 ),1101 'mingw32': (1102 'cygwinccompiler',1103 'Mingw32CCompiler',1104 "Mingw32 port of GNU C Compiler for Win32",1105 ),1106 'bcpp': ('bcppcompiler', 'BCPPCompiler', "Borland C++ Compiler"),1107 'zos': ('zosccompiler', 'zOSCCompiler', 'IBM XL C/C++ Compilers'),1108}1109 1110 1111def show_compilers():1112 """Print list of available compilers (used by the "--help-compiler"1113 options to "build", "build_ext", "build_clib").1114 """1115 # XXX this "knows" that the compiler option it's describing is1116 # "--compiler", which just happens to be the case for the three1117 # commands that use it.1118 from distutils.fancy_getopt import FancyGetopt1119 1120 compilers = []1121 for compiler in compiler_class.keys():1122 compilers.append(("compiler=" + compiler, None, compiler_class[compiler][2]))1123 compilers.sort()1124 pretty_printer = FancyGetopt(compilers)1125 pretty_printer.print_help("List of available compilers:")1126 1127 1128def new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0):1129 """Generate an instance of some CCompiler subclass for the supplied1130 platform/compiler combination. 'plat' defaults to 'os.name'1131 (eg. 'posix', 'nt'), and 'compiler' defaults to the default compiler1132 for that platform. Currently only 'posix' and 'nt' are supported, and1133 the default compilers are "traditional Unix interface" (UnixCCompiler1134 class) and Visual C++ (MSVCCompiler class). Note that it's perfectly1135 possible to ask for a Unix compiler object under Windows, and a1136 Microsoft compiler object under Unix -- if you supply a value for1137 'compiler', 'plat' is ignored.1138 """1139 if plat is None:1140 plat = os.name1141 1142 try:1143 if compiler is None:1144 compiler = get_default_compiler(plat)1145 1146 (module_name, class_name, long_description) = compiler_class[compiler]1147 except KeyError:1148 msg = "don't know how to compile C/C++ code on platform '%s'" % plat1149 if compiler is not None:1150 msg = msg + " with '%s' compiler" % compiler1151 raise DistutilsPlatformError(msg)1152 1153 try:1154 module_name = "distutils." + module_name1155 __import__(module_name)1156 module = sys.modules[module_name]1157 klass = vars(module)[class_name]1158 except ImportError:1159 raise DistutilsModuleError(1160 "can't compile C/C++ code: unable to load module '%s'" % module_name1161 )1162 except KeyError:1163 raise DistutilsModuleError(1164 f"can't compile C/C++ code: unable to find class '{class_name}' "1165 f"in module '{module_name}'"1166 )1167 1168 # XXX The None is necessary to preserve backwards compatibility1169 # with classes that expect verbose to be the first positional1170 # argument.1171 return klass(None, dry_run, force)1172 1173 1174def gen_preprocess_options(macros, include_dirs):1175 """Generate C pre-processor options (-D, -U, -I) as used by at least1176 two types of compilers: the typical Unix compiler and Visual C++.1177 'macros' is the usual thing, a list of 1- or 2-tuples, where (name,)1178 means undefine (-U) macro 'name', and (name,value) means define (-D)1179 macro 'name' to 'value'. 'include_dirs' is just a list of directory1180 names to be added to the header file search path (-I). Returns a list1181 of command-line options suitable for either Unix compilers or Visual1182 C++.1183 """1184 # XXX it would be nice (mainly aesthetic, and so we don't generate1185 # stupid-looking command lines) to go over 'macros' and eliminate1186 # redundant definitions/undefinitions (ie. ensure that only the1187 # latest mention of a particular macro winds up on the command1188 # line). I don't think it's essential, though, since most (all?)1189 # Unix C compilers only pay attention to the latest -D or -U1190 # mention of a macro on their command line. Similar situation for1191 # 'include_dirs'. I'm punting on both for now. Anyways, weeding out1192 # redundancies like this should probably be the province of1193 # CCompiler, since the data structures used are inherited from it1194 # and therefore common to all CCompiler classes.1195 pp_opts = []1196 for macro in macros:1197 if not (isinstance(macro, tuple) and 1 <= len(macro) <= 2):1198 raise TypeError(1199 "bad macro definition '%s': "1200 "each element of 'macros' list must be a 1- or 2-tuple" % macro