sbsv2/raptor/python/raptor_meta.py
changeset 616 24e4ef208cca
parent 590 360bd6b35136
child 625 a1925fb7753a
equal deleted inserted replaced
613:839712f5a78c 616:24e4ef208cca
    33 import zipfile
    33 import zipfile
    34 from xml.sax.saxutils import escape
    34 from xml.sax.saxutils import escape
    35 from mmpparser import *
    35 from mmpparser import *
    36 
    36 
    37 import time
    37 import time
       
    38 import generic_path
    38 
    39 
    39 
    40 
    40 PiggyBackedBuildPlatforms = {'ARMV5':['GCCXML']}
    41 PiggyBackedBuildPlatforms = {'ARMV5':['GCCXML']}
    41 
    42 
    42 PlatformDefaultDefFileDir = {'WINSCW':'bwins',
    43 PlatformDefaultDefFileDir = {'WINSCW':'bwins',
   766 			eiloc="." # Someone building with a relative raptor path
   767 			eiloc="." # Someone building with a relative raptor path
   767 		if biloc is None or biloc == "":
   768 		if biloc is None or biloc == "":
   768 			biloc="." # Someone building with a relative raptor path
   769 			biloc="." # Someone building with a relative raptor path
   769 
   770 
   770 		self.__StandardVariables = {}
   771 		self.__StandardVariables = {}
   771 		# Relative step-down to the root - let's try ignoring this for now, as it
   772 		# The source root directory is SRCROOT if set in the environment
   772 		# should amount to the same thing in a world where absolute paths are king
   773 		# Set TO_ROOT to SRCROOT in case SBS_BUILD_DIR is on a different drive
   773 		self.__StandardVariables['TO_ROOT'] = ""
   774 		if 'SRCROOT' in os.environ:
       
   775 			self.__StandardVariables['TO_ROOT'] = str(generic_path.Path(os.environ['SRCROOT']))
       
   776 		else:
       
   777 			self.__StandardVariables['TO_ROOT'] = ""
       
   778 		
   774 		# Top-level bld.inf location
   779 		# Top-level bld.inf location
   775 		self.__StandardVariables['TO_BLDINF'] = biloc
   780 		self.__StandardVariables['TO_BLDINF'] = biloc
   776 		self.__StandardVariables['EXTENSION_ROOT'] = eiloc
   781 		self.__StandardVariables['EXTENSION_ROOT'] = eiloc
   777 
   782 
   778 		# Get the directory and filename from the full path containing the extension makefile
   783 		# Get the directory and filename from the full path containing the extension makefile
   836 		eiloc = str(extInfLocation)
   841 		eiloc = str(extInfLocation)
   837 		if eiloc is None or eiloc == "":
   842 		if eiloc is None or eiloc == "":
   838 			eiloc="." # Someone building with a relative raptor path
   843 			eiloc="." # Someone building with a relative raptor path
   839 
   844 
   840 		self.__StandardVariables = {}
   845 		self.__StandardVariables = {}
   841 		# Relative step-down to the root - let's try ignoring this for now, as it
   846 		# The source root directory is SRCROOT if set in the environment	
   842 		# should amount to the same thing in a world where absolute paths are king
   847 		# Set TO_ROOT to SRCROOT in case SBS_BUILD_DIR is on a different drive
   843 		self.__StandardVariables['TO_ROOT'] = ""
   848 		if 'SRCROOT' in os.environ:
       
   849 			self.__StandardVariables['TO_ROOT'] = str(generic_path.Path(os.environ['SRCROOT']))
       
   850 		else:
       
   851 			self.__StandardVariables['TO_ROOT'] = ""
   844 		# Top-level bld.inf location
   852 		# Top-level bld.inf location
   845 		self.__StandardVariables['TO_BLDINF'] = biloc
   853 		self.__StandardVariables['TO_BLDINF'] = biloc
   846 		# Location of bld.inf file containing the current EXTENSION block
   854 		# Location of bld.inf file containing the current EXTENSION block
   847 		self.__StandardVariables['EXTENSION_ROOT'] = eiloc
   855 		self.__StandardVariables['EXTENSION_ROOT'] = eiloc
   848 
   856 
  1205 		'killanyprocess':0,
  1213 		'killanyprocess':0,
  1206 		'devman':0,
  1214 		'devman':0,
  1207 		'phonenetwork':0,
  1215 		'phonenetwork':0,
  1208 		'localnetwork':0
  1216 		'localnetwork':0
  1209 	  	}
  1217 	  	}
       
  1218 	
       
  1219 	# Valid ARMFPU options
       
  1220 	armfpu_options = [
       
  1221 		'softvfp',
       
  1222 		'vfpv2',
       
  1223 		'softvfp+vfpv2'
       
  1224 		]
  1210 
  1225 
  1211 	library_re = re.compile(r"^(?P<name>[^{]+?)(?P<version>{(?P<major>[0-9]+)\.(?P<minor>[0-9]+)})?(\.(lib|dso))?$",re.I)
  1226 	library_re = re.compile(r"^(?P<name>[^{]+?)(?P<version>{(?P<major>[0-9]+)\.(?P<minor>[0-9]+)})?(\.(lib|dso))?$",re.I)
  1212 
  1227 
  1213 
  1228 
  1214 	def __init__(self, aRaptor, aMmpfilename, aBldInfFilename):
  1229 	def __init__(self, aRaptor, aMmpfilename, aBldInfFilename):
  1489 				else:
  1504 				else:
  1490 					self.__Raptor.Warn("VERSION (%s) missing '.minor' in %s, using '.0'" % (toks[1],self.__currentMmpFile))
  1505 					self.__Raptor.Warn("VERSION (%s) missing '.minor' in %s, using '.0'" % (toks[1],self.__currentMmpFile))
  1491 
  1506 
  1492 				self.__versionhex = "%04x%04x" % (major, minor)
  1507 				self.__versionhex = "%04x%04x" % (major, minor)
  1493 				self.BuildVariant.AddOperation(raptor_data.Set(varname, "%d.%d" %(major, minor)))
  1508 				self.BuildVariant.AddOperation(raptor_data.Set(varname, "%d.%d" %(major, minor)))
  1494 				self.BuildVariant.AddOperation(raptor_data.Set(varname+"HEX", self.__versionhex))
  1509 				self.BuildVariant.AddOperation(raptor_data.Set("VERSIONHEX", self.__versionhex))
  1495 				self.__debug("Set "+toks[0]+"  OPTION to " + toks[1])
  1510 				self.__debug("Set "+toks[0]+"  OPTION to " + toks[1])
  1496 				self.__debug("Set "+toks[0]+"HEX OPTION to " + "%04x%04x" % (major,minor))
  1511 				self.__debug("Set VERSIONHEX OPTION to " + self.__versionhex)
  1497 
  1512 
  1498 			else:
  1513 			else:
  1499 				self.__Raptor.Warn("Invalid version supplied to VERSION (%s), using default value" % toks[1])
  1514 				self.__Raptor.Warn("Invalid version supplied to VERSION (%s), using default value" % toks[1])
  1500 
  1515 
  1501 		elif varname=='EPOCHEAPSIZE':
  1516 		elif varname=='EPOCHEAPSIZE':
  1553 					toks1 = re.sub("[,'\[\]]", "", toks1).replace("//","/")
  1568 					toks1 = re.sub("[,'\[\]]", "", toks1).replace("//","/")
  1554 				self.__debug("Set "+toks[0]+" to " + toks1)
  1569 				self.__debug("Set "+toks[0]+" to " + toks1)
  1555 				self.BuildVariant.AddOperation(raptor_data.Set(varname,toks1))
  1570 				self.BuildVariant.AddOperation(raptor_data.Set(varname,toks1))
  1556 		elif varname=='APPLY':
  1571 		elif varname=='APPLY':
  1557 			self.ApplyVariants.append(toks[1])
  1572 			self.ApplyVariants.append(toks[1])
       
  1573 		elif varname=='ARMFPU':
       
  1574 			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))
       
  1576 			else:
       
  1577 				self.__debug("Set "+toks[0]+" to " + str(toks[1]))
       
  1578 				self.BuildVariant.AddOperation(raptor_data.Set(varname,str(toks[1])))
  1558 		else:
  1579 		else:
  1559 			self.__debug("Set "+toks[0]+" to " + str(toks[1]))
  1580 			self.__debug("Set "+toks[0]+" to " + str(toks[1]))
  1560 			self.BuildVariant.AddOperation(raptor_data.Set(varname,"".join(toks[1])))
  1581 			self.BuildVariant.AddOperation(raptor_data.Set(varname,"".join(toks[1])))
  1561 
  1582 
  1562 			if varname=='LINKAS':
  1583 			if varname=='LINKAS':
  2276 		# Put the list of sourcefiles in with one Set operation - saves memory
  2297 		# Put the list of sourcefiles in with one Set operation - saves memory
  2277 		# and performance over using multiple Append operations.
  2298 		# and performance over using multiple Append operations.
  2278 		self.BuildVariant.AddOperation(raptor_data.Set("SOURCE",
  2299 		self.BuildVariant.AddOperation(raptor_data.Set("SOURCE",
  2279 						   " ".join(self.sources)))
  2300 						   " ".join(self.sources)))
  2280 
  2301 
       
  2302 	def validate(self):
       
  2303 		"""Test that the parsed MMP file is correct.
       
  2304 		
       
  2305 		By "correct" we mean that all the required keywords were present
       
  2306 		with acceptable and mutually consistent values.
       
  2307 		
       
  2308 		There should be no attempt to build anything if this method returns False."""
       
  2309 		
       
  2310 		# do all the checks so that we can see all the errors at once...
       
  2311 		valid = True
       
  2312 		
       
  2313 		# for "TARGETTYPE none", it is permitted to omit the "TARGET" keyword
       
  2314 		if not self.__TARGET and not self.getTargetType() == "none":
       
  2315 			self.__Raptor.Error("required keyword TARGET is missing in " + self.__currentMmpFile, bldinf=self.__bldInfFilename)
       
  2316 			valid = False
       
  2317 		
       
  2318 		# what else could be wrong?
       
  2319 			
       
  2320 		return valid
       
  2321 	
  2281 	def getTargetType(self):
  2322 	def getTargetType(self):
  2282 		"""Target type in lower case - the standard format"""
  2323 		"""Target type in lower case - the standard format"""
  2283 		return self.__targettype.lower()
  2324 		return self.__targettype.lower()
  2284 
  2325 
  2285 	def resolveCompressionKeyword(self, aCompressionKeyword):
  2326 	def resolveCompressionKeyword(self, aCompressionKeyword):
  2853 
  2894 
  2854 
  2895 
  2855 			destDir = destination.Dir()
  2896 			destDir = destination.Dir()
  2856 			if not destDir.isDir():
  2897 			if not destDir.isDir():
  2857 				os.makedirs(str(destDir))
  2898 				os.makedirs(str(destDir))
  2858 				shutil.copyfile(source_str, dest_str)
  2899 				# preserve permissions
       
  2900 				shutil.copy(source_str, dest_str)
  2859 				return exportwhatlog
  2901 				return exportwhatlog
  2860 
  2902 
  2861 			sourceMTime = 0
  2903 			sourceMTime = 0
  2862 			destMTime = 0
  2904 			destMTime = 0
  2863 			sourceStat = 0
  2905 			sourceStat = 0
  2872 						raise MetaDataError(message)
  2914 						raise MetaDataError(message)
  2873 					else:
  2915 					else:
  2874 						self.__Raptor.Error(message, bldinf=bldInfFile)
  2916 						self.__Raptor.Error(message, bldinf=bldInfFile)
  2875 
  2917 
  2876 			if destMTime == 0 or destMTime < sourceMTime:
  2918 			if destMTime == 0 or destMTime < sourceMTime:
       
  2919 				# remove old version
       
  2920 				#	- not having ownership prevents chmod
       
  2921 				#	- avoid clobbering the original if it is a hard link
  2877 				if os.path.exists(dest_str):
  2922 				if os.path.exists(dest_str):
  2878 					os.chmod(dest_str,stat.S_IREAD | stat.S_IWRITE)
  2923 					os.unlink(dest_str)
  2879 				shutil.copyfile(source_str, dest_str)
  2924 				# preserve permissions
  2880 
  2925 				shutil.copy(source_str, dest_str)
  2881 				# Ensure that the destination file remains executable if the source was also:
  2926 
  2882 				os.chmod(dest_str,sourceStat[stat.ST_MODE] | stat.S_IREAD | stat.S_IWRITE | stat.S_IWGRP ) 
       
  2883 				self.__Raptor.Info("Copied %s to %s", source_str, dest_str)
  2927 				self.__Raptor.Info("Copied %s to %s", source_str, dest_str)
  2884 			else:
  2928 			else:
  2885 				self.__Raptor.Info("Up-to-date: %s", dest_str)
  2929 				self.__Raptor.Info("Up-to-date: %s", dest_str)
  2886 
  2930 
  2887 
  2931 
  2921 			markerfiledir = generic_path.Path(_sbs_build_dir)
  2965 			markerfiledir = generic_path.Path(_sbs_build_dir)
  2922 			if not markerfiledir.isDir():
  2966 			if not markerfiledir.isDir():
  2923 				os.makedirs(str(markerfiledir))
  2967 				os.makedirs(str(markerfiledir))
  2924 
  2968 
  2925 			# Form the marker file name and convert to Python string
  2969 			# Form the marker file name and convert to Python string
  2926 			markerfilename = str(generic_path.Join(markerfiledir, sanitisedSource + sanitisedDestination + ".unzipped"))
  2970 			combinedPath = sanitisedSource + sanitisedDestination
       
  2971 			sanitisedPath = self.unzippedPathFragment(combinedPath)
       
  2972 			markerfilename = str(generic_path.Join(markerfiledir, sanitisedPath + ".unzipped"))
  2927 
  2973 
  2928 			# Don't unzip if the marker file is already there or more uptodate
  2974 			# Don't unzip if the marker file is already there or more uptodate
  2929 			sourceMTime = 0
  2975 			sourceMTime = 0
  2930 			destMTime = 0
  2976 			destMTime = 0
  2931 			try:
  2977 			try:
  3080 			for option in options:
  3126 			for option in options:
  3081 				self.__Raptor.Debug("Set %s=%s", option, options[option])
  3127 				self.__Raptor.Debug("Set %s=%s", option, options[option])
  3082 				value = options[option].replace('$(EPOCROOT)', '$(EPOCROOT)/')
  3128 				value = options[option].replace('$(EPOCROOT)', '$(EPOCROOT)/')
  3083 				value = value.replace('$(', '$$$$(')
  3129 				value = value.replace('$(', '$$$$(')
  3084 				value = value.replace('$/', '/').replace('$;', ':')
  3130 				value = value.replace('$/', '/').replace('$;', ':')
  3085 				value = value.replace('$/', '/').replace('$;', ':')
       
  3086 
  3131 
  3087 				if customInterface:
  3132 				if customInterface:
  3088 					var.AddOperation(raptor_data.Set(option, value))
  3133 					var.AddOperation(raptor_data.Set(option, value))
  3089 				else:
  3134 				else:
  3090 					var.AddOperation(raptor_data.Append("O._MEMBERS", option))
  3135 					var.AddOperation(raptor_data.Append("O._MEMBERS", option))
  3161 				self.__Raptor.Debug(content)
  3206 				self.__Raptor.Debug(content)
  3162 				self.__Raptor.Debug("The parse result was %s", parseresult)
  3207 				self.__Raptor.Debug("The parse result was %s", parseresult)
  3163 			else:
  3208 			else:
  3164 				backend.finalise(buildPlatform)
  3209 				backend.finalise(buildPlatform)
  3165 
  3210 
       
  3211 			# if the parsed MMP file is fundamentally broken then report
       
  3212 			# the errors and stop processing this MMP node
       
  3213 			if not backend.validate():
       
  3214 				continue
       
  3215 			
  3166 			# feature variation only processes FEATUREVARIANT binaries
  3216 			# feature variation only processes FEATUREVARIANT binaries
  3167 			if buildPlatform["ISFEATUREVARIANT"] and not backend.featureVariant:
  3217 			if buildPlatform["ISFEATUREVARIANT"] and not backend.featureVariant:
  3168 				continue
  3218 				continue
  3169 			
  3219 			
  3170 			# now build the specification tree
  3220 			# now build the specification tree
  3349 		if osVersion and osVersion in self.__Raptor.cache.variants:
  3399 		if osVersion and osVersion in self.__Raptor.cache.variants:
  3350 			self.__Raptor.Info("applying the OS variant to the configuration \"%s\"." % aBuildUnit.name)
  3400 			self.__Raptor.Info("applying the OS variant to the configuration \"%s\"." % aBuildUnit.name)
  3351 			aBuildUnit.variants.append(self.__Raptor.cache.variants[osVersion])
  3401 			aBuildUnit.variants.append(self.__Raptor.cache.variants[osVersion])
  3352 		else:
  3402 		else:
  3353 			self.__Raptor.Info("no OS variant for the configuration \"%s\"." % aBuildUnit.name)
  3403 			self.__Raptor.Info("no OS variant for the configuration \"%s\"." % aBuildUnit.name)
  3354 
  3404 			
       
  3405 	@classmethod		
       
  3406 	def unzippedPathFragment(self, sanitisedPath):
       
  3407 		fragment = hashlib.md5(sanitisedPath).hexdigest()[:16]
       
  3408 		return fragment
       
  3409 
       
  3410