• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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