3
|
1 |
#
|
|
2 |
# Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
3 |
# All rights reserved.
|
|
4 |
# This component and the accompanying materials are made available
|
|
5 |
# under the terms of the License "Eclipse Public License v1.0"
|
|
6 |
# which accompanies this distribution, and is available
|
|
7 |
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
|
8 |
#
|
|
9 |
# Initial Contributors:
|
|
10 |
# Nokia Corporation - initial contribution.
|
|
11 |
#
|
|
12 |
# Contributors:
|
|
13 |
#
|
|
14 |
# Description:
|
|
15 |
# raptor module
|
|
16 |
# This module represents the running Raptor program. Raptor is started
|
|
17 |
# either by calling the Main() function, which creates an instance of
|
|
18 |
# the raptor.Raptor class and calls its methods to perform a build based
|
|
19 |
# on command-line parameters, or by explicitly creating a raptor.Raptor
|
|
20 |
# instance and calling its methods to set-up and perform a build.
|
|
21 |
#
|
|
22 |
|
|
23 |
name = "sbs" # the public name for the raptor build tool
|
|
24 |
env = "SBS_HOME" # the environment variable that locates us
|
|
25 |
xml = "sbs_init.xml" # the primary initialisation file
|
|
26 |
env2 = "HOME" # the environment variable that locates the user
|
|
27 |
xml2 = ".sbs_init.xml" # the override initialisation file
|
|
28 |
|
|
29 |
import generic_path
|
|
30 |
import os
|
|
31 |
import raptor_cache
|
|
32 |
import raptor_cli
|
|
33 |
import raptor_data
|
|
34 |
import raptor_make
|
5
|
35 |
import raptor_makefile
|
3
|
36 |
import raptor_meta
|
|
37 |
import raptor_utilities
|
|
38 |
import raptor_version
|
|
39 |
import raptor_xml
|
|
40 |
import filter_list
|
|
41 |
import sys
|
|
42 |
import types
|
|
43 |
import time
|
|
44 |
import re
|
|
45 |
import traceback
|
|
46 |
import pluginbox
|
|
47 |
from xml.sax.saxutils import escape
|
|
48 |
|
|
49 |
|
|
50 |
if not "HOSTPLATFORM" in os.environ or not "HOSTPLATFORM_DIR" in os.environ:
|
|
51 |
print "Error: HOSTPLATFORM and HOSTPLATFORM_DIR must be set in the environment (this is usually done automatically by the startup script)."
|
|
52 |
sys.exit(1)
|
|
53 |
|
|
54 |
hostplatform = os.environ["HOSTPLATFORM"].split(" ")
|
|
55 |
hostplatform_dir = os.environ["HOSTPLATFORM_DIR"]
|
|
56 |
|
|
57 |
# defaults can use EPOCROOT
|
5
|
58 |
|
3
|
59 |
if "EPOCROOT" in os.environ:
|
5
|
60 |
epocroot = os.environ["EPOCROOT"].replace("\\","/")
|
3
|
61 |
else:
|
|
62 |
if 'linux' in hostplatform:
|
|
63 |
epocroot=os.environ['HOME'] + os.sep + "epocroot"
|
|
64 |
os.environ["EPOCROOT"] = epocroot
|
|
65 |
else:
|
|
66 |
epocroot = "/"
|
|
67 |
os.environ["EPOCROOT"] = os.sep
|
|
68 |
|
|
69 |
if "SBS_BUILD_DIR" in os.environ:
|
|
70 |
sbs_build_dir = os.environ["SBS_BUILD_DIR"]
|
|
71 |
else:
|
|
72 |
sbs_build_dir = (epocroot + "/epoc32/build").replace("//","/")
|
|
73 |
|
|
74 |
|
|
75 |
# only use default XML from the epoc32 tree if it exists
|
|
76 |
defaultSystemConfig = "lib/config"
|
|
77 |
epoc32UserConfigDir = generic_path.Join(epocroot, "epoc32/sbs_config")
|
|
78 |
if epoc32UserConfigDir.isDir():
|
|
79 |
defaultSystemConfig = str(epoc32UserConfigDir) + os.pathsep + defaultSystemConfig
|
|
80 |
|
|
81 |
# parameters that can be overriden by the sbs_init.xml file
|
|
82 |
# or by the command-line.
|
|
83 |
defaults = {
|
|
84 |
"allowCommandLineOverrides" : True,
|
|
85 |
"CLI" : "raptor_cli",
|
|
86 |
"buildInformation" : generic_path.Path("bld.inf"),
|
|
87 |
"defaultConfig" : "default",
|
|
88 |
"jobs": 4,
|
|
89 |
"keepGoing": False,
|
|
90 |
"logFileName" : generic_path.Join(sbs_build_dir,"Makefile.%TIME.log"),
|
|
91 |
"makeEngine" : "make",
|
|
92 |
"preferBuildInfoToSystemDefinition" : False,
|
|
93 |
"pruneDuplicateMakefiles": True,
|
|
94 |
"quiet" : False,
|
|
95 |
"systemConfig" : defaultSystemConfig,
|
|
96 |
"systemDefinition" : generic_path.Path("System_Definition.xml"),
|
|
97 |
"systemDefinitionBase" : generic_path.Path("."),
|
|
98 |
"systemFLM" : generic_path.Path("lib/flm"),
|
|
99 |
"systemPlugins" : generic_path.Path("python/plugins"),
|
|
100 |
"topMakefile" : generic_path.Join(sbs_build_dir,"Makefile"),
|
|
101 |
"tries": 1,
|
|
102 |
"writeSingleMakefile": True,
|
|
103 |
"ignoreOsDetection": False,
|
|
104 |
"toolcheck": "on",
|
|
105 |
"filterList": "filterterminal,filterlogfile"
|
|
106 |
}
|
|
107 |
|
|
108 |
|
5
|
109 |
|
|
110 |
class ModelNode(object):
|
|
111 |
""" Represents any node in a a tree of build information
|
|
112 |
e.g. a tree of bld.infs, mmps and finally things like resource blocks and string table blocks.
|
|
113 |
This is before they are produced into "build" specs.
|
|
114 |
"""
|
|
115 |
|
|
116 |
def __init__(self, id, parent = None):
|
|
117 |
self.id = id
|
|
118 |
self.type = type
|
|
119 |
self.specs = []
|
|
120 |
self.deps = []
|
|
121 |
self.children = set()
|
|
122 |
self.unfurled = False
|
|
123 |
self.parent = parent
|
|
124 |
|
|
125 |
# Allow one to make a set
|
|
126 |
def __hash__(self):
|
|
127 |
return hash(self.id)
|
|
128 |
|
|
129 |
def __cmp__(self,other):
|
|
130 |
return cmp(self.id, other)
|
3
|
131 |
|
|
132 |
def __iter__(self):
|
5
|
133 |
return iter(self.children)
|
3
|
134 |
|
|
135 |
def __getitem__(self,x):
|
|
136 |
if isinstance(x, slice):
|
5
|
137 |
return self.children[x.start:x.stop]
|
|
138 |
return self.children[x]
|
3
|
139 |
|
|
140 |
def __setitem__(self,k, v):
|
5
|
141 |
self.children[k] = v
|
3
|
142 |
|
|
143 |
def __len__(self):
|
5
|
144 |
return len(self.children)
|
3
|
145 |
|
5
|
146 |
def add(self, item):
|
|
147 |
return self.children.add(item)
|
|
148 |
|
|
149 |
def isunfurled(self, c):
|
|
150 |
return self.unfurled == False
|
3
|
151 |
|
5
|
152 |
def unfurl(self, build):
|
|
153 |
"""Find any children of this node by processing it, produces specs"""
|
|
154 |
pass
|
3
|
155 |
|
5
|
156 |
def unfurl_all(self, build):
|
|
157 |
"""Unfurl self and all children - preparatory e.g for realisation"""
|
|
158 |
if not self.unfurled:
|
|
159 |
self.unfurl(build)
|
3
|
160 |
|
5
|
161 |
self.realise_exports(build) # permit communication of dependencies between children
|
3
|
162 |
|
5
|
163 |
for c in self.children:
|
|
164 |
c.unfurl_all(build)
|
|
165 |
|
3
|
166 |
|
5
|
167 |
def realise_exports(self, build):
|
|
168 |
"""Do the things that are needed such that we can fully unfurl all
|
|
169 |
sibling nodes. i.e. this step is here to "take care" of the dependencies
|
|
170 |
between siblings.
|
|
171 |
"""
|
|
172 |
pass
|
|
173 |
|
|
174 |
def realise_makefile(self, build, specs):
|
|
175 |
makefilename_base = build.topMakefile
|
|
176 |
if self.name is not None:
|
3
|
177 |
makefile = generic_path.Path(str(makefilename_base) + "_" + raptor_utilities.sanitise(self.name))
|
|
178 |
else:
|
|
179 |
makefile = generic_path.Path(str(makefilename_base))
|
|
180 |
|
|
181 |
# insert the start time into the Makefile name?
|
|
182 |
makefile.path = makefile.path.replace("%TIME", build.timestring)
|
|
183 |
|
5
|
184 |
makefileset = build.maker.Write(makefile, specs, build.buildUnitsToBuild)
|
|
185 |
|
|
186 |
return makefileset
|
|
187 |
|
|
188 |
|
|
189 |
def realise(self, build):
|
|
190 |
"""Give the spec trees to the make engine and actually
|
|
191 |
"build" the product represented by this model node"""
|
|
192 |
# Must ensure that all children are unfurled at this point
|
|
193 |
self.unfurl_all(build)
|
|
194 |
|
|
195 |
sp = self.specs
|
|
196 |
|
|
197 |
build.AssertBuildOK()
|
|
198 |
|
|
199 |
m = self.realise_makefile(build, sp)
|
|
200 |
|
|
201 |
return build.Make(m)
|
|
202 |
|
3
|
203 |
|
5
|
204 |
class Project(ModelNode):
|
|
205 |
"""A project or, in symbian-speak, an MMP
|
|
206 |
"""
|
|
207 |
def __init__(self, filename, parent = None):
|
|
208 |
super(Project,self).__init__(filename, parent = parent)
|
|
209 |
# Assume that components are specified in mmp files for now
|
|
210 |
# One day that tyranny might end.
|
|
211 |
self.mmp_name = str(generic_path.Path.Absolute(filename))
|
|
212 |
self.id = self.mmp_name
|
|
213 |
self.unfurled = False
|
|
214 |
|
|
215 |
def makefile(self, makefilename_base, engine, named = False):
|
|
216 |
"""Makefiles for individual mmps not feasible at the moment"""
|
|
217 |
pass # Cannot, currently, "unfurl an mmp" directly but do want
|
|
218 |
# to be able to simulate the overall recursive unfurling of a build.
|
|
219 |
|
|
220 |
class Component(ModelNode):
|
|
221 |
"""A group of projects or, in symbian-speak, a bld.inf.
|
|
222 |
"""
|
|
223 |
def __init__(self, filename):
|
|
224 |
super(Component,self).__init__(filename)
|
|
225 |
# Assume that components are specified in bld.inf files for now
|
|
226 |
# One day that tyranny might end.
|
|
227 |
self.bldinf = None # Slot for a bldinf object if we spot one later
|
|
228 |
self.bldinf_filename = generic_path.Path.Absolute(filename)
|
|
229 |
|
|
230 |
self.id = str(self.bldinf_filename)
|
|
231 |
self.exportspecs = []
|
|
232 |
self.depfiles = []
|
|
233 |
self.unfurled = False # We can parse this
|
|
234 |
|
|
235 |
def AddMMP(self, filename):
|
|
236 |
self.children.add(Project(filename))
|
3
|
237 |
|
|
238 |
|
5
|
239 |
class Layer(ModelNode):
|
|
240 |
""" Some components that should be built togther
|
|
241 |
e.g. a Layer in the system definition.
|
|
242 |
"""
|
|
243 |
def __init__(self, name, componentlist=[]):
|
|
244 |
super(Layer,self).__init__(name)
|
|
245 |
self.name = name
|
|
246 |
|
|
247 |
for c in componentlist:
|
|
248 |
self.children.add(Component(c))
|
|
249 |
|
|
250 |
def unfurl(self, build):
|
|
251 |
"""Discover the children of this layer. This involves parsing the component MetaData (bld.infs, mmps).
|
|
252 |
Takes a raptor object as a parameter (build), together with a list of Configurations.
|
|
253 |
|
|
254 |
We currently have parsers that work on collections of components/bld.infs and that cannot
|
|
255 |
parse at a "finer" level. So one can't 'unfurl' an mmp at the moment.
|
|
256 |
|
|
257 |
Returns True if the object was successfully unfurled.
|
|
258 |
"""
|
|
259 |
|
|
260 |
# setup all our components
|
|
261 |
for c in self.children:
|
|
262 |
c.specs = []
|
|
263 |
|
|
264 |
self.configs = build.buildUnitsToBuild
|
|
265 |
|
|
266 |
|
|
267 |
metaReader = None
|
|
268 |
if len (self.children):
|
|
269 |
try:
|
|
270 |
# create a MetaReader that is aware of the list of
|
|
271 |
# configurations that we are trying to build.
|
|
272 |
metaReader = raptor_meta.MetaReader(build, build.buildUnitsToBuild)
|
|
273 |
|
|
274 |
# convert the list of bld.inf files into a specification
|
|
275 |
# hierarchy suitable for all the configurations we are using.
|
|
276 |
self.specs = list(build.generic_specs)
|
|
277 |
self.specs.extend(metaReader.ReadBldInfFiles(self.children, build.doExportOnly))
|
|
278 |
|
|
279 |
except raptor_meta.MetaDataError, e:
|
|
280 |
build.Error(e.Text)
|
|
281 |
|
|
282 |
self.unfurled = True
|
|
283 |
|
|
284 |
|
|
285 |
def meta_realise(self, build):
|
|
286 |
"""Generate specs that can be used to "take care of" finding out more
|
|
287 |
about this metaunit - i.e. one doesn't want to parse it immediately
|
|
288 |
but to create a makefile that will parse it.
|
|
289 |
In this case it allows bld.infs to be parsed in parallel by make."""
|
|
290 |
|
3
|
291 |
# insert the start time into the Makefile name?
|
|
292 |
|
5
|
293 |
buildconfig = build.GetConfig("build").GenerateBuildUnits(build.cache)
|
|
294 |
self.configs = build.buildUnitsToBuild
|
3
|
295 |
|
|
296 |
# Pass certain CLI flags through to the makefile-generating sbs calls
|
|
297 |
cli_options = ""
|
|
298 |
|
|
299 |
if build.debugOutput == True:
|
|
300 |
cli_options += " -d"
|
|
301 |
|
|
302 |
if build.ignoreOsDetection == True:
|
|
303 |
cli_options += " -i"
|
|
304 |
|
|
305 |
if build.keepGoing == True:
|
|
306 |
cli_options += " -k"
|
|
307 |
|
|
308 |
if build.quiet == True:
|
|
309 |
cli_options += " -q"
|
|
310 |
|
|
311 |
|
5
|
312 |
nc = len(self.children)
|
|
313 |
number_blocks = build.jobs
|
3
|
314 |
block_size = (nc / number_blocks) + 1
|
|
315 |
component_blocks = []
|
|
316 |
spec_nodes = []
|
|
317 |
|
|
318 |
b = 0
|
5
|
319 |
childlist = list(self.children)
|
3
|
320 |
while b < nc:
|
5
|
321 |
component_blocks.append(childlist[b:b+block_size])
|
3
|
322 |
b += block_size
|
|
323 |
|
5
|
324 |
while len(component_blocks[-1]) <= 0:
|
3
|
325 |
component_blocks.pop()
|
5
|
326 |
number_blocks -= 1
|
|
327 |
|
|
328 |
build.Info("Parallel Parsing: bld.infs split into %d blocks\n", number_blocks)
|
|
329 |
# Cause the binding makefiles to have the toplevel makefile's
|
|
330 |
# name. The bindee's have __pp appended.
|
|
331 |
tm = build.topMakefile.Absolute()
|
|
332 |
binding_makefiles = raptor_makefile.MakefileSet(str(tm.Dir()), build.maker.selectors, makefiles=None, filenamebase=str(tm.File()))
|
|
333 |
build.topMakefile = generic_path.Path(str(build.topMakefile) + "_pp")
|
|
334 |
|
3
|
335 |
loop_number = 0
|
|
336 |
for block in component_blocks:
|
|
337 |
loop_number += 1
|
|
338 |
specNode = raptor_data.Specification("metadata_" + self.name)
|
|
339 |
|
5
|
340 |
componentList = " ".join([str(c.bldinf_filename) for c in block])
|
|
341 |
|
|
342 |
|
|
343 |
configList = " ".join([c.name for c in self.configs if c.name != "build" ])
|
3
|
344 |
|
|
345 |
makefile_path = str(build.topMakefile) + "_" + str(loop_number)
|
|
346 |
try:
|
|
347 |
os.unlink(makefile_path) # until we have dependencies working properly
|
|
348 |
except Exception,e:
|
|
349 |
# print "couldn't unlink %s: %s" %(componentMakefileName, str(e))
|
|
350 |
pass
|
|
351 |
|
|
352 |
# add some basic data in a component-wide variant
|
|
353 |
var = raptor_data.Variant()
|
|
354 |
var.AddOperation(raptor_data.Set("COMPONENT_PATHS", componentList))
|
|
355 |
var.AddOperation(raptor_data.Set("MAKEFILE_PATH", makefile_path))
|
|
356 |
var.AddOperation(raptor_data.Set("CONFIGS", configList))
|
|
357 |
var.AddOperation(raptor_data.Set("CLI_OPTIONS", cli_options))
|
|
358 |
# Pass on '-n' (if specified) to the makefile-generating sbs calls
|
|
359 |
if build.noBuild:
|
|
360 |
var.AddOperation(raptor_data.Set("NO_BUILD", "1"))
|
|
361 |
specNode.AddVariant(var)
|
|
362 |
|
|
363 |
try:
|
|
364 |
interface = build.cache.FindNamedInterface("build.makefiles")
|
|
365 |
specNode.SetInterface(interface)
|
|
366 |
except KeyError:
|
|
367 |
build.Error("Can't find flm interface 'build.makefiles' ")
|
|
368 |
|
|
369 |
spec_nodes.append(specNode)
|
5
|
370 |
binding_makefiles.addInclude(str(makefile_path)+"_all")
|
|
371 |
|
|
372 |
ppstart = time.time()
|
|
373 |
build.Info("Parallel Parsing: time: Start %d", int(ppstart))
|
|
374 |
m = self.realise_makefile(build, spec_nodes)
|
|
375 |
m.close()
|
|
376 |
gen_result = build.Make(m)
|
3
|
377 |
|
5
|
378 |
ppfinish = time.time()
|
|
379 |
build.Info("Parallel Parsing: time: Finish %d", int(ppfinish))
|
|
380 |
build.Info("Parallel Parsing: time: Parse Duration %d", int(ppfinish - ppstart))
|
|
381 |
build.Debug("Binding Makefile base name is %s ", binding_makefiles.filenamebase)
|
|
382 |
binding_makefiles.close()
|
|
383 |
b = build.Make(binding_makefiles)
|
|
384 |
buildfinish = time.time()
|
|
385 |
build.Info("Parallel Parsing: time: Build Duration %d", int(buildfinish - ppfinish))
|
|
386 |
return b
|
3
|
387 |
|
|
388 |
|
5
|
389 |
|
|
390 |
|
|
391 |
class BuildCannotProgressException(Exception):
|
3
|
392 |
pass
|
|
393 |
|
|
394 |
# raptor module classes
|
|
395 |
|
|
396 |
class Raptor(object):
|
|
397 |
"""An instance of a running Raptor program.
|
|
398 |
|
|
399 |
When operated from the command-line there is a single Raptor object
|
|
400 |
created by the Main function. When operated by an IDE several Raptor
|
|
401 |
objects may be created and operated at the same time."""
|
|
402 |
|
|
403 |
|
|
404 |
M_BUILD = 1
|
|
405 |
M_VERSION = 2
|
|
406 |
|
|
407 |
def __init__(self, home = None):
|
|
408 |
|
|
409 |
self.DefaultSetUp(home)
|
|
410 |
|
|
411 |
|
|
412 |
def DefaultSetUp(self, home = None):
|
|
413 |
"revert to the default set-up state"
|
|
414 |
self.errorCode = 0
|
|
415 |
self.skipAll = False
|
|
416 |
self.summary = True
|
|
417 |
self.out = sys.stdout # Just until filters get started.
|
|
418 |
|
|
419 |
# Create a bootstrap output system.
|
|
420 |
self.out = filter_list.FilterList()
|
|
421 |
|
|
422 |
if home == None:
|
|
423 |
try:
|
|
424 |
home = os.environ[env]
|
|
425 |
except KeyError:
|
|
426 |
home = os.getcwd()
|
|
427 |
|
|
428 |
# make sure the home directory exists
|
|
429 |
self.home = generic_path.Path(home).Absolute()
|
|
430 |
|
|
431 |
if not self.home.isDir():
|
|
432 |
self.Error("%s '%s' is not a directory", env, self.home)
|
|
433 |
return
|
|
434 |
|
|
435 |
# the set-up file location.
|
|
436 |
# use the override "env2/xml2" if it exists
|
|
437 |
# else use the primary "env/xml" if it exists
|
|
438 |
# else keep the hard-coded defaults.
|
|
439 |
self.raptorXML = self.home.Append(xml)
|
|
440 |
|
|
441 |
if env2 in os.environ:
|
|
442 |
sbs_init = generic_path.Join(os.environ[env2], xml2)
|
|
443 |
if sbs_init.isFile():
|
|
444 |
self.raptorXML = sbs_init
|
|
445 |
|
|
446 |
# things that can be overridden by the set-up file
|
|
447 |
for key, value in defaults.items():
|
|
448 |
self.__dict__[key] = value
|
|
449 |
|
|
450 |
# things to initialise
|
|
451 |
self.args = []
|
|
452 |
|
5
|
453 |
self.layers = []
|
|
454 |
self.orderLayers = False
|
3
|
455 |
self.commandlineComponents = []
|
|
456 |
|
|
457 |
self.systemModel = None
|
|
458 |
self.systemDefinitionFile = None
|
|
459 |
self.systemDefinitionRequestedLayers = []
|
|
460 |
self.systemDefinitionOrderLayers = False
|
|
461 |
|
|
462 |
self.specGroups = {}
|
|
463 |
|
|
464 |
self.configNames = []
|
|
465 |
self.configsToBuild = set()
|
|
466 |
self.makeOptions = []
|
|
467 |
self.maker = None
|
|
468 |
self.debugOutput = False
|
|
469 |
self.doExportOnly = False
|
|
470 |
self.noBuild = False
|
|
471 |
self.noDependInclude = False
|
|
472 |
self.projects = set()
|
|
473 |
|
|
474 |
self.cache = raptor_cache.Cache(self)
|
|
475 |
self.override = {env: str(self.home)}
|
|
476 |
self.targets = []
|
|
477 |
self.defaultTargets = []
|
|
478 |
|
|
479 |
self.doCheck = False
|
|
480 |
self.doWhat = False
|
|
481 |
self.doParallelParsing = False
|
|
482 |
self.mission = Raptor.M_BUILD
|
|
483 |
|
|
484 |
# what platform and filesystem are we running on?
|
|
485 |
self.filesystem = raptor_utilities.getOSFileSystem()
|
|
486 |
|
|
487 |
self.toolset = None
|
|
488 |
|
|
489 |
self.starttime = time.time()
|
|
490 |
self.timestring = time.strftime("%Y-%m-%d-%H-%M-%S")
|
|
491 |
|
|
492 |
self.fatalErrorState = False
|
|
493 |
|
|
494 |
def AddConfigList(self, configPathList):
|
|
495 |
# this function converts cmd line option into a list
|
|
496 |
# and prepends it to default config.
|
|
497 |
self.configPath = generic_path.NormalisePathList(configPathList.split(os.pathsep)) + self.configPath
|
|
498 |
return True
|
|
499 |
|
|
500 |
def AddConfigName(self, name):
|
5
|
501 |
if name == "build":
|
|
502 |
traceback.print_stack((sys.stdout))
|
|
503 |
sys.exit(1)
|
3
|
504 |
self.configNames.append(name)
|
|
505 |
return True
|
|
506 |
|
|
507 |
def RunQuietly(self, TrueOrFalse):
|
|
508 |
self.quiet = TrueOrFalse
|
|
509 |
return True
|
|
510 |
|
|
511 |
def SetCheck(self, TrueOrFalse):
|
|
512 |
self.doCheck = TrueOrFalse
|
|
513 |
return True
|
|
514 |
|
|
515 |
def SetWhat(self, TrueOrFalse):
|
|
516 |
self.doWhat = TrueOrFalse
|
|
517 |
return True
|
|
518 |
|
|
519 |
def SetEnv(self, name, value):
|
|
520 |
self.override[name] = value
|
|
521 |
|
|
522 |
def AddTarget(self, target):
|
|
523 |
if self.doCheck or self.doWhat:
|
|
524 |
self.Warn("ignoring target %s because --what or --check is specified.\n", target)
|
|
525 |
else:
|
|
526 |
self.targets.append(target)
|
|
527 |
|
|
528 |
def AddSourceTarget(self, filename):
|
|
529 |
# source targets are sanitised and then added as if they were a "normal" makefile target
|
|
530 |
# in addition they have a default, empty, top-level target assigned in order that they can
|
|
531 |
# be presented to any generated makefile without error
|
|
532 |
sourceTarget = generic_path.Path(filename).Absolute()
|
|
533 |
sourceTarget = 'SOURCETARGET_' + raptor_utilities.sanitise(str(sourceTarget))
|
|
534 |
self.AddTarget(sourceTarget)
|
|
535 |
self.defaultTargets.append(sourceTarget)
|
|
536 |
return True
|
|
537 |
|
|
538 |
def SetSysDefFile(self, filename):
|
|
539 |
self.systemDefinitionFile = generic_path.Path(filename)
|
|
540 |
return True
|
|
541 |
|
|
542 |
def SetSysDefBase(self, path):
|
|
543 |
self.systemDefinitionBase = generic_path.Path(path)
|
|
544 |
return True
|
|
545 |
|
|
546 |
def AddSysDefLayer(self, layer):
|
|
547 |
self.systemDefinitionRequestedLayers.append(layer)
|
|
548 |
return True
|
|
549 |
|
|
550 |
def SetSysDefOrderLayers(self, TrueOrFalse):
|
|
551 |
self.systemDefinitionOrderLayers = TrueOrFalse
|
|
552 |
return True
|
|
553 |
|
|
554 |
def AddBuildInfoFile(self, filename):
|
|
555 |
bldinf = generic_path.Path(filename).Absolute()
|
|
556 |
self.commandlineComponents.append(bldinf)
|
|
557 |
return True
|
|
558 |
|
|
559 |
def SetTopMakefile(self, filename):
|
|
560 |
self.topMakefile = generic_path.Path(filename)
|
|
561 |
return True
|
|
562 |
|
|
563 |
def SetDebugOutput(self, TrueOrFalse):
|
|
564 |
self.debugOutput = TrueOrFalse
|
|
565 |
return True
|
|
566 |
|
|
567 |
def SetExportOnly(self, TrueOrFalse):
|
|
568 |
self.doExportOnly = TrueOrFalse
|
|
569 |
return True
|
|
570 |
|
|
571 |
def SetNoBuild(self, TrueOrFalse):
|
|
572 |
self.noBuild = TrueOrFalse
|
|
573 |
return True
|
|
574 |
|
|
575 |
def SetNoDependInclude(self, TrueOrFalse):
|
|
576 |
self.noDependInclude = TrueOrFalse
|
|
577 |
return True
|
|
578 |
|
|
579 |
def SetKeepGoing(self, TrueOrFalse):
|
|
580 |
self.keepGoing = TrueOrFalse
|
|
581 |
return True
|
|
582 |
|
|
583 |
def SetLogFileName(self, logfile):
|
|
584 |
if logfile == "-":
|
|
585 |
self.logFileName = None # stdout
|
|
586 |
else:
|
|
587 |
self.logFileName = generic_path.Path(logfile)
|
|
588 |
return True
|
|
589 |
|
|
590 |
def SetMakeEngine(self, makeEngine):
|
|
591 |
self.makeEngine = makeEngine
|
|
592 |
return True
|
|
593 |
|
|
594 |
def AddMakeOption(self, makeOption):
|
|
595 |
self.makeOptions.append(makeOption)
|
|
596 |
return True
|
|
597 |
|
|
598 |
def SetJobs(self, numberOfJobs):
|
|
599 |
try:
|
|
600 |
self.jobs = int(numberOfJobs)
|
|
601 |
except ValueError:
|
|
602 |
self.jobs = 0
|
|
603 |
|
|
604 |
if self.jobs < 1:
|
|
605 |
self.Warn("The number of jobs (%s) must be a positive integer\n", numberOfJobs)
|
|
606 |
self.jobs = 1
|
|
607 |
return False
|
|
608 |
return True
|
|
609 |
|
|
610 |
def SetTries(self, numberOfTries):
|
|
611 |
try:
|
|
612 |
self.tries = int(numberOfTries)
|
|
613 |
except ValueError:
|
|
614 |
self.tries = 0
|
|
615 |
|
|
616 |
if self.tries < 1:
|
|
617 |
self.Warn("The number of tries (%s) must be a positive integer\n", numberOfTries)
|
|
618 |
self.tries = 1
|
|
619 |
return False
|
|
620 |
return True
|
|
621 |
|
|
622 |
def SetToolCheck(self, type):
|
|
623 |
type = type.lower()
|
|
624 |
toolcheck_types= [ "forced", "on", "off" ]
|
|
625 |
if type in toolcheck_types:
|
|
626 |
self.toolcheck=type
|
|
627 |
else:
|
|
628 |
self.Warn("toolcheck option must be one of: %s" % toolcheck_types)
|
|
629 |
return False
|
|
630 |
|
|
631 |
return True
|
|
632 |
|
|
633 |
def SetParallelParsing(self, type):
|
|
634 |
type = type.lower()
|
|
635 |
if type == "on":
|
|
636 |
self.doParallelParsing = True
|
5
|
637 |
elif type == "slave":
|
|
638 |
self.isParallelParsingSlave = True
|
3
|
639 |
elif type == "off":
|
|
640 |
self.doParallelParsing = False
|
|
641 |
else:
|
|
642 |
self.Warn(" parallel parsing option must be either 'on' or 'off' (was %s)" % type)
|
|
643 |
return False
|
|
644 |
|
|
645 |
return True
|
|
646 |
|
|
647 |
def AddProject(self, projectName):
|
|
648 |
self.projects.add(projectName.lower())
|
|
649 |
return True
|
|
650 |
|
|
651 |
def FilterList(self, value):
|
|
652 |
self.filterList = value
|
|
653 |
return True
|
|
654 |
|
|
655 |
def IgnoreOsDetection(self, value):
|
|
656 |
self.ignoreOsDetection = value
|
|
657 |
return True
|
|
658 |
|
|
659 |
def PrintVersion(self,dummy):
|
|
660 |
global name
|
5
|
661 |
print name, "version", raptor_version.fullversion()
|
3
|
662 |
self.mission = Raptor.M_VERSION
|
|
663 |
return False
|
|
664 |
|
|
665 |
# worker methods
|
|
666 |
|
|
667 |
def Introduction(self):
|
|
668 |
"""Print a header of useful information about Raptor"""
|
|
669 |
|
5
|
670 |
self.Info("%s: version %s\n", name, raptor_version.fullversion())
|
3
|
671 |
|
|
672 |
self.Info("%s %s", env, str(self.home))
|
|
673 |
self.Info("Set-up %s", str(self.raptorXML))
|
|
674 |
self.Info("Command-line-arguments %s", " ".join(self.args))
|
|
675 |
self.Info("Current working directory %s", os.getcwd())
|
|
676 |
|
|
677 |
# the inherited environment
|
|
678 |
for e, value in os.environ.items():
|
5
|
679 |
self.Info("Environment %s=%s", e, value.replace("]]>", "]]>"))
|
3
|
680 |
|
|
681 |
# and some general debug stuff
|
|
682 |
self.Debug("Platform %s", "-".join(hostplatform))
|
|
683 |
self.Debug("Filesystem %s", self.filesystem)
|
|
684 |
self.Debug("Python %d.%d.%d", *sys.version_info[:3])
|
|
685 |
self.Debug("Command-line-parser %s", self.CLI)
|
|
686 |
|
|
687 |
for e,value in self.override.items():
|
|
688 |
self.Debug("Override %s = %s", e, value)
|
|
689 |
|
|
690 |
for t in self.targets:
|
|
691 |
self.Debug("Target %s", t)
|
|
692 |
|
|
693 |
|
|
694 |
def ConfigFile(self):
|
|
695 |
if not self.raptorXML.isFile():
|
|
696 |
return
|
|
697 |
|
|
698 |
self.cache.Load(self.raptorXML)
|
|
699 |
|
|
700 |
# find the 'defaults.raptor' variant and extract the values
|
|
701 |
try:
|
|
702 |
var = self.cache.FindNamedVariant("defaults.init")
|
|
703 |
evaluator = self.GetEvaluator( None, raptor_data.BuildUnit(var.name,[var]) )
|
|
704 |
|
|
705 |
for key, value in defaults.items():
|
|
706 |
newValue = evaluator.Resolve(key)
|
|
707 |
|
|
708 |
if newValue != None:
|
|
709 |
# got a string for the value
|
|
710 |
if type(value) == types.BooleanType:
|
|
711 |
newValue = (newValue.lower() != "false")
|
|
712 |
elif type(value) == types.IntType:
|
|
713 |
newValue = int(newValue)
|
|
714 |
elif isinstance(value, generic_path.Path):
|
|
715 |
newValue = generic_path.Path(newValue)
|
|
716 |
|
|
717 |
self.__dict__[key] = newValue
|
|
718 |
|
|
719 |
except KeyError:
|
|
720 |
# it is OK to not have this but useful to say it wasn't there
|
|
721 |
self.Info("No 'defaults.init' configuration found in " + str(self.raptorXML))
|
|
722 |
|
|
723 |
|
|
724 |
def CommandLine(self, args):
|
|
725 |
# remember the arguments for the log
|
|
726 |
self.args = args
|
|
727 |
|
|
728 |
# assuming self.CLI = "raptor_cli"
|
|
729 |
more_to_do = raptor_cli.GetArgs(self, args)
|
|
730 |
|
|
731 |
# resolve inter-argument dependencies.
|
|
732 |
# --what or --check implies the WHAT target and FilterWhat Filter
|
|
733 |
if self.doWhat or self.doCheck:
|
|
734 |
self.targets = ["WHAT"]
|
|
735 |
self.filterList = "filterwhat"
|
|
736 |
|
|
737 |
else:
|
|
738 |
# 1. CLEAN/CLEANEXPORT/REALLYCLEAN needs the FilterClean filter.
|
|
739 |
# 2. Targets that clean should not be combined with other targets.
|
|
740 |
|
|
741 |
targets = [x.lower() for x in self.targets]
|
|
742 |
|
|
743 |
CL = "clean"
|
|
744 |
CE = "cleanexport"
|
|
745 |
RC = "reallyclean"
|
|
746 |
|
|
747 |
is_clean = 0
|
|
748 |
is_suspicious_clean = 0
|
|
749 |
|
|
750 |
if CL in targets and CE in targets:
|
|
751 |
is_clean = 1
|
|
752 |
if len(targets) > 2:
|
|
753 |
is_suspicious_clean = 1
|
|
754 |
elif RC in targets or CL in targets or CE in targets:
|
|
755 |
is_clean = 1
|
|
756 |
if len(targets) > 1:
|
|
757 |
is_suspicious_clean = 1
|
|
758 |
|
|
759 |
if is_clean:
|
|
760 |
self.filterList += ",filterclean"
|
|
761 |
if is_suspicious_clean:
|
|
762 |
self.Warn('CLEAN, CLEANEXPORT and a REALLYCLEAN should not be combined with other targets as the result is unpredictable.')
|
|
763 |
|
|
764 |
if not more_to_do:
|
|
765 |
self.skipAll = True # nothing else to do
|
|
766 |
|
|
767 |
def ProcessConfig(self):
|
|
768 |
# this function will perform additional processing of config
|
|
769 |
|
|
770 |
# create list of generic paths
|
|
771 |
self.configPath = generic_path.NormalisePathList(self.systemConfig.split(os.pathsep))
|
|
772 |
|
|
773 |
def LoadCache(self):
|
|
774 |
def mkAbsolute(aGenericPath):
|
|
775 |
""" internal function to make a generic_path.Path
|
|
776 |
absolute if required"""
|
|
777 |
if not aGenericPath.isAbsolute():
|
|
778 |
return self.home.Append(aGenericPath)
|
|
779 |
else:
|
|
780 |
return aGenericPath
|
|
781 |
|
|
782 |
# make generic paths absolute (if required)
|
|
783 |
self.configPath = map(mkAbsolute, self.configPath)
|
|
784 |
self.cache.Load(self.configPath)
|
|
785 |
|
|
786 |
if not self.systemFLM.isAbsolute():
|
|
787 |
self.systemFLM = self.home.Append(self.systemFLM)
|
|
788 |
|
|
789 |
self.cache.Load(self.systemFLM)
|
|
790 |
|
|
791 |
def GetConfig(self, configname):
|
|
792 |
names = configname.split(".")
|
|
793 |
|
|
794 |
cache = self.cache
|
|
795 |
|
|
796 |
base = names[0]
|
|
797 |
mods = names[1:]
|
|
798 |
|
|
799 |
if base in cache.groups:
|
|
800 |
x = cache.FindNamedGroup(base)
|
|
801 |
elif base in cache.aliases:
|
|
802 |
x = cache.FindNamedAlias(base)
|
|
803 |
elif base in cache.variants:
|
|
804 |
x = cache.FindNamedVariant(base)
|
|
805 |
else:
|
|
806 |
raise Exception("Unknown build configuration '%s'" % configname)
|
|
807 |
|
|
808 |
x.ClearModifiers()
|
|
809 |
|
|
810 |
|
|
811 |
try:
|
|
812 |
for m in mods: x.AddModifier( cache.FindNamedVariant(m) )
|
|
813 |
except KeyError:
|
|
814 |
raise Exception("Unknown build configuration '%s'" % configname)
|
|
815 |
return x
|
|
816 |
|
|
817 |
def GetBuildUnitsToBuild(self, configNames):
|
|
818 |
"""Return a list of the configuration objects that correspond to the
|
|
819 |
list of configuration names in the configNames parameter.
|
|
820 |
|
|
821 |
raptor.GetBuildUnitsToBuild(["armv5", "winscw"])
|
|
822 |
>>> [ config1, config2, ... , configN ]
|
|
823 |
"""
|
|
824 |
|
|
825 |
if len(configNames) == 0:
|
|
826 |
# use default config
|
|
827 |
if len(self.defaultConfig) == 0:
|
|
828 |
self.Warn("No default configuration name")
|
|
829 |
else:
|
|
830 |
configNames.append(self.defaultConfig)
|
|
831 |
|
|
832 |
buildUnitsToBuild = set()
|
|
833 |
|
|
834 |
|
|
835 |
for c in set(configNames):
|
5
|
836 |
self.Debug("BuildUnit: %s", c)
|
3
|
837 |
try:
|
|
838 |
x = self.GetConfig(c)
|
5
|
839 |
gb = x.GenerateBuildUnits(self.cache)
|
|
840 |
buildUnitsToBuild.update( gb )
|
3
|
841 |
except Exception, e:
|
|
842 |
self.FatalError(str(e))
|
|
843 |
|
|
844 |
for b in buildUnitsToBuild:
|
|
845 |
self.Info("Buildable configuration '%s'", b.name)
|
|
846 |
|
|
847 |
if len(buildUnitsToBuild) == 0:
|
|
848 |
self.Error("No build configurations given")
|
|
849 |
|
|
850 |
return buildUnitsToBuild
|
|
851 |
|
|
852 |
def CheckToolset(self, evaluator, configname):
|
|
853 |
"""Check the toolset for a particular config, allow other objects access
|
|
854 |
to the toolset for this build (e.g. the raptor_make class)."""
|
|
855 |
if self.toolset is None:
|
|
856 |
if self.toolcheck == 'on':
|
|
857 |
self.toolset = raptor_data.ToolSet(log=self)
|
|
858 |
elif self.toolcheck == 'forced' :
|
|
859 |
self.toolset = raptor_data.ToolSet(log=self, forced=True)
|
|
860 |
else:
|
|
861 |
return True
|
|
862 |
|
|
863 |
return self.toolset.check(evaluator, configname)
|
|
864 |
|
|
865 |
|
|
866 |
def CheckConfigs(self, configs):
|
|
867 |
""" Tool checking for all the buildable configurations
|
|
868 |
NB. We are allowed to use different tool versions for different
|
|
869 |
configurations."""
|
|
870 |
|
|
871 |
tools_ok = True
|
|
872 |
for b in configs:
|
|
873 |
self.Debug("Tool check for %s", b.name)
|
|
874 |
evaluator = self.GetEvaluator(None, b, gathertools=True)
|
|
875 |
tools_ok = tools_ok and self.CheckToolset(evaluator, b.name)
|
|
876 |
|
|
877 |
return tools_ok
|
|
878 |
|
|
879 |
|
|
880 |
|
|
881 |
def GatherSysModelLayers(self, systemModel, systemDefinitionRequestedLayers):
|
|
882 |
"""Return a list of lists of components to be built.
|
|
883 |
|
|
884 |
components = GatherSysModelLayers(self, configurations)
|
|
885 |
>>> set("abc/group/bld.inf","def/group/bld.inf, ....")
|
|
886 |
"""
|
|
887 |
layersToBuild = []
|
|
888 |
|
|
889 |
if systemModel:
|
|
890 |
# We either process all available layers in the system model, or a subset of
|
|
891 |
# layers specified on the command line. In both cases, the processing is the same,
|
|
892 |
# and can be subject to ordering if explicitly requested.
|
|
893 |
systemModel.DumpInfo()
|
|
894 |
|
|
895 |
if systemDefinitionRequestedLayers:
|
|
896 |
layersToProcess = systemDefinitionRequestedLayers
|
|
897 |
else:
|
|
898 |
layersToProcess = systemModel.GetLayerNames()
|
|
899 |
|
|
900 |
for layer in layersToProcess:
|
|
901 |
systemModel.DumpLayerInfo(layer)
|
|
902 |
|
|
903 |
if systemModel.IsLayerBuildable(layer):
|
5
|
904 |
layersToBuild.append(Layer(layer,
|
3
|
905 |
systemModel.GetLayerComponents(layer)))
|
|
906 |
|
|
907 |
return layersToBuild
|
|
908 |
|
|
909 |
|
5
|
910 |
# Add bld.inf or system definition xml to command line layers (depending on preference)
|
3
|
911 |
def FindSysDefIn(self, aDir = None):
|
|
912 |
# Find a system definition file
|
|
913 |
|
|
914 |
if aDir is None:
|
|
915 |
dir = generic_path.CurrentDir()
|
|
916 |
else:
|
|
917 |
dir = generic_path.Path(aDir)
|
|
918 |
|
|
919 |
sysDef = dir.Append(self.systemDefinition)
|
|
920 |
if not sysDef.isFile():
|
|
921 |
return None
|
|
922 |
|
|
923 |
return sysDef
|
|
924 |
|
|
925 |
|
|
926 |
def FindComponentIn(self, aDir = None):
|
|
927 |
# look for a bld.inf
|
|
928 |
|
|
929 |
if aDir is None:
|
|
930 |
dir = generic_path.CurrentDir()
|
|
931 |
else:
|
|
932 |
dir = generic_path.Path(aDir)
|
|
933 |
|
|
934 |
bldInf = dir.Append(self.buildInformation)
|
|
935 |
componentgroup = []
|
|
936 |
|
|
937 |
if bldInf.isFile():
|
|
938 |
return bldInf
|
|
939 |
|
|
940 |
return None
|
|
941 |
|
|
942 |
def GenerateGenericSpecs(self, configsToBuild):
|
|
943 |
# if a Configuration has any config-wide interfaces
|
|
944 |
# then add a Specification node to call each of them.
|
|
945 |
configWide = {}
|
|
946 |
genericSpecs = []
|
|
947 |
for c in configsToBuild:
|
|
948 |
evaluator = self.GetEvaluator(None, c)
|
|
949 |
iface = evaluator.Get("INTERFACE.config")
|
|
950 |
if iface:
|
|
951 |
if iface in configWide:
|
|
952 |
# seen it already, so reuse the node
|
|
953 |
filter = configWide[iface]
|
|
954 |
filter.AddConfigCondition(c.name)
|
|
955 |
else:
|
|
956 |
# create a new node
|
5
|
957 |
filter = raptor_data.Filter(name = "config_wide")
|
3
|
958 |
filter.AddConfigCondition(c.name)
|
|
959 |
for i in iface.split():
|
|
960 |
spec = raptor_data.Specification(i)
|
|
961 |
spec.SetInterface(i)
|
|
962 |
filter.AddChildSpecification(spec)
|
|
963 |
# remember it, use it
|
|
964 |
configWide[iface] = filter
|
|
965 |
genericSpecs.append(filter)
|
|
966 |
|
|
967 |
return genericSpecs
|
|
968 |
|
|
969 |
|
|
970 |
def GetEvaluator(self, specification, configuration, gathertools=False):
|
|
971 |
""" this will perform some caching later """
|
5
|
972 |
return raptor_data.Evaluator(specification, configuration, gathertools=gathertools, cache = self.cache)
|
3
|
973 |
|
|
974 |
|
5
|
975 |
def Make(self, makefileset):
|
|
976 |
if not self.noBuild and makefileset is not None:
|
|
977 |
if self.maker.Make(makefileset):
|
|
978 |
self.Info("The make-engine exited successfully.")
|
|
979 |
return True
|
|
980 |
else:
|
|
981 |
self.Error("The make-engine exited with errors.")
|
|
982 |
return False
|
|
983 |
else:
|
|
984 |
self.Info("No build performed")
|
3
|
985 |
|
|
986 |
|
|
987 |
|
|
988 |
def Report(self):
|
|
989 |
if self.quiet:
|
|
990 |
return
|
|
991 |
|
|
992 |
self.endtime = time.time()
|
|
993 |
self.runtime = int(0.5 + self.endtime - self.starttime)
|
|
994 |
self.raptor_params.runtime = self.runtime
|
|
995 |
self.Info("Run time %s seconds" % self.runtime)
|
|
996 |
|
|
997 |
def AssertBuildOK(self):
|
5
|
998 |
"""Raise a BuildCannotProgressException if no further processing is required
|
3
|
999 |
"""
|
|
1000 |
if self.Skip():
|
5
|
1001 |
raise BuildCannotProgressException("")
|
3
|
1002 |
|
|
1003 |
return True
|
|
1004 |
|
|
1005 |
def Skip(self):
|
|
1006 |
"""Indicate not to perform operation if:
|
|
1007 |
fatalErrorState is set
|
|
1008 |
an error code is set but we're not in keepgoing mode
|
|
1009 |
"""
|
|
1010 |
return self.fatalErrorState or ((self.errorCode != 0) and (not self.keepGoing))
|
|
1011 |
|
|
1012 |
|
|
1013 |
# log file open/close
|
|
1014 |
|
|
1015 |
def OpenLog(self):
|
|
1016 |
"""Open a log file for the various I/O methods to write to."""
|
|
1017 |
|
|
1018 |
try:
|
|
1019 |
# Find all the raptor plugins and put them into a pluginbox.
|
|
1020 |
if not self.systemPlugins.isAbsolute():
|
|
1021 |
self.systemPlugins = self.home.Append(self.systemPlugins)
|
|
1022 |
|
|
1023 |
self.pbox = pluginbox.PluginBox(str(self.systemPlugins))
|
|
1024 |
|
|
1025 |
self.raptor_params = BuildStats(self)
|
|
1026 |
|
|
1027 |
# Open the requested plugins using the pluginbox
|
|
1028 |
self.out.open(self.raptor_params, self.filterList.split(','), self.pbox)
|
|
1029 |
|
|
1030 |
# log header
|
|
1031 |
self.out.write("<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n")
|
|
1032 |
|
|
1033 |
namespace = "http://symbian.com/xml/build/log"
|
|
1034 |
schema = "http://symbian.com/xml/build/log/1_0.xsd"
|
|
1035 |
|
|
1036 |
self.out.write("<buildlog sbs_version=\"%s\" xmlns=\"%s\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"%s %s\">\n"
|
5
|
1037 |
% (raptor_version.fullversion(), namespace, namespace, schema))
|
3
|
1038 |
self.logOpen = True
|
|
1039 |
except Exception,e:
|
|
1040 |
self.out = sys.stdout # make sure that we can actually get errors out.
|
|
1041 |
self.logOpen = False
|
9
|
1042 |
self.FatalError("Unable to open the output logs: %s" % str(e))
|
3
|
1043 |
|
|
1044 |
def CloseLog(self):
|
|
1045 |
if self.logOpen:
|
|
1046 |
self.out.summary()
|
|
1047 |
self.out.write("</buildlog>\n")
|
|
1048 |
|
|
1049 |
if not self.out.close():
|
|
1050 |
self.errorCode = 1
|
|
1051 |
|
|
1052 |
|
|
1053 |
def Cleanup(self):
|
|
1054 |
# ensure that the toolset cache is flushed.
|
|
1055 |
if self.toolset is not None:
|
|
1056 |
self.toolset.write()
|
|
1057 |
|
|
1058 |
# I/O methods
|
|
1059 |
|
|
1060 |
@staticmethod
|
|
1061 |
def attributeString(dictionary):
|
|
1062 |
"turn a dictionary into a string of XML attributes"
|
|
1063 |
atts = ""
|
|
1064 |
for a,v in dictionary.items():
|
|
1065 |
atts += " " + a + "='" + v + "'"
|
|
1066 |
return atts
|
|
1067 |
|
|
1068 |
def Info(self, format, *extras, **attributes):
|
|
1069 |
"""Send an information message to the configured channel
|
|
1070 |
(XML control characters will be escaped)
|
|
1071 |
"""
|
|
1072 |
self.out.write("<info" + self.attributeString(attributes) + ">" +
|
|
1073 |
escape(format % extras) + "</info>\n")
|
|
1074 |
|
|
1075 |
def Debug(self, format, *extras, **attributes):
|
|
1076 |
"Send a debugging message to the configured channel"
|
|
1077 |
|
|
1078 |
# the debug text is out of our control so wrap it in a CDATA
|
|
1079 |
# in case it contains characters special to XML... like <>
|
|
1080 |
if self.debugOutput:
|
|
1081 |
self.out.write("<debug" + self.attributeString(attributes) + ">" +
|
|
1082 |
"><![CDATA[\n" + (format % extras) + "\n]]></debug>\n")
|
|
1083 |
|
|
1084 |
def Warn(self, format, *extras, **attributes):
|
|
1085 |
"""Send a warning message to the configured channel
|
|
1086 |
(XML control characters will be escaped)
|
|
1087 |
"""
|
|
1088 |
self.out.write("<warning" + self.attributeString(attributes) + ">" +
|
|
1089 |
escape(format % extras) + "</warning>\n")
|
|
1090 |
|
|
1091 |
def FatalError(self, format, *extras, **attributes):
|
|
1092 |
"""Send an error message to the configured channel. This implies such a serious
|
|
1093 |
error that the entire build must be shut down asap whilst still finishing off
|
|
1094 |
correctly whatever housekeeping is possible e.g. producing error reports.
|
|
1095 |
Remains quiet if the raptor object is already in a fatal state since there
|
|
1096 |
further errors are probably triggered by the first.
|
|
1097 |
"""
|
|
1098 |
if not self.fatalErrorState:
|
|
1099 |
self.out.write("<error" + self.attributeString(attributes) + ">" +
|
|
1100 |
(format % extras) + "</error>\n")
|
|
1101 |
self.errorCode = 1
|
|
1102 |
self.fatalErrorState = True
|
|
1103 |
|
|
1104 |
def Error(self, format, *extras, **attributes):
|
|
1105 |
"""Send an error message to the configured channel
|
|
1106 |
(XML control characters will be escaped)
|
|
1107 |
"""
|
|
1108 |
self.out.write("<error" + self.attributeString(attributes) + ">" +
|
|
1109 |
escape(format % extras) + "</error>\n")
|
|
1110 |
self.errorCode = 1
|
|
1111 |
|
|
1112 |
|
|
1113 |
def PrintXML(self, format, *extras):
|
|
1114 |
"Print to configured channel (no newline is added) (assumes valid xml)"
|
|
1115 |
if format:
|
|
1116 |
self.out.write(format % extras)
|
|
1117 |
|
5
|
1118 |
def GetLayersFromCLI(self):
|
|
1119 |
"""Returns the list of layers as specified by the
|
3
|
1120 |
commandline interface to Raptor e.g. parameters
|
|
1121 |
or the current directory"""
|
5
|
1122 |
layers=[]
|
3
|
1123 |
# Look for bld.infs or sysdefs in the current dir if none were specified
|
|
1124 |
if self.systemDefinitionFile == None and len(self.commandlineComponents) == 0:
|
|
1125 |
if not self.preferBuildInfoToSystemDefinition:
|
|
1126 |
cwd = os.getcwd()
|
|
1127 |
self.systemDefinitionFile = self.FindSysDefIn(cwd)
|
|
1128 |
if self.systemDefinitionFile == None:
|
|
1129 |
aComponent = self.FindComponentIn(cwd)
|
|
1130 |
if aComponent:
|
5
|
1131 |
layers.append(Layer('default',[aComponent]))
|
3
|
1132 |
else:
|
|
1133 |
aComponent = self.FindComponentIn(cwd)
|
|
1134 |
if aComponent is None:
|
|
1135 |
self.systemDefinitionFile = self.FindSysDefIn(cwd)
|
|
1136 |
else:
|
5
|
1137 |
layers.append(Layer('default',[aComponent]))
|
3
|
1138 |
|
5
|
1139 |
if len(layers) <= 0 and self.systemDefinitionFile == None:
|
3
|
1140 |
self.Warn("No default bld.inf or system definition file found in current directory (%s)", cwd)
|
|
1141 |
|
|
1142 |
# If we now have a System Definition to parse then get the layers of components
|
|
1143 |
if self.systemDefinitionFile != None:
|
|
1144 |
systemModel = raptor_xml.SystemModel(self, self.systemDefinitionFile, self.systemDefinitionBase)
|
5
|
1145 |
layers = self.GatherSysModelLayers(systemModel, self.systemDefinitionRequestedLayers)
|
3
|
1146 |
|
|
1147 |
# Now get components specified on a commandline - build them after any
|
|
1148 |
# layers in the system definition.
|
|
1149 |
if len(self.commandlineComponents) > 0:
|
5
|
1150 |
layers.append(Layer('commandline',self.commandlineComponents))
|
3
|
1151 |
|
|
1152 |
# If we aren't building components in order then flatten down
|
|
1153 |
# the groups
|
|
1154 |
if not self.systemDefinitionOrderLayers:
|
|
1155 |
# Flatten the layers into one group of components if
|
|
1156 |
# we are not required to build them in order.
|
5
|
1157 |
newcg = Layer("all")
|
|
1158 |
for cg in layers:
|
|
1159 |
for c in cg:
|
|
1160 |
newcg.add(c)
|
|
1161 |
layers = [newcg]
|
3
|
1162 |
|
5
|
1163 |
return layers
|
3
|
1164 |
|
|
1165 |
def Build(self):
|
|
1166 |
|
|
1167 |
if self.mission != Raptor.M_BUILD: # help or version requested instead.
|
|
1168 |
return 0
|
|
1169 |
|
|
1170 |
# open the log file
|
|
1171 |
self.OpenLog()
|
|
1172 |
|
|
1173 |
|
|
1174 |
try:
|
|
1175 |
# show the command and platform info
|
|
1176 |
self.AssertBuildOK()
|
|
1177 |
self.Introduction()
|
|
1178 |
# establish an object cache
|
|
1179 |
self.AssertBuildOK()
|
|
1180 |
|
|
1181 |
self.LoadCache()
|
|
1182 |
|
|
1183 |
# find out what configurations to build
|
|
1184 |
self.AssertBuildOK()
|
|
1185 |
buildUnitsToBuild = self.GetBuildUnitsToBuild(self.configNames)
|
|
1186 |
|
5
|
1187 |
self.buildUnitsToBuild = buildUnitsToBuild
|
|
1188 |
|
3
|
1189 |
# find out what components to build, and in what way
|
5
|
1190 |
layers = []
|
3
|
1191 |
|
|
1192 |
self.AssertBuildOK()
|
|
1193 |
if len(buildUnitsToBuild) >= 0:
|
5
|
1194 |
layers = self.GetLayersFromCLI()
|
3
|
1195 |
|
5
|
1196 |
componentCount = reduce(lambda x,y : x + y, [len(cg) for cg in layers])
|
3
|
1197 |
|
|
1198 |
if not componentCount > 0:
|
5
|
1199 |
raise BuildCannotProgressException("No components to build.")
|
3
|
1200 |
|
|
1201 |
# check the configurations (tools versions)
|
|
1202 |
self.AssertBuildOK()
|
|
1203 |
|
|
1204 |
if self.toolcheck != 'off':
|
|
1205 |
self.CheckConfigs(buildUnitsToBuild)
|
|
1206 |
else:
|
|
1207 |
self.Info(" Not Checking Tool Versions")
|
|
1208 |
|
|
1209 |
self.AssertBuildOK()
|
|
1210 |
|
5
|
1211 |
# Setup a make engine.
|
|
1212 |
if not self.maker:
|
|
1213 |
self.maker = raptor_make.MakeEngine(self)
|
|
1214 |
if self.maker == None:
|
|
1215 |
self.Error("No make engine present")
|
3
|
1216 |
|
5
|
1217 |
self.AssertBuildOK()
|
|
1218 |
|
|
1219 |
# if self.doParallelParsing and not (len(layers) == 1 and len(layers[0]) == 1):
|
3
|
1220 |
if self.doParallelParsing:
|
|
1221 |
# Create a Makefile to parse components in parallel and build them
|
5
|
1222 |
for l in layers:
|
|
1223 |
l.meta_realise(self)
|
3
|
1224 |
else:
|
|
1225 |
# Parse components serially, creating one set of makefiles
|
|
1226 |
# create non-component specs
|
5
|
1227 |
self.generic_specs = self.GenerateGenericSpecs(buildUnitsToBuild)
|
3
|
1228 |
|
|
1229 |
self.AssertBuildOK()
|
5
|
1230 |
for l in layers:
|
3
|
1231 |
# create specs for a specific group of components
|
5
|
1232 |
l.realise(self)
|
3
|
1233 |
|
5
|
1234 |
except BuildCannotProgressException,b:
|
3
|
1235 |
if str(b) != "":
|
|
1236 |
self.Info(str(b))
|
|
1237 |
|
|
1238 |
# final report
|
|
1239 |
if not self.fatalErrorState:
|
|
1240 |
self.Report()
|
|
1241 |
|
|
1242 |
self.Cleanup()
|
|
1243 |
|
|
1244 |
# close the log file
|
|
1245 |
self.CloseLog()
|
|
1246 |
|
|
1247 |
return self.errorCode
|
|
1248 |
|
|
1249 |
@classmethod
|
|
1250 |
def CreateCommandlineBuild(cls, argv):
|
|
1251 |
""" Perform a 'typical' build. """
|
|
1252 |
# configure the framework
|
|
1253 |
|
|
1254 |
build = Raptor()
|
|
1255 |
build.AssertBuildOK()
|
|
1256 |
build.ConfigFile()
|
|
1257 |
build.ProcessConfig()
|
|
1258 |
build.CommandLine(argv)
|
|
1259 |
|
|
1260 |
return build
|
|
1261 |
|
|
1262 |
|
|
1263 |
|
|
1264 |
# Class for passing constricted parameters to filters
|
|
1265 |
class BuildStats(object):
|
|
1266 |
|
|
1267 |
def __init__(self, raptor_instance):
|
|
1268 |
self.logFileName = raptor_instance.logFileName
|
|
1269 |
self.quiet = raptor_instance.quiet
|
|
1270 |
self.doCheck = raptor_instance.doCheck
|
|
1271 |
self.doWhat = raptor_instance.doWhat
|
|
1272 |
self.platform = hostplatform
|
|
1273 |
self.skipAll = raptor_instance.fatalErrorState
|
|
1274 |
self.timestring = raptor_instance.timestring
|
|
1275 |
self.targets = raptor_instance.targets
|
|
1276 |
self.runtime = 0
|
|
1277 |
self.name = name
|
|
1278 |
|
|
1279 |
|
|
1280 |
# raptor module functions
|
|
1281 |
|
|
1282 |
def Main(argv):
|
|
1283 |
"""The main entry point for Raptor.
|
|
1284 |
|
|
1285 |
argv is a list of command-line parameters,
|
|
1286 |
NOT including the name of the calling script.
|
|
1287 |
|
|
1288 |
The return value is zero for success and non-zero for failure."""
|
|
1289 |
|
|
1290 |
DisplayBanner()
|
|
1291 |
|
|
1292 |
# object which represents a build
|
|
1293 |
b = Raptor.CreateCommandlineBuild(argv)
|
|
1294 |
|
5
|
1295 |
return b.Build()
|
3
|
1296 |
|
|
1297 |
|
|
1298 |
def DisplayBanner():
|
|
1299 |
"""Stuff that needs printing out for every command."""
|
|
1300 |
pass
|
|
1301 |
|
|
1302 |
|
|
1303 |
|
5
|
1304 |
|
3
|
1305 |
# end of the raptor module
|