--- a/sbsv2/raptor/python/raptor.py Thu Jun 10 13:50:24 2010 +0800
+++ b/sbsv2/raptor/python/raptor.py Mon Jul 26 11:04:29 2010 +0800
@@ -1,1234 +1,1419 @@
-#
-# Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
-# All rights reserved.
-# This component and the accompanying materials are made available
-# under the terms of the License "Eclipse Public License v1.0"
-# which accompanies this distribution, and is available
-# at the URL "http://www.eclipse.org/legal/epl-v10.html".
-#
-# Initial Contributors:
-# Nokia Corporation - initial contribution.
-#
-# Contributors:
-#
-# Description:
-# raptor module
-# This module represents the running Raptor program. Raptor is started
-# either by calling the Main() function, which creates an instance of
-# the raptor.Raptor class and calls its methods to perform a build based
-# on command-line parameters, or by explicitly creating a raptor.Raptor
-# instance and calling its methods to set-up and perform a build.
-#
-
-name = "sbs" # the public name for the raptor build tool
-env = "SBS_HOME" # the environment variable that locates us
-xml = "sbs_init.xml" # the primary initialisation file
-env2 = "HOME" # the environment variable that locates the user
-xml2 = ".sbs_init.xml" # the override initialisation file
-
-import generic_path
-import os
-import raptor_cache
-import raptor_cli
-import raptor_data
-import raptor_make
-import raptor_meta
-import raptor_utilities
-import raptor_version
-import raptor_xml
-import filter_list
-import sys
-import types
-import time
-import re
-import traceback
-import pluginbox
-from xml.sax.saxutils import escape
-
-
-if not "HOSTPLATFORM" in os.environ or not "HOSTPLATFORM_DIR" in os.environ:
- print "Error: HOSTPLATFORM and HOSTPLATFORM_DIR must be set in the environment (this is usually done automatically by the startup script)."
- sys.exit(1)
-
-hostplatform = os.environ["HOSTPLATFORM"].split(" ")
-hostplatform_dir = os.environ["HOSTPLATFORM_DIR"]
-
-# defaults can use EPOCROOT
-if "EPOCROOT" in os.environ:
- epocroot = os.environ["EPOCROOT"].replace("\\","/")
-else:
- if 'linux' in hostplatform:
- epocroot=os.environ['HOME'] + os.sep + "epocroot"
- os.environ["EPOCROOT"] = epocroot
- else:
- epocroot = "/"
- os.environ["EPOCROOT"] = os.sep
-
-if "SBS_BUILD_DIR" in os.environ:
- sbs_build_dir = os.environ["SBS_BUILD_DIR"]
-else:
- sbs_build_dir = (epocroot + "/epoc32/build").replace("//","/")
-
-
-
-# only use default XML from the epoc32 tree if it exists
-defaultSystemConfig = "lib/config"
-epoc32UserConfigDir = generic_path.Join(epocroot, "epoc32/sbs_config")
-if epoc32UserConfigDir.isDir():
- defaultSystemConfig = str(epoc32UserConfigDir) + os.pathsep + defaultSystemConfig
-
-# parameters that can be overriden by the sbs_init.xml file
-# or by the command-line.
-defaults = {
- "allowCommandLineOverrides" : True,
- "CLI" : "raptor_cli",
- "buildInformation" : generic_path.Path("bld.inf"),
- "defaultConfig" : "default",
- "jobs": 4,
- "keepGoing": False,
- "logFileName" : generic_path.Join(sbs_build_dir,"Makefile.%TIME.log"),
- "makeEngine" : "make",
- "preferBuildInfoToSystemDefinition" : False,
- "pruneDuplicateMakefiles": True,
- "quiet" : False,
- "systemConfig" : defaultSystemConfig,
- "systemDefinition" : generic_path.Path("System_Definition.xml"),
- "systemDefinitionBase" : generic_path.Path("."),
- "systemFLM" : generic_path.Path("lib/flm"),
- "systemPlugins" : generic_path.Path("python/plugins"),
- "topMakefile" : generic_path.Join(sbs_build_dir,"Makefile"),
- "tries": 1,
- "writeSingleMakefile": True,
- "ignoreOsDetection": False,
- "toolcheck": "on",
- "filterList": "filterterminal,filterlogfile"
- }
-
-
-class ComponentGroup(object):
- """ Some components that should be built togther
- e.g. a Layer in the system definition.
- """
- def __init__(self, name, componentlist=[]):
- self.components = componentlist
- self.name = name
-
- def __iter__(self):
- return iter(self.components)
-
- def __getitem__(self,x):
- if isinstance(x, slice):
- return self.components[x.start:x.stop]
- return self.components[x]
-
- def __setitem__(self,k, v):
- self.components[k] = v
-
- def __len__(self):
- return len(self.components)
-
- def extend(self, c):
- self.components.extend(c)
-
- def append(self, c):
- self.components.append(c)
-
- def GenerateSpecs(self, genericspecs, configs):
- """Return a build spec hierarchy for a ComponentGroup. This involves parsing the component MetaData (bld.infs, mmps).
- Takes a raptor object as a parameter (build), together with a list of Configurations.
-
- Returns a tuple consisting of a list of specification objects and a list of dependency files
- that relate to these specs.
- """
-
- self.specs = []
- self.specs.extend(genericspecs)
- self.configs = configs
- self.dependencies = set()
-
- metaReader = None
- if len (self.components):
- try:
- # create a MetaReader that is aware of the list of
- # configurations that we are trying to build.
- metaReader = raptor_meta.MetaReader(build, configs)
-
- # convert the list of bld.inf files into a specification
- # hierarchy suitable for all the configurations we are using.
- self.specs.extend(metaReader.ReadBldInfFiles(self.components,build.doExportOnly))
-
- except raptor_meta.MetaDataError, e:
- log.Error(e.Text)
-
- log.Info("Buildable specification group '%s'", name)
- build.AttachSpecs(self.specs)
-
- # Get a unique list of the dependency files that were created
- if metaReader:
- for c in metaReader.BuildPlatforms:
- self.dependencies.update(c["METADEPS"])
-
-
- def CreateMakefile(self, makefilename_base, engine, named = False):
- if len(self.specs) <= 0:
- return None
-
- if named:
- makefile = generic_path.Path(str(makefilename_base) + "_" + raptor_utilities.sanitise(self.name))
- else:
- makefile = generic_path.Path(str(makefilename_base))
-
- # insert the start time into the Makefile name?
- makefile.path = makefile.path.replace("%TIME", build.timestring)
-
- engine.Write(makefile, self.specs, self.configs)
-
- return makefile
-
-
- def GenerateMetadataSpecs(self, configs):
- # insert the start time into the Makefile name?
-
- self.configs = build.GetConfig("build").GenerateBuildUnits()
-
- # Pass certain CLI flags through to the makefile-generating sbs calls
- cli_options = ""
-
- if build.debugOutput == True:
- cli_options += " -d"
-
- if build.ignoreOsDetection == True:
- cli_options += " -i"
-
- if build.keepGoing == True:
- cli_options += " -k"
-
- if build.quiet == True:
- cli_options += " -q"
-
-
- nc = len(self.components)
- number_blocks = 16
- block_size = (nc / number_blocks) + 1
- component_blocks = []
- spec_nodes = []
-
- b = 0
- while b < nc:
- component_blocks.append(self.components[b:b+block_size])
- b += block_size
-
- if len(component_blocks[-1]) <= 0:
- component_blocks.pop()
-
- loop_number = 0
- for block in component_blocks:
- loop_number += 1
- specNode = raptor_data.Specification("metadata_" + self.name)
-
- componentList = " ".join([str(c) for c in block])
- configList = " ".join([c.name for c in configs])
-
- makefile_path = str(build.topMakefile) + "_" + str(loop_number)
- try:
- os.unlink(makefile_path) # until we have dependencies working properly
- except Exception,e:
- # print "couldn't unlink %s: %s" %(componentMakefileName, str(e))
- pass
-
- # add some basic data in a component-wide variant
- var = raptor_data.Variant()
- var.AddOperation(raptor_data.Set("COMPONENT_PATHS", componentList))
- var.AddOperation(raptor_data.Set("MAKEFILE_PATH", makefile_path))
- var.AddOperation(raptor_data.Set("CONFIGS", configList))
- var.AddOperation(raptor_data.Set("CLI_OPTIONS", cli_options))
- # Pass on '-n' (if specified) to the makefile-generating sbs calls
- if build.noBuild:
- var.AddOperation(raptor_data.Set("NO_BUILD", "1"))
- specNode.AddVariant(var)
-
-
-
- try:
- interface = build.cache.FindNamedInterface("build.makefiles")
- specNode.SetInterface(interface)
- except KeyError:
- build.Error("Can't find flm interface 'build.makefiles' ")
-
- spec_nodes.append(specNode)
-
-
-
- ## possibly some error handling here?
-
- self.specs = spec_nodes
-
-
-class BuildCompleteException(Exception):
- pass
-
-# raptor module classes
-
-class Raptor(object):
- """An instance of a running Raptor program.
-
- When operated from the command-line there is a single Raptor object
- created by the Main function. When operated by an IDE several Raptor
- objects may be created and operated at the same time."""
-
-
- M_BUILD = 1
- M_VERSION = 2
-
- def __init__(self, home = None):
-
- self.DefaultSetUp(home)
-
-
- def DefaultSetUp(self, home = None):
- "revert to the default set-up state"
- self.errorCode = 0
- self.skipAll = False
- self.summary = True
- self.out = sys.stdout # Just until filters get started.
-
- # Create a bootstrap output system.
- self.out = filter_list.FilterList()
-
- if home == None:
- try:
- home = os.environ[env]
- except KeyError:
- home = os.getcwd()
-
- # make sure the home directory exists
- self.home = generic_path.Path(home).Absolute()
-
- if not self.home.isDir():
- self.Error("%s '%s' is not a directory", env, self.home)
- return
-
- # the set-up file location.
- # use the override "env2/xml2" if it exists
- # else use the primary "env/xml" if it exists
- # else keep the hard-coded defaults.
- self.raptorXML = self.home.Append(xml)
-
- if env2 in os.environ:
- sbs_init = generic_path.Join(os.environ[env2], xml2)
- if sbs_init.isFile():
- self.raptorXML = sbs_init
-
- # things that can be overridden by the set-up file
- for key, value in defaults.items():
- self.__dict__[key] = value
-
- # things to initialise
- self.args = []
-
- self.componentGroups = []
- self.orderComponentGroups = False
- self.commandlineComponents = []
-
- self.systemModel = None
- self.systemDefinitionFile = None
- self.systemDefinitionRequestedLayers = []
- self.systemDefinitionOrderLayers = False
-
- self.specGroups = {}
-
- self.configNames = []
- self.configsToBuild = set()
- self.makeOptions = []
- self.maker = None
- self.debugOutput = False
- self.doExportOnly = False
- self.noBuild = False
- self.noDependInclude = False
- self.projects = set()
-
- self.cache = raptor_cache.Cache(self)
- self.override = {env: str(self.home)}
- self.targets = []
- self.defaultTargets = []
-
- self.doCheck = False
- self.doWhat = False
- self.doParallelParsing = False
- self.mission = Raptor.M_BUILD
-
- # what platform and filesystem are we running on?
- self.filesystem = raptor_utilities.getOSFileSystem()
-
- self.toolset = None
-
- self.starttime = time.time()
- self.timestring = time.strftime("%Y-%m-%d-%H-%M-%S")
-
- self.fatalErrorState = False
-
- def AddConfigList(self, configPathList):
- # this function converts cmd line option into a list
- # and prepends it to default config.
- self.configPath = generic_path.NormalisePathList(configPathList.split(os.pathsep)) + self.configPath
- return True
-
- def AddConfigName(self, name):
- self.configNames.append(name)
- return True
-
- def RunQuietly(self, TrueOrFalse):
- self.quiet = TrueOrFalse
- return True
-
- def SetCheck(self, TrueOrFalse):
- self.doCheck = TrueOrFalse
- return True
-
- def SetWhat(self, TrueOrFalse):
- self.doWhat = TrueOrFalse
- return True
-
- def SetEnv(self, name, value):
- self.override[name] = value
-
- def AddTarget(self, target):
- if self.doCheck or self.doWhat:
- self.Warn("ignoring target %s because --what or --check is specified.\n", target)
- else:
- self.targets.append(target)
-
- def AddSourceTarget(self, filename):
- # source targets are sanitised and then added as if they were a "normal" makefile target
- # in addition they have a default, empty, top-level target assigned in order that they can
- # be presented to any generated makefile without error
- sourceTarget = generic_path.Path(filename).Absolute()
- sourceTarget = 'SOURCETARGET_' + raptor_utilities.sanitise(str(sourceTarget))
- self.AddTarget(sourceTarget)
- self.defaultTargets.append(sourceTarget)
- return True
-
- def SetSysDefFile(self, filename):
- self.systemDefinitionFile = generic_path.Path(filename)
- return True
-
- def SetSysDefBase(self, path):
- self.systemDefinitionBase = generic_path.Path(path)
- return True
-
- def AddSysDefLayer(self, layer):
- self.systemDefinitionRequestedLayers.append(layer)
- return True
-
- def SetSysDefOrderLayers(self, TrueOrFalse):
- self.systemDefinitionOrderLayers = TrueOrFalse
- return True
-
- def AddBuildInfoFile(self, filename):
- bldinf = generic_path.Path(filename).Absolute()
- self.commandlineComponents.append(bldinf)
- return True
-
- def SetTopMakefile(self, filename):
- self.topMakefile = generic_path.Path(filename)
- return True
-
- def SetDebugOutput(self, TrueOrFalse):
- self.debugOutput = TrueOrFalse
- return True
-
- def SetExportOnly(self, TrueOrFalse):
- self.doExportOnly = TrueOrFalse
- return True
-
- def SetNoBuild(self, TrueOrFalse):
- self.noBuild = TrueOrFalse
- return True
-
- def SetNoDependInclude(self, TrueOrFalse):
- self.noDependInclude = TrueOrFalse
- return True
-
- def SetKeepGoing(self, TrueOrFalse):
- self.keepGoing = TrueOrFalse
- return True
-
- def SetLogFileName(self, logfile):
- if logfile == "-":
- self.logFileName = None # stdout
- else:
- self.logFileName = generic_path.Path(logfile)
- return True
-
- def SetMakeEngine(self, makeEngine):
- self.makeEngine = makeEngine
- return True
-
- def AddMakeOption(self, makeOption):
- self.makeOptions.append(makeOption)
- return True
-
- def SetJobs(self, numberOfJobs):
- try:
- self.jobs = int(numberOfJobs)
- except ValueError:
- self.jobs = 0
-
- if self.jobs < 1:
- self.Warn("The number of jobs (%s) must be a positive integer\n", numberOfJobs)
- self.jobs = 1
- return False
- return True
-
- def SetTries(self, numberOfTries):
- try:
- self.tries = int(numberOfTries)
- except ValueError:
- self.tries = 0
-
- if self.tries < 1:
- self.Warn("The number of tries (%s) must be a positive integer\n", numberOfTries)
- self.tries = 1
- return False
- return True
-
- def SetToolCheck(self, type):
- type = type.lower()
- toolcheck_types= [ "forced", "on", "off" ]
- if type in toolcheck_types:
- self.toolcheck=type
- else:
- self.Warn("toolcheck option must be one of: %s" % toolcheck_types)
- return False
-
- return True
-
- def SetParallelParsing(self, type):
- type = type.lower()
- if type == "on":
- self.doParallelParsing = True
- elif type == "off":
- self.doParallelParsing = False
- else:
- self.Warn(" parallel parsing option must be either 'on' or 'off' (was %s)" % type)
- return False
-
- return True
-
- def AddProject(self, projectName):
- self.projects.add(projectName.lower())
- return True
-
- def FilterList(self, value):
- self.filterList = value
- return True
-
- def IgnoreOsDetection(self, value):
- self.ignoreOsDetection = value
- return True
-
- def PrintVersion(self,dummy):
- global name
- print name, "version", raptor_version.Version()
- self.mission = Raptor.M_VERSION
- return False
-
- # worker methods
-
- def Introduction(self):
- """Print a header of useful information about Raptor"""
-
- self.Info("%s: version %s\n", name, raptor_version.Version())
-
- self.Info("%s %s", env, str(self.home))
- self.Info("Set-up %s", str(self.raptorXML))
- self.Info("Command-line-arguments %s", " ".join(self.args))
- self.Info("Current working directory %s", os.getcwd())
-
- # the inherited environment
- for e, value in os.environ.items():
- self.Info("Environment %s=%s", e, value)
-
- # and some general debug stuff
- self.Debug("Platform %s", "-".join(hostplatform))
- self.Debug("Filesystem %s", self.filesystem)
- self.Debug("Python %d.%d.%d", *sys.version_info[:3])
- self.Debug("Command-line-parser %s", self.CLI)
-
- for e,value in self.override.items():
- self.Debug("Override %s = %s", e, value)
-
- for t in self.targets:
- self.Debug("Target %s", t)
-
-
- def ConfigFile(self):
- if not self.raptorXML.isFile():
- return
-
- self.cache.Load(self.raptorXML)
-
- # find the 'defaults.raptor' variant and extract the values
- try:
- var = self.cache.FindNamedVariant("defaults.init")
- evaluator = self.GetEvaluator( None, raptor_data.BuildUnit(var.name,[var]) )
-
- for key, value in defaults.items():
- newValue = evaluator.Resolve(key)
-
- if newValue != None:
- # got a string for the value
- if type(value) == types.BooleanType:
- newValue = (newValue.lower() != "false")
- elif type(value) == types.IntType:
- newValue = int(newValue)
- elif isinstance(value, generic_path.Path):
- newValue = generic_path.Path(newValue)
-
- self.__dict__[key] = newValue
-
- except KeyError:
- # it is OK to not have this but useful to say it wasn't there
- self.Info("No 'defaults.init' configuration found in " + str(self.raptorXML))
-
-
- def CommandLine(self, args):
- # remember the arguments for the log
- self.args = args
-
- # assuming self.CLI = "raptor_cli"
- more_to_do = raptor_cli.GetArgs(self, args)
-
- # resolve inter-argument dependencies.
- # --what or --check implies the WHAT target and FilterWhat Filter
- if self.doWhat or self.doCheck:
- self.targets = ["WHAT"]
- self.filterList = "filterwhat"
-
- else:
- # 1. CLEAN/CLEANEXPORT/REALLYCLEAN needs the FilterClean filter.
- # 2. Targets that clean should not be combined with other targets.
-
- targets = [x.lower() for x in self.targets]
-
- CL = "clean"
- CE = "cleanexport"
- RC = "reallyclean"
-
- is_clean = 0
- is_suspicious_clean = 0
-
- if CL in targets and CE in targets:
- is_clean = 1
- if len(targets) > 2:
- is_suspicious_clean = 1
- elif RC in targets or CL in targets or CE in targets:
- is_clean = 1
- if len(targets) > 1:
- is_suspicious_clean = 1
-
- if is_clean:
- self.filterList += ",filterclean"
- if is_suspicious_clean:
- self.Warn('CLEAN, CLEANEXPORT and a REALLYCLEAN should not be combined with other targets as the result is unpredictable.')
-
- if not more_to_do:
- self.skipAll = True # nothing else to do
-
- def ProcessConfig(self):
- # this function will perform additional processing of config
-
- # create list of generic paths
- self.configPath = generic_path.NormalisePathList(self.systemConfig.split(os.pathsep))
-
- def LoadCache(self):
- def mkAbsolute(aGenericPath):
- """ internal function to make a generic_path.Path
- absolute if required"""
- if not aGenericPath.isAbsolute():
- return self.home.Append(aGenericPath)
- else:
- return aGenericPath
-
- # make generic paths absolute (if required)
- self.configPath = map(mkAbsolute, self.configPath)
- self.cache.Load(self.configPath)
-
- if not self.systemFLM.isAbsolute():
- self.systemFLM = self.home.Append(self.systemFLM)
-
- self.cache.Load(self.systemFLM)
-
- def GetConfig(self, configname):
- names = configname.split(".")
-
- cache = self.cache
-
- base = names[0]
- mods = names[1:]
-
- if base in cache.groups:
- x = cache.FindNamedGroup(base)
- elif base in cache.aliases:
- x = cache.FindNamedAlias(base)
- elif base in cache.variants:
- x = cache.FindNamedVariant(base)
- else:
- raise Exception("Unknown build configuration '%s'" % configname)
-
- x.ClearModifiers()
-
-
- try:
- for m in mods: x.AddModifier( cache.FindNamedVariant(m) )
- except KeyError:
- raise Exception("Unknown build configuration '%s'" % configname)
- return x
-
- def GetBuildUnitsToBuild(self, configNames):
- """Return a list of the configuration objects that correspond to the
- list of configuration names in the configNames parameter.
-
- raptor.GetBuildUnitsToBuild(["armv5", "winscw"])
- >>> [ config1, config2, ... , configN ]
- """
-
- if len(configNames) == 0:
- # use default config
- if len(self.defaultConfig) == 0:
- self.Warn("No default configuration name")
- else:
- configNames.append(self.defaultConfig)
-
- buildUnitsToBuild = set()
-
-
- for c in set(configNames):
- try:
- x = self.GetConfig(c)
- buildUnitsToBuild.update( x.GenerateBuildUnits() )
- except Exception, e:
- self.FatalError(str(e))
-
- for b in buildUnitsToBuild:
- self.Info("Buildable configuration '%s'", b.name)
-
- if len(buildUnitsToBuild) == 0:
- self.Error("No build configurations given")
-
- return buildUnitsToBuild
-
- def CheckToolset(self, evaluator, configname):
- """Check the toolset for a particular config, allow other objects access
- to the toolset for this build (e.g. the raptor_make class)."""
- if self.toolset is None:
- if self.toolcheck == 'on':
- self.toolset = raptor_data.ToolSet(log=self)
- elif self.toolcheck == 'forced' :
- self.toolset = raptor_data.ToolSet(log=self, forced=True)
- else:
- return True
-
- return self.toolset.check(evaluator, configname)
-
-
- def CheckConfigs(self, configs):
- """ Tool checking for all the buildable configurations
- NB. We are allowed to use different tool versions for different
- configurations."""
-
- tools_ok = True
- for b in configs:
- self.Debug("Tool check for %s", b.name)
- evaluator = self.GetEvaluator(None, b, gathertools=True)
- tools_ok = tools_ok and self.CheckToolset(evaluator, b.name)
-
- return tools_ok
-
-
-
- def GatherSysModelLayers(self, systemModel, systemDefinitionRequestedLayers):
- """Return a list of lists of components to be built.
-
- components = GatherSysModelLayers(self, configurations)
- >>> set("abc/group/bld.inf","def/group/bld.inf, ....")
- """
- layersToBuild = []
-
- if systemModel:
- # We either process all available layers in the system model, or a subset of
- # layers specified on the command line. In both cases, the processing is the same,
- # and can be subject to ordering if explicitly requested.
- systemModel.DumpInfo()
-
- if systemDefinitionRequestedLayers:
- layersToProcess = systemDefinitionRequestedLayers
- else:
- layersToProcess = systemModel.GetLayerNames()
-
- for layer in layersToProcess:
- systemModel.DumpLayerInfo(layer)
-
- if systemModel.IsLayerBuildable(layer):
- layersToBuild.append(ComponentGroup(layer,
- systemModel.GetLayerComponents(layer)))
-
- return layersToBuild
-
-
- # Add bld.inf or system definition xml to command line componentGroups (depending on preference)
- def FindSysDefIn(self, aDir = None):
- # Find a system definition file
-
- if aDir is None:
- dir = generic_path.CurrentDir()
- else:
- dir = generic_path.Path(aDir)
-
- sysDef = dir.Append(self.systemDefinition)
- if not sysDef.isFile():
- return None
-
- return sysDef
-
-
- def FindComponentIn(self, aDir = None):
- # look for a bld.inf
-
- if aDir is None:
- dir = generic_path.CurrentDir()
- else:
- dir = generic_path.Path(aDir)
-
- bldInf = dir.Append(self.buildInformation)
- componentgroup = []
-
- if bldInf.isFile():
- return bldInf
-
- return None
-
- def AttachSpecs(self, groups):
- # tell the specs which Raptor object they work for (so that they can
- # access the cache and issue warnings and errors)
- for spec in groups:
- spec.SetOwner(self)
- self.Info("Buildable specification '%s'", spec.name)
- if self.debugOutput:
- spec.DebugPrint()
-
- def GenerateGenericSpecs(self, configsToBuild):
- # if a Configuration has any config-wide interfaces
- # then add a Specification node to call each of them.
- configWide = {}
- genericSpecs = []
- for c in configsToBuild:
- evaluator = self.GetEvaluator(None, c)
- iface = evaluator.Get("INTERFACE.config")
- if iface:
- if iface in configWide:
- # seen it already, so reuse the node
- filter = configWide[iface]
- filter.AddConfigCondition(c.name)
- else:
- # create a new node
- filter = raptor_data.Filter("config_wide")
- filter.AddConfigCondition(c.name)
- for i in iface.split():
- spec = raptor_data.Specification(i)
- spec.SetInterface(i)
- filter.AddChildSpecification(spec)
- # remember it, use it
- configWide[iface] = filter
- genericSpecs.append(filter)
-
- self.AttachSpecs(genericSpecs)
-
- return genericSpecs
-
-
- def WriteMetadataDepsMakefile(self, component_group):
- """ Takes a list of (filename, target) tuples that indicate where """
- # Create a Makefile that includes all the dependency information for this spec group
- build_metamakefile_name = \
- os.path.abspath(sbs_build_dir).replace('\\','/').rstrip('/') + \
- '/metadata_%s.mk' % component_group.name.lower()
- bmkmf = open(build_metamakefile_name, "w+")
- bmkmf.write("# Build Metamakefile - Dependencies for metadata during the 'previous' build\n\n")
- bmkmf.write("PARSETARGET:=%s\n" % build_metamakefile_name)
- bmkmf.write("%s: \n" % build_metamakefile_name)
- bmkmf.write("\t@echo -e \"\\nRE-RUNNING SBS with previous parameters\"\n")
- bmkmf.write("\t@echo pretend-sbs %s\n" % " ".join(self.args))
- try:
- for m in component_group.dependencies:
- filename, target = m
- bmkmf.write("-include %s\n\n" % filename)
- finally:
- bmkmf.close()
-
- return build_metamakefile_name
-
-
- def GetEvaluator(self, specification, configuration, gathertools=False):
- """ this will perform some caching later """
- return raptor_data.Evaluator(self, specification, configuration, gathertools=gathertools)
-
-
- def areMakefilesUptodate(self):
- return False
-
-
- def Make(self, makefile):
-
- if self.maker.Make(makefile):
- self.Info("The make-engine exited successfully.")
- return True
- else:
- self.Error("The make-engine exited with errors.")
- return False
-
-
- def Report(self):
- if self.quiet:
- return
-
- self.endtime = time.time()
- self.runtime = int(0.5 + self.endtime - self.starttime)
- self.raptor_params.runtime = self.runtime
- self.Info("Run time %s seconds" % self.runtime)
-
- def AssertBuildOK(self):
- """Raise a BuildCompleteException if no further processing is required
- """
- if self.Skip():
- raise BuildCompleteException("")
-
- return True
-
- def Skip(self):
- """Indicate not to perform operation if:
- fatalErrorState is set
- an error code is set but we're not in keepgoing mode
- """
- return self.fatalErrorState or ((self.errorCode != 0) and (not self.keepGoing))
-
-
- # log file open/close
-
- def OpenLog(self):
- """Open a log file for the various I/O methods to write to."""
-
- try:
- # Find all the raptor plugins and put them into a pluginbox.
- if not self.systemPlugins.isAbsolute():
- self.systemPlugins = self.home.Append(self.systemPlugins)
-
- self.pbox = pluginbox.PluginBox(str(self.systemPlugins))
-
- self.raptor_params = BuildStats(self)
-
- # Open the requested plugins using the pluginbox
- self.out.open(self.raptor_params, self.filterList.split(','), self.pbox)
-
- # log header
- self.out.write("<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n")
-
- namespace = "http://symbian.com/xml/build/log"
- schema = "http://symbian.com/xml/build/log/1_0.xsd"
-
- self.out.write("<buildlog sbs_version=\"%s\" xmlns=\"%s\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"%s %s\">\n"
- % (raptor_version.Version(), namespace, namespace, schema))
- self.logOpen = True
- except Exception,e:
- self.out = sys.stdout # make sure that we can actually get errors out.
- self.logOpen = False
- self.FatalError("Unable to open the output logs: %s" % str(e))
-
-
- def CloseLog(self):
- if self.logOpen:
- self.out.summary()
- self.out.write("</buildlog>\n")
-
- if not self.out.close():
- self.errorCode = 1
-
-
- def Cleanup(self):
- # ensure that the toolset cache is flushed.
- if self.toolset is not None:
- self.toolset.write()
-
- # I/O methods
-
- @staticmethod
- def attributeString(dictionary):
- "turn a dictionary into a string of XML attributes"
- atts = ""
- for a,v in dictionary.items():
- atts += " " + a + "='" + v + "'"
- return atts
-
- def Info(self, format, *extras, **attributes):
- """Send an information message to the configured channel
- (XML control characters will be escaped)
- """
- self.out.write("<info" + self.attributeString(attributes) + ">" +
- escape(format % extras) + "</info>\n")
-
- def Debug(self, format, *extras, **attributes):
- "Send a debugging message to the configured channel"
-
- # the debug text is out of our control so wrap it in a CDATA
- # in case it contains characters special to XML... like <>
- if self.debugOutput:
- self.out.write("<debug" + self.attributeString(attributes) + ">" +
- "><![CDATA[\n" + (format % extras) + "\n]]></debug>\n")
-
- def Warn(self, format, *extras, **attributes):
- """Send a warning message to the configured channel
- (XML control characters will be escaped)
- """
- self.out.write("<warning" + self.attributeString(attributes) + ">" +
- escape(format % extras) + "</warning>\n")
-
- def FatalError(self, format, *extras, **attributes):
- """Send an error message to the configured channel. This implies such a serious
- error that the entire build must be shut down asap whilst still finishing off
- correctly whatever housekeeping is possible e.g. producing error reports.
- Remains quiet if the raptor object is already in a fatal state since there
- further errors are probably triggered by the first.
- """
- if not self.fatalErrorState:
- self.out.write("<error" + self.attributeString(attributes) + ">" +
- (format % extras) + "</error>\n")
- self.errorCode = 1
- self.fatalErrorState = True
-
- def Error(self, format, *extras, **attributes):
- """Send an error message to the configured channel
- (XML control characters will be escaped)
- """
- self.out.write("<error" + self.attributeString(attributes) + ">" +
- escape(format % extras) + "</error>\n")
- self.errorCode = 1
-
-
- def PrintXML(self, format, *extras):
- "Print to configured channel (no newline is added) (assumes valid xml)"
- if format:
- self.out.write(format % extras)
-
-
- def MakeComponentGroup(self, cg):
- if not self.maker:
- self.maker = raptor_make.MakeEngine(self)
-
- if self.maker == None:
- self.Error("No make engine present")
- return None
-
- makefile = cg.CreateMakefile(self.topMakefile, self.maker, self.systemDefinitionOrderLayers)
- if (not self.noBuild and makefile is not None) \
- or self.doParallelParsing:
- # run the build for a single group of specs
- self.Make(makefile)
- else:
- self.Info("No build performed for %s" % cg.name)
-
- def GetComponentGroupsFromCLI(self):
- """Returns the list of componentGroups as specified by the
- commandline interface to Raptor e.g. parameters
- or the current directory"""
- componentGroups=[]
- # Look for bld.infs or sysdefs in the current dir if none were specified
- if self.systemDefinitionFile == None and len(self.commandlineComponents) == 0:
- if not self.preferBuildInfoToSystemDefinition:
- cwd = os.getcwd()
- self.systemDefinitionFile = self.FindSysDefIn(cwd)
- if self.systemDefinitionFile == None:
- aComponent = self.FindComponentIn(cwd)
- if aComponent:
- componentGroups.append(ComponentGroup('default',[aComponent]))
- else:
- aComponent = self.FindComponentIn(cwd)
- if aComponent is None:
- self.systemDefinitionFile = self.FindSysDefIn(cwd)
- else:
- componentGroups.append(ComponentGroup('default',[aComponent]))
-
- if len(componentGroups) <= 0 and self.systemDefinitionFile == None:
- self.Warn("No default bld.inf or system definition file found in current directory (%s)", cwd)
-
- # If we now have a System Definition to parse then get the layers of components
- if self.systemDefinitionFile != None:
- systemModel = raptor_xml.SystemModel(self, self.systemDefinitionFile, self.systemDefinitionBase)
- componentGroups = self.GatherSysModelLayers(systemModel, self.systemDefinitionRequestedLayers)
-
- # Now get components specified on a commandline - build them after any
- # layers in the system definition.
- if len(self.commandlineComponents) > 0:
- componentGroups.append(ComponentGroup('commandline',self.commandlineComponents))
-
- # If we aren't building components in order then flatten down
- # the groups
- if not self.systemDefinitionOrderLayers:
- # Flatten the layers into one group of components if
- # we are not required to build them in order.
- newcg = ComponentGroup("all")
- for cg in componentGroups:
- newcg.extend(cg)
- componentGroups = [newcg]
-
- return componentGroups
-
- def Build(self):
-
- if self.mission != Raptor.M_BUILD: # help or version requested instead.
- return 0
-
- # open the log file
- self.OpenLog()
-
-
- try:
- # show the command and platform info
- self.AssertBuildOK()
- self.Introduction()
- # establish an object cache
- self.AssertBuildOK()
-
- self.LoadCache()
-
- # find out what configurations to build
- self.AssertBuildOK()
- buildUnitsToBuild = set()
- buildUnitsToBuild = self.GetBuildUnitsToBuild(self.configNames)
-
- # find out what components to build, and in what way
- componentGroups = []
-
- self.AssertBuildOK()
- if len(buildUnitsToBuild) >= 0:
- componentGroups = self.GetComponentGroupsFromCLI()
-
- componentCount = reduce(lambda x,y : x + y, [len(cg) for cg in componentGroups])
-
- if not componentCount > 0:
- raise BuildCompleteException("No components to build.")
-
- # check the configurations (tools versions)
- self.AssertBuildOK()
-
- if self.toolcheck != 'off':
- self.CheckConfigs(buildUnitsToBuild)
- else:
- self.Info(" Not Checking Tool Versions")
-
- self.AssertBuildOK()
-
-
- # if self.doParallelParsing and not (len(componentGroups) == 1 and len(componentGroups[0]) == 1):
- if self.doParallelParsing:
- # Create a Makefile to parse components in parallel and build them
- for cg in componentGroups:
- cg.GenerateMetadataSpecs(buildUnitsToBuild)
- self.MakeComponentGroup(cg)
- if self.noBuild:
- self.Info("No build performed")
- else:
- # Parse components serially, creating one set of makefiles
- # create non-component specs
- self.AssertBuildOK()
- generic_specs = self.GenerateGenericSpecs(buildUnitsToBuild)
-
- self.AssertBuildOK()
- for cg in componentGroups:
- # create specs for a specific group of components
- cg.GenerateSpecs(generic_specs, buildUnitsToBuild)
- self.WriteMetadataDepsMakefile(cg)
-
- # generate the makefiles for one group of specs
- self.MakeComponentGroup(cg)
-
- except BuildCompleteException,b:
- if str(b) != "":
- self.Info(str(b))
-
- # final report
- if not self.fatalErrorState:
- self.Report()
-
- self.Cleanup()
-
- # close the log file
- self.CloseLog()
-
- return self.errorCode
-
- @classmethod
- def CreateCommandlineBuild(cls, argv):
- """ Perform a 'typical' build. """
- # configure the framework
-
- build = Raptor()
- build.AssertBuildOK()
- build.ConfigFile()
- build.ProcessConfig()
- build.CommandLine(argv)
-
- return build
-
-
-
-# Class for passing constricted parameters to filters
-class BuildStats(object):
-
- def __init__(self, raptor_instance):
- self.logFileName = raptor_instance.logFileName
- self.quiet = raptor_instance.quiet
- self.doCheck = raptor_instance.doCheck
- self.doWhat = raptor_instance.doWhat
- self.platform = hostplatform
- self.skipAll = raptor_instance.fatalErrorState
- self.timestring = raptor_instance.timestring
- self.targets = raptor_instance.targets
- self.runtime = 0
- self.name = name
-
-
-# raptor module functions
-
-def Main(argv):
- """The main entry point for Raptor.
-
- argv is a list of command-line parameters,
- NOT including the name of the calling script.
-
- The return value is zero for success and non-zero for failure."""
-
- DisplayBanner()
-
- # object which represents a build
- b = Raptor.CreateCommandlineBuild(argv)
-
- # allow all objects to log to the
- # build they're being used in
- global build
- global log
- build = b
- log = b
-
-
- result = b.Build()
-
- return result
-
-
-def DisplayBanner():
- """Stuff that needs printing out for every command."""
- pass
-
-
-
-# end of the raptor module
+#
+# Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of the License "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description:
+# raptor module
+# This module represents the running Raptor program. Raptor is started
+# either by calling the Main() function, which creates an instance of
+# the raptor.Raptor class and calls its methods to perform a build based
+# on command-line parameters, or by explicitly creating a raptor.Raptor
+# instance and calling its methods to set-up and perform a build.
+#
+
+name = "sbs" # the public name for the raptor build tool
+env = "SBS_HOME" # the environment variable that locates us
+xml = "sbs_init.xml" # the primary initialisation file
+env2 = "HOME" # the environment variable that locates the user
+xml2 = ".sbs_init.xml" # the override initialisation file
+
+import generic_path
+import os
+import raptor_cache
+import raptor_cli
+import raptor_data
+import raptor_make
+import raptor_makefile
+import raptor_meta
+import raptor_timing
+import raptor_utilities
+import raptor_version
+import raptor_xml
+import filter_list
+import sys
+import types
+import time
+import traceback
+import pluginbox
+from xml.sax.saxutils import escape
+
+
+if not "HOSTPLATFORM" in os.environ or not "HOSTPLATFORM_DIR" in os.environ:
+ print "Error: HOSTPLATFORM and HOSTPLATFORM_DIR must be set in the environment (this is usually done automatically by the startup script)."
+ sys.exit(1)
+
+hostplatform = os.environ["HOSTPLATFORM"].split(" ")
+hostplatform_dir = os.environ["HOSTPLATFORM_DIR"]
+
+# defaults can use EPOCROOT
+
+if "EPOCROOT" in os.environ:
+ incoming_epocroot = os.environ["EPOCROOT"]
+ epocroot = incoming_epocroot.replace("\\","/")
+else:
+ if 'win' in hostplatform:
+ incoming_epocroot = os.sep
+ epocroot = "/"
+ os.environ["EPOCROOT"] = os.sep
+ else:
+ epocroot=os.environ['HOME'] + os.sep + "epocroot"
+ os.environ["EPOCROOT"] = epocroot
+ incoming_epocroot = epocroot
+
+if "SBS_BUILD_DIR" in os.environ:
+ sbs_build_dir = os.environ["SBS_BUILD_DIR"]
+else:
+ sbs_build_dir = (epocroot + "/epoc32/build").replace("//","/")
+
+
+# only use default XML from the epoc32 tree if it exists
+defaultSystemConfig = "lib/config"
+epoc32UserConfigDir = generic_path.Join(epocroot, "epoc32/sbs_config")
+if epoc32UserConfigDir.isDir():
+ defaultSystemConfig = str(epoc32UserConfigDir) + os.pathsep + defaultSystemConfig
+
+# parameters that can be overriden by the sbs_init.xml file
+# or by the command-line.
+defaults = {
+ "allowCommandLineOverrides" : True,
+ "CLI" : "raptor_cli",
+ "buildInformation" : generic_path.Path("bld.inf"),
+ "defaultConfig" : "default",
+ "jobs": 4,
+ "keepGoing": False,
+ "logFileName" : generic_path.Join(sbs_build_dir,"Makefile.%TIME.log"),
+ "makeEngine" : "make",
+ "preferBuildInfoToSystemDefinition" : False,
+ "pruneDuplicateMakefiles": True,
+ "quiet" : False,
+ "systemConfig" : defaultSystemConfig,
+ "systemDefinition" : generic_path.Path("System_Definition.xml"),
+ "systemDefinitionBase" : generic_path.Path("."),
+ "systemFLM" : generic_path.Path("lib/flm"),
+ "systemPlugins" : generic_path.Path("python/plugins"),
+ "topMakefile" : generic_path.Join(sbs_build_dir,"Makefile"),
+ "tries": 1,
+ "writeSingleMakefile": True,
+ "ignoreOsDetection": False,
+ "toolcheck": "on",
+ "filterList": "filterterminal,filterlogfile"
+ }
+
+
+
+class ModelNode(object):
+ """ Represents any node in a a tree of build information
+ e.g. a tree of bld.infs, mmps and finally things like resource blocks and string table blocks.
+ This is before they are produced into "build" specs.
+ """
+
+ def __init__(self, id, parent = None):
+ self.id = id
+ self.type = type
+ self.specs = []
+ self.deps = []
+ self.children = set()
+ self.unfurled = False
+ self.parent = parent
+
+ # Allow one to make a set
+ def __hash__(self):
+ return hash(self.id)
+
+ def __cmp__(self,other):
+ return cmp(self.id, other)
+
+ def __iter__(self):
+ return iter(self.children)
+
+ def __getitem__(self,x):
+ if isinstance(x, slice):
+ return self.children[x.start:x.stop]
+ return self.children[x]
+
+ def __setitem__(self,k, v):
+ self.children[k] = v
+
+ def __len__(self):
+ return len(self.children)
+
+ def add(self, item):
+ return self.children.add(item)
+
+ def isunfurled(self, c):
+ return self.unfurled == False
+
+ def unfurl(self, build):
+ """Find any children of this node by processing it, produces specs"""
+ pass
+
+ def unfurl_all(self, build):
+ """Unfurl self and all children - preparatory e.g for realisation"""
+ if not self.unfurled:
+ self.unfurl(build)
+
+ self.realise_exports(build) # permit communication of dependencies between children
+
+ for c in self.children:
+ c.unfurl_all(build)
+
+
+ def realise_exports(self, build):
+ """Do the things that are needed such that we can fully unfurl all
+ sibling nodes. i.e. this step is here to "take care" of the dependencies
+ between siblings.
+ """
+ pass
+
+ def realise_makefile(self, build, specs):
+ makefilename_base = build.topMakefile
+ if self.name is not None:
+ makefile = generic_path.Path(str(makefilename_base) + "_" + raptor_utilities.sanitise(self.name))
+ else:
+ makefile = generic_path.Path(str(makefilename_base))
+
+ # insert the start time into the Makefile name?
+ makefile.path = makefile.path.replace("%TIME", build.timestring)
+
+ build.InfoDiscovery(object_type = "layers", count = 1)
+ build.InfoStartTime(object_type = "layer", task = "parse",
+ key = str(makefile.path))
+ makefileset = build.maker.Write(makefile, specs, build.buildUnitsToBuild)
+ build.InfoEndTime(object_type = "layer", task = "parse",
+ key = str(makefile.path))
+
+ return makefileset
+
+
+
+ def realise(self, build):
+ """Give the spec trees to the make engine and actually
+ "build" the product represented by this model node"""
+ # Must ensure that all children are unfurled at this point
+ self.unfurl_all(build)
+
+ sp = self.specs
+
+ build.AssertBuildOK()
+
+ m = self.realise_makefile(build, sp)
+
+ build.InfoStartTime(object_type = "layer", task = "build",
+ key = (str(m.directory) + "/" + str(m.filenamebase)))
+ result = build.Make(m)
+ build.InfoEndTime(object_type = "layer", task = "build",
+ key = (str(m.directory) + "/" + str(m.filenamebase)))
+
+
+ return result
+
+
+
+class Project(ModelNode):
+ """A project or, in symbian-speak, an MMP
+ """
+ def __init__(self, filename, parent = None):
+ super(Project,self).__init__(filename, parent = parent)
+ # Assume that components are specified in mmp files for now
+ # One day that tyranny might end.
+ self.mmp_name = str(generic_path.Path.Absolute(filename))
+ self.id = self.mmp_name
+ self.unfurled = False
+
+ def makefile(self, makefilename_base, engine, named = False):
+ """Makefiles for individual mmps not feasible at the moment"""
+ pass
+ # Cannot, currently, "unfurl an mmp" directly but do want
+ # to be able to simulate the overall recursive unfurling of a build.
+
+class Component(ModelNode):
+ """A group of projects or, in symbian-speak, a bld.inf.
+ """
+ def __init__(self, filename, layername="", componentname=""):
+ super(Component,self).__init__(filename)
+ # Assume that components are specified in bld.inf files for now
+ # One day that tyranny might end.
+ self.bldinf = None # Slot for a bldinf object if we spot one later
+ self.bldinf_filename = generic_path.Path.Absolute(filename)
+
+ self.id = str(self.bldinf_filename)
+ self.exportspecs = []
+ self.depfiles = []
+ self.unfurled = False # We can parse this
+
+ # Extra metadata optionally supplied with system definition file gathered components
+ self.layername = layername
+ self.componentname = componentname
+
+ def AddMMP(self, filename):
+ self.children.add(Project(filename))
+
+
+class Layer(ModelNode):
+ """ Some components that should be built togther
+ e.g. a Layer in the system definition.
+
+ Components that come from system definition files can
+ have extra surrounding metadata that we need to pass
+ on for use in log output.
+ """
+ def __init__(self, name, componentlist=[]):
+ super(Layer,self).__init__(name)
+ self.name = name
+
+ for c in componentlist:
+ if isinstance(c, raptor_xml.SystemModelComponent):
+ # this component came from a system_definition.xml
+ self.children.add(Component(c, c.GetContainerName("layer"), c.GetContainerName("component")))
+ else:
+ # this is a plain old bld.inf file from the command-line
+ self.children.add(Component(c))
+
+ def unfurl(self, build):
+ """Discover the children of this layer. This involves parsing the component MetaData (bld.infs, mmps).
+ Takes a raptor object as a parameter (build), together with a list of Configurations.
+
+ We currently have parsers that work on collections of components/bld.infs and that cannot
+ parse at a "finer" level. So one can't 'unfurl' an mmp at the moment.
+
+ Returns True if the object was successfully unfurled.
+ """
+
+ # setup all our components
+ for c in self.children:
+ c.specs = []
+
+ self.configs = build.buildUnitsToBuild
+
+
+ metaReader = None
+ if len (self.children):
+ try:
+ # create a MetaReader that is aware of the list of
+ # configurations that we are trying to build.
+ metaReader = raptor_meta.MetaReader(build, build.buildUnitsToBuild)
+
+ # convert the list of bld.inf files into a specification
+ # hierarchy suitable for all the configurations we are using.
+ self.specs = list(build.generic_specs)
+ self.specs.extend(metaReader.ReadBldInfFiles(self.children, doexport = build.doExport, dobuild = not build.doExportOnly))
+
+ except raptor_meta.MetaDataError, e:
+ build.Error(e.Text)
+
+ self.unfurled = True
+
+
+ def meta_realise(self, build):
+ """Generate specs that can be used to "take care of" finding out more
+ about this metaunit - i.e. one doesn't want to parse it immediately
+ but to create a makefile that will parse it.
+ In this case it allows bld.infs to be parsed in parallel by make."""
+
+ # insert the start time into the Makefile name?
+
+ self.configs = build.buildUnitsToBuild
+
+ # Pass certain CLI flags through to the makefile-generating sbs calls
+ cli_options = ""
+
+ if build.debugOutput == True:
+ cli_options += " -d"
+
+ if build.ignoreOsDetection == True:
+ cli_options += " -i"
+
+ if build.keepGoing == True:
+ cli_options += " -k"
+
+ if build.quiet == True:
+ cli_options += " -q"
+
+ if build.noDependInclude == True:
+ cli_options += " --no-depend-include"
+
+ if build.noDependGenerate == True:
+ cli_options += " --no-depend-generate"
+
+
+ nc = len(self.children)
+ number_blocks = build.jobs
+ block_size = (nc / number_blocks) + 1
+ component_blocks = []
+ spec_nodes = []
+
+ b = 0
+ childlist = list(self.children)
+ while b < nc:
+ component_blocks.append(childlist[b:b+block_size])
+ b += block_size
+
+ while len(component_blocks[-1]) <= 0:
+ component_blocks.pop()
+ number_blocks -= 1
+
+ build.Info("Parallel Parsing: bld.infs split into %d blocks\n", number_blocks)
+ # Cause the binding makefiles to have the toplevel makefile's
+ # name. The bindee's have __pp appended.
+ tm = build.topMakefile.Absolute()
+ binding_makefiles = raptor_makefile.MakefileSet(str(tm.Dir()), build.maker.selectors, makefiles=None, filenamebase=str(tm.File()))
+ build.topMakefile = generic_path.Path(str(build.topMakefile) + "_pp")
+
+ loop_number = 0
+ for block in component_blocks:
+ loop_number += 1
+ specNode = raptor_data.Specification("metadata_" + self.name)
+
+ componentList = " ".join([str(c.bldinf_filename) for c in block])
+
+
+ configList = " ".join([c.name for c in self.configs if c.name != "build" ])
+
+ makefile_path = str(build.topMakefile) + "_" + str(loop_number)
+ try:
+ os.unlink(makefile_path) # until we have dependencies working properly
+ except Exception:
+ pass
+
+ # add some basic data in a component-wide variant
+ var = raptor_data.Variant()
+ var.AddOperation(raptor_data.Set("COMPONENT_PATHS", componentList))
+ var.AddOperation(raptor_data.Set("MAKEFILE_PATH", makefile_path))
+ var.AddOperation(raptor_data.Set("CONFIGS", configList))
+ var.AddOperation(raptor_data.Set("CLI_OPTIONS", cli_options))
+
+
+ # Allow the flm to skip exports. Note: this parameter
+ doexport_str = '1'
+ if not build.doExport:
+ doexport_str = ''
+ var.AddOperation(raptor_data.Set("DOEXPORT", doexport_str ))
+
+ # Pass on '-n' (if specified) to the makefile-generating sbs calls
+ if build.noBuild:
+ var.AddOperation(raptor_data.Set("NO_BUILD", "1"))
+ specNode.AddVariant(var)
+
+ try:
+ interface = build.cache.FindNamedInterface("build.makefiles")
+ specNode.SetInterface(interface)
+ except KeyError:
+ build.Error("Can't find flm interface 'build.makefiles' ")
+
+ spec_nodes.append(specNode)
+ binding_makefiles.addInclude(str(makefile_path)+"_all")
+
+ build.InfoDiscovery(object_type = "layers", count = 1)
+ build.InfoStartTime(object_type = "layer", task = "parse",
+ key = str(build.topMakefile))
+ m = self.realise_makefile(build, spec_nodes)
+ m.close()
+ gen_result = build.Make(m)
+
+ build.InfoEndTime(object_type = "layer", task = "parse",
+ key = str(build.topMakefile))
+ build.InfoStartTime(object_type = "layer", task = "build",
+ key = str(build.topMakefile))
+ build.Debug("Binding Makefile base name is %s ", binding_makefiles.filenamebase)
+ binding_makefiles.close()
+ b = build.Make(binding_makefiles)
+ build.InfoEndTime(object_type = "layer", task = "build",
+ key = str(build.topMakefile))
+ return b
+
+
+
+
+class BuildCannotProgressException(Exception):
+ pass
+
+# raptor module classes
+
+class Raptor(object):
+ """An instance of a running Raptor program.
+
+ When operated from the command-line there is a single Raptor object
+ created by the Main function. When operated by an IDE several Raptor
+ objects may be created and operated at the same time."""
+
+ # mission enumeration
+ M_BUILD = 1
+ M_QUERY = 2
+ M_VERSION = 3
+
+ def __init__(self, home = None):
+
+ self.DefaultSetUp(home)
+
+
+ def DefaultSetUp(self, home = None):
+ "revert to the default set-up state"
+ self.errorCode = 0
+ self.skipAll = False
+ self.summary = True
+ self.out = sys.stdout # Just until filters get started.
+
+ # Create a bootstrap output system.
+ self.out = filter_list.FilterList()
+
+ if home == None:
+ try:
+ home = os.environ[env]
+ except KeyError:
+ home = os.getcwd()
+
+ # make sure the home directory exists
+ self.home = generic_path.Path(home).Absolute()
+
+ if not self.home.isDir():
+ self.Error("%s '%s' is not a directory", env, self.home)
+ return
+
+ # the set-up file location.
+ # use the override "env2/xml2" if it exists
+ # else use the primary "env/xml" if it exists
+ # else keep the hard-coded defaults.
+ self.raptorXML = self.home.Append(xml)
+
+ if env2 in os.environ:
+ sbs_init = generic_path.Join(os.environ[env2], xml2)
+ if sbs_init.isFile():
+ self.raptorXML = sbs_init
+
+ # things that can be overridden by the set-up file
+ for key, value in defaults.items():
+ self.__dict__[key] = value
+
+ # things to initialise
+ self.args = []
+
+ self.layers = []
+ self.orderLayers = False
+ self.commandlineComponents = []
+
+ self.systemModel = None
+ self.systemDefinitionFile = None
+ self.systemDefinitionRequestedLayers = []
+ self.systemDefinitionOrderLayers = False
+
+ self.specGroups = {}
+
+ self.configNames = []
+ self.configsToBuild = set()
+ self.makeOptions = []
+ self.maker = None
+ self.debugOutput = False
+ self.doExportOnly = False
+ self.doExport = True
+ self.noBuild = False
+ self.noDependInclude = False
+ self.noDependGenerate = False
+ self.projects = set()
+ self.queries = []
+
+ self.cache = raptor_cache.Cache(self)
+ self.override = {env: str(self.home)}
+ self.targets = []
+ self.defaultTargets = []
+
+ self.doCheck = False
+ self.doWhat = False
+ self.doParallelParsing = False
+ self.mission = Raptor.M_BUILD
+
+ # what platform and filesystem are we running on?
+ self.filesystem = raptor_utilities.getOSFileSystem()
+
+ self.timing = True # Needed by filters such as copy_file to monitor progress
+ self.toolset = None
+
+ self.starttime = time.time()
+ self.timestring = time.strftime("%Y-%m-%d-%H-%M-%S")
+
+ self.fatalErrorState = False
+
+ def AddConfigList(self, configPathList):
+ # this function converts cmd line option into a list
+ # and prepends it to default config.
+ self.configPath = generic_path.NormalisePathList(configPathList.split(os.pathsep)) + self.configPath
+ return True
+
+ def AddConfigName(self, name):
+ if name == "build":
+ traceback.print_stack((sys.stdout))
+ sys.exit(1)
+ self.configNames.append(name)
+ return True
+
+ def RunQuietly(self, TrueOrFalse):
+ self.quiet = TrueOrFalse
+ return True
+
+ def SetCheck(self, TrueOrFalse):
+ self.doCheck = TrueOrFalse
+ return True
+
+ def SetWhat(self, TrueOrFalse):
+ self.doWhat = TrueOrFalse
+ return True
+
+ def SetEnv(self, name, value):
+ self.override[name] = value
+
+ def AddTarget(self, target):
+ if self.doCheck or self.doWhat:
+ self.Warn("ignoring target %s because --what or --check is specified.\n", target)
+ else:
+ self.targets.append(target)
+
+ def AddSourceTarget(self, filename):
+ # source targets are sanitised and then added as if they were a "normal" makefile target
+ # in addition they have a default, empty, top-level target assigned in order that they can
+ # be presented to any generated makefile without error
+ sourceTarget = generic_path.Path(filename).Absolute()
+ sourceTarget = 'SOURCETARGET_' + raptor_utilities.sanitise(str(sourceTarget))
+ self.AddTarget(sourceTarget)
+ self.defaultTargets.append(sourceTarget)
+ return True
+
+ def SetSysDefFile(self, filename):
+ self.systemDefinitionFile = generic_path.Path(filename)
+ return True
+
+ def SetSysDefBase(self, path):
+ self.systemDefinitionBase = generic_path.Path(path)
+ return True
+
+ def AddSysDefLayer(self, layer):
+ self.systemDefinitionRequestedLayers.append(layer)
+ return True
+
+ def SetSysDefOrderLayers(self, TrueOrFalse):
+ self.systemDefinitionOrderLayers = TrueOrFalse
+ return True
+
+ def AddBuildInfoFile(self, filename):
+ bldinf = generic_path.Path(filename).Absolute()
+ self.commandlineComponents.append(bldinf)
+ return True
+
+ def SetTopMakefile(self, filename):
+ self.topMakefile = generic_path.Path(filename)
+ return True
+
+ def SetDebugOutput(self, TrueOrFalse):
+ self.debugOutput = TrueOrFalse
+ return True
+
+ def SetExportOnly(self, TrueOrFalse):
+ self.doExportOnly = TrueOrFalse
+ if not self.doExport:
+ self.Error("The --noexport and --export-only options are incompatible - won't to do anything useful")
+ return False
+ return True
+
+ def SetNoExport(self, TrueOrFalse):
+ self.doExport = not TrueOrFalse
+ if self.doExportOnly:
+ self.Error("The --noexport and --export-only options are incompatible - won't to do anything useful")
+ return False
+ return True
+
+ def SetNoBuild(self, TrueOrFalse):
+ self.noBuild = TrueOrFalse
+ return True
+
+ def SetNoDependInclude(self, TrueOrFalse):
+ self.noDependInclude = TrueOrFalse
+ return True
+
+ def SetNoDependGenerate(self, TrueOrFalse):
+ self.noDependGenerate = TrueOrFalse
+ return True
+
+ def SetKeepGoing(self, TrueOrFalse):
+ self.keepGoing = TrueOrFalse
+ return True
+
+ def SetLogFileName(self, logfile):
+ if logfile == "-":
+ self.logFileName = None # stdout
+ else:
+ self.logFileName = generic_path.Path(logfile)
+ return True
+
+ def SetMakeEngine(self, makeEngine):
+ self.makeEngine = makeEngine
+ return True
+
+ def AddMakeOption(self, makeOption):
+ self.makeOptions.append(makeOption)
+ return True
+
+ def SetJobs(self, numberOfJobs):
+ try:
+ self.jobs = int(numberOfJobs)
+ except ValueError:
+ self.jobs = 0
+
+ if self.jobs < 1:
+ self.Warn("The number of jobs (%s) must be a positive integer\n", numberOfJobs)
+ self.jobs = 1
+ return False
+ return True
+
+ def SetTries(self, numberOfTries):
+ try:
+ self.tries = int(numberOfTries)
+ except ValueError:
+ self.tries = 0
+
+ if self.tries < 1:
+ self.Warn("The number of tries (%s) must be a positive integer\n", numberOfTries)
+ self.tries = 1
+ return False
+ return True
+
+ def SetToolCheck(self, type):
+ type = type.lower()
+ toolcheck_types= [ "forced", "on", "off" ]
+ if type in toolcheck_types:
+ self.toolcheck=type
+ else:
+ self.Warn("toolcheck option must be one of: %s" % toolcheck_types)
+ return False
+
+ return True
+
+ def SetTiming(self, TrueOrFalse):
+ self.Info("--timing switch no longer has any effect - build timing is now permanently on")
+ return True
+
+ def SetParallelParsing(self, type):
+ type = type.lower()
+ if type == "on":
+ self.doParallelParsing = True
+ elif type == "slave":
+ self.isParallelParsingSlave = True
+ elif type == "off":
+ self.doParallelParsing = False
+ else:
+ self.Warn(" parallel parsing option must be either 'on' or 'off' (was %s)" % type)
+ return False
+
+ return True
+
+ def AddProject(self, projectName):
+ self.projects.add(projectName.lower())
+ return True
+
+ def AddQuery(self, q):
+ self.queries.append(q)
+ self.mission = Raptor.M_QUERY
+ return True
+
+ def FilterList(self, value):
+ self.filterList = value
+ return True
+
+ def IgnoreOsDetection(self, value):
+ self.ignoreOsDetection = value
+ return True
+
+ def PrintVersion(self,dummy):
+ global name
+ print name, "version", raptor_version.fullversion()
+ self.mission = Raptor.M_VERSION
+ return False
+
+ # worker methods
+
+ def Introduction(self):
+ """Print a header of useful information about Raptor"""
+
+ self.Info("%s: version %s\n", name, raptor_version.fullversion())
+
+ self.Info("%s %s", env, str(self.home))
+ self.Info("Set-up %s", str(self.raptorXML))
+ self.Info("Command-line-arguments %s", " ".join(self.args))
+ self.Info("Current working directory %s", os.getcwd())
+
+ # the inherited environment
+ for e, value in sorted( os.environ.items() ):
+ self.Info("Environment %s=%s", e, value.replace("]]>", "]]>"))
+
+ # and some general debug stuff
+ self.Debug("Platform %s", "-".join(hostplatform))
+ self.Debug("Filesystem %s", self.filesystem)
+ self.Debug("Python %d.%d.%d", *sys.version_info[:3])
+ self.Debug("Command-line-parser %s", self.CLI)
+
+ for e,value in self.override.items():
+ self.Debug("Override %s = %s", e, value)
+
+ for t in self.targets:
+ self.Debug("Target %s", t)
+
+
+ def ConfigFile(self):
+ if not self.raptorXML.isFile():
+ return
+
+ self.cache.Load(self.raptorXML)
+
+ # find the 'defaults.raptor' variant and extract the values
+ try:
+ var = self.cache.FindNamedVariant("defaults.init")
+ evaluator = self.GetEvaluator( None, raptor_data.BuildUnit(var.name,[var]) )
+
+ for key, value in defaults.items():
+ newValue = evaluator.Resolve(key)
+
+ if newValue != None:
+ # got a string for the value
+ if type(value) == types.BooleanType:
+ newValue = (newValue.lower() != "false")
+ elif type(value) == types.IntType:
+ newValue = int(newValue)
+ elif isinstance(value, generic_path.Path):
+ newValue = generic_path.Path(newValue)
+
+ self.__dict__[key] = newValue
+
+ except KeyError:
+ # it is OK to not have this but useful to say it wasn't there
+ self.Info("No 'defaults.init' configuration found in " + str(self.raptorXML))
+
+
+ def CommandLine(self, args):
+ # remember the arguments for the log
+ self.args = args
+
+ # assuming self.CLI = "raptor_cli"
+ if not raptor_cli.GetArgs(self, args):
+ self.skipAll = True # nothing else to do
+
+ def ParseCommandLineTargets(self):
+ # resolve inter-argument dependencies.
+ # --what or --check implies the WHAT target and FilterWhat Filter
+ if self.doWhat or self.doCheck:
+ self.targets = ["WHAT"]
+ self.filterList = "filterwhat"
+
+ else:
+ # 1. CLEAN/CLEANEXPORT/REALLYCLEAN needs the FilterClean filter.
+ # 2. Targets that clean should not be combined with other targets.
+
+ targets = [x.lower() for x in self.targets]
+
+ CL = "clean"
+ CE = "cleanexport"
+ RC = "reallyclean"
+
+ is_clean = 0
+ is_suspicious_clean = 0
+
+ if CL in targets and CE in targets:
+ is_clean = 1
+ if len(targets) > 2:
+ is_suspicious_clean = 1
+ elif RC in targets or CL in targets or CE in targets:
+ is_clean = 1
+ if len(targets) > 1:
+ is_suspicious_clean = 1
+
+ if is_clean:
+ self.filterList += ",filterclean"
+ if is_suspicious_clean:
+ self.Warn('CLEAN, CLEANEXPORT and a REALLYCLEAN should not be combined with other targets as the result is unpredictable.')
+ else:
+ """ Copyfile implements the <copy> tag which is primarily useful with cluster builds.
+ It allows file copying to occur on the primary build host rather than on the cluster.
+ This is more efficient.
+ """
+ self.filterList += ",filtercopyfile"
+
+
+ def ProcessConfig(self):
+ # this function will perform additional processing of config
+
+ # create list of generic paths
+ self.configPath = generic_path.NormalisePathList(self.systemConfig.split(os.pathsep))
+
+ def LoadCache(self):
+ def mkAbsolute(aGenericPath):
+ """ internal function to make a generic_path.Path
+ absolute if required"""
+ if not aGenericPath.isAbsolute():
+ return self.home.Append(aGenericPath)
+ else:
+ return aGenericPath
+
+ # make generic paths absolute (if required)
+ self.configPath = map(mkAbsolute, self.configPath)
+ self.cache.Load(self.configPath)
+
+ if not self.systemFLM.isAbsolute():
+ self.systemFLM = self.home.Append(self.systemFLM)
+
+ self.cache.Load(self.systemFLM)
+
+ def GetBuildUnitsToBuild(self, configNames):
+ """Return a list of the configuration objects that correspond to the
+ list of configuration names in the configNames parameter.
+
+ raptor.GetBuildUnitsToBuild(["armv5", "winscw"])
+ >>> [ config1, config2, ... , configN ]
+ """
+
+ if len(configNames) == 0:
+ # use default config
+ if len(self.defaultConfig) == 0:
+ self.Warn("No default configuration name")
+ else:
+ configNames.append(self.defaultConfig)
+
+ buildUnitsToBuild = raptor_data.GetBuildUnits(configNames, self.cache, self)
+
+ for b in buildUnitsToBuild:
+ self.Info("Buildable configuration '%s'", b.name)
+
+ if len(buildUnitsToBuild) == 0:
+ self.Error("No build configurations given")
+
+ return buildUnitsToBuild
+
+ def CheckToolset(self, evaluator, configname):
+ """Check the toolset for a particular config, allow other objects access
+ to the toolset for this build (e.g. the raptor_make class)."""
+ if self.toolset is None:
+ if self.toolcheck == 'on':
+ self.toolset = raptor_data.ToolSet(log=self)
+ elif self.toolcheck == 'forced' :
+ self.toolset = raptor_data.ToolSet(log=self, forced=True)
+ else:
+ return True
+
+ return self.toolset.check(evaluator, configname)
+
+
+ def CheckConfigs(self, configs):
+ """ Tool checking for all the buildable configurations
+ NB. We are allowed to use different tool versions for different
+ configurations."""
+
+ tools_ok = True
+ for b in configs:
+ self.Debug("Tool check for %s", b.name)
+ evaluator = self.GetEvaluator(None, b, gathertools=True)
+ tools_ok = tools_ok and self.CheckToolset(evaluator, b.name)
+
+ return tools_ok
+
+
+
+ def GatherSysModelLayers(self, systemModel, systemDefinitionRequestedLayers):
+ """Return a list of lists of components to be built.
+
+ components = GatherSysModelLayers(self, configurations)
+ >>> set("abc/group/bld.inf","def/group/bld.inf, ....")
+ """
+ layersToBuild = []
+
+ if systemModel:
+ # We either process all available layers in the system model, or a subset of
+ # layers specified on the command line. In both cases, the processing is the same,
+ # and can be subject to ordering if explicitly requested.
+ systemModel.DumpInfo()
+
+ if systemDefinitionRequestedLayers:
+ layersToProcess = systemDefinitionRequestedLayers
+ else:
+ layersToProcess = systemModel.GetLayerNames()
+
+ for layer in layersToProcess:
+ systemModel.DumpLayerInfo(layer)
+
+ if systemModel.IsLayerBuildable(layer):
+ layersToBuild.append(Layer(layer,
+ systemModel.GetLayerComponents(layer)))
+
+ return layersToBuild
+
+
+ # Add bld.inf or system definition xml to command line layers (depending on preference)
+ def FindSysDefIn(self, aDir = None):
+ # Find a system definition file
+
+ if aDir is None:
+ dir = generic_path.CurrentDir()
+ else:
+ dir = generic_path.Path(aDir)
+
+ sysDef = dir.Append(self.systemDefinition)
+ if not sysDef.isFile():
+ return None
+
+ return sysDef
+
+
+ def FindComponentIn(self, aDir = None):
+ # look for a bld.inf
+
+ if aDir is None:
+ dir = generic_path.CurrentDir()
+ else:
+ dir = generic_path.Path(aDir)
+
+ bldInf = dir.Append(self.buildInformation)
+
+ if bldInf.isFile():
+ return bldInf
+
+ return None
+
+ def GenerateGenericSpecs(self, configsToBuild):
+ # if a Configuration has any config-wide interfaces
+ # then add a Specification node to call each of them.
+ configWide = {}
+ genericSpecs = []
+ for c in configsToBuild:
+ evaluator = self.GetEvaluator(None, c)
+ iface = evaluator.Get("INTERFACE.config")
+ if iface:
+ if iface in configWide:
+ # seen it already, so reuse the node
+ filter = configWide[iface]
+ filter.AddConfigCondition(c.name)
+ else:
+ # create a new node
+ filter = raptor_data.Filter(name = "config_wide")
+ filter.AddConfigCondition(c.name)
+ for i in iface.split():
+ spec = raptor_data.Specification(i)
+ spec.SetInterface(i)
+ filter.AddChildSpecification(spec)
+ # remember it, use it
+ configWide[iface] = filter
+ genericSpecs.append(filter)
+
+ return genericSpecs
+
+
+ def GetEvaluator(self, specification, configuration, gathertools=False):
+ """ this will perform some caching later """
+ return raptor_data.Evaluator(specification, configuration, gathertools=gathertools, cache = self.cache)
+
+
+ def Make(self, makefileset):
+ if not self.noBuild and makefileset is not None:
+ if self.maker.Make(makefileset):
+ self.Info("The make-engine exited successfully.")
+ return True
+ else:
+ self.Error("The make-engine exited with errors.")
+ return False
+ else:
+ self.Info("No build performed")
+
+
+
+ def Report(self):
+ if self.quiet:
+ return
+
+ self.endtime = time.time()
+ self.runtime = int(0.5 + self.endtime - self.starttime)
+ self.raptor_params.runtime = self.runtime
+ self.Info("Run time %s seconds" % self.runtime)
+
+ def AssertBuildOK(self):
+ """Raise a BuildCannotProgressException if no further processing is required
+ """
+ if self.Skip():
+ raise BuildCannotProgressException("")
+
+ return True
+
+ def Skip(self):
+ """Indicate not to perform operation if:
+ fatalErrorState is set
+ an error code is set but we're not in keepgoing mode
+ """
+ return self.fatalErrorState or ((self.errorCode != 0) and (not self.keepGoing))
+
+
+ # log file open/close
+
+ def OpenLog(self):
+ """Open a log file for the various I/O methods to write to."""
+
+ try:
+ # Find all the raptor plugins and put them into a pluginbox.
+ if not self.systemPlugins.isAbsolute():
+ self.systemPlugins = self.home.Append(self.systemPlugins)
+
+ self.pbox = pluginbox.PluginBox(str(self.systemPlugins))
+
+ self.raptor_params = BuildStats(self)
+
+ # Open the requested plugins using the pluginbox
+ self.out.open(self.raptor_params, self.filterList, self.pbox)
+
+ # log header
+ self.out.write("<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n")
+
+ namespace = "http://symbian.com/xml/build/log"
+ progress_namespace = "http://symbian.com/xml/build/log/progress"
+ schema = "http://symbian.com/xml/build/log/1_0.xsd"
+
+ self.out.write("<buildlog sbs_version=\"%s\" xmlns=\"%s\" xmlns:progress=\"%s\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"%s %s\">\n"
+ % (raptor_version.fullversion(), namespace, progress_namespace, namespace, schema))
+ self.logOpen = True
+ except Exception,e:
+ self.out = sys.stdout # make sure that we can actually get errors out.
+ self.logOpen = False
+ self.FatalError("Unable to open the output logs: %s" % str(e))
+
+ def CloseLog(self):
+ if self.logOpen:
+ self.out.summary()
+ self.out.write("</buildlog>\n")
+
+ if not self.out.close():
+ self.errorCode = 1
+
+
+ def Cleanup(self):
+ # ensure that the toolset cache is flushed.
+ if self.toolset is not None:
+ self.toolset.write()
+
+ # I/O methods
+
+ @staticmethod
+ def attributeString(dictionary):
+ "turn a dictionary into a string of XML attributes"
+ atts = ""
+ for a,v in dictionary.items():
+ atts += " " + a + "='" + v + "'"
+ return atts
+
+ def Info(self, format, *extras, **attributes):
+ """Send an information message to the configured channel
+ (XML control characters will be escaped)
+ """
+ self.out.write("<info" + self.attributeString(attributes) + ">" +
+ escape(format % extras) + "</info>\n")
+
+ def InfoDiscovery(self, object_type, count):
+ if self.timing:
+ try:
+ self.out.write(raptor_timing.Timing.discovery_string(object_type = object_type,
+ count = count))
+ except Exception, exception:
+ self.Error(exception.Text, function = "InfoDiscoveryTime")
+
+ def InfoStartTime(self, object_type, task, key):
+ if self.timing:
+ try:
+ self.out.write(raptor_timing.Timing.start_string(object_type = object_type,
+ task = task, key = key))
+ except Exception, exception:
+ self.Error(exception.Text, function = "InfoStartTime")
+
+ def InfoEndTime(self, object_type, task, key):
+ if self.timing:
+ try:
+ self.out.write(raptor_timing.Timing.end_string(object_type = object_type,
+ task = task, key = key))
+ except Exception, exception:
+ self.Error(exception.Text, function = "InfoEndTime")
+
+ def Debug(self, format, *extras, **attributes):
+ "Send a debugging message to the configured channel"
+
+ # the debug text is out of our control so wrap it in a CDATA
+ # in case it contains characters special to XML... like <>
+ if self.debugOutput:
+ self.out.write("<debug" + self.attributeString(attributes) + ">" +
+ "><![CDATA[\n" + (format % extras) + "\n]]></debug>\n")
+
+ def Warn(self, format, *extras, **attributes):
+ """Send a warning message to the configured channel
+ (XML control characters will be escaped)
+ """
+ self.out.write("<warning" + self.attributeString(attributes) + ">" +
+ escape(format % extras) + "</warning>\n")
+
+ def FatalError(self, format, *extras, **attributes):
+ """Send an error message to the configured channel. This implies such a serious
+ error that the entire build must be shut down asap whilst still finishing off
+ correctly whatever housekeeping is possible e.g. producing error reports.
+ Remains quiet if the raptor object is already in a fatal state since there
+ further errors are probably triggered by the first.
+ """
+ if not self.fatalErrorState:
+ self.out.write("<error" + self.attributeString(attributes) + ">" +
+ (format % extras) + "</error>\n")
+ self.errorCode = 1
+ self.fatalErrorState = True
+
+ def Error(self, format, *extras, **attributes):
+ """Send an error message to the configured channel
+ (XML control characters will be escaped)
+ """
+ self.out.write("<error" + self.attributeString(attributes) + ">" +
+ escape(format % extras) + "</error>\n")
+ self.errorCode = 1
+
+
+ def PrintXML(self, format, *extras):
+ "Print to configured channel (no newline is added) (assumes valid xml)"
+ if format:
+ self.out.write(format % extras)
+
+ def GetLayersFromCLI(self):
+ """Returns the list of layers as specified by the
+ commandline interface to Raptor e.g. parameters
+ or the current directory"""
+ layers=[]
+ # Look for bld.infs or sysdefs in the current dir if none were specified
+ if self.systemDefinitionFile == None and len(self.commandlineComponents) == 0:
+ if not self.preferBuildInfoToSystemDefinition:
+ cwd = os.getcwd()
+ self.systemDefinitionFile = self.FindSysDefIn(cwd)
+ if self.systemDefinitionFile == None:
+ aComponent = self.FindComponentIn(cwd)
+ if aComponent:
+ layers.append(Layer('default',[aComponent]))
+ else:
+ aComponent = self.FindComponentIn(cwd)
+ if aComponent is None:
+ self.systemDefinitionFile = self.FindSysDefIn(cwd)
+ else:
+ layers.append(Layer('default',[aComponent]))
+
+ if len(layers) <= 0 and self.systemDefinitionFile == None:
+ self.Warn("No default bld.inf or system definition file found in current directory (%s)", cwd)
+
+ # If we now have a System Definition to parse then get the layers of components
+ if self.systemDefinitionFile != None:
+ systemModel = raptor_xml.SystemModel(self, self.systemDefinitionFile, self.systemDefinitionBase)
+ layers = self.GatherSysModelLayers(systemModel, self.systemDefinitionRequestedLayers)
+
+ # Now get components specified on a commandline - build them after any
+ # layers in the system definition.
+ if len(self.commandlineComponents) > 0:
+ layers.append(Layer('commandline',self.commandlineComponents))
+
+ # If we aren't building components in order then flatten down
+ # the groups
+ if not self.systemDefinitionOrderLayers:
+ # Flatten the layers into one group of components if
+ # we are not required to build them in order.
+ newcg = Layer("all")
+ for cg in layers:
+ for c in cg:
+ newcg.add(c)
+ layers = [newcg]
+
+ return layers
+
+ def Query(self):
+ "process command-line queries."
+
+ if self.mission != Raptor.M_QUERY:
+ return 0
+
+ # establish an object cache based on the current settings
+ self.LoadCache()
+
+ # our "self" is a valid object for initialising an API Context
+ import raptor_api
+ api = raptor_api.Context(self)
+
+ print "<sbs version='%s'>" % raptor_version.numericversion()
+
+ for q in self.queries:
+ try:
+ print api.stringquery(q)
+
+ except Exception, e:
+ self.Error("exception '%s' with query '%s'", str(e), q)
+
+ print "</sbs>"
+ return self.errorCode
+
+ def Build(self):
+
+ if self.mission != Raptor.M_BUILD: # help or version requested instead.
+ return 0
+
+ # open the log file
+ self.OpenLog()
+
+
+ try:
+ # show the command and platform info
+ self.AssertBuildOK()
+ self.Introduction()
+ # establish an object cache
+ self.AssertBuildOK()
+
+ self.LoadCache()
+
+ # find out what configurations to build
+ self.AssertBuildOK()
+ buildUnitsToBuild = self.GetBuildUnitsToBuild(self.configNames)
+
+ if len(buildUnitsToBuild) == 0:
+ raise BuildCannotProgressException("No configurations to build.")
+
+ self.buildUnitsToBuild = buildUnitsToBuild
+
+ # find out what components to build, and in what way
+ layers = []
+
+ self.AssertBuildOK()
+ if len(buildUnitsToBuild) >= 0:
+ layers = self.GetLayersFromCLI()
+
+ componentCount = reduce(lambda x,y : x + y, [len(cg) for cg in layers])
+
+ if not componentCount > 0:
+ raise BuildCannotProgressException("No components to build.")
+
+ # check the configurations (tools versions)
+ self.AssertBuildOK()
+
+ if self.toolcheck != 'off':
+ self.CheckConfigs(buildUnitsToBuild)
+ else:
+ self.Info("Not Checking Tool Versions")
+
+ self.AssertBuildOK()
+
+ # Setup a make engine.
+ if not self.maker:
+ try:
+ self.maker = raptor_make.MakeEngine(self, self.makeEngine)
+ except raptor_make.BadMakeEngineException,e:
+ self.Error("Unable to use make engine: %s " % str(e))
+
+
+ self.AssertBuildOK()
+
+ # if self.doParallelParsing and not (len(layers) == 1 and len(layers[0]) == 1):
+ if self.doParallelParsing:
+ # Create a Makefile to parse components in parallel and build them
+ for l in layers:
+ l.meta_realise(self)
+ else:
+ # Parse components serially, creating one set of makefiles
+ # create non-component specs
+ self.generic_specs = self.GenerateGenericSpecs(buildUnitsToBuild)
+
+ self.AssertBuildOK()
+ for l in layers:
+ # create specs for a specific group of components
+ l.realise(self)
+
+ except BuildCannotProgressException,b:
+ if str(b) != "":
+ self.Info(str(b))
+
+ # final report
+ if not self.fatalErrorState:
+ self.Report()
+
+ self.Cleanup()
+
+ # close the log file
+ self.CloseLog()
+
+ return self.errorCode
+
+ @classmethod
+ def CreateCommandlineBuild(cls, argv):
+ """ Perform a 'typical' build. """
+ # configure the framework
+
+ build = Raptor()
+ build.AssertBuildOK()
+ build.ConfigFile()
+ build.ProcessConfig()
+ build.CommandLine(argv)
+ build.ParseCommandLineTargets()
+
+ return build
+
+ @classmethod
+ def CreateCommandlineAnalysis(cls, argv):
+ """ Perform an analysis run where a build is not performed. """
+ build = Raptor()
+ build.AssertBuildOK()
+ build.ConfigFile()
+ build.ProcessConfig()
+ build.CommandLine(argv)
+ # Don't parse command line targets - they don't make any sense if you're not doing a build
+
+ return build
+
+
+# Class for passing constricted parameters to filters
+class BuildStats(object):
+
+ def __init__(self, raptor_instance):
+ self.incoming_epocroot = incoming_epocroot
+ self.epocroot = epocroot
+ self.logFileName = raptor_instance.logFileName
+ self.quiet = raptor_instance.quiet
+ self.doCheck = raptor_instance.doCheck
+ self.doWhat = raptor_instance.doWhat
+ self.platform = hostplatform
+ self.skipAll = raptor_instance.fatalErrorState
+ self.timestring = raptor_instance.timestring
+ self.targets = raptor_instance.targets
+ self.runtime = 0
+ self.name = name
+
+
+# raptor module functions
+
+def Main(argv):
+ """The main entry point for Raptor.
+
+ argv is a list of command-line parameters,
+ NOT including the name of the calling script.
+
+ The return value is zero for success and non-zero for failure."""
+
+ DisplayBanner()
+
+ # object which represents a build
+ b = Raptor.CreateCommandlineBuild(argv)
+
+ if b.mission == Raptor.M_QUERY:
+ return b.Query()
+
+ return b.Build()
+
+
+def DisplayBanner():
+ """Stuff that needs printing out for every command."""
+ pass
+
+
+
+
+# end of the raptor module