Fix a bug on GenBuild and have a minor update on BuildMacro.xml
[mirror_edk2.git] / Tools / Source / GenBuild / org / tianocore / build / global / GlobalData.java
1 /** @file
2 GlobalData class.
3
4 GlobalData provide initializing, instoring, querying and update global data.
5 It is a bridge to intercommunicate between multiple component, such as AutoGen,
6 PCD and so on.
7
8 Copyright (c) 2006, Intel Corporation
9 All rights reserved. This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
13
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 **/
17 package org.tianocore.build.global;
18
19 import java.io.File;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Set;
26
27 import org.apache.tools.ant.BuildException;
28 import org.apache.xmlbeans.XmlObject;
29 import org.tianocore.FrameworkDatabaseDocument;
30 import org.tianocore.MsaFilesDocument;
31 import org.tianocore.PackageListDocument;
32 import org.tianocore.PackageSurfaceAreaDocument;
33 import org.tianocore.MsaHeaderDocument.MsaHeader;
34 import org.tianocore.MsaLibHeaderDocument.MsaLibHeader;
35 import org.tianocore.build.pcd.entity.MemoryDatabaseManager;
36 import org.tianocore.build.autogen.CommonDefinition;
37 import org.tianocore.build.fpd.FpdParserTask;
38
39 /**
40 GlobalData provide initializing, instoring, querying and update global data.
41 It is a bridge to intercommunicate between multiple component, such as AutoGen,
42 PCD and so on.
43
44 <p>Note that all global information are initialized incrementally. All data will
45 parse and record only it is necessary during build time. </p>
46
47 @since GenBuild 1.0
48 **/
49 public class GlobalData {
50
51 ///
52 /// means no surface area information for module
53 ///
54 public static final int NO_SA = 0;
55
56 ///
57 /// means only MSA
58 ///
59 public static final int ONLY_MSA = 1;
60
61 ///
62 /// means only Library MSA
63 ///
64 public static final int ONLY_LIBMSA = 2;
65
66 ///
67 /// means both MSA and MBD
68 ///
69 public static final int MSA_AND_MBD = 3;
70
71 ///
72 /// means both Library MSA and Library MBD
73 ///
74 public static final int LIBMSA_AND_LIBMBD = 4;
75
76 ///
77 /// Be used to ensure Global data will be initialized only once.
78 ///
79 public static boolean globalFlag = false;
80
81 ///
82 /// Record current WORKSPACE Directory
83 ///
84 private static String workspaceDir = "";
85
86 ///
87 /// Two columns: Package Name (Key), Package Path(ralative to WORKSPACE)
88 ///
89 private static final Map<String, String> packageInfo = new HashMap<String, String>();
90
91 ///
92 /// spdTable
93 /// Key: Package Name, Value: SPD detail info
94 ///
95 private static final Map<String, Spd> spdTable = new HashMap<String, Spd>();
96
97 ///
98 /// Three columns:
99 /// 1. Module Name | BaseName (Key)
100 /// 2. Module Path + Msa file name (relative to Package)
101 /// 3. Package Name (This module belong to which package)
102 ///
103 private static final Map<String, String[]> moduleInfo = new HashMap<String, String[]>();
104
105 ///
106 /// List all libraries for current build module
107 /// Key: Library BaseName, Value: output library path+name
108 ///
109 private static final Map<String, String> libraries = new HashMap<String, String>();
110
111 ///
112 /// Store every module's relative library instances BaseName
113 /// Key: Module BaseName, Value: All library instances module depends on.
114 ///
115 private static final Map<String, Set<String> > moduleLibraryMap = new HashMap<String, Set<String> >();
116
117 ///
118 /// Key: Module BaseName, Value: original MSA info
119 ///
120 private static final Map<String, Map<String, XmlObject> > nativeMsa = new HashMap<String, Map<String, XmlObject> >();
121
122 ///
123 /// Key: Module BaseName, Value: original MBD info
124 ///
125 private static final Map<String, Map<String, XmlObject> > nativeMbd = new HashMap<String, Map<String, XmlObject> >();
126
127 ///
128 /// Two columns: Module Name or Base Name as Key
129 /// Value is a HashMap with overridden data from MSA/MBD or/and Platform
130 ///
131 private static final Map<String, Map<String, XmlObject> > parsedModules = new HashMap<String, Map<String, XmlObject> >();
132
133 ///
134 /// List all built Module; Value is Module BaseName + Arch. TBD
135 ///
136 private static final Set<String> builtModules = new HashSet<String>();
137
138 ///
139 /// Library instance information table which recored the library and it's
140 /// constructor and distructor function
141 ///
142 private static final Map<String, String[]> libInstanceInfo = new HashMap<String, String[]>();
143
144 ///
145 /// PCD memory database stored all PCD information which collected from FPD,MSA and SPD.
146 ///
147 private static final MemoryDatabaseManager pcdDbManager = new MemoryDatabaseManager();
148
149 /**
150 Query the module's absolute path with module base name.
151
152 @param moduleName the base name of the module
153 @return the absolute module path
154 **/
155 public synchronized static String getModulePath(String moduleName) {
156 String[] info = moduleInfo.get(moduleName);
157 String packagePath = (String) packageInfo.get(info[1]);
158 File convertFile = new File(workspaceDir + File.separatorChar + packagePath + File.separatorChar + info[0]);
159 return convertFile.getParent();
160 }
161
162 /**
163 Query the module's absolute MSA file path with module base name.
164
165 @param moduleName the base name of the module
166 @return the absolute MSA file name
167 @throws BuildException
168 Base name is not registered in any SPD files
169 **/
170 private synchronized static String getMsaFilename(String moduleName) throws BuildException {
171 String[] info = moduleInfo.get(moduleName);
172 if (info == null) {
173 throw new BuildException("Module base name [" + moduleName + "] can't found in all SPD.");
174 }
175 String packagePath = (String) packageInfo.get(info[1]);
176 File convertFile = new File(workspaceDir + File.separatorChar + packagePath + File.separatorChar + info[0]);
177 return convertFile.getPath();
178 }
179
180 /**
181 Query the module's absolute MBD file path with module base name.
182
183 @param moduleName the base name of the module
184 @return the absolute MBD file name
185 @throws BuildException
186 Base name is not registered in any SPD files
187 **/
188 private synchronized static String getMbdFilename(String moduleName) throws BuildException {
189 String[] info = moduleInfo.get(moduleName);
190 if (info == null) {
191 throw new BuildException("Info: Module base name [" + moduleName + "] can't found in all SPD.");
192 }
193 String packagePath = (String) packageInfo.get(info[1]);
194 File convertFile = new File(workspaceDir + File.separatorChar + packagePath + File.separatorChar + info[0]);
195 return convertFile.getPath().substring(0, convertFile.getPath().length() - 4) + ".mbd";
196 }
197
198 /**
199 Get the current WORKSPACE Directory.
200 @return current workspace directory
201 **/
202 public synchronized static String getWorkspacePath() {
203 return workspaceDir;
204 }
205
206 /**
207 Query package relative path to WORKSPACE_DIR with package name.
208
209 @param packageName the name of the package
210 @return the path relative to WORKSPACE_DIR
211 **/
212 public synchronized static String getPackagePath(String packageName) {
213 return (String) packageInfo.get(packageName);
214 }
215
216 /**
217 Query package (which the module belongs to) relative path to WORSPACE_DIR.
218
219 @param moduleName the base name of the module
220 @return the relative path to WORKSPACE_DIR of the package which the module belongs to
221 **/
222 public synchronized static String getPackagePathForModule(String moduleName) {
223 String[] info = moduleInfo.get(moduleName);
224 String packagePath = (String) packageInfo.get(info[1]);
225 return packagePath;
226 }
227
228 /**
229 Query the package name which the module belongs to with the module's base name.
230
231 @param moduleName the base name of the module
232 @return the package name which the module belongs to
233 **/
234 public synchronized static String getPackageNameForModule(String moduleName) {
235 return moduleInfo.get(moduleName)[1];
236 }
237
238 /**
239 Parse framework database (DB) and all SPD files listed in DB to initialize
240 the environment for next build. This method will only be executed only once
241 in the whole build process.
242
243 @param workspaceDatabaseFile the file name of framework database
244 @param workspaceDir current workspace directory path
245 @throws BuildException
246 Framework Dababase or SPD or MSA file is not valid
247 **/
248 public synchronized static void initInfo(String workspaceDatabaseFile, String workspaceDir) throws BuildException {
249 if (globalFlag) {
250 return;
251 }
252 globalFlag = true;
253 GlobalData.workspaceDir = workspaceDir;
254 File dbFile = new File(workspaceDir + File.separatorChar + workspaceDatabaseFile);
255 try {
256 FrameworkDatabaseDocument db = (FrameworkDatabaseDocument) XmlObject.Factory.parse(dbFile);
257 List<PackageListDocument.PackageList.Package> packages = db.getFrameworkDatabase().getPackageList()
258 .getPackageList();
259 Iterator iter = packages.iterator();
260 while (iter.hasNext()) {
261 PackageListDocument.PackageList.Package packageItem = (PackageListDocument.PackageList.Package) iter
262 .next();
263 String name = packageItem.getPackageNameArray(0).getStringValue();
264 String path = packageItem.getPathArray(0).getStringValue();
265 packageInfo.put(name, path);
266 File spdFile = new File(workspaceDir + File.separatorChar + path + File.separatorChar + name + ".spd");
267 initPackageInfo(spdFile.getPath(), name);
268 //
269 // SPD Parse.
270 //
271 PackageSurfaceAreaDocument spdDoc = (PackageSurfaceAreaDocument) XmlObject.Factory.parse(spdFile);
272 Spd spd = new Spd(spdDoc, path);
273 spdTable.put(name, spd);
274
275 }
276 } catch (Exception e) {
277 throw new BuildException("Parse workspace Database [" + dbFile.getPath() + "] Error.\n" + e.getMessage());
278 }
279 }
280
281 /**
282 Parse every MSA files, get base name from MSA Header. And record those
283 values to ModuleInfo.
284
285 @param packageFilename the file name of the package
286 @param packageName the name of the package
287 @throws BuildException
288 SPD or MSA file is not valid
289 **/
290 private synchronized static void initPackageInfo(String packageFilename, String packageName) throws BuildException {
291 File packageFile = new File(packageFilename);
292 try {
293 PackageSurfaceAreaDocument spd = (PackageSurfaceAreaDocument) XmlObject.Factory.parse(packageFile);
294 List<MsaFilesDocument.MsaFiles.MsaFile> msasList = spd.getPackageSurfaceArea().getMsaFiles()
295 .getMsaFileList();
296 Iterator msasIter = msasList.iterator();
297 while (msasIter.hasNext()) {
298 MsaFilesDocument.MsaFiles.MsaFile msas = (MsaFilesDocument.MsaFiles.MsaFile) msasIter.next();
299 String msaFilename = msas.getFilename().getStringValue();
300 File msaFile = new File(workspaceDir + File.separatorChar + GlobalData.getPackagePath(packageName)
301 + File.separatorChar + msaFilename);
302 SurfaceAreaParser surfaceAreaParser = new SurfaceAreaParser();
303 Map<String, XmlObject> map = surfaceAreaParser.parseFile(msaFile);
304 String baseName = "";
305 XmlObject header = null;
306 if ((header = map.get("MsaHeader")) != null) {
307 baseName = ((MsaHeader) header).getBaseName().getStringValue();
308 } else if ((header = map.get("MsaLibHeader")) != null) {
309 baseName = ((MsaLibHeader) header).getBaseName().getStringValue();
310 } else {
311 continue;
312 }
313 nativeMsa.put(baseName, map);
314 String[] info = { msaFilename, packageName };
315 moduleInfo.put(baseName, info);
316 }
317 } catch (Exception e) {
318 throw new BuildException("Parse package description file [" + packageFile.getPath() + "] Error.\n"
319 + e.getMessage());
320 }
321 }
322
323 /**
324 Query the libraries which the module depends on.
325
326 @param moduleName the base name of the module
327 @return the libraries which the module depends on
328 **/
329 public synchronized static String[] getModuleLibrary(String moduleName, String arch) {
330 Set<String> set = moduleLibraryMap.get(moduleName + "-" + arch);
331 return set.toArray(new String[set.size()]);
332 }
333
334 /**
335 Register module's library list which it depends on for later use.
336
337 @param moduleName the base name of the module
338 @param libraryList the libraries which the module depends on
339 **/
340 public synchronized static void addModuleLibrary(String moduleName, String arch, Set<String> libraryList) {
341 moduleLibraryMap.put(moduleName + "-" + arch, libraryList);
342 }
343
344 /**
345 Query the library absolute file name with library name.
346
347 @param library the base name of the library
348 @return the library absolute file name
349 **/
350 public synchronized static String getLibrary(String library, String arch) {
351 return libraries.get(library + "-" + arch);
352 }
353
354 /**
355 Register library absolute file name for later use.
356
357 @param library the base name of the library
358 @param resultPath the library absolute file name
359 **/
360 public synchronized static void addLibrary(String library, String arch, String resultPath) {
361 libraries.put(library + "-" + arch, resultPath);
362 }
363
364 /**
365 Whether the module with ARCH has built in the previous build.
366
367 @param moduleName the base name of the module
368 @param arch current build ARCH
369 @return true if the module has built in previous, otherwise return false
370 **/
371 public synchronized static boolean isModuleBuilt(String moduleName, String arch) {
372 return builtModules.contains(moduleName + "-" + arch);
373 }
374
375 /**
376 Register the module with ARCH has built.
377
378 @param moduleName the base name of the module
379 @param arch current build ARCH
380 **/
381 public synchronized static void registerBuiltModule(String moduleName, String arch) {
382 builtModules.add(moduleName + "-" + arch);
383 }
384
385 /**
386 Whether the module's surface area has parsed in the previous build.
387
388 @param moduleName the base name of the module
389 @return true if the module's surface area has parsed in previous, otherwise
390 return false
391 **/
392 public synchronized static boolean isModuleParsed(String moduleName) {
393 return parsedModules.containsKey(moduleName);
394 }
395
396 /**
397 Query overrided module surface area information. If current is Package
398 or Platform build, also include the information from FPD file.
399
400 <p>Note that surface area parsing is incremental. That means the method will
401 only to parse the MSA and MBD files when never parsed before. </p>
402
403 @param moduleName the base name of the module
404 @return the overrided module surface area information
405 @throws BuildException
406 MSA or MBD is not valid
407 **/
408 public synchronized static Map<String, XmlObject> getDoc(String moduleName) throws BuildException {
409 if (parsedModules.containsKey(moduleName)) {
410 return parsedModules.get(moduleName);
411 }
412 Map<String, XmlObject> msaMap = getNativeMsa(moduleName);
413 Map<String, XmlObject> mbdMap = getNativeMbd(moduleName);
414 OverrideProcess op = new OverrideProcess();
415 Map<String, XmlObject> map = op.override(mbdMap, msaMap);
416 //
417 // IF IT IS A PALTFORM BUILD, OVERRIDE FROM PLATFORM
418 //
419 if (FpdParserTask.platformBuildOptions != null) {
420 Map<String, XmlObject> platformMap = new HashMap<String, XmlObject>();
421 platformMap.put("BuildOptions", FpdParserTask.platformBuildOptions);
422 Map<String, XmlObject> overrideMap = op.override(platformMap, OverrideProcess.deal(map));
423 GlobalData.registerModule(moduleName, overrideMap);
424 return overrideMap;
425 } else {
426 parsedModules.put(moduleName, map);
427 return map;
428 }
429 }
430
431 /**
432 Query the native MSA information with module base name.
433
434 <p>Note that MSA parsing is incremental. That means the method will
435 only to parse the MSA files when never parsed before. </p>
436
437 @param moduleName the base name of the module
438 @return the native MSA information
439 @throws BuildException
440 MSA file is not valid
441 **/
442 public synchronized static Map<String, XmlObject> getNativeMsa(String moduleName) throws BuildException {
443 if (nativeMsa.containsKey(moduleName)) {
444 return nativeMsa.get(moduleName);
445 }
446 String msaFilename = getMsaFilename(moduleName);
447 File msaFile = new File(msaFilename);
448 if (!msaFile.exists()) {
449 throw new BuildException("Info: Surface Area file [" + msaFile.getPath() + "] can't found.");
450 }
451 SurfaceAreaParser surfaceAreaParser = new SurfaceAreaParser();
452 Map<String, XmlObject> map = surfaceAreaParser.parseFile(msaFile);
453 nativeMsa.put(moduleName, map);
454 return map;
455 }
456
457 /**
458 Query the native MBD information with module base name.
459
460 <p>Note that MBD parsing is incremental. That means the method will
461 only to parse the MBD files when never parsed before. </p>
462
463 @param moduleName the base name of the module
464 @return the native MBD information
465 @throws BuildException
466 MBD file is not valid
467 **/
468 public synchronized static Map<String, XmlObject> getNativeMbd(String moduleName) throws BuildException {
469 if (nativeMbd.containsKey(moduleName)) {
470 return nativeMbd.get(moduleName);
471 }
472 String mbdFilename = getMbdFilename(moduleName);
473 File mbdFile = new File(mbdFilename);
474 if (!mbdFile.exists()) {
475 throw new BuildException("Info: Surface Area file [" + mbdFile.getPath() + "] can't found.");
476 }
477 SurfaceAreaParser surfaceAreaParser = new SurfaceAreaParser();
478 Map<String, XmlObject> map = surfaceAreaParser.parseFile(mbdFile);
479 nativeMbd.put(moduleName, map);
480 return map;
481 }
482
483 /**
484 Register module overrided surface area information. If has existed, then update.
485
486 @param moduleName the base name of the module
487 @param map the overrided surface area information
488 **/
489 public synchronized static void registerModule(String moduleName, Map<String, XmlObject> map) {
490 parsedModules.put(moduleName, map);
491 }
492
493 /**
494 *
495 * @param protocolName
496 * @return
497 */
498 public synchronized static String[] getProtocolInfoGuid(String protocolName) {
499 Set set = spdTable.keySet();
500 Iterator iter = set.iterator();
501 String[] cNameGuid = null;
502
503 while (iter.hasNext()) {
504 Spd spd = (Spd) spdTable.get(iter.next());
505 cNameGuid = spd.getProtocolNameGuidArray(protocolName);
506 if (cNameGuid != null) {
507 break;
508 }
509 }
510 return cNameGuid;
511 }
512
513 public synchronized static String[] getPpiInfoGuid(String ppiName) {
514 Set set = spdTable.keySet();
515 Iterator iter = set.iterator();
516 String[] cNameGuid = null;
517
518 while (iter.hasNext()) {
519 Spd spd = (Spd) spdTable.get(iter.next());
520 cNameGuid = spd.getPpiCnameGuidArray(ppiName);
521
522 if (cNameGuid != null) {
523 break;
524 }
525 }
526 return cNameGuid;
527 }
528
529 /**
530 *
531 * @param guidName
532 * @return
533 */
534 public synchronized static String[] getGuidInfoGuid(String guidName) {
535 String[] cNameGuid = null;
536 Set set = spdTable.keySet();
537 Iterator iter = set.iterator();
538
539 while (iter.hasNext()) {
540 Spd spd = (Spd) spdTable.get(iter.next());
541 cNameGuid = spd.getGuidNameArray(guidName);
542 if (cNameGuid != null) {
543 break;
544 }
545 }
546 return cNameGuid;
547 }
548
549 public synchronized static String getLibClassIncluder(String libName) {
550 String libIncluder = null;
551 Set set = spdTable.keySet();
552 Iterator iter = set.iterator();
553
554 while (iter.hasNext()) {
555 String packageName = (String) iter.next();
556 Spd spd = (Spd) spdTable.get(packageName);
557 libIncluder = spd.getLibClassIncluder(libName);
558 String packagePath = spd.packagePath;
559 if (packagePath != null) {
560 packagePath = packagePath.replace('\\', File.separatorChar);
561 packagePath = packagePath.replace('/', File.separatorChar);
562 } else {
563 packagePath = packageName;
564 }
565 if (libIncluder != null) {
566 libIncluder = libIncluder.replace('\\', File.separatorChar);
567 libIncluder = libIncluder.replace('/', File.separatorChar);
568 libIncluder = packageName + File.separatorChar + libIncluder;
569 break;
570 }
571 }
572 return libIncluder;
573 }
574
575 public synchronized static String getModuleInfoByPackageName(String packageName, String moduleType) {
576 Spd spd;
577 String includeFile = null;
578 String includeStr = "";
579 String cleanPath = "";
580
581 spd = (Spd) spdTable.get(packageName);
582 includeFile = spd.getModuleTypeIncluder(moduleType);
583 if (includeFile != null) {
584 includeFile = includeFile.replace('\\', File.separatorChar);
585 includeFile = includeFile.replace('/', File.separatorChar);
586 includeStr = CommonDefinition.include + " <" + includeStr;
587 cleanPath = spd.packagePath;
588 cleanPath = cleanPath.replace('\\', File.separatorChar);
589 cleanPath = cleanPath.replace('/', File.separatorChar);
590
591 if (cleanPath.charAt(spd.packagePath.length() - 1) != File.separatorChar) {
592 cleanPath = cleanPath + File.separatorChar;
593 }
594 includeStr = includeStr + cleanPath;
595 includeStr = includeStr + includeFile;
596 includeStr = includeStr + ">\r\n";
597 }
598
599 return includeStr;
600 }
601
602 public synchronized static void setLibInstanceInfo(String libName, String libConstructor, String libDesturctor) {
603 String[] libConsDes = new String[2];
604 libConsDes[0] = libConstructor;
605 libConsDes[1] = libDesturctor;
606
607 libInstanceInfo.put(libName, libConsDes);
608 }
609
610 public synchronized static boolean isHaveLibInstance(String libName) {
611 return libInstanceInfo.containsKey(libName);
612 }
613
614 public synchronized static String getLibInstanceConstructor(String libName) {
615 String[] libInstanceValue;
616 libInstanceValue = libInstanceInfo.get(libName);
617 if (libInstanceValue != null) {
618 return libInstanceValue[0];
619 } else {
620 return null;
621 }
622 }
623
624 public synchronized static String getLibInstanceDestructor(String libName) {
625 String[] libInstanceValue;
626 libInstanceValue = libInstanceInfo.get(libName);
627 if (libInstanceValue != null) {
628 return libInstanceValue[1];
629 } else {
630 return null;
631 }
632 }
633
634 public synchronized static MemoryDatabaseManager getPCDMemoryDBManager() {
635 return pcdDbManager;
636 }
637 }