Module rom |
[hide private]
[frames] | no frames]

# Source Code for Module rom

      1  #============================================================================
      2  #Name        : rom.py
      3  #Part of     : Helium
      4
      5  #Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
      6  #All rights reserved.
      7  #This component and the accompanying materials are made available
      8  #under the terms of the License "Eclipse Public License v1.0"
      9  #which accompanies this distribution, and is available
     10  #at the URL "http://www.eclipse.org/legal/epl-v10.html".
     11  #
     12  #Initial Contributors:
     13  #Nokia Corporation - initial contribution.
     14  #
     15  #Contributors:
     16  #
     17  #Description:
     18  #===============================================================================
     19
     20  """ This modules implements rombuilders.
     21  """
     22  import logging
     23  import os
     24  import sys
     25  import shutil
     26  import types
     27  from version import Version
     28  import re
     29  import escapeddict
     30  import imaker
     31
     32  # Uncomment this line to enable logging in this module, or configure logging elsewhere
     33  #logging.basicConfig(level=logging.DEBUG)
     34  logger = logging.getLogger("rom")
     35
     36
     37 -def get_abstract_parents(config):
     38      """ Create from a config element a list of parent
     39          that are abstract (not buildable).
     40      """
     41      result = []
     42      while (config.parent != None):
     43          if config.parent.abstract != None:
     44              result.append(config.parent)
     45          config = config.parent
     46      return result
     47
     48 -def read_file_content(filename):
     49      """ Read the whole file content.
     50      """
     51      ftr = open(filename, "r")
     52      content = ftr.read()
     53      ftr.close()
     54      return content
     55
     56 -def escape_string(string, config):
     57      """ Escape a string recursively.
     58      """
     59      #data = escapeddict.EscapedDict(config)
     60      #string = re.sub(r'\${(?P<name>[._a-zA-Z0-9]+)}', r'%(\g<name>)s', string)
     61      #return string % data
     62      return config.interpolate(string)
     63
     64 -def get_makefile_target(text):
     65      """ Retrieve the target name of a step
     66      """
     67      result = re.search(r"^(?P<target>.+?)\s*:", text, re.M)
     68      if (result != None):
     69          return result.groupdict()['target']
     70      raise Exception("Could'nt determine target name")
     71
     72 -def remove_duplicates(array):
     73      """ Remove dusplicates values from an array. """
     74      elements = {}
     75      for element in array: elements[element] = element
     76      return elements.keys()
     77
     78 -def get_product_path_bsf(product):
     79      """ Get product path using the BSF. """
     80      import bsf
     81      # read product hierarchy
     82      bsfs = bsf.read_all()
     83      return bsfs[product].get_path()
     84
     85 -def get_product_path_var(product):
     86      """ Get product path using the new tool. """
     87      return imaker.get_product_dir(product)
     88
     89 -class IMakerRomBuilder:
     90      """ Configuration Builder for iMaker tool.
     91          This tool generate a makefile.
     92      """
     93
     94 -    def __init__(self, config, product, usevar=False):
     95          self._config = config
     96          self._product = product
     97
     98 -    def process_my_traces(self, config):
     99          """ Generates a mytraces.txt file under \epoc32 based on the <mytraces/>
    100              XML sub-elements defined for the image.
    101          """
    102          sys.stdout.flush()
    103          if config.has_key('mytraces.binaries') and len(str(config['mytraces.binaries'])) > 0:
    104              mytracestxt = escape_string(config['mytraces.file'], config)
    105              logger.debug("Writing %s file" % mytracestxt)
    106              binaries = config['mytraces.binaries']
    107              traces_file = open(mytracestxt, 'w')
    108              for binary in binaries:
    109                  traces_file.write(str(binary) + "\n")
    110              traces_file.close()
    111
    112 -    def build(self):
    113          """ Generate the makefile from xml configuration.
    114              That method should be splitted....it's to long!!!
    115          """
    116          configs = self._config.getConfigurations(self._product)
    117          if (len(configs) > 0):
    118
    119              # creating additional targets
    120              targets = {}
    121
    122              master_filename = configs[0]['main.makefile.template']
    123
    124              outputfilename = os.path.basename(master_filename)
    125              if configs[0].has_key('output.makefile.filename'):
    126                  outputfilename = configs[0]['output.makefile.filename']
    127
    128              filename = "%s/%s" % (get_product_path_var(self._product), outputfilename)
    129              output = open(filename, "w+")
    130              output.write("# DO NOT EDIT - FILE AUTOMATICALLY GENERATED\n")
    131              output.write("# HELIUM variant configuration tool (C) Nokia - 2007\n\n")
    132              mkdefine = '__' + re.sub(r'[^\w]', '_', os.path.basename(outputfilename)).upper() + '__'
    133              output.write("ifndef %s\n" % mkdefine)
    134              output.write("%s := 1\n\n" % mkdefine)
    135              master_template = read_file_content(master_filename)
    136              output.write(configs[0].interpolate(master_template) + "\n")
    137
    138              for config in configs:
    139                  # generating traces
    140                  #self.process_my_traces(config)
    141
    142
    143                  if config.type == None:
    144                      raise Exception("Type not defined for configuration '%s'" % config.name)
    145
    146                  # generate makefile targets from templates
    147                  if config.has_key("%s.makefile.template" % config.type):
    148                      template = read_file_content(config["%s.makefile.template" % config.type])
    149                      image_types = config['image.type']
    150                      if not isinstance(config['image.type'], types.ListType):
    151                          image_types = [config['image.type']]
    152                      for romtype in image_types:
    153                          config['image.type'] = romtype
    154                          out = config.interpolate(str(template))
    155                          output.write(out+"\n")
    156                          subtargets = [get_makefile_target(out)]
    157                          for parent in get_abstract_parents(config):
    158                              if not targets.has_key(parent.name):
    159                                  targets[parent.name] = {}
    160                                  targets[parent.name]['parent'] = parent
    161                                  targets[parent.name]['subtargets'] = []
    162                              targets[parent.name]['subtargets'].extend(subtargets)
    163                              targets[parent.name]['subtargets'] = remove_duplicates(targets[parent.name]['subtargets'])
    164                              subtargets = [parent.name]
    165                      config['image.type'] = image_types
    166                  else:
    167                      # Do not raise error anymore when template is not found.
    168                      print "WARNING: Could not find template for %s (%s)" % (config.name,"%s.makefile.template" % config.type)
    169                      #raise Exception("Could not find template for %s (%s)" % (config.name,"%s.makefile.template" % config.type))
    170
    171
    172              output.write("###############################################################################\n")
    173              output.write("# Generated group target\n")
    174              output.write("###############################################################################\n\n")
    175              for target in targets.keys():
    176                  if targets[target]['parent']['build.parallel'] == 'true':
    177                      output.write("%s: %s\n\n" % (target, " ".join(targets[target]['subtargets'])))
    178                      output.write("%s-dryrun:\n" % target)
    179                      output.write("\t@$(CALL_TARGET) -n %s\n\n" % target)
    180                  else:
    181                      output.write("%s-dryrun:\n" % target)
    182                      for subtarget in targets[target]['subtargets']:
    183                          output.write("\t@$(CALL_TARGET) -n %s\n" % subtarget)
    184                      output.write("\n")
    185                      output.write("%s:\n" % target)
    186                      output.write("\t@echo === %s started\n" % target)
    187                      for subtarget in targets[target]['subtargets']:
    188                          output.write("\t$(CALL_TARGET) %s\n" % subtarget)
    189                      output.write("\t@echo === %s finished\n" % target)
    190                      output.write("\n")
    191              output.write("\nendif # %s\n" % mkdefine)
    192              output.close()
    193              print "File %s has been generated." % filename
    194          else:
    195              raise Exception("Could not find configuration: '%s'" % self._product)
    196
    197
    198 -class RomBuilder:
    199      """ Builder that create roms using makefpsx.
    200      """
    201 -    def __init__(self, configs):
    202          self.configs = configs
    203
    204 -    def build(self):
    205          """ Go throught the config and build each roms.
    206          """
    207          for config in self.configs:
    208              for k in sorted(config.keys()):
    209                  value = config[k]
    210                  if isinstance(value, types.UnicodeType):
    211                      value = value.encode('ascii', 'ignore')
    212                  print k + ': ' + str(value)
    213              image = Image(config)
    214              image.build()
    215              print '======================================'
    216              print
    217
    218 -class Image:
    219      """ An Image object represents a ROM image, or .fpsx file.
    220      """
    221
    222 -    def __init__(self, config):
    223          """ Initialise the Image object.
    224          """
    225          self.config = config
    226
    227 -    def build(self):
    228          """ Main method that handles the whole sequence of building the rom and
    229              moving all related files to the correct location.
    230          """
    231          self._create_destination()
    232          self._process_cmt()
    233          self._write_version()
    234          self._process_my_traces()
    235          self._callrommake()
    236          self._clean_mytraces()
    237          self._move_image_files()
    238          print
    239
    240 -    def _create_destination(self):
    241          """ Creates the destination directory of the ROM files if it does not exist.
    242          """
    243          dest = self.config['rom.output.dir']
    244          if not os.path.exists( dest ):
    245              os.makedirs( dest )
    246
    247 -    def _process_cmt(self):
    248          """ Copies the CMT image under \epoc32 and to the destination directory of
    249              the ROM image, if the image will include the CMT.
    250          """
    251          # Check if a CMT is needed
    252          if self.config['image.nocmt'] != 'true':
    253              dest = self.config['rom.output.dir']
    254              logger.debug("Copying " + self.config['cmt'] + " to " + dest)
    255              shutil.copy( self.config['cmt'], dest )
    256              logger.debug("Copying " + self.config['cmt'] + " to " + self.config['rommake.cmt.path'])
    257              shutil.copy( self.config['cmt'], self.config['rommake.cmt.path'] )
    258
    259 -    def _write_version(self):
    260          """ Generates the version text files that define the version of the ROM image.
    261              These are in UTF16 little endian (Symbian) format.
    262          """
    263          Version('sw', self.config).write()
    264          Version('langsw', self.config).write()
    265          Version('model', self.config).write()
    266
    267 -    def _process_my_traces(self):
    268          """ Generates a mytraces.txt file under \epoc32 based on the <mytraces/>
    269              XML sub-elements defined for the image.
    270          """
    271          sys.stdout.flush()
    272          if self.config.has_key('mytraces.binaries'):
    273              logger.debug("Writing mytraces.txt file")
    274              binaries = self.config['mytraces.binaries']
    275              traces_file = open( str(self.config['rommake.mytraces.file']), 'w' )
    276              for binary in binaries:
    277                  traces_file.write( str(binary) + "\n" )
    278              traces_file.close()
    279          else:
    280              self._clean_mytraces()
    281
    282 -    def _callrommake(self):
    283          """ Calls the make_fpsx.cmd to build a ROM image.
    284          """
    285          logger.debug("Building rom image: " + str(self))
    286          sys.stdout.flush()
    287
    288          args = [str(self.config['rommake.command']),
    289                  '-hid',
    290                  str(self.config['rommake.hwid']),
    291                  '-p',
    292                  str(self.config['rommake.product.name']),
    293                  '-iby',
    294                  str(self.config['image.iby']),
    295                  '-type',
    296                  str(self.config['image.type']),
    297                  '-traces',
    298                  '-verbose',
    299                  '-target',
    300                  self.config['rom.output.dir'],
    301                  '-o' + str(self)]
    302          if 'rommake.args' in self.config:
    303              extra_args = str(self.config['rommake.args']).split( ' ' )
    304              args += extra_args
    305          logger.debug("with args: " + str(args))
    306          os.chdir(os.path.dirname(str(self.config['rommake.command'])))
    307          os.spawnv(os.P_WAIT, str(self.config['rommake.command']), args)
    308
    309 -    def _clean_mytraces(self):
    310          logger.debug("Removing mytraces.txt file")
    311          if os.path.exists( str( self.config['rommake.mytraces.file'] ) ):
    312              os.remove( str( self.config['rommake.mytraces.file'] ) )
    313
    314 -    def _move_image_files(self):
    315          os.chdir( self.config['rom.output.dir'] )
    316          if not( os.path.isdir('temp') ):
    317              os.mkdir( 'temp' )
    318          if not( os.path.isdir('logs') ):
    319              os.mkdir( 'logs' )
    320          if not( os.path.isdir('obys') ):
    321              os.mkdir( 'obys' )
    322
    323          for element in os.listdir('.'):
    324              if( os.path.isfile(element) ):
    325                  if( element.endswith('.img') or element.endswith('.bin') or element.endswith('.bb5') ):
    326                      shutil.move( element, 'temp' )
    327                  if( element.endswith('.log') or element.endswith('.dir') or element.endswith('.symbol') ):
    328                      shutil.move( element, 'logs' )
    329                  if( element.endswith('.oby') ):
    330                      shutil.move( element, 'obys' )
    331
    332
    333      # Returns the name of this ROM image
    334 -    def __str__(self):
    335          """ Returns the filename of the image file once copied to the
    336              \*_flash_images directory.
    337          """
    338          # Get the unique build ID for these ROM image names
    339          name = str(self.config['rom.id']) + '_' + self.config['image.type']
    340
    341          # Add a flag if the ROM is textshell
    342          if self.config['image.ui'] == 'text':
    343              name += "_text"
    344
    345          # Add a flag if the image does not a CMT
    346          if self.config['image.nocmt'] == 'true':
    347              name += "_nocmt"
    348
    349          # Add any differentiating name extension if present3
    350          if self.config['image.name.extension'] != '':
    351              name += '_' + self.config['image.name.extension']
    352
    353          return name
    354