]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/GenBuild/org/tianocore/build/GenBuildTask.java
added the support for new schema and old schema at the same time
[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 Return the name of the directory that corresponds to the architecture.
272 This is a translation from the XML Schema tag to a directory that
273 corresponds to our directory name coding convention.
274
275 **/
276 private String archDir(String arch) {
277 return arch.replaceFirst("X64", "x64")
278 .replaceFirst("IPF", "Ipf")
279 .replaceFirst("IA32", "Ia32")
280 .replaceFirst("ARM", "Arm")
281 .replaceFirst("EBC", "Ebc");
282 }
283
284 /**
285 Get the dependent library instances and include package name from
286 surface area, and initialize module include pathes.
287
288 **/
289 private void updateIncludesAndLibraries() {
290 List<String> rawIncludes = SurfaceAreaQuery.getIncludePackageName(arch);
291 if (rawIncludes != null) {
292 Iterator iter = rawIncludes.iterator();
293 while (iter.hasNext()) {
294 String packageName = (String) iter.next();
295 includes.add("${WORKSPACE_DIR}" + File.separatorChar + GlobalData.getPackagePath(packageName)
296 + File.separatorChar + "Include");
297 includes.add("${WORKSPACE_DIR}" + File.separatorChar + GlobalData.getPackagePath(packageName)
298 + File.separatorChar + "Include" + File.separatorChar + archDir(arch));
299 }
300 }
301 includes.add("${DEST_DIR_DEBUG}");
302 List<String> rawLibraries = SurfaceAreaQuery.getLibraryInstance(this.arch, CommonDefinition.AlwaysConsumed);
303 if (rawLibraries != null) {
304 Iterator iter = rawLibraries.iterator();
305 while (iter.hasNext()) {
306 libraries.add((String) iter.next());
307 }
308 }
309 normalize();
310 }
311
312 /**
313 Normalize all dependent library instance and include pathes' format.
314
315 **/
316 private void normalize() {
317 String[] includesArray = includes.toArray(new String[includes.size()]);
318 includes.clear();
319 for (int i = 0; i < includesArray.length; i++) {
320 includes.add((new File(includesArray[i])).getPath());
321 }
322 String[] librariesArray = libraries.toArray(new String[libraries.size()]);
323 libraries.clear();
324 for (int i = 0; i < librariesArray.length; i++) {
325 libraries.add((new File(librariesArray[i])).getPath());
326 }
327 }
328
329 /**
330 Restore some important ANT property. If current build is single module
331 build, here will set many default values.
332
333 <p> If current build is single module build, then the default <code>ARCH</code>
334 is <code>IA32</code>. Also set up the properties <code>PACKAGE</code>,
335 <code>PACKAGE_DIR</code>, <code>TARGET</code> and <code>MODULE_DIR</code></p>
336
337 <p> Note that for package build, package name is stored in <code>PLATFORM</code>
338 and package directory is stored in <code>PLATFORM_DIR</code>. </p>
339
340 @see org.tianocore.build.global.OutputManager
341 **/
342 private void recallFixedProperties() {
343 //
344 // If build is for module build
345 //
346 if (getProject().getProperty("PACKAGE_DIR") == null) {
347 ToolChainFactory toolChainFactory = new ToolChainFactory(getProject());
348 toolChainFactory.setupToolChain();
349 //
350 // PACKAGE PACKAGE_DIR ARCH (Default) COMMON_FILE BUILD_MACRO
351 //
352 if (getProject().getProperty("ARCH") == null) {
353 getProject().setProperty("ARCH", "IA32");
354 }
355 String packageName = GlobalData.getPackageNameForModule(baseName);
356 getProject().setProperty("PACKAGE", packageName);
357
358 String packageDir = GlobalData.getPackagePath(packageName);
359 getProject().setProperty("PACKAGE_DIR",
360 getProject().getProperty("WORKSPACE_DIR") + File.separatorChar + packageDir);
361
362 getProject().setProperty("TARGET", toolChainFactory.getCurrentTarget());
363
364 getProject().setProperty("MODULE_DIR",
365 getProject().replaceProperties(getProject().getProperty("MODULE_DIR")));
366 }
367 if (OutputManager.PLATFORM != null) {
368 getProject().setProperty("PLATFORM", OutputManager.PLATFORM);
369 }
370 if (OutputManager.PLATFORM_DIR != null) {
371 getProject().setProperty("PLATFORM_DIR", OutputManager.PLATFORM_DIR);
372 }
373 }
374
375 /**
376 The whole BaseName_build.xml is composed of seven part.
377 <ul>
378 <li> ANT properties; </li>
379 <li> Dependent module (dependent library instances in most case); </li>
380 <li> Source files; </li>
381 <li> Sections if module is not library; </li>
382 <li> Output (different for library module and driver module); </li>
383 <li> Clean; </li>
384 <li> Clean all. </li>
385 </ul>
386
387 @throws BuildException
388 Error throws during BaseName_build.xml generating.
389 **/
390 private void genBuildFile() throws BuildException {
391 FfsProcess fp = new FfsProcess();
392 DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance();
393 try {
394 DocumentBuilder dombuilder = domfac.newDocumentBuilder();
395 Document document = dombuilder.newDocument();
396 Comment rootComment = document.createComment(info);
397 //
398 // create root element and its attributes
399 //
400 Element root = document.createElement("project");
401 //
402 // root.setAttribute("name", base_name);
403 //
404 root.setAttribute("default", "main");
405 root.setAttribute("basedir", ".");
406 //
407 // element for External ANT tasks
408 //
409 root.appendChild(document.createComment("Apply external ANT tasks"));
410 Element ele = document.createElement("taskdef");
411 ele.setAttribute("resource", "frameworktasks.tasks");
412 root.appendChild(ele);
413 ele = document.createElement("taskdef");
414 ele.setAttribute("resource", "cpptasks.tasks");
415 root.appendChild(ele);
416 ele = document.createElement("typedef");
417 ele.setAttribute("resource", "cpptasks.types");
418 root.appendChild(ele);
419 ele = document.createElement("taskdef");
420 ele.setAttribute("resource", "net/sf/antcontrib/antlib.xml");
421 root.appendChild(ele);
422 //
423 // elements for Properties
424 //
425 root.appendChild(document.createComment("All Properties"));
426 ele = document.createElement("property");
427 ele.setAttribute("name", "BASE_NAME");
428 ele.setAttribute("value", baseName);
429 root.appendChild(ele);
430 //
431 // Generate the default target,
432 // which depends on init, sections and output target
433 //
434 root.appendChild(document.createComment("Default target"));
435 ele = document.createElement("target");
436 ele.setAttribute("name", "main");
437 ele.setAttribute("depends", "libraries, sourcefiles, sections, output");
438 root.appendChild(ele);
439 //
440 // compile all source files
441 //
442 root.appendChild(document.createComment("Compile all dependency Library instances."));
443 ele = document.createElement("target");
444 ele.setAttribute("name", "libraries");
445 //
446 // Parse all sourfiles but files specified in sections
447 //
448 applyLibraryInstance(document, ele);
449 root.appendChild(ele);
450 //
451 // compile all source files
452 //
453 root.appendChild(document.createComment("sourcefiles target"));
454 ele = document.createElement("target");
455 ele.setAttribute("name", "sourcefiles");
456 //
457 // Parse all sourfiles but files specified in sections
458 //
459 applyCompileElement(document, ele);
460 root.appendChild(ele);
461 //
462 // generate the init target
463 // main purpose is create all nessary pathes
464 // generate the sections target
465 //
466 root.appendChild(document.createComment("sections target"));
467 ele = document.createElement("target");
468 ele.setAttribute("name", "sections");
469 applySectionsElement(document, ele, fp);
470 root.appendChild(ele);
471 //
472 // generate the output target
473 //
474 root.appendChild(document.createComment("output target"));
475 ele = document.createElement("target");
476 ele.setAttribute("name", "output");
477 applyOutputElement(document, ele, fp);
478 root.appendChild(ele);
479 //
480 // generate the clean target
481 //
482 root.appendChild(document.createComment("clean target"));
483 ele = document.createElement("target");
484 ele.setAttribute("name", "clean");
485 applyCleanElement(document, ele);
486 root.appendChild(ele);
487 //
488 // generate the Clean All target
489 //
490 root.appendChild(document.createComment("Clean All target"));
491 ele = document.createElement("target");
492 ele.setAttribute("name", "cleanall");
493 applyDeepcleanElement(document, ele);
494 root.appendChild(ele);
495 //
496 // add the root element to the document
497 //
498 document.appendChild(rootComment);
499 document.appendChild(root);
500 //
501 // Prepare the DOM document for writing
502 //
503 Source source = new DOMSource(document);
504 //
505 // Prepare the output file
506 //
507 File file = new File(getProject().getProperty("DEST_DIR_OUTPUT") + File.separatorChar + baseName
508 + "_build.xml");
509 //
510 // generate all directory path
511 //
512 (new File(file.getParent())).mkdirs();
513 Result result = new StreamResult(file);
514 //
515 // Write the DOM document to the file
516 //
517 Transformer xformer = TransformerFactory.newInstance().newTransformer();
518 xformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
519 xformer.setOutputProperty(OutputKeys.INDENT, "yes");
520 xformer.transform(source, result);
521 } catch (Exception ex) {
522 throw new BuildException("Module [" + baseName + "] generating build file failed.\n" + ex.getMessage());
523 }
524 }
525
526 /**
527 Generate the clean elements for BaseName_build.xml.
528
529 @param document current BaseName_build.xml XML document
530 @param root Root element for current
531 **/
532 private void applyCleanElement(Document document, Node root) {
533 String[] libinstances = libraries.toArray(new String[libraries.size()]);
534 for (int i = 0; i < libinstances.length; i++) {
535 File file = new File(GlobalData.getModulePath(libinstances[i]) + File.separatorChar + "build.xml");
536
537 Element ifEle = document.createElement("if");
538 Element availableEle = document.createElement("available");
539 availableEle.setAttribute("file", file.getPath());
540 ifEle.appendChild(availableEle);
541 Element elseEle = document.createElement("then");
542
543 Element ele = document.createElement("ant");
544 ele.setAttribute("antfile", file.getPath());
545 ele.setAttribute("inheritAll", "false");
546 ele.setAttribute("target", libinstances[i] + "_clean");
547 //
548 // Workspace_DIR
549 //
550 Element property = document.createElement("property");
551 property.setAttribute("name", "WORKSPACE_DIR");
552 property.setAttribute("value", "${WORKSPACE_DIR}");
553 ele.appendChild(property);
554 //
555 // Package Dir
556 //
557 property = document.createElement("property");
558 property.setAttribute("name", "PACKAGE_DIR");
559 property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar
560 + GlobalData.getPackagePathForModule(libinstances[i]));
561 ele.appendChild(property);
562 //
563 // ARCH
564 //
565 property = document.createElement("property");
566 property.setAttribute("name", "ARCH");
567 property.setAttribute("value", "${ARCH}");
568 ele.appendChild(property);
569 //
570 // TARGET
571 //
572 property = document.createElement("property");
573 property.setAttribute("name", "TARGET");
574 property.setAttribute("value", "${TARGET}");
575 ele.appendChild(property);
576 //
577 // PACKAGE
578 //
579 property = document.createElement("property");
580 property.setAttribute("name", "PACKAGE");
581 property.setAttribute("value", GlobalData.getPackageNameForModule(libinstances[i]));
582 ele.appendChild(property);
583
584 elseEle.appendChild(ele);
585 ifEle.appendChild(elseEle);
586 root.appendChild(ifEle);
587 }
588 }
589
590 /**
591 Generate the cleanall elements for BaseName_build.xml.
592
593 @param document current BaseName_build.xml XML document
594 @param root Root element for current
595 **/
596 private void applyDeepcleanElement(Document document, Node root) {
597 String[] libinstances = libraries.toArray(new String[libraries.size()]);
598 for (int i = 0; i < libinstances.length; i++) {
599 File file = new File(GlobalData.getModulePath(libinstances[i]) + File.separatorChar + "build.xml");
600
601 Element ifEle = document.createElement("if");
602 Element availableEle = document.createElement("available");
603 availableEle.setAttribute("file", file.getPath());
604 ifEle.appendChild(availableEle);
605 Element elseEle = document.createElement("then");
606
607 Element ele = document.createElement("ant");
608 ele.setAttribute("antfile", file.getPath());
609 ele.setAttribute("inheritAll", "false");
610 ele.setAttribute("target", libinstances[i] + "_cleanall");
611 //
612 // Workspace_DIR
613 //
614 Element property = document.createElement("property");
615 property.setAttribute("name", "WORKSPACE_DIR");
616 property.setAttribute("value", "${WORKSPACE_DIR}");
617 ele.appendChild(property);
618 //
619 // Package Dir
620 //
621 property = document.createElement("property");
622 property.setAttribute("name", "PACKAGE_DIR");
623 property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar
624 + GlobalData.getPackagePathForModule(libinstances[i]));
625 ele.appendChild(property);
626 //
627 // ARCH
628 //
629 property = document.createElement("property");
630 property.setAttribute("name", "ARCH");
631 property.setAttribute("value", "${ARCH}");
632 ele.appendChild(property);
633 //
634 // TARGET
635 //
636 property = document.createElement("property");
637 property.setAttribute("name", "TARGET");
638 property.setAttribute("value", "${TARGET}");
639 ele.appendChild(property);
640 //
641 // PACKAGE
642 //
643 property = document.createElement("property");
644 property.setAttribute("name", "PACKAGE");
645 property.setAttribute("value", GlobalData.getPackageNameForModule(libinstances[i]));
646 ele.appendChild(property);
647
648 elseEle.appendChild(ele);
649 ifEle.appendChild(elseEle);
650 root.appendChild(ifEle);
651 }
652 }
653
654 /**
655 Generate the dependent library instances elements for BaseName_build.xml.
656
657 @param document current BaseName_build.xml XML document
658 @param root Root element for current
659 **/
660 private void applyLibraryInstance(Document document, Node root) {
661 String[] libinstances = libraries.toArray(new String[libraries.size()]);
662 for (int i = 0; i < libinstances.length; i++) {
663 Element ele = document.createElement("ant");
664 File file = new File(GlobalData.getModulePath(libinstances[i]) + File.separatorChar + "build.xml");
665 ele.setAttribute("antfile", file.getPath());
666 ele.setAttribute("inheritAll", "false");
667 ele.setAttribute("target", libinstances[i]);
668 //
669 // Workspace_DIR
670 //
671 Element property = document.createElement("property");
672 property.setAttribute("name", "WORKSPACE_DIR");
673 property.setAttribute("value", "${WORKSPACE_DIR}");
674 ele.appendChild(property);
675 //
676 // Package Dir
677 //
678 property = document.createElement("property");
679 property.setAttribute("name", "PACKAGE_DIR");
680 property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar
681 + GlobalData.getPackagePathForModule(libinstances[i]));
682 ele.appendChild(property);
683 //
684 // ARCH
685 //
686 property = document.createElement("property");
687 property.setAttribute("name", "ARCH");
688 property.setAttribute("value", "${ARCH}");
689 ele.appendChild(property);
690 //
691 // TARGET
692 //
693 property = document.createElement("property");
694 property.setAttribute("name", "TARGET");
695 property.setAttribute("value", "${TARGET}");
696 ele.appendChild(property);
697 //
698 // PACKAGE
699 //
700 property = document.createElement("property");
701 property.setAttribute("name", "PACKAGE");
702 property.setAttribute("value", GlobalData.getPackageNameForModule(libinstances[i]));
703 ele.appendChild(property);
704 root.appendChild(ele);
705 }
706 Element expand = document.createElement("Expand");
707 root.appendChild(expand);
708 }
709
710 /**
711 Generate the build source files elements for BaseName_build.xml.
712
713 @param document current BaseName_build.xml XML document
714 @param root Root element for current
715 **/
716 private void applyCompileElement(Document document, Node root) {
717 FileProcess fileProcess = new FileProcess();
718 fileProcess.init(getProject(), includes, sourceFiles, document);
719 Node[] files = this.getSourceFiles();
720 //
721 // Parse all unicode files
722 //
723 for (int i = 0; i < files.length; i++) {
724 String filetype = getFiletype(files[i]);
725 if (filetype != null) {
726 fileProcess.parseFile(getFilename(files[i]), filetype, root, true);
727 } else {
728 fileProcess.parseFile(getFilename(files[i]), root, true);
729 }
730 }
731 if (fileProcess.isUnicodeExist()) {
732 Element ele = document.createElement("Build_Unicode_Database");
733 ele.setAttribute("FILEPATH", ".");
734 ele.setAttribute("FILENAME", "${BASE_NAME}");
735 root.appendChild(ele);
736 }
737
738 //
739 // Parse AutoGen.c & AutoGen.h
740 //
741 if (!baseName.equalsIgnoreCase("Shell")) {
742 fileProcess.parseFile(getProject().getProperty("DEST_DIR_DEBUG") + File.separatorChar + "AutoGen.c", root,
743 false);
744 }
745 //
746 // Parse all source files
747 //
748 for (int i = 0; i < files.length; i++) {
749 String filetype = getFiletype(files[i]);
750 if (filetype != null) {
751 fileProcess.parseFile(getFilename(files[i]), filetype, root, false);
752 } else {
753 fileProcess.parseFile(getFilename(files[i]), root, false);
754 }
755 }
756 //
757 // root.appendChild(parallelEle);
758 //
759 Iterator iter = sourceFiles.iterator();
760 String str = "";
761 while (iter.hasNext()) {
762 str += " " + (String) iter.next();
763 }
764 getProject().setProperty("SOURCE_FILES", str);
765 }
766
767 /**
768 Generate the section elements for BaseName_build.xml. Library module will
769 skip this process.
770
771 @param document current BaseName_build.xml XML document
772 @param root Root element for current
773 **/
774 private void applySectionsElement(Document document, Node root, FfsProcess fp) {
775 if (fp.initSections(buildType, getProject())) {
776 String targetFilename = guid + "-" + baseName + FpdParserTask.getSuffix(componentType);
777 String[] list = fp.getGenSectionElements(document, baseName, guid, targetFilename);
778
779 for (int i = 0; i < list.length; i++) {
780 Element ele = document.createElement(list[i]);
781 ele.setAttribute("FILEPATH", ".");
782 ele.setAttribute("FILENAME", "${BASE_NAME}");
783 root.appendChild(ele);
784 }
785 }
786 }
787
788 /**
789 Generate the output elements for BaseName_build.xml. If module is library,
790 call the <em>LIB</em> command, else call the <em>GenFfs</em> command.
791
792 @param document current BaseName_build.xml XML document
793 @param root Root element for current
794 **/
795 private void applyOutputElement(Document document, Node root, FfsProcess fp) {
796 if (flag == GlobalData.ONLY_LIBMSA || flag == GlobalData.LIBMSA_AND_LIBMBD) {
797 //
798 // call Lib command
799 //
800 Element cc = document.createElement("Build_Library");
801 cc.setAttribute("FILENAME", baseName);
802 root.appendChild(cc);
803 }
804 //
805 // if it is a module but library
806 //
807 else {
808 if (fp.getFfsNode() != null) {
809 root.appendChild(fp.getFfsNode());
810 }
811 }
812 }
813
814 /**
815 Get file name from node. If some wrong, return string with zero length.
816
817 @param node Filename node of MSA/MBD or specified in each Section
818 @return File name
819 **/
820 private String getFilename(Node node) {
821 String path = null;
822 String filename = "${MODULE_DIR}" + File.separatorChar;
823 String str = "";
824 try {
825 FilenameDocument file = (FilenameDocument) XmlObject.Factory.parse(node);
826 str = file.getFilename().getStringValue().trim();
827 path = file.getFilename().getPath();
828 } catch (Exception e) {
829 str = "";
830 }
831 if (path != null) {
832 filename += path + File.separatorChar + str;
833 } else {
834 filename += str;
835 }
836 return getProject().replaceProperties(filename);
837 }
838
839 /**
840 Get file type from node. If some wrong or not specified, return
841 <code>null</code>.
842
843 @param node Filename node of MSA/MBD or specified in each Section
844 @return File type
845 **/
846 private String getFiletype(Node node) {
847 String str = null;
848 try {
849 FilenameDocument file = (FilenameDocument) XmlObject.Factory.parse(node);
850 str = file.getFilename().getFileType();
851 } catch (Exception e) {
852 str = null;
853 }
854 return str;
855 }
856
857 /**
858 Return all source files but AutoGen.c.
859
860 @return source files Node array
861 **/
862 public Node[] getSourceFiles() {
863 XmlObject[] files = SurfaceAreaQuery.getSourceFiles(arch);
864 if (files == null) {
865 return new Node[0];
866 }
867 Vector<Node> vector = new Vector<Node>();
868 for (int i = 0; i < files.length; i++) {
869 vector.addElement(files[i].getDomNode());
870 }
871 //
872 // To be consider sourcefiles from Sections
873 //
874 return vector.toArray(new Node[vector.size()]);
875 }
876
877 /**
878 Get current module's base name.
879
880 @return base name
881 **/
882 public String getBaseName() {
883 return baseName;
884 }
885
886 /**
887 Set MBD surface area file. For ANT use.
888
889 @param mbdFilename Surface Area file
890 **/
891 public void setMbdFilename(File mbdFilename) {
892 this.mbdFilename = mbdFilename;
893 }
894
895 /**
896 Set MSA surface area file. For ANT use.
897
898 @param msaFilename Surface Area file
899 **/
900 public void setMsaFilename(File msaFilename) {
901 this.msaFilename = msaFilename;
902 }
903
904 /**
905 Compile flags setup.
906
907 <p> Take command <code>CC</code> and arch <code>IA32</code> for example,
908 Those flags are from <code>ToolChainFactory</code>: </p>
909 <ul>
910 <li> IA32_CC </li>
911 <li> IA32_CC_STD_FLAGS </li>
912 <li> IA32_CC_GLOBAL_FLAGS </li>
913 <li> IA32_CC_GLOBAL_ADD_FLAGS </li>
914 <li> IA32_CC_GLOBAL_SUB_FLAGS </li>
915 </ul>
916 Those flags can user-define:
917 <ul>
918 <li> IA32_CC_PROJ_FLAGS </li>
919 <li> IA32_CC_PROJ_ADD_FLAGS </li>
920 <li> IA32_CC_PROJ_SUB_FLAGS </li>
921 <li> CC_PROJ_FLAGS </li>
922 <li> CC_PROJ_ADD_FLAGS </li>
923 <li> CC_PROJ_SUB_FLAGS </li>
924 <li> CC_FLAGS </li>
925 <li> IA32_CC_FLAGS </li>
926 </ul>
927
928 <p> The final flags is composed of STD, GLOBAL and PROJ. If CC_FLAGS or
929 IA32_CC_FLAGS is specified, STD, GLOBAL and PROJ will not affect. </p>
930
931 Note that the <code>ToolChainFactory</code> executes only once
932 during whole build process.
933 **/
934 private void flagsSetup() {
935 Project project = getProject();
936 //
937 // If ToolChain has been set up before, do nothing.
938 //
939 ToolChainFactory toolChainFactory = new ToolChainFactory(project);
940 toolChainFactory.setupToolChain();
941
942 String[] cmd = ToolChainFactory.commandType;
943 Set<String> addSet = new HashSet<String>(40);
944 Set<String> subSet = new HashSet<String>(40);
945 for (int i = 0; i < cmd.length; i++) {
946 String str = ToolChainFactory.getValue(arch + "_" + cmd[i]);
947 //
948 // Command line path+command name
949 //
950 if (str != null) {
951 project.setProperty(cmd[i], str);
952 }
953 //
954 // ARCH_CMD_STD_FLAGS
955 //
956 str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_STD_FLAGS");
957 if (str != null) {
958 putFlagsToSet(addSet, str);
959 project.setProperty(cmd[i] + "_STD_FLAGS", str);
960 }
961 //
962 // ARCH_CMD_GLOBAL_FLAGS
963 //
964 str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_GLOBAL_FLAGS");
965 if (str != null) {
966 putFlagsToSet(addSet, str);
967 }
968 //
969 // ARCH_CMD_GLOBAL_ADD_FLAGS
970 //
971 str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_GLOBAL_ADD_FLAGS");
972 if (str != null) {
973 putFlagsToSet(addSet, str);
974 }
975 //
976 // ARCH_CMD_GLOBAL_SUB_FLAGS
977 //
978 str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_GLOBAL_SUB_FLAGS");
979 if (str != null) {
980 putFlagsToSet(subSet, str);
981 }
982 //
983 // ARCH_CMD_PROJ_FLAGS
984 //
985 str = project.getProperty(arch + "_" + cmd[i] + "_PROJ_FLAGS");
986 if (str != null) {
987 putFlagsToSet(addSet, str);
988 }
989 //
990 // ARCH_CMD_PROG_FLAGS
991 //
992 str = project.getProperty(arch + "_" + cmd[i] + "_PROJ_ADD_FLAGS");
993 if (str != null) {
994 putFlagsToSet(addSet, str);
995 }
996 //
997 // ARCH_CMD_PROG_FLAGS
998 //
999 str = project.getProperty(arch + "_" + cmd[i] + "_PROJ_SUB_FLAGS");
1000 if (str != null) {
1001 putFlagsToSet(subSet, str);
1002 }
1003 //
1004 // CMD_PROJ_FLAGS
1005 //
1006 str = project.getProperty(cmd[i] + "_PROJ_FLAGS");
1007 if (str != null) {
1008 putFlagsToSet(addSet, str);
1009 }
1010 //
1011 // CMD_PROG_FLAGS
1012 //
1013 str = project.getProperty(cmd[i] + "_PROJ_ADD_FLAGS");
1014 if (str != null) {
1015 putFlagsToSet(addSet, str);
1016 }
1017 //
1018 // CMD_PROG_FLAGS
1019 //
1020 str = project.getProperty(cmd[i] + "_PROJ_SUB_FLAGS");
1021 if (str != null) {
1022 putFlagsToSet(subSet, str);
1023 }
1024 //
1025 // If IA32_CC_FLAGS or IA32_LIB_FLAGS .. has defined in BuildOptions
1026 //
1027 if ((str = project.getProperty(arch + "_" + cmd[i] + "_FLAGS")) != null) {
1028 project.setProperty(cmd[i] + "_FLAGS", getRawFlags(addSet, subSet));
1029 addSet.clear();
1030 subSet.clear();
1031 putFlagsToSet(addSet, project.replaceProperties(str));
1032 project.setProperty(cmd[i] + "_FLAGS", project.replaceProperties(getFlags(addSet, subSet)));
1033 addSet.clear();
1034 subSet.clear();
1035 }
1036 //
1037 // If CC_FLAGS or LIB_FLAGS .. has defined in BuildOptions
1038 //
1039 else if ((str = project.getProperty(cmd[i] + "_FLAGS")) != null) {
1040 project.setProperty(cmd[i] + "_FLAGS", getRawFlags(addSet, subSet));
1041 addSet.clear();
1042 subSet.clear();
1043 putFlagsToSet(addSet, project.replaceProperties(str));
1044 project.setProperty(cmd[i] + "_FLAGS", project.replaceProperties(getFlags(addSet, subSet)));
1045 addSet.clear();
1046 subSet.clear();
1047 } else {
1048 project.setProperty(cmd[i] + "_FLAGS", getFlags(addSet, subSet));
1049 addSet.clear();
1050 subSet.clear();
1051 }
1052 }
1053 project.setProperty("C_FLAGS", project.getProperty("CC_FLAGS"));
1054 }
1055
1056 /**
1057 Initialize some properties will be used in current module build, including
1058 user-defined option from <em>Option</em> of <em>BuildOptions</em> in
1059 surface area.
1060 **/
1061 private void updateParameters() {
1062 getProject().setProperty("OBJECTS", "");
1063 getProject().setProperty("SDB_FILES", "");
1064 getProject().setProperty("BASE_NAME", baseName);
1065 if (map.get("MsaHeader") != null) {
1066 guid = SurfaceAreaQuery.getModuleGuid();//header.getGuid().getStringValue();
1067 componentType = SurfaceAreaQuery.getComponentType();//header.getComponentType().toString();
1068 if (!componentType.equalsIgnoreCase("LIBRARY")) {
1069 flag = GlobalData.MSA_AND_MBD;
1070 } else {
1071 flag = GlobalData.LIBMSA_AND_LIBMBD;
1072 }
1073 }
1074
1075 else if (map.get("MsaLibHeader") != null) {
1076 flag = GlobalData.LIBMSA_AND_LIBMBD;
1077 MsaLibHeaderDocument.MsaLibHeader header = ((MsaLibHeaderDocument) map.get("MsaLibHeader"))
1078 .getMsaLibHeader();
1079 guid = header.getGuid().getStringValue();
1080 componentType = header.getComponentType().toString();
1081 }
1082
1083 if (componentType != null) {
1084 getProject().setProperty("COMPONENT_TYPE", componentType);
1085 }
1086
1087 if (guid != null) {
1088 getProject().setProperty("FILE_GUID", guid);
1089 }
1090 //
1091 // Get all options and set to properties
1092 //
1093 String[][] options = SurfaceAreaQuery.getOptions(arch);
1094 for (int i = 0; i < options.length; i++) {
1095 if (options[i][0] != null && options[i][1] != null) {
1096 getProject().setProperty(options[i][0], getProject().replaceProperties(options[i][1]));
1097 }
1098 }
1099
1100 buildType = getProject().getProperty("BUILD_TYPE");
1101 if (buildType == null) {
1102 buildType = componentType;
1103 }
1104
1105 }
1106
1107 /**
1108 Separate the string and instore in set.
1109
1110 <p> String is separated by Java Regulation Expression
1111 "[^\\\\]?(\".*?[^\\\\]\")[ \t,]+". </p>
1112
1113 <p>For example: </p>
1114
1115 <pre>
1116 "/nologo", "/W3", "/WX"
1117 "/C", "/DSTRING_DEFINES_FILE=\"BdsStrDefs.h\""
1118 </pre>
1119
1120 @param set store the separated string
1121 @param str string to separate
1122 **/
1123 private void putFlagsToSet(Set<String> set, String str) {
1124 Pattern myPattern = Pattern.compile("[^\\\\]?(\".*?[^\\\\]\")[ \t,]+");
1125 Matcher matcher = myPattern.matcher(str + " ");
1126 while (matcher.find()) {
1127 String item = str.substring(matcher.start(1), matcher.end(1));
1128 if (!set.contains(item)) {
1129 set.add(item);
1130 }
1131 }
1132 }
1133
1134 /**
1135 Generate the final flags string will be used by compile command.
1136
1137 @param add the add flags set
1138 @param sub the sub flags set
1139 @return final flags after add set substract sub set
1140 **/
1141 private String getFlags(Set<String> add, Set<String> sub) {
1142 String result = "";
1143 add.removeAll(sub);
1144 Iterator iter = add.iterator();
1145 while (iter.hasNext()) {
1146 String str = getProject().replaceProperties((String) iter.next());
1147 result += str.substring(1, str.length() - 1) + " ";
1148 }
1149 return result;
1150 }
1151
1152 /**
1153 Generate the flags string with original format. The format is defined by
1154 Java Regulation Expression "[^\\\\]?(\".*?[^\\\\]\")[ \t,]+". </p>
1155
1156 <p>For example: </p>
1157
1158 <pre>
1159 "/nologo", "/W3", "/WX"
1160 "/C", "/DSTRING_DEFINES_FILE=\"BdsStrDefs.h\""
1161 </pre>
1162
1163 @param add the add flags set
1164 @param sub the sub flags set
1165 @return flags with original format
1166 **/
1167 private String getRawFlags(Set<String> add, Set<String> sub) {
1168 String result = "";
1169 add.removeAll(sub);
1170 Iterator iter = add.iterator();
1171 while (iter.hasNext()) {
1172 String str = getProject().replaceProperties((String) iter.next());
1173 result += "\"" + str.substring(1, str.length() - 1) + "\", ";
1174 }
1175 return result;
1176 }
1177
1178 /**
1179 Set base name. For ANT use.
1180
1181 @param baseName Base name
1182 **/
1183 public void setBaseName(String baseName) {
1184 this.baseName = baseName;
1185 }
1186
1187 }