home *** CD-ROM | disk | FTP | other *** search
/ PC Extra 07 & 08 / pca1507.iso / Software / psp8 / Data1.cab / unixccompiler.py < prev    next >
Encoding:
Python Source  |  2003-04-22  |  11.6 KB  |  303 lines

  1. """distutils.unixccompiler
  2.  
  3. Contains the UnixCCompiler class, a subclass of CCompiler that handles
  4. the "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.  
  16. # created 1999/07/05, Greg Ward
  17.  
  18. __revision__ = "$Id: unixccompiler.py,v 1.38 2001/12/11 05:04:24 fdrake Exp $"
  19.  
  20. import string, re, os
  21. from types import *
  22. from copy import copy
  23. from distutils import sysconfig
  24. from distutils.dep_util import newer
  25. from distutils.ccompiler import \
  26.      CCompiler, gen_preprocess_options, gen_lib_options
  27. from distutils.errors import \
  28.      DistutilsExecError, CompileError, LibError, LinkError
  29.  
  30. # XXX Things not currently handled:
  31. #   * optimization/debug/warning flags; we just use whatever's in Python's
  32. #     Makefile and live with it.  Is this adequate?  If not, we might
  33. #     have to have a bunch of subclasses GNUCCompiler, SGICCompiler,
  34. #     SunCCompiler, and I suspect down that road lies madness.
  35. #   * even if we don't know a warning flag from an optimization flag,
  36. #     we need some way for outsiders to feed preprocessor/compiler/linker
  37. #     flags in to us -- eg. a sysadmin might want to mandate certain flags
  38. #     via a site config file, or a user might want to set something for
  39. #     compiling this module distribution only via the setup.py command
  40. #     line, whatever.  As long as these options come from something on the
  41. #     current system, they can be as system-dependent as they like, and we
  42. #     should just happily stuff them into the preprocessor/compiler/linker
  43. #     options and carry on.
  44.  
  45.  
  46. class UnixCCompiler (CCompiler):
  47.  
  48.     compiler_type = 'unix'
  49.  
  50.     # These are used by CCompiler in two places: the constructor sets
  51.     # instance attributes 'preprocessor', 'compiler', etc. from them, and
  52.     # 'set_executable()' allows any of these to be set.  The defaults here
  53.     # are pretty generic; they will probably have to be set by an outsider
  54.     # (eg. using information discovered by the sysconfig about building
  55.     # Python extensions).
  56.     executables = {'preprocessor' : None,
  57.                    'compiler'     : ["cc"],
  58.                    'compiler_so'  : ["cc"],
  59.                    'linker_so'    : ["cc", "-shared"],
  60.                    'linker_exe'   : ["cc"],
  61.                    'archiver'     : ["ar", "-cr"],
  62.                    'ranlib'       : None,
  63.                   }
  64.  
  65.     # Needed for the filename generation methods provided by the base
  66.     # class, CCompiler.  NB. whoever instantiates/uses a particular
  67.     # UnixCCompiler instance should set 'shared_lib_ext' -- we set a
  68.     # reasonable common default here, but it's not necessarily used on all
  69.     # Unices!
  70.  
  71.     src_extensions = [".c",".C",".cc",".cxx",".cpp",".m"]
  72.     obj_extension = ".o"
  73.     static_lib_extension = ".a"
  74.     shared_lib_extension = ".so"
  75.     dylib_lib_extension = ".dylib"
  76.     static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s"
  77.  
  78.  
  79.  
  80.     def __init__ (self,
  81.                   verbose=0,
  82.                   dry_run=0,
  83.                   force=0):
  84.         CCompiler.__init__ (self, verbose, dry_run, force)
  85.  
  86.  
  87.     def preprocess (self,
  88.                     source,
  89.                     output_file=None,
  90.                     macros=None,
  91.                     include_dirs=None,
  92.                     extra_preargs=None,
  93.                     extra_postargs=None):
  94.  
  95.         (_, macros, include_dirs) = \
  96.             self._fix_compile_args(None, macros, include_dirs)
  97.         pp_opts = gen_preprocess_options(macros, include_dirs)
  98.         pp_args = self.preprocessor + pp_opts
  99.         if output_file:
  100.             pp_args.extend(['-o', output_file])
  101.         if extra_preargs:
  102.             pp_args[:0] = extra_preargs
  103.         if extra_postargs:
  104.             pp_args.extend(extra_postargs)
  105.  
  106.         # We need to preprocess: either we're being forced to, or we're
  107.         # generating output to stdout, or there's a target output file and
  108.         # the source file is newer than the target (or the target doesn't
  109.         # exist).
  110.         if self.force or output_file is None or newer(source, output_file):
  111.             if output_file:
  112.                 self.mkpath(os.path.dirname(output_file))
  113.             try:
  114.                 self.spawn(pp_args)
  115.             except DistutilsExecError, msg:
  116.                 raise CompileError, msg
  117.  
  118.  
  119.     def compile (self,
  120.                  sources,
  121.                  output_dir=None,
  122.                  macros=None,
  123.                  include_dirs=None,
  124.                  debug=0,
  125.                  extra_preargs=None,
  126.                  extra_postargs=None):
  127.  
  128.         (output_dir, macros, include_dirs) = \
  129.             self._fix_compile_args(output_dir, macros, include_dirs)
  130.         (objects, skip_sources) = self._prep_compile(sources, output_dir)
  131.  
  132.         # Figure out the options for the compiler command line.
  133.         pp_opts = gen_preprocess_options(macros, include_dirs)
  134.         cc_args = pp_opts + ['-c']
  135.         if debug:
  136.             cc_args[:0] = ['-g']
  137.         if extra_preargs:
  138.             cc_args[:0] = extra_preargs
  139.         if extra_postargs is None:
  140.             extra_postargs = []
  141.  
  142.         # Compile all source files that weren't eliminated by
  143.         # '_prep_compile()'.
  144.         for i in range(len(sources)):
  145.             src = sources[i] ; obj = objects[i]
  146.             if skip_sources[src]:
  147.                 self.announce("skipping %s (%s up-to-date)" % (src, obj))
  148.             else:
  149.                 self.mkpath(os.path.dirname(obj))
  150.                 try:
  151.                     self.spawn(self.compiler_so + cc_args +
  152.                                [src, '-o', obj] +
  153.                                extra_postargs)
  154.                 except DistutilsExecError, msg:
  155.                     raise CompileError, msg
  156.  
  157.         # Return *all* object filenames, not just the ones we just built.
  158.         return objects
  159.  
  160.     # compile ()
  161.  
  162.  
  163.     def create_static_lib (self,
  164.                            objects,
  165.                            output_libname,
  166.                            output_dir=None,
  167.                            debug=0):
  168.  
  169.         (objects, output_dir) = self._fix_object_args(objects, output_dir)
  170.  
  171.         output_filename = \
  172.             self.library_filename(output_libname, output_dir=output_dir)
  173.  
  174.         if self._need_link(objects, output_filename):
  175.             self.mkpath(os.path.dirname(output_filename))
  176.             self.spawn(self.archiver +
  177.                        [output_filename] +
  178.                        objects + self.objects)
  179.  
  180.             # Not many Unices required ranlib anymore -- SunOS 4.x is, I
  181.             # think the only major Unix that does.  Maybe we need some
  182.             # platform intelligence here to skip ranlib if it's not
  183.             # needed -- or maybe Python's configure script took care of
  184.             # it for us, hence the check for leading colon.
  185.             if self.ranlib:
  186.                 try:
  187.                     self.spawn(self.ranlib + [output_filename])
  188.                 except DistutilsExecError, msg:
  189.                     raise LibError, msg
  190.         else:
  191.             self.announce("skipping %s (up-to-date)" % output_filename)
  192.  
  193.     # create_static_lib ()
  194.  
  195.  
  196.     def link (self,
  197.               target_desc,
  198.               objects,
  199.               output_filename,
  200.               output_dir=None,
  201.               libraries=None,
  202.               library_dirs=None,
  203.               runtime_library_dirs=None,
  204.               export_symbols=None,
  205.               debug=0,
  206.               extra_preargs=None,
  207.               extra_postargs=None,
  208.               build_temp=None):
  209.  
  210.         (objects, output_dir) = self._fix_object_args(objects, output_dir)
  211.         (libraries, library_dirs, runtime_library_dirs) = \
  212.             self._fix_lib_args(libraries, library_dirs, runtime_library_dirs)
  213.  
  214.         lib_opts = gen_lib_options(self,
  215.                                    library_dirs, runtime_library_dirs,
  216.                                    libraries)
  217.         if type(output_dir) not in (StringType, NoneType):
  218.             raise TypeError, "'output_dir' must be a string or None"
  219.         if output_dir is not None:
  220.             output_filename = os.path.join(output_dir, output_filename)
  221.  
  222.         if self._need_link(objects, output_filename):
  223.             ld_args = (objects + self.objects +
  224.                        lib_opts + ['-o', output_filename])
  225.             if debug:
  226.                 ld_args[:0] = ['-g']
  227.             if extra_preargs:
  228.                 ld_args[:0] = extra_preargs
  229.             if extra_postargs:
  230.                 ld_args.extend(extra_postargs)
  231.             self.mkpath(os.path.dirname(output_filename))
  232.             try:
  233.                 if target_desc == CCompiler.EXECUTABLE:
  234.                     self.spawn(self.linker_exe + ld_args)
  235.                 else:
  236.                     self.spawn(self.linker_so + ld_args)
  237.             except DistutilsExecError, msg:
  238.                 raise LinkError, msg
  239.         else:
  240.             self.announce("skipping %s (up-to-date)" % output_filename)
  241.  
  242.     # link ()
  243.  
  244.  
  245.     # -- Miscellaneous methods -----------------------------------------
  246.     # These are all used by the 'gen_lib_options() function, in
  247.     # ccompiler.py.
  248.  
  249.     def library_dir_option (self, dir):
  250.         return "-L" + dir
  251.  
  252.     def runtime_library_dir_option (self, dir):
  253.         # XXX Hackish, at the very least.  See Python bug #445902:
  254.         # http://sourceforge.net/tracker/index.php
  255.         #   ?func=detail&aid=445902&group_id=5470&atid=105470
  256.         # Linkers on different platforms need different options to
  257.         # specify that directories need to be added to the list of
  258.         # directories searched for dependencies when a dynamic library
  259.         # is sought.  GCC has to be told to pass the -R option through
  260.         # to the linker, whereas other compilers just know this.
  261.         # Other compilers may need something slightly different.  At
  262.         # this time, there's no way to determine this information from
  263.         # the configuration data stored in the Python installation, so
  264.         # we use this hack.
  265.         compiler = os.path.basename(sysconfig.get_config_var("CC"))
  266.         if compiler == "gcc" or compiler == "g++":
  267.             return "-Wl,-R" + dir
  268.         else:
  269.             return "-R" + dir
  270.  
  271.     def library_option (self, lib):
  272.         return "-l" + lib
  273.  
  274.  
  275.     def find_library_file (self, dirs, lib, debug=0):
  276.  
  277.         for dir in dirs:
  278.             shared = os.path.join(
  279.                 dir, self.library_filename(lib, lib_type='shared'))
  280.             dylib = os.path.join(
  281.                 dir, self.library_filename(lib, lib_type='dylib'))
  282.             static = os.path.join(
  283.                 dir, self.library_filename(lib, lib_type='static'))
  284.  
  285.             # We're second-guessing the linker here, with not much hard
  286.             # data to go on: GCC seems to prefer the shared library, so I'm
  287.             # assuming that *all* Unix C compilers do.  And of course I'm
  288.             # ignoring even GCC's "-static" option.  So sue me.
  289.             if os.path.exists(dylib):
  290.                 return dylib
  291.             elif os.path.exists(shared):
  292.                 return shared
  293.             elif os.path.exists(static):
  294.                 return static
  295.  
  296.         else:
  297.             # Oops, didn't find it in *any* of 'dirs'
  298.             return None
  299.  
  300.     # find_library_file ()
  301.  
  302. # class UnixCCompiler
  303.