]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Java/Source/GenBuild/org/tianocore/build/fpd/FpdParserTask.java
- Fixed EDKT513 by adding existing section files into the dependency check of genffsf...
[mirror_edk2.git] / Tools / Java / Source / GenBuild / org / tianocore / build / fpd / FpdParserTask.java
CommitLineData
878ddf1f 1/** @file\r
ff225cbb 2 This file is ANT task FpdParserTask.\r
3\r
a29c47e0 4 FpdParserTask is used to parse FPD (Framework Platform Description) and generate\r
ff225cbb 5 build.out.xml. It is for Package or Platform build use.\r
6\r
a29c47e0 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
878ddf1f 16package org.tianocore.build.fpd;\r
17\r
18import java.io.BufferedWriter;\r
19import java.io.File;\r
20import java.io.FileWriter;\r
89e1408f 21import java.io.IOException;\r
878ddf1f 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
878ddf1f 29\r
30import org.apache.tools.ant.BuildException;\r
31import org.apache.tools.ant.Task;\r
a29c47e0 32import org.apache.tools.ant.taskdefs.Ant;\r
878ddf1f 33import org.apache.tools.ant.taskdefs.Property;\r
89e1408f 34import org.apache.xmlbeans.XmlException;\r
878ddf1f 35import org.apache.xmlbeans.XmlObject;\r
878ddf1f 36\r
4a6a5026 37import org.tianocore.common.definitions.EdkDefinitions;\r
b0a80562 38import org.tianocore.common.definitions.ToolDefinitions;\r
ff225cbb 39import org.tianocore.common.exception.EdkException;\r
bb511931 40import org.tianocore.common.logger.EdkLog;\r
aca6c736 41import org.tianocore.build.FrameworkBuildTask;\r
878ddf1f 42import org.tianocore.build.global.GlobalData;\r
43import org.tianocore.build.global.OutputManager;\r
878ddf1f 44import org.tianocore.build.global.SurfaceAreaQuery;\r
a29c47e0 45import org.tianocore.build.id.FpdModuleIdentification;\r
46import org.tianocore.build.id.ModuleIdentification;\r
bb511931 47import org.tianocore.build.id.PackageIdentification;\r
a29c47e0 48import org.tianocore.build.id.PlatformIdentification;\r
af98370e 49import org.tianocore.build.pcd.action.PlatformPcdPreprocessActionForBuilding;\r
a29c47e0 50import org.tianocore.build.toolchain.ToolChainElement;\r
51import org.tianocore.build.toolchain.ToolChainMap;\r
05b52e96 52import org.tianocore.build.toolchain.ToolChainInfo;\r
bb511931 53import org.w3c.dom.NamedNodeMap;\r
54import org.w3c.dom.Node;\r
55import org.w3c.dom.NodeList;\r
878ddf1f 56\r
57/**\r
a29c47e0 58 <code>FpdParserTask</code> is an ANT task. The main function is parsing Framework\r
ff225cbb 59 Platform Descritpion (FPD) XML file and generating its ANT build script for\r
60 corresponding platform.\r
a29c47e0 61\r
62 <p>The task sets global properties PLATFORM, PLATFORM_DIR, PLATFORM_RELATIVE_DIR\r
63 and BUILD_DIR. </p>\r
ff225cbb 64\r
a29c47e0 65 <p>The task generates ${PLATFORM}_build.xml file which will be called by top level\r
4b5f5549 66 build.xml. The task also generate Fv.inf files (File is for Tool GenFvImage). </p>\r
ff225cbb 67\r
a29c47e0 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
ff225cbb 71\r
a29c47e0 72 <p>The method parseFpdFile is also prepared for single module build. </p>\r
ff225cbb 73\r
878ddf1f 74 @since GenBuild 1.0\r
75**/\r
76public class FpdParserTask extends Task {\r
ff225cbb 77\r
2c0bc1a2 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
a29c47e0 83 private File fpdFile = null;\r
ff225cbb 84\r
19bf6b15 85 PlatformIdentification platformId;\r
ff225cbb 86\r
a29c47e0 87 private String type;\r
ff225cbb 88\r
878ddf1f 89 ///\r
90 /// Mapping from modules identification to out put file name\r
91 ///\r
19bf6b15 92 Map<FpdModuleIdentification, String> outfiles = new LinkedHashMap<FpdModuleIdentification, String>();\r
878ddf1f 93\r
94 ///\r
95 /// Mapping from FV name to its modules\r
96 ///\r
19bf6b15 97 Map<String, Set<FpdModuleIdentification>> fvs = new HashMap<String, Set<FpdModuleIdentification>>();\r
878ddf1f 98\r
380191dd 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
878ddf1f 104 ///\r
ff225cbb 105 /// FpdParserTask can specify some ANT properties.\r
878ddf1f 106 ///\r
107 private Vector<Property> properties = new Vector<Property>();\r
ff225cbb 108\r
83fba802 109 SurfaceAreaQuery saq = null;\r
878ddf1f 110\r
380191dd 111 boolean isUnified = true;\r
112 \r
e799f87f 113 public static String PEI_APRIORI_GUID = "1b45cc0a-156a-428a-af62-49864da0e6e6";\r
380191dd 114 \r
115 public static String DXE_APRIORI_GUID = "fc510ee7-ffdc-11d4-bd41-0080c73c8881";\r
116 \r
878ddf1f 117 /**\r
118 Public construct method. It is necessary for ANT task.\r
119 **/\r
a29c47e0 120 public FpdParserTask() {\r
878ddf1f 121 }\r
122\r
123 /**\r
ff225cbb 124 ANT task's entry method. The main steps is described as following:\r
125\r
a29c47e0 126 <ul>\r
ff225cbb 127 <li>Initialize global information (Framework DB, SPD files and all MSA files\r
a29c47e0 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
ff225cbb 134\r
a29c47e0 135 @throws BuildException\r
ff225cbb 136 Surface area is not valid.\r
878ddf1f 137 **/\r
138 public void execute() throws BuildException {\r
bb511931 139 this.setTaskName("FpdParser");\r
140 \r
878ddf1f 141 //\r
142 // Parse FPD file\r
143 //\r
144 parseFpdFile();\r
ff225cbb 145\r
a29c47e0 146 //\r
147 // Prepare BUILD_DIR\r
878ddf1f 148 //\r
a29c47e0 149 isUnified = OutputManager.getInstance().prepareBuildDir(getProject());\r
ff225cbb 150\r
02c768ee 151 String buildDir = getProject().getProperty("BUILD_DIR");\r
a29c47e0 152 //\r
153 // For every Target and ToolChain\r
154 //\r
155 String[] targetList = GlobalData.getToolChainInfo().getTargets();\r
82516887 156 for (int i = 0; i < targetList.length; i++) {\r
a29c47e0 157 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();\r
82516887 158 for(int j = 0; j < toolchainList.length; j++) {\r
a29c47e0 159 //\r
160 // Prepare FV_DIR\r
161 //\r
02c768ee 162 String ffsCommonDir = buildDir + File.separatorChar\r
6ae1510e 163 + targetList[i] + "_"\r
a29c47e0 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
ff225cbb 168\r
a29c47e0 169 //\r
170 // Gen Fv.inf files\r
171 //\r
172 genFvInfFiles(ffsCommonDir);\r
173 }\r
174 }\r
175\r
878ddf1f 176 //\r
177 // Gen build.xml\r
178 //\r
02c768ee 179 String platformBuildFile = buildDir + File.separatorChar + platformId.getName() + "_build.xml";\r
380191dd 180 PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, isUnified, saq, platformBuildFile, aprioriType);\r
a29c47e0 181 fileGenerator.genBuildFile();\r
ff225cbb 182\r
a29c47e0 183 //\r
184 // Ant call ${PLATFORM}_build.xml\r
878ddf1f 185 //\r
a29c47e0 186 Ant ant = new Ant();\r
187 ant.setProject(getProject());\r
02c768ee 188 ant.setAntfile(platformBuildFile);\r
a29c47e0 189 ant.setTarget(type);\r
190 ant.setInheritAll(true);\r
191 ant.init();\r
192 ant.execute();\r
878ddf1f 193 }\r
a29c47e0 194\r
878ddf1f 195 /**\r
ff225cbb 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
a29c47e0 198 will be under FV_DIR.\r
ff225cbb 199\r
878ddf1f 200 @throws BuildException\r
ff225cbb 201 File write FV.inf files error.\r
878ddf1f 202 **/\r
19bf6b15 203 void genFvInfFiles(String ffsCommonDir) throws BuildException {\r
83fba802 204 String[] validFv = saq.getFpdValidImageNames();\r
878ddf1f 205 for (int i = 0; i < validFv.length; i++) {\r
878ddf1f 206 //\r
207 // Get all global variables from FPD and set them to properties\r
208 //\r
83fba802 209 String[][] globalVariables = saq.getFpdGlobalVariable();\r
878ddf1f 210 for (int j = 0; j < globalVariables.length; j++) {\r
a29c47e0 211 getProject().setProperty(globalVariables[j][0], globalVariables[j][1]);\r
878ddf1f 212 }\r
213\r
57cc2ee7 214 getProject().setProperty("FV_FILENAME", validFv[i]);\r
ff225cbb 215\r
57cc2ee7 216 File fvFile = new File(getProject().replaceProperties( getProject().getProperty("FV_DIR") + File.separatorChar + validFv[i] + ".inf"));\r
d946661a 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
878ddf1f 223 fvFile.getParentFile().mkdirs();\r
224\r
225 try {\r
226 FileWriter fw = new FileWriter(fvFile);\r
227 BufferedWriter bw = new BufferedWriter(fw);\r
ff225cbb 228\r
878ddf1f 229 //\r
230 // Options\r
231 //\r
83fba802 232 String[][] options = saq.getFpdOptions(validFv[i]);\r
878ddf1f 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
ff225cbb 249\r
878ddf1f 250 //\r
251 // Attributes;\r
252 //\r
83fba802 253 String[][] attributes = saq.getFpdAttributes(validFv[i]);\r
878ddf1f 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
a29c47e0 265 bw.write(getProject().replaceProperties(str.toString()));\r
878ddf1f 266 bw.newLine();\r
267 }\r
268 bw.newLine();\r
269 }\r
ff225cbb 270\r
878ddf1f 271 //\r
272 // Components\r
273 //\r
83fba802 274 String[][] components = saq.getFpdComponents(validFv[i]);\r
878ddf1f 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
a29c47e0 286 bw.write(getProject().replaceProperties(str.toString()));\r
878ddf1f 287 bw.newLine();\r
288 }\r
289 bw.newLine();\r
290 }\r
bb511931 291 \r
878ddf1f 292 //\r
293 // Files\r
294 //\r
bb511931 295 Set<FpdModuleIdentification> moduleSeqSet = getModuleSequenceForFv(validFv[i]);\r
296 \r
57cc2ee7 297 Set<FpdModuleIdentification> filesSet = fvs.get(validFv[i]);\r
bb511931 298 \r
299 FpdModuleIdentification[] files = null;\r
f6390d37 300 \r
bb511931 301 if (moduleSeqSet == null) {\r
302 if (filesSet != null) {\r
303 files = filesSet.toArray(new FpdModuleIdentification[filesSet.size()]);\r
304 }\r
f6390d37 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
bb511931 309 } else {\r
310 //\r
311 // if moduleSeqSet and filesSet is inconsistent, report error\r
312 //\r
f6390d37 313 if(moduleSeqSet.size() != filesSet.size()){\r
bb511931 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
878ddf1f 333 bw.write("[files]");\r
334 bw.newLine();\r
380191dd 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
878ddf1f 362 for (int j = 0; j < files.length; j++) {\r
a29c47e0 363 String str = ffsCommonDir + File.separatorChar + outfiles.get(files[j]);\r
364 bw.write(getProject().replaceProperties("EFI_FILE_NAME = " + str));\r
878ddf1f 365 bw.newLine();\r
366 }\r
367 }\r
368 bw.flush();\r
369 bw.close();\r
370 fw.close();\r
89e1408f 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
bb511931 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
878ddf1f 379 }\r
380 }\r
381 }\r
706c2ad4 382 \r
a29c47e0 383 /**\r
384 This method is used for Single Module Build.\r
ff225cbb 385\r
a29c47e0 386 @throws BuildException\r
ff225cbb 387 FPD file is not valid.\r
a29c47e0 388 **/\r
89e1408f 389 public void parseFpdFile(File fpdFile) throws BuildException, EdkException {\r
a29c47e0 390 this.fpdFile = fpdFile;\r
5acb4b67 391 parseFpdFile();\r
2a9060e2 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
380191dd 419 PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, isUnified, saq, platformBuildFile, aprioriType);\r
2a9060e2 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
a29c47e0 429 }\r
878ddf1f 430\r
431 /**\r
ff225cbb 432 Parse FPD file.\r
433\r
878ddf1f 434 @throws BuildException\r
ff225cbb 435 FPD file is not valid.\r
a29c47e0 436 **/\r
19bf6b15 437 void parseFpdFile() throws BuildException {\r
878ddf1f 438 try {\r
a29c47e0 439 XmlObject doc = XmlObject.Factory.parse(fpdFile);\r
ff225cbb 440\r
a29c47e0 441 if (!doc.validate()) {\r
391dbbb1 442 throw new BuildException("Platform Surface Area file [" + fpdFile.getPath() + "] format is invalid!");\r
878ddf1f 443 }\r
ff225cbb 444\r
a29c47e0 445 Map<String, XmlObject> map = new HashMap<String, XmlObject>();\r
446 map.put("PlatformSurfaceArea", doc);\r
83fba802 447 saq = new SurfaceAreaQuery(map);\r
8031d48d 448\r
a29c47e0 449 //\r
450 // Initialize\r
451 //\r
83fba802 452 platformId = saq.getFpdHeader();\r
a29c47e0 453 platformId.setFpdFile(fpdFile);\r
de4bb9f6 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
aca6c736 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
a29c47e0 465\r
466 //\r
ff225cbb 467 // Build mode. User-defined output dir.\r
a29c47e0 468 //\r
83fba802 469 String buildMode = saq.getFpdIntermediateDirectories();\r
470 String userDefinedOutputDir = saq.getFpdOutputDirectory();\r
a29c47e0 471\r
472 OutputManager.getInstance().setup(userDefinedOutputDir, buildMode);\r
473\r
474 //\r
475 // TBD. Deal PCD and BuildOption related Info\r
476 //\r
83fba802 477 GlobalData.setFpdBuildOptions(saq.getFpdBuildOptions());\r
ff225cbb 478\r
83fba802 479 GlobalData.setToolChainPlatformInfo(saq.getFpdToolChainInfo());\r
ff225cbb 480\r
878ddf1f 481 //\r
482 // Parse all list modules SA\r
483 //\r
07193171 484 parseModuleSAFiles();\r
a29c47e0 485\r
486 //\r
487 // TBD. Deal PCD and BuildOption related Info\r
488 //\r
489 parseToolChainFamilyOptions();\r
490 parseToolChainOptions();\r
491\r
05b52e96 492 //\r
493 // check if the tool chain is valid or not\r
494 // \r
495 checkToolChain();\r
496\r
83fba802 497 saq.push(map);\r
ff225cbb 498\r
de4bb9f6 499 //\r
500 // Pcd Collection. Call CollectPCDAction to collect pcd info.\r
501 //\r
2c0bc1a2 502 if (!parsed) {\r
503 PlatformPcdPreprocessActionForBuilding ca = new PlatformPcdPreprocessActionForBuilding();\r
504 ca.perform(platformId.getFpdFile().getPath());\r
505 }\r
89e1408f 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
878ddf1f 518 }\r
2c0bc1a2 519 if (!parsed) {\r
520 parsed = true;\r
521 }\r
878ddf1f 522 }\r
523\r
524 /**\r
ff225cbb 525 Parse all modules listed in FPD file.\r
878ddf1f 526 **/\r
19bf6b15 527 void parseModuleSAFiles() throws EdkException{\r
83fba802 528 Map<FpdModuleIdentification, Map<String, XmlObject>> moduleSAs = saq.getFpdModules();\r
136adffc 529\r
878ddf1f 530 //\r
531 // For every Module lists in FPD file.\r
532 //\r
a29c47e0 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
ff225cbb 537\r
878ddf1f 538 //\r
ff225cbb 539 // Judge if Module is existed?\r
a29c47e0 540 // TBD\r
a29c47e0 541 GlobalData.registerFpdModuleSA(fpdModuleId, moduleSAs.get(fpdModuleId));\r
542\r
878ddf1f 543 //\r
a29c47e0 544 // Put fpdModuleId to the corresponding FV\r
878ddf1f 545 //\r
83fba802 546 saq.push(GlobalData.getDoc(fpdModuleId));\r
547 String fvBinding = saq.getModuleFvBindingKeyword();\r
a29c47e0 548\r
549 fpdModuleId.setFvBinding(fvBinding);\r
01413f0c 550 updateFvs(fvBinding, fpdModuleId);\r
ff225cbb 551\r
878ddf1f 552 //\r
a29c47e0 553 // Prepare for out put file name\r
878ddf1f 554 //\r
a29c47e0 555 ModuleIdentification moduleId = fpdModuleId.getModule();\r
82516887 556\r
83fba802 557 String baseName = saq.getModuleOutputFileBasename();\r
82516887 558 \r
a29c47e0 559 if (baseName == null) {\r
560 baseName = moduleId.getName();\r
878ddf1f 561 }\r
ff225cbb 562 outfiles.put(fpdModuleId, fpdModuleId.getArch() + File.separatorChar\r
563 + moduleId.getGuid() + "-" + baseName\r
a29c47e0 564 + getSuffix(moduleId.getModuleType()));\r
565\r
566 //\r
567 // parse module build options, if any\r
ff225cbb 568 //\r
a29c47e0 569 GlobalData.addModuleToolChainOption(fpdModuleId, parseModuleBuildOptions(false));\r
570 GlobalData.addModuleToolChainFamilyOption(fpdModuleId, parseModuleBuildOptions(true));\r
b69bb9ba 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
15d449ba 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
83fba802 586 saq.pop();\r
878ddf1f 587 }\r
588 }\r
589\r
19bf6b15 590 ToolChainMap parseModuleBuildOptions(boolean toolChainFamilyFlag) throws EdkException {\r
83fba802 591 String[][] options = saq.getModuleBuildOptions(toolChainFamilyFlag);\r
a29c47e0 592 if (options == null || options.length == 0) {\r
80eb97ff 593 return new ToolChainMap();\r
878ddf1f 594 }\r
a29c47e0 595 return parseOptions(options);\r
878ddf1f 596 }\r
ff225cbb 597\r
a29c47e0 598 private ToolChainMap parsePlatformBuildOptions(boolean toolChainFamilyFlag) throws EdkException {\r
83fba802 599 String[][] options = saq.getPlatformBuildOptions(toolChainFamilyFlag);\r
a29c47e0 600 if (options == null || options.length == 0) {\r
80eb97ff 601 return new ToolChainMap();\r
878ddf1f 602 }\r
a29c47e0 603 return parseOptions(options);\r
878ddf1f 604 }\r
605\r
b69bb9ba 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
a29c47e0 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
b0a80562 623 options[i][flagIndex] = ToolDefinitions.TOOLS_DEF_ATTRIBUTE_FLAGS;\r
a29c47e0 624 map.put(options[i], flagString.trim());\r
625 }\r
626\r
878ddf1f 627 return map;\r
628 }\r
ff225cbb 629\r
a29c47e0 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
878ddf1f 637\r
638 /**\r
ff225cbb 639 Add the current module to corresponding FV.\r
640\r
a29c47e0 641 @param fvName current FV name\r
642 @param moduleName current module identification\r
878ddf1f 643 **/\r
19bf6b15 644 void updateFvs(String fvName, FpdModuleIdentification fpdModuleId) {\r
fa2da5b1 645 if (fvName == null || fvName.trim().length() == 0) {\r
646 fvName = "NULL";\r
647 }\r
57cc2ee7 648 String[] fvNameArray = fvName.split("[, \t]+");\r
a29c47e0 649 for (int i = 0; i < fvNameArray.length; i++) {\r
878ddf1f 650 //\r
a29c47e0 651 // Put module to corresponding fvName\r
878ddf1f 652 //\r
a29c47e0 653 if (fvs.containsKey(fvNameArray[i])) {\r
654 Set<FpdModuleIdentification> set = fvs.get(fvNameArray[i]);\r
655 set.add(fpdModuleId);\r
82516887 656 } else {\r
a29c47e0 657 Set<FpdModuleIdentification> set = new LinkedHashSet<FpdModuleIdentification>();\r
658 set.add(fpdModuleId);\r
659 fvs.put(fvNameArray[i], set);\r
878ddf1f 660 }\r
878ddf1f 661 }\r
662 }\r
663\r
664 /**\r
ff225cbb 665 Get the suffix based on module type. Current relationship are listed:\r
666\r
a29c47e0 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
ff225cbb 683\r
a29c47e0 684 @param moduleType module type\r
685 @return\r
686 @throws BuildException\r
687 If module type is null\r
878ddf1f 688 **/\r
a29c47e0 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
878ddf1f 693\r
4a6a5026 694 String[][] suffix = EdkDefinitions.ModuleTypeExtensions;\r
ff225cbb 695\r
a29c47e0 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
878ddf1f 705 }\r
878ddf1f 706 /**\r
ff225cbb 707 Add a property.\r
708\r
a29c47e0 709 @param p property\r
710 **/\r
711 public void addProperty(Property p) {\r
712 properties.addElement(p);\r
878ddf1f 713 }\r
714\r
a29c47e0 715 public void setFpdFile(File fpdFile) {\r
716 this.fpdFile = fpdFile;\r
878ddf1f 717 }\r
718\r
a29c47e0 719 public void setType(String type) {\r
720 this.type = type;\r
878ddf1f 721 }\r
3790e93c 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
bb511931 736 \r
380191dd 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
bb511931 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
05b52e96 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
015849a4 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
05b52e96 931 }\r
932\r
933 if (toolChainInfo.getTagnames().length == 0) {\r
015849a4 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
05b52e96 937 }\r
938\r
939 if (toolChainInfo.getArchs().length == 0) {\r
015849a4 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
05b52e96 943 }\r
944\r
945 if (toolChainInfo.getCommands().length == 0) {\r
015849a4 946 throw new EdkException("No valid COMMAND found! Please check the tool chain definitions "+\r
947 "in Tools/Conf/tools_def.txt.");\r
05b52e96 948 }\r
949 }\r
878ddf1f 950}\r