sbsv2/raptor/python/raptor_makefile.py
changeset 0 044383f39525
child 3 e1eecf4d390d
child 590 360bd6b35136
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     1 #
       
     2 # Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # This component and the accompanying materials are made available
       
     5 # under the terms of the License "Eclipse Public License v1.0"
       
     6 # which accompanies this distribution, and is available
       
     7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 #
       
     9 # Initial Contributors:
       
    10 # Nokia Corporation - initial contribution.
       
    11 #
       
    12 # Contributors:
       
    13 #
       
    14 # Description: 
       
    15 # makefile module
       
    16 # This module is for writing calls to Function-Like Makefiles
       
    17 #
       
    18 
       
    19 import re
       
    20 import os
       
    21 import generic_path
       
    22 
       
    23 class MakefileSelector(object):
       
    24 	"""A "query" which is used to separate some flm interface calls
       
    25 	  into separate makefile trees."""
       
    26 	def __init__(self, name="default", interfacepattern=None, defaulttarget=None, ignoretargets=None):
       
    27 		self.name=name
       
    28 		if interfacepattern is not None:
       
    29 			self.interfacepattern=re.compile(interfacepattern, re.I)
       
    30 		else:
       
    31 			self.interfacepattern=None
       
    32 		self.defaulttarget=defaulttarget
       
    33 		self.ignoretargets=ignoretargets
       
    34 
       
    35 class Makefile(object):
       
    36 	"""Representation of the file that is created from the build specification 
       
    37 	   tree.
       
    38 	"""
       
    39 	def __init__(self, directory, selector, parent=None, filenamebase="Makefile", prologue=None, epilogue=None, defaulttargets=None):
       
    40 		self.filenamebase = filenamebase
       
    41 		self.directory = directory
       
    42 		if selector.name != "":
       
    43 			extension = "." + selector.name
       
    44 		else:
       
    45 			extension = ""
       
    46 		self.filename = generic_path.Join(directory,filenamebase + extension)
       
    47 		self.selector = selector
       
    48 		self.parent = parent
       
    49 		self.childlist = []
       
    50 		self.file = None
       
    51 		self.prologue = prologue
       
    52 		self.epilogue = epilogue
       
    53 		self.defaulttargets = defaulttargets
       
    54 		self.dead = False
       
    55 
       
    56 	def open(self):
       
    57 		if self.dead:
       
    58 			raise Exception, "Attempt to reopen completed makefile %s " % (self.filename)
       
    59 
       
    60 		if self.file is None:
       
    61 			directory = self.filename.Dir()
       
    62 			if not (str(directory) == "" or directory.Exists()):
       
    63 				try:
       
    64 					os.makedirs(directory.GetLocalString())
       
    65 				except Exception,e:
       
    66 					raise Exception, "Cannot make directory '%s' for file '%s' in '%s': %s " % (str(directory),str(self.filename),str(self.directory),str(e))
       
    67 
       
    68 			self.file = open(str(self.filename),"w+")
       
    69 			
       
    70 			self.file.write('# GENERATED MAKEFILE : DO NOT EDIT\n\n')
       
    71 			if self.selector.defaulttarget:
       
    72 				self.file.write('MAKEFILE_GROUP:=%s\n.PHONY:: %s\n%s:: # Default target\n' \
       
    73 							% (self.selector.defaulttarget, self.selector.defaulttarget, self.selector.defaulttarget))
       
    74 			else:
       
    75 				self.file.write('MAKEFILE_GROUP:=DEFAULT\n')
       
    76 			if self.prologue != None:
       
    77 				self.file.write(self.prologue)
       
    78 				
       
    79 			if self.defaulttargets != None:
       
    80 				self.file.write('# dynamic default targets\n')
       
    81 				for defaulttarget in self.defaulttargets:
       
    82 					self.file.write('.PHONY:: %s\n' % defaulttarget)
       
    83 					self.file.write('%s:\n' % defaulttarget)
       
    84 				self.file.write('\n')
       
    85 			
       
    86 	def addChild(self, child):
       
    87 		self.open()
       
    88 		self.file.write("include %s\n" % child.filename)
       
    89 		child.open()
       
    90 
       
    91 	def createChild(self, subdir):
       
    92 		child = Makefile(str(self.filename.Dir().Append(subdir)), self.selector, self, self.filenamebase, self.prologue, self.epilogue, self.defaulttargets)
       
    93 		self.addChild(child)
       
    94 		child.open()
       
    95 		return child
       
    96 
       
    97 	def addCall(self, specname, configname, ifname, useAllInterfaces, flmpath, parameters, guard = None):
       
    98 		"""Add an FLM call to the makefile.
       
    99 			specname is the name of the build specification (e.g. the mmp name)
       
   100 			configname is the name of the configuration which this call is made for
       
   101 			flmpath is the absolute path to the flm
       
   102 			parameters is an array of tuples, (paramname, paramvalue)	
       
   103 			guard is a hash value that should be unique to the FLM call
       
   104 
       
   105 		   This call will return False if the ifname does not match the selector for 
       
   106 		   the makefile. e.g. it prevents one from adding a resource FLM call to a
       
   107 		   makefile which is selecting export FLM calls. Selection is overridden if
       
   108 		   useAllInterfaces is True.
       
   109 		"""
       
   110 		# create the directory if it does not exist
       
   111 
       
   112 		if self.selector.interfacepattern is not None:
       
   113 			ifmatch = self.selector.interfacepattern.search(ifname)
       
   114 			if ifmatch == None and useAllInterfaces == False:
       
   115 				return False
       
   116 
       
   117 		self.open()
       
   118 		# now we can write the values into the makefile
       
   119 		self.file.write("# call %s\n" % flmpath)
       
   120 		self.file.write("SBS_SPECIFICATION:=%s\n" % specname)
       
   121 		self.file.write("SBS_CONFIGURATION:=%s\n\n" % configname)
       
   122 
       
   123 		if guard:
       
   124 			self.file.write("ifeq ($(%s),)\n%s:=1\n\n" % (guard, guard))
       
   125 		
       
   126 		for (p, value) in parameters:
       
   127 			self.file.write("%s:=%s\n" % (p, value))
       
   128 	
       
   129 		self.file.write("include %s\n" % flmpath)
       
   130 		self.file.write("MAKEFILE_LIST:= # work around potential gnu make stack overflow\n\n")
       
   131 		
       
   132 		if guard:
       
   133 			self.file.write("endif\n\n")
       
   134 
       
   135 		return True
       
   136 
       
   137 	def close(self):
       
   138 		if self.file is not None:
       
   139 			if self.epilogue != None:
       
   140 				self.file.write(self.epilogue)
       
   141 			self.file.write('# END OF GENERATED MAKEFILE : DO NOT EDIT\n')
       
   142 			self.file.close()
       
   143 			self.file = None
       
   144 			self.dead = True
       
   145 
       
   146 	def __del__(self):
       
   147 		self.close()
       
   148 			
       
   149 		
       
   150 
       
   151 class MakefileSet(object):
       
   152 	grouperselector = MakefileSelector(name="")
       
   153 	defaultselectors = [ 
       
   154 		MakefileSelector("export", '\.export$', "EXPORT"),
       
   155 		MakefileSelector("bitmap", '\.bitmap$', "BITMAP"),
       
   156 		MakefileSelector("resource", '\.resource$', "RESOURCE"),
       
   157 		MakefileSelector("default", '\.(?!export$|bitmap$|resource$).*$', "ALL")
       
   158 		]
       
   159 
       
   160 	def __init__(self, directory, selectors=defaultselectors, makefiles=None, parent=None, filenamebase="Makefile", prologue=None, epilogue=None, defaulttargets=None):
       
   161 		self.directory = generic_path.Path(directory)
       
   162 		self.filenamebase = filenamebase
       
   163 		self.parent = parent
       
   164 		if makefiles is not None:
       
   165 			self.makefiles = makefiles
       
   166 		else:
       
   167 			self.makefiles = []
       
   168 			for sel in selectors:
       
   169 				self.makefiles.append(Makefile(directory, sel, None, filenamebase, prologue, epilogue, defaulttargets))
       
   170 		self.groupermakefile = Makefile(directory, MakefileSet.grouperselector, None, filenamebase, "# GROUPER MAKEFILE\n\nALL::\n\n", "\n")
       
   171 		
       
   172 		for mf in self.makefiles:
       
   173 			self.groupermakefile.addChild(mf)
       
   174 
       
   175 
       
   176 	def createChild(self, subdir):
       
   177 		"""Create a set of "sub" makefiles that are included by this set."""
       
   178 		newmakefiles = []
       
   179 		for mf in self.makefiles:
       
   180 			newmf = mf.createChild(subdir)
       
   181 			newmakefiles.append(newmf)
       
   182 
       
   183 		newset = MakefileSet(str(self.directory.Append(subdir)), None, newmakefiles, self, self.filenamebase)
       
   184 		self.groupermakefile.addChild(newset.groupermakefile)
       
   185 
       
   186 		return newset
       
   187 
       
   188 	def addCall(self, specname, configname, ifname, useAllInterfaces, flmpath, parameters, guard = None):
       
   189 		"""Find out which makefiles to write this FLM call to 
       
   190 		   and write it to those (e.g. the exports makefile) """
       
   191 		for f in self.makefiles:
       
   192 			f.addCall(specname, configname, ifname, useAllInterfaces, flmpath, parameters, guard)
       
   193 
       
   194 	def makefileNames(self):
       
   195 		for mf in self.makefiles:
       
   196 			yield str(mf.filename)
       
   197 	
       
   198 	def ignoreTargets(self, makefile):
       
   199 		"""Get hold of a makefile's selector based on its name and
       
   200 		   determine whether it ignores targets based on a regexp."""
       
   201 		for mf in self.makefiles:
       
   202 			filename = str(mf.filename)			
       
   203 			if filename == makefile:
       
   204 				return mf.selector.ignoretargets 
       
   205 		return None
       
   206 
       
   207 	def close(self):
       
   208 		for mf in self.makefiles:
       
   209 			mf.close()
       
   210 		self.groupermakefile.close()
       
   211 
       
   212 	def __del__(self):
       
   213 		self.close()