|
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() |