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