diff -r 7685cec9fd3c -r f2ddfa555b0f doc/api/python/buildtools-pysrc.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/api/python/buildtools-pysrc.html Fri Sep 11 11:54:49 2009 +0100 @@ -0,0 +1,2779 @@ + + + + + buildtools + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + Module buildtools + + + + + + +
[hide private]
[frames] | no frames]
+
+

Source Code for Module buildtools

+
+  1  #============================================================================  
+  2  #Name        : buildtools.py  
+  3  #Part of     : Helium  
+  4   
+  5  #Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+  6  #All rights reserved. 
+  7  #This component and the accompanying materials are made available 
+  8  #under the terms of the License "Eclipse Public License v1.0" 
+  9  #which accompanies this distribution, and is available 
+ 10  #at the URL "http://www.eclipse.org/legal/epl-v10.html". 
+ 11  # 
+ 12  #Initial Contributors: 
+ 13  #Nokia Corporation - initial contribution. 
+ 14  # 
+ 15  #Contributors: 
+ 16  # 
+ 17  #Description: 
+ 18  #=============================================================================== 
+ 19   
+ 20  """Enables creation of build command list in several formats. 
+ 21   
+ 22  This module implements class that represent shell commands. 
+ 23  It supports build stage and command parallelization (depends of the output format). 
+ 24  CommandList can be generated in different format: ant, make, ebs, batch. 
+ 25   
+ 26  Example: 
+ 27  from mc.buildtools import CommandList, Convert 
+ 28  list = CommandList() 
+ 29  list.addCommand("\\epoc32\\rombuild", "make_fpsx.bat..yy...", "build_xx_rom") 
+ 30  list.addCommand("\\epoc32\\rombuild", "make_fpsx.bat..xx...", "build_yy_rom") 
+ 31  list.addCommand("\\epoc32\\rombuild", "copy \\foo \\bar", "simple copy", False) 
+ 32   
+ 33  convert(list, "outputfile.mk", "make") 
+ 34  convert(list, "outputfile.ant.xml", "ant") 
+ 35  convert(list, "outputfile.ebs.xml", "ebs") 
+ 36  convert(list, "outputfile.bat", "bat") 
+ 37   
+ 38  """ 
+ 39  import os 
+ 40  import types 
+ 41  import xml.dom.minidom 
+ 42  import sys 
+ 43   
+
44 -class PreBuilder(object): +
45 """ This class implements an abstract prebuilder. + 46 A prebuilder takes a configurationset as input and generates a build file. + 47 """ +
48 - def __init__(self, configSet): +
49 self.configSet = configSet + 50 # Select the first configuration as a default, for referencing common properties + 51 self.config = configSet.getConfigurations()[0] +
52 +
53 - def writeBuildFile(self, taskList, buildFilePath, output='ant'): +
54 """ Converting a task list into output format and writing it into buildFilePath file. """ + 55 writer = None + 56 #if 'build.tool' in self.config: + 57 # Choose appropriate build tool + 58 # print 'choosing build tool!' + 59 # pass + 60 #else: + 61 # Choose Ant by default for now + 62 print self.config.keys() + 63 buildFileDir = os.path.dirname(buildFilePath) + 64 if not os.path.exists(buildFileDir): + 65 os.makedirs(buildFileDir) + 66 writer = get_writer(output, open(buildFilePath, 'w')) + 67 writer.write(taskList) +
68 +
69 -class Task(object): +
70 """ Abstract Task object. """ + 71 pass +
72 +
73 -class Command(Task): +
74 """ + 75 This class implements a command definition. + 76 It handles command id and stage. + 77 All command from one stage should be finished before starting the next stage. + 78 """ +
79 - def __init__(self, executable, path, args=None, name=''): +
80 Task.__init__(self) + 81 if args == None: + 82 args = [] + 83 self._id = 1 + 84 self._stage = 1 + 85 self._name = name + 86 self._executable = executable + 87 self._path = path + 88 self._args = args +
89 +
90 - def setJobId(self, idn): +
91 """ Set the command id. """ + 92 self._id = idn +
93 +
94 - def setStage(self, stage): +
95 """ Set the command stage. """ + 96 self._stage = stage +
97 +
98 - def jobId(self): +
99 """ Get the command id. """ +100 return self._id +
101 +
102 - def stage(self): +
103 """ Get the command stage. """ +104 return self._stage +
105 +
106 - def name(self): +
107 """ Get the command name. """ +108 return self._name +
109 +
110 - def executable(self): +
111 """ Get the command executable. """ +112 return self._executable +
113 +
114 - def path(self): +
115 """ Get the command path. """ +116 return self._path +
117 +
118 - def cmd(self): +
119 """ Get the command line. """ +120 return ' '.join(self._args) +
121 +
122 - def addArg(self, arg): +
123 """ Add a command line argument. """ +124 self._args.append(arg) +
125 +
126 - def __repr__(self): +
127 argsString = ' '.join(self._args) +128 return "%s: %s: %s" % (self.name(), self.path(), argsString) +
129 +
130 -class AntTask(Task): +
131 """ Interface that defines supports for an Ant task rendering. """ +132 +
133 - def toAntTask(self, doc): +
134 """ Override this method to convert a specific command into Ant command. +135 e.g: Delete Class will use delete task from Ant, else convert into perl ... remove filename.__getCommandByStage +136 """ +137 pass +
138 +
139 -class Delete(AntTask, Command): +
140 """ Implements file/directory deleletion mechanism. """ +141 +
142 - def __init__(self, filename=None, dirname=None): +
143 Command.__init__(self, "perl", "") +144 AntTask.__init__(self) +145 self._filename = filename +146 self._dir = dirname +147 self._args.append("-MExtUtils::Command") +148 self._args.append("-e") +149 if self._filename != None: +150 self._args.append("rm_f") +151 self._args.append('"' + self._filename + '"') +152 elif self._dir != None: +153 self._args.append("rm_rf") +154 self._args.append('"' + self._dir + '"') +
155 +
156 - def toAntTask(self, doc): +
157 """ Render the delete as an Ant task. """ +158 node = doc.createElementNS("", "delete") +159 node.setAttributeNS("", "verbose", "true") +160 node.setAttributeNS("", "failonerror", "false") +161 if self._filename != None: +162 node.setAttributeNS("", "file", self._filename) +163 elif self._dir != None: +164 node.setAttributeNS("", "dir", self._dir) +165 return node +
166 +167 +
168 -class Copy(AntTask, Command): +
169 """ Implement copy command. """ +
170 - def __init__(self, srcFile, todir): +
171 Command.__init__(self, "perl", os.path.dirname(srcFile)) +172 AntTask.__init__(self) +173 self.srcFile = srcFile +174 self.todir = todir +175 self._args.append("-MExtUtils::Command") +176 self._args.append("-e") +177 self._args.append("cp") +178 self._args.append('"' + self.srcFile + '"') +179 self._args.append('"' + os.path.join(self.todir, os.path.basename(self.srcFile)) + '"') +
180 +
181 - def toAntTask(self, doc): +
182 """ Render the copy as an Ant task. """ +183 node = doc.createElementNS("", "copy") +184 node.setAttributeNS("", "verbose", "true") +185 node.setAttributeNS("", "failonerror", "false") +186 node.setAttributeNS("", "file", self.srcFile) +187 node.setAttributeNS("", "todir", self.todir) +188 return node +
189 +190 +
191 -class CommandList(object): +
192 """ +193 This class allows to safely handle Command object into lists +194 """ +
195 - def __init__(self): +
196 self.__cmds = [] +
197 +
198 - def allCommands(self): +
199 """ Returns all command list. """ +200 return self.__cmds +
201 +
202 - def addCommand(self, cmd, newstage=False): +
203 """ Add a Command to the list. """ +204 stage = 1 +205 idn = 1 +206 if len(self.__cmds) > 0: +207 lastcmd = self.__cmds[-1] +208 idn = lastcmd.jobId() + 1 +209 stage = lastcmd.stage() +210 if newstage: +211 stage = stage + 1 +212 cmd.setStage(stage) +213 cmd.setJobId(idn) +214 self.__cmds.append(cmd) +
215 +216 +
217 -class AbstractOutputWriter: +
218 """Base class which contains define an AbstractOutputWriter. +219 +220 The subclass must implement a convert method which compute a command list into +221 some output file. +222 """ +
223 - def __init__(self, fileOut): +
224 if isinstance(fileOut, types.StringType): +225 self._fileOut = open(fileOut, 'w') +226 else: +227 self._fileOut = fileOut +
228 +
229 - def write(self, cmdList): +
230 """ Method to override to implement format specific output. """ +
231 - def writeTopLevel(self, config_list, spec_name, output_path, xml_file): +
232 """ Method to override to implement top level commands. """ +
233 +
234 - def __call__(self, cmdList): +
235 self.write(cmdList) +
236 +
237 - def close(self): +
238 """ Close the output stream. """ +239 self._fileOut.close() +
240 +241 +
242 -class StringWriter(AbstractOutputWriter): +
243 """ Implements a Writer which is able to directly write to the output stream. """ +244 +
245 - def __init__(self, fileOut): +
246 AbstractOutputWriter.__init__(self, fileOut) +
247 +
248 - def write(self, content): +
249 """ Write content to the output. """ +250 self._fileOut.write(content) +
251 +252 +
253 -class EBSWriter(AbstractOutputWriter): +
254 """ Implements EBS XML output format. """ +255 +
256 - def __init__(self, fileOut): +
257 AbstractOutputWriter.__init__(self, fileOut) +
258 +
259 - def write(self, cmdList): +
260 """ Write the command list to EBS format. """ +261 doc = xml.dom.minidom.Document() +262 productnode = doc.createElementNS("", "Product") +263 cmdsnode = doc.createElementNS("", "Commands") +264 productnode.appendChild(cmdsnode) +265 doc.appendChild(productnode) +266 +267 for cmd in cmdList.allCommands(): +268 cmdsnode.appendChild(self.__commandToXml(doc, cmd)) +269 +270 self._fileOut.write(doc.toprettyxml()) +
271 +272 @staticmethod +
273 - def __commandToXml(doc, cmd): +
274 """ Convert a Command into an EBS command. """ +275 # <Execute ID="1" Stage="1" Component="MAS" Cwd="%EPOCROOT%" CommandLine="getrel MAS 92_013_Symbian_OS"/> +276 cmdsnode = doc.createElementNS("", "Execute") +277 cmdsnode.setAttributeNS("", "ID", "%d" % cmd.jobId()) +278 cmdsnode.setAttributeNS("", "Stage", "%d" % cmd.stage()) +279 cmdsnode.setAttributeNS("", "Component", cmd.name()) +280 cmdsnode.setAttributeNS("", "Cwd", cmd.path()) +281 cmdsnode.setAttributeNS("", "CommandLine", cmd.executable()+" "+cmd.cmd()) +282 return cmdsnode +
283 +284 +
285 -class AntWriter(AbstractOutputWriter): +
286 """ Implements Ant XML output format. """ +287 +
288 - def __init__(self, fileOut): +
289 AbstractOutputWriter.__init__(self, fileOut) +
290 +
291 - def writeTopLevel(self, config_list, spec_name, output_path, xml_file): +
292 doc = xml.dom.minidom.Document() +293 projectnode = doc.createElementNS("", "project") +294 projectnode.setAttributeNS("", "name", '') +295 projectnode.setAttributeNS("", "default", "all") +296 doc.appendChild(projectnode) +297 target = doc.createElementNS("", "target") +298 target.setAttributeNS("", "name", "all") +299 projectnode.appendChild(target) +300 +301 parallel = doc.createElementNS("", "parallel") +302 parallel.setAttributeNS("", "threadCount", "${number.of.threads}") +303 target.appendChild(parallel) +304 index = 0 +305 script_loc = os.path.normpath(os.path.join(os.environ['HELIUM_HOME'], 'tools/common/python/lib/CreateZipInput.py')) +306 for config in config_list: +307 sequential = doc.createElementNS("", "sequential") +308 outputfile = os.path.normpath(os.path.join(output_path, config + ".xml")) +309 exec_element = doc.createElementNS("", "exec") +310 exec_element.setAttributeNS("", "executable", "python") +311 +312 args = doc.createElementNS("", "arg") +313 args.setAttributeNS("", "value", "%s" % script_loc) +314 exec_element.appendChild(args) +315 +316 args = doc.createElementNS("", "arg") +317 args.setAttributeNS("", "line", "--output=%s" % outputfile) +318 exec_element.appendChild(args) +319 args = doc.createElementNS("", "arg") +320 args.setAttributeNS("", "line", "--config=%s" % spec_name) +321 exec_element.appendChild(args) +322 args = doc.createElementNS("", "arg") +323 args.setAttributeNS("", "line", "--filename=%s" % xml_file) +324 exec_element.appendChild(args) +325 args = doc.createElementNS("", "arg") +326 args.setAttributeNS("", "line", "--id=%d" % index) +327 exec_element.appendChild(args) +328 args = doc.createElementNS("", "arg") +329 args.setAttributeNS("", "line", "--writertype=ant") +330 exec_element.appendChild(args) +331 sequential.appendChild(exec_element) +332 index += 1 +333 ant_exec = doc.createElementNS("", "ant") +334 ant_exec.setAttributeNS("", "antfile", outputfile) +335 sequential.appendChild(ant_exec) +336 parallel.appendChild(sequential) +337 +338 self._fileOut.write(doc.toprettyxml()) +
339 - def write(self, cmdList): +
340 """ Writes the command list to Ant format. """ +341 doc = xml.dom.minidom.Document() +342 projectnode = doc.createElementNS("", "project") +343 projectnode.setAttributeNS("", "name", '') +344 projectnode.setAttributeNS("", "default", "all") +345 doc.appendChild(projectnode) +346 +347 stages = self.__getCommandByStage(cmdList) +348 +349 for stage in stages.keys(): +350 projectnode.appendChild(self.__stageToTarget(doc, stage, stages[stage])) +351 +352 target = doc.createElementNS("", "target") +353 target.setAttributeNS("", "name", "all") +354 def __toStage(stage): +355 """ Convert the stage id into and Ant target name. """ +356 return "stage%s" % stage +
357 target.setAttributeNS("", "depends", ','.join([__toStage(stage) for stage in stages.keys()])) +358 projectnode.appendChild(target) +359 +360 self._fileOut.write(doc.toprettyxml()) +
361 +
362 - def __stageToTarget(self, doc, stage, cmds): +
363 """ Convert a stage into an Ant target. """ +364 target = doc.createElementNS("", "target") +365 target.setAttributeNS("", "name", "stage%s" % stage) +366 parallel = doc.createElementNS("", "parallel") +367 parallel.setAttributeNS("", "threadCount", "${number.of.threads}") +368 target.appendChild(parallel) +369 +370 for cmd in cmds: +371 parallel.appendChild(self.__commandToAnt(doc, cmd)) +372 return target +
373 +374 @staticmethod +
375 - def __commandToAnt(doc, cmd): +
376 """ Convert a command into an Ant task. """ +377 # does the API support Ant task conversion. +378 # else treat it as a cmd +379 if issubclass(type(cmd), AntTask): +380 return cmd.toAntTask(doc) +381 else: +382 execnode = doc.createElementNS("", "exec") +383 execnode.setAttributeNS("", "executable", cmd.executable()) +384 execnode.setAttributeNS("", "dir", cmd.path()) +385 arg = doc.createElementNS("", "arg") +386 arg.setAttributeNS("", "line", cmd.cmd()) +387 execnode.appendChild(arg) +388 return execnode +
389 +390 @staticmethod +
391 - def __getCommandByStage(cmdList): +
392 """ Reorder a CommandList into a list of stages. """ +393 stages = {} +394 for cmd in cmdList.allCommands(): +395 if not stages.has_key(cmd.stage()): +396 stages[cmd.stage()]=[] +397 stages[cmd.stage()].append(cmd) +398 +399 return stages +
400 +401 +
402 -class MakeWriter(AbstractOutputWriter): +
403 """ Implements Makefile writer. """ +404 +
405 - def __init__(self, fileOut): +
406 AbstractOutputWriter.__init__(self, fileOut) +
407 +
408 - def writeTopLevel(self, config_list, spec_name, output_path, xml_file): +
409 content = "\n\nall: zip_inputs zip_files\n\n" +410 index = 0 +411 input_list = "zip_inputs: " +412 zip_list = "\n\nzip_files: " +413 full_content = "" +414 script_path = os.path.normpath(os.path.join(os.environ['HELIUM_HOME'], 'tools/compile/ec')) +415 for config in config_list: +416 outputfile = os.path.normpath(os.path.join(output_path, config + ".mk")) +417 input_list += " \\\n\t zip_input%d" % index +418 zip_list += " \\\n\t zip_files%d" % index +419 content += "\n\nzip_input%d :\n" % index +420 content += "\t@echo === identifying files for %s\n" % config +421 +422 content += "\tpython $(HELIUM_HOME)\\tools\\common\\python\\lib\\CreateZipInput.py --config=%s --filename=%s --id=%d --output=%s --writertype=%s\n\n" % (spec_name, xml_file, index, outputfile,'make') +423 content += "\n\nzip_files%d :zip_input%d\n" % (index, index) +424 content += "\t@echo === identifying files for %s\n" % config +425 content += "\t$(MAKE) -f %s" % (outputfile) +426 index += 1 +427 +428 full_content += input_list +429 full_content += zip_list +430 full_content += content +431 self._fileOut.write(full_content) +
432 - def write(self, cmdList): +
433 """ Converts the list of command into Makefile. """ +434 stages = {} +435 for cmd in cmdList.allCommands(): +436 if not stages.has_key(cmd.stage()): +437 stages[cmd.stage()] = [] +438 stages[cmd.stage()].append(cmd) +439 +440 # Write the all rule +441 def __toStage(stage): +442 """ Convert stage Id into a target name. """ +443 return "stage%s" % stage +
444 +445 #self._fileOut.write("all : %s\n" % ' '.join(map(__toStage, max(stages.keys()))) +446 if len(stages.keys()) > 0: +447 self._fileOut.write("all : stage%s ;\n" % max(stages.keys())) +448 else: +449 self._fileOut.write("all: ;\n") +450 +451 for stage in stages.keys(): +452 # Write each stage rule +453 def __toId(cmd): +454 """ Convert command Id into a target name. """ +455 self.__commandToTarget(cmd) +456 return "id%s" % cmd.jobId() +
457 self._fileOut.write("stage%s : %s\n" % (stage, ' '.join([__toId(task) for task in stages[stage]]))) +458 +459 +
460 - def __commandToTarget(self, cmd): +
461 """ Converting a Command into a Makefile target. """ +462 deps = "" +463 if cmd.stage() > 1: +464 deps = " stage%s" % (cmd.stage() - 1) +465 self._fileOut.write("id%s:%s\n" % (cmd.jobId(), deps)) +466 self._fileOut.write("\t@echo Target %s\n" % cmd.name()) +467 winargs = "" +468 if sys.platform == "win32": +469 winargs = "/d" +470 self._fileOut.write("\tcd %s %s && %s " % (winargs, cmd.path(), cmd.executable())) +471 self._fileOut.write("%s\n" % cmd.cmd()) +472 self._fileOut.write("\n") +
473 +474 +475 __writerConstructors = { 'ant': AntWriter, +476 'make': MakeWriter, +477 'ebs': EBSWriter } +478 +
479 -def convert(cmdList, filename, outputtype="ant"): +
480 """ Helper to directly convert a command list into a specific runnable command format. +481 e.g: +482 cmdList = CommandList() +483 cmdList.addCommand(...) +484 convert(cmdList, "echo Hello world", "ant") +485 """ +486 writer = __writerConstructors[outputtype](filename) +487 writer(cmdList) +
488 +
489 -def get_writer(buildTool, fileOut): +
490 """ Get a Writer for a specific format. """ +491 return __writerConstructors[buildTool](fileOut) +
492 +493 +
494 -def supported_writers(): +
495 """ Return the list of supported Writer. """ +496 return __writerConstructors.keys() +
497 +
+
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + +