Package sysdef :: Module api
[hide private]
[frames] | no frames]

Source Code for Module sysdef.api

  1  #============================================================================  
  2  #Name        : api.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  """ System Definition file parser. 
 21   
 22  Priority are not handled yet. 
 23  Nested task unitlist are not handled properly yet. 
 24       
 25  How to use it:: 
 26   
 27      sdf = SystemDefinition(filename) 
 28      for name in sdf.layers: 
 29          print " + Units in layer %s" % name 
 30          for unit in sdf.layers[name].units: 
 31              print "     - " +  sdf.units[name].id 
 32   
 33      for name in sdf.units: 
 34          print sdf.units[name].id 
 35       
 36  """ 
 37   
 38  import logging 
 39  import os 
 40  import re 
 41  import sys 
 42  import types 
 43   
 44  import amara 
 45  from xmlhelper import node_scan, recursive_node_scan 
 46  from xml.dom import Node 
 47   
 48  import buildtools 
 49   
 50  logging.basicConfig(level=logging.INFO) 
 51  _logger = logging.getLogger('sysdef.api') 
 52   
 53   
54 -def filter_out(config_filters, unit_filters):
55 """ Function that determines if a unit should be included or not. 56 returns None => could be included, string reason. 57 """ 58 59 def hasvalue(filter_list, value): 60 """ Check if a filter list contains a particular value. 61 It handles list's item negation using "!". 62 """ 63 for list_value in filter_list: 64 if list_value == value: 65 return True 66 return False
67 for filter_ in unit_filters: 68 if filter_.startswith("!"): 69 if hasvalue(config_filters, filter_[1:]): 70 return filter 71 else: 72 if not hasvalue(config_filters, filter_): 73 return filter_ 74 return None 75 76
77 -def extract_filter_list(filters):
78 """ Convert a comma separated list of filters into a python list. 79 The method will skip empty filters (empty strings). 80 """ 81 result = [] 82 for filter_ in [filter_.strip() for filter_ in filters.split(",")]: 83 if len(filter_) > 0: 84 result.append(filter_) 85 return result
86 87
88 -class SysDefElement(object):
89 """ A generic element of a System Definition. """
90 - def __init__(self, sysDef):
91 """ Initialisation """ 92 self._sysDef = sysDef
93
94 - def _getname(self):
95 """ Name getter method """ 96 return NotImplementedError()
97
98 - def get_id(self):
99 """ Use name as default ID. """ 100 return getattr(self, 'name').lower()
101
102 - def __str__(self):
103 return self.get_id()
104 105
106 -class Unit(SysDefElement):
107 """ Abstract unit from SDF file. """
108 - def __init__(self, node, sysDef):
109 """ Initialisation """ 110 SysDefElement.__init__(self, sysDef) 111 self.__xml = node 112 self.binaries = []
113
114 - def __getid(self):
115 """ Id getter. """ 116 return self.__xml.unitID
117
118 - def _getname(self):
119 """ Name getter. """ 120 return self.__xml.name
121
122 - def __getpath(self):
123 """ Path getter. """ 124 return os.path.join(os.path.sep, self.__xml.bldFile)
125
126 - def __getfilters(self):
127 """ filter getter. """ 128 filters = [] 129 if hasattr(self.__xml, 'filter'): 130 filters = extract_filter_list(self.__xml.filter) 131 return filters
132 133 id = property(__getid) 134 name = property(_getname) 135 path = property(__getpath) 136 filters = property(__getfilters)
137 138
139 -class _UnitGroup(SysDefElement):
140 """ A group of units. """
141 - def __init__(self, node, sysDef):
142 """ Initialisation """ 143 SysDefElement.__init__(self, sysDef) 144 self._xml = node 145 self._units = []
146
147 - def __getname(self):
148 """ Name getter method """ 149 return self._xml.name
150
151 - def __getunits(self):
152 """ Units getter method """ 153 return self._units
154 155 name = property(__getname) 156 units = property(__getunits)
157 158
159 -class Layer(_UnitGroup):
160 """ Abstract layer from SDF file. """
161 - def __init__(self, node, sysDef):
162 """ Initialisation """ 163 _UnitGroup.__init__(self, node, sysDef) 164 self._modules = [] 165 self._module_count = 0 166 for unitNode in recursive_node_scan(self._xml, 'unit'): 167 unit = Unit(unitNode, self._sysDef) 168 self._units.append(unit) 169 self._sysDef.addElement(unit) 170 171 for moduleNode in recursive_node_scan(self._xml, 'module'): 172 module = Module(moduleNode, self._sysDef) 173 self._modules.append(module) 174 self._module_count += 1
175 # Not added to the model. 176 #self._sysDef.addElement(module) 177
178 - def __getmodules(self):
179 """ Module list accessor. """ 180 return self._modules
181
182 - def __getmodulescount(self):
183 """ Module cound accessor. """ 184 return self._module_count
185 186 modules = property(__getmodules) 187 modules_count = property(__getmodulescount)
188 189
190 -class Module(_UnitGroup):
191 """ Abstract module from SDF file. """
192 - def __init__(self, node, sysDef):
193 """ Initialisation """ 194 _UnitGroup.__init__(self, node, sysDef) 195 for unitNode in recursive_node_scan(self._xml, "unit"): 196 unit = Unit(unitNode, self._sysDef) 197 self._units.append(unit)
198 199
200 -class UnitList(_UnitGroup):
201 """ Abstract unitlist from SDF file. """
202 - def __init__(self, node, units, sysDef):
203 """ Initialisation """ 204 _UnitGroup.__init__(self, node, sysDef) 205 for unitRef in node_scan(self._xml, "unitRef"): 206 try: 207 self._units.append(units[unitRef.unit]) 208 except KeyError, error: 209 sys.stderr.write("ERROR: Could not find unit '%s'\n" % unitRef.unit + "\n" + error)
210 211
212 -class BuildLayer(SysDefElement):
213 """ Abstract buildlayer. """
214 - def __init__(self, node, config, sysDef):
215 """ Initialisation """ 216 SysDefElement.__init__(self, sysDef) 217 self.__xml = node 218 self.config = config 219 self.targetList = [] 220 if hasattr(self.__xml, 'targetList'): 221 for tlname in re.split(r'\s+', self.__xml.targetList.strip()): 222 for target in self._sysDef.targetlists[tlname].targets: 223 self.targetList.append(target)
224
225 - def __getcommand(self):
226 """ Command getter method. """ 227 return self.__xml.command
228
229 - def __getunitParallel(self):
230 """ Unit Parallel getter method (boolean). """ 231 return (self.__xml.unitParallel.upper() == "Y")
232 233 command = property(__getcommand) 234 unitParallel = property(__getunitParallel)
235 236
237 -class Option(SysDefElement):
238 """ Represents an option used in abld calls. """
239 - def __init__(self, node, sysDef):
240 """ Initialisation """ 241 SysDefElement.__init__(self, sysDef) 242 self.__xml = node
243
244 - def __getname(self):
245 """ Name getter method. """ 246 return self.__xml.name
247
248 - def __getabldOption(self):
249 """ Abld option getter method. """ 250 return self.__xml.abldOption
251
252 - def __getenable(self):
253 """ Unit Parallel getter method (boolean). """ 254 return (self.__xml.enable.upper() == 'Y')
255
256 - def __getfilteredOption(self):
257 """ Filtered abld option getter method. """ 258 if not self.enable: 259 return '' 260 return self.abldOption
261 262 name = property(__getname) 263 abldOption = property(__getabldOption) 264 enable = property(__getenable) 265 filteredOption = property(__getfilteredOption)
266 267
268 -class SpecialInstruction(SysDefElement):
269 """ Reads special instruction command. """
270 - def __init__(self, node, sysDef):
271 """ Initialisation """ 272 SysDefElement.__init__(self, sysDef) 273 self.__xml = node
274
275 - def __getname(self):
276 """ Name getter method """ 277 return self.__xml.name
278
279 - def __getcommand(self):
280 """ Command getter method """ 281 return self.__xml.command
282
283 - def __getpath(self):
284 """ Path getter method """ 285 return self.__xml.cwd
286 287 name = property(__getname) 288 command = property(__getcommand) 289 path = property(__getpath)
290 291
292 -class Task(SysDefElement):
293 """ Abstract task node from SDF xml. """
294 - def __init__(self, node, config, sysDef):
295 """ Initialisation """ 296 SysDefElement.__init__(self, sysDef) 297 self.__xml = node 298 self._config = config 299 self.__job = None
300
301 - def units(self):
302 """ Process unit list from layers """ 303 result = [] 304 for ref in node_scan(self.__xml, "unitListRef"): 305 units = [] 306 try: 307 units = self._config.sdf.unitlists[ref.unitList].units 308 for unit in units: 309 reason = filter_out(self._config.filters, unit.filters) 310 if reason == None: 311 result.append(unit) 312 else: 313 sys.stderr.write("Filter-out: %s (%s)\n" % (unit.id, reason)) 314 except KeyError, error: 315 sys.stderr.write("ERROR: Could not find unitList of layer %s\n" % error) 316 return result
317
318 - def __getjob(self):
319 """ Return the job contained inside the task. """ 320 for job in node_scan(self.__xml, r"buildLayer|specialInstructions"): 321 if job.nodeName == 'specialInstructions': 322 self.__job = SpecialInstruction(job, self._sysDef) 323 elif job.nodeName == 'buildLayer': 324 self.__job = BuildLayer(job, self._config, self._sysDef) 325 return self.__job
326 327 job = property(__getjob)
328 329
330 -class Configuration(SysDefElement):
331 """ Abstract configuration from SDF file. """
332 - def __init__(self, node, sysDef):
333 """ Initialisation """ 334 SysDefElement.__init__(self, sysDef) 335 self.__xml = node
336
337 - def __getname(self):
338 """ Name getter method """ 339 return self.__xml.name
340
341 - def __getfilters(self):
342 """ Filters getter method. """ 343 filters = [] 344 if hasattr(self.__xml, 'filter'): 345 filters = extract_filter_list(self.__xml.filter) 346 return filters
347
348 - def __getlayerrefs(self):
349 """ Layer's references getter method. """ 350 result = [] 351 for ref in node_scan(self.__xml, "layerRef"): 352 try: 353 result.append(self._sysDef.layers[ref.layerName]) 354 except KeyError, error: 355 sys.stderr.write("ERROR: Could not find layer '%s'\n" % error) 356 return result
357
358 - def __getunitlistrefs(self):
359 """ Unit list references getter method. """ 360 result = [] 361 for ref in node_scan(self.__xml, "unitListRef"): 362 try: 363 result.append(self._sysDef.unitlists[ref.unitList]) 364 except KeyError, error: 365 sys.stderr.write("ERROR: Could not find unitList %s\n" % error) 366 return result
367
368 - def __getunits(self):
369 """ Return unit from unitList or layer. """ 370 result = [] 371 for ref in node_scan(self.__xml, "unitListRef|layerRef"): 372 units = [] 373 try: 374 if ref.nodeName == 'unitListRef': 375 units = self._sysDef.unitlists[ref.unitList].units 376 else: 377 units = self._sysDef.layers[ref.layerName].units 378 for unit in units: 379 reason = filter_out(self.filters, unit.filters) 380 if reason == None: 381 # Get the unit object from the cache if this is a string 382 # TODO - remove once unitlist returns list of Unit objects 383 if isinstance(unit, types.UnicodeType): 384 unit = self._sysDef[unit] 385 result.append(unit) 386 else: 387 sys.stderr.write("Filter-out: %s (%s)\n" % (unit.id, reason)) 388 except KeyError, error: 389 sys.stderr.write("ERROR: Could not find unitList or layer %s\n" % error) 390 return result
391
392 - def __gettasks(self):
393 """ Tasks getter method. """ 394 result = [] 395 for task in node_scan(self.__xml, "task"): 396 result.append(Task(task, self, self._sysDef)) 397 return result
398 399 name = property(__getname) 400 filters = property(__getfilters) 401 layerrefs = property(__getlayerrefs) 402 unitlistrefs = property(__getunitlistrefs) 403 units = property(__getunits) 404 tasks = property(__gettasks)
405 406
407 -class Target(SysDefElement):
408 """ Abstract target from SDF file. """
409 - def __init__(self, node, sysDef):
410 """ Initialisation """ 411 SysDefElement.__init__(self, sysDef) 412 self.__xml = node
413
414 - def __getname(self):
415 """ Name getter method. """ 416 return self.__xml.name
417
418 - def __getabldTarget(self):
419 """ Abld target getter method. """ 420 return self.__xml.abldTarget
421 422 name = property(__getname) 423 abldTarget = property(__getabldTarget)
424 425
426 -class TargetList(SysDefElement):
427 """ Abstract targetlist from SDF file. """
428 - def __init__(self, node, sysDef):
429 """ Initialisation """ 430 SysDefElement.__init__(self, sysDef) 431 self.__xml = node
432
433 - def __getname(self):
434 """ Name getter method. """ 435 return self.__xml.name
436
437 - def __gettargets(self):
438 """ Targets getter method. """ 439 result = [] 440 for target in re.split(r'\s+', self.__xml.target): 441 result.append(self._sysDef.targets[target.strip()]) 442 return result
443 444 name = property(__getname) 445 targets = property(__gettargets)
446 447
448 -class SystemDefinition(object):
449 """ Logical representation of the System Definition. 450 451 The System Definition is defined in terms of a system model and a 452 build model. The default physical representation of this is the Symbian 453 XML format. """
454 - def __init__(self, filename):
455 """ Initialisation """ 456 self.__xml = amara.parse(open(filename, "r")) 457 self._cache = {} 458 #TODO - why store these as hashes? 459 self._units = {} 460 self._layers = {} 461 self._modules = {} 462 self._unitlists = {} 463 self._configurations = {} 464 self._options = {} 465 self._targets = {} 466 self._targetlists = {} 467 self.__parse()
468
469 - def __getunits(self):
470 """ Units getter method. """ 471 return self._units
472
473 - def __getmodules(self):
474 """ Modules getter method. """ 475 return self._modules
476
477 - def __getlayers(self):
478 """ Layers getter method. """ 479 return self._layers
480
481 - def __getunitlists(self):
482 """ Unit lists getter method. """ 483 return self._unitlists
484
485 - def __getoptions(self):
486 """ Options getter method. """ 487 return self._options
488
489 - def __getconfigurations(self):
490 """ Configurations getter method. """ 491 return self._configurations
492
493 - def __gettargetlists(self):
494 """ Targets lists getter method. """ 495 return self._targetlists
496
497 - def __gettargets(self):
498 """ Targets getter method. """ 499 return self._targets
500 501 units = property(__getunits) 502 unitlists = property(__getunitlists) 503 layers = property(__getlayers) 504 options = property(__getoptions) 505 configurations = property(__getconfigurations) 506 targetlists = property(__gettargetlists) 507 targets = property(__gettargets) 508 modules = property(__getmodules) 509
510 - def __parse(self):
511 if hasattr(self.__xml, u'SystemDefinition'): 512 for systemdef in self.__xml.SystemDefinition: 513 if hasattr(systemdef, u'systemModel'): 514 for systemmodel in systemdef.systemModel: 515 if hasattr(systemmodel, u'layer'): 516 for l in systemmodel.layer: 517 layer = Layer(l, self) 518 self.layers[layer.name] = layer 519 self.addElement(layer) 520 for unit in layer.units: 521 self._units[unit.get_id()] = unit 522 for mod in layer.modules: 523 self._modules[mod.name] = mod 524 525 if hasattr(systemdef, u'build'): 526 for build in systemdef.build: 527 if hasattr(build, u'unitList'): 528 for ul in build.unitList: 529 unitlist = UnitList(ul, self._units, self) 530 self.unitlists[unitlist.name] = unitlist 531 self.addElement(unitlist) 532 533 if hasattr(build, u'configuration'): 534 for xml_config in build.configuration: 535 config = Configuration(xml_config, self) 536 self.configurations[config.name] = config 537 self.addElement(config) 538 539 if hasattr(build, u'option'): 540 for option_node in build.option: 541 option = Option(option_node, self) 542 if option.name == 'SAVESPACE': 543 continue 544 self.options[option.name] = option 545 self.addElement(option) 546 547 if hasattr(build, u'target'): 548 for target_node in build.target: 549 target = Target(target_node, self) 550 self.targets[target.name] = target 551 self.addElement(target) 552 553 if hasattr(build, u'targetList'): 554 for targetlist_node in build.targetList: 555 targetlist = TargetList(targetlist_node, self) 556 self.targetlists[targetlist.name] = targetlist 557 self.addElement(targetlist)
558
559 - def addElement(self, element):
560 """ Adds SysDef element to cache. """ 561 #TODO - handle duplicate names of different types 562 if not self._cache.has_key(element.get_id()): 563 self._cache[element.get_id()] = element 564 _logger.info('Adding SysDef element to cache: %s' % str(element)) 565 else: 566 _logger.warning("Element already exists: %s" % element.name)
567
568 - def __getitem__(self, key):
569 """ Item getter method. """ 570 return self._cache[key]
571
572 - def merge_binaries(self, binaries_reader):
573 """ Merge binaries based on build log and system definition. """ 574 for (unit_name, binaries) in binaries_reader: 575 unit_name = unit_name.lower() 576 if self.units.has_key(unit_name): 577 for bin in binaries: 578 #if bin.find('_stolon_ekern') != -1: 579 _logger.debug("Merging: %s" % bin) 580 unit = self.units[unit_name] 581 unit.binaries = [Binary(bin.lower(), self) for bin in binaries] 582 for binary in unit.binaries: 583 self.addElement(binary) 584 _logger.info('Merging binary: %s' % str(binary)) 585 else: 586 _logger.warning('Component found in the build log but not in sysdef: %s' % unit_name)
587
588 - def merge_binary_sizes(self, binary_sizes_reader):
589 """ Merge binary size base on binary sizes input and system definition. """ 590 for (binary_name, size, rom_type) in binary_sizes_reader: 591 #if binary_name.find('_stolon_ekern') != -1: 592 593 binary_name = binary_name.lower() 594 _logger.debug("Merging binary size: %s" % binary_name) 595 if self._cache.has_key(binary_name): 596 binary = self._cache[binary_name] 597 binary.size = size 598 binary.rom_type = rom_type 599 else: 600 _logger.warning('Binary found in the binary sizes input but not in the system definition: %s' % binary_name)
601 602
603 -class Binary(SysDefElement):
604 """ A binary file that may go into a ROM image. """ 605
606 - def __init__(self, name, sysDef):
607 """ Initialisation """ 608 SysDefElement.__init__(self, sysDef) 609 self.name = name
610 611 612 613 614 615 616 #if __name__ == "__main__": 617 # sdf = SystemDefinitionFile("Z:/output/build/canonical_system_definition.xml") 618 # writer = MakeWriter2("Z:/output/build/makefile") 619 # writer.write(sdf) 620 # writer.close() 621 # print sdf.toMakefile() 622