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