Path: blob/main/Tools/c-analyzer/distutils/ccompiler.py
12 views
"""distutils.ccompiler12Contains CCompiler, an abstract base class that defines the interface3for the Distutils compiler abstraction model."""45import sys, os, re6from distutils.errors import (7DistutilsModuleError, DistutilsPlatformError,8)9from distutils.util import split_quoted1011class CCompiler:12"""Abstract base class to define the interface that must be implemented13by real compiler classes. Also has some utility methods used by14several compiler classes.1516The basic idea behind a compiler abstraction class is that each17instance can be used for all the compile/link steps in building a18single project. Thus, attributes common to all of those compile and19link steps -- include directories, macros to define, libraries to link20against, etc. -- are attributes of the compiler instance. To allow for21variability in how individual files are treated, most of those22attributes may be varied on a per-compilation or per-link basis.23"""2425# 'compiler_type' is a class attribute that identifies this class. It26# keeps code that wants to know what kind of compiler it's dealing with27# from having to import all possible compiler classes just to do an28# 'isinstance'. In concrete CCompiler subclasses, 'compiler_type'29# should really, really be one of the keys of the 'compiler_class'30# dictionary (see below -- used by the 'new_compiler()' factory31# function) -- authors of new compiler interface classes are32# responsible for updating 'compiler_class'!33compiler_type = None3435# XXX things not handled by this compiler abstraction model:36# * client can't provide additional options for a compiler,37# e.g. warning, optimization, debugging flags. Perhaps this38# should be the domain of concrete compiler abstraction classes39# (UnixCCompiler, MSVCCompiler, etc.) -- or perhaps the base40# class should have methods for the common ones.41# * can't completely override the include or library searchg42# path, ie. no "cc -I -Idir1 -Idir2" or "cc -L -Ldir1 -Ldir2".43# I'm not sure how widely supported this is even by Unix44# compilers, much less on other platforms. And I'm even less45# sure how useful it is; maybe for cross-compiling, but46# support for that is a ways off. (And anyways, cross47# compilers probably have a dedicated binary with the48# right paths compiled in. I hope.)49# * can't do really freaky things with the library list/library50# dirs, e.g. "-Ldir1 -lfoo -Ldir2 -lfoo" to link against51# different versions of libfoo.a in different locations. I52# think this is useless without the ability to null out the53# library search path anyways.545556# Subclasses that rely on the standard filename generation methods57# implemented below should override these; see the comment near58# those methods ('object_filenames()' et. al.) for details:59src_extensions = None # list of strings60obj_extension = None # string61static_lib_extension = None62shared_lib_extension = None # string63static_lib_format = None # format string64shared_lib_format = None # prob. same as static_lib_format65exe_extension = None # string6667# Default language settings. language_map is used to detect a source68# file or Extension target language, checking source filenames.69# language_order is used to detect the language precedence, when deciding70# what language to use when mixing source types. For example, if some71# extension has two files with ".c" extension, and one with ".cpp", it72# is still linked as c++.73language_map = {".c" : "c",74".cc" : "c++",75".cpp" : "c++",76".cxx" : "c++",77".m" : "objc",78}79language_order = ["c++", "objc", "c"]8081def __init__(self, verbose=0, dry_run=0, force=0):82self.dry_run = dry_run83self.force = force84self.verbose = verbose8586# 'output_dir': a common output directory for object, library,87# shared object, and shared library files88self.output_dir = None8990# 'macros': a list of macro definitions (or undefinitions). A91# macro definition is a 2-tuple (name, value), where the value is92# either a string or None (no explicit value). A macro93# undefinition is a 1-tuple (name,).94self.macros = []9596# 'include_dirs': a list of directories to search for include files97self.include_dirs = []9899# 'libraries': a list of libraries to include in any link100# (library names, not filenames: eg. "foo" not "libfoo.a")101self.libraries = []102103# 'library_dirs': a list of directories to search for libraries104self.library_dirs = []105106# 'runtime_library_dirs': a list of directories to search for107# shared libraries/objects at runtime108self.runtime_library_dirs = []109110# 'objects': a list of object files (or similar, such as explicitly111# named library files) to include on any link112self.objects = []113114for key in self.executables.keys():115self.set_executable(key, self.executables[key])116117def set_executables(self, **kwargs):118"""Define the executables (and options for them) that will be run119to perform the various stages of compilation. The exact set of120executables that may be specified here depends on the compiler121class (via the 'executables' class attribute), but most will have:122compiler the C/C++ compiler123linker_so linker used to create shared objects and libraries124linker_exe linker used to create binary executables125archiver static library creator126127On platforms with a command-line (Unix, DOS/Windows), each of these128is a string that will be split into executable name and (optional)129list of arguments. (Splitting the string is done similarly to how130Unix shells operate: words are delimited by spaces, but quotes and131backslashes can override this. See132'distutils.util.split_quoted()'.)133"""134135# Note that some CCompiler implementation classes will define class136# attributes 'cpp', 'cc', etc. with hard-coded executable names;137# this is appropriate when a compiler class is for exactly one138# compiler/OS combination (eg. MSVCCompiler). Other compiler139# classes (UnixCCompiler, in particular) are driven by information140# discovered at run-time, since there are many different ways to do141# basically the same things with Unix C compilers.142143for key in kwargs:144if key not in self.executables:145raise ValueError("unknown executable '%s' for class %s" %146(key, self.__class__.__name__))147self.set_executable(key, kwargs[key])148149def set_executable(self, key, value):150if isinstance(value, str):151setattr(self, key, split_quoted(value))152else:153setattr(self, key, value)154155def _find_macro(self, name):156i = 0157for defn in self.macros:158if defn[0] == name:159return i160i += 1161return None162163def _check_macro_definitions(self, definitions):164"""Ensures that every element of 'definitions' is a valid macro165definition, ie. either (name,value) 2-tuple or a (name,) tuple. Do166nothing if all definitions are OK, raise TypeError otherwise.167"""168for defn in definitions:169if not (isinstance(defn, tuple) and170(len(defn) in (1, 2) and171(isinstance (defn[1], str) or defn[1] is None)) and172isinstance (defn[0], str)):173raise TypeError(("invalid macro definition '%s': " % defn) + \174"must be tuple (string,), (string, string), or " + \175"(string, None)")176177178# -- Bookkeeping methods -------------------------------------------179180def define_macro(self, name, value=None):181"""Define a preprocessor macro for all compilations driven by this182compiler object. The optional parameter 'value' should be a183string; if it is not supplied, then the macro will be defined184without an explicit value and the exact outcome depends on the185compiler used (XXX true? does ANSI say anything about this?)186"""187# Delete from the list of macro definitions/undefinitions if188# already there (so that this one will take precedence).189i = self._find_macro (name)190if i is not None:191del self.macros[i]192193self.macros.append((name, value))194195def undefine_macro(self, name):196"""Undefine a preprocessor macro for all compilations driven by197this compiler object. If the same macro is defined by198'define_macro()' and undefined by 'undefine_macro()' the last call199takes precedence (including multiple redefinitions or200undefinitions). If the macro is redefined/undefined on a201per-compilation basis (ie. in the call to 'compile()'), then that202takes precedence.203"""204# Delete from the list of macro definitions/undefinitions if205# already there (so that this one will take precedence).206i = self._find_macro (name)207if i is not None:208del self.macros[i]209210undefn = (name,)211self.macros.append(undefn)212213def add_include_dir(self, dir):214"""Add 'dir' to the list of directories that will be searched for215header files. The compiler is instructed to search directories in216the order in which they are supplied by successive calls to217'add_include_dir()'.218"""219self.include_dirs.append(dir)220221def set_include_dirs(self, dirs):222"""Set the list of directories that will be searched to 'dirs' (a223list of strings). Overrides any preceding calls to224'add_include_dir()'; subsequence calls to 'add_include_dir()' add225to the list passed to 'set_include_dirs()'. This does not affect226any list of standard include directories that the compiler may227search by default.228"""229self.include_dirs = dirs[:]230231232# -- Private utility methods --------------------------------------233# (here for the convenience of subclasses)234235# Helper method to prep compiler in subclass compile() methods236237def _fix_compile_args(self, output_dir, macros, include_dirs):238"""Typecheck and fix-up some of the arguments to the 'compile()'239method, and return fixed-up values. Specifically: if 'output_dir'240is None, replaces it with 'self.output_dir'; ensures that 'macros'241is a list, and augments it with 'self.macros'; ensures that242'include_dirs' is a list, and augments it with 'self.include_dirs'.243Guarantees that the returned values are of the correct type,244i.e. for 'output_dir' either string or None, and for 'macros' and245'include_dirs' either list or None.246"""247if output_dir is None:248output_dir = self.output_dir249elif not isinstance(output_dir, str):250raise TypeError("'output_dir' must be a string or None")251252if macros is None:253macros = self.macros254elif isinstance(macros, list):255macros = macros + (self.macros or [])256else:257raise TypeError("'macros' (if supplied) must be a list of tuples")258259if include_dirs is None:260include_dirs = self.include_dirs261elif isinstance(include_dirs, (list, tuple)):262include_dirs = list(include_dirs) + (self.include_dirs or [])263else:264raise TypeError(265"'include_dirs' (if supplied) must be a list of strings")266267return output_dir, macros, include_dirs268269270# -- Worker methods ------------------------------------------------271# (must be implemented by subclasses)272273def preprocess(self, source, output_file=None, macros=None,274include_dirs=None, extra_preargs=None, extra_postargs=None):275"""Preprocess a single C/C++ source file, named in 'source'.276Output will be written to file named 'output_file', or stdout if277'output_file' not supplied. 'macros' is a list of macro278definitions as for 'compile()', which will augment the macros set279with 'define_macro()' and 'undefine_macro()'. 'include_dirs' is a280list of directory names that will be added to the default list.281282Raises PreprocessError on failure.283"""284pass285286287# -- Miscellaneous methods -----------------------------------------288# These are all used by the 'gen_lib_options() function; there is289# no appropriate default implementation so subclasses should290# implement all of these.291292# def library_dir_option(self, dir):293# """Return the compiler option to add 'dir' to the list of294# directories searched for libraries.295# """296# raise NotImplementedError297#298# def runtime_library_dir_option(self, dir):299# """Return the compiler option to add 'dir' to the list of300# directories searched for runtime libraries.301# """302# raise NotImplementedError303#304# def library_option(self, lib):305# """Return the compiler option to add 'lib' to the list of libraries306# linked into the shared library or executable.307# """308# raise NotImplementedError309#310# def find_library_file (self, dirs, lib, debug=0):311# """Search the specified list of directories for a static or shared312# library file 'lib' and return the full path to that file. If313# 'debug' true, look for a debugging version (if that makes sense on314# the current platform). Return None if 'lib' wasn't found in any of315# the specified directories.316# """317# raise NotImplementedError318319320# -- Utility methods -----------------------------------------------321322def spawn(self, cmd):323raise NotImplementedError324325326# Map a sys.platform/os.name ('posix', 'nt') to the default compiler327# type for that platform. Keys are interpreted as re match328# patterns. Order is important; platform mappings are preferred over329# OS names.330_default_compilers = (331332# Platform string mappings333334# on a cygwin built python we can use gcc like an ordinary UNIXish335# compiler336('cygwin.*', 'unix'),337338# OS name mappings339('posix', 'unix'),340('nt', 'msvc'),341342)343344def get_default_compiler(osname=None, platform=None):345"""Determine the default compiler to use for the given platform.346347osname should be one of the standard Python OS names (i.e. the348ones returned by os.name) and platform the common value349returned by sys.platform for the platform in question.350351The default values are os.name and sys.platform in case the352parameters are not given.353"""354if osname is None:355osname = os.name356if platform is None:357platform = sys.platform358for pattern, compiler in _default_compilers:359if re.match(pattern, platform) is not None or \360re.match(pattern, osname) is not None:361return compiler362# Default to Unix compiler363return 'unix'364365# Map compiler types to (module_name, class_name) pairs -- ie. where to366# find the code that implements an interface to this compiler. (The module367# is assumed to be in the 'distutils' package.)368compiler_class = { 'unix': ('unixccompiler', 'UnixCCompiler',369"standard UNIX-style compiler"),370'msvc': ('_msvccompiler', 'MSVCCompiler',371"Microsoft Visual C++"),372'cygwin': ('cygwinccompiler', 'CygwinCCompiler',373"Cygwin port of GNU C Compiler for Win32"),374'mingw32': ('cygwinccompiler', 'Mingw32CCompiler',375"Mingw32 port of GNU C Compiler for Win32"),376'bcpp': ('bcppcompiler', 'BCPPCompiler',377"Borland C++ Compiler"),378}379380381def new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0):382"""Generate an instance of some CCompiler subclass for the supplied383platform/compiler combination. 'plat' defaults to 'os.name'384(eg. 'posix', 'nt'), and 'compiler' defaults to the default compiler385for that platform. Currently only 'posix' and 'nt' are supported, and386the default compilers are "traditional Unix interface" (UnixCCompiler387class) and Visual C++ (MSVCCompiler class). Note that it's perfectly388possible to ask for a Unix compiler object under Windows, and a389Microsoft compiler object under Unix -- if you supply a value for390'compiler', 'plat' is ignored.391"""392if plat is None:393plat = os.name394395try:396if compiler is None:397compiler = get_default_compiler(plat)398399(module_name, class_name, long_description) = compiler_class[compiler]400except KeyError:401msg = "don't know how to compile C/C++ code on platform '%s'" % plat402if compiler is not None:403msg = msg + " with '%s' compiler" % compiler404raise DistutilsPlatformError(msg)405406try:407module_name = "distutils." + module_name408__import__ (module_name)409module = sys.modules[module_name]410klass = vars(module)[class_name]411except ImportError:412raise413raise DistutilsModuleError(414"can't compile C/C++ code: unable to load module '%s'" % \415module_name)416except KeyError:417raise DistutilsModuleError(418"can't compile C/C++ code: unable to find class '%s' "419"in module '%s'" % (class_name, module_name))420421# XXX The None is necessary to preserve backwards compatibility422# with classes that expect verbose to be the first positional423# argument.424return klass(None, dry_run, force)425426427def gen_preprocess_options(macros, include_dirs):428"""Generate C pre-processor options (-D, -U, -I) as used by at least429two types of compilers: the typical Unix compiler and Visual C++.430'macros' is the usual thing, a list of 1- or 2-tuples, where (name,)431means undefine (-U) macro 'name', and (name,value) means define (-D)432macro 'name' to 'value'. 'include_dirs' is just a list of directory433names to be added to the header file search path (-I). Returns a list434of command-line options suitable for either Unix compilers or Visual435C++.436"""437# XXX it would be nice (mainly aesthetic, and so we don't generate438# stupid-looking command lines) to go over 'macros' and eliminate439# redundant definitions/undefinitions (ie. ensure that only the440# latest mention of a particular macro winds up on the command441# line). I don't think it's essential, though, since most (all?)442# Unix C compilers only pay attention to the latest -D or -U443# mention of a macro on their command line. Similar situation for444# 'include_dirs'. I'm punting on both for now. Anyways, weeding out445# redundancies like this should probably be the province of446# CCompiler, since the data structures used are inherited from it447# and therefore common to all CCompiler classes.448pp_opts = []449for macro in macros:450if not (isinstance(macro, tuple) and 1 <= len(macro) <= 2):451raise TypeError(452"bad macro definition '%s': "453"each element of 'macros' list must be a 1- or 2-tuple"454% macro)455456if len(macro) == 1: # undefine this macro457pp_opts.append("-U%s" % macro[0])458elif len(macro) == 2:459if macro[1] is None: # define with no explicit value460pp_opts.append("-D%s" % macro[0])461else:462# XXX *don't* need to be clever about quoting the463# macro value here, because we're going to avoid the464# shell at all costs when we spawn the command!465pp_opts.append("-D%s=%s" % macro)466467for dir in include_dirs:468pp_opts.append("-I%s" % dir)469return pp_opts470471472