Add exception and log mechanism
[mirror_edk2.git] / Tools / Source / GenBuild / org / tianocore / build / GenBuildTask.java
CommitLineData
878ddf1f 1/** @file\r
2 This file is ANT task GenBuild. \r
3 \r
4 The file is used to parse a specified Module, and generate its build time \r
5 ANT script build.xml, then call the the ANT script to build the module.\r
6 \r
7Copyright (c) 2006, Intel Corporation\r
8All rights reserved. This program and the accompanying materials\r
9are licensed and made available under the terms and conditions of the BSD License\r
10which accompanies this distribution. The full text of the license may be found at\r
11http://opensource.org/licenses/bsd-license.php\r
12\r
13THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15**/\r
16package org.tianocore.build;\r
17\r
18import java.io.File;\r
19import java.util.HashMap;\r
20import java.util.HashSet;\r
21import java.util.Iterator;\r
22import java.util.LinkedHashSet;\r
23import java.util.List;\r
24import java.util.Map;\r
25import java.util.Set;\r
26import java.util.Vector;\r
27import java.util.regex.Matcher;\r
28import java.util.regex.Pattern;\r
29\r
30import javax.xml.parsers.DocumentBuilder;\r
31import javax.xml.parsers.DocumentBuilderFactory;\r
32import javax.xml.transform.OutputKeys;\r
33import javax.xml.transform.Result;\r
34import javax.xml.transform.Source;\r
35import javax.xml.transform.Transformer;\r
36import javax.xml.transform.TransformerFactory;\r
37import javax.xml.transform.dom.DOMSource;\r
38import javax.xml.transform.stream.StreamResult;\r
39\r
40import org.apache.tools.ant.BuildException;\r
41import org.apache.tools.ant.Project;\r
42import org.apache.tools.ant.Task;\r
43import org.apache.tools.ant.taskdefs.Ant;\r
44import org.apache.xmlbeans.XmlObject;\r
45import org.w3c.dom.Comment;\r
46import org.w3c.dom.Document;\r
47import org.w3c.dom.Element;\r
48import org.w3c.dom.Node;\r
49\r
50import org.tianocore.build.autogen.AutoGen;\r
51import org.tianocore.build.autogen.CommonDefinition;\r
52import org.tianocore.build.fpd.FpdParserTask;\r
b9546cc8 53import org.tianocore.build.global.GenBuildLogger;\r
878ddf1f 54import org.tianocore.build.global.GlobalData;\r
55import org.tianocore.build.global.OutputManager;\r
56import org.tianocore.build.global.SurfaceAreaQuery;\r
57import org.tianocore.build.toolchain.ToolChainFactory;\r
b9546cc8 58import org.tianocore.logger.EdkLog;\r
878ddf1f 59import org.tianocore.FilenameDocument;\r
60import org.tianocore.MsaHeaderDocument;\r
61import org.tianocore.MsaLibHeaderDocument;\r
62\r
63/**\r
64 <p>\r
65 <code>GenBuildTask</code> is an ANT task that can be used in ANT build\r
66 system. The main function of this task is to parse module's surface area,\r
67 then generate the corresponding <em>BaseName_build.xml</em> (the real ANT\r
68 build script) and call this to build the module.\r
69 </p>\r
70 \r
71 <p>\r
72 The usage is (take module <em>HelloWorld</em> for example):\r
73 </p>\r
74 \r
75 <pre>\r
76 &lt;GenBuild baseName=&quot;HelloWorld&quot; \r
77 mbdFilename=&quot;${MODULE_DIR}/HelloWorld.mbd&quot; \r
78 msaFilename=&quot;${MODULE_DIR}/HelloWorld.msa&quot;/&gt;\r
79 </pre>\r
80 \r
81 <p>\r
82 This task calls <code>AutoGen</code> to generate <em>AutoGen.c</em> and\r
83 <em>AutoGen.h</em>. The task also parses the development environment\r
84 configuration files, such as collecting package information, setting compiler\r
85 flags and so on.\r
86 </p>\r
87 \r
88 \r
89 @since GenBuild 1.0\r
90**/\r
91public class GenBuildTask extends Task {\r
92\r
93 ///\r
94 /// Module surface area file.\r
95 ///\r
96 File msaFilename;\r
97\r
98 ///\r
99 /// Module build description file.\r
100 ///\r
101 File mbdFilename;\r
102\r
103 ///\r
104 /// Module surface area information after overrided.\r
105 ///\r
106 public Map<String, XmlObject> map = new HashMap<String, XmlObject>();\r
107\r
108 ///\r
109 /// Module's base name.\r
110 ///\r
111 private String baseName;\r
112\r
113 ///\r
114 /// Current build Arch, such as IA32, X64, IPF and so on.\r
115 ///\r
116 private String arch;\r
117\r
118 ///\r
119 /// Module's GUID (Globally Unique Identifier).\r
120 ///\r
121 private String guid;\r
122\r
123 ///\r
124 /// Module's component type, such as SEC, LIBRARY, BS_DRIVER and so on.\r
125 ///\r
126 private String componentType;\r
127\r
128 ///\r
129 /// This value is used in build time. Override module's component type. When\r
130 /// search FFS (Sections information) in common file, buildtype instead of\r
131 /// component type.\r
132 ///\r
133 private String buildType;\r
134\r
135 ///\r
136 /// List all required includes for current build module.\r
137 ///\r
138 public Set<String> includes = new LinkedHashSet<String>();\r
139\r
140 ///\r
141 /// List all libraries for current build module.\r
142 ///\r
143 public Set<String> libraries = new LinkedHashSet<String>();\r
144\r
145 ///\r
146 /// List all source files for current build module.\r
147 ///\r
148 public Set<String> sourceFiles = new LinkedHashSet<String>();\r
149\r
150 ///\r
151 /// Flag to identify what surface area files are specified. Current value is\r
152 /// <em>NO_SA</em>, <em>ONLY_MSA</em>, <em>ONLY_LIBMSA</em>,\r
153 /// <em>MSA_AND_MBD</em> or <em>LIBMSA_AND_LIBMBD</em>.\r
154 /// \r
155 /// @see org.tianocore.build.global.GlobaData\r
156 ///\r
157 private int flag = GlobalData.NO_SA;\r
158\r
159 ///\r
160 /// The information at the header of <em>build.xml</em>.\r
161 ///\r
162 private String info = "====================================================================\n"\r
163 + "DO NOT EDIT \n"\r
164 + "File auto-generated by build utility\n"\r
165 + "\n"\r
166 + "Abstract:\n"\r
167 + "Auto-generated ANT build file for building of EFI Modules/Platforms\n"\r
168 + "=====================================================================";\r
169\r
170 /**\r
171 Public construct method. It is necessary for ANT task.\r
172 **/\r
173 public GenBuildTask() {\r
174 }\r
175\r
176 /**\r
177 ANT task's entry point, will be called after init(). The main steps is described\r
178 as following: \r
179 <ul>\r
180 <li> Judge current build mode (MODULE | PACKAGE | PLATFORM). This step will execute\r
181 only once in whole build process; </li>\r
182 <li> Initialize global information (Framework DB, SPD files and all MSA files \r
183 listed in SPD). This step will execute only once in whole build process; </li>\r
184 <li> Restore some important ANT property. If current build is single module \r
185 build, here will set many default values; </li>\r
186 <li> Get the current module's overridded surface area information from \r
187 global data; </li> \r
188 <li> Set up the output directories, including BIN_DIR, DEST_DIR_OUTPUT and\r
189 DEST_DIR_DEBUG; </li>\r
190 <li> Get module dependent library instances and include pathes; </li>\r
191 <li> Judge whether current module is built. If yes, skip it; </li>\r
192 <li> Call AutoGen and PCD to generate AutoGen.c & AutoGen.h </li>\r
193 <li> Set up the compile flags; </li>\r
194 <li> Generate BaseName_build.xml; </li>\r
195 <li> Call to BaseName_build.xml, and build the current module. </li>\r
196 </ul>\r
197 \r
198 <p>Build is dependent on BuildMacro.xml which define many macro. </p> \r
199 \r
200 @throws BuildException\r
201 From module build, exception from module surface area invalid.\r
202 **/\r
203 public void execute() throws BuildException {\r
204 System.out.println("Module [" + baseName + "] start.");\r
b9546cc8 205 //\r
206 // Inital GenBuild log method \r
207 //\r
208 GenBuildLogger logger = new GenBuildLogger(getProject());\r
209 EdkLog.setLogger(logger);\r
210 EdkLog.setLogLevel(1);\r
211 \r
878ddf1f 212 OutputManager.update(getProject());\r
213 GlobalData.initInfo("Tools" + File.separatorChar + "Conf" + File.separatorChar + "FrameworkDatabase.db",\r
214 getProject().getProperty("WORKSPACE_DIR"));\r
215 recallFixedProperties();\r
216 arch = getProject().getProperty("ARCH");\r
217 arch = arch.toUpperCase();\r
218 map = GlobalData.getDoc(baseName);\r
219 //\r
220 // Initialize SurfaceAreaQuery\r
221 //\r
222 SurfaceAreaQuery.setDoc(map);\r
223 //\r
224 // Setup Output Management\r
225 //\r
226 String[] outdir = SurfaceAreaQuery.getOutputDirectory();\r
227 OutputManager.update(getProject(), outdir[1], outdir[0]);\r
228\r
229 updateIncludesAndLibraries();\r
230\r
231 if (GlobalData.isModuleBuilt(baseName, arch)) {\r
232 return;\r
233 } else {\r
234 GlobalData.registerBuiltModule(baseName, arch);\r
235 }\r
236 //\r
237 // Call AutoGen\r
238 //\r
239 AutoGen autogen = new AutoGen(getProject().getProperty("DEST_DIR_DEBUG"), baseName, arch);\r
240 autogen.genAutogen();\r
241 //\r
242 // Update parameters\r
243 //\r
244 updateParameters();\r
245 //\r
246 // Update flags like CC_FLAGS, LIB_FLAGS etc.\r
247 //\r
248 flagsSetup();\r
61746a87 249 GlobalData.addLibrary(baseName, arch, getProject().getProperty("BIN_DIR") + File.separatorChar + baseName + ".lib");\r
250 GlobalData.addModuleLibrary(baseName, arch, libraries);\r
878ddf1f 251 //\r
252 // If ComponentType is USER_DEFINED,\r
253 // then call the exist BaseName_build.xml directly.\r
254 //\r
255 if (buildType.equalsIgnoreCase("CUSTOM_BUILD")) {\r
256 System.out.println("Call user-defined " + baseName + "_build.xml");\r
257 Ant ant = new Ant();\r
258 ant.setProject(getProject());\r
259 ant.setAntfile(getProject().getProperty("MODULE_DIR") + File.separatorChar + baseName + "_build.xml");\r
260 ant.setInheritAll(true);\r
261 ant.init();\r
262 ant.execute();\r
263 return;\r
264 }\r
265 //\r
266 // Generate ${BASE_NAME}_build.xml file\r
267 //\r
268 System.out.println("Generate " + baseName + "_build.xml");\r
269 genBuildFile();\r
270 System.out.println("Call the " + baseName + "_build.xml");\r
271 Ant ant = new Ant();\r
272 ant.setProject(getProject());\r
273 ant.setAntfile(getProject().getProperty("DEST_DIR_OUTPUT") + File.separatorChar + baseName + "_build.xml");\r
274 ant.setInheritAll(true);\r
275 ant.init();\r
276 ant.execute();\r
277 }\r
278\r
c43c6719 279 /**\r
280 Return the name of the directory that corresponds to the architecture.\r
281 This is a translation from the XML Schema tag to a directory that\r
282 corresponds to our directory name coding convention.\r
283 \r
284 **/\r
285 private String archDir(String arch) {\r
286 return arch.replaceFirst("X64", "x64")\r
287 .replaceFirst("IPF", "Ipf")\r
288 .replaceFirst("IA32", "Ia32")\r
289 .replaceFirst("ARM", "Arm")\r
290 .replaceFirst("EBC", "Ebc");\r
291 }\r
292\r
878ddf1f 293 /**\r
294 Get the dependent library instances and include package name from \r
295 surface area, and initialize module include pathes. \r
296 \r
297 **/\r
298 private void updateIncludesAndLibraries() {\r
299 List<String> rawIncludes = SurfaceAreaQuery.getIncludePackageName(arch);\r
300 if (rawIncludes != null) {\r
301 Iterator iter = rawIncludes.iterator();\r
302 while (iter.hasNext()) {\r
303 String packageName = (String) iter.next();\r
304 includes.add("${WORKSPACE_DIR}" + File.separatorChar + GlobalData.getPackagePath(packageName)\r
305 + File.separatorChar + "Include");\r
306 includes.add("${WORKSPACE_DIR}" + File.separatorChar + GlobalData.getPackagePath(packageName)\r
c43c6719 307 + File.separatorChar + "Include" + File.separatorChar + archDir(arch));\r
878ddf1f 308 }\r
309 }\r
310 includes.add("${DEST_DIR_DEBUG}");\r
311 List<String> rawLibraries = SurfaceAreaQuery.getLibraryInstance(this.arch, CommonDefinition.AlwaysConsumed);\r
312 if (rawLibraries != null) {\r
313 Iterator iter = rawLibraries.iterator();\r
314 while (iter.hasNext()) {\r
315 libraries.add((String) iter.next());\r
316 }\r
317 }\r
318 normalize();\r
319 }\r
320\r
321 /**\r
322 Normalize all dependent library instance and include pathes' format. \r
323 \r
324 **/\r
325 private void normalize() {\r
326 String[] includesArray = includes.toArray(new String[includes.size()]);\r
327 includes.clear();\r
328 for (int i = 0; i < includesArray.length; i++) {\r
329 includes.add((new File(includesArray[i])).getPath());\r
330 }\r
331 String[] librariesArray = libraries.toArray(new String[libraries.size()]);\r
332 libraries.clear();\r
333 for (int i = 0; i < librariesArray.length; i++) {\r
334 libraries.add((new File(librariesArray[i])).getPath());\r
335 }\r
336 }\r
337\r
338 /**\r
339 Restore some important ANT property. If current build is single module \r
340 build, here will set many default values.\r
341 \r
342 <p> If current build is single module build, then the default <code>ARCH</code>\r
343 is <code>IA32</code>. Also set up the properties <code>PACKAGE</code>, \r
344 <code>PACKAGE_DIR</code>, <code>TARGET</code> and <code>MODULE_DIR</code></p>\r
345 \r
346 <p> Note that for package build, package name is stored in <code>PLATFORM</code>\r
347 and package directory is stored in <code>PLATFORM_DIR</code>. </p> \r
348 \r
349 @see org.tianocore.build.global.OutputManager\r
350 **/\r
351 private void recallFixedProperties() {\r
352 //\r
353 // If build is for module build\r
354 //\r
355 if (getProject().getProperty("PACKAGE_DIR") == null) {\r
356 ToolChainFactory toolChainFactory = new ToolChainFactory(getProject());\r
357 toolChainFactory.setupToolChain();\r
358 //\r
359 // PACKAGE PACKAGE_DIR ARCH (Default) COMMON_FILE BUILD_MACRO\r
360 //\r
361 if (getProject().getProperty("ARCH") == null) {\r
362 getProject().setProperty("ARCH", "IA32");\r
363 }\r
364 String packageName = GlobalData.getPackageNameForModule(baseName);\r
365 getProject().setProperty("PACKAGE", packageName);\r
366 \r
367 String packageDir = GlobalData.getPackagePath(packageName);\r
368 getProject().setProperty("PACKAGE_DIR",\r
369 getProject().getProperty("WORKSPACE_DIR") + File.separatorChar + packageDir);\r
370 \r
371 getProject().setProperty("TARGET", toolChainFactory.getCurrentTarget());\r
372 \r
373 getProject().setProperty("MODULE_DIR",\r
374 getProject().replaceProperties(getProject().getProperty("MODULE_DIR")));\r
375 }\r
376 if (OutputManager.PLATFORM != null) {\r
377 getProject().setProperty("PLATFORM", OutputManager.PLATFORM);\r
378 }\r
379 if (OutputManager.PLATFORM_DIR != null) {\r
380 getProject().setProperty("PLATFORM_DIR", OutputManager.PLATFORM_DIR);\r
381 }\r
382 }\r
383\r
384 /**\r
385 The whole BaseName_build.xml is composed of seven part. \r
386 <ul>\r
387 <li> ANT properties; </li>\r
388 <li> Dependent module (dependent library instances in most case); </li>\r
389 <li> Source files; </li>\r
390 <li> Sections if module is not library; </li>\r
391 <li> Output (different for library module and driver module); </li>\r
392 <li> Clean; </li>\r
393 <li> Clean all. </li>\r
394 </ul>\r
395 \r
396 @throws BuildException\r
397 Error throws during BaseName_build.xml generating. \r
398 **/\r
399 private void genBuildFile() throws BuildException {\r
400 FfsProcess fp = new FfsProcess();\r
401 DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance();\r
402 try {\r
403 DocumentBuilder dombuilder = domfac.newDocumentBuilder();\r
404 Document document = dombuilder.newDocument();\r
405 Comment rootComment = document.createComment(info);\r
406 //\r
407 // create root element and its attributes\r
408 //\r
409 Element root = document.createElement("project");\r
410 //\r
411 // root.setAttribute("name", base_name);\r
412 //\r
413 root.setAttribute("default", "main");\r
414 root.setAttribute("basedir", ".");\r
415 //\r
416 // element for External ANT tasks\r
417 //\r
418 root.appendChild(document.createComment("Apply external ANT tasks"));\r
419 Element ele = document.createElement("taskdef");\r
420 ele.setAttribute("resource", "frameworktasks.tasks");\r
421 root.appendChild(ele);\r
422 ele = document.createElement("taskdef");\r
423 ele.setAttribute("resource", "cpptasks.tasks");\r
424 root.appendChild(ele);\r
425 ele = document.createElement("typedef");\r
426 ele.setAttribute("resource", "cpptasks.types");\r
427 root.appendChild(ele);\r
428 ele = document.createElement("taskdef");\r
429 ele.setAttribute("resource", "net/sf/antcontrib/antlib.xml");\r
430 root.appendChild(ele);\r
431 //\r
432 // elements for Properties\r
433 //\r
434 root.appendChild(document.createComment("All Properties"));\r
435 ele = document.createElement("property");\r
436 ele.setAttribute("name", "BASE_NAME");\r
437 ele.setAttribute("value", baseName);\r
438 root.appendChild(ele);\r
439 //\r
440 // Generate the default target,\r
441 // which depends on init, sections and output target\r
442 //\r
443 root.appendChild(document.createComment("Default target"));\r
444 ele = document.createElement("target");\r
445 ele.setAttribute("name", "main");\r
446 ele.setAttribute("depends", "libraries, sourcefiles, sections, output");\r
447 root.appendChild(ele);\r
448 //\r
449 // compile all source files\r
450 //\r
451 root.appendChild(document.createComment("Compile all dependency Library instances."));\r
452 ele = document.createElement("target");\r
453 ele.setAttribute("name", "libraries");\r
454 //\r
455 // Parse all sourfiles but files specified in sections\r
456 //\r
457 applyLibraryInstance(document, ele);\r
458 root.appendChild(ele);\r
459 //\r
460 // compile all source files\r
461 //\r
462 root.appendChild(document.createComment("sourcefiles target"));\r
463 ele = document.createElement("target");\r
464 ele.setAttribute("name", "sourcefiles");\r
465 //\r
466 // Parse all sourfiles but files specified in sections\r
467 //\r
468 applyCompileElement(document, ele);\r
469 root.appendChild(ele);\r
470 //\r
471 // generate the init target\r
472 // main purpose is create all nessary pathes\r
473 // generate the sections target\r
474 //\r
475 root.appendChild(document.createComment("sections target"));\r
476 ele = document.createElement("target");\r
477 ele.setAttribute("name", "sections");\r
478 applySectionsElement(document, ele, fp);\r
479 root.appendChild(ele);\r
480 //\r
481 // generate the output target\r
482 //\r
483 root.appendChild(document.createComment("output target"));\r
484 ele = document.createElement("target");\r
485 ele.setAttribute("name", "output");\r
486 applyOutputElement(document, ele, fp);\r
487 root.appendChild(ele);\r
488 //\r
489 // generate the clean target\r
490 //\r
491 root.appendChild(document.createComment("clean target"));\r
492 ele = document.createElement("target");\r
493 ele.setAttribute("name", "clean");\r
494 applyCleanElement(document, ele);\r
495 root.appendChild(ele);\r
496 //\r
497 // generate the Clean All target\r
498 //\r
499 root.appendChild(document.createComment("Clean All target"));\r
500 ele = document.createElement("target");\r
501 ele.setAttribute("name", "cleanall");\r
502 applyDeepcleanElement(document, ele);\r
503 root.appendChild(ele);\r
504 //\r
505 // add the root element to the document\r
506 //\r
507 document.appendChild(rootComment);\r
508 document.appendChild(root);\r
509 //\r
510 // Prepare the DOM document for writing\r
511 //\r
512 Source source = new DOMSource(document);\r
513 //\r
514 // Prepare the output file\r
515 //\r
516 File file = new File(getProject().getProperty("DEST_DIR_OUTPUT") + File.separatorChar + baseName\r
517 + "_build.xml");\r
518 //\r
519 // generate all directory path\r
520 //\r
521 (new File(file.getParent())).mkdirs();\r
522 Result result = new StreamResult(file);\r
523 //\r
524 // Write the DOM document to the file\r
525 //\r
526 Transformer xformer = TransformerFactory.newInstance().newTransformer();\r
527 xformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");\r
528 xformer.setOutputProperty(OutputKeys.INDENT, "yes");\r
529 xformer.transform(source, result);\r
530 } catch (Exception ex) {\r
531 throw new BuildException("Module [" + baseName + "] generating build file failed.\n" + ex.getMessage());\r
532 }\r
533 }\r
534\r
535 /**\r
536 Generate the clean elements for BaseName_build.xml. \r
537 \r
538 @param document current BaseName_build.xml XML document\r
539 @param root Root element for current\r
540 **/\r
541 private void applyCleanElement(Document document, Node root) {\r
542 String[] libinstances = libraries.toArray(new String[libraries.size()]);\r
543 for (int i = 0; i < libinstances.length; i++) {\r
544 File file = new File(GlobalData.getModulePath(libinstances[i]) + File.separatorChar + "build.xml");\r
545\r
546 Element ifEle = document.createElement("if");\r
547 Element availableEle = document.createElement("available");\r
548 availableEle.setAttribute("file", file.getPath());\r
549 ifEle.appendChild(availableEle);\r
550 Element elseEle = document.createElement("then");\r
551\r
552 Element ele = document.createElement("ant");\r
553 ele.setAttribute("antfile", file.getPath());\r
554 ele.setAttribute("inheritAll", "false");\r
555 ele.setAttribute("target", libinstances[i] + "_clean");\r
556 //\r
557 // Workspace_DIR\r
558 //\r
559 Element property = document.createElement("property");\r
560 property.setAttribute("name", "WORKSPACE_DIR");\r
561 property.setAttribute("value", "${WORKSPACE_DIR}");\r
562 ele.appendChild(property);\r
563 //\r
564 // Package Dir\r
565 //\r
566 property = document.createElement("property");\r
567 property.setAttribute("name", "PACKAGE_DIR");\r
568 property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar\r
569 + GlobalData.getPackagePathForModule(libinstances[i]));\r
570 ele.appendChild(property);\r
571 //\r
572 // ARCH\r
573 //\r
574 property = document.createElement("property");\r
575 property.setAttribute("name", "ARCH");\r
576 property.setAttribute("value", "${ARCH}");\r
577 ele.appendChild(property);\r
578 //\r
579 // TARGET\r
580 //\r
581 property = document.createElement("property");\r
582 property.setAttribute("name", "TARGET");\r
583 property.setAttribute("value", "${TARGET}");\r
584 ele.appendChild(property);\r
585 //\r
586 // PACKAGE\r
587 //\r
588 property = document.createElement("property");\r
589 property.setAttribute("name", "PACKAGE");\r
590 property.setAttribute("value", GlobalData.getPackageNameForModule(libinstances[i]));\r
591 ele.appendChild(property);\r
592\r
593 elseEle.appendChild(ele);\r
594 ifEle.appendChild(elseEle);\r
595 root.appendChild(ifEle);\r
596 }\r
597 }\r
598\r
599 /**\r
600 Generate the cleanall elements for BaseName_build.xml. \r
601 \r
602 @param document current BaseName_build.xml XML document\r
603 @param root Root element for current\r
604 **/\r
605 private void applyDeepcleanElement(Document document, Node root) {\r
606 String[] libinstances = libraries.toArray(new String[libraries.size()]);\r
607 for (int i = 0; i < libinstances.length; i++) {\r
608 File file = new File(GlobalData.getModulePath(libinstances[i]) + File.separatorChar + "build.xml");\r
609\r
610 Element ifEle = document.createElement("if");\r
611 Element availableEle = document.createElement("available");\r
612 availableEle.setAttribute("file", file.getPath());\r
613 ifEle.appendChild(availableEle);\r
614 Element elseEle = document.createElement("then");\r
615\r
616 Element ele = document.createElement("ant");\r
617 ele.setAttribute("antfile", file.getPath());\r
618 ele.setAttribute("inheritAll", "false");\r
619 ele.setAttribute("target", libinstances[i] + "_cleanall");\r
620 //\r
621 // Workspace_DIR\r
622 //\r
623 Element property = document.createElement("property");\r
624 property.setAttribute("name", "WORKSPACE_DIR");\r
625 property.setAttribute("value", "${WORKSPACE_DIR}");\r
626 ele.appendChild(property);\r
627 //\r
628 // Package Dir\r
629 //\r
630 property = document.createElement("property");\r
631 property.setAttribute("name", "PACKAGE_DIR");\r
632 property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar\r
633 + GlobalData.getPackagePathForModule(libinstances[i]));\r
634 ele.appendChild(property);\r
635 //\r
636 // ARCH\r
637 //\r
638 property = document.createElement("property");\r
639 property.setAttribute("name", "ARCH");\r
640 property.setAttribute("value", "${ARCH}");\r
641 ele.appendChild(property);\r
642 //\r
643 // TARGET\r
644 //\r
645 property = document.createElement("property");\r
646 property.setAttribute("name", "TARGET");\r
647 property.setAttribute("value", "${TARGET}");\r
648 ele.appendChild(property);\r
649 //\r
650 // PACKAGE\r
651 //\r
652 property = document.createElement("property");\r
653 property.setAttribute("name", "PACKAGE");\r
654 property.setAttribute("value", GlobalData.getPackageNameForModule(libinstances[i]));\r
655 ele.appendChild(property);\r
656\r
657 elseEle.appendChild(ele);\r
658 ifEle.appendChild(elseEle);\r
659 root.appendChild(ifEle);\r
660 }\r
661 }\r
662\r
663 /**\r
664 Generate the dependent library instances elements for BaseName_build.xml. \r
665 \r
666 @param document current BaseName_build.xml XML document\r
667 @param root Root element for current\r
668 **/\r
669 private void applyLibraryInstance(Document document, Node root) {\r
670 String[] libinstances = libraries.toArray(new String[libraries.size()]);\r
671 for (int i = 0; i < libinstances.length; i++) {\r
672 Element ele = document.createElement("ant");\r
673 File file = new File(GlobalData.getModulePath(libinstances[i]) + File.separatorChar + "build.xml");\r
674 ele.setAttribute("antfile", file.getPath());\r
675 ele.setAttribute("inheritAll", "false");\r
676 ele.setAttribute("target", libinstances[i]);\r
677 //\r
678 // Workspace_DIR\r
679 //\r
680 Element property = document.createElement("property");\r
681 property.setAttribute("name", "WORKSPACE_DIR");\r
682 property.setAttribute("value", "${WORKSPACE_DIR}");\r
683 ele.appendChild(property);\r
684 //\r
685 // Package Dir\r
686 //\r
687 property = document.createElement("property");\r
688 property.setAttribute("name", "PACKAGE_DIR");\r
689 property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar\r
690 + GlobalData.getPackagePathForModule(libinstances[i]));\r
691 ele.appendChild(property);\r
692 //\r
693 // ARCH\r
694 //\r
695 property = document.createElement("property");\r
696 property.setAttribute("name", "ARCH");\r
697 property.setAttribute("value", "${ARCH}");\r
698 ele.appendChild(property);\r
699 //\r
700 // TARGET\r
701 //\r
702 property = document.createElement("property");\r
703 property.setAttribute("name", "TARGET");\r
704 property.setAttribute("value", "${TARGET}");\r
705 ele.appendChild(property);\r
706 //\r
707 // PACKAGE\r
708 //\r
709 property = document.createElement("property");\r
710 property.setAttribute("name", "PACKAGE");\r
711 property.setAttribute("value", GlobalData.getPackageNameForModule(libinstances[i]));\r
712 ele.appendChild(property);\r
713 root.appendChild(ele);\r
714 }\r
715 Element expand = document.createElement("Expand");\r
716 root.appendChild(expand);\r
717 }\r
718 \r
719 /**\r
720 Generate the build source files elements for BaseName_build.xml. \r
721 \r
722 @param document current BaseName_build.xml XML document\r
723 @param root Root element for current\r
724 **/\r
725 private void applyCompileElement(Document document, Node root) {\r
726 FileProcess fileProcess = new FileProcess();\r
727 fileProcess.init(getProject(), includes, sourceFiles, document);\r
728 Node[] files = this.getSourceFiles();\r
729 //\r
730 // Parse all unicode files\r
731 //\r
732 for (int i = 0; i < files.length; i++) {\r
733 String filetype = getFiletype(files[i]);\r
734 if (filetype != null) {\r
735 fileProcess.parseFile(getFilename(files[i]), filetype, root, true);\r
736 } else {\r
737 fileProcess.parseFile(getFilename(files[i]), root, true);\r
738 }\r
739 }\r
740 if (fileProcess.isUnicodeExist()) {\r
741 Element ele = document.createElement("Build_Unicode_Database");\r
742 ele.setAttribute("FILEPATH", ".");\r
743 ele.setAttribute("FILENAME", "${BASE_NAME}");\r
744 root.appendChild(ele);\r
745 }\r
746\r
747 //\r
748 // Parse AutoGen.c & AutoGen.h\r
749 //\r
750 if (!baseName.equalsIgnoreCase("Shell")) {\r
751 fileProcess.parseFile(getProject().getProperty("DEST_DIR_DEBUG") + File.separatorChar + "AutoGen.c", root,\r
752 false);\r
753 }\r
754 //\r
755 // Parse all source files\r
756 //\r
757 for (int i = 0; i < files.length; i++) {\r
758 String filetype = getFiletype(files[i]);\r
759 if (filetype != null) {\r
760 fileProcess.parseFile(getFilename(files[i]), filetype, root, false);\r
761 } else {\r
762 fileProcess.parseFile(getFilename(files[i]), root, false);\r
763 }\r
764 }\r
765 //\r
766 // root.appendChild(parallelEle);\r
767 //\r
768 Iterator iter = sourceFiles.iterator();\r
769 String str = "";\r
770 while (iter.hasNext()) {\r
771 str += " " + (String) iter.next();\r
772 }\r
773 getProject().setProperty("SOURCE_FILES", str);\r
774 }\r
775\r
776 /**\r
777 Generate the section elements for BaseName_build.xml. Library module will\r
778 skip this process. \r
779 \r
780 @param document current BaseName_build.xml XML document\r
781 @param root Root element for current\r
782 **/\r
783 private void applySectionsElement(Document document, Node root, FfsProcess fp) {\r
784 if (fp.initSections(buildType, getProject())) {\r
785 String targetFilename = guid + "-" + baseName + FpdParserTask.getSuffix(componentType);\r
786 String[] list = fp.getGenSectionElements(document, baseName, guid, targetFilename);\r
787\r
788 for (int i = 0; i < list.length; i++) {\r
789 Element ele = document.createElement(list[i]);\r
790 ele.setAttribute("FILEPATH", ".");\r
791 ele.setAttribute("FILENAME", "${BASE_NAME}");\r
792 root.appendChild(ele);\r
793 }\r
794 }\r
795 }\r
796\r
797 /**\r
798 Generate the output elements for BaseName_build.xml. If module is library,\r
799 call the <em>LIB</em> command, else call the <em>GenFfs</em> command. \r
800 \r
801 @param document current BaseName_build.xml XML document\r
802 @param root Root element for current\r
803 **/\r
804 private void applyOutputElement(Document document, Node root, FfsProcess fp) {\r
805 if (flag == GlobalData.ONLY_LIBMSA || flag == GlobalData.LIBMSA_AND_LIBMBD) {\r
806 //\r
807 // call Lib command\r
808 //\r
809 Element cc = document.createElement("Build_Library");\r
810 cc.setAttribute("FILENAME", baseName);\r
811 root.appendChild(cc);\r
812 }\r
813 //\r
814 // if it is a module but library\r
815 //\r
816 else {\r
817 if (fp.getFfsNode() != null) {\r
818 root.appendChild(fp.getFfsNode());\r
819 }\r
820 }\r
821 }\r
822\r
823 /**\r
824 Get file name from node. If some wrong, return string with zero length. \r
825 \r
826 @param node Filename node of MSA/MBD or specified in each Section\r
827 @return File name\r
828 **/\r
829 private String getFilename(Node node) {\r
830 String path = null;\r
831 String filename = "${MODULE_DIR}" + File.separatorChar;\r
832 String str = "";\r
833 try {\r
834 FilenameDocument file = (FilenameDocument) XmlObject.Factory.parse(node);\r
835 str = file.getFilename().getStringValue().trim();\r
836 path = file.getFilename().getPath();\r
837 } catch (Exception e) {\r
838 str = "";\r
839 }\r
840 if (path != null) {\r
841 filename += path + File.separatorChar + str;\r
842 } else {\r
843 filename += str;\r
844 }\r
845 return getProject().replaceProperties(filename);\r
846 }\r
847\r
848 /**\r
849 Get file type from node. If some wrong or not specified, return \r
850 <code>null</code>. \r
851 \r
852 @param node Filename node of MSA/MBD or specified in each Section\r
853 @return File type\r
854 **/\r
855 private String getFiletype(Node node) {\r
856 String str = null;\r
857 try {\r
858 FilenameDocument file = (FilenameDocument) XmlObject.Factory.parse(node);\r
859 str = file.getFilename().getFileType();\r
860 } catch (Exception e) {\r
861 str = null;\r
862 }\r
863 return str;\r
864 }\r
865\r
866 /**\r
867 Return all source files but AutoGen.c.\r
868 \r
869 @return source files Node array\r
870 **/\r
871 public Node[] getSourceFiles() {\r
872 XmlObject[] files = SurfaceAreaQuery.getSourceFiles(arch);\r
873 if (files == null) {\r
874 return new Node[0];\r
875 }\r
876 Vector<Node> vector = new Vector<Node>();\r
877 for (int i = 0; i < files.length; i++) {\r
878 vector.addElement(files[i].getDomNode());\r
879 }\r
880 //\r
881 // To be consider sourcefiles from Sections\r
882 //\r
883 return vector.toArray(new Node[vector.size()]);\r
884 }\r
885\r
886 /**\r
887 Get current module's base name. \r
888 \r
889 @return base name\r
890 **/\r
891 public String getBaseName() {\r
892 return baseName;\r
893 }\r
894\r
895 /**\r
896 Set MBD surface area file. For ANT use.\r
897 \r
898 @param mbdFilename Surface Area file\r
899 **/\r
900 public void setMbdFilename(File mbdFilename) {\r
901 this.mbdFilename = mbdFilename;\r
902 }\r
903\r
904 /**\r
905 Set MSA surface area file. For ANT use.\r
906 \r
907 @param msaFilename Surface Area file\r
908 **/\r
909 public void setMsaFilename(File msaFilename) {\r
910 this.msaFilename = msaFilename;\r
911 }\r
912\r
913 /**\r
914 Compile flags setup. \r
915 \r
916 <p> Take command <code>CC</code> and arch <code>IA32</code> for example, \r
917 Those flags are from <code>ToolChainFactory</code>: </p>\r
918 <ul>\r
919 <li> IA32_CC </li>\r
920 <li> IA32_CC_STD_FLAGS </li>\r
921 <li> IA32_CC_GLOBAL_FLAGS </li>\r
922 <li> IA32_CC_GLOBAL_ADD_FLAGS </li>\r
923 <li> IA32_CC_GLOBAL_SUB_FLAGS </li>\r
924 </ul>\r
925 Those flags can user-define: \r
926 <ul>\r
927 <li> IA32_CC_PROJ_FLAGS </li>\r
928 <li> IA32_CC_PROJ_ADD_FLAGS </li>\r
929 <li> IA32_CC_PROJ_SUB_FLAGS </li>\r
930 <li> CC_PROJ_FLAGS </li>\r
931 <li> CC_PROJ_ADD_FLAGS </li>\r
932 <li> CC_PROJ_SUB_FLAGS </li>\r
933 <li> CC_FLAGS </li>\r
934 <li> IA32_CC_FLAGS </li>\r
935 </ul>\r
936 \r
937 <p> The final flags is composed of STD, GLOBAL and PROJ. If CC_FLAGS or\r
938 IA32_CC_FLAGS is specified, STD, GLOBAL and PROJ will not affect. </p>\r
939 \r
940 Note that the <code>ToolChainFactory</code> executes only once \r
941 during whole build process. \r
942 **/\r
943 private void flagsSetup() {\r
944 Project project = getProject();\r
945 //\r
946 // If ToolChain has been set up before, do nothing.\r
947 //\r
948 ToolChainFactory toolChainFactory = new ToolChainFactory(project);\r
949 toolChainFactory.setupToolChain();\r
950\r
951 String[] cmd = ToolChainFactory.commandType;\r
952 Set<String> addSet = new HashSet<String>(40);\r
953 Set<String> subSet = new HashSet<String>(40);\r
954 for (int i = 0; i < cmd.length; i++) {\r
955 String str = ToolChainFactory.getValue(arch + "_" + cmd[i]);\r
956 //\r
957 // Command line path+command name\r
958 //\r
959 if (str != null) {\r
960 project.setProperty(cmd[i], str);\r
961 }\r
962 //\r
963 // ARCH_CMD_STD_FLAGS\r
964 //\r
965 str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_STD_FLAGS");\r
966 if (str != null) {\r
967 putFlagsToSet(addSet, str);\r
968 project.setProperty(cmd[i] + "_STD_FLAGS", str);\r
969 }\r
970 //\r
971 // ARCH_CMD_GLOBAL_FLAGS\r
972 //\r
973 str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_GLOBAL_FLAGS");\r
974 if (str != null) {\r
975 putFlagsToSet(addSet, str);\r
976 }\r
977 //\r
978 // ARCH_CMD_GLOBAL_ADD_FLAGS\r
979 //\r
980 str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_GLOBAL_ADD_FLAGS");\r
981 if (str != null) {\r
982 putFlagsToSet(addSet, str);\r
983 }\r
984 //\r
985 // ARCH_CMD_GLOBAL_SUB_FLAGS\r
986 //\r
987 str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_GLOBAL_SUB_FLAGS");\r
988 if (str != null) {\r
989 putFlagsToSet(subSet, str);\r
990 }\r
991 //\r
992 // ARCH_CMD_PROJ_FLAGS\r
993 //\r
994 str = project.getProperty(arch + "_" + cmd[i] + "_PROJ_FLAGS");\r
995 if (str != null) {\r
996 putFlagsToSet(addSet, str);\r
997 }\r
998 //\r
999 // ARCH_CMD_PROG_FLAGS\r
1000 //\r
1001 str = project.getProperty(arch + "_" + cmd[i] + "_PROJ_ADD_FLAGS");\r
1002 if (str != null) {\r
1003 putFlagsToSet(addSet, str);\r
1004 }\r
1005 //\r
1006 // ARCH_CMD_PROG_FLAGS\r
1007 //\r
1008 str = project.getProperty(arch + "_" + cmd[i] + "_PROJ_SUB_FLAGS");\r
1009 if (str != null) {\r
1010 putFlagsToSet(subSet, str);\r
1011 }\r
1012 //\r
1013 // CMD_PROJ_FLAGS\r
1014 //\r
1015 str = project.getProperty(cmd[i] + "_PROJ_FLAGS");\r
1016 if (str != null) {\r
1017 putFlagsToSet(addSet, str);\r
1018 }\r
1019 //\r
1020 // CMD_PROG_FLAGS\r
1021 //\r
1022 str = project.getProperty(cmd[i] + "_PROJ_ADD_FLAGS");\r
1023 if (str != null) {\r
1024 putFlagsToSet(addSet, str);\r
1025 }\r
1026 //\r
1027 // CMD_PROG_FLAGS\r
1028 //\r
1029 str = project.getProperty(cmd[i] + "_PROJ_SUB_FLAGS");\r
1030 if (str != null) {\r
1031 putFlagsToSet(subSet, str);\r
1032 }\r
1033 //\r
1034 // If IA32_CC_FLAGS or IA32_LIB_FLAGS .. has defined in BuildOptions\r
1035 //\r
1036 if ((str = project.getProperty(arch + "_" + cmd[i] + "_FLAGS")) != null) {\r
1037 project.setProperty(cmd[i] + "_FLAGS", getRawFlags(addSet, subSet));\r
1038 addSet.clear();\r
1039 subSet.clear();\r
1040 putFlagsToSet(addSet, project.replaceProperties(str));\r
1041 project.setProperty(cmd[i] + "_FLAGS", project.replaceProperties(getFlags(addSet, subSet)));\r
1042 addSet.clear();\r
1043 subSet.clear();\r
1044 }\r
1045 //\r
1046 // If CC_FLAGS or LIB_FLAGS .. has defined in BuildOptions\r
1047 //\r
1048 else if ((str = project.getProperty(cmd[i] + "_FLAGS")) != null) {\r
1049 project.setProperty(cmd[i] + "_FLAGS", getRawFlags(addSet, subSet));\r
1050 addSet.clear();\r
1051 subSet.clear();\r
1052 putFlagsToSet(addSet, project.replaceProperties(str));\r
1053 project.setProperty(cmd[i] + "_FLAGS", project.replaceProperties(getFlags(addSet, subSet)));\r
1054 addSet.clear();\r
1055 subSet.clear();\r
1056 } else {\r
1057 project.setProperty(cmd[i] + "_FLAGS", getFlags(addSet, subSet));\r
1058 addSet.clear();\r
1059 subSet.clear();\r
1060 }\r
1061 }\r
1062 project.setProperty("C_FLAGS", project.getProperty("CC_FLAGS"));\r
1063 }\r
1064\r
1065 /**\r
1066 Initialize some properties will be used in current module build, including\r
1067 user-defined option from <em>Option</em> of <em>BuildOptions</em> in \r
1068 surface area. \r
1069 **/\r
1070 private void updateParameters() {\r
1071 getProject().setProperty("OBJECTS", "");\r
1072 getProject().setProperty("SDB_FILES", "");\r
1073 getProject().setProperty("BASE_NAME", baseName);\r
1074 if (map.get("MsaHeader") != null) {\r
250258de 1075 guid = SurfaceAreaQuery.getModuleGuid();//header.getGuid().getStringValue();\r
1076 componentType = SurfaceAreaQuery.getComponentType();//header.getComponentType().toString();\r
1077 if (!componentType.equalsIgnoreCase("LIBRARY")) {\r
1078 flag = GlobalData.MSA_AND_MBD;\r
1079 } else {\r
1080 flag = GlobalData.LIBMSA_AND_LIBMBD;\r
1081 }\r
878ddf1f 1082 } \r
1083 \r
1084 else if (map.get("MsaLibHeader") != null) {\r
1085 flag = GlobalData.LIBMSA_AND_LIBMBD;\r
1086 MsaLibHeaderDocument.MsaLibHeader header = ((MsaLibHeaderDocument) map.get("MsaLibHeader"))\r
1087 .getMsaLibHeader();\r
1088 guid = header.getGuid().getStringValue();\r
1089 componentType = header.getComponentType().toString();\r
1090 }\r
1091 \r
1092 if (componentType != null) {\r
1093 getProject().setProperty("COMPONENT_TYPE", componentType);\r
1094 }\r
250258de 1095\r
878ddf1f 1096 if (guid != null) {\r
1097 getProject().setProperty("FILE_GUID", guid);\r
1098 }\r
1099 //\r
1100 // Get all options and set to properties\r
1101 //\r
1102 String[][] options = SurfaceAreaQuery.getOptions(arch);\r
1103 for (int i = 0; i < options.length; i++) {\r
1104 if (options[i][0] != null && options[i][1] != null) {\r
1105 getProject().setProperty(options[i][0], getProject().replaceProperties(options[i][1]));\r
1106 }\r
1107 }\r
1108\r
1109 buildType = getProject().getProperty("BUILD_TYPE");\r
1110 if (buildType == null) {\r
1111 buildType = componentType;\r
1112 }\r
1113\r
1114 }\r
1115\r
1116 /**\r
1117 Separate the string and instore in set.\r
1118 \r
1119 <p> String is separated by Java Regulation Expression \r
1120 "[^\\\\]?(\".*?[^\\\\]\")[ \t,]+". </p>\r
1121 \r
1122 <p>For example: </p>\r
1123 \r
1124 <pre>\r
1125 "/nologo", "/W3", "/WX"\r
1126 "/C", "/DSTRING_DEFINES_FILE=\"BdsStrDefs.h\""\r
1127 </pre>\r
1128 \r
1129 @param set store the separated string\r
1130 @param str string to separate\r
1131 **/\r
1132 private void putFlagsToSet(Set<String> set, String str) {\r
1133 Pattern myPattern = Pattern.compile("[^\\\\]?(\".*?[^\\\\]\")[ \t,]+");\r
1134 Matcher matcher = myPattern.matcher(str + " ");\r
1135 while (matcher.find()) {\r
1136 String item = str.substring(matcher.start(1), matcher.end(1));\r
1137 if (!set.contains(item)) {\r
1138 set.add(item);\r
1139 }\r
1140 }\r
1141 }\r
1142 \r
1143 /**\r
1144 Generate the final flags string will be used by compile command. \r
1145 \r
1146 @param add the add flags set\r
1147 @param sub the sub flags set\r
1148 @return final flags after add set substract sub set\r
1149 **/\r
1150 private String getFlags(Set<String> add, Set<String> sub) {\r
1151 String result = "";\r
1152 add.removeAll(sub);\r
1153 Iterator iter = add.iterator();\r
1154 while (iter.hasNext()) {\r
1155 String str = getProject().replaceProperties((String) iter.next());\r
1156 result += str.substring(1, str.length() - 1) + " ";\r
1157 }\r
1158 return result;\r
1159 }\r
1160\r
1161 /**\r
1162 Generate the flags string with original format. The format is defined by \r
1163 Java Regulation Expression "[^\\\\]?(\".*?[^\\\\]\")[ \t,]+". </p>\r
1164 \r
1165 <p>For example: </p>\r
1166 \r
1167 <pre>\r
1168 "/nologo", "/W3", "/WX"\r
1169 "/C", "/DSTRING_DEFINES_FILE=\"BdsStrDefs.h\""\r
1170 </pre>\r
1171 \r
1172 @param add the add flags set\r
1173 @param sub the sub flags set\r
1174 @return flags with original format\r
1175 **/\r
1176 private String getRawFlags(Set<String> add, Set<String> sub) {\r
1177 String result = "";\r
1178 add.removeAll(sub);\r
1179 Iterator iter = add.iterator();\r
1180 while (iter.hasNext()) {\r
1181 String str = getProject().replaceProperties((String) iter.next());\r
1182 result += "\"" + str.substring(1, str.length() - 1) + "\", ";\r
1183 }\r
1184 return result;\r
1185 }\r
1186\r
1187 /**\r
1188 Set base name. For ANT use.\r
1189 \r
1190 @param baseName Base name\r
1191 **/\r
1192 public void setBaseName(String baseName) {\r
1193 this.baseName = baseName;\r
1194 }\r
1195\r
1196}\r