161 |
161 |
162 self.realise_exports(build) # permit communication of dependencies between children |
162 self.realise_exports(build) # permit communication of dependencies between children |
163 |
163 |
164 for c in self.children: |
164 for c in self.children: |
165 c.unfurl_all(build) |
165 c.unfurl_all(build) |
166 |
166 |
167 |
167 |
168 def realise_exports(self, build): |
168 def realise_exports(self, build): |
169 """Do the things that are needed such that we can fully unfurl all |
169 """Do the things that are needed such that we can fully unfurl all |
170 sibling nodes. i.e. this step is here to "take care" of the dependencies |
170 sibling nodes. i.e. this step is here to "take care" of the dependencies |
171 between siblings. |
171 between siblings. |
172 """ |
172 """ |
173 pass |
173 pass |
174 |
174 |
175 def realise_makefile(self, build, specs): |
175 def realise_makefile(self, build, specs): |
176 makefilename_base = build.topMakefile |
176 makefilename_base = build.topMakefile |
177 if self.name is not None: |
177 if self.name is not None: |
178 makefile = generic_path.Path(str(makefilename_base) + "_" + raptor_utilities.sanitise(self.name)) |
178 makefile = generic_path.Path(str(makefilename_base) + "_" + raptor_utilities.sanitise(self.name)) |
179 else: |
179 else: |
188 makefileset = build.maker.Write(makefile, specs, build.buildUnitsToBuild) |
188 makefileset = build.maker.Write(makefile, specs, build.buildUnitsToBuild) |
189 build.InfoEndTime(object_type = "layer", task = "parse", |
189 build.InfoEndTime(object_type = "layer", task = "parse", |
190 key = str(makefile.path)) |
190 key = str(makefile.path)) |
191 |
191 |
192 return makefileset |
192 return makefileset |
193 |
193 |
194 |
194 |
195 |
195 |
196 def realise(self, build): |
196 def realise(self, build): |
197 """Give the spec trees to the make engine and actually |
197 """Give the spec trees to the make engine and actually |
198 "build" the product represented by this model node""" |
198 "build" the product represented by this model node""" |
199 # Must ensure that all children are unfurled at this point |
199 # Must ensure that all children are unfurled at this point |
200 self.unfurl_all(build) |
200 self.unfurl_all(build) |
201 |
201 |
202 sp = self.specs |
202 sp = self.specs |
203 |
203 |
204 build.AssertBuildOK() |
204 build.AssertBuildOK() |
205 |
205 |
206 m = self.realise_makefile(build, sp) |
206 m = self.realise_makefile(build, sp) |
207 |
207 |
208 build.InfoStartTime(object_type = "layer", task = "build", |
208 build.InfoStartTime(object_type = "layer", task = "build", |
209 key = (str(m.directory) + "/" + str(m.filenamebase))) |
209 key = (str(m.directory) + "/" + str(m.filenamebase))) |
210 result = build.Make(m) |
210 result = build.Make(m) |
211 build.InfoEndTime(object_type = "layer", task = "build", |
211 build.InfoEndTime(object_type = "layer", task = "build", |
212 key = (str(m.directory) + "/" + str(m.filenamebase))) |
212 key = (str(m.directory) + "/" + str(m.filenamebase))) |
213 |
213 |
214 |
214 |
215 return result |
215 return result |
216 |
216 |
217 |
217 |
218 |
218 |
219 class Project(ModelNode): |
219 class Project(ModelNode): |
227 self.id = self.mmp_name |
227 self.id = self.mmp_name |
228 self.unfurled = False |
228 self.unfurled = False |
229 |
229 |
230 def makefile(self, makefilename_base, engine, named = False): |
230 def makefile(self, makefilename_base, engine, named = False): |
231 """Makefiles for individual mmps not feasible at the moment""" |
231 """Makefiles for individual mmps not feasible at the moment""" |
232 pass # Cannot, currently, "unfurl an mmp" directly but do want |
232 pass # Cannot, currently, "unfurl an mmp" directly but do want |
233 # to be able to simulate the overall recursive unfurling of a build. |
233 # to be able to simulate the overall recursive unfurling of a build. |
234 |
234 |
235 class Component(ModelNode): |
235 class Component(ModelNode): |
236 """A group of projects or, in symbian-speak, a bld.inf. |
236 """A group of projects or, in symbian-speak, a bld.inf. |
237 """ |
237 """ |
250 def AddMMP(self, filename): |
250 def AddMMP(self, filename): |
251 self.children.add(Project(filename)) |
251 self.children.add(Project(filename)) |
252 |
252 |
253 |
253 |
254 class Layer(ModelNode): |
254 class Layer(ModelNode): |
255 """ Some components that should be built togther |
255 """ Some components that should be built togther |
256 e.g. a Layer in the system definition. |
256 e.g. a Layer in the system definition. |
257 """ |
257 """ |
258 def __init__(self, name, componentlist=[]): |
258 def __init__(self, name, componentlist=[]): |
259 super(Layer,self).__init__(name) |
259 super(Layer,self).__init__(name) |
260 self.name = name |
260 self.name = name |
261 |
261 |
262 for c in componentlist: |
262 for c in componentlist: |
263 self.children.add(Component(c)) |
263 self.children.add(Component(c)) |
264 |
264 |
265 def unfurl(self, build): |
265 def unfurl(self, build): |
266 """Discover the children of this layer. This involves parsing the component MetaData (bld.infs, mmps). |
266 """Discover the children of this layer. This involves parsing the component MetaData (bld.infs, mmps). |
267 Takes a raptor object as a parameter (build), together with a list of Configurations. |
267 Takes a raptor object as a parameter (build), together with a list of Configurations. |
268 |
268 |
269 We currently have parsers that work on collections of components/bld.infs and that cannot |
269 We currently have parsers that work on collections of components/bld.infs and that cannot |
270 parse at a "finer" level. So one can't 'unfurl' an mmp at the moment. |
270 parse at a "finer" level. So one can't 'unfurl' an mmp at the moment. |
271 |
271 |
272 Returns True if the object was successfully unfurled. |
272 Returns True if the object was successfully unfurled. |
273 """ |
273 """ |
274 |
274 |
275 # setup all our components |
275 # setup all our components |
298 |
298 |
299 |
299 |
300 def meta_realise(self, build): |
300 def meta_realise(self, build): |
301 """Generate specs that can be used to "take care of" finding out more |
301 """Generate specs that can be used to "take care of" finding out more |
302 about this metaunit - i.e. one doesn't want to parse it immediately |
302 about this metaunit - i.e. one doesn't want to parse it immediately |
303 but to create a makefile that will parse it. |
303 but to create a makefile that will parse it. |
304 In this case it allows bld.infs to be parsed in parallel by make.""" |
304 In this case it allows bld.infs to be parsed in parallel by make.""" |
305 |
305 |
306 # insert the start time into the Makefile name? |
306 # insert the start time into the Makefile name? |
307 |
307 |
308 buildconfig = build.GetConfig("build").GenerateBuildUnits(build.cache) |
308 buildconfig = build.GetConfig("build").GenerateBuildUnits(build.cache) |
309 self.configs = build.buildUnitsToBuild |
309 self.configs = build.buildUnitsToBuild |
310 |
310 |
311 # Pass certain CLI flags through to the makefile-generating sbs calls |
311 # Pass certain CLI flags through to the makefile-generating sbs calls |
312 cli_options = "" |
312 cli_options = "" |
313 |
313 |
314 if build.debugOutput == True: |
314 if build.debugOutput == True: |
315 cli_options += " -d" |
315 cli_options += " -d" |
316 |
316 |
317 if build.ignoreOsDetection == True: |
317 if build.ignoreOsDetection == True: |
318 cli_options += " -i" |
318 cli_options += " -i" |
319 |
319 |
320 if build.keepGoing == True: |
320 if build.keepGoing == True: |
321 cli_options += " -k" |
321 cli_options += " -k" |
322 |
322 |
323 if build.quiet == True: |
323 if build.quiet == True: |
324 cli_options += " -q" |
324 cli_options += " -q" |
325 |
325 |
326 if build.timing == True: |
326 if build.timing == True: |
327 cli_options += " --timing" |
327 cli_options += " --timing" |
328 |
328 |
329 |
329 |
330 nc = len(self.children) |
330 nc = len(self.children) |
331 number_blocks = build.jobs |
331 number_blocks = build.jobs |
332 block_size = (nc / number_blocks) + 1 |
332 block_size = (nc / number_blocks) + 1 |
333 component_blocks = [] |
333 component_blocks = [] |
334 spec_nodes = [] |
334 spec_nodes = [] |
335 |
335 |
336 b = 0 |
336 b = 0 |
337 childlist = list(self.children) |
337 childlist = list(self.children) |
338 while b < nc: |
338 while b < nc: |
339 component_blocks.append(childlist[b:b+block_size]) |
339 component_blocks.append(childlist[b:b+block_size]) |
340 b += block_size |
340 b += block_size |
341 |
341 |
342 while len(component_blocks[-1]) <= 0: |
342 while len(component_blocks[-1]) <= 0: |
343 component_blocks.pop() |
343 component_blocks.pop() |
344 number_blocks -= 1 |
344 number_blocks -= 1 |
345 |
345 |
346 build.Info("Parallel Parsing: bld.infs split into %d blocks\n", number_blocks) |
346 build.Info("Parallel Parsing: bld.infs split into %d blocks\n", number_blocks) |
347 # Cause the binding makefiles to have the toplevel makefile's |
347 # Cause the binding makefiles to have the toplevel makefile's |
348 # name. The bindee's have __pp appended. |
348 # name. The bindee's have __pp appended. |
349 tm = build.topMakefile.Absolute() |
349 tm = build.topMakefile.Absolute() |
350 binding_makefiles = raptor_makefile.MakefileSet(str(tm.Dir()), build.maker.selectors, makefiles=None, filenamebase=str(tm.File())) |
350 binding_makefiles = raptor_makefile.MakefileSet(str(tm.Dir()), build.maker.selectors, makefiles=None, filenamebase=str(tm.File())) |
351 build.topMakefile = generic_path.Path(str(build.topMakefile) + "_pp") |
351 build.topMakefile = generic_path.Path(str(build.topMakefile) + "_pp") |
352 |
352 |
353 loop_number = 0 |
353 loop_number = 0 |
354 for block in component_blocks: |
354 for block in component_blocks: |
355 loop_number += 1 |
355 loop_number += 1 |
356 specNode = raptor_data.Specification("metadata_" + self.name) |
356 specNode = raptor_data.Specification("metadata_" + self.name) |
357 |
357 |
358 componentList = " ".join([str(c.bldinf_filename) for c in block]) |
358 componentList = " ".join([str(c.bldinf_filename) for c in block]) |
359 |
359 |
360 |
360 |
361 configList = " ".join([c.name for c in self.configs if c.name != "build" ]) |
361 configList = " ".join([c.name for c in self.configs if c.name != "build" ]) |
362 |
362 |
363 makefile_path = str(build.topMakefile) + "_" + str(loop_number) |
363 makefile_path = str(build.topMakefile) + "_" + str(loop_number) |
364 try: |
364 try: |
365 os.unlink(makefile_path) # until we have dependencies working properly |
365 os.unlink(makefile_path) # until we have dependencies working properly |
366 except Exception,e: |
366 except Exception,e: |
367 # print "couldn't unlink %s: %s" %(componentMakefileName, str(e)) |
367 # print "couldn't unlink %s: %s" %(componentMakefileName, str(e)) |
368 pass |
368 pass |
369 |
369 |
370 # add some basic data in a component-wide variant |
370 # add some basic data in a component-wide variant |
371 var = raptor_data.Variant() |
371 var = raptor_data.Variant() |
372 var.AddOperation(raptor_data.Set("COMPONENT_PATHS", componentList)) |
372 var.AddOperation(raptor_data.Set("COMPONENT_PATHS", componentList)) |
373 var.AddOperation(raptor_data.Set("MAKEFILE_PATH", makefile_path)) |
373 var.AddOperation(raptor_data.Set("MAKEFILE_PATH", makefile_path)) |
374 var.AddOperation(raptor_data.Set("CONFIGS", configList)) |
374 var.AddOperation(raptor_data.Set("CONFIGS", configList)) |
383 |
383 |
384 # Pass on '-n' (if specified) to the makefile-generating sbs calls |
384 # Pass on '-n' (if specified) to the makefile-generating sbs calls |
385 if build.noBuild: |
385 if build.noBuild: |
386 var.AddOperation(raptor_data.Set("NO_BUILD", "1")) |
386 var.AddOperation(raptor_data.Set("NO_BUILD", "1")) |
387 specNode.AddVariant(var) |
387 specNode.AddVariant(var) |
388 |
388 |
389 try: |
389 try: |
390 interface = build.cache.FindNamedInterface("build.makefiles") |
390 interface = build.cache.FindNamedInterface("build.makefiles") |
391 specNode.SetInterface(interface) |
391 specNode.SetInterface(interface) |
392 except KeyError: |
392 except KeyError: |
393 build.Error("Can't find flm interface 'build.makefiles' ") |
393 build.Error("Can't find flm interface 'build.makefiles' ") |
394 |
394 |
395 spec_nodes.append(specNode) |
395 spec_nodes.append(specNode) |
396 binding_makefiles.addInclude(str(makefile_path)+"_all") |
396 binding_makefiles.addInclude(str(makefile_path)+"_all") |
397 |
397 |
398 build.InfoDiscovery(object_type = "layers", count = 1) |
398 build.InfoDiscovery(object_type = "layers", count = 1) |
399 build.InfoStartTime(object_type = "layer", task = "parse", |
399 build.InfoStartTime(object_type = "layer", task = "parse", |
552 def AddTarget(self, target): |
552 def AddTarget(self, target): |
553 if self.doCheck or self.doWhat: |
553 if self.doCheck or self.doWhat: |
554 self.Warn("ignoring target %s because --what or --check is specified.\n", target) |
554 self.Warn("ignoring target %s because --what or --check is specified.\n", target) |
555 else: |
555 else: |
556 self.targets.append(target) |
556 self.targets.append(target) |
557 |
557 |
558 def AddSourceTarget(self, filename): |
558 def AddSourceTarget(self, filename): |
559 # source targets are sanitised and then added as if they were a "normal" makefile target |
559 # source targets are sanitised and then added as if they were a "normal" makefile target |
560 # in addition they have a default, empty, top-level target assigned in order that they can |
560 # in addition they have a default, empty, top-level target assigned in order that they can |
561 # be presented to any generated makefile without error |
561 # be presented to any generated makefile without error |
562 sourceTarget = generic_path.Path(filename).Absolute() |
562 sourceTarget = generic_path.Path(filename).Absolute() |
715 |
715 |
716 self.Info("%s %s", env, str(self.home)) |
716 self.Info("%s %s", env, str(self.home)) |
717 self.Info("Set-up %s", str(self.raptorXML)) |
717 self.Info("Set-up %s", str(self.raptorXML)) |
718 self.Info("Command-line-arguments %s", " ".join(self.args)) |
718 self.Info("Command-line-arguments %s", " ".join(self.args)) |
719 self.Info("Current working directory %s", os.getcwd()) |
719 self.Info("Current working directory %s", os.getcwd()) |
720 |
720 |
721 # the inherited environment |
721 # the inherited environment |
722 for e, value in os.environ.items(): |
722 for e, value in sorted( os.environ.items() ): |
723 self.Info("Environment %s=%s", e, value.replace("]]>", "]]>")) |
723 self.Info("Environment %s=%s", e, value.replace("]]>", "]]>")) |
724 |
724 |
725 # and some general debug stuff |
725 # and some general debug stuff |
726 self.Debug("Platform %s", "-".join(hostplatform)) |
726 self.Debug("Platform %s", "-".join(hostplatform)) |
727 self.Debug("Filesystem %s", self.filesystem) |
727 self.Debug("Filesystem %s", self.filesystem) |
857 except KeyError: |
857 except KeyError: |
858 raise Exception("Unknown build configuration '%s'" % configname) |
858 raise Exception("Unknown build configuration '%s'" % configname) |
859 return x |
859 return x |
860 |
860 |
861 def GetBuildUnitsToBuild(self, configNames): |
861 def GetBuildUnitsToBuild(self, configNames): |
862 """Return a list of the configuration objects that correspond to the |
862 """Return a list of the configuration objects that correspond to the |
863 list of configuration names in the configNames parameter. |
863 list of configuration names in the configNames parameter. |
864 |
864 |
865 raptor.GetBuildUnitsToBuild(["armv5", "winscw"]) |
865 raptor.GetBuildUnitsToBuild(["armv5", "winscw"]) |
866 >>> [ config1, config2, ... , configN ] |
866 >>> [ config1, config2, ... , configN ] |
867 """ |
867 """ |
868 |
868 |
869 if len(configNames) == 0: |
869 if len(configNames) == 0: |
870 # use default config |
870 # use default config |
871 if len(self.defaultConfig) == 0: |
871 if len(self.defaultConfig) == 0: |
872 self.Warn("No default configuration name") |
872 self.Warn("No default configuration name") |
892 self.Error("No build configurations given") |
892 self.Error("No build configurations given") |
893 |
893 |
894 return buildUnitsToBuild |
894 return buildUnitsToBuild |
895 |
895 |
896 def CheckToolset(self, evaluator, configname): |
896 def CheckToolset(self, evaluator, configname): |
897 """Check the toolset for a particular config, allow other objects access |
897 """Check the toolset for a particular config, allow other objects access |
898 to the toolset for this build (e.g. the raptor_make class).""" |
898 to the toolset for this build (e.g. the raptor_make class).""" |
899 if self.toolset is None: |
899 if self.toolset is None: |
900 if self.toolcheck == 'on': |
900 if self.toolcheck == 'on': |
901 self.toolset = raptor_data.ToolSet(log=self) |
901 self.toolset = raptor_data.ToolSet(log=self) |
902 elif self.toolcheck == 'forced' : |
902 elif self.toolcheck == 'forced' : |
1107 "turn a dictionary into a string of XML attributes" |
1107 "turn a dictionary into a string of XML attributes" |
1108 atts = "" |
1108 atts = "" |
1109 for a,v in dictionary.items(): |
1109 for a,v in dictionary.items(): |
1110 atts += " " + a + "='" + v + "'" |
1110 atts += " " + a + "='" + v + "'" |
1111 return atts |
1111 return atts |
1112 |
1112 |
1113 def Info(self, format, *extras, **attributes): |
1113 def Info(self, format, *extras, **attributes): |
1114 """Send an information message to the configured channel |
1114 """Send an information message to the configured channel |
1115 (XML control characters will be escaped) |
1115 (XML control characters will be escaped) |
1116 """ |
1116 """ |
1117 self.out.write("<info" + self.attributeString(attributes) + ">" + |
1117 self.out.write("<info" + self.attributeString(attributes) + ">" + |
1118 escape(format % extras) + "</info>\n") |
1118 escape(format % extras) + "</info>\n") |
1119 |
1119 |
1120 def InfoDiscovery(self, object_type, count): |
1120 def InfoDiscovery(self, object_type, count): |
1121 if self.timing: |
1121 if self.timing: |
1122 try: |
1122 try: |
1123 self.out.write(raptor_timing.Timing.discovery_string(object_type = object_type, |
1123 self.out.write(raptor_timing.Timing.discovery_string(object_type = object_type, |
1124 count = count)) |
1124 count = count)) |
1125 except Exception, exception: |
1125 except Exception, exception: |
1126 Error(exception.Text, function = "InfoDiscoveryTime") |
1126 Error(exception.Text, function = "InfoDiscoveryTime") |
1127 |
1127 |
1128 def InfoStartTime(self, object_type, task, key): |
1128 def InfoStartTime(self, object_type, task, key): |
1129 if self.timing: |
1129 if self.timing: |
1130 try: |
1130 try: |
1131 self.out.write(raptor_timing.Timing.start_string(object_type = object_type, |
1131 self.out.write(raptor_timing.Timing.start_string(object_type = object_type, |
1132 task = task, key = key)) |
1132 task = task, key = key)) |
1133 except Exception, exception: |
1133 except Exception, exception: |
1134 Error(exception.Text, function = "InfoStartTime") |
1134 Error(exception.Text, function = "InfoStartTime") |
1135 |
1135 |
1136 def InfoEndTime(self, object_type, task, key): |
1136 def InfoEndTime(self, object_type, task, key): |
1137 if self.timing: |
1137 if self.timing: |
1138 try: |
1138 try: |
1139 self.out.write(raptor_timing.Timing.end_string(object_type = object_type, |
1139 self.out.write(raptor_timing.Timing.end_string(object_type = object_type, |
1140 task = task, key = key)) |
1140 task = task, key = key)) |
1152 |
1152 |
1153 def Warn(self, format, *extras, **attributes): |
1153 def Warn(self, format, *extras, **attributes): |
1154 """Send a warning message to the configured channel |
1154 """Send a warning message to the configured channel |
1155 (XML control characters will be escaped) |
1155 (XML control characters will be escaped) |
1156 """ |
1156 """ |
1157 self.out.write("<warning" + self.attributeString(attributes) + ">" + |
1157 self.out.write("<warning" + self.attributeString(attributes) + ">" + |
1158 escape(format % extras) + "</warning>\n") |
1158 escape(format % extras) + "</warning>\n") |
1159 |
1159 |
1160 def FatalError(self, format, *extras, **attributes): |
1160 def FatalError(self, format, *extras, **attributes): |
1161 """Send an error message to the configured channel. This implies such a serious |
1161 """Send an error message to the configured channel. This implies such a serious |
1162 error that the entire build must be shut down asap whilst still finishing off |
1162 error that the entire build must be shut down asap whilst still finishing off |
1163 correctly whatever housekeeping is possible e.g. producing error reports. |
1163 correctly whatever housekeeping is possible e.g. producing error reports. |
1164 Remains quiet if the raptor object is already in a fatal state since there |
1164 Remains quiet if the raptor object is already in a fatal state since there |
1165 further errors are probably triggered by the first. |
1165 further errors are probably triggered by the first. |
1166 """ |
1166 """ |
1167 if not self.fatalErrorState: |
1167 if not self.fatalErrorState: |
1168 self.out.write("<error" + self.attributeString(attributes) + ">" + |
1168 self.out.write("<error" + self.attributeString(attributes) + ">" + |
1169 (format % extras) + "</error>\n") |
1169 (format % extras) + "</error>\n") |
1170 self.errorCode = 1 |
1170 self.errorCode = 1 |
1171 self.fatalErrorState = True |
1171 self.fatalErrorState = True |
1172 |
1172 |
1173 def Error(self, format, *extras, **attributes): |
1173 def Error(self, format, *extras, **attributes): |
1174 """Send an error message to the configured channel |
1174 """Send an error message to the configured channel |
1175 (XML control characters will be escaped) |
1175 (XML control characters will be escaped) |
1176 """ |
1176 """ |
1177 self.out.write("<error" + self.attributeString(attributes) + ">" + |
1177 self.out.write("<error" + self.attributeString(attributes) + ">" + |
1178 escape(format % extras) + "</error>\n") |
1178 escape(format % extras) + "</error>\n") |
1179 self.errorCode = 1 |
1179 self.errorCode = 1 |
1180 |
1180 |
1181 |
1181 |
1182 def PrintXML(self, format, *extras): |
1182 def PrintXML(self, format, *extras): |
1210 |
1210 |
1211 # If we now have a System Definition to parse then get the layers of components |
1211 # If we now have a System Definition to parse then get the layers of components |
1212 if self.systemDefinitionFile != None: |
1212 if self.systemDefinitionFile != None: |
1213 systemModel = raptor_xml.SystemModel(self, self.systemDefinitionFile, self.systemDefinitionBase) |
1213 systemModel = raptor_xml.SystemModel(self, self.systemDefinitionFile, self.systemDefinitionBase) |
1214 layers = self.GatherSysModelLayers(systemModel, self.systemDefinitionRequestedLayers) |
1214 layers = self.GatherSysModelLayers(systemModel, self.systemDefinitionRequestedLayers) |
1215 |
1215 |
1216 # Now get components specified on a commandline - build them after any |
1216 # Now get components specified on a commandline - build them after any |
1217 # layers in the system definition. |
1217 # layers in the system definition. |
1218 if len(self.commandlineComponents) > 0: |
1218 if len(self.commandlineComponents) > 0: |
1219 layers.append(Layer('commandline',self.commandlineComponents)) |
1219 layers.append(Layer('commandline',self.commandlineComponents)) |
1220 |
1220 |