|
1 |
|
2 # Copyright (c) 2008-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 "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 # mmbuild2 - python script intended to replace mmbuild.pl |
|
16 # |
|
17 |
|
18 from optparse import (make_option,OptionParser) |
|
19 import sys |
|
20 import os |
|
21 import subprocess |
|
22 import MbcUtils |
|
23 |
|
24 # some literals. TODO - use explicit type? |
|
25 _KAll = "all" |
|
26 _KMmf = "mmf" |
|
27 _KMisc = "misc" |
|
28 _KIcl = "icl" |
|
29 |
|
30 _KMainTempConfig = ".config.xml" |
|
31 _KTestTempConfig = ".testconfig.xml" |
|
32 _KTestBuildTempConfig = ".testbuildconfig.xml" |
|
33 |
|
34 class Unimplemented(Exception): |
|
35 """Raised for invalid commands""" |
|
36 |
|
37 def __init__(self, msg): |
|
38 self.__msg = msg |
|
39 |
|
40 def __str__(self): |
|
41 return self.__msg |
|
42 |
|
43 class Script(object): |
|
44 |
|
45 |
|
46 # TODO this option_list should be replaced by add_option calls to parameter |
|
47 # option_list parameter to OptionParser is down as deprecated |
|
48 option_table = [ |
|
49 make_option ("-t", "--test", |
|
50 action="store_true", dest="buildTest", default=False, |
|
51 help="""build test code rather than main code (without -b, that built by "abld build" or equiv)"""), |
|
52 make_option ("-b", "--testBuild", |
|
53 action="store_true", dest="buildTestBuild", default=False, |
|
54 help="""when given with -t, build that code that requires "abld test build" """), |
|
55 make_option ("-x", "--additional", "--opt", "--extra", |
|
56 action="store_true", dest="extra", default=False, |
|
57 help="build additional modules (from Xopt.mbc files)"), |
|
58 make_option ("-i", "--icl", |
|
59 action="store_const", const=_KIcl, dest="toBuild", default=_KAll, |
|
60 help="build icl modules only"), |
|
61 make_option ("-m", "--mmf", |
|
62 action="store_const", const=_KMmf, dest="toBuild", default=_KAll, |
|
63 help="build mmf modules only"), |
|
64 make_option ("-c", "--misc", |
|
65 action="store_const", const=_KMisc, dest="toBuild", default=_KAll, |
|
66 help="build misc modules only"), |
|
67 make_option ("-f", "--full", "--all", |
|
68 action="store_const", const=_KAll, dest="toBuild", default=_KAll, |
|
69 help="build all modules (which depends on if -x is given too)"), |
|
70 make_option ("-k", "--keepgoing", |
|
71 action="store_true", dest="keepgoing", default=False, |
|
72 help="keep going if errors are found"), |
|
73 make_option ("-g", "--gccxml", |
|
74 action="store_true", dest="gccxml", default=False, |
|
75 help="build for gccxml"), |
|
76 make_option ("-s", "--skipmake", |
|
77 action="store_true", dest="skipmake", default=False, |
|
78 help="skip building makefile (ignored)"), |
|
79 make_option ("--iclTestdata", |
|
80 action="store_true", dest="icl_tests", default=False, |
|
81 help="build ICL Tests"), |
|
82 ] |
|
83 |
|
84 description = \ |
|
85 """Script for selection appropriate set of multimedia |
|
86 components and build them together, so build order does not matter. |
|
87 One, and only one of "setup", "build" or "clean" must be given. |
|
88 """ |
|
89 |
|
90 def __init__(self): |
|
91 # need to implement commands as property and not class constant or |
|
92 # we get a forward declaration problem |
|
93 self.iCommands = {"setup": self.doSetup, "build": self.doBuild, "clean": self.doClean} |
|
94 self.iOptions = None |
|
95 self.iProdCodeList = [] |
|
96 self.iTestCodeList = [] |
|
97 self.iTestBuildCodeList = [] |
|
98 self.iOptionParser = None |
|
99 self.iDebug = False |
|
100 |
|
101 def main(self): |
|
102 "main function of script" |
|
103 self.iOptionParser = OptionParser( |
|
104 option_list = Script.option_table, |
|
105 usage="%prog [-t [-b]] [-i|-m|-c|-f] (setup|build [winscw]|clean)", |
|
106 description = Script.description |
|
107 ) |
|
108 (self.iOptions, args) = self.iOptionParser.parse_args() |
|
109 |
|
110 self.DebugPrint (str(self.iOptions)) |
|
111 self.DebugPrint (str(args)) |
|
112 |
|
113 if (len(args)==0 or not args[0] in self.iCommands or |
|
114 not self.CheckOptions()): |
|
115 self.iOptionParser.print_usage() |
|
116 return -1 |
|
117 |
|
118 remainingArgs = args[1:len(args)] |
|
119 |
|
120 return self.iCommands[args[0]](remainingArgs) # effective switch to doBuild, doSetup or doClean |
|
121 |
|
122 def CheckOptions(self): |
|
123 "Check for any invalid option combinations. Warn about ignored ones etc" |
|
124 if self.iOptions.skipmake: |
|
125 print ("Warning ignoring -s - option is no longer valid in raptor version") |
|
126 if not self.iOptions.buildTest and self.iOptions.buildTestBuild: |
|
127 return False # can't do -b without -t |
|
128 return True # all other combinations OK |
|
129 |
|
130 def doBuild(self, remainingArgs): |
|
131 # if we have a remainingArg, only "winscw" is allowed |
|
132 if not (len(remainingArgs)==0 or len(remainingArgs)==1 and remainingArgs[0]=="winscw"): |
|
133 self.iOptionParser.print_usage() |
|
134 return -1 |
|
135 |
|
136 # for normal build need to run "sbs -s .config.xml build" |
|
137 # for test build need to run "sbs -s .testconfig.xml build" |
|
138 # use --logfile=- to send output to stdout instead of log file |
|
139 configFile = _KMainTempConfig |
|
140 testBuild = False |
|
141 if self.iOptions.buildTest: |
|
142 if not self.iOptions.buildTestBuild: |
|
143 # build test config instead when -t etc given |
|
144 configFile = _KTestTempConfig |
|
145 else: |
|
146 # build test config instead when -t -b etc given |
|
147 configFile = _KTestBuildTempConfig |
|
148 testBuild = True |
|
149 sbs_command = self.sbsCommand() |
|
150 commands = [sbs_command, "-s", configFile] |
|
151 commands += ["--logfile=-"] # send output to stdout |
|
152 if self.iOptions.keepgoing: |
|
153 commands += ["--keepgoing"] |
|
154 if len(remainingArgs)>0 and remainingArgs[0]=="winscw": |
|
155 if testBuild: |
|
156 commands += ["--config=winscw.test"] |
|
157 else: |
|
158 commands += ["--config=winscw"] |
|
159 else: |
|
160 if testBuild: |
|
161 commands += ["--config=default.test"] |
|
162 commands += ["--filters=FilterSquashLog"] # reduce log size |
|
163 commands += ["--tries=2"] # retry on failure - e.g. for license fails |
|
164 commands += ["build"] |
|
165 self.DebugPrint("""command="%s" """ % str(commands)) |
|
166 print "------------------ sbs start : %s" % str(commands) |
|
167 sys.stdout.flush() # flush any output here so appears correct in log |
|
168 subprocess.check_call(commands) # raises exception on error |
|
169 print "------------------ sbs end" |
|
170 return 0 |
|
171 |
|
172 def sbsCommand(self): |
|
173 "sbs command - that can be used by subprocess" |
|
174 # For some reason, have to work out batch file to run by longhand |
|
175 # rather than just saying "sbs" and letting command work it out. |
|
176 # Could use sys.command() instead, but that is deprecated |
|
177 sbs_home = os.getenv("SBS_HOME") |
|
178 assert sbs_home, "SBS_HOME must be defined to use this script" |
|
179 sbs_command = os.path.join(sbs_home, "bin", "sbs.bat") |
|
180 return sbs_command |
|
181 |
|
182 def doSetup(self, remainingArgs): |
|
183 if len(remainingArgs)!=0: |
|
184 self.iOptionParser.print_usage() |
|
185 return -1 |
|
186 |
|
187 self.buildMbcLists() |
|
188 |
|
189 self.DebugPrint ("prodCodeList=%s" % str(self.iProdCodeList)) |
|
190 self.DebugPrint ("testCodeList=%s" % str(self.iTestCodeList)) |
|
191 self.DebugPrint ("testBuildCodeList=%s" % str(self.iTestBuildCodeList)) |
|
192 |
|
193 mbcParser = MbcUtils.MbcParser(self.iProdCodeList) |
|
194 folders = mbcParser() |
|
195 self.DebugPrint ("folders=%s" % str (folders)) |
|
196 getFolderList = MbcUtils.GetFolderList(folders) |
|
197 groupFolders = getFolderList() |
|
198 self.DebugPrint ("prodCodeFolderList=%s" % str(groupFolders)) |
|
199 |
|
200 generator = MbcUtils.ConfigFileGenerator(groupFolders, _KMainTempConfig) |
|
201 generator.write() |
|
202 |
|
203 mbcParser = MbcUtils.MbcParser(self.iTestCodeList) |
|
204 folders = mbcParser() |
|
205 self.DebugPrint ("testfolders=%s" % str (folders)) |
|
206 getFolderList = MbcUtils.GetFolderList(folders) |
|
207 groupFolders = getFolderList() |
|
208 self.DebugPrint ("testCodeFolderList=%s" % str(groupFolders)) |
|
209 |
|
210 generator = MbcUtils.ConfigFileGenerator(groupFolders, _KTestTempConfig) |
|
211 generator.write() |
|
212 |
|
213 mbcParser = MbcUtils.MbcParser(self.iTestBuildCodeList) |
|
214 folders = mbcParser() |
|
215 self.DebugPrint ("testBuildfolders=%s" % str (folders)) |
|
216 getFolderList = MbcUtils.GetFolderList(folders) |
|
217 groupFolders = getFolderList() |
|
218 self.DebugPrint ("testBuildCodeFolderList=%s" % str(groupFolders)) |
|
219 |
|
220 generator = MbcUtils.ConfigFileGenerator(groupFolders, _KTestBuildTempConfig) |
|
221 generator.write() |
|
222 return 0 |
|
223 |
|
224 def buildMbcLists(self): |
|
225 # some boolean values |
|
226 want_mmf = self.iOptions.toBuild in [_KAll, _KMmf]; |
|
227 want_icl = self.iOptions.toBuild in [_KAll, _KIcl]; |
|
228 want_misc = self.iOptions.toBuild in [_KAll, _KMisc]; |
|
229 want_extra = self.iOptions.extra |
|
230 want_icl_tests = self.iOptions.icl_tests |
|
231 |
|
232 # now build up the lists depending on which "component" we want |
|
233 # perhaps this should be reworked as a table, but not obvious as to how |
|
234 self.iTestCodeList += ["AllTests.mbc", "TestFrameworkTest.mbc", |
|
235 "targettools.mbc"] |
|
236 if want_mmf: |
|
237 self.iProdCodeList += ["mmf.mbc"] |
|
238 self.iTestCodeList += ["mmfTest.mbc"] |
|
239 self.iTestBuildCodeList += ["mmfTestBuild.mbc"] |
|
240 # assume mmfPhys and mmfOptPhys can currently be ignored |
|
241 # they should generate another list and be built as special cases |
|
242 # self.iProdCodeList += ["mmfPhys.mbc"] |
|
243 if want_extra: |
|
244 self.iProdCodeList += ["mmfOpt.mbc"] |
|
245 self.iTestCodeList += ["mmfOptTest.mbc"] |
|
246 self.iTestBuildCodeList += ["mmfOptTestBuild.mbc"] |
|
247 # self.iProdCodeList += ["mmfOptPhys.mbc"] |
|
248 else: |
|
249 self.iTestCodeList += ["mmfNotOptTest.mbc"] |
|
250 if want_icl: |
|
251 self.iProdCodeList += ["icl.mbc"] |
|
252 if want_icl_tests: |
|
253 self.iTestCodeList += ["iclTest.mbc"] |
|
254 self.iTestBuildCodeList += ["iclTestBuild.mbc"] |
|
255 if want_extra: |
|
256 self.iTestCodeList += ["iclOptTest.mbc"] |
|
257 self.iTestBuildCodeList += ["iclOptTestBuild.mbc"] |
|
258 if want_extra: |
|
259 self.iProdCodeList += ["iclOpt.mbc"] |
|
260 if want_misc: |
|
261 self.iProdCodeList += ["misc.mbc"] |
|
262 self.iTestCodeList += ["miscTest.mbc"] |
|
263 self.iTestBuildCodeList += ["miscTestBuild.mbc"] |
|
264 if want_extra: |
|
265 self.iProdCodeList += ["miscOpt.mbc"] |
|
266 self.iTestCodeList += ["miscOptTest.mbc"] |
|
267 self.iTestBuildCodeList += ["miscOptTestBuild.mbc"] |
|
268 |
|
269 def doClean(self, remainingArgs): |
|
270 "clean is called. Note -t clean means clean test code too, not instead" |
|
271 # for normal clean need to run "sbs -s .config.xml clean" |
|
272 # for test clean need to run "sbs -s .testconfig.xml clean" |
|
273 # use --logfile=- to send output to stdout instead of log file |
|
274 whatToClean = [_KMainTempConfig] |
|
275 if self.iOptions.buildTest: |
|
276 whatToClean += [_KTestTempConfig] |
|
277 for configFile in whatToClean: |
|
278 sbs_command = self.sbsCommand() |
|
279 commands = [sbs_command, "-s", configFile] |
|
280 commands += ["--logfile=-"] # send output to stdout |
|
281 commands += ["reallyclean"] |
|
282 self.DebugPrint ("""command="%s" """ % str(commands)) |
|
283 subprocess.check_call(commands) # raises exception on error |
|
284 return 0 |
|
285 |
|
286 def DebugPrint(self, str): |
|
287 "print a string if self.iDebug is set - would be turned on manually" |
|
288 if self.iDebug: |
|
289 print(str) |
|
290 |
|
291 if __name__ == "__main__": |
|
292 script = Script() |
|
293 sys.exit(script.main()) |