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