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