1"""distutils.unixccompiler 2 3Contains the UnixCCompiler class, a subclass of CCompiler that handles 4the "typical" Unix-style command-line C compiler: 5 * macros defined with -Dname[=value] 6 * macros undefined with -Uname 7 * include search directories specified with -Idir 8 * libraries specified with -lllib 9 * library search directories specified with -Ldir 10 * compile handled by 'cc' (or similar) executable with -c option: 11 compiles .c to .o 12 * link static library handled by 'ar' command (possibly with 'ranlib') 13 * link shared library handled by 'cc -shared' 14""" 15 16import os, sys 17 18from distutils.dep_util import newer 19from distutils.ccompiler import CCompiler, gen_preprocess_options 20from distutils.errors import DistutilsExecError, CompileError 21 22# XXX Things not currently handled: 23# * optimization/debug/warning flags; we just use whatever's in Python's 24# Makefile and live with it. Is this adequate? If not, we might 25# have to have a bunch of subclasses GNUCCompiler, SGICCompiler, 26# SunCCompiler, and I suspect down that road lies madness. 27# * even if we don't know a warning flag from an optimization flag, 28# we need some way for outsiders to feed preprocessor/compiler/linker 29# flags in to us -- eg. a sysadmin might want to mandate certain flags 30# via a site config file, or a user might want to set something for 31# compiling this module distribution only via the setup.py command 32# line, whatever. As long as these options come from something on the 33# current system, they can be as system-dependent as they like, and we 34# should just happily stuff them into the preprocessor/compiler/linker 35# options and carry on. 36 37 38class UnixCCompiler(CCompiler): 39 40 compiler_type = 'unix' 41 42 # These are used by CCompiler in two places: the constructor sets 43 # instance attributes 'preprocessor', 'compiler', etc. from them, and 44 # 'set_executable()' allows any of these to be set. The defaults here 45 # are pretty generic; they will probably have to be set by an outsider 46 # (eg. using information discovered by the sysconfig about building 47 # Python extensions). 48 executables = {'preprocessor' : None, 49 'compiler' : ["cc"], 50 'compiler_so' : ["cc"], 51 'compiler_cxx' : ["cc"], 52 'linker_so' : ["cc", "-shared"], 53 'linker_exe' : ["cc"], 54 'archiver' : ["ar", "-cr"], 55 'ranlib' : None, 56 } 57 58 if sys.platform[:6] == "darwin": 59 executables['ranlib'] = ["ranlib"] 60 61 # Needed for the filename generation methods provided by the base 62 # class, CCompiler. NB. whoever instantiates/uses a particular 63 # UnixCCompiler instance should set 'shared_lib_ext' -- we set a 64 # reasonable common default here, but it's not necessarily used on all 65 # Unices! 66 67 src_extensions = [".c",".C",".cc",".cxx",".cpp",".m"] 68 obj_extension = ".o" 69 static_lib_extension = ".a" 70 shared_lib_extension = ".so" 71 dylib_lib_extension = ".dylib" 72 xcode_stub_lib_extension = ".tbd" 73 static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s" 74 xcode_stub_lib_format = dylib_lib_format 75 if sys.platform == "cygwin": 76 exe_extension = ".exe" 77 78 def preprocess(self, source, output_file=None, macros=None, 79 include_dirs=None, extra_preargs=None, extra_postargs=None): 80 fixed_args = self._fix_compile_args(None, macros, include_dirs) 81 ignore, macros, include_dirs = fixed_args 82 pp_opts = gen_preprocess_options(macros, include_dirs) 83 pp_args = self.preprocessor + pp_opts 84 if output_file: 85 pp_args.extend(['-o', output_file]) 86 if extra_preargs: 87 pp_args[:0] = extra_preargs 88 if extra_postargs: 89 pp_args.extend(extra_postargs) 90 pp_args.append(source) 91 92 # We need to preprocess: either we're being forced to, or we're 93 # generating output to stdout, or there's a target output file and 94 # the source file is newer than the target (or the target doesn't 95 # exist). 96 if self.force or output_file is None or newer(source, output_file): 97 if output_file: 98 self.mkpath(os.path.dirname(output_file)) 99 try: 100 self.spawn(pp_args) 101 except DistutilsExecError as msg: 102 raise CompileError(msg) 103