sbsv2/raptor/python/raptor_make.py
branchfix
changeset 39 164b0547f8a5
parent 29 ee00c00df073
child 118 375b7128e900
equal deleted inserted replaced
6:29df63210f13 39:164b0547f8a5
    18 
    18 
    19 import hashlib
    19 import hashlib
    20 import os
    20 import os
    21 import random
    21 import random
    22 import raptor
    22 import raptor
    23 import raptor_data
    23 import raptor_timing
    24 import raptor_utilities
    24 import raptor_utilities
    25 import raptor_version
    25 import raptor_version
       
    26 import raptor_data
    26 import re
    27 import re
    27 import subprocess
    28 import subprocess
    28 import time
    29 import time
    29 from raptor_makefile import *
    30 from raptor_makefile import *
       
    31 import traceback
       
    32 import sys
    30 
    33 
    31 # raptor_make module classes
    34 # raptor_make module classes
    32 
    35 
    33 class MakeEngine(object):
    36 class MakeEngine(object):
    34 
    37 
    35 	def __init__(self, Raptor):
    38 	def __init__(self, Raptor):
    36 		self.raptor = Raptor
    39 		self.raptor = Raptor
    37 		self.valid = True
    40 		self.valid = True
    38 		self.makefileset = None
       
    39 		self.descrambler = None
    41 		self.descrambler = None
    40 		self.descrambler_started = False
    42 		self.descrambler_started = False
    41 
    43 
    42 		engine = Raptor.makeEngine
    44 		engine = Raptor.makeEngine
    43 		
    45 		
    51 			Raptor.Error("No settings found for build engine '%s'", engine)
    53 			Raptor.Error("No settings found for build engine '%s'", engine)
    52 			return
    54 			return
    53 					
    55 					
    54 		# find the variant and extract the values
    56 		# find the variant and extract the values
    55 		try:
    57 		try:
    56 			units = avar.GenerateBuildUnits()
    58 			units = avar.GenerateBuildUnits(Raptor.cache)
    57 			evaluator = Raptor.GetEvaluator( None, units[0] , gathertools=True)
    59 			evaluator = Raptor.GetEvaluator( None, units[0] , gathertools=True)
    58 
    60 
    59 			# shell
    61 			# shell
    60 			self.shellpath = evaluator.Get("DEFAULT_SHELL")
    62 			self.shellpath = evaluator.Get("DEFAULT_SHELL")
    61 			usetalon_s = evaluator.Get("USE_TALON") 
    63 			usetalon_s = evaluator.Get("USE_TALON") 
   121  host='$$HOSTNAME'\
   123  host='$$HOSTNAME'\
   122  layer='$$COMPONENT_LAYER'\
   124  layer='$$COMPONENT_LAYER'\
   123  component='$$COMPONENT_NAME'\
   125  component='$$COMPONENT_NAME'\
   124  bldinf='$$COMPONENT_META' mmp='$$PROJECT_META'\
   126  bldinf='$$COMPONENT_META' mmp='$$PROJECT_META'\
   125  config='$$SBS_CONFIGURATION' platform='$$PLATFORM'\
   127  config='$$SBS_CONFIGURATION' platform='$$PLATFORM'\
   126  phase='$$MAKEFILE_GROUP' source='$$SOURCE
   128  phase='$$MAKEFILE_GROUP' source='$$SOURCE'
   127 export TALON_RECIPEATTRIBUTES TALON_SHELL TALON_TIMEOUT
   129 export TALON_RECIPEATTRIBUTES TALON_SHELL TALON_TIMEOUT
   128 USE_TALON:=%s
   130 USE_TALON:=%s
   129 
   131 
   130 """ % (self.talonshell, self.talontimeout, "1")
   132 """ % (self.talonshell, self.talontimeout, "1")
   131 		else:
   133 		else:
   132 			talon_settings="""
   134 			talon_settings="""
   133 USE_TALON:=
   135 USE_TALON:=
   134 
   136 
   135 """
   137 """
   136 		
   138 
       
   139 
       
   140 		timing_start = "$(info " + \
       
   141 				raptor_timing.Timing.custom_string(tag = "start",
       
   142 				object_type = "makefile", task = "parse",
       
   143 				key = "$(THIS_FILENAME)",
       
   144 				time="$(shell date +%s.%N)").rstrip("\n") + ")"
       
   145 				
       
   146 		timing_end = "$(info " + \
       
   147 				raptor_timing.Timing.custom_string(tag = "end",
       
   148 				object_type = "makefile", task = "parse",
       
   149 				key = "$(THIS_FILENAME)",
       
   150 				time="$(shell date +%s.%N)").rstrip("\n") + ")"
       
   151 
   137 
   152 
   138 		self.makefile_prologue = """
   153 		self.makefile_prologue = """
       
   154 
   139 # generated by %s %s
   155 # generated by %s %s
   140 
   156 
   141 HOSTPLATFORM:=%s
   157 HOSTPLATFORM:=%s
   142 HOSTPLATFORM_DIR:=%s
   158 HOSTPLATFORM_DIR:=%s
   143 OSTYPE:=%s
   159 OSTYPE:=%s
   144 FLMHOME:=%s
   160 FLMHOME:=%s
   145 SHELL:=%s
   161 SHELL:=%s
       
   162 THIS_FILENAME:=$(firstword $(MAKEFILE_LIST))
   146 
   163 
   147 %s
   164 %s
   148 
   165 
   149 include %s
   166 include %s
   150 
   167 
   151 """ 		% (  raptor.name, raptor_version.Version(),
   168 """ 		% (  raptor.name, raptor_version.fullversion(),
   152 			 " ".join(raptor.hostplatform),
   169 			 " ".join(raptor.hostplatform),
   153 			 raptor.hostplatform_dir,
   170 			 raptor.hostplatform_dir,
   154 			 self.raptor.filesystem,
   171 			 self.raptor.filesystem,
   155 			 str(self.raptor.systemFLM),
   172 			 str(self.raptor.systemFLM),
   156 			 self.shellpath,
   173 			 self.shellpath,
   157 			 talon_settings,
   174 			 talon_settings,
   158 			 self.raptor.systemFLM.Append('globals.mk') )
   175 			 self.raptor.systemFLM.Append('globals.mk') )
   159 
   176 
   160 
   177 		# Only output timings if requested on CLI
   161 		self.makefile_epilogue = """
   178 		if self.raptor.timing:
       
   179 			self.makefile_prologue += "\n# Print Start-time of Makefile parsing\n" \
       
   180 					+ timing_start + "\n\n"
       
   181 	
       
   182 	
       
   183 			self.makefile_epilogue = "\n\n# Print End-time of Makefile parsing\n" \
       
   184 				+ timing_end + "\n"
       
   185 		else:
       
   186 			self.makefile_epilogue = ""
       
   187 
       
   188 		self.makefile_epilogue += """
   162 
   189 
   163 include %s
   190 include %s
   164 
   191 
   165 """ 			% (self.raptor.systemFLM.Append('final.mk') )
   192 """ 			% (self.raptor.systemFLM.Append('final.mk') )
   166 
   193 
   167 	def Write(self, toplevel, specs, configs):
   194 	def Write(self, toplevel, specs, configs):
   168 		"""Generate a set of makefiles, or one big Makefile."""
   195 		"""Generate a set of makefiles, or one big Makefile."""
   169 
   196 
   170 		if not self.valid:
   197 		if not self.valid:
   171 			return
   198 			return None
       
   199 
       
   200 		self.raptor.Debug("Writing Makefile '%s'" % (str(toplevel)))
   172 
   201 
   173 		self.toplevel = toplevel
   202 		self.toplevel = toplevel
   174 
   203 
   175 		# create the top-level makefiles
   204 		# create the top-level makefiles
       
   205 		makefileset = None
   176 
   206 
   177 		try:
   207 		try:
   178 			self.makefileset = MakefileSet(directory = str(toplevel.Dir()),
   208 			makefileset = MakefileSet(directory = str(toplevel.Dir()),
   179 										   selectors = self.selectors,
   209 										   selectors = self.selectors,
   180 										   filenamebase = str(toplevel.File()),
   210 										   filenamebase = str(toplevel.File()),
   181 										   prologue = self.makefile_prologue,
   211 										   prologue = self.makefile_prologue,
   182 										   epilogue = self.makefile_epilogue,
   212 										   epilogue = self.makefile_epilogue,
   183 										   defaulttargets = self.defaultTargets)
   213 										   defaulttargets = self.defaultTargets)
   188 
   218 
   189 			# are we writing one Makefile or lots?
   219 			# are we writing one Makefile or lots?
   190 			self.many = not self.raptor.writeSingleMakefile
   220 			self.many = not self.raptor.writeSingleMakefile
   191 
   221 
   192 			# add a makefile for each spec under each config
   222 			# add a makefile for each spec under each config
   193 			config_makefileset = self.makefileset
   223 			config_makefileset = makefileset
   194 
       
   195 			for c in configs:
   224 			for c in configs:
   196 				if self.many:
   225 				if self.many:
   197 					config_makefileset = self.makefileset.createChild(c.name)
   226 					config_makefileset = makefileset.createChild(c.name)
   198 
   227 
   199 				# make sure the config_wide spec item is put out first so that it
   228 				# make sure the config_wide spec item is put out first so that it
   200 				# can affect everything.
   229 				# can affect everything.
   201 				ordered_specs=[]
   230 				ordered_specs=[]
   202 				config_wide_spec = None
   231 				config_wide_spec = None
   205 						config_wide_spec = s
   234 						config_wide_spec = s
   206 					else:
   235 					else:
   207 						ordered_specs.append(s)
   236 						ordered_specs.append(s)
   208 
   237 
   209 				if config_wide_spec is not None:
   238 				if config_wide_spec is not None:
   210 					config_wide_spec.Configure(c)
   239 					config_wide_spec.Configure(c, cache = self.raptor.cache)
   211 					self.WriteConfiguredSpec(config_makefileset, config_wide_spec, c, True)
   240 					self.WriteConfiguredSpec(config_makefileset, config_wide_spec, c, True)
   212 
   241 
   213 				for s in ordered_specs:
   242 				for s in ordered_specs:
   214 					s.Configure(c)
   243 					s.Configure(c, cache = self.raptor.cache)
   215 					self.WriteConfiguredSpec(config_makefileset, s, c, False)
   244 					self.WriteConfiguredSpec(config_makefileset, s, c, False)
   216 
   245 
   217 			self.makefileset.close()
   246 			makefileset.close()
   218 		except Exception,e:
   247 		except Exception,e:
   219 			self.raptor.Error("Failed to write makefile '%s': %s" % (str(toplevel),str(e)))
   248 			tb = traceback.format_exc()
       
   249 			if not self.raptor.debugOutput:
       
   250 				tb=""
       
   251 			self.raptor.Error("Failed to write makefile '%s': %s : %s" % (str(toplevel),str(e),tb))
       
   252 			makefileset = None
       
   253 
       
   254 		return makefileset
   220 
   255 
   221 
   256 
   222 	def WriteConfiguredSpec(self, parentMakefileSet, spec, config, useAllInterfaces):
   257 	def WriteConfiguredSpec(self, parentMakefileSet, spec, config, useAllInterfaces):
   223 		# ignore this spec if it is empty
   258 		# ignore this spec if it is empty
   224 		hasInterface = spec.HasInterface()
   259 		hasInterface = spec.HasInterface()
   231 		dupe = True
   266 		dupe = True
   232 		iface = None
   267 		iface = None
   233 		guard = None
   268 		guard = None
   234 		if hasInterface:
   269 		if hasInterface:
   235 			# find the Interface (it may be a ref)
   270 			# find the Interface (it may be a ref)
   236 			iface = spec.GetInterface()
   271 			try:
   237 
   272 				iface = spec.GetInterface(self.raptor.cache)
   238 			if iface == None:
   273 
       
   274 			except raptor_data.MissingInterfaceError, e:	
   239 				self.raptor.Error("No interface for '%s'", spec.name)
   275 				self.raptor.Error("No interface for '%s'", spec.name)
   240 				return
   276 				return
   241 
   277 
   242 			if iface.abstract:
   278 			if iface.abstract:
   243 				self.raptor.Error("Abstract interface '%s' for '%s'",
   279 				self.raptor.Error("Abstract interface '%s' for '%s'",
   266 
   302 
   267 				parameters.append((k, value))
   303 				parameters.append((k, value))
   268 				md5hash.update(value)
   304 				md5hash.update(value)
   269 
   305 
   270 			# parameters required by the interface
   306 			# parameters required by the interface
   271 			for p in iface.GetParams():
   307 			for p in iface.GetParams(self.raptor.cache):
   272 				val = evaluator.Resolve(p.name)
   308 				val = evaluator.Resolve(p.name)
   273 				addparam(p.name,val,p.default)
   309 				addparam(p.name,val,p.default)
   274 
   310 
   275 			# Use Patterns to fetch a group of parameters
   311 			# Use Patterns to fetch a group of parameters
   276 			for g in iface.GetParamGroups():
   312 			for g in iface.GetParamGroups(self.raptor.cache):
   277 				for k,v in evaluator.ResolveMatching(g.patternre):
   313 				for k,v in evaluator.ResolveMatching(g.patternre):
   278 					addparam(k,v,g.default)
   314 					addparam(k,v,g.default)
   279 
   315 
   280 			hash = md5hash.hexdigest()
   316 			hash = md5hash.hexdigest()
   281 			dupe = hash in self.hashes
   317 			dupe = hash in self.hashes
   299 			else:
   335 			else:
   300 				guard = "guard_" + hash
   336 				guard = "guard_" + hash
   301 
   337 
   302 		# generate the call to the FLM
   338 		# generate the call to the FLM
   303 		if iface is not None:
   339 		if iface is not None:
   304 			makefileset.addCall(spec.name, config.name, iface.name, useAllInterfaces, iface.GetFLMIncludePath(), parameters, guard)
   340 			makefileset.addCall(spec.name, config.name, iface.name, useAllInterfaces, iface.GetFLMIncludePath(self.raptor.cache), parameters, guard)
   305 
   341 
   306 		# recursive includes
   342 		# recursive includes
   307 
   343 
   308 		for child in childSpecs:
   344 		for child in childSpecs:
   309 			self.WriteConfiguredSpec(makefileset, child, config, useAllInterfaces)
   345 			self.WriteConfiguredSpec(makefileset, child, config, useAllInterfaces)
   339 				self.raptor.Error("Failed in %s", self.initCommand)
   375 				self.raptor.Error("Failed in %s", self.initCommand)
   340 				self.Tidy()
   376 				self.Tidy()
   341 				return False
   377 				return False
   342 
   378 
   343 		# Save file names to a list, to allow the order to be reversed
   379 		# Save file names to a list, to allow the order to be reversed
   344 		fileName_list = list(self.makefileset.makefileNames())
   380 		fileName_list = list(makefileset.makefileNames())
   345 
   381 
   346 		# Iterate through args passed to raptor, searching for CLEAN or REALLYCLEAN
   382 		# Iterate through args passed to raptor, searching for CLEAN or REALLYCLEAN
   347 		clean_flag = False
   383 		clean_flag = False
   348 		for arg in self.raptor.args:
   384 		for arg in self.raptor.args:
   349 			clean_flag = ("CLEAN" in self.raptor.args) or \
   385 			clean_flag = ("CLEAN" in self.raptor.args) or \
   351 
   387 
   352 		# Files should be deleted in the opposite order to the order
   388 		# Files should be deleted in the opposite order to the order
   353 		# they were built. So reverse file order if cleaning
   389 		# they were built. So reverse file order if cleaning
   354 		if clean_flag:
   390 		if clean_flag:
   355 			fileName_list.reverse()
   391 			fileName_list.reverse()
       
   392 
       
   393 		# Report number of makefiles to be built
       
   394 		self.raptor.InfoDiscovery(object_type = "makefile", count = len(fileName_list))
   356 
   395 
   357 		# Process each file in turn
   396 		# Process each file in turn
   358 		for makefile in fileName_list:
   397 		for makefile in fileName_list:
   359 			if not os.path.exists(makefile):
   398 			if not os.path.exists(makefile):
   360 				self.raptor.Info("Skipping makefile %s", makefile)
   399 				self.raptor.Info("Skipping makefile %s", makefile)
   399 				command += ' RECIPETRIES=' + str(self.raptor.tries)
   438 				command += ' RECIPETRIES=' + str(self.raptor.tries)
   400 				command += ' TALON_RETRIES=' + str(self.raptor.tries - 1)
   439 				command += ' TALON_RETRIES=' + str(self.raptor.tries - 1)
   401 
   440 
   402 			# targets go at the end, if the makefile supports them
   441 			# targets go at the end, if the makefile supports them
   403 			addTargets = self.raptor.targets[:]
   442 			addTargets = self.raptor.targets[:]
   404 			ignoreTargets = self.makefileset.ignoreTargets(makefile)
   443 			ignoreTargets = makefileset.ignoreTargets(makefile)
   405 			if addTargets and ignoreTargets:
   444 			if addTargets and ignoreTargets:
   406 				for target in self.raptor.targets:
   445 				for target in self.raptor.targets:
   407 					if re.match(ignoreTargets, target):
   446 					if re.match(ignoreTargets, target):
   408 						addTargets.remove(target)
   447 						addTargets.remove(target)
   409 
   448 
   410 			if addTargets:
   449 			if addTargets:
   411 				command += " " + " ".join(addTargets)
   450 				command += " " + " ".join(addTargets)
       
   451 
       
   452 			# Substitute the makefile name for any occurrence of #MAKEFILE#
       
   453 			command = command.replace("#MAKEFILE#", str(makefile))
   412 
   454 
   413 			self.raptor.Info("Executing '%s'", command)
   455 			self.raptor.Info("Executing '%s'", command)
   414 
   456 
   415 			# execute the build.
   457 			# execute the build.
   416 			# the actual call differs between Windows and Unix.
   458 			# the actual call differs between Windows and Unix.
   417 			# bufsize=1 means "line buffered"
   459 			# bufsize=1 means "line buffered"
   418 			#
   460 			#
   419 			try:
   461 			try:
       
   462 				# Time the build
       
   463 				self.raptor.InfoStartTime(object_type = "makefile",
       
   464 						task = "build", key = str(makefile))
       
   465 				
   420 				makeenv=os.environ.copy()
   466 				makeenv=os.environ.copy()
   421 				if self.usetalon:
   467 				if self.usetalon:
   422 					makeenv['TALON_RECIPEATTRIBUTES']="none"
   468 					makeenv['TALON_RECIPEATTRIBUTES']="none"
   423 					makeenv['TALON_SHELL']=self.talonshell
   469 					makeenv['TALON_SHELL']=self.talonshell
   424 					makeenv['TALON_BUILDID']=str(self.buildID)
   470 					makeenv['TALON_BUILDID']=str(self.buildID)
   442 					self.raptor.out.write(line)
   488 					self.raptor.out.write(line)
   443 
   489 
   444 				# should be done now
   490 				# should be done now
   445 				returncode = p.wait()
   491 				returncode = p.wait()
   446 
   492 
       
   493 				# Report end-time of the build
       
   494 				self.raptor.InfoEndTime(object_type = "makefile",
       
   495 						task = "build", key = str(makefile))
   447 
   496 
   448 				if returncode != 0  and not self.raptor.keepGoing:
   497 				if returncode != 0  and not self.raptor.keepGoing:
   449 					self.Tidy()
   498 					self.Tidy()
   450 					return False
   499 					return False
   451 
   500 
   452 			except Exception,e:
   501 			except Exception,e:
   453 				self.raptor.Error("Exception '%s' during '%s'", str(e), command)
   502 				self.raptor.Error("Exception '%s' during '%s'", str(e), command)
   454 				self.Tidy()
   503 				self.Tidy()
       
   504 				# Still report end-time of the build
       
   505 				self.raptor.InfoEnd(object_type = "Building", task = "Makefile",
       
   506 						key = str(makefile))
   455 				return False
   507 				return False
   456 
   508 
   457 		# run any shutdown script
   509 		# run any shutdown script
   458 		if self.shutdownCommand != None and self.shutdownCommand != "":
   510 		if self.shutdownCommand != None and self.shutdownCommand != "":
   459 			self.raptor.Info("Running %s", self.shutdownCommand)
   511 			self.raptor.Info("Running %s", self.shutdownCommand)
   494 			os.environ["TALON_BUILDID"] = self.buildID
   546 			os.environ["TALON_BUILDID"] = self.buildID
   495 			self.raptor.Info("Running %s", command)
   547 			self.raptor.Info("Running %s", command)
   496 			looking = (os.system(command) != 0)
   548 			looking = (os.system(command) != 0)
   497 			tries += 1
   549 			tries += 1
   498 		if looking:
   550 		if looking:
   499 			self.raptor.Error("Failed to initilaise the talon shell for this build")
   551 			self.raptor.Error("Failed to initialise the talon shell for this build")
   500 			self.talonctl = ""
   552 			self.talonctl = ""
   501 			return False
   553 			return False
   502 		
   554 		
   503 		return True
   555 		return True
   504 	
   556