sbsv2/raptor/python/raptor_meta.py
changeset 625 a1925fb7753a
parent 616 24e4ef208cca
child 630 31ef8a13d4f4
equal deleted inserted replaced
624:f70b728ea30c 625:a1925fb7753a
    36 
    36 
    37 import time
    37 import time
    38 import generic_path
    38 import generic_path
    39 
    39 
    40 
    40 
    41 PiggyBackedBuildPlatforms = {'ARMV5':['GCCXML']}
    41 PiggyBackedBuildPlatforms = {'ARMV5':['GCCXML', 'X86GCC']}
    42 
    42 
    43 PlatformDefaultDefFileDir = {'WINSCW':'bwins',
    43 PlatformDefaultDefFileDir = {'WINSCW':'bwins',
    44 				  'ARMV5' :'eabi',
    44 				  'ARMV5' :'eabi',
    45 				  'ARMV5SMP' :'eabi',
    45 				  'ARMV5SMP' :'eabi',
    46 				  'GCCXML':'eabi',
    46 				  'GCCXML':'eabi',
    47 				  'ARMV6':'eabi',
    47 				  'ARMV6':'eabi',
    48 				  'ARMV7' : 'eabi',
    48 				  'ARMV7' : 'eabi',
    49 				  'ARMV7SMP' : 'eabi'}
    49 				  'ARMV7SMP' : 'eabi',
       
    50 				  'X86GCC' : ['bx86gcc', 'eabi']}
    50 
    51 
    51 def getVariantCfgDetail(aEPOCROOT, aVariantCfgFile):
    52 def getVariantCfgDetail(aEPOCROOT, aVariantCfgFile):
    52 	"""Obtain pertinent build related detail from the Symbian variant.cfg file.
    53 	"""Obtain pertinent build related detail from the Symbian variant.cfg file.
    53 
    54 
    54 	This variant.cfg file, usually located relative to $(EPOCROOT), contains:
    55 	This variant.cfg file, usually located relative to $(EPOCROOT), contains:
   298 
   299 
   299 	def call(self, aArgs, sourcefilename):
   300 	def call(self, aArgs, sourcefilename):
   300 		""" Override call so that we can do our own error handling."""
   301 		""" Override call so that we can do our own error handling."""
   301 		tool = self._ExternalTool__Tool
   302 		tool = self._ExternalTool__Tool
   302 		commandline = tool + " " + aArgs + " " + str(sourcefilename)
   303 		commandline = tool + " " + aArgs + " " + str(sourcefilename)
       
   304 		
       
   305 		self.raptor.Debug("Preprocessing command line %s", str(commandline))
       
   306 			
   303 		try:
   307 		try:
   304 			# the actual call differs between Windows and Unix
   308 			# the actual call differs between Windows and Unix
   305 			if raptor_utilities.getOSFileSystem() == "unix":
   309 			if raptor_utilities.getOSFileSystem() == "unix":
   306 				p = subprocess.Popen(commandline, \
   310 				p = subprocess.Popen(commandline, \
   307 									 shell=True, bufsize=65535, \
   311 									 shell=True, bufsize=65535, \
   318 									 universal_newlines=True)
   322 									 universal_newlines=True)
   319 
   323 
   320 			# run the command and wait for all the output
   324 			# run the command and wait for all the output
   321 			(self._ExternalTool__Output, errors) = p.communicate()
   325 			(self._ExternalTool__Output, errors) = p.communicate()
   322 
   326 
   323 			if self.raptor.debugOutput:
   327 			self.raptor.Debug("Preprocessing Start %s", str(sourcefilename))
   324 				self.raptor.Debug("Preprocessing Start %s", str(sourcefilename))
   328 			self.raptor.Debug("Output:\n%s", self._ExternalTool__Output)
   325 				self.raptor.Debug("Output:\n%s", self._ExternalTool__Output)
   329 			self.raptor.Debug("Errors:\n%s", errors)
   326 				self.raptor.Debug("Errors:\n%s", errors)
   330 			self.raptor.Debug("Preprocessing End %s", str(sourcefilename))
   327 				self.raptor.Debug("Preprocessing End %s", str(sourcefilename))
       
   328 
   331 
   329 			incRE = re.compile("In file included from")
   332 			incRE = re.compile("In file included from")
   330 			fromRE = re.compile(r"\s+from")
   333 			fromRE = re.compile(r"\s+from")
   331 			warningRE = re.compile("warning:|pasting.+token|from.+:")
   334 			warningRE = re.compile("warning:|pasting.+token|from.+:")
   332 			remarkRE = re.compile("no newline at end of file|does not give a valid preprocessing token")
   335 			remarkRE = re.compile("no newline at end of file|does not give a valid preprocessing token")
   401 		for includePath in self.__IncludePaths:
   404 		for includePath in self.__IncludePaths:
   402 			call += " " + self.__IncludeOption
   405 			call += " " + self.__IncludeOption
   403 			call += " " + str(includePath)
   406 			call += " " + str(includePath)
   404 
   407 
   405 		return call
   408 		return call
   406 
       
   407 
   409 
   408 class MetaDataFile(object):
   410 class MetaDataFile(object):
   409 	"""A generic representation of a Symbian metadata file
   411 	"""A generic representation of a Symbian metadata file
   410 
   412 
   411 	Symbian metadata files are subject to preprocessing, primarily with macros based
   413 	Symbian metadata files are subject to preprocessing, primarily with macros based
   457 			try:
   459 			try:
   458 				os.makedirs(os.path.dirname(adepfilename))
   460 				os.makedirs(os.path.dirname(adepfilename))
   459 			except Exception, e:
   461 			except Exception, e:
   460 				self.log.Debug("Couldn't make bldinf outputpath for dependency generation")
   462 				self.log.Debug("Couldn't make bldinf outputpath for dependency generation")
   461 
   463 
   462 		config_macros = (aBuildPlatform['PLATMACROS']).split()
       
   463 
       
   464 		if not key in self.__PreProcessedContent:
   464 		if not key in self.__PreProcessedContent:
   465 
   465 
   466 			preProcessor = PreProcessor(self.__gnucpp, '-undef -nostdinc ' + generateDepsOptions + ' ',
   466 			preProcessor = PreProcessor(self.__gnucpp, '-undef -nostdinc ' + generateDepsOptions + ' ',
   467 										'-I', '-D', '-include', self.log)
   467 										'-I', '-D', '-include', self.log)
   468 			preProcessor.filename = self.filename
   468 			preProcessor.filename = self.filename
   469 
   469 
   470 			# always have the current directory on the include path
   470 			# Set the preprocessor include paths
   471 			preProcessor.addIncludePath('.')
   471 			self.setPreProcessorIncludePaths(preProcessor, aBuildPlatform)
   472 
   472 
   473 			# the SYSTEMINCLUDE directories defined in the build config
   473 			# there is always a pre-include file
   474 			# should be on the include path. This is added mainly to support
       
   475 			# Feature Variation as SYSTEMINCLUDE is usually empty at this point.
       
   476 			systemIncludes = aBuildPlatform['SYSTEMINCLUDE']
       
   477 			if systemIncludes:
       
   478 				preProcessor.addIncludePaths(systemIncludes.split())
       
   479 
       
   480 			preInclude = aBuildPlatform['VARIANT_HRH']
   474 			preInclude = aBuildPlatform['VARIANT_HRH']
   481 
       
   482 			# for non-Feature Variant builds, the directory containing the HRH should
       
   483 			# be on the include path
       
   484 			if not aBuildPlatform['ISFEATUREVARIANT']:
       
   485 				preProcessor.addIncludePath(preInclude.Dir())
       
   486 
       
   487 			# and EPOCROOT/epoc32/include
       
   488 			preProcessor.addIncludePath(aBuildPlatform['EPOCROOT'].Append('epoc32/include'))
       
   489 
       
   490 			# and the directory containing the bld.inf file
       
   491 			if self.__RootLocation is not None and str(self.__RootLocation) != "":
       
   492 				preProcessor.addIncludePath(self.__RootLocation)
       
   493 
       
   494 			# and the directory containing the file we are processing
       
   495 			preProcessor.addIncludePath(self.filename.Dir())
       
   496 
       
   497 			# there is always a pre-include file
       
   498 			preProcessor.setPreIncludeFile(preInclude)
   475 			preProcessor.setPreIncludeFile(preInclude)
   499 
   476 
   500 			macros = ["SBSV2"]
   477 			# Set the preprocessor macros
   501 
   478 			self.setPreProcessorMacros(preProcessor, aBuildPlatform)
   502 			if config_macros:
       
   503 				macros.extend(config_macros)
       
   504 
       
   505 			if macros:
       
   506 				for macro in macros:
       
   507 					preProcessor.addMacro(macro + "=_____" +macro)
       
   508 
       
   509 			# extra "raw" macros that do not need protecting
       
   510 			preProcessor.addMacro("__GNUC__=3")
       
   511 
   479 
   512 			preProcessorOutput = preProcessor.preprocess()
   480 			preProcessorOutput = preProcessor.preprocess()
   513 
   481 
   514 			# Resurrect preprocessing replacements
   482 			# Resurrect preprocessing replacements
   515 			pattern = r'([\\|/]| |) ?_____(('+macros[0]+')'
   483 			pattern = r'([\\|/]| |) ?_____(('+self.macros[0]+')'
   516 			for macro in macros[1:]:
   484 			for macro in self.macros[1:]:
   517 				pattern += r'|('+macro+r')'
   485 				pattern += r'|('+macro+r')'
   518 
   486 
   519 			pattern += r'\s*)'
   487 			pattern += r'\s*)'
   520 			# Work on all Macros in one substitution.
   488 			# Work on all Macros in one substitution.
   521 			text = re.sub(pattern, r"\1\2", preProcessorOutput)
   489 			text = re.sub(pattern, r"\1\2", preProcessorOutput)
   522 			text = re.sub(r"\n[\t ]*", r"\n", text)
   490 			text = re.sub(r"\n[\t ]*", r"\n", text)
   523 
   491 
   524 			self.__PreProcessedContent[key] = text
   492 			self.__PreProcessedContent[key] = text
   525 
   493 
   526 		return self.__PreProcessedContent[key]
   494 		return self.__PreProcessedContent[key]
       
   495 	
       
   496 	def setPreProcessorMacros(self, aPreprocessor, aBuildPlatform):
       
   497 		""" Apply the macros for aBuildPlatform to a preprocessor object. """
       
   498 		preprocessormacros = self.preparePreProcessorMacros(aBuildPlatform)
       
   499 		for macro in preprocessormacros:
       
   500 			aPreprocessor.addMacro(macro)
       
   501 			
       
   502 	def preparePreProcessorMacros(self, aBuildPlatform):
       
   503 		""" Prepare a list of macros (e.g. for use by the preprocessor) """
       
   504 		prepared_macros = []
       
   505 		config_macros = (aBuildPlatform['PLATMACROS']).split()
       
   506 		macros = ["SBSV2"]
       
   507 
       
   508 		if config_macros:
       
   509 			macros.extend(config_macros)
       
   510 
       
   511 		if macros:
       
   512 			for macro in macros:
       
   513 				prepared_macros.append(macro + "=_____" +macro)
       
   514 		
       
   515 		self.macros = macros # For later use
       
   516 		
       
   517 		# extra "raw" macros that do not need protecting
       
   518 		prepared_macros.append("__GNUC__=3")
       
   519 		
       
   520 		return prepared_macros
       
   521 		
       
   522 	def setPreProcessorIncludePaths(self, aPreprocessor, aBuildPlatform):
       
   523 		""" setPreProcessorIncludePaths: set the preprocessor include paths """
       
   524 		ppip = self.preparePreProcessorIncludePaths(aBuildPlatform)
       
   525 		aPreprocessor.addIncludePaths(ppip)
       
   526 		
       
   527 	def preparePreProcessorIncludePaths(self, aBuildPlatform):
       
   528 		""" Prepare a list of the include paths for use by the preprocessor. """
       
   529 		paths = []
       
   530 		
       
   531 		# always have the current directory on the include path
       
   532 		paths.append('.')
       
   533 
       
   534 		# the SYSTEMINCLUDE directories defined in the build config
       
   535 		# should be on the include path. This is added mainly to support
       
   536 		# Feature Variation as SYSTEMINCLUDE is usually empty at this point.
       
   537 		systemIncludes = aBuildPlatform['SYSTEMINCLUDE']
       
   538 		if systemIncludes:
       
   539 			paths.extend(systemIncludes.split())
       
   540 
       
   541 		preInclude = aBuildPlatform['VARIANT_HRH']
       
   542 		
       
   543 		# for non-Feature Variant builds, the directory containing the HRH should
       
   544 		# be on the include path
       
   545 		if not aBuildPlatform['ISFEATUREVARIANT']:
       
   546 			paths.append(preInclude.Dir())
       
   547 
       
   548 		# and EPOCROOT/epoc32/include
       
   549 		paths.append(aBuildPlatform['EPOCROOT'].Append('epoc32/include'))
       
   550 
       
   551 		# and the directory containing the bld.inf file
       
   552 		if self.__RootLocation is not None and str(self.__RootLocation) != "":
       
   553 			paths.append(self.__RootLocation)
       
   554 
       
   555 		# and the directory containing the file we are processing.
       
   556 		# This won't always be applicable - if the client is a front-end query for preprocessing
       
   557 		# include paths then there's no bld.inf path to take into account
       
   558 		if self.filename.Dir().Exists():
       
   559 			paths.append(self.filename.Dir())
       
   560 		
       
   561 		return paths
   527 
   562 
   528 class MMPFile(MetaDataFile):
   563 class MMPFile(MetaDataFile):
   529 	"""A generic representation of a Symbian metadata file
   564 	"""A generic representation of a Symbian metadata file
   530 
   565 
   531 	Symbian metadata files are subject to preprocessing, primarily with macros based
   566 	Symbian metadata files are subject to preprocessing, primarily with macros based
  1250 		self.__pageConflict = []
  1285 		self.__pageConflict = []
  1251 		self.__debuggable = ""
  1286 		self.__debuggable = ""
  1252 		self.__compressionKeyword = ""
  1287 		self.__compressionKeyword = ""
  1253 		self.sources = []
  1288 		self.sources = []
  1254 		self.capabilities = []
  1289 		self.capabilities = []
       
  1290 		self.documents = []
  1255 
  1291 
  1256 		self.__TARGET = ""
  1292 		self.__TARGET = ""
  1257 		self.__TARGETEXT = ""
  1293 		self.__TARGETEXT = ""
  1258 		self.deffile = ""
  1294 		self.deffile = ""
  1259 		self.__LINKAS = ""
  1295 		self.__LINKAS = ""
  1566 				toks1 = str(toks[1]).replace("\\","/")
  1602 				toks1 = str(toks[1]).replace("\\","/")
  1567 				if toks1.find(","):
  1603 				if toks1.find(","):
  1568 					toks1 = re.sub("[,'\[\]]", "", toks1).replace("//","/")
  1604 					toks1 = re.sub("[,'\[\]]", "", toks1).replace("//","/")
  1569 				self.__debug("Set "+toks[0]+" to " + toks1)
  1605 				self.__debug("Set "+toks[0]+" to " + toks1)
  1570 				self.BuildVariant.AddOperation(raptor_data.Set(varname,toks1))
  1606 				self.BuildVariant.AddOperation(raptor_data.Set(varname,toks1))
       
  1607 				
       
  1608 		elif varname == 'TRACES':
       
  1609 			self.__debug("Set " + toks[0] + " to 1" )
       
  1610 			self.BuildVariant.AddOperation(raptor_data.Set(varname, "1"))
       
  1611 			
       
  1612 			if len(toks) == 1:
       
  1613 				toks1 = "../traces"
       
  1614 			else:
       
  1615 				toks1 = os.path.join(toks[1], "traces").replace("\\","/")
       
  1616 			path = toks1 + "/" + self.__TARGET + "_" + self.__TARGETEXT
       
  1617 			resolved = raptor_utilities.resolveSymbianPath(self.__currentMmpFile, path)
       
  1618 			self.BuildVariant.AddOperation(raptor_data.Append('USERINCLUDE', resolved))
       
  1619 			self.__userinclude += ' ' + resolved
       
  1620 			self.__debug("  %s = %s", "USERINCLUDE", self.__userinclude)
       
  1621 		
  1571 		elif varname=='APPLY':
  1622 		elif varname=='APPLY':
  1572 			self.ApplyVariants.append(toks[1])
  1623 			self.ApplyVariants.append(toks[1])
  1573 		elif varname=='ARMFPU':
  1624 		elif varname=='ARMFPU':
  1574 			if not str(toks[1]).lower() in self.armfpu_options:
  1625 			if not str(toks[1]).lower() in self.armfpu_options:
  1575 				self.__Raptor.Error("ARMFPU option '"+str(toks[1])+"' not recognised - should be one of "+", ".join(self.armfpu_options))
  1626 				self.__Raptor.Error("ARMFPU option '"+str(toks[1])+"' not recognised - should be one of "+", ".join(self.armfpu_options))
  1671 		self.__currentLineNumber += 1
  1722 		self.__currentLineNumber += 1
  1672 		self.__sourcepath = raptor_utilities.resolveSymbianPath(self.__currentMmpFile, toks[1])
  1723 		self.__sourcepath = raptor_utilities.resolveSymbianPath(self.__currentMmpFile, toks[1])
  1673 		self.__debug( "Remembering self.sourcepath state:  "+str(toks[0])+" is now " + self.__sourcepath)
  1724 		self.__debug( "Remembering self.sourcepath state:  "+str(toks[0])+" is now " + self.__sourcepath)
  1674 		self.__debug("selfcurrentMmpFile: " + self.__currentMmpFile)
  1725 		self.__debug("selfcurrentMmpFile: " + self.__currentMmpFile)
  1675 		return "OK"
  1726 		return "OK"
  1676 
  1727 	
  1677 
  1728 	def __doAssignment(self,filelist,toks):
  1678 	def doSourceAssignment(self,s,loc,toks):
  1729 		""" Ancillary method factorying out the common functionality between doSourceAssignment
       
  1730 		and doDocumentAssignment. Arguments are
       
  1731 		filelist - list to append items to, should be self.sources or self.documents 
       
  1732 		toks - toks parameter as passed from PyParsing. """
       
  1733 		
  1679 		self.__currentLineNumber += 1
  1734 		self.__currentLineNumber += 1
  1680 		self.__debug( "Setting "+toks[0]+" to " + str(toks[1]))
  1735 		self.__debug( "Setting "+toks[0]+" to " + str(toks[1]))
  1681 		for file in toks[1]:
  1736 		for file in toks[1]:
  1682 			# file is always relative to sourcepath but some MMP files
  1737 			# file is always relative to sourcepath but some MMP files
  1683 			# have items that begin with a slash...
  1738 			# have items that begin with a slash...
  1685 			source = generic_path.Join(self.__sourcepath, file)
  1740 			source = generic_path.Join(self.__sourcepath, file)
  1686 
  1741 
  1687 			# If the SOURCEPATH itself begins with a '/', then dont look up the caseless version, since
  1742 			# If the SOURCEPATH itself begins with a '/', then dont look up the caseless version, since
  1688 			# we don't know at this time what $(EPOCROOT) will evaluate to.
  1743 			# we don't know at this time what $(EPOCROOT) will evaluate to.
  1689 			if source.GetLocalString().startswith('$(EPOCROOT)'):
  1744 			if source.GetLocalString().startswith('$(EPOCROOT)'):
  1690 				self.sources.append(str(source))	
  1745 				filelist.append(str(source))						
  1691 				self.__debug("Append SOURCE " + str(source))
  1746 				self.__debug("Append " + toks[0] + " " + str(source))
  1692 
  1747 
  1693 			else:
  1748 			else:
  1694 				foundsource = source.FindCaseless()
  1749 				foundsource = source.FindCaseless()
  1695 				if foundsource == None:
  1750 				if foundsource == None:
  1696 					# Hope that the file will be generated later
  1751 					# Hope that the file will be generated later
  1697 					self.__debug("Sourcefile not found: %s" % source)
  1752 					self.__debug("%s file not found: %s" % (toks[0], source))
  1698 					foundsource = source
  1753 					foundsource = source
  1699 
  1754 
  1700 				self.sources.append(str(foundsource))	
  1755 				filelist.append(str(foundsource))					
  1701 				self.__debug("Append SOURCE " + str(foundsource))
  1756 				self.__debug("Append " + toks[0] + " " + str(foundsource))
  1702 
  1757 
  1703 
  1758 
  1704 		self.__debug("		sourcepath: " + self.__sourcepath)
  1759 		self.__debug("		sourcepath: " + self.__sourcepath)
  1705 		return "OK"
  1760 		return "OK"
       
  1761 
       
  1762 	def doSourceAssignment(self,s,loc,toks):
       
  1763 		""" Populate the list of source files from the MMP. """
       
  1764 		self.__doAssignment(self.sources,toks)
       
  1765 
       
  1766 	def doDocumentAssignment(self,s,loc,toks):
       
  1767 		""" Populate the list of document files from the MMP. """
       
  1768 		self.__doAssignment(self.documents,toks)
  1706 
  1769 
  1707 	# Resource
  1770 	# Resource
  1708 
  1771 
  1709 	def doOldResourceAssignment(self,s,loc,toks):
  1772 	def doOldResourceAssignment(self,s,loc,toks):
  1710 		# Technically deprecated, but still used, so...
  1773 		# Technically deprecated, but still used, so...
  2135 			# NOTE: Changing default .def file name based on the LINKAS argument is actually
  2198 			# NOTE: Changing default .def file name based on the LINKAS argument is actually
  2136 			# a defect, but this follows the behaviour of the current build system.
  2199 			# a defect, but this follows the behaviour of the current build system.
  2137 			if (self.__LINKAS):
  2200 			if (self.__LINKAS):
  2138 				defaultRootName = self.__LINKAS
  2201 				defaultRootName = self.__LINKAS
  2139 
  2202 
  2140 			resolvedDefFile = self.resolveDefFile(defaultRootName, aBuildPlatform)
  2203 			(resolvedDefFile, isSecondaryDefFile) = self.resolveDefFile(defaultRootName, aBuildPlatform)
       
  2204 			# We need to store the resolved .def file and location for the FREEZE target
  2141 			self.__debug("Resolved def file:  %s" % resolvedDefFile )
  2205 			self.__debug("Resolved def file:  %s" % resolvedDefFile )
  2142 			# We need to store this resolved deffile location for the FREEZE target
       
  2143 			self.BuildVariant.AddOperation(raptor_data.Set("RESOLVED_DEFFILE", resolvedDefFile))
  2206 			self.BuildVariant.AddOperation(raptor_data.Set("RESOLVED_DEFFILE", resolvedDefFile))
       
  2207 			# We need to store the primary/secondary status of the resolved .def file as some configurations
       
  2208 			# require additional processing based on the result
       
  2209 			secondaryDefFile = ""
       
  2210 			if isSecondaryDefFile:
       
  2211 				secondaryDefFile = "1"
       
  2212 			self.__debug("Set RESOLVED_DEFFILE_SECONDARY to '%s'" % secondaryDefFile)
       
  2213 			self.BuildVariant.AddOperation(raptor_data.Set("RESOLVED_DEFFILE_SECONDARY", secondaryDefFile))
  2144 
  2214 
  2145 		# If a deffile is specified, an FLM will put in a dependency.
  2215 		# If a deffile is specified, an FLM will put in a dependency.
  2146 		# If a deffile is specified then raptor_meta will guess a name but:
  2216 		# If a deffile is specified then raptor_meta will guess a name but:
  2147 		#	1) If the guess is wrong then the FLM will complain "no rule to make ..."
  2217 		#	1) If the guess is wrong then the FLM will complain "no rule to make ..."
  2148 		#	2) In some cases, e.g. plugin, 1) is not desirable as the presence of a def file
  2218 		#	2) In some cases, e.g. plugin, 1) is not desirable as the presence of a def file
  2296 
  2366 
  2297 		# Put the list of sourcefiles in with one Set operation - saves memory
  2367 		# Put the list of sourcefiles in with one Set operation - saves memory
  2298 		# and performance over using multiple Append operations.
  2368 		# and performance over using multiple Append operations.
  2299 		self.BuildVariant.AddOperation(raptor_data.Set("SOURCE",
  2369 		self.BuildVariant.AddOperation(raptor_data.Set("SOURCE",
  2300 						   " ".join(self.sources)))
  2370 						   " ".join(self.sources)))
       
  2371 		
       
  2372 		# Put the list of document files in with one Set operation - saves memory
       
  2373 		# and performance over using multiple Append operations.
       
  2374 		self.BuildVariant.AddOperation(raptor_data.Set("DOCUMENT",
       
  2375 						   " ".join(self.documents)))
       
  2376 
  2301 
  2377 
  2302 	def validate(self):
  2378 	def validate(self):
  2303 		"""Test that the parsed MMP file is correct.
  2379 		"""Test that the parsed MMP file is correct.
  2304 		
  2380 		
  2305 		By "correct" we mean that all the required keywords were present
  2381 		By "correct" we mean that all the required keywords were present
  2346 
  2422 
  2347 	def resolveDefFile(self, aTARGET, aBuildPlatform):
  2423 	def resolveDefFile(self, aTARGET, aBuildPlatform):
  2348 		"""Returns a fully resolved DEFFILE entry depending on .mmp file location and TARGET, DEFFILE and NOSTRICTDEF
  2424 		"""Returns a fully resolved DEFFILE entry depending on .mmp file location and TARGET, DEFFILE and NOSTRICTDEF
  2349 		entries in the .mmp file itself (where appropriate).
  2425 		entries in the .mmp file itself (where appropriate).
  2350 		Is able to deal with target names that have multiple '.' characters e.g. messageintercept.esockdebug.dll
  2426 		Is able to deal with target names that have multiple '.' characters e.g. messageintercept.esockdebug.dll
       
  2427 		Supports configurations that allow primary and secondary .def file locations.
  2351 		"""
  2428 		"""
  2352 
  2429 
  2353 		resolvedDefFile = ""
  2430 		resolvedDefFile = ""
  2354 		platform = aBuildPlatform['PLATFORM']
  2431 		platform = aBuildPlatform['PLATFORM']
       
  2432 		isSecondaryDefaultDefFile = False
  2355 
  2433 
  2356 		# Not having a default .def file directory is a pretty strong indicator that
  2434 		# Not having a default .def file directory is a pretty strong indicator that
  2357 		# .def files aren't supported for the particular platform
  2435 		# .def files aren't supported for the particular platform
  2358 		if PlatformDefaultDefFileDir.has_key(platform):
  2436 		if PlatformDefaultDefFileDir.has_key(platform):
       
  2437 			
       
  2438 			# Some configurations support both primary and secondary default .def file locations - we need to take this
       
  2439 			# into account in resolving .def file locations
       
  2440 			primaryDefaultDefFileDir = PlatformDefaultDefFileDir[platform]
       
  2441 			secondaryDefaultDefFileDir = ""
       
  2442 			
       
  2443 			if type(PlatformDefaultDefFileDir[platform]) == list:
       
  2444 				(primaryDefaultDefFileDir, secondaryDefaultDefFileDir) = PlatformDefaultDefFileDir[platform]
       
  2445 			
  2359 			(targetname,targetext) = os.path.splitext(aTARGET)
  2446 			(targetname,targetext) = os.path.splitext(aTARGET)
  2360 			(defname,defext) = os.path.splitext(self.deffile)
  2447 			(defname,defext) = os.path.splitext(self.deffile)
  2361 			if defext=="":
  2448 			if defext=="":
  2362 				defext = ".def"
  2449 				defext = ".def"
  2363 
  2450 
  2364 			# NOTE: WORKAROUND
  2451 			# NOTE: WORKAROUND
  2365 			if len(targetext) > 4:
  2452 			if len(targetext) > 4:
  2366 				targetname += defext
  2453 				targetname += defext
  2367 
  2454 
  2368 			if not self.deffile:
  2455 			if not self.deffile:
       
  2456 				# No DEFFILE entry - expected .def filename will be based on the target name
  2369 				resolvedDefFile = targetname
  2457 				resolvedDefFile = targetname
  2370 			else:
  2458 			else:
       
  2459 				# DEFFILE listed - take into account the value, depending on what format it takes
  2371 				if re.search('[\\|\/]$', self.deffile):
  2460 				if re.search('[\\|\/]$', self.deffile):
  2372 					# If DEFFILE is *solely* a path, signified by ending in a slash, then TARGET is the
  2461 					# If DEFFILE is *solely* a path, signified by ending in a slash, then TARGET is the
  2373 					# basis for the default .def filename but with the specified path as prefix
  2462 					# basis for the default .def filename but with the specified path as prefix
  2374 					resolvedDefFile = self.deffile + targetname
  2463 					resolvedDefFile = self.deffile + targetname
  2375 
       
  2376 				else:
  2464 				else:
  2377 					resolvedDefFile = defname
  2465 					resolvedDefFile = defname
  2378 
  2466 
  2379 				resolvedDefFile = resolvedDefFile.replace('~', PlatformDefaultDefFileDir[platform])
  2467 				resolvedDefFile = resolvedDefFile.replace('~', primaryDefaultDefFileDir)
  2380 
  2468 
  2381 			if resolvedDefFile:
  2469 			if not self.nostrictdef:
  2382 				if not self.nostrictdef:
  2470 				resolvedDefFile += 'u'
  2383 					resolvedDefFile += 'u'
  2471 
  2384 
  2472 			if self.__explicitversion:
  2385 				if self.__explicitversion:
  2473 				resolvedDefFile += '{' + self.__versionhex + '}'
  2386 					resolvedDefFile += '{' + self.__versionhex + '}'
  2474 
  2387 
  2475 			resolvedDefFile += defext
  2388 				resolvedDefFile += defext
  2476 
  2389 
  2477 			# If the resolved .def file we have so far doesn't include a path in any shape or form, we prepend the default,
  2390 
  2478 			# implicit, .def file location based on the configuration being built
  2391 				# If a DEFFILE statement doesn't specify a path in any shape or form, prepend the default .def file
  2479 			if not re.search('[\\\/]+', self.deffile):
  2392 				# location based on the platform being built
  2480 				resolvedDefFile = '../'+primaryDefaultDefFileDir+'/'+resolvedDefFile
  2393 				if not re.search('[\\\/]+', self.deffile):
  2481 				
  2394 					resolvedDefFile = '../'+PlatformDefaultDefFileDir[platform]+'/'+resolvedDefFile
  2482 			# Some configurations support a secondary, "fall back", .def file location if a .def file doesn't physically
  2395 
  2483 			# exist at the primary location.
  2396 				resolvedDefFile = raptor_utilities.resolveSymbianPath(self.__defFileRoot, resolvedDefFile, 'DEFFILE', "", str(aBuildPlatform['EPOCROOT']))
  2484 			# We therefore check exisitance of the primary located file if a secondary location is available, and use the
  2397 
  2485 			# secondary location if required (recording the fact that the secondary file has been used, as this can influence
  2398 		return resolvedDefFile
  2486 			# downstream processing).
       
  2487 			if secondaryDefaultDefFileDir:
       
  2488 				primaryFileCheck = raptor_utilities.resolveSymbianPath(self.__defFileRoot, resolvedDefFile, 'DEFFILE', "", str(aBuildPlatform['EPOCROOT']))
       
  2489 			
       
  2490 				if not os.path.exists(primaryFileCheck):
       
  2491 					isSecondaryDefaultDefFile = True
       
  2492 					resolvedDefFile = '../'+secondaryDefaultDefFileDir+'/'+os.path.basename(resolvedDefFile)
       
  2493 
       
  2494 			resolvedDefFile = raptor_utilities.resolveSymbianPath(self.__defFileRoot, resolvedDefFile, 'DEFFILE', "", str(aBuildPlatform['EPOCROOT']))
       
  2495 
       
  2496 		return (resolvedDefFile, isSecondaryDefaultDefFile)
  2399 
  2497 
  2400 
  2498 
  2401 def CheckedGet(self, key, default = None):
  2499 def CheckedGet(self, key, default = None):
  2402 	"""extract a value from an self and raise an exception if None.
  2500 	"""extract a value from an self and raise an exception if None.
  2403 
  2501 
  2520 				detail['ISFEATUREVARIANT'] = False
  2618 				detail['ISFEATUREVARIANT'] = False
  2521 
  2619 
  2522 			detail['VARIANT_HRH'] = variantHRH
  2620 			detail['VARIANT_HRH'] = variantHRH
  2523 			self.__Raptor.Info("'%s' uses variant hrh file '%s'", buildConfig.name, variantHRH)
  2621 			self.__Raptor.Info("'%s' uses variant hrh file '%s'", buildConfig.name, variantHRH)
  2524 			detail['SYSTEMINCLUDE'] = evaluator.CheckedGet("SYSTEMINCLUDE")
  2622 			detail['SYSTEMINCLUDE'] = evaluator.CheckedGet("SYSTEMINCLUDE")
  2525 
  2623             
       
  2624 			detail['TARGET_TYPES'] = evaluator.CheckedGet("TARGET_TYPES")
  2526 
  2625 
  2527 			# find all the interface names we need
  2626 			# find all the interface names we need
  2528 			ifaceTypes = evaluator.CheckedGet("INTERFACE_TYPES")
  2627 			ifaceTypes = evaluator.CheckedGet("INTERFACE_TYPES")
  2529 			interfaces = ifaceTypes.split()
  2628 			interfaces = ifaceTypes.split()
  2530 
  2629 
  3241 			if mmpFileEntry.armoption:
  3340 			if mmpFileEntry.armoption:
  3242 				var.AddOperation(raptor_data.Set("ALWAYS_BUILD_AS_ARM","1"))
  3341 				var.AddOperation(raptor_data.Set("ALWAYS_BUILD_AS_ARM","1"))
  3243 
  3342 
  3244 			# what interface builds this node?
  3343 			# what interface builds this node?
  3245 			try:
  3344 			try:
  3246 				interfaceName = buildPlatform[backend.getTargetType()]
  3345 				targettype = backend.getTargetType()
  3247 				mmpSpec.SetInterface(interfaceName)
  3346 				validtargettypes = buildPlatform['TARGET_TYPES'].split()
  3248 			except KeyError:
  3347 			except KeyError:
  3249 				self.__Raptor.Error("Unsupported target type '%s' in %s",
  3348 				# Shouldn't get this since it should have been CheckedGetted already
  3250 								    backend.getTargetType(),
  3349 				self.__Raptor.Error("TARGET_TYPES not defined in platform %s",
  3251 								    str(mmpFileEntry.filename),
  3350 									buildPlatform['PLATFORM'])
       
  3351 
       
  3352 			try:
       
  3353 				if not targettype in validtargettypes:
       
  3354 					self.__Raptor.Error("Unsupported target type '%s' in %s - should be one of %s",
       
  3355 										targettype,
       
  3356 										str(mmpFileEntry.filename),
       
  3357 										", ".join(validtargettypes),
       
  3358 										bldinf=str(bldInfFile))
       
  3359 				else:
       
  3360 					interfaceName = buildPlatform[targettype]
       
  3361 					mmpSpec.SetInterface(interfaceName)
       
  3362 			except KeyError:
       
  3363 				# Shouldn't get this far unless INTERFACE_TYPES doesn't contain TARGET_TYPES
       
  3364 				self.__Raptor.Error("%s interface not defined for %s (invalid configuration?)",
       
  3365 								    targettype,
       
  3366 									buildPlatform['PLATFORM'],
  3252 								    bldinf=str(bldInfFile))
  3367 								    bldinf=str(bldInfFile))
  3253 				continue
  3368 				continue
  3254 
  3369 
  3255 			# Although not part of the MMP, some MMP-based build specs additionally require knowledge of their
  3370 			# Although not part of the MMP, some MMP-based build specs additionally require knowledge of their
  3256 			# container bld.inf exported headers
  3371 			# container bld.inf exported headers