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