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