NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

ccompiler.py (20177B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\distutils\ccompiler.py
      2 __revision__ = '$Id: ccompiler.py 87602 2011-01-01 04:24:26Z richard.tew $'
      3 import sys
      4 import os
      5 import re
      6 from distutils.errors import CompileError, LinkError, UnknownFileError, DistutilsPlatformError, DistutilsModuleError
      7 from distutils.spawn import spawn
      8 from distutils.file_util import move_file
      9 from distutils.dir_util import mkpath
     10 from distutils.dep_util import newer_group
     11 from distutils.util import split_quoted, execute
     12 from distutils import log
     13 _sysconfig = __import__('sysconfig')
     14 
     15 def customize_compiler(compiler):
     16     if compiler.compiler_type == 'unix':
     17         cc, cxx, opt, cflags, ccshared, ldshared, so_ext, ar, ar_flags = _sysconfig.get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS', 'CCSHARED', 'LDSHARED', 'SO', 'AR', 'ARFLAGS')
     18         if 'CC' in os.environ:
     19             cc = os.environ['CC']
     20         if 'CXX' in os.environ:
     21             cxx = os.environ['CXX']
     22         if 'LDSHARED' in os.environ:
     23             ldshared = os.environ['LDSHARED']
     24         if 'CPP' in os.environ:
     25             cpp = os.environ['CPP']
     26         else:
     27             cpp = cc + ' -E'
     28         if 'LDFLAGS' in os.environ:
     29             ldshared = ldshared + ' ' + os.environ['LDFLAGS']
     30         if 'CFLAGS' in os.environ:
     31             cflags = opt + ' ' + os.environ['CFLAGS']
     32             ldshared = ldshared + ' ' + os.environ['CFLAGS']
     33         if 'CPPFLAGS' in os.environ:
     34             cpp = cpp + ' ' + os.environ['CPPFLAGS']
     35             cflags = cflags + ' ' + os.environ['CPPFLAGS']
     36             ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
     37         if 'AR' in os.environ:
     38             ar = os.environ['AR']
     39         if 'ARFLAGS' in os.environ:
     40             archiver = ar + ' ' + os.environ['ARFLAGS']
     41         else:
     42             archiver = ar + ' ' + ar_flags
     43         cc_cmd = cc + ' ' + cflags
     44         compiler.set_executables(preprocessor=cpp, compiler=cc_cmd, compiler_so=cc_cmd + ' ' + ccshared, compiler_cxx=cxx, linker_so=ldshared, linker_exe=cc, archiver=archiver)
     45         compiler.shared_lib_extension = so_ext
     46 
     47 
     48 class CCompiler():
     49     compiler_type = None
     50     src_extensions = None
     51     obj_extension = None
     52     static_lib_extension = None
     53     shared_lib_extension = None
     54     static_lib_format = None
     55     shared_lib_format = None
     56     exe_extension = None
     57     language_map = {'.c': 'c',
     58      '.cc': 'c++',
     59      '.cpp': 'c++',
     60      '.cxx': 'c++',
     61      '.m': 'objc'}
     62     language_order = ['c++', 'objc', 'c']
     63 
     64     def __init__(self, verbose = 0, dry_run = 0, force = 0):
     65         self.dry_run = dry_run
     66         self.force = force
     67         self.verbose = verbose
     68         self.output_dir = None
     69         self.macros = []
     70         self.include_dirs = []
     71         self.libraries = []
     72         self.library_dirs = []
     73         self.runtime_library_dirs = []
     74         self.objects = []
     75         for key in self.executables.keys():
     76             self.set_executable(key, self.executables[key])
     77 
     78     def set_executables(self, **args):
     79         for key in args.keys():
     80             if key not in self.executables:
     81                 raise ValueError, "unknown executable '%s' for class %s" % (key, self.__class__.__name__)
     82             self.set_executable(key, args[key])
     83 
     84     def set_executable(self, key, value):
     85         if isinstance(value, str):
     86             setattr(self, key, split_quoted(value))
     87         else:
     88             setattr(self, key, value)
     89 
     90     def _find_macro(self, name):
     91         i = 0
     92         for defn in self.macros:
     93             if defn[0] == name:
     94                 return i
     95             i = i + 1
     96 
     97     def _check_macro_definitions(self, definitions):
     98         for defn in definitions:
     99             if not (isinstance(defn, tuple) and (len(defn) == 1 or len(defn) == 2 and (isinstance(defn[1], str) or defn[1] is None)) and isinstance(defn[0], str)):
    100                 raise TypeError, "invalid macro definition '%s': " % defn + 'must be tuple (string,), (string, string), or ' + '(string, None)'
    101 
    102     def define_macro(self, name, value = None):
    103         i = self._find_macro(name)
    104         if i is not None:
    105             del self.macros[i]
    106         defn = (name, value)
    107         self.macros.append(defn)
    108 
    109     def undefine_macro(self, name):
    110         i = self._find_macro(name)
    111         if i is not None:
    112             del self.macros[i]
    113         undefn = (name,)
    114         self.macros.append(undefn)
    115 
    116     def add_include_dir(self, dir):
    117         self.include_dirs.append(dir)
    118 
    119     def set_include_dirs(self, dirs):
    120         self.include_dirs = dirs[:]
    121 
    122     def add_library(self, libname):
    123         self.libraries.append(libname)
    124 
    125     def set_libraries(self, libnames):
    126         self.libraries = libnames[:]
    127 
    128     def add_library_dir(self, dir):
    129         self.library_dirs.append(dir)
    130 
    131     def set_library_dirs(self, dirs):
    132         self.library_dirs = dirs[:]
    133 
    134     def add_runtime_library_dir(self, dir):
    135         self.runtime_library_dirs.append(dir)
    136 
    137     def set_runtime_library_dirs(self, dirs):
    138         self.runtime_library_dirs = dirs[:]
    139 
    140     def add_link_object(self, object):
    141         self.objects.append(object)
    142 
    143     def set_link_objects(self, objects):
    144         self.objects = objects[:]
    145 
    146     def _setup_compile(self, outdir, macros, incdirs, sources, depends, extra):
    147         if outdir is None:
    148             outdir = self.output_dir
    149         elif not isinstance(outdir, str):
    150             raise TypeError, "'output_dir' must be a string or None"
    151         if macros is None:
    152             macros = self.macros
    153         elif isinstance(macros, list):
    154             macros = macros + (self.macros or [])
    155         else:
    156             raise TypeError, "'macros' (if supplied) must be a list of tuples"
    157         if incdirs is None:
    158             incdirs = self.include_dirs
    159         elif isinstance(incdirs, (list, tuple)):
    160             incdirs = list(incdirs) + (self.include_dirs or [])
    161         else:
    162             raise TypeError, "'include_dirs' (if supplied) must be a list of strings"
    163         if extra is None:
    164             extra = []
    165         objects = self.object_filenames(sources, strip_dir=0, output_dir=outdir)
    166         pp_opts = gen_preprocess_options(macros, incdirs)
    167         build = {}
    168         for i in range(len(sources)):
    169             src = sources[i]
    170             obj = objects[i]
    171             ext = os.path.splitext(src)[1]
    172             self.mkpath(os.path.dirname(obj))
    173             build[obj] = (src, ext)
    174 
    175         return (macros,
    176          objects,
    177          extra,
    178          pp_opts,
    179          build)
    180 
    181     def _get_cc_args(self, pp_opts, debug, before):
    182         cc_args = pp_opts + ['-c']
    183         if debug:
    184             cc_args[:0] = ['-g']
    185         if before:
    186             cc_args[:0] = before
    187         return cc_args
    188 
    189     def _fix_compile_args(self, output_dir, macros, include_dirs):
    190         if output_dir is None:
    191             output_dir = self.output_dir
    192         elif not isinstance(output_dir, str):
    193             raise TypeError, "'output_dir' must be a string or None"
    194         if macros is None:
    195             macros = self.macros
    196         elif isinstance(macros, list):
    197             macros = macros + (self.macros or [])
    198         else:
    199             raise TypeError, "'macros' (if supplied) must be a list of tuples"
    200         if include_dirs is None:
    201             include_dirs = self.include_dirs
    202         elif isinstance(include_dirs, (list, tuple)):
    203             include_dirs = list(include_dirs) + (self.include_dirs or [])
    204         else:
    205             raise TypeError, "'include_dirs' (if supplied) must be a list of strings"
    206         return (output_dir, macros, include_dirs)
    207 
    208     def _fix_object_args(self, objects, output_dir):
    209         if not isinstance(objects, (list, tuple)):
    210             raise TypeError, "'objects' must be a list or tuple of strings"
    211         objects = list(objects)
    212         if output_dir is None:
    213             output_dir = self.output_dir
    214         elif not isinstance(output_dir, str):
    215             raise TypeError, "'output_dir' must be a string or None"
    216         return (objects, output_dir)
    217 
    218     def _fix_lib_args(self, libraries, library_dirs, runtime_library_dirs):
    219         if libraries is None:
    220             libraries = self.libraries
    221         elif isinstance(libraries, (list, tuple)):
    222             libraries = list(libraries) + (self.libraries or [])
    223         else:
    224             raise TypeError, "'libraries' (if supplied) must be a list of strings"
    225         if library_dirs is None:
    226             library_dirs = self.library_dirs
    227         elif isinstance(library_dirs, (list, tuple)):
    228             library_dirs = list(library_dirs) + (self.library_dirs or [])
    229         else:
    230             raise TypeError, "'library_dirs' (if supplied) must be a list of strings"
    231         if runtime_library_dirs is None:
    232             runtime_library_dirs = self.runtime_library_dirs
    233         elif isinstance(runtime_library_dirs, (list, tuple)):
    234             runtime_library_dirs = list(runtime_library_dirs) + (self.runtime_library_dirs or [])
    235         else:
    236             raise TypeError, "'runtime_library_dirs' (if supplied) " + 'must be a list of strings'
    237         return (libraries, library_dirs, runtime_library_dirs)
    238 
    239     def _need_link(self, objects, output_file):
    240         if self.force:
    241             return 1
    242         else:
    243             if self.dry_run:
    244                 newer = newer_group(objects, output_file, missing='newer')
    245             else:
    246                 newer = newer_group(objects, output_file)
    247             return newer
    248 
    249     def detect_language(self, sources):
    250         if not isinstance(sources, list):
    251             sources = [sources]
    252         lang = None
    253         index = len(self.language_order)
    254         for source in sources:
    255             base, ext = os.path.splitext(source)
    256             extlang = self.language_map.get(ext)
    257             try:
    258                 extindex = self.language_order.index(extlang)
    259                 if extindex < index:
    260                     lang = extlang
    261                     index = extindex
    262             except ValueError:
    263                 pass
    264 
    265         return lang
    266 
    267     def preprocess(self, source, output_file = None, macros = None, include_dirs = None, extra_preargs = None, extra_postargs = None):
    268         pass
    269 
    270     def compile(self, sources, output_dir = None, macros = None, include_dirs = None, debug = 0, extra_preargs = None, extra_postargs = None, depends = None):
    271         macros, objects, extra_postargs, pp_opts, build = self._setup_compile(output_dir, macros, include_dirs, sources, depends, extra_postargs)
    272         cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
    273         for obj in objects:
    274             try:
    275                 src, ext = build[obj]
    276             except KeyError:
    277                 continue
    278 
    279             self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
    280 
    281         return objects
    282 
    283     def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
    284         pass
    285 
    286     def create_static_lib(self, objects, output_libname, output_dir = None, debug = 0, target_lang = None):
    287         pass
    288 
    289     SHARED_OBJECT = 'shared_object'
    290     SHARED_LIBRARY = 'shared_library'
    291     EXECUTABLE = 'executable'
    292 
    293     def link(self, target_desc, objects, output_filename, output_dir = None, libraries = None, library_dirs = None, runtime_library_dirs = None, export_symbols = None, debug = 0, extra_preargs = None, extra_postargs = None, build_temp = None, target_lang = None):
    294         raise NotImplementedError
    295 
    296     def link_shared_lib(self, objects, output_libname, output_dir = None, libraries = None, library_dirs = None, runtime_library_dirs = None, export_symbols = None, debug = 0, extra_preargs = None, extra_postargs = None, build_temp = None, target_lang = None):
    297         self.link(CCompiler.SHARED_LIBRARY, objects, self.library_filename(output_libname, lib_type='shared'), output_dir, libraries, library_dirs, runtime_library_dirs, export_symbols, debug, extra_preargs, extra_postargs, build_temp, target_lang)
    298 
    299     def link_shared_object(self, objects, output_filename, output_dir = None, libraries = None, library_dirs = None, runtime_library_dirs = None, export_symbols = None, debug = 0, extra_preargs = None, extra_postargs = None, build_temp = None, target_lang = None):
    300         self.link(CCompiler.SHARED_OBJECT, objects, output_filename, output_dir, libraries, library_dirs, runtime_library_dirs, export_symbols, debug, extra_preargs, extra_postargs, build_temp, target_lang)
    301 
    302     def link_executable(self, objects, output_progname, output_dir = None, libraries = None, library_dirs = None, runtime_library_dirs = None, debug = 0, extra_preargs = None, extra_postargs = None, target_lang = None):
    303         self.link(CCompiler.EXECUTABLE, objects, self.executable_filename(output_progname), output_dir, libraries, library_dirs, runtime_library_dirs, None, debug, extra_preargs, extra_postargs, None, target_lang)
    304 
    305     def library_dir_option(self, dir):
    306         raise NotImplementedError
    307 
    308     def runtime_library_dir_option(self, dir):
    309         raise NotImplementedError
    310 
    311     def library_option(self, lib):
    312         raise NotImplementedError
    313 
    314     def has_function(self, funcname, includes = None, include_dirs = None, libraries = None, library_dirs = None):
    315         import tempfile
    316         if includes is None:
    317             includes = []
    318         if include_dirs is None:
    319             include_dirs = []
    320         if libraries is None:
    321             libraries = []
    322         if library_dirs is None:
    323             library_dirs = []
    324         fd, fname = tempfile.mkstemp('.c', funcname, text=True)
    325         f = os.fdopen(fd, 'w')
    326         try:
    327             for incl in includes:
    328                 f.write('#include "%s"\n' % incl)
    329 
    330             f.write('main (int argc, char **argv) {\n    %s();\n}\n' % funcname)
    331         finally:
    332             f.close()
    333 
    334         try:
    335             objects = self.compile([fname], include_dirs=include_dirs)
    336         except CompileError:
    337             return False
    338 
    339         try:
    340             self.link_executable(objects, 'a.out', libraries=libraries, library_dirs=library_dirs)
    341         except (LinkError, TypeError):
    342             return False
    343 
    344         return True
    345 
    346     def find_library_file(self, dirs, lib, debug = 0):
    347         raise NotImplementedError
    348 
    349     def object_filenames(self, source_filenames, strip_dir = 0, output_dir = ''):
    350         if output_dir is None:
    351             output_dir = ''
    352         obj_names = []
    353         for src_name in source_filenames:
    354             base, ext = os.path.splitext(src_name)
    355             base = os.path.splitdrive(base)[1]
    356             base = base[os.path.isabs(base):]
    357             if ext not in self.src_extensions:
    358                 raise UnknownFileError, "unknown file type '%s' (from '%s')" % (ext, src_name)
    359             if strip_dir:
    360                 base = os.path.basename(base)
    361             obj_names.append(os.path.join(output_dir, base + self.obj_extension))
    362 
    363         return obj_names
    364 
    365     def shared_object_filename(self, basename, strip_dir = 0, output_dir = ''):
    366         if strip_dir:
    367             basename = os.path.basename(basename)
    368         return os.path.join(output_dir, basename + self.shared_lib_extension)
    369 
    370     def executable_filename(self, basename, strip_dir = 0, output_dir = ''):
    371         if strip_dir:
    372             basename = os.path.basename(basename)
    373         return os.path.join(output_dir, basename + (self.exe_extension or ''))
    374 
    375     def library_filename(self, libname, lib_type = 'static', strip_dir = 0, output_dir = ''):
    376         if lib_type not in ('static', 'shared', 'dylib'):
    377             raise ValueError, '\'lib_type\' must be "static", "shared" or "dylib"'
    378         fmt = getattr(self, lib_type + '_lib_format')
    379         ext = getattr(self, lib_type + '_lib_extension')
    380         dir, base = os.path.split(libname)
    381         filename = fmt % (base, ext)
    382         if strip_dir:
    383             dir = ''
    384         return os.path.join(output_dir, dir, filename)
    385 
    386     def announce(self, msg, level = 1):
    387         log.debug(msg)
    388 
    389     def debug_print(self, msg):
    390         from distutils.debug import DEBUG
    391         if DEBUG:
    392             print msg
    393 
    394     def warn(self, msg):
    395         sys.stderr.write('warning: %s\n' % msg)
    396 
    397     def execute(self, func, args, msg = None, level = 1):
    398         execute(func, args, msg, self.dry_run)
    399 
    400     def spawn(self, cmd):
    401         spawn(cmd, dry_run=self.dry_run)
    402 
    403     def move_file(self, src, dst):
    404         return move_file(src, dst, dry_run=self.dry_run)
    405 
    406     def mkpath(self, name, mode = 511):
    407         mkpath(name, mode, dry_run=self.dry_run)
    408 
    409 
    410 _default_compilers = (('cygwin.*', 'unix'),
    411  ('os2emx', 'emx'),
    412  ('posix', 'unix'),
    413  ('nt', 'msvc'))
    414 
    415 def get_default_compiler(osname = None, platform = None):
    416     if osname is None:
    417         osname = os.name
    418     if platform is None:
    419         platform = sys.platform
    420     for pattern, compiler in _default_compilers:
    421         if re.match(pattern, platform) is not None or re.match(pattern, osname) is not None:
    422             return compiler
    423 
    424     return 'unix'
    425 
    426 
    427 compiler_class = {'unix': ('unixccompiler', 'UnixCCompiler', 'standard UNIX-style compiler'),
    428  'msvc': ('msvccompiler', 'MSVCCompiler', 'Microsoft Visual C++'),
    429  'cygwin': ('cygwinccompiler', 'CygwinCCompiler', 'Cygwin port of GNU C Compiler for Win32'),
    430  'mingw32': ('cygwinccompiler', 'Mingw32CCompiler', 'Mingw32 port of GNU C Compiler for Win32'),
    431  'bcpp': ('bcppcompiler', 'BCPPCompiler', 'Borland C++ Compiler'),
    432  'emx': ('emxccompiler', 'EMXCCompiler', 'EMX port of GNU C Compiler for OS/2')}
    433 
    434 def show_compilers():
    435     from distutils.fancy_getopt import FancyGetopt
    436     compilers = []
    437     for compiler in compiler_class.keys():
    438         compilers.append(('compiler=' + compiler, None, compiler_class[compiler][2]))
    439 
    440     compilers.sort()
    441     pretty_printer = FancyGetopt(compilers)
    442     pretty_printer.print_help('List of available compilers:')
    443 
    444 
    445 def new_compiler(plat = None, compiler = None, verbose = 0, dry_run = 0, force = 0):
    446     if plat is None:
    447         plat = os.name
    448     try:
    449         if compiler is None:
    450             compiler = get_default_compiler(plat)
    451         module_name, class_name, long_description = compiler_class[compiler]
    452     except KeyError:
    453         msg = "don't know how to compile C/C++ code on platform '%s'" % plat
    454         if compiler is not None:
    455             msg = msg + " with '%s' compiler" % compiler
    456         raise DistutilsPlatformError, msg
    457 
    458     try:
    459         module_name = 'distutils.' + module_name
    460         __import__(module_name)
    461         module = sys.modules[module_name]
    462         klass = vars(module)[class_name]
    463     except ImportError:
    464         raise DistutilsModuleError, "can't compile C/C++ code: unable to load module '%s'" % module_name
    465     except KeyError:
    466         raise DistutilsModuleError, ("can't compile C/C++ code: unable to find class '%s' " + "in module '%s'") % (class_name, module_name)
    467 
    468     return klass(None, dry_run, force)
    469 
    470 
    471 def gen_preprocess_options(macros, include_dirs):
    472     pp_opts = []
    473     for macro in macros:
    474         if not (isinstance(macro, tuple) and 1 <= len(macro) <= 2):
    475             raise TypeError, ("bad macro definition '%s': " + "each element of 'macros' list must be a 1- or 2-tuple") % macro
    476         if len(macro) == 1:
    477             pp_opts.append('-U%s' % macro[0])
    478         elif len(macro) == 2:
    479             if macro[1] is None:
    480                 pp_opts.append('-D%s' % macro[0])
    481             else:
    482                 pp_opts.append('-D%s=%s' % macro)
    483 
    484     for dir in include_dirs:
    485         pp_opts.append('-I%s' % dir)
    486 
    487     return pp_opts
    488 
    489 
    490 def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries):
    491     lib_opts = []
    492     for dir in library_dirs:
    493         lib_opts.append(compiler.library_dir_option(dir))
    494 
    495     for dir in runtime_library_dirs:
    496         opt = compiler.runtime_library_dir_option(dir)
    497         if isinstance(opt, list):
    498             lib_opts.extend(opt)
    499         else:
    500             lib_opts.append(opt)
    501 
    502     for lib in libraries:
    503         lib_dir, lib_name = os.path.split(lib)
    504         if lib_dir != '':
    505             lib_file = compiler.find_library_file([lib_dir], lib_name)
    506             if lib_file is not None:
    507                 lib_opts.append(lib_file)
    508             else:
    509                 compiler.warn("no library file corresponding to '%s' found (skipping)" % lib)
    510         else:
    511             lib_opts.append(compiler.library_option(lib))
    512 
    513     return lib_opts