home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 June / PCWorld_2005-06_cd.bin / software / vyzkuste / firewally / firewally.exe / framework-2.3.exe / mwerkscompiler.py < prev    next >
Text File  |  2003-12-30  |  10KB  |  249 lines

  1. """distutils.mwerkscompiler
  2.  
  3. Contains MWerksCompiler, an implementation of the abstract CCompiler class
  4. for MetroWerks CodeWarrior on the Macintosh. Needs work to support CW on
  5. Windows."""
  6.  
  7. # This module should be kept compatible with Python 1.5.2.
  8.  
  9. __revision__ = "$Id: mwerkscompiler.py,v 1.12 2002/11/19 13:12:27 akuchling Exp $"
  10.  
  11. import sys, os, string
  12. from types import *
  13. from distutils.errors import \
  14.      DistutilsExecError, DistutilsPlatformError, \
  15.      CompileError, LibError, LinkError
  16. from distutils.ccompiler import \
  17.      CCompiler, gen_preprocess_options, gen_lib_options
  18. import distutils.util
  19. import distutils.dir_util
  20. from distutils import log
  21. import mkcwproject
  22.  
  23. class MWerksCompiler (CCompiler) :
  24.     """Concrete class that implements an interface to MetroWerks CodeWarrior,
  25.        as defined by the CCompiler abstract class."""
  26.  
  27.     compiler_type = 'mwerks'
  28.  
  29.     # Just set this so CCompiler's constructor doesn't barf.  We currently
  30.     # don't use the 'set_executables()' bureaucracy provided by CCompiler,
  31.     # as it really isn't necessary for this sort of single-compiler class.
  32.     # Would be nice to have a consistent interface with UnixCCompiler,
  33.     # though, so it's worth thinking about.
  34.     executables = {}
  35.  
  36.     # Private class data (need to distinguish C from C++ source for compiler)
  37.     _c_extensions = ['.c']
  38.     _cpp_extensions = ['.cc', '.cpp', '.cxx']
  39.     _rc_extensions = ['.r']
  40.     _exp_extension = '.exp'
  41.  
  42.     # Needed for the filename generation methods provided by the
  43.     # base class, CCompiler.
  44.     src_extensions = (_c_extensions + _cpp_extensions +
  45.                       _rc_extensions)
  46.     res_extension = '.rsrc'
  47.     obj_extension = '.obj' # Not used, really
  48.     static_lib_extension = '.lib'
  49.     shared_lib_extension = '.slb'
  50.     static_lib_format = shared_lib_format = '%s%s'
  51.     exe_extension = ''
  52.  
  53.  
  54.     def __init__ (self,
  55.                   verbose=0,
  56.                   dry_run=0,
  57.                   force=0):
  58.  
  59.         CCompiler.__init__ (self, verbose, dry_run, force)
  60.  
  61.  
  62.     def compile (self,
  63.                  sources,
  64.                  output_dir=None,
  65.                  macros=None,
  66.                  include_dirs=None,
  67.                  debug=0,
  68.                  extra_preargs=None,
  69.                  extra_postargs=None,
  70.                  depends=None):
  71.         (output_dir, macros, include_dirs) = \
  72.            self._fix_compile_args (output_dir, macros, include_dirs)
  73.         self.__sources = sources
  74.         self.__macros = macros
  75.         self.__include_dirs = include_dirs
  76.         # Don't need extra_preargs and extra_postargs for CW
  77.         return []
  78.  
  79.     def link (self,
  80.               target_desc,
  81.               objects,
  82.               output_filename,
  83.               output_dir=None,
  84.               libraries=None,
  85.               library_dirs=None,
  86.               runtime_library_dirs=None,
  87.               export_symbols=None,
  88.               debug=0,
  89.               extra_preargs=None,
  90.               extra_postargs=None,
  91.               build_temp=None,
  92.               target_lang=None):
  93.         # First fixup.
  94.         (objects, output_dir) = self._fix_object_args (objects, output_dir)
  95.         (libraries, library_dirs, runtime_library_dirs) = \
  96.             self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
  97.  
  98.         # First examine a couple of options for things that aren't implemented yet
  99.         if not target_desc in (self.SHARED_LIBRARY, self.SHARED_OBJECT):
  100.             raise DistutilsPlatformError, 'Can only make SHARED_LIBRARY or SHARED_OBJECT targets on the Mac'
  101.         if runtime_library_dirs:
  102.             raise DistutilsPlatformError, 'Runtime library dirs not implemented yet'
  103.         if extra_preargs or extra_postargs:
  104.             raise DistutilsPlatformError, 'Runtime library dirs not implemented yet'
  105.         if len(export_symbols) != 1:
  106.             raise DistutilsPlatformError, 'Need exactly one export symbol'
  107.         # Next there are various things for which we need absolute pathnames.
  108.         # This is because we (usually) create the project in a subdirectory of
  109.         # where we are now, and keeping the paths relative is too much work right
  110.         # now.
  111.         sources = map(self._filename_to_abs, self.__sources)
  112.         include_dirs = map(self._filename_to_abs, self.__include_dirs)
  113.         if objects:
  114.             objects = map(self._filename_to_abs, objects)
  115.         else:
  116.             objects = []
  117.         if build_temp:
  118.             build_temp = self._filename_to_abs(build_temp)
  119.         else:
  120.             build_temp = os.curdir()
  121.         if output_dir:
  122.             output_filename = os.path.join(output_dir, output_filename)
  123.         # The output filename needs special handling: splitting it into dir and
  124.         # filename part. Actually I'm not sure this is really needed, but it
  125.         # can't hurt.
  126.         output_filename = self._filename_to_abs(output_filename)
  127.         output_dir, output_filename = os.path.split(output_filename)
  128.         # Now we need the short names of a couple of things for putting them
  129.         # into the project.
  130.         if output_filename[-8:] == '.ppc.slb':
  131.             basename = output_filename[:-8]
  132.         elif output_filename[-11:] == '.carbon.slb':
  133.             basename = output_filename[:-11]
  134.         else:
  135.             basename = os.path.strip(output_filename)[0]
  136.         projectname = basename + '.mcp'
  137.         targetname = basename
  138.         xmlname = basename + '.xml'
  139.         exportname = basename + '.mcp.exp'
  140.         prefixname = 'mwerks_%s_config.h'%basename
  141.         # Create the directories we need
  142.         distutils.dir_util.mkpath(build_temp, dry_run=self.dry_run)
  143.         distutils.dir_util.mkpath(output_dir, dry_run=self.dry_run)
  144.         # And on to filling in the parameters for the project builder
  145.         settings = {}
  146.         settings['mac_exportname'] = exportname
  147.         settings['mac_outputdir'] = output_dir
  148.         settings['mac_dllname'] = output_filename
  149.         settings['mac_targetname'] = targetname
  150.         settings['sysprefix'] = sys.prefix
  151.         settings['mac_sysprefixtype'] = 'Absolute'
  152.         sourcefilenames = []
  153.         sourcefiledirs = []
  154.         for filename in sources + objects:
  155.             dirname, filename = os.path.split(filename)
  156.             sourcefilenames.append(filename)
  157.             if not dirname in sourcefiledirs:
  158.                 sourcefiledirs.append(dirname)
  159.         settings['sources'] = sourcefilenames
  160.         settings['libraries'] = libraries
  161.         settings['extrasearchdirs'] = sourcefiledirs + include_dirs + library_dirs
  162.         if self.dry_run:
  163.             print 'CALLING LINKER IN', os.getcwd()
  164.             for key, value in settings.items():
  165.                 print '%20.20s %s'%(key, value)
  166.             return
  167.         # Build the export file
  168.         exportfilename = os.path.join(build_temp, exportname)
  169.         log.debug("\tCreate export file %s", exportfilename)
  170.         fp = open(exportfilename, 'w')
  171.         fp.write('%s\n'%export_symbols[0])
  172.         fp.close()
  173.         # Generate the prefix file, if needed, and put it in the settings
  174.         if self.__macros:
  175.             prefixfilename = os.path.join(os.getcwd(), os.path.join(build_temp, prefixname))
  176.             fp = open(prefixfilename, 'w')
  177.             fp.write('#include "mwerks_shcarbon_config.h"\n')
  178.             for name, value in self.__macros:
  179.                 if value is None:
  180.                     fp.write('#define %s\n'%name)
  181.                 else:
  182.                     fp.write('#define %s %s\n'%(name, value))
  183.             fp.close()
  184.             settings['prefixname'] = prefixname
  185.  
  186.         # Build the XML file. We need the full pathname (only lateron, really)
  187.         # because we pass this pathname to CodeWarrior in an AppleEvent, and CW
  188.         # doesn't have a clue about our working directory.
  189.         xmlfilename = os.path.join(os.getcwd(), os.path.join(build_temp, xmlname))
  190.         log.debug("\tCreate XML file %s", xmlfilename)
  191.         xmlbuilder = mkcwproject.cwxmlgen.ProjectBuilder(settings)
  192.         xmlbuilder.generate()
  193.         xmldata = settings['tmp_projectxmldata']
  194.         fp = open(xmlfilename, 'w')
  195.         fp.write(xmldata)
  196.         fp.close()
  197.         # Generate the project. Again a full pathname.
  198.         projectfilename = os.path.join(os.getcwd(), os.path.join(build_temp, projectname))
  199.         log.debug('\tCreate project file %s', projectfilename)
  200.         mkcwproject.makeproject(xmlfilename, projectfilename)
  201.         # And build it
  202.         log.debug('\tBuild project')
  203.         mkcwproject.buildproject(projectfilename)
  204.  
  205.     def _filename_to_abs(self, filename):
  206.         # Some filenames seem to be unix-like. Convert to Mac names.
  207. ##        if '/' in filename and ':' in filename:
  208. ##           raise DistutilsPlatformError, 'Filename may be Unix or Mac style: %s'%filename
  209. ##        if '/' in filename:
  210. ##           filename = macurl2path(filename)
  211.         filename = distutils.util.convert_path(filename)
  212.         if not os.path.isabs(filename):
  213.             curdir = os.getcwd()
  214.             filename = os.path.join(curdir, filename)
  215.         # Finally remove .. components
  216.         components = string.split(filename, ':')
  217.         for i in range(1, len(components)):
  218.             if components[i] == '..':
  219.                 components[i] = ''
  220.         return string.join(components, ':')
  221.  
  222.     def library_dir_option (self, dir):
  223.         """Return the compiler option to add 'dir' to the list of
  224.         directories searched for libraries.
  225.         """
  226.         return # XXXX Not correct...
  227.  
  228.     def runtime_library_dir_option (self, dir):
  229.         """Return the compiler option to add 'dir' to the list of
  230.         directories searched for runtime libraries.
  231.         """
  232.         # Nothing needed or Mwerks/Mac.
  233.         return
  234.  
  235.     def library_option (self, lib):
  236.         """Return the compiler option to add 'dir' to the list of libraries
  237.         linked into the shared library or executable.
  238.         """
  239.         return
  240.  
  241.     def find_library_file (self, dirs, lib, debug=0):
  242.         """Search the specified list of directories for a static or shared
  243.         library file 'lib' and return the full path to that file.  If
  244.         'debug' true, look for a debugging version (if that makes sense on
  245.         the current platform).  Return None if 'lib' wasn't found in any of
  246.         the specified directories.
  247.         """
  248.         return 0
  249.