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