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