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