]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/GenBuild/org/tianocore/build/fpd/FpdParserTask.java
Removed the printStackTrace() which is used only for debug purpose.
[mirror_edk2.git] / Tools / 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.util.HashMap;
22 import java.util.Iterator;
23 import java.util.LinkedHashMap;
24 import java.util.LinkedHashSet;
25 import java.util.Map;
26 import java.util.Set;
27 import java.util.Vector;
28 import java.util.TreeMap;
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.XmlObject;
35
36 import org.tianocore.build.global.GlobalData;
37 import org.tianocore.build.global.OutputManager;
38 import org.tianocore.build.global.SurfaceAreaQuery;
39 import org.tianocore.build.id.FpdModuleIdentification;
40 import org.tianocore.build.id.ModuleIdentification;
41 import org.tianocore.build.id.PlatformIdentification;
42 import org.tianocore.build.pcd.action.ActionMessage;
43 import org.tianocore.build.pcd.action.CollectPCDAction;
44 import org.tianocore.build.pcd.exception.EntityException;
45 import org.tianocore.build.toolchain.ToolChainAttribute;
46 import org.tianocore.build.toolchain.ToolChainElement;
47 import org.tianocore.build.toolchain.ToolChainMap;
48 import org.tianocore.exception.EdkException;
49
50 /**
51 <code>FpdParserTask</code> is an ANT task. The main function is parsing Framework
52 Platform Descritpion (FPD) XML file and generating its ANT build script for
53 corresponding platform.
54
55 <p>The task sets global properties PLATFORM, PLATFORM_DIR, PLATFORM_RELATIVE_DIR
56 and BUILD_DIR. </p>
57
58 <p>The task generates ${PLATFORM}_build.xml file which will be called by top level
59 build.xml. The task also generate Fv.inf files (File is for Tool GenFvImage)
60 and flash definition file (File is for Tool FlashMap) if necessary. </p>
61
62 <p>FpdParserTask task stores all FPD information to GlobalData. And parse
63 tools definition file to set up compiler options for different Target and
64 different ToolChainTag. </p>
65
66 <p>The method parseFpdFile is also prepared for single module build. </p>
67
68 <p>The usage is (take NT32 Platform for example):</p>
69
70 <pre>
71 &lt;FPDParser platformName="Nt32" /&gt;
72 </pre>
73
74 <p>The task will initialize all information through parsing Framework Database,
75 SPD, Tool chain configuration files. </p>
76
77 @since GenBuild 1.0
78 **/
79 public class FpdParserTask extends Task {
80
81 private String platformName;
82
83 private File fpdFile = null;
84
85 private PlatformIdentification platformId;
86
87 ///
88 ///
89 ///
90 private String type;
91
92 ///
93 /// Mapping from modules identification to out put file name
94 ///
95 private Map<FpdModuleIdentification, String> outfiles = new LinkedHashMap<FpdModuleIdentification, String>();
96
97 ///
98 /// Mapping from FV name to its modules
99 ///
100 private Map<String, Set<FpdModuleIdentification>> fvs = new HashMap<String, Set<FpdModuleIdentification>>();
101
102 ///
103 /// Mapping from sequence number to FV names
104 ///
105 private Map<String, Set<String>> sequences = new TreeMap<String, Set<String>>();
106
107 ///
108 /// FpdParserTask can specify some ANT properties.
109 ///
110 private Vector<Property> properties = new Vector<Property>();
111
112 private boolean isUnified = true;
113
114
115 /**
116 Public construct method. It is necessary for ANT task.
117 **/
118 public FpdParserTask() {
119 }
120
121 /**
122 ANT task's entry method. The main steps is described as following:
123
124 <ul>
125 <li>Initialize global information (Framework DB, SPD files and all MSA files
126 listed in SPD). This step will execute only once in whole build process;</li>
127 <li>Parse specified FPD file; </li>
128 <li>Generate FV.inf files; </li>
129 <li>Generate PlatformName_build.xml file for Flatform build; </li>
130 <li>Collect PCD information. </li>
131 </ul>
132
133 @throws BuildException
134 Surface area is not valid.
135 **/
136 public void execute() throws BuildException {
137 // Remove !!
138 if ( fpdFile == null) {
139 if (platformName == null) {
140 throw new BuildException("FpdParserTask parameter error. Please specify platform name or FPD file. ");
141 }
142 platformId = GlobalData.getPlatformByName(platformName);
143 fpdFile = platformId.getFpdFile();
144 }
145
146 //
147 // Parse FPD file
148 //
149 parseFpdFile();
150
151 //
152 // Prepare BUILD_DIR
153 //
154 isUnified = OutputManager.getInstance().prepareBuildDir(getProject());
155
156 //
157 // Generate FDF (Flash Definition File) file
158 //
159
160 //
161 // For every Target and ToolChain
162 //
163 String[] targetList = GlobalData.getToolChainInfo().getTargets();
164 for (int i = 0; i < targetList.length; i++){
165 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();
166 for(int j = 0; j < toolchainList.length; j++){
167 //
168 // Prepare FV_DIR
169 //
170 String ffsCommonDir = getProject().getProperty("BUILD_DIR") + File.separatorChar
171 + targetList[i] + File.separatorChar
172 + toolchainList[j];
173 File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");
174 fvDir.mkdirs();
175 getProject().setProperty("FV_DIR", fvDir.getPath().replaceAll("(\\\\)", "/"));
176
177 //
178 // Gen Fv.inf files
179 //
180 genFvInfFiles(ffsCommonDir);
181 }
182 }
183
184 //
185 // Gen build.xml
186 //
187 PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, sequences, isUnified);
188 fileGenerator.genBuildFile();
189
190 //
191 // Ant call ${PLATFORM}_build.xml
192 //
193
194 Ant ant = new Ant();
195 ant.setProject(getProject());
196 ant.setAntfile(platformId.getFpdFile().getParent() + File.separatorChar + platformId.getName() + "_build.xml");
197 ant.setTarget(type);
198 ant.setInheritAll(true);
199 ant.init();
200 ant.execute();
201
202 // GlobalData.log.info("Fpd build end. ");
203 }
204
205 /**
206 Generate Fv.inf files. The Fv.inf file is composed with four
207 parts: Options, Attributes, Components and Files. The Fv.inf files
208 will be under FV_DIR.
209
210 @throws BuildException
211 File write FV.inf files error.
212 **/
213 private void genFvInfFiles(String ffsCommonDir) throws BuildException {
214 String[] validFv = SurfaceAreaQuery.getFpdValidImageNames();
215 for (int i = 0; i < validFv.length; i++) {
216 //
217 // Get all global variables from FPD and set them to properties
218 //
219 String[][] globalVariables = SurfaceAreaQuery.getFpdGlobalVariable();
220 for (int j = 0; j < globalVariables.length; j++) {
221 getProject().setProperty(globalVariables[j][0], globalVariables[j][1]);
222 }
223
224 getProject().setProperty("FV_FILENAME", validFv[i].toUpperCase());
225
226 File fvFile = new File(getProject().replaceProperties( getProject().getProperty("FV_DIR") + File.separatorChar + validFv[i].toUpperCase() + ".inf"));
227 fvFile.getParentFile().mkdirs();
228
229 try {
230 FileWriter fw = new FileWriter(fvFile);
231 BufferedWriter bw = new BufferedWriter(fw);
232
233 //
234 // Options
235 //
236 String[][] options = SurfaceAreaQuery.getFpdOptions(validFv[i]);
237 if (options.length > 0) {
238 bw.write("[options]");
239 bw.newLine();
240 for (int j = 0; j < options.length; j++) {
241 StringBuffer str = new StringBuffer(100);
242 str.append(options[j][0]);
243 while (str.length() < 40) {
244 str.append(' ');
245 }
246 str.append("= ");
247 str.append(options[j][1]);
248 bw.write(getProject().replaceProperties(str.toString()));
249 bw.newLine();
250 }
251 bw.newLine();
252 }
253
254 //
255 // Attributes;
256 //
257 String[][] attributes = SurfaceAreaQuery.getFpdAttributes(validFv[i]);
258 if (attributes.length > 0) {
259 bw.write("[attributes]");
260 bw.newLine();
261 for (int j = 0; j < attributes.length; j++) {
262 StringBuffer str = new StringBuffer(100);
263 str.append(attributes[j][0]);
264 while (str.length() < 40) {
265 str.append(' ');
266 }
267 str.append("= ");
268 str.append(attributes[j][1]);
269 bw.write(getProject().replaceProperties(str.toString()));
270 bw.newLine();
271 }
272 bw.newLine();
273 }
274
275 //
276 // Components
277 //
278 String[][] components = SurfaceAreaQuery.getFpdComponents(validFv[i]);
279 if (components.length > 0) {
280 bw.write("[components]");
281 bw.newLine();
282 for (int j = 0; j < components.length; j++) {
283 StringBuffer str = new StringBuffer(100);
284 str.append(components[j][0]);
285 while (str.length() < 40) {
286 str.append(' ');
287 }
288 str.append("= ");
289 str.append(components[j][1]);
290 bw.write(getProject().replaceProperties(str.toString()));
291 bw.newLine();
292 }
293 bw.newLine();
294 }
295
296 //
297 // Files
298 //
299 Set<FpdModuleIdentification> filesSet = fvs.get(validFv[i].toUpperCase());
300 if (filesSet != null) {
301 FpdModuleIdentification[] files = filesSet.toArray(new FpdModuleIdentification[filesSet.size()]);
302 bw.write("[files]");
303 bw.newLine();
304 for (int j = 0; j < files.length; j++) {
305 String str = ffsCommonDir + File.separatorChar + outfiles.get(files[j]);
306 bw.write(getProject().replaceProperties("EFI_FILE_NAME = " + str));
307 bw.newLine();
308 }
309 }
310 bw.flush();
311 bw.close();
312 fw.close();
313 } catch (Exception e) {
314 throw new BuildException("Generate FV file [" + fvFile.getPath() + "] failed. \n" + e.getMessage());
315 }
316 }
317 }
318 /**
319 This method is used for Single Module Build.
320
321
322 @throws BuildException
323 FPD file is not valid.
324 **/
325 public void parseFpdFile(File fpdFile) throws BuildException {
326 this.fpdFile = fpdFile;
327 parseFpdFile();
328 }
329
330 /**
331 Parse FPD file.
332
333 @throws BuildException
334 FPD file is not valid.
335 **/
336 private void parseFpdFile() throws BuildException {
337 try {
338 XmlObject doc = XmlObject.Factory.parse(fpdFile);
339
340 if (!doc.validate()) {
341 throw new BuildException("Platform Surface Area file [" + fpdFile.getPath() + "] is invalid.");
342 }
343
344 Map<String, XmlObject> map = new HashMap<String, XmlObject>();
345 map.put("PlatformSurfaceArea", doc);
346 SurfaceAreaQuery.setDoc(map);
347
348 //
349 // Initialize
350 //
351 platformId = SurfaceAreaQuery.getFpdHeader();
352 platformId.setFpdFile(fpdFile);
353 getProject().setProperty("PLATFORM", platformId.getName());
354 getProject().setProperty("PLATFORM_FILE", platformId.getRelativeFpdFile().replaceAll("(\\\\)", "/"));
355 getProject().setProperty("PLATFORM_DIR", platformId.getFpdFile().getParent().replaceAll("(\\\\)", "/"));
356 getProject().setProperty("PLATFORM_RELATIVE_DIR", platformId.getPlatformRelativeDir().replaceAll("(\\\\)", "/"));
357
358 //
359 // Build mode. User-defined output dir.
360 //
361 String buildMode = SurfaceAreaQuery.getFpdIntermediateDirectories();
362 String userDefinedOutputDir = SurfaceAreaQuery.getFpdOutputDirectory();
363
364 OutputManager.getInstance().setup(userDefinedOutputDir, buildMode);
365
366 //
367 // TBD. Deal PCD and BuildOption related Info
368 //
369 GlobalData.setFpdBuildOptions(SurfaceAreaQuery.getFpdBuildOptions());
370
371 GlobalData.setToolChainPlatformInfo(SurfaceAreaQuery.getFpdToolChainInfo());
372
373 //
374 // Parse all list modules SA
375 //
376 parseModuleSAFiles();
377
378 //
379 // TBD. Deal PCD and BuildOption related Info
380 //
381 parseToolChainFamilyOptions();
382 parseToolChainOptions();
383
384 SurfaceAreaQuery.setDoc(map);
385
386 //
387 // Pcd Collection. Call CollectPCDAction to collect pcd info.
388 //
389 try {
390 CollectPCDAction ca = new CollectPCDAction();
391 ca.perform(GlobalData.getWorkspacePath(),platformId.getFpdFile().getPath(),ActionMessage.NULL_MESSAGE_LEVEL);
392 } catch (Exception e){
393 throw new BuildException(e.getMessage());
394 }
395 } catch (Exception e) {
396 throw new BuildException("Load FPD file [" + fpdFile.getPath() + "] error. \n" + e.getMessage());
397 }
398 }
399
400
401
402 /**
403 Parse all modules listed in FPD file.
404 **/
405 private void parseModuleSAFiles() throws EdkException{
406 Map<FpdModuleIdentification, Map<String, XmlObject>> moduleSAs = SurfaceAreaQuery.getFpdModules();
407
408 //
409 // For every Module lists in FPD file.
410 //
411 Set<FpdModuleIdentification> keys = moduleSAs.keySet();
412 Iterator iter = keys.iterator();
413 while (iter.hasNext()) {
414 FpdModuleIdentification fpdModuleId = (FpdModuleIdentification) iter.next();
415
416 //
417 // Judge if Module is existed?
418 // TBD
419
420 GlobalData.registerFpdModuleSA(fpdModuleId, moduleSAs.get(fpdModuleId));
421
422 //
423 // Put fpdModuleId to the corresponding FV
424 //
425 SurfaceAreaQuery.push(GlobalData.getDoc(fpdModuleId));
426 String fvBinding = SurfaceAreaQuery.getModuleFvBindingKeyword();
427 SurfaceAreaQuery.pop();
428
429 fpdModuleId.setFvBinding(fvBinding);
430 String fvSequence = fpdModuleId.getSequence();
431 updateFvs(fvSequence, fvBinding, fpdModuleId);
432
433 //
434 // Prepare for out put file name
435 //
436 ModuleIdentification moduleId = fpdModuleId.getModule();
437 SurfaceAreaQuery.push(GlobalData.getDoc(fpdModuleId));
438 String baseName = SurfaceAreaQuery.getModuleOutputFileBasename();
439 SurfaceAreaQuery.pop();
440 if (baseName == null) {
441 baseName = moduleId.getName();
442 }
443 outfiles.put(fpdModuleId, fpdModuleId.getArch() + File.separatorChar
444 + moduleId.getGuid() + "-" + baseName
445 + getSuffix(moduleId.getModuleType()));
446
447 //
448 // parse module build options, if any
449 //
450 SurfaceAreaQuery.push(GlobalData.getDoc(fpdModuleId));
451 GlobalData.addModuleToolChainOption(fpdModuleId, parseModuleBuildOptions(false));
452 GlobalData.addModuleToolChainFamilyOption(fpdModuleId, parseModuleBuildOptions(true));
453 SurfaceAreaQuery.pop();
454 }
455 }
456
457 private ToolChainMap parseModuleBuildOptions(boolean toolChainFamilyFlag) throws EdkException {
458 String[][] options = SurfaceAreaQuery.getModuleBuildOptions(toolChainFamilyFlag);
459 if (options == null || options.length == 0) {
460 return null;
461 }
462 return parseOptions(options);
463 }
464
465 private ToolChainMap parsePlatformBuildOptions(boolean toolChainFamilyFlag) throws EdkException {
466 String[][] options = SurfaceAreaQuery.getPlatformBuildOptions(toolChainFamilyFlag);
467 if (options == null || options.length == 0) {
468 return null;
469 }
470 return parseOptions(options);
471 }
472
473 private ToolChainMap parseOptions(String[][] options) throws EdkException {
474 ToolChainMap map = new ToolChainMap();
475 int flagIndex = ToolChainElement.ATTRIBUTE.value;
476
477 for (int i = 0; i < options.length; ++i) {
478 String flagString = options[i][flagIndex];
479 if (flagString == null) {
480 flagString = "";
481 }
482 options[i][flagIndex] = ToolChainAttribute.FLAGS + "";
483 map.put(options[i], flagString.trim());
484 }
485
486 return map;
487 }
488
489 private void parseToolChainFamilyOptions() throws EdkException {
490 GlobalData.setPlatformToolChainFamilyOption(parsePlatformBuildOptions(true));
491 }
492
493 private void parseToolChainOptions() throws EdkException {
494 GlobalData.setPlatformToolChainOption(parsePlatformBuildOptions(false));
495 }
496
497 /**
498 Add the current module to corresponding FV.
499
500 @param fvName current FV name
501 @param moduleName current module identification
502 **/
503 private void updateFvs(String fvSequence, String fvName, FpdModuleIdentification fpdModuleId) {
504 String upcaseFvName = fvName.toUpperCase();
505 String[] fvNameArray = upcaseFvName.split("[, \t]+");
506 for (int i = 0; i < fvNameArray.length; i++) {
507 //
508 // Put module to corresponding fvName
509 //
510 if (fvs.containsKey(fvNameArray[i])) {
511 Set<FpdModuleIdentification> set = fvs.get(fvNameArray[i]);
512 set.add(fpdModuleId);
513 }
514 else {
515 Set<FpdModuleIdentification> set = new LinkedHashSet<FpdModuleIdentification>();
516 set.add(fpdModuleId);
517 fvs.put(fvNameArray[i], set);
518 }
519
520 //
521 // Put fvName to corresponding fvSequence
522 //
523 if (sequences.containsKey(fvSequence)) {
524 Set<String> set = sequences.get(fvSequence);
525 set.add(fvNameArray[i]);
526 }
527 else {
528 Set<String> set = new LinkedHashSet<String>();
529 set.add(fvNameArray[i]);
530 sequences.put(fvSequence, set);
531 }
532 }
533 }
534
535 /**
536 Get the suffix based on module type. Current relationship are listed:
537
538 <pre>
539 <b>ModuleType</b> <b>Suffix</b>
540 BASE .FFS
541 SEC .SEC
542 PEI_CORE .PEI
543 PEIM .PEI
544 DXE_CORE .DXE
545 DXE_DRIVER .DXE
546 DXE_RUNTIME_DRIVER .DXE
547 DXE_SAL_DRIVER .DXE
548 DXE_SMM_DRIVER .DXE
549 TOOL .FFS
550 UEFI_DRIVER .DXE
551 UEFI_APPLICATION .APP
552 USER_DEFINED .FFS
553 </pre>
554
555 @param moduleType module type
556 @return
557 @throws BuildException
558 If module type is null
559 **/
560 public static String getSuffix(String moduleType) throws BuildException {
561 if (moduleType == null) {
562 throw new BuildException("Module type is not specified.");
563 }
564
565 String[][] suffix = { { "BASE", ".FFS"},
566 { "SEC", ".SEC" }, { "PEI_CORE", ".PEI" },
567 { "PEIM", ".PEI" }, { "DXE_CORE", ".DXE" },
568 { "DXE_DRIVER", ".DXE" }, { "DXE_RUNTIME_DRIVER", ".DXE" },
569 { "DXE_SAL_DRIVER", ".DXE" }, { "DXE_SMM_DRIVER", ".DXE" },
570 { "TOOL", ".FFS" }, { "UEFI_DRIVER", ".DXE" },
571 { "UEFI_APPLICATION", ".APP" }, { "USER_DEFINED", ".FFS" } };
572
573 for (int i = 0; i < suffix.length; i++) {
574 if (suffix[i][0].equalsIgnoreCase(moduleType)) {
575 return suffix[i][1];
576 }
577 }
578 //
579 // Default is '.FFS'
580 //
581 return ".FFS";
582 }
583 /**
584 Add a property.
585
586 @param p property
587 **/
588 public void addProperty(Property p) {
589 properties.addElement(p);
590 }
591
592 public void setPlatformName(String platformName) {
593 this.platformName = platformName;
594 }
595
596 public void setFpdFile(File fpdFile) {
597 this.fpdFile = fpdFile;
598 }
599
600 public void setType(String type) {
601 this.type = type;
602 }
603
604
605 }