Fixed the issue in multi-msa build in single mode; cleaned the code of re-ordering...
[mirror_edk2.git] / Tools / Java / Source / GenBuild / org / tianocore / build / fpd / FpdParserTask.java
1 /** @file
2 This file is ANT task FpdParserTask.
3
4 FpdParserTask is used to parse FPD (Framework Platform Description) and generate
5 build.out.xml. It is for Package or Platform build use.
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.fpd;
17
18 import java.io.BufferedWriter;
19 import java.io.File;
20 import java.io.FileWriter;
21 import java.io.IOException;
22 import java.util.HashMap;
23 import java.util.Iterator;
24 import java.util.LinkedHashMap;
25 import java.util.LinkedHashSet;
26 import java.util.Map;
27 import java.util.Set;
28 import java.util.Vector;
29
30 import org.apache.tools.ant.BuildException;
31 import org.apache.tools.ant.Task;
32 import org.apache.tools.ant.taskdefs.Ant;
33 import org.apache.tools.ant.taskdefs.Property;
34 import org.apache.xmlbeans.XmlException;
35 import org.apache.xmlbeans.XmlObject;
36
37 import org.tianocore.common.definitions.EdkDefinitions;
38 import org.tianocore.common.definitions.ToolDefinitions;
39 import org.tianocore.common.exception.EdkException;
40 import org.tianocore.common.logger.EdkLog;
41 import org.tianocore.build.FrameworkBuildTask;
42 import org.tianocore.build.global.GlobalData;
43 import org.tianocore.build.global.OutputManager;
44 import org.tianocore.build.global.SurfaceAreaQuery;
45 import org.tianocore.build.id.FpdModuleIdentification;
46 import org.tianocore.build.id.ModuleIdentification;
47 import org.tianocore.build.id.PackageIdentification;
48 import org.tianocore.build.id.PlatformIdentification;
49 import org.tianocore.build.pcd.action.PlatformPcdPreprocessActionForBuilding;
50 import org.tianocore.build.toolchain.ToolChainElement;
51 import org.tianocore.build.toolchain.ToolChainMap;
52 import org.tianocore.build.toolchain.ToolChainInfo;
53 import org.w3c.dom.NamedNodeMap;
54 import org.w3c.dom.Node;
55 import org.w3c.dom.NodeList;
56
57 /**
58 <code>FpdParserTask</code> is an ANT task. The main function is parsing Framework
59 Platform Descritpion (FPD) XML file and generating its ANT build script for
60 corresponding platform.
61
62 <p>The task sets global properties PLATFORM, PLATFORM_DIR, PLATFORM_RELATIVE_DIR
63 and BUILD_DIR. </p>
64
65 <p>The task generates ${PLATFORM}_build.xml file which will be called by top level
66 build.xml. The task also generate Fv.inf files (File is for Tool GenFvImage). </p>
67
68 <p>FpdParserTask task stores all FPD information to GlobalData. And parse
69 tools definition file to set up compiler options for different Target and
70 different ToolChainTag. </p>
71
72 <p>The method parseFpdFile is also prepared for single module build. </p>
73
74 @since GenBuild 1.0
75 **/
76 public class FpdParserTask extends Task {
77
78 ///
79 /// Be used to ensure Global data will be initialized only once.
80 ///
81 private static boolean parsed = false;
82
83 private File fpdFile = null;
84
85 PlatformIdentification platformId;
86
87 private String type;
88
89 ///
90 /// Mapping from modules identification to out put file name
91 ///
92 Map<FpdModuleIdentification, String> outfiles = new LinkedHashMap<FpdModuleIdentification, String>();
93
94 ///
95 /// Mapping from FV name to its modules
96 ///
97 Map<String, Set<FpdModuleIdentification>> fvs = new HashMap<String, Set<FpdModuleIdentification>>();
98
99 ///
100 /// Mapping from FV apriori file to its type (PEI or DXE)
101 ///
102 Map<String, String> aprioriType = new HashMap<String, String>();
103
104 ///
105 /// FpdParserTask can specify some ANT properties.
106 ///
107 private Vector<Property> properties = new Vector<Property>();
108
109 SurfaceAreaQuery saq = null;
110
111 boolean isUnified = true;
112
113 public static String PEI_APRIORI_GUID = "1b45cc0a-156a-428a-af62-49864da0e6e6";
114
115 public static String DXE_APRIORI_GUID = "fc510ee7-ffdc-11d4-bd41-0080c73c8881";
116
117 /**
118 Public construct method. It is necessary for ANT task.
119 **/
120 public FpdParserTask() {
121 }
122
123 /**
124 ANT task's entry method. The main steps is described as following:
125
126 <ul>
127 <li>Initialize global information (Framework DB, SPD files and all MSA files
128 listed in SPD). This step will execute only once in whole build process;</li>
129 <li>Parse specified FPD file; </li>
130 <li>Generate FV.inf files; </li>
131 <li>Generate PlatformName_build.xml file for Flatform build; </li>
132 <li>Collect PCD information. </li>
133 </ul>
134
135 @throws BuildException
136 Surface area is not valid.
137 **/
138 public void execute() throws BuildException {
139 this.setTaskName("FpdParser");
140
141 //
142 // Parse FPD file
143 //
144 parseFpdFile();
145
146 //
147 // Prepare BUILD_DIR
148 //
149 isUnified = OutputManager.getInstance().prepareBuildDir(getProject());
150
151 String buildDir = getProject().getProperty("BUILD_DIR");
152 //
153 // For every Target and ToolChain
154 //
155 String[] targetList = GlobalData.getToolChainInfo().getTargets();
156 for (int i = 0; i < targetList.length; i++) {
157 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();
158 for(int j = 0; j < toolchainList.length; j++) {
159 //
160 // Prepare FV_DIR
161 //
162 String ffsCommonDir = buildDir + File.separatorChar
163 + targetList[i] + "_"
164 + toolchainList[j];
165 File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");
166 fvDir.mkdirs();
167 getProject().setProperty("FV_DIR", fvDir.getPath().replaceAll("(\\\\)", "/"));
168
169 //
170 // Gen Fv.inf files
171 //
172 genFvInfFiles(ffsCommonDir);
173 }
174 }
175
176 //
177 // Gen build.xml
178 //
179 String platformBuildFile = buildDir + File.separatorChar + platformId.getName() + "_build.xml";
180 PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, isUnified, saq, platformBuildFile, aprioriType);
181 fileGenerator.genBuildFile();
182
183 //
184 // Ant call ${PLATFORM}_build.xml
185 //
186 Ant ant = new Ant();
187 ant.setProject(getProject());
188 ant.setAntfile(platformBuildFile);
189 ant.setTarget(type);
190 ant.setInheritAll(true);
191 ant.init();
192 ant.execute();
193 }
194
195 /**
196 Generate Fv.inf files. The Fv.inf file is composed with four
197 parts: Options, Attributes, Components and Files. The Fv.inf files
198 will be under FV_DIR.
199
200 @throws BuildException
201 File write FV.inf files error.
202 **/
203 void genFvInfFiles(String ffsCommonDir) throws BuildException {
204 String[] validFv = saq.getFpdValidImageNames();
205 for (int i = 0; i < validFv.length; i++) {
206 //
207 // Get all global variables from FPD and set them to properties
208 //
209 String[][] globalVariables = saq.getFpdGlobalVariable();
210 for (int j = 0; j < globalVariables.length; j++) {
211 getProject().setProperty(globalVariables[j][0], globalVariables[j][1]);
212 }
213
214 getProject().setProperty("FV_FILENAME", validFv[i]);
215
216 File fvFile = new File(getProject().replaceProperties( getProject().getProperty("FV_DIR") + File.separatorChar + validFv[i] + ".inf"));
217 if (fvFile.exists() && (fvFile.lastModified() >= fpdFile.lastModified())) {
218 //
219 // don't re-generate FV.inf if fpd has not been changed
220 //
221 continue;
222 }
223 fvFile.getParentFile().mkdirs();
224
225 try {
226 FileWriter fw = new FileWriter(fvFile);
227 BufferedWriter bw = new BufferedWriter(fw);
228
229 //
230 // Options
231 //
232 String[][] options = saq.getFpdOptions(validFv[i]);
233 if (options.length > 0) {
234 bw.write("[options]");
235 bw.newLine();
236 for (int j = 0; j < options.length; j++) {
237 StringBuffer str = new StringBuffer(100);
238 str.append(options[j][0]);
239 while (str.length() < 40) {
240 str.append(' ');
241 }
242 str.append("= ");
243 str.append(options[j][1]);
244 bw.write(getProject().replaceProperties(str.toString()));
245 bw.newLine();
246 }
247 bw.newLine();
248 }
249
250 //
251 // Attributes;
252 //
253 String[][] attributes = saq.getFpdAttributes(validFv[i]);
254 if (attributes.length > 0) {
255 bw.write("[attributes]");
256 bw.newLine();
257 for (int j = 0; j < attributes.length; j++) {
258 StringBuffer str = new StringBuffer(100);
259 str.append(attributes[j][0]);
260 while (str.length() < 40) {
261 str.append(' ');
262 }
263 str.append("= ");
264 str.append(attributes[j][1]);
265 bw.write(getProject().replaceProperties(str.toString()));
266 bw.newLine();
267 }
268 bw.newLine();
269 }
270
271 //
272 // Components
273 //
274 String[][] components = saq.getFpdComponents(validFv[i]);
275 if (components.length > 0) {
276 bw.write("[components]");
277 bw.newLine();
278 for (int j = 0; j < components.length; j++) {
279 StringBuffer str = new StringBuffer(100);
280 str.append(components[j][0]);
281 while (str.length() < 40) {
282 str.append(' ');
283 }
284 str.append("= ");
285 str.append(components[j][1]);
286 bw.write(getProject().replaceProperties(str.toString()));
287 bw.newLine();
288 }
289 bw.newLine();
290 }
291
292 //
293 // Files
294 //
295 Set<FpdModuleIdentification> moduleSeqSet = getModuleSequenceForFv(validFv[i]);
296
297 Set<FpdModuleIdentification> filesSet = fvs.get(validFv[i]);
298
299 FpdModuleIdentification[] files = null;
300
301 if (moduleSeqSet == null) {
302 if (filesSet != null) {
303 files = filesSet.toArray(new FpdModuleIdentification[filesSet.size()]);
304 }
305 } else if (filesSet == null) {
306 if (moduleSeqSet.size() != 0) {
307 throw new BuildException("Can not find any modules belongs to FV[" + validFv[i] + "], but listed some in BuildOptions.UserExtensions[@UserID='IMAGES' @Identifier='1']");
308 }
309 } else {
310 //
311 // if moduleSeqSet and filesSet is inconsistent, report error
312 //
313 if(moduleSeqSet.size() != filesSet.size()){
314 throw new BuildException("Modules for FV[" + validFv[i] + "] defined in FrameworkModules and in BuildOptions.UserExtensions[@UserID='IMAGES' @Identifier='1'] are inconsistent. ");
315 } else {
316 //
317 // whether all modules in moduleSeqSet listed in filesSet
318 //
319 Iterator<FpdModuleIdentification> iter = moduleSeqSet.iterator();
320 while (iter.hasNext()) {
321 FpdModuleIdentification item = iter.next();
322 if (!filesSet.contains(item)) {
323 throw new BuildException("Can not find " + item + " belongs to FV[" + validFv[i] + "]");
324 }
325 }
326 }
327
328 files = moduleSeqSet.toArray(new FpdModuleIdentification[moduleSeqSet.size()]);
329 }
330
331
332 if (files != null) {
333 bw.write("[files]");
334 bw.newLine();
335
336 Set<FpdModuleIdentification> modules = null;
337
338 if ( (modules = getPeiApriori(validFv[i])) != null) {
339 //
340 // Special GUID - validFv[i].FFS
341 //
342 String str = ffsCommonDir + File.separatorChar + "FV" + File.separatorChar + PEI_APRIORI_GUID + "-" + validFv[i] + ".FFS";
343 bw.write(getProject().replaceProperties("EFI_FILE_NAME = " + str));
344 bw.newLine();
345
346 File aprioriFile = new File(getProject().getProperty("FV_DIR") + File.separatorChar + validFv[i] + ".apr");
347 aprioriType.put(validFv[i], PEI_APRIORI_GUID);
348 genAprioriFile(modules, aprioriFile);
349 } else if((modules = getDxeApriori(validFv[i])) != null) {
350 //
351 // Special GUID - validFv[i].FFS
352 //
353 String str = ffsCommonDir + File.separatorChar + "FV" + File.separatorChar + DXE_APRIORI_GUID + "-" + validFv[i] + ".FFS";
354 bw.write(getProject().replaceProperties("EFI_FILE_NAME = " + str));
355 bw.newLine();
356
357 File aprioriFile = new File(getProject().getProperty("FV_DIR") + File.separatorChar + validFv[i] + ".apr");
358 aprioriType.put(validFv[i], DXE_APRIORI_GUID);
359 genAprioriFile(modules, aprioriFile);
360 }
361
362 for (int j = 0; j < files.length; j++) {
363 String str = ffsCommonDir + File.separatorChar + outfiles.get(files[j]);
364 bw.write(getProject().replaceProperties("EFI_FILE_NAME = " + str));
365 bw.newLine();
366 }
367 }
368 bw.flush();
369 bw.close();
370 fw.close();
371 } catch (IOException ex) {
372 BuildException buildException = new BuildException("Generation of the FV file [" + fvFile.getPath() + "] failed!\n" + ex.getMessage());
373 buildException.setStackTrace(ex.getStackTrace());
374 throw buildException;
375 } catch (EdkException ex) {
376 BuildException buildException = new BuildException("Generation of the FV file [" + fvFile.getPath() + "] failed!\n" + ex.getMessage());
377 buildException.setStackTrace(ex.getStackTrace());
378 throw buildException;
379 }
380 }
381 }
382
383 /**
384 This method is used for Single Module Build.
385
386 @throws BuildException
387 FPD file is not valid.
388 **/
389 public void parseFpdFile(File fpdFile) throws BuildException, EdkException {
390 this.fpdFile = fpdFile;
391 parseFpdFile();
392
393 //
394 // Call Platform_build.xml prebuild firstly in stand-alone build
395 // Prepare BUILD_DIR
396 //
397 isUnified = OutputManager.getInstance().prepareBuildDir(getProject());
398
399 String buildDir = getProject().getProperty("BUILD_DIR");
400 //
401 // For every Target and ToolChain
402 //
403 String[] targetList = GlobalData.getToolChainInfo().getTargets();
404 for (int i = 0; i < targetList.length; i++) {
405 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();
406 for(int j = 0; j < toolchainList.length; j++) {
407 //
408 // Prepare FV_DIR
409 //
410 String ffsCommonDir = buildDir + File.separatorChar
411 + targetList[i] + "_"
412 + toolchainList[j];
413 File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");
414 fvDir.mkdirs();
415 }
416 }
417
418 String platformBuildFile = buildDir + File.separatorChar + platformId.getName() + "_build.xml";
419 PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, isUnified, saq, platformBuildFile, aprioriType);
420 fileGenerator.genBuildFile();
421
422 Ant ant = new Ant();
423 ant.setProject(getProject());
424 ant.setAntfile(platformBuildFile);
425 ant.setTarget("prebuild");
426 ant.setInheritAll(true);
427 ant.init();
428 ant.execute();
429 }
430
431 /**
432 Parse FPD file.
433
434 @throws BuildException
435 FPD file is not valid.
436 **/
437 void parseFpdFile() throws BuildException {
438 try {
439 XmlObject doc = XmlObject.Factory.parse(fpdFile);
440
441 if (!doc.validate()) {
442 throw new BuildException("Platform Surface Area file [" + fpdFile.getPath() + "] format is invalid!");
443 }
444
445 Map<String, XmlObject> map = new HashMap<String, XmlObject>();
446 map.put("PlatformSurfaceArea", doc);
447 saq = new SurfaceAreaQuery(map);
448
449 //
450 // Initialize
451 //
452 platformId = saq.getFpdHeader();
453 platformId.setFpdFile(fpdFile);
454 getProject().setProperty("PLATFORM", platformId.getName());
455 getProject().setProperty("PLATFORM_FILE", platformId.getRelativeFpdFile().replaceAll("(\\\\)", "/"));
456 getProject().setProperty("PLATFORM_DIR", platformId.getFpdFile().getParent().replaceAll("(\\\\)", "/"));
457 getProject().setProperty("PLATFORM_RELATIVE_DIR", platformId.getPlatformRelativeDir().replaceAll("(\\\\)", "/"));
458
459 if( !FrameworkBuildTask.multithread) {
460 FrameworkBuildTask.originalProperties.put("PLATFORM", platformId.getName());
461 FrameworkBuildTask.originalProperties.put("PLATFORM_FILE", platformId.getRelativeFpdFile().replaceAll("(\\\\)", "/"));
462 FrameworkBuildTask.originalProperties.put("PLATFORM_DIR", platformId.getFpdFile().getParent().replaceAll("(\\\\)", "/"));
463 FrameworkBuildTask.originalProperties.put("PLATFORM_RELATIVE_DIR", platformId.getPlatformRelativeDir().replaceAll("(\\\\)", "/"));
464 }
465
466 //
467 // Build mode. User-defined output dir.
468 //
469 String buildMode = saq.getFpdIntermediateDirectories();
470 String userDefinedOutputDir = saq.getFpdOutputDirectory();
471
472 OutputManager.getInstance().setup(userDefinedOutputDir, buildMode);
473
474 //
475 // TBD. Deal PCD and BuildOption related Info
476 //
477 GlobalData.setFpdBuildOptions(saq.getFpdBuildOptions());
478
479 GlobalData.setToolChainPlatformInfo(saq.getFpdToolChainInfo());
480
481 //
482 // Parse all list modules SA
483 //
484 parseModuleSAFiles();
485
486 //
487 // TBD. Deal PCD and BuildOption related Info
488 //
489 parseToolChainFamilyOptions();
490 parseToolChainOptions();
491
492 //
493 // check if the tool chain is valid or not
494 //
495 checkToolChain();
496
497 saq.push(map);
498
499 //
500 // Pcd Collection. Call CollectPCDAction to collect pcd info.
501 //
502 if (!parsed) {
503 PlatformPcdPreprocessActionForBuilding ca = new PlatformPcdPreprocessActionForBuilding();
504 ca.perform(platformId.getFpdFile().getPath());
505 }
506 } catch (IOException ex) {
507 BuildException buildException = new BuildException("Parsing of the FPD file [" + fpdFile.getPath() + "] failed!\n" + ex.getMessage());
508 buildException.setStackTrace(ex.getStackTrace());
509 throw buildException;
510 } catch (XmlException ex) {
511 BuildException buildException = new BuildException("Parsing of the FPD file [" + fpdFile.getPath() + "] failed!\n" + ex.getMessage());
512 buildException.setStackTrace(ex.getStackTrace());
513 throw buildException;
514 } catch (EdkException ex) {
515 BuildException buildException = new BuildException("Parsing of the FPD file [" + fpdFile.getPath() + "] failed!\n" + ex.getMessage());
516 buildException.setStackTrace(ex.getStackTrace());
517 throw buildException;
518 }
519 if (!parsed) {
520 parsed = true;
521 }
522 }
523
524 /**
525 Parse all modules listed in FPD file.
526 **/
527 void parseModuleSAFiles() throws EdkException{
528 Map<FpdModuleIdentification, Map<String, XmlObject>> moduleSAs = saq.getFpdModules();
529
530 //
531 // For every Module lists in FPD file.
532 //
533 Set<FpdModuleIdentification> keys = moduleSAs.keySet();
534 Iterator iter = keys.iterator();
535 while (iter.hasNext()) {
536 FpdModuleIdentification fpdModuleId = (FpdModuleIdentification) iter.next();
537
538 //
539 // Judge if Module is existed?
540 // TBD
541 GlobalData.registerFpdModuleSA(fpdModuleId, moduleSAs.get(fpdModuleId));
542
543 //
544 // Put fpdModuleId to the corresponding FV
545 //
546 saq.push(GlobalData.getDoc(fpdModuleId));
547 String fvBinding = saq.getModuleFvBindingKeyword();
548
549 fpdModuleId.setFvBinding(fvBinding);
550 updateFvs(fvBinding, fpdModuleId);
551
552 //
553 // Prepare for out put file name
554 //
555 ModuleIdentification moduleId = fpdModuleId.getModule();
556
557 String baseName = saq.getModuleOutputFileBasename();
558
559 if (baseName == null) {
560 baseName = moduleId.getName();
561 }
562 outfiles.put(fpdModuleId, fpdModuleId.getArch() + File.separatorChar
563 + moduleId.getGuid() + "-" + baseName
564 + getSuffix(moduleId.getModuleType()));
565
566 //
567 // parse module build options, if any
568 //
569 GlobalData.addModuleToolChainOption(fpdModuleId, parseModuleBuildOptions(false));
570 GlobalData.addModuleToolChainFamilyOption(fpdModuleId, parseModuleBuildOptions(true));
571
572 //
573 // parse MSA build options
574 //
575 GlobalData.addMsaBuildOption(moduleId, parseMsaBuildOptions(false));
576 GlobalData.addMsaFamilyBuildOption(moduleId, parseMsaBuildOptions(true));
577
578 ModuleIdentification[] libraryInstances = saq.getLibraryInstance(null);
579 for (int i = 0; i < libraryInstances.length; i++) {
580 saq.push(GlobalData.getDoc(libraryInstances[i], fpdModuleId.getArch()));
581 GlobalData.addMsaBuildOption(libraryInstances[i], parseMsaBuildOptions(false));
582 GlobalData.addMsaFamilyBuildOption(libraryInstances[i], parseMsaBuildOptions(true));
583 saq.pop();
584 }
585
586 saq.pop();
587 }
588 }
589
590 ToolChainMap parseModuleBuildOptions(boolean toolChainFamilyFlag) throws EdkException {
591 String[][] options = saq.getModuleBuildOptions(toolChainFamilyFlag);
592 if (options == null || options.length == 0) {
593 return new ToolChainMap();
594 }
595 return parseOptions(options);
596 }
597
598 private ToolChainMap parsePlatformBuildOptions(boolean toolChainFamilyFlag) throws EdkException {
599 String[][] options = saq.getPlatformBuildOptions(toolChainFamilyFlag);
600 if (options == null || options.length == 0) {
601 return new ToolChainMap();
602 }
603 return parseOptions(options);
604 }
605
606 ToolChainMap parseMsaBuildOptions(boolean toolChainFamilyFlag) throws EdkException {
607 String[][] options = saq.getMsaBuildOptions(toolChainFamilyFlag);
608 if (options == null || options.length == 0) {
609 return new ToolChainMap();
610 }
611 return parseOptions(options);
612 }
613
614 private ToolChainMap parseOptions(String[][] options) throws EdkException {
615 ToolChainMap map = new ToolChainMap();
616 int flagIndex = ToolChainElement.ATTRIBUTE.value;
617
618 for (int i = 0; i < options.length; ++i) {
619 String flagString = options[i][flagIndex];
620 if (flagString == null) {
621 flagString = "";
622 }
623 options[i][flagIndex] = ToolDefinitions.TOOLS_DEF_ATTRIBUTE_FLAGS;
624 map.put(options[i], flagString.trim());
625 }
626
627 return map;
628 }
629
630 private void parseToolChainFamilyOptions() throws EdkException {
631 GlobalData.setPlatformToolChainFamilyOption(parsePlatformBuildOptions(true));
632 }
633
634 private void parseToolChainOptions() throws EdkException {
635 GlobalData.setPlatformToolChainOption(parsePlatformBuildOptions(false));
636 }
637
638 /**
639 Add the current module to corresponding FV.
640
641 @param fvName current FV name
642 @param moduleName current module identification
643 **/
644 void updateFvs(String fvName, FpdModuleIdentification fpdModuleId) {
645 if (fvName == null || fvName.trim().length() == 0) {
646 fvName = "NULL";
647 }
648 String[] fvNameArray = fvName.split("[, \t]+");
649 for (int i = 0; i < fvNameArray.length; i++) {
650 //
651 // Put module to corresponding fvName
652 //
653 if (fvs.containsKey(fvNameArray[i])) {
654 Set<FpdModuleIdentification> set = fvs.get(fvNameArray[i]);
655 set.add(fpdModuleId);
656 } else {
657 Set<FpdModuleIdentification> set = new LinkedHashSet<FpdModuleIdentification>();
658 set.add(fpdModuleId);
659 fvs.put(fvNameArray[i], set);
660 }
661 }
662 }
663
664 /**
665 Get the suffix based on module type. Current relationship are listed:
666
667 <pre>
668 <b>ModuleType</b> <b>Suffix</b>
669 BASE .FFS
670 SEC .SEC
671 PEI_CORE .PEI
672 PEIM .PEI
673 DXE_CORE .DXE
674 DXE_DRIVER .DXE
675 DXE_RUNTIME_DRIVER .DXE
676 DXE_SAL_DRIVER .DXE
677 DXE_SMM_DRIVER .DXE
678 TOOL .FFS
679 UEFI_DRIVER .DXE
680 UEFI_APPLICATION .APP
681 USER_DEFINED .FFS
682 </pre>
683
684 @param moduleType module type
685 @return
686 @throws BuildException
687 If module type is null
688 **/
689 public static String getSuffix(String moduleType) throws BuildException {
690 if (moduleType == null) {
691 throw new BuildException("Module type is not specified.");
692 }
693
694 String[][] suffix = EdkDefinitions.ModuleTypeExtensions;
695
696 for (int i = 0; i < suffix.length; i++) {
697 if (suffix[i][0].equalsIgnoreCase(moduleType)) {
698 return suffix[i][1];
699 }
700 }
701 //
702 // Default is '.FFS'
703 //
704 return ".FFS";
705 }
706 /**
707 Add a property.
708
709 @param p property
710 **/
711 public void addProperty(Property p) {
712 properties.addElement(p);
713 }
714
715 public void setFpdFile(File fpdFile) {
716 this.fpdFile = fpdFile;
717 }
718
719 public void setType(String type) {
720 this.type = type;
721 }
722
723 public String getAllArchForModule(ModuleIdentification moduleId) {
724 String archs = "";
725 Iterator<FpdModuleIdentification> iter = outfiles.keySet().iterator();
726 while (iter.hasNext()) {
727 FpdModuleIdentification fpdModuleId = iter.next();
728
729 if (fpdModuleId.getModule().equals(moduleId)) {
730 archs += fpdModuleId.getArch() + " ";
731 }
732 }
733
734 return archs;
735 }
736
737 private void genAprioriFile(Set<FpdModuleIdentification> modules, File file) {
738 try {
739 FileWriter fw = new FileWriter(file);
740 BufferedWriter bw = new BufferedWriter(fw);
741
742 Iterator<FpdModuleIdentification> iter = modules.iterator();
743 while(iter.hasNext()) {
744 bw.write(iter.next().getModule().getGuid());
745 bw.newLine();
746 }
747
748 bw.flush();
749 bw.close();
750 fw.close();
751 } catch (IOException ex) {
752 BuildException buildException = new BuildException("Generation of the Apriori file [" + file.getPath() + "] failed!\n" + ex.getMessage());
753 buildException.setStackTrace(ex.getStackTrace());
754 throw buildException;
755 }
756 }
757
758 private Set<FpdModuleIdentification> getPeiApriori(String fvName) throws EdkException {
759 Node node = saq.getPeiApriori(fvName);
760 Set<FpdModuleIdentification> result = new LinkedHashSet<FpdModuleIdentification>();
761 if (node == null) {
762 return null;
763 }
764
765 NodeList childNodes = node.getChildNodes();
766 for (int i = 0; i < childNodes.getLength(); i++) {
767 Node childItem = childNodes.item(i);
768 if (childItem.getNodeType() == Node.ELEMENT_NODE) {
769 //
770 // Find child elements "IncludeModules"
771 //
772 if (childItem.getNodeName().compareTo("IncludeModules") == 0) {
773 //
774 // result will be updated
775 //
776 processNodes(childItem, result);
777 } else if (childItem.getNodeName().compareTo("FvName") == 0) {
778
779 } else if (childItem.getNodeName().compareTo("InfFileName") == 0) {
780
781 } else {
782 //
783 // Report Warning
784 //
785 EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised element " + childItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='APRIORI' Identifier='0']");
786 }
787 }
788 }
789
790 return result;
791 }
792
793 private Set<FpdModuleIdentification> getDxeApriori(String fvName) throws EdkException {
794 Node node = saq.getDxeApriori(fvName);
795 Set<FpdModuleIdentification> result = new LinkedHashSet<FpdModuleIdentification>();
796 if (node == null) {
797 return null;
798 }
799
800 NodeList childNodes = node.getChildNodes();
801 for (int i = 0; i < childNodes.getLength(); i++) {
802 Node childItem = childNodes.item(i);
803 if (childItem.getNodeType() == Node.ELEMENT_NODE) {
804 //
805 // Find child elements "IncludeModules"
806 //
807 if (childItem.getNodeName().compareTo("IncludeModules") == 0) {
808 //
809 // result will be updated
810 //
811 processNodes(childItem, result);
812 } else if (childItem.getNodeName().compareTo("FvName") == 0) {
813
814 } else if (childItem.getNodeName().compareTo("InfFileName") == 0) {
815
816 } else {
817 //
818 // Report Warning
819 //
820 EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised element " + childItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='APRIORI' Identifier='1']");
821 }
822 }
823 }
824
825 return result;
826 }
827
828 private Set<FpdModuleIdentification> getModuleSequenceForFv(String fvName) throws EdkException {
829 Node node = saq.getFpdModuleSequence(fvName);
830 Set<FpdModuleIdentification> result = new LinkedHashSet<FpdModuleIdentification>();
831
832 if ( node == null) {
833 EdkLog.log(this, EdkLog.EDK_WARNING, "FV[" + fvName + "] does not specify module sequence in FPD. Assuming present sequence as default sequence in FV. ");
834 return null;
835 } else {
836 NodeList childNodes = node.getChildNodes();
837 for (int i = 0; i < childNodes.getLength(); i++) {
838 Node childItem = childNodes.item(i);
839 if (childItem.getNodeType() == Node.ELEMENT_NODE) {
840 //
841 // Find child elements "IncludeModules"
842 //
843 if (childItem.getNodeName().compareTo("IncludeModules") == 0) {
844 //
845 // result will be updated
846 //
847 processNodes(childItem, result);
848 } else if (childItem.getNodeName().compareTo("FvName") == 0) {
849
850 } else if (childItem.getNodeName().compareTo("InfFileName") == 0) {
851
852 } else {
853 //
854 // Report Warning
855 //
856 EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised element " + childItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1']");
857 }
858 }
859 }
860 }
861
862 return result;
863 }
864
865 private void processNodes(Node node, Set<FpdModuleIdentification> result) throws EdkException {
866 //
867 // Found out all elements "Module"
868 //
869 NodeList childNodes = node.getChildNodes();
870 for (int j = 0; j < childNodes.getLength(); j++) {
871 Node childItem = childNodes.item(j);
872 if (childItem.getNodeType() == Node.ELEMENT_NODE) {
873 if (childItem.getNodeName().compareTo("Module") == 0) {
874 String moduleGuid = null;
875 String moduleVersion = null;
876 String packageGuid = null;
877 String packageVersion = null;
878 String arch = null;
879
880 NamedNodeMap attr = childItem.getAttributes();
881 for (int i = 0; i < attr.getLength(); i++) {
882 Node attrItem = attr.item(i);
883 if (attrItem.getNodeName().compareTo("ModuleGuid") == 0) {
884 moduleGuid = attrItem.getNodeValue();
885 } else if (attrItem.getNodeName().compareTo("ModuleVersion") == 0) {
886 moduleVersion = attrItem.getNodeValue();
887 } else if (attrItem.getNodeName().compareTo("PackageGuid") == 0) {
888 packageGuid = attrItem.getNodeValue();
889 } else if (attrItem.getNodeName().compareTo("PackageVersion") == 0) {
890 packageVersion = attrItem.getNodeValue();
891 } else if (attrItem.getNodeName().compareTo("Arch") == 0) {
892 arch = attrItem.getNodeValue();
893 } else {
894 //
895 // Report warning
896 //
897 EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised attribute " + attrItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1'].IncludeModules.Module");
898 }
899 }
900
901 PackageIdentification packageId = new PackageIdentification(packageGuid, packageVersion);
902 GlobalData.refreshPackageIdentification(packageId);
903
904 ModuleIdentification moduleId = new ModuleIdentification(moduleGuid, moduleVersion);
905 moduleId.setPackage(packageId);
906 GlobalData.refreshModuleIdentification(moduleId);
907
908 if (arch == null) {
909 throw new EdkException("Attribute [Arch] is required for element FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1'].IncludeModules.Module. ");
910 }
911
912 result.add(new FpdModuleIdentification(moduleId, arch));
913 } else {
914 //
915 // Report Warning
916 //
917 EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised element " + childItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1'].IncludeModules");
918 }
919 }
920 }
921 }
922
923
924 private void checkToolChain() throws EdkException {
925 ToolChainInfo toolChainInfo = GlobalData.getToolChainInfo();
926
927 if (toolChainInfo.getTargets().length == 0) {
928 throw new EdkException("No valid target found! "+
929 "Please check the TARGET definition in Tools/Conf/target.txt, "+
930 "or the <BuildTarget>, <BuildOptions> in the FPD file.");
931 }
932
933 if (toolChainInfo.getTagnames().length == 0) {
934 throw new EdkException("No valid tool chain found! "+
935 "Please check the TOOL_CHAIN_TAG definition in Tools/Conf/target.txt, "+
936 "or the <BuildOptions> in the FPD file.");
937 }
938
939 if (toolChainInfo.getArchs().length == 0) {
940 throw new EdkException("No valid architecture found! "+
941 "Please check the TARGET_ARCH definition in Tools/Conf/target.txt, "+
942 "or the <SupportedArchitectures>, <BuildOptions> in the FPD file.");
943 }
944
945 if (toolChainInfo.getCommands().length == 0) {
946 throw new EdkException("No valid COMMAND found! Please check the tool chain definitions "+
947 "in Tools/Conf/tools_def.txt.");
948 }
949 }
950 }