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