1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
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
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
89 """ A generic element of a System Definition. """
91 """ Initialisation """
92 self._sysDef = sysDef
93
95 """ Name getter method """
96 return NotImplementedError()
97
99 """ Use name as default ID. """
100 return getattr(self, 'name').lower()
101
104
105
106 -class Unit(SysDefElement):
107 """ Abstract unit from SDF file. """
109 """ Initialisation """
110 SysDefElement.__init__(self, sysDef)
111 self.__xml = node
112 self.binaries = []
113
115 """ Id getter. """
116 return self.__xml.unitID
117
119 """ Name getter. """
120 return self.__xml.name
121
123 """ Path getter. """
124 return os.path.join(os.path.sep, self.__xml.bldFile)
125
132
133 id = property(__getid)
134 name = property(_getname)
135 path = property(__getpath)
136 filters = property(__getfilters)
137
138
140 """ A group of units. """
142 """ Initialisation """
143 SysDefElement.__init__(self, sysDef)
144 self._xml = node
145 self._units = []
146
148 """ Name getter method """
149 return self._xml.name
150
152 """ Units getter method """
153 return self._units
154
155 name = property(__getname)
156 units = property(__getunits)
157
158
160 """ Abstract layer from SDF file. """
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
176
177
179 """ Module list accessor. """
180 return self._modules
181
183 """ Module cound accessor. """
184 return self._module_count
185
186 modules = property(__getmodules)
187 modules_count = property(__getmodulescount)
188
189
191 """ Abstract module from SDF file. """
198
199
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
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
226 """ Command getter method. """
227 return self.__xml.command
228
230 """ Unit Parallel getter method (boolean). """
231 return (self.__xml.unitParallel.upper() == "Y")
232
233 command = property(__getcommand)
234 unitParallel = property(__getunitParallel)
235
236
266
267
269 """ Reads special instruction command. """
274
276 """ Name getter method """
277 return self.__xml.name
278
280 """ Command getter method """
281 return self.__xml.command
282
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
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
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
331 """ Abstract configuration from SDF file. """
336
338 """ Name getter method """
339 return self.__xml.name
340
347
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
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
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
382
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
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
424
425
427 """ Abstract targetlist from SDF file. """
432
434 """ Name getter method. """
435 return self.__xml.name
436
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
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. """
455 """ Initialisation """
456 self.__xml = amara.parse(open(filename, "r"))
457 self._cache = {}
458
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
470 """ Units getter method. """
471 return self._units
472
474 """ Modules getter method. """
475 return self._modules
476
478 """ Layers getter method. """
479 return self._layers
480
482 """ Unit lists getter method. """
483 return self._unitlists
484
486 """ Options getter method. """
487 return self._options
488
490 """ Configurations getter method. """
491 return self._configurations
492
494 """ Targets lists getter method. """
495 return self._targetlists
496
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
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
560 """ Adds SysDef element to cache. """
561
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
569 """ Item getter method. """
570 return self._cache[key]
571
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
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
589 """ Merge binary size base on binary sizes input and system definition. """
590 for (binary_name, size, rom_type) in binary_sizes_reader:
591
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
604 """ A binary file that may go into a ROM image. """
605
610
611
612
613
614
615
616
617
618
619
620
621
622