| """distutils.unixccompiler |
| |
| Contains the UnixCCompiler class, a subclass of CCompiler that handles |
| the "typical" Unix-style command-line C compiler: |
| * macros defined with -Dname[=value] |
| * macros undefined with -Uname |
| * include search directories specified with -Idir |
| * libraries specified with -lllib |
| * library search directories specified with -Ldir |
| * compile handled by 'cc' (or similar) executable with -c option: |
| compiles .c to .o |
| * link static library handled by 'ar' command (possibly with 'ranlib') |
| * link shared library handled by 'cc -shared' |
| """ |
| |
| import os, sys |
| |
| from distutils.dep_util import newer |
| from distutils.ccompiler import CCompiler, gen_preprocess_options |
| from distutils.errors import DistutilsExecError, CompileError |
| |
| # XXX Things not currently handled: |
| # * optimization/debug/warning flags; we just use whatever's in Python's |
| # Makefile and live with it. Is this adequate? If not, we might |
| # have to have a bunch of subclasses GNUCCompiler, SGICCompiler, |
| # SunCCompiler, and I suspect down that road lies madness. |
| # * even if we don't know a warning flag from an optimization flag, |
| # we need some way for outsiders to feed preprocessor/compiler/linker |
| # flags in to us -- eg. a sysadmin might want to mandate certain flags |
| # via a site config file, or a user might want to set something for |
| # compiling this module distribution only via the setup.py command |
| # line, whatever. As long as these options come from something on the |
| # current system, they can be as system-dependent as they like, and we |
| # should just happily stuff them into the preprocessor/compiler/linker |
| # options and carry on. |
| |
| |
| class UnixCCompiler(CCompiler): |
| |
| compiler_type = 'unix' |
| |
| # These are used by CCompiler in two places: the constructor sets |
| # instance attributes 'preprocessor', 'compiler', etc. from them, and |
| # 'set_executable()' allows any of these to be set. The defaults here |
| # are pretty generic; they will probably have to be set by an outsider |
| # (eg. using information discovered by the sysconfig about building |
| # Python extensions). |
| executables = {'preprocessor' : None, |
| 'compiler' : ["cc"], |
| 'compiler_so' : ["cc"], |
| 'compiler_cxx' : ["cc"], |
| 'linker_so' : ["cc", "-shared"], |
| 'linker_exe' : ["cc"], |
| 'archiver' : ["ar", "-cr"], |
| 'ranlib' : None, |
| } |
| |
| if sys.platform[:6] == "darwin": |
| executables['ranlib'] = ["ranlib"] |
| |
| # Needed for the filename generation methods provided by the base |
| # class, CCompiler. NB. whoever instantiates/uses a particular |
| # UnixCCompiler instance should set 'shared_lib_ext' -- we set a |
| # reasonable common default here, but it's not necessarily used on all |
| # Unices! |
| |
| src_extensions = [".c",".C",".cc",".cxx",".cpp",".m"] |
| obj_extension = ".o" |
| static_lib_extension = ".a" |
| shared_lib_extension = ".so" |
| dylib_lib_extension = ".dylib" |
| xcode_stub_lib_extension = ".tbd" |
| static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s" |
| xcode_stub_lib_format = dylib_lib_format |
| if sys.platform == "cygwin": |
| exe_extension = ".exe" |
| |
| def preprocess(self, source, output_file=None, macros=None, |
| include_dirs=None, extra_preargs=None, extra_postargs=None): |
| fixed_args = self._fix_compile_args(None, macros, include_dirs) |
| ignore, macros, include_dirs = fixed_args |
| pp_opts = gen_preprocess_options(macros, include_dirs) |
| pp_args = self.preprocessor + pp_opts |
| if output_file: |
| pp_args.extend(['-o', output_file]) |
| if extra_preargs: |
| pp_args[:0] = extra_preargs |
| if extra_postargs: |
| pp_args.extend(extra_postargs) |
| pp_args.append(source) |
| |
| # We need to preprocess: either we're being forced to, or we're |
| # generating output to stdout, or there's a target output file and |
| # the source file is newer than the target (or the target doesn't |
| # exist). |
| if self.force or output_file is None or newer(source, output_file): |
| if output_file: |
| self.mkpath(os.path.dirname(output_file)) |
| try: |
| self.spawn(pp_args) |
| except DistutilsExecError as msg: |
| raise CompileError(msg) |