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