123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 |
- #
- # Copyright (c) 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_api module
- #
- # Python API for Raptor. External code should interact with Raptor via this
- # module only, as it is the only programatic interface considered public. The
- # command line --query option is also implemented using this module.
- # constants
- ALL = 1
- # objects
- class Reply(object):
- """object to return values from API calls.
- """
- def __init__(self, text="", raptor=None):
- self._raptor = raptor
- self.text = text
-
- def _getEvaluator(self, meaning):
- """ Note: Will pass on Evaluator constructor exceptions """
- try:
- return self.__evaluator
- except AttributeError:
- # create an evaluator for the named configuration
- tmp = raptor_data.Alias("tmp")
- tmp.SetProperty("meaning", meaning)
-
- units = tmp.GenerateBuildUnits(self._raptor.cache)
- self.__evaluator = self._raptor.GetEvaluator(None, units[0])
- return self.__evaluator
-
- def __str__(self):
- name = type(self).__name__.lower()
-
- string = "<" + name
- children = []
- longend = False
-
- for attribute,value in self.__dict__.items():
- if attribute != "text" and not attribute.startswith('_'):
- if isinstance(value, Reply):
- children.append(value)
- elif isinstance(value, list):
- for item in value:
- if isinstance(item, Reply):
- children.append(item)
- else:
- raise BadReply(str(item)+" is not a Reply object")
- else:
- if value != None: # skip attributes whose value is None
- string += " %s='%s'" % (attribute, value)
-
- if children or self.text:
- string += ">"
- longend = True
-
- if self.text:
- string += self.text
- children.sort()
- # Note mixing sortable and unsortable lists results in
- # sort not working, so if you really need your
- # children to come out in the right order, put them in
- # a list. This is only for niceness, where it works.
-
- if children:
- string += "\n"
-
- for c in children:
- clines = str(c).rstrip().split("\n")
- string += "".join(map(lambda l:" "+l+"\n",clines))
-
- if longend:
- string += "</%s>\n" % name
- else:
- string += "/>\n"
-
- return string
-
- class BadReply(Exception):
- pass
- class Alias(Reply):
- def __init__(self, name, meaning):
- super(Alias,self).__init__()
- self.name = name
- self.meaning = meaning
-
- def __cmp__(self, other):
- """ Add __cmp__ to enable comparisons between two Alias objects based upon name."""
- return cmp(self.name, other.name)
- class Config(Reply):
- def __init__(self, raptor, name, text = None):
- """ Constructor to create a Config from a user-supplied name.
- possibly including aliases (but not groups)
- """
- super(Config,self).__init__(text, raptor)
- self.query = name
-
- # Work out the real name
- names = name.split(".")
- if names[0] in self._raptor.cache.aliases:
- x = self._raptor.cache.FindNamedAlias(names[0])
-
- if len(names) > 1:
- self.meaning = x.meaning + "." + ".".join(names[1:])
- else:
- self.meaning = x.meaning
-
- elif names[0] in self._raptor.cache.variants:
- self.meaning = name
-
- else:
- raise BadQuery("'%s' is not an alias or a variant" % names[0])
-
- def resolveOutputPath(self):
- """ Get the outputpath """
- try:
- evaluator = self._getEvaluator(self.meaning)
- # This is messy as some configs construct the path inside the FLM
- # rather than talking it from the XML: usually because of some
- # conditional logic... but maybe some refactoring could avoid that.
- releasepath = evaluator.Get("RELEASEPATH")
- if not releasepath:
- raise BadQuery("could not get RELEASEPATH for config '%s'" % self.fullname)
-
- variantplatform = evaluator.Get("VARIANTPLATFORM")
- varianttype = evaluator.Get("VARIANTTYPE")
- featurevariantname = evaluator.Get("FEATUREVARIANTNAME")
-
- platform = evaluator.Get("TRADITIONAL_PLATFORM")
-
- if platform == "TOOLS2":
- self.outputpath = releasepath
- else:
- if not variantplatform:
- raise BadQuery("could not get VARIANTPLATFORM for config '%s'" % self.fullname)
-
- if featurevariantname:
- variantplatform += featurevariantname
-
- if not varianttype:
- raise BadQuery("could not get VARIANTTYPE for config '%s'" % self.fullname)
-
- self.outputpath = str(generic_path.Join(releasepath, variantplatform, varianttype))
- except Exception, e: # Unable to determine output path
- self.text = str(e)
- def resolveMetadata(self):
- try:
- metadata = self.metadata
- except AttributeError:
- metadata = MetaData(self.meaning, self._raptor)
- self.metadata = metadata
-
- try:
- metadata.resolve()
- except Exception:
- # Evaluator exception hopefully - already handled
- self.metadata = None
- def resolveBuild(self):
- try:
- build = self.build
- except AttributeError:
- build = Build(self.meaning, self._raptor)
- self.build = build
-
- try:
- build.resolve()
- except Exception:
- # Evaluator exception, hopefully - already handled
- self.build = None
-
- def resolveTargettypes(self):
- try:
- build = self.build
- except AttributeError:
- build = Build(self.meaning, self._raptor)
- self.build = build
-
- try:
- build.resolveTargettypes()
- except Exception:
- # Evaluator exception hopefully - already handled
- self.build = None
- class MetaData(Reply):
- def __init__(self, meaning, raptor):
- super(MetaData,self).__init__("", raptor)
- self.__meaning = meaning
- def resolve(self):
- includepaths = []
- preincludeheader = ""
- platmacros = []
- evaluator = self._getEvaluator(self.__meaning)
- # Initialise data and metadata objects
- buildunits = raptor_data.GetBuildUnits([self.__meaning], self._raptor.cache, self._raptor)
- metareader = raptor_meta.MetaReader(self._raptor, buildunits)
- metadatafile = raptor_meta.MetaDataFile(generic_path.Path("bld.inf"), "cpp", [], None, self._raptor)
-
- # There is only one build platform here; obtain the pre-processing include paths,
- # OS pre-include file, compiler pre-include file and macros.
- includepaths = metadatafile.preparePreProcessorIncludePaths(metareader.BuildPlatforms[0])
- preincludeheader = metareader.BuildPlatforms[0]['VARIANT_HRH']
-
- # Macros arrive as a a list of strings, or a single string, containing definitions of the form "name" or "name=value".
- platmacrolist = metadatafile.preparePreProcessorMacros(metareader.BuildPlatforms[0])
- platmacros.extend(map(lambda macrodef: [macrodef.partition("=")[0], macrodef.partition("=")[2]], platmacrolist))
- # Add child elements to appropriate areas if they were calculated
- if len(includepaths) > 0:
- self.includepaths = map(lambda x: Include(str(x)), includepaths)
-
- if preincludeheader != "":
- self.preincludeheader = PreInclude(str(preincludeheader))
-
- if len(platmacros):
- self.platmacros = map(lambda x: Macro(x[0],x[1]) if x[1] else Macro(x[0]), platmacros)
- class Build(Reply):
- def __init__(self, meaning, raptor):
- super(Build,self).__init__("", raptor)
- self.__meaning = meaning
-
- def resolve(self):
- compilerpreincludeheader = ""
- sourcemacros = []
- evaluator = self._getEvaluator(self.__meaning)
- platform = evaluator.Get("TRADITIONAL_PLATFORM")
-
- # Compiler preinclude files may or may not be present, depending on the configuration.
- if evaluator.Get("PREINCLUDE"):
- compilerpreincludeheader = generic_path.Path(evaluator.Get("PREINCLUDE"))
-
- # Macros arrive as a a list of strings, or a single string, containing definitions of the form "name" or "name=value".
- # If required, we split to a list, and then processes the constituent parts of the macro.
- sourcemacrolist = evaluator.Get("CDEFS").split()
- sourcemacros.extend(map(lambda macrodef: [macrodef.partition("=")[0], macrodef.partition("=")[2]], sourcemacrolist))
- if platform == "TOOLS2":
- # Source macros are determined in the FLM for tools2 builds, therefore we have to
- # mimic the logic here
- if 'win' in raptor.hostplatform or 'win32' in self.__meaning:
- sourcemacrolist = evaluator.Get("CDEFS.WIN32").split()
- else:
- sourcemacrolist = evaluator.Get("CDEFS.LINUX").split()
- sourcemacros.extend(map(lambda macrodef: [macrodef.partition("=")[0], macrodef.partition("=")[2]], sourcemacrolist))
- if len(sourcemacros):
- self.sourcemacros = map(lambda x: Macro(x[0],x[1]) if x[1] else Macro(x[0]), sourcemacros)
-
- if compilerpreincludeheader:
- self.compilerpreincludeheader = PreInclude(str(compilerpreincludeheader))
- def resolveTargettypes(self):
- evaluator = self._getEvaluator(self.__meaning)
- targettypes = evaluator.Get("TARGET_TYPES").split(' ')
- self.targettypes = []
- for type in targettypes:
- self.targettypes.append(TargetType(type))
- self.targettypes.sort()
- class TargetType(Reply):
- def __init__(self, name):
- super(TargetType,self).__init__()
- self.name = name
- def __cmp__(self, other):
- return cmp(self.name, other.name)
- class Product(Reply):
- def __init__(self, name):
- super(Product,self).__init__()
- self.name = name
-
- def __cmp__(self, other):
- """ Add __cmp__ to enable comparisons between two Product objects based upon name."""
- return cmp(self.name, other.name)
- class Include(Reply):
- def __init__(self, path):
- super(Include,self).__init__()
- self.path = path
- class PreInclude(Reply):
- def __init__(self, file):
- super(PreInclude,self).__init__()
- self.file = file
- class Macro(Reply):
- def __init__(self, name, value=None):
- super(Macro,self).__init__()
- self.name = name
- self.value = value
- import generic_path
- import raptor
- import raptor_data
- import raptor_meta
- import re
- class Context(object):
- """object to contain state information for API calls.
-
- For example,
-
- api = raptor_api.Context()
- val = api.getaliases("X")
- """
- def __init__(self, initialiser=None):
- # this object has a private Raptor object that can either be
- # passed in or created internally.
-
- if initialiser == None:
- self.__raptor = raptor.Raptor()
- else:
- self.__raptor = initialiser
-
- def stringquery(self, query):
- """turn a string into an API call and execute it.
-
- This is a convenience method for "lazy" callers.
-
- The return value is also converted into a well-formed XML string.
- """
-
- if query == "aliases":
- aliases = self.getaliases()
- return "".join(map(str, aliases)).strip()
-
- elif query == "products":
- variants = self.getproducts()
- return "".join(map(str, variants)).strip()
-
- elif query.startswith("config"):
- match = re.match("config\[(.*)\]", query)
- if match:
- config = self.getconfig(match.group(1))
- return str(config).strip()
- else:
- raise BadQuery("syntax error")
-
- raise BadQuery("unknown query")
- def getaliases(self, type=""):
- """extract all aliases of a given type.
-
- the default type is "".
- to get all aliases pass type=ALL
- """
- aliases = []
-
- for a in self.__raptor.cache.aliases.values():
- if type == ALL or a.type == type:
- # copy the members we want to expose
- aliases.append( Alias(a.name, a.meaning) )
- aliases.sort()
- return aliases
-
- def getconfig(self, name):
- """extract the values for a given configuration.
-
- 'name' should be an alias or variant followed optionally by a
- dot-separated list of variants. For example "armv5_urel" or
- "armv5_urel.savespace.vasco".
- """
- config = Config(self.__raptor, name)
- config.resolveOutputPath()
- config.resolveTargettypes()
- config.resolveMetadata()
- config.resolveBuild()
- return config
-
- def getproducts(self):
- """extract all product variants."""
-
- variants = []
-
- for v in self.__raptor.cache.variants.values():
- if v.type == "product":
- # copy the members we want to expose
- variants.append( Product(v.name) )
- variants.sort()
- return variants
- class BadQuery(Exception):
- pass
- # end of the raptor_api module
|