]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
dad6ecd49a071fb0f81cc6012441698cb22c8bfd
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / WorkspaceDatabase.py
1 ## @file
2 # This file is used to create a database used by build tool
3 #
4 # Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
9 #
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 #
13
14 ##
15 # Import Modules
16 #
17 import sqlite3
18 import os
19 import os.path
20 import pickle
21 import uuid
22
23 import Common.EdkLogger as EdkLogger
24 import Common.GlobalData as GlobalData
25
26 from Common.String import *
27 from Common.DataType import *
28 from Common.Misc import *
29 from types import *
30
31 from CommonDataClass.CommonClass import SkuInfoClass
32
33 from MetaDataTable import *
34 from MetaFileTable import *
35 from MetaFileParser import *
36 from BuildClassObject import *
37
38 ## Platform build information from DSC file
39 #
40 # This class is used to retrieve information stored in database and convert them
41 # into PlatformBuildClassObject form for easier use for AutoGen.
42 #
43 class DscBuildData(PlatformBuildClassObject):
44 # dict used to convert PCD type in database to string used by build tool
45 _PCD_TYPE_STRING_ = {
46 MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild",
47 MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule",
48 MODEL_PCD_FEATURE_FLAG : "FeatureFlag",
49 MODEL_PCD_DYNAMIC : "Dynamic",
50 MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic",
51 MODEL_PCD_DYNAMIC_HII : "DynamicHii",
52 MODEL_PCD_DYNAMIC_VPD : "DynamicVpd",
53 MODEL_PCD_DYNAMIC_EX : "DynamicEx",
54 MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx",
55 MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii",
56 MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd",
57 }
58
59 # dict used to convert part of [Defines] to members of DscBuildData directly
60 _PROPERTY_ = {
61 #
62 # Required Fields
63 #
64 TAB_DSC_DEFINES_PLATFORM_NAME : "_PlatformName",
65 TAB_DSC_DEFINES_PLATFORM_GUID : "_Guid",
66 TAB_DSC_DEFINES_PLATFORM_VERSION : "_Version",
67 TAB_DSC_DEFINES_DSC_SPECIFICATION : "_DscSpecification",
68 #TAB_DSC_DEFINES_OUTPUT_DIRECTORY : "_OutputDirectory",
69 #TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES : "_SupArchList",
70 #TAB_DSC_DEFINES_BUILD_TARGETS : "_BuildTargets",
71 #TAB_DSC_DEFINES_SKUID_IDENTIFIER : "_SkuName",
72 #TAB_DSC_DEFINES_FLASH_DEFINITION : "_FlashDefinition",
73 TAB_DSC_DEFINES_BUILD_NUMBER : "_BuildNumber",
74 TAB_DSC_DEFINES_MAKEFILE_NAME : "_MakefileName",
75 TAB_DSC_DEFINES_BS_BASE_ADDRESS : "_BsBaseAddress",
76 TAB_DSC_DEFINES_RT_BASE_ADDRESS : "_RtBaseAddress",
77 }
78
79 # used to compose dummy library class name for those forced library instances
80 _NullLibraryNumber = 0
81
82 ## Constructor of DscBuildData
83 #
84 # Initialize object of DscBuildData
85 #
86 # @param FilePath The path of platform description file
87 # @param RawData The raw data of DSC file
88 # @param BuildDataBase Database used to retrieve module/package information
89 # @param Arch The target architecture
90 # @param Platform (not used for DscBuildData)
91 # @param Macros Macros used for replacement in DSC file
92 #
93 def __init__(self, FilePath, RawData, BuildDataBase, Arch='COMMON', Platform='DUMMY', Macros={}):
94 self.MetaFile = FilePath
95 self._RawData = RawData
96 self._Bdb = BuildDataBase
97 self._Arch = Arch
98 self._Macros = Macros
99 self._Clear()
100 RecordList = self._RawData[MODEL_META_DATA_DEFINE, self._Arch]
101 for Record in RecordList:
102 GlobalData.gEdkGlobal[Record[0]] = Record[1]
103
104 RecordList = self._RawData[MODEL_META_DATA_GLOBAL_DEFINE, self._Arch]
105 for Record in RecordList:
106 GlobalData.gGlobalDefines[Record[0]] = Record[1]
107
108 ## XXX[key] = value
109 def __setitem__(self, key, value):
110 self.__dict__[self._PROPERTY_[key]] = value
111
112 ## value = XXX[key]
113 def __getitem__(self, key):
114 return self.__dict__[self._PROPERTY_[key]]
115
116 ## "in" test support
117 def __contains__(self, key):
118 return key in self._PROPERTY_
119
120 ## Set all internal used members of DscBuildData to None
121 def _Clear(self):
122 self._Header = None
123 self._PlatformName = None
124 self._Guid = None
125 self._Version = None
126 self._DscSpecification = None
127 self._OutputDirectory = None
128 self._SupArchList = None
129 self._BuildTargets = None
130 self._SkuName = None
131 self._FlashDefinition = None
132 self._BuildNumber = None
133 self._MakefileName = None
134 self._BsBaseAddress = None
135 self._RtBaseAddress = None
136 self._SkuIds = None
137 self._Modules = None
138 self._LibraryInstances = None
139 self._LibraryClasses = None
140 self._Pcds = None
141 self._BuildOptions = None
142 self._LoadFixAddress = None
143 self._VpdToolGuid = None
144 self._VpdFileName = None
145
146 ## Get architecture
147 def _GetArch(self):
148 return self._Arch
149
150 ## Set architecture
151 #
152 # Changing the default ARCH to another may affect all other information
153 # because all information in a platform may be ARCH-related. That's
154 # why we need to clear all internal used members, in order to cause all
155 # information to be re-retrieved.
156 #
157 # @param Value The value of ARCH
158 #
159 def _SetArch(self, Value):
160 if self._Arch == Value:
161 return
162 self._Arch = Value
163 self._Clear()
164
165 ## Retrieve all information in [Defines] section
166 #
167 # (Retriving all [Defines] information in one-shot is just to save time.)
168 #
169 def _GetHeaderInfo(self):
170 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch]
171 for Record in RecordList:
172 Name = Record[0]
173 # items defined _PROPERTY_ don't need additional processing
174 if Name in self:
175 self[Name] = Record[1]
176 # some special items in [Defines] section need special treatment
177 elif Name == TAB_DSC_DEFINES_OUTPUT_DIRECTORY:
178 self._OutputDirectory = NormPath(Record[1], self._Macros)
179 if ' ' in self._OutputDirectory:
180 EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "No space is allowed in OUTPUT_DIRECTORY",
181 File=self.MetaFile, Line=Record[-1],
182 ExtraData=self._OutputDirectory)
183 elif Name == TAB_DSC_DEFINES_FLASH_DEFINITION:
184 self._FlashDefinition = PathClass(NormPath(Record[1], self._Macros), GlobalData.gWorkspace)
185 ErrorCode, ErrorInfo = self._FlashDefinition.Validate('.fdf')
186 if ErrorCode != 0:
187 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=Record[-1],
188 ExtraData=ErrorInfo)
189 elif Name == TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES:
190 self._SupArchList = GetSplitValueList(Record[1], TAB_VALUE_SPLIT)
191 elif Name == TAB_DSC_DEFINES_BUILD_TARGETS:
192 self._BuildTargets = GetSplitValueList(Record[1])
193 elif Name == TAB_DSC_DEFINES_SKUID_IDENTIFIER:
194 if self._SkuName == None:
195 self._SkuName = Record[1]
196 elif Name == TAB_FIX_LOAD_TOP_MEMORY_ADDRESS:
197 self._LoadFixAddress = Record[1]
198 elif Name == TAB_DSC_DEFINES_VPD_TOOL_GUID:
199 #
200 # try to convert GUID to a real UUID value to see whether the GUID is format
201 # for VPD_TOOL_GUID is correct.
202 #
203 try:
204 uuid.UUID(Record[1])
205 except:
206 EdkLogger.error("build", FORMAT_INVALID, "Invalid GUID format for VPD_TOOL_GUID", File=self.MetaFile)
207 self._VpdToolGuid = Record[1]
208 elif Name == TAB_DSC_DEFINES_VPD_FILENAME:
209 self._VpdFileName = Record[1]
210 # set _Header to non-None in order to avoid database re-querying
211 self._Header = 'DUMMY'
212
213 ## Retrieve platform name
214 def _GetPlatformName(self):
215 if self._PlatformName == None:
216 if self._Header == None:
217 self._GetHeaderInfo()
218 if self._PlatformName == None:
219 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_NAME", File=self.MetaFile)
220 return self._PlatformName
221
222 ## Retrieve file guid
223 def _GetFileGuid(self):
224 if self._Guid == None:
225 if self._Header == None:
226 self._GetHeaderInfo()
227 if self._Guid == None:
228 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No FILE_GUID", File=self.MetaFile)
229 return self._Guid
230
231 ## Retrieve platform version
232 def _GetVersion(self):
233 if self._Version == None:
234 if self._Header == None:
235 self._GetHeaderInfo()
236 if self._Version == None:
237 self._Version = ''
238 return self._Version
239
240 ## Retrieve platform description file version
241 def _GetDscSpec(self):
242 if self._DscSpecification == None:
243 if self._Header == None:
244 self._GetHeaderInfo()
245 if self._DscSpecification == None:
246 self._DscSpecification = ''
247 return self._DscSpecification
248
249 ## Retrieve OUTPUT_DIRECTORY
250 def _GetOutpuDir(self):
251 if self._OutputDirectory == None:
252 if self._Header == None:
253 self._GetHeaderInfo()
254 if self._OutputDirectory == None:
255 self._OutputDirectory = os.path.join("Build", self._PlatformName)
256 return self._OutputDirectory
257
258 ## Retrieve SUPPORTED_ARCHITECTURES
259 def _GetSupArch(self):
260 if self._SupArchList == None:
261 if self._Header == None:
262 self._GetHeaderInfo()
263 if self._SupArchList == None:
264 self._SupArchList = ARCH_LIST
265 return self._SupArchList
266
267 ## Retrieve BUILD_TARGETS
268 def _GetBuildTarget(self):
269 if self._BuildTargets == None:
270 if self._Header == None:
271 self._GetHeaderInfo()
272 if self._BuildTargets == None:
273 self._BuildTargets = ['DEBUG', 'RELEASE']
274 return self._BuildTargets
275
276 ## Retrieve SKUID_IDENTIFIER
277 def _GetSkuName(self):
278 if self._SkuName == None:
279 if self._Header == None:
280 self._GetHeaderInfo()
281 if self._SkuName == None or self._SkuName not in self.SkuIds:
282 self._SkuName = 'DEFAULT'
283 return self._SkuName
284
285 ## Override SKUID_IDENTIFIER
286 def _SetSkuName(self, Value):
287 if Value in self.SkuIds:
288 self._SkuName = Value
289 # Needs to re-retrieve the PCD information
290 self._Pcds = None
291
292 def _GetFdfFile(self):
293 if self._FlashDefinition == None:
294 if self._Header == None:
295 self._GetHeaderInfo()
296 if self._FlashDefinition == None:
297 self._FlashDefinition = ''
298 return self._FlashDefinition
299
300 ## Retrieve FLASH_DEFINITION
301 def _GetBuildNumber(self):
302 if self._BuildNumber == None:
303 if self._Header == None:
304 self._GetHeaderInfo()
305 if self._BuildNumber == None:
306 self._BuildNumber = ''
307 return self._BuildNumber
308
309 ## Retrieve MAKEFILE_NAME
310 def _GetMakefileName(self):
311 if self._MakefileName == None:
312 if self._Header == None:
313 self._GetHeaderInfo()
314 if self._MakefileName == None:
315 self._MakefileName = ''
316 return self._MakefileName
317
318 ## Retrieve BsBaseAddress
319 def _GetBsBaseAddress(self):
320 if self._BsBaseAddress == None:
321 if self._Header == None:
322 self._GetHeaderInfo()
323 if self._BsBaseAddress == None:
324 self._BsBaseAddress = ''
325 return self._BsBaseAddress
326
327 ## Retrieve RtBaseAddress
328 def _GetRtBaseAddress(self):
329 if self._RtBaseAddress == None:
330 if self._Header == None:
331 self._GetHeaderInfo()
332 if self._RtBaseAddress == None:
333 self._RtBaseAddress = ''
334 return self._RtBaseAddress
335
336 ## Retrieve the top address for the load fix address
337 def _GetLoadFixAddress(self):
338 if self._LoadFixAddress == None:
339 if self._Header == None:
340 self._GetHeaderInfo()
341 if self._LoadFixAddress == None:
342 self._LoadFixAddress = ''
343 return self._LoadFixAddress
344
345 ## Retrieve the GUID string for VPD tool
346 def _GetVpdToolGuid(self):
347 if self._VpdToolGuid == None:
348 if self._Header == None:
349 self._GetHeaderInfo()
350 if self._VpdToolGuid == None:
351 self._VpdToolGuid = ''
352 return self._VpdToolGuid
353
354 ## Retrieve the VPD file Name, this is optional in DSC file
355 def _GetVpdFileName(self):
356 if self._VpdFileName == None:
357 if self._Header == None:
358 self._GetHeaderInfo()
359 if self._VpdFileName == None:
360 self._VpdFileName = ''
361 return self._VpdFileName
362
363 ## Retrieve [SkuIds] section information
364 def _GetSkuIds(self):
365 if self._SkuIds == None:
366 self._SkuIds = {}
367 RecordList = self._RawData[MODEL_EFI_SKU_ID]
368 for Record in RecordList:
369 if Record[0] in [None, '']:
370 EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID number',
371 File=self.MetaFile, Line=Record[-1])
372 if Record[1] in [None, '']:
373 EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID name',
374 File=self.MetaFile, Line=Record[-1])
375 self._SkuIds[Record[1]] = Record[0]
376 if 'DEFAULT' not in self._SkuIds:
377 self._SkuIds['DEFAULT'] = 0
378 return self._SkuIds
379
380 ## Retrieve [Components] section information
381 def _GetModules(self):
382 if self._Modules != None:
383 return self._Modules
384
385 self._Modules = sdict()
386 RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch]
387 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource}
388 Macros.update(self._Macros)
389 for Record in RecordList:
390 ModuleFile = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
391 ModuleId = Record[5]
392 LineNo = Record[6]
393
394 # check the file validation
395 ErrorCode, ErrorInfo = ModuleFile.Validate('.inf')
396 if ErrorCode != 0:
397 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
398 ExtraData=ErrorInfo)
399 # Check duplication
400 if ModuleFile in self._Modules:
401 EdkLogger.error('build', FILE_DUPLICATED, File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo)
402
403 Module = ModuleBuildClassObject()
404 Module.MetaFile = ModuleFile
405
406 # get module override path
407 RecordList = self._RawData[MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH, self._Arch, None, ModuleId]
408 if RecordList != []:
409 Module.SourceOverridePath = os.path.join(GlobalData.gWorkspace, NormPath(RecordList[0][0], Macros))
410
411 # Check if the source override path exists
412 if not os.path.isdir(Module.SourceOverridePath):
413 EdkLogger.error('build', FILE_NOT_FOUND, Message = 'Source override path does not exist:', File=self.MetaFile, ExtraData=Module.SourceOverridePath, Line=LineNo)
414
415 #Add to GlobalData Variables
416 GlobalData.gOverrideDir[ModuleFile.Key] = Module.SourceOverridePath
417
418 # get module private library instance
419 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, ModuleId]
420 for Record in RecordList:
421 LibraryClass = Record[0]
422 LibraryPath = PathClass(NormPath(Record[1], Macros), GlobalData.gWorkspace, Arch=self._Arch)
423 LineNo = Record[-1]
424
425 # check the file validation
426 ErrorCode, ErrorInfo = LibraryPath.Validate('.inf')
427 if ErrorCode != 0:
428 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
429 ExtraData=ErrorInfo)
430
431 if LibraryClass == '' or LibraryClass == 'NULL':
432 self._NullLibraryNumber += 1
433 LibraryClass = 'NULL%d' % self._NullLibraryNumber
434 EdkLogger.verbose("Found forced library for %s\n\t%s [%s]" % (ModuleFile, LibraryPath, LibraryClass))
435 Module.LibraryClasses[LibraryClass] = LibraryPath
436 if LibraryPath not in self.LibraryInstances:
437 self.LibraryInstances.append(LibraryPath)
438
439 # get module private PCD setting
440 for Type in [MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, \
441 MODEL_PCD_FEATURE_FLAG, MODEL_PCD_DYNAMIC, MODEL_PCD_DYNAMIC_EX]:
442 RecordList = self._RawData[Type, self._Arch, None, ModuleId]
443 for TokenSpaceGuid, PcdCName, Setting, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList:
444 TokenList = GetSplitValueList(Setting)
445 DefaultValue = TokenList[0]
446 if len(TokenList) > 1:
447 MaxDatumSize = TokenList[1]
448 else:
449 MaxDatumSize = ''
450 TypeString = self._PCD_TYPE_STRING_[Type]
451 Pcd = PcdClassObject(
452 PcdCName,
453 TokenSpaceGuid,
454 TypeString,
455 '',
456 DefaultValue,
457 '',
458 MaxDatumSize,
459 {},
460 False,
461 None
462 )
463 Module.Pcds[PcdCName, TokenSpaceGuid] = Pcd
464
465 # get module private build options
466 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, None, ModuleId]
467 for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList:
468 if (ToolChainFamily, ToolChain) not in Module.BuildOptions:
469 Module.BuildOptions[ToolChainFamily, ToolChain] = Option
470 else:
471 OptionString = Module.BuildOptions[ToolChainFamily, ToolChain]
472 Module.BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option
473
474 self._Modules[ModuleFile] = Module
475 return self._Modules
476
477 ## Retrieve all possible library instances used in this platform
478 def _GetLibraryInstances(self):
479 if self._LibraryInstances == None:
480 self._GetLibraryClasses()
481 return self._LibraryInstances
482
483 ## Retrieve [LibraryClasses] information
484 def _GetLibraryClasses(self):
485 if self._LibraryClasses == None:
486 self._LibraryInstances = []
487 #
488 # tdict is a special dict kind of type, used for selecting correct
489 # library instance for given library class and module type
490 #
491 LibraryClassDict = tdict(True, 3)
492 # track all library class names
493 LibraryClassSet = set()
494 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch]
495 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource}
496 Macros.update(self._Macros)
497 for Record in RecordList:
498 LibraryClass, LibraryInstance, Dummy, Arch, ModuleType, Dummy, LineNo = Record
499 if LibraryClass == '' or LibraryClass == 'NULL':
500 self._NullLibraryNumber += 1
501 LibraryClass = 'NULL%d' % self._NullLibraryNumber
502 EdkLogger.verbose("Found forced library for arch=%s\n\t%s [%s]" % (Arch, LibraryInstance, LibraryClass))
503 LibraryClassSet.add(LibraryClass)
504 LibraryInstance = PathClass(NormPath(LibraryInstance, Macros), GlobalData.gWorkspace, Arch=self._Arch)
505 # check the file validation
506 ErrorCode, ErrorInfo = LibraryInstance.Validate('.inf')
507 if ErrorCode != 0:
508 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
509 ExtraData=ErrorInfo)
510
511 if ModuleType != 'COMMON' and ModuleType not in SUP_MODULE_LIST:
512 EdkLogger.error('build', OPTION_UNKNOWN, "Unknown module type [%s]" % ModuleType,
513 File=self.MetaFile, ExtraData=LibraryInstance, Line=LineNo)
514 LibraryClassDict[Arch, ModuleType, LibraryClass] = LibraryInstance
515 if LibraryInstance not in self._LibraryInstances:
516 self._LibraryInstances.append(LibraryInstance)
517
518 # resolve the specific library instance for each class and each module type
519 self._LibraryClasses = tdict(True)
520 for LibraryClass in LibraryClassSet:
521 # try all possible module types
522 for ModuleType in SUP_MODULE_LIST:
523 LibraryInstance = LibraryClassDict[self._Arch, ModuleType, LibraryClass]
524 if LibraryInstance == None:
525 continue
526 self._LibraryClasses[LibraryClass, ModuleType] = LibraryInstance
527
528 # for R8 style library instances, which are listed in different section
529 RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch]
530 for Record in RecordList:
531 File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
532 LineNo = Record[-1]
533 # check the file validation
534 ErrorCode, ErrorInfo = File.Validate('.inf')
535 if ErrorCode != 0:
536 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
537 ExtraData=ErrorInfo)
538 if File not in self._LibraryInstances:
539 self._LibraryInstances.append(File)
540 #
541 # we need the module name as the library class name, so we have
542 # to parse it here. (self._Bdb[] will trigger a file parse if it
543 # hasn't been parsed)
544 #
545 Library = self._Bdb[File, self._Arch]
546 self._LibraryClasses[Library.BaseName, ':dummy:'] = Library
547 return self._LibraryClasses
548
549 ## Retrieve all PCD settings in platform
550 def _GetPcds(self):
551 if self._Pcds == None:
552 self._Pcds = {}
553 self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
554 self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
555 self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
556 self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_DEFAULT))
557 self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_HII))
558 self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_VPD))
559 self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_EX_DEFAULT))
560 self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_EX_HII))
561 self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_EX_VPD))
562 return self._Pcds
563
564 ## Retrieve [BuildOptions]
565 def _GetBuildOptions(self):
566 if self._BuildOptions == None:
567 self._BuildOptions = {}
568 #
569 # Retrieve build option for EDKII style module
570 #
571 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, 'COMMON', EDKII_NAME]
572 for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList:
573 self._BuildOptions[ToolChainFamily, ToolChain, EDKII_NAME] = Option
574 #
575 # Retrieve build option for EDK style module
576 #
577 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, 'COMMON', EDK_NAME]
578 for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList:
579 self._BuildOptions[ToolChainFamily, ToolChain, EDK_NAME] = Option
580 return self._BuildOptions
581
582 ## Retrieve non-dynamic PCD settings
583 #
584 # @param Type PCD type
585 #
586 # @retval a dict object contains settings of given PCD type
587 #
588 def _GetPcd(self, Type):
589 Pcds = {}
590 #
591 # tdict is a special dict kind of type, used for selecting correct
592 # PCD settings for certain ARCH
593 #
594 PcdDict = tdict(True, 3)
595 PcdSet = set()
596 # Find out all possible PCD candidates for self._Arch
597 RecordList = self._RawData[Type, self._Arch]
598 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:
599 PcdSet.add((PcdCName, TokenSpaceGuid))
600 PcdDict[Arch, PcdCName, TokenSpaceGuid] = Setting
601 # Remove redundant PCD candidates
602 for PcdCName, TokenSpaceGuid in PcdSet:
603 ValueList = ['', '', '']
604 Setting = PcdDict[self._Arch, PcdCName, TokenSpaceGuid]
605 if Setting == None:
606 continue
607 TokenList = Setting.split(TAB_VALUE_SPLIT)
608 ValueList[0:len(TokenList)] = TokenList
609 PcdValue, DatumType, MaxDatumSize = ValueList
610 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
611 PcdCName,
612 TokenSpaceGuid,
613 self._PCD_TYPE_STRING_[Type],
614 DatumType,
615 PcdValue,
616 '',
617 MaxDatumSize,
618 {},
619 False,
620 None
621 )
622 return Pcds
623
624 ## Retrieve dynamic PCD settings
625 #
626 # @param Type PCD type
627 #
628 # @retval a dict object contains settings of given PCD type
629 #
630 def _GetDynamicPcd(self, Type):
631 Pcds = {}
632 #
633 # tdict is a special dict kind of type, used for selecting correct
634 # PCD settings for certain ARCH and SKU
635 #
636 PcdDict = tdict(True, 4)
637 PcdSet = set()
638 # Find out all possible PCD candidates for self._Arch
639 RecordList = self._RawData[Type, self._Arch]
640 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:
641 PcdSet.add((PcdCName, TokenSpaceGuid))
642 PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting
643 # Remove redundant PCD candidates, per the ARCH and SKU
644 for PcdCName, TokenSpaceGuid in PcdSet:
645 ValueList = ['', '', '']
646 Setting = PcdDict[self._Arch, self.SkuName, PcdCName, TokenSpaceGuid]
647 if Setting == None:
648 continue
649 TokenList = Setting.split(TAB_VALUE_SPLIT)
650 ValueList[0:len(TokenList)] = TokenList
651 PcdValue, DatumType, MaxDatumSize = ValueList
652
653 SkuInfo = SkuInfoClass(self.SkuName, self.SkuIds[self.SkuName], '', '', '', '', '', PcdValue)
654 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
655 PcdCName,
656 TokenSpaceGuid,
657 self._PCD_TYPE_STRING_[Type],
658 DatumType,
659 PcdValue,
660 '',
661 MaxDatumSize,
662 {self.SkuName : SkuInfo},
663 False,
664 None
665 )
666 return Pcds
667
668 ## Retrieve dynamic HII PCD settings
669 #
670 # @param Type PCD type
671 #
672 # @retval a dict object contains settings of given PCD type
673 #
674 def _GetDynamicHiiPcd(self, Type):
675 Pcds = {}
676 #
677 # tdict is a special dict kind of type, used for selecting correct
678 # PCD settings for certain ARCH and SKU
679 #
680 PcdDict = tdict(True, 4)
681 PcdSet = set()
682 RecordList = self._RawData[Type, self._Arch]
683 # Find out all possible PCD candidates for self._Arch
684 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:
685 PcdSet.add((PcdCName, TokenSpaceGuid))
686 PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting
687 # Remove redundant PCD candidates, per the ARCH and SKU
688 for PcdCName, TokenSpaceGuid in PcdSet:
689 ValueList = ['', '', '', '']
690 Setting = PcdDict[self._Arch, self.SkuName, PcdCName, TokenSpaceGuid]
691 if Setting == None:
692 continue
693 TokenList = Setting.split(TAB_VALUE_SPLIT)
694 ValueList[0:len(TokenList)] = TokenList
695 VariableName, VariableGuid, VariableOffset, DefaultValue = ValueList
696 SkuInfo = SkuInfoClass(self.SkuName, self.SkuIds[self.SkuName], VariableName, VariableGuid, VariableOffset, DefaultValue)
697 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
698 PcdCName,
699 TokenSpaceGuid,
700 self._PCD_TYPE_STRING_[Type],
701 '',
702 DefaultValue,
703 '',
704 '',
705 {self.SkuName : SkuInfo},
706 False,
707 None
708 )
709 return Pcds
710
711 ## Retrieve dynamic VPD PCD settings
712 #
713 # @param Type PCD type
714 #
715 # @retval a dict object contains settings of given PCD type
716 #
717 def _GetDynamicVpdPcd(self, Type):
718 Pcds = {}
719 #
720 # tdict is a special dict kind of type, used for selecting correct
721 # PCD settings for certain ARCH and SKU
722 #
723 PcdDict = tdict(True, 4)
724 PcdSet = set()
725 # Find out all possible PCD candidates for self._Arch
726 RecordList = self._RawData[Type, self._Arch]
727 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:
728 PcdSet.add((PcdCName, TokenSpaceGuid))
729 PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting
730 # Remove redundant PCD candidates, per the ARCH and SKU
731 for PcdCName, TokenSpaceGuid in PcdSet:
732 ValueList = ['', '', '']
733 Setting = PcdDict[self._Arch, self.SkuName, PcdCName, TokenSpaceGuid]
734 if Setting == None:
735 continue
736 TokenList = Setting.split(TAB_VALUE_SPLIT)
737 ValueList[0:len(TokenList)] = TokenList
738 #
739 # For the VOID* type, it can have optional data of MaxDatumSize and InitialValue
740 # For the Integer & Boolean type, the optional data can only be InitialValue.
741 # At this point, we put all the data into the PcdClssObject for we don't know the PCD's datumtype
742 # until the DEC parser has been called.
743 #
744 VpdOffset, MaxDatumSize, InitialValue = ValueList
745
746 SkuInfo = SkuInfoClass(self.SkuName, self.SkuIds[self.SkuName], '', '', '', '', VpdOffset, InitialValue)
747 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
748 PcdCName,
749 TokenSpaceGuid,
750 self._PCD_TYPE_STRING_[Type],
751 '',
752 '',
753 '',
754 MaxDatumSize,
755 {self.SkuName : SkuInfo},
756 False,
757 None
758 )
759 return Pcds
760
761 ## Add external modules
762 #
763 # The external modules are mostly those listed in FDF file, which don't
764 # need "build".
765 #
766 # @param FilePath The path of module description file
767 #
768 def AddModule(self, FilePath):
769 FilePath = NormPath(FilePath)
770 if FilePath not in self.Modules:
771 Module = ModuleBuildClassObject()
772 Module.MetaFile = FilePath
773 self.Modules.append(Module)
774
775 ## Add external PCDs
776 #
777 # The external PCDs are mostly those listed in FDF file to specify address
778 # or offset information.
779 #
780 # @param Name Name of the PCD
781 # @param Guid Token space guid of the PCD
782 # @param Value Value of the PCD
783 #
784 def AddPcd(self, Name, Guid, Value):
785 if (Name, Guid) not in self.Pcds:
786 self.Pcds[Name, Guid] = PcdClassObject(Name, Guid, '', '', '', '', '', {}, False, None)
787 self.Pcds[Name, Guid].DefaultValue = Value
788
789 Arch = property(_GetArch, _SetArch)
790 Platform = property(_GetPlatformName)
791 PlatformName = property(_GetPlatformName)
792 Guid = property(_GetFileGuid)
793 Version = property(_GetVersion)
794 DscSpecification = property(_GetDscSpec)
795 OutputDirectory = property(_GetOutpuDir)
796 SupArchList = property(_GetSupArch)
797 BuildTargets = property(_GetBuildTarget)
798 SkuName = property(_GetSkuName, _SetSkuName)
799 FlashDefinition = property(_GetFdfFile)
800 BuildNumber = property(_GetBuildNumber)
801 MakefileName = property(_GetMakefileName)
802 BsBaseAddress = property(_GetBsBaseAddress)
803 RtBaseAddress = property(_GetRtBaseAddress)
804 LoadFixAddress = property(_GetLoadFixAddress)
805 VpdToolGuid = property(_GetVpdToolGuid)
806 VpdFileName = property(_GetVpdFileName)
807 SkuIds = property(_GetSkuIds)
808 Modules = property(_GetModules)
809 LibraryInstances = property(_GetLibraryInstances)
810 LibraryClasses = property(_GetLibraryClasses)
811 Pcds = property(_GetPcds)
812 BuildOptions = property(_GetBuildOptions)
813
814 ## Platform build information from DEC file
815 #
816 # This class is used to retrieve information stored in database and convert them
817 # into PackageBuildClassObject form for easier use for AutoGen.
818 #
819 class DecBuildData(PackageBuildClassObject):
820 # dict used to convert PCD type in database to string used by build tool
821 _PCD_TYPE_STRING_ = {
822 MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild",
823 MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule",
824 MODEL_PCD_FEATURE_FLAG : "FeatureFlag",
825 MODEL_PCD_DYNAMIC : "Dynamic",
826 MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic",
827 MODEL_PCD_DYNAMIC_HII : "DynamicHii",
828 MODEL_PCD_DYNAMIC_VPD : "DynamicVpd",
829 MODEL_PCD_DYNAMIC_EX : "DynamicEx",
830 MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx",
831 MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii",
832 MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd",
833 }
834
835 # dict used to convert part of [Defines] to members of DecBuildData directly
836 _PROPERTY_ = {
837 #
838 # Required Fields
839 #
840 TAB_DEC_DEFINES_PACKAGE_NAME : "_PackageName",
841 TAB_DEC_DEFINES_PACKAGE_GUID : "_Guid",
842 TAB_DEC_DEFINES_PACKAGE_VERSION : "_Version",
843 TAB_DEC_DEFINES_PKG_UNI_FILE : "_PkgUniFile",
844 }
845
846
847 ## Constructor of DecBuildData
848 #
849 # Initialize object of DecBuildData
850 #
851 # @param FilePath The path of package description file
852 # @param RawData The raw data of DEC file
853 # @param BuildDataBase Database used to retrieve module information
854 # @param Arch The target architecture
855 # @param Platform (not used for DecBuildData)
856 # @param Macros Macros used for replacement in DSC file
857 #
858 def __init__(self, File, RawData, BuildDataBase, Arch='COMMON', Platform='DUMMY', Macros={}):
859 self.MetaFile = File
860 self._PackageDir = File.Dir
861 self._RawData = RawData
862 self._Bdb = BuildDataBase
863 self._Arch = Arch
864 self._Macros = Macros
865 self._Clear()
866
867 ## XXX[key] = value
868 def __setitem__(self, key, value):
869 self.__dict__[self._PROPERTY_[key]] = value
870
871 ## value = XXX[key]
872 def __getitem__(self, key):
873 return self.__dict__[self._PROPERTY_[key]]
874
875 ## "in" test support
876 def __contains__(self, key):
877 return key in self._PROPERTY_
878
879 ## Set all internal used members of DecBuildData to None
880 def _Clear(self):
881 self._Header = None
882 self._PackageName = None
883 self._Guid = None
884 self._Version = None
885 self._PkgUniFile = None
886 self._Protocols = None
887 self._Ppis = None
888 self._Guids = None
889 self._Includes = None
890 self._LibraryClasses = None
891 self._Pcds = None
892
893 ## Get architecture
894 def _GetArch(self):
895 return self._Arch
896
897 ## Set architecture
898 #
899 # Changing the default ARCH to another may affect all other information
900 # because all information in a platform may be ARCH-related. That's
901 # why we need to clear all internal used members, in order to cause all
902 # information to be re-retrieved.
903 #
904 # @param Value The value of ARCH
905 #
906 def _SetArch(self, Value):
907 if self._Arch == Value:
908 return
909 self._Arch = Value
910 self._Clear()
911
912 ## Retrieve all information in [Defines] section
913 #
914 # (Retriving all [Defines] information in one-shot is just to save time.)
915 #
916 def _GetHeaderInfo(self):
917 RecordList = self._RawData[MODEL_META_DATA_HEADER]
918 for Record in RecordList:
919 Name = Record[0]
920 if Name in self:
921 self[Name] = Record[1]
922 self._Header = 'DUMMY'
923
924 ## Retrieve package name
925 def _GetPackageName(self):
926 if self._PackageName == None:
927 if self._Header == None:
928 self._GetHeaderInfo()
929 if self._PackageName == None:
930 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_NAME", File=self.MetaFile)
931 return self._PackageName
932
933 ## Retrieve file guid
934 def _GetFileGuid(self):
935 if self._Guid == None:
936 if self._Header == None:
937 self._GetHeaderInfo()
938 if self._Guid == None:
939 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_GUID", File=self.MetaFile)
940 return self._Guid
941
942 ## Retrieve package version
943 def _GetVersion(self):
944 if self._Version == None:
945 if self._Header == None:
946 self._GetHeaderInfo()
947 if self._Version == None:
948 self._Version = ''
949 return self._Version
950
951 ## Retrieve protocol definitions (name/value pairs)
952 def _GetProtocol(self):
953 if self._Protocols == None:
954 #
955 # tdict is a special kind of dict, used for selecting correct
956 # protocol defition for given ARCH
957 #
958 ProtocolDict = tdict(True)
959 NameList = []
960 # find out all protocol definitions for specific and 'common' arch
961 RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch]
962 for Name, Guid, Dummy, Arch, ID, LineNo in RecordList:
963 if Name not in NameList:
964 NameList.append(Name)
965 ProtocolDict[Arch, Name] = Guid
966 # use sdict to keep the order
967 self._Protocols = sdict()
968 for Name in NameList:
969 #
970 # limit the ARCH to self._Arch, if no self._Arch found, tdict
971 # will automatically turn to 'common' ARCH for trying
972 #
973 self._Protocols[Name] = ProtocolDict[self._Arch, Name]
974 return self._Protocols
975
976 ## Retrieve PPI definitions (name/value pairs)
977 def _GetPpi(self):
978 if self._Ppis == None:
979 #
980 # tdict is a special kind of dict, used for selecting correct
981 # PPI defition for given ARCH
982 #
983 PpiDict = tdict(True)
984 NameList = []
985 # find out all PPI definitions for specific arch and 'common' arch
986 RecordList = self._RawData[MODEL_EFI_PPI, self._Arch]
987 for Name, Guid, Dummy, Arch, ID, LineNo in RecordList:
988 if Name not in NameList:
989 NameList.append(Name)
990 PpiDict[Arch, Name] = Guid
991 # use sdict to keep the order
992 self._Ppis = sdict()
993 for Name in NameList:
994 #
995 # limit the ARCH to self._Arch, if no self._Arch found, tdict
996 # will automatically turn to 'common' ARCH for trying
997 #
998 self._Ppis[Name] = PpiDict[self._Arch, Name]
999 return self._Ppis
1000
1001 ## Retrieve GUID definitions (name/value pairs)
1002 def _GetGuid(self):
1003 if self._Guids == None:
1004 #
1005 # tdict is a special kind of dict, used for selecting correct
1006 # GUID defition for given ARCH
1007 #
1008 GuidDict = tdict(True)
1009 NameList = []
1010 # find out all protocol definitions for specific and 'common' arch
1011 RecordList = self._RawData[MODEL_EFI_GUID, self._Arch]
1012 for Name, Guid, Dummy, Arch, ID, LineNo in RecordList:
1013 if Name not in NameList:
1014 NameList.append(Name)
1015 GuidDict[Arch, Name] = Guid
1016 # use sdict to keep the order
1017 self._Guids = sdict()
1018 for Name in NameList:
1019 #
1020 # limit the ARCH to self._Arch, if no self._Arch found, tdict
1021 # will automatically turn to 'common' ARCH for trying
1022 #
1023 self._Guids[Name] = GuidDict[self._Arch, Name]
1024 return self._Guids
1025
1026 ## Retrieve public include paths declared in this package
1027 def _GetInclude(self):
1028 if self._Includes == None:
1029 self._Includes = []
1030 RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch]
1031 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource}
1032 Macros.update(self._Macros)
1033 for Record in RecordList:
1034 File = PathClass(NormPath(Record[0], Macros), self._PackageDir, Arch=self._Arch)
1035 LineNo = Record[-1]
1036 # validate the path
1037 ErrorCode, ErrorInfo = File.Validate()
1038 if ErrorCode != 0:
1039 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
1040
1041 # avoid duplicate include path
1042 if File not in self._Includes:
1043 self._Includes.append(File)
1044 return self._Includes
1045
1046 ## Retrieve library class declarations (not used in build at present)
1047 def _GetLibraryClass(self):
1048 if self._LibraryClasses == None:
1049 #
1050 # tdict is a special kind of dict, used for selecting correct
1051 # library class declaration for given ARCH
1052 #
1053 LibraryClassDict = tdict(True)
1054 LibraryClassSet = set()
1055 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch]
1056 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource}
1057 Macros.update(self._Macros)
1058 for LibraryClass, File, Dummy, Arch, ID, LineNo in RecordList:
1059 File = PathClass(NormPath(File, Macros), self._PackageDir, Arch=self._Arch)
1060 # check the file validation
1061 ErrorCode, ErrorInfo = File.Validate()
1062 if ErrorCode != 0:
1063 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
1064 LibraryClassSet.add(LibraryClass)
1065 LibraryClassDict[Arch, LibraryClass] = File
1066 self._LibraryClasses = sdict()
1067 for LibraryClass in LibraryClassSet:
1068 self._LibraryClasses[LibraryClass] = LibraryClassDict[self._Arch, LibraryClass]
1069 return self._LibraryClasses
1070
1071 ## Retrieve PCD declarations
1072 def _GetPcds(self):
1073 if self._Pcds == None:
1074 self._Pcds = {}
1075 self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
1076 self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
1077 self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
1078 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC))
1079 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
1080 return self._Pcds
1081
1082 ## Retrieve PCD declarations for given type
1083 def _GetPcd(self, Type):
1084 Pcds = {}
1085 #
1086 # tdict is a special kind of dict, used for selecting correct
1087 # PCD declaration for given ARCH
1088 #
1089 PcdDict = tdict(True, 3)
1090 # for summarizing PCD
1091 PcdSet = set()
1092 # find out all PCDs of the 'type'
1093 RecordList = self._RawData[Type, self._Arch]
1094 for TokenSpaceGuid, PcdCName, Setting, Arch, Dummy1, Dummy2 in RecordList:
1095 PcdDict[Arch, PcdCName, TokenSpaceGuid] = Setting
1096 PcdSet.add((PcdCName, TokenSpaceGuid))
1097
1098 for PcdCName, TokenSpaceGuid in PcdSet:
1099 ValueList = ['', '', '']
1100 #
1101 # limit the ARCH to self._Arch, if no self._Arch found, tdict
1102 # will automatically turn to 'common' ARCH and try again
1103 #
1104 Setting = PcdDict[self._Arch, PcdCName, TokenSpaceGuid]
1105 if Setting == None:
1106 continue
1107 TokenList = Setting.split(TAB_VALUE_SPLIT)
1108 ValueList[0:len(TokenList)] = TokenList
1109 DefaultValue, DatumType, TokenNumber = ValueList
1110 Pcds[PcdCName, TokenSpaceGuid, self._PCD_TYPE_STRING_[Type]] = PcdClassObject(
1111 PcdCName,
1112 TokenSpaceGuid,
1113 self._PCD_TYPE_STRING_[Type],
1114 DatumType,
1115 DefaultValue,
1116 TokenNumber,
1117 '',
1118 {},
1119 False,
1120 None
1121 )
1122 return Pcds
1123
1124
1125 Arch = property(_GetArch, _SetArch)
1126 PackageName = property(_GetPackageName)
1127 Guid = property(_GetFileGuid)
1128 Version = property(_GetVersion)
1129
1130 Protocols = property(_GetProtocol)
1131 Ppis = property(_GetPpi)
1132 Guids = property(_GetGuid)
1133 Includes = property(_GetInclude)
1134 LibraryClasses = property(_GetLibraryClass)
1135 Pcds = property(_GetPcds)
1136
1137 ## Module build information from INF file
1138 #
1139 # This class is used to retrieve information stored in database and convert them
1140 # into ModuleBuildClassObject form for easier use for AutoGen.
1141 #
1142 class InfBuildData(ModuleBuildClassObject):
1143 # dict used to convert PCD type in database to string used by build tool
1144 _PCD_TYPE_STRING_ = {
1145 MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild",
1146 MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule",
1147 MODEL_PCD_FEATURE_FLAG : "FeatureFlag",
1148 MODEL_PCD_DYNAMIC : "Dynamic",
1149 MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic",
1150 MODEL_PCD_DYNAMIC_HII : "DynamicHii",
1151 MODEL_PCD_DYNAMIC_VPD : "DynamicVpd",
1152 MODEL_PCD_DYNAMIC_EX : "DynamicEx",
1153 MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx",
1154 MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii",
1155 MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd",
1156 }
1157
1158 # dict used to convert part of [Defines] to members of InfBuildData directly
1159 _PROPERTY_ = {
1160 #
1161 # Required Fields
1162 #
1163 TAB_INF_DEFINES_BASE_NAME : "_BaseName",
1164 TAB_INF_DEFINES_FILE_GUID : "_Guid",
1165 TAB_INF_DEFINES_MODULE_TYPE : "_ModuleType",
1166 #
1167 # Optional Fields
1168 #
1169 TAB_INF_DEFINES_INF_VERSION : "_AutoGenVersion",
1170 TAB_INF_DEFINES_COMPONENT_TYPE : "_ComponentType",
1171 TAB_INF_DEFINES_MAKEFILE_NAME : "_MakefileName",
1172 #TAB_INF_DEFINES_CUSTOM_MAKEFILE : "_CustomMakefile",
1173 TAB_INF_DEFINES_VERSION_NUMBER : "_Version",
1174 TAB_INF_DEFINES_VERSION_STRING : "_Version",
1175 TAB_INF_DEFINES_VERSION : "_Version",
1176 TAB_INF_DEFINES_PCD_IS_DRIVER : "_PcdIsDriver",
1177 TAB_INF_DEFINES_SHADOW : "_Shadow",
1178
1179 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH : "_SourceOverridePath",
1180 }
1181
1182 # dict used to convert Component type to Module type
1183 _MODULE_TYPE_ = {
1184 "LIBRARY" : "BASE",
1185 "SECURITY_CORE" : "SEC",
1186 "PEI_CORE" : "PEI_CORE",
1187 "COMBINED_PEIM_DRIVER" : "PEIM",
1188 "PIC_PEIM" : "PEIM",
1189 "RELOCATABLE_PEIM" : "PEIM",
1190 "PE32_PEIM" : "PEIM",
1191 "BS_DRIVER" : "DXE_DRIVER",
1192 "RT_DRIVER" : "DXE_RUNTIME_DRIVER",
1193 "SAL_RT_DRIVER" : "DXE_SAL_DRIVER",
1194 "DXE_SMM_DRIVER" : "DXE_SMM_DRIVER",
1195 # "SMM_DRIVER" : "DXE_SMM_DRIVER",
1196 # "BS_DRIVER" : "DXE_SMM_DRIVER",
1197 # "BS_DRIVER" : "UEFI_DRIVER",
1198 "APPLICATION" : "UEFI_APPLICATION",
1199 "LOGO" : "BASE",
1200 }
1201
1202 # regular expression for converting XXX_FLAGS in [nmake] section to new type
1203 _NMAKE_FLAG_PATTERN_ = re.compile("(?:EBC_)?([A-Z]+)_(?:STD_|PROJ_|ARCH_)?FLAGS(?:_DLL|_ASL|_EXE)?", re.UNICODE)
1204 # dict used to convert old tool name used in [nmake] section to new ones
1205 _TOOL_CODE_ = {
1206 "C" : "CC",
1207 "LIB" : "SLINK",
1208 "LINK" : "DLINK",
1209 }
1210
1211
1212 ## Constructor of DscBuildData
1213 #
1214 # Initialize object of DscBuildData
1215 #
1216 # @param FilePath The path of platform description file
1217 # @param RawData The raw data of DSC file
1218 # @param BuildDataBase Database used to retrieve module/package information
1219 # @param Arch The target architecture
1220 # @param Platform The name of platform employing this module
1221 # @param Macros Macros used for replacement in DSC file
1222 #
1223 def __init__(self, FilePath, RawData, BuildDatabase, Arch='COMMON', Platform='COMMON', Macros={}):
1224 self.MetaFile = FilePath
1225 self._ModuleDir = FilePath.Dir
1226 self._RawData = RawData
1227 self._Bdb = BuildDatabase
1228 self._Arch = Arch
1229 self._Platform = 'COMMON'
1230 self._Macros = Macros
1231 self._SourceOverridePath = None
1232 if FilePath.Key in GlobalData.gOverrideDir:
1233 self._SourceOverridePath = GlobalData.gOverrideDir[FilePath.Key]
1234 self._Clear()
1235
1236 ## XXX[key] = value
1237 def __setitem__(self, key, value):
1238 self.__dict__[self._PROPERTY_[key]] = value
1239
1240 ## value = XXX[key]
1241 def __getitem__(self, key):
1242 return self.__dict__[self._PROPERTY_[key]]
1243
1244 ## "in" test support
1245 def __contains__(self, key):
1246 return key in self._PROPERTY_
1247
1248 ## Set all internal used members of InfBuildData to None
1249 def _Clear(self):
1250 self._Header_ = None
1251 self._AutoGenVersion = None
1252 self._BaseName = None
1253 self._ModuleType = None
1254 self._ComponentType = None
1255 self._BuildType = None
1256 self._Guid = None
1257 self._Version = None
1258 self._PcdIsDriver = None
1259 self._BinaryModule = None
1260 self._Shadow = None
1261 self._MakefileName = None
1262 self._CustomMakefile = None
1263 self._Specification = None
1264 self._LibraryClass = None
1265 self._ModuleEntryPointList = None
1266 self._ModuleUnloadImageList = None
1267 self._ConstructorList = None
1268 self._DestructorList = None
1269 self._Defs = None
1270 self._Binaries = None
1271 self._Sources = None
1272 self._LibraryClasses = None
1273 self._Libraries = None
1274 self._Protocols = None
1275 self._Ppis = None
1276 self._Guids = None
1277 self._Includes = None
1278 self._Packages = None
1279 self._Pcds = None
1280 self._BuildOptions = None
1281 self._Depex = None
1282 self._DepexExpression = None
1283 #self._SourceOverridePath = None
1284
1285 ## Get architecture
1286 def _GetArch(self):
1287 return self._Arch
1288
1289 ## Set architecture
1290 #
1291 # Changing the default ARCH to another may affect all other information
1292 # because all information in a platform may be ARCH-related. That's
1293 # why we need to clear all internal used members, in order to cause all
1294 # information to be re-retrieved.
1295 #
1296 # @param Value The value of ARCH
1297 #
1298 def _SetArch(self, Value):
1299 if self._Arch == Value:
1300 return
1301 self._Arch = Value
1302 self._Clear()
1303
1304 ## Return the name of platform employing this module
1305 def _GetPlatform(self):
1306 return self._Platform
1307
1308 ## Change the name of platform employing this module
1309 #
1310 # Changing the default name of platform to another may affect some information
1311 # because they may be PLATFORM-related. That's why we need to clear all internal
1312 # used members, in order to cause all information to be re-retrieved.
1313 #
1314 def _SetPlatform(self, Value):
1315 if self._Platform == Value:
1316 return
1317 self._Platform = Value
1318 self._Clear()
1319
1320 ## Retrieve all information in [Defines] section
1321 #
1322 # (Retriving all [Defines] information in one-shot is just to save time.)
1323 #
1324 def _GetHeaderInfo(self):
1325 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform]
1326 for Record in RecordList:
1327 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1328 Name = Record[0]
1329 # items defined _PROPERTY_ don't need additional processing
1330 if Name in self:
1331 self[Name] = Record[1]
1332 # some special items in [Defines] section need special treatment
1333 elif Name in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION'):
1334 if self._Specification == None:
1335 self._Specification = sdict()
1336 self._Specification['UEFI_SPECIFICATION_VERSION'] = Record[1]
1337 elif Name == 'EDK_RELEASE_VERSION':
1338 if self._Specification == None:
1339 self._Specification = sdict()
1340 self._Specification[Name] = Record[1]
1341 elif Name == 'PI_SPECIFICATION_VERSION':
1342 if self._Specification == None:
1343 self._Specification = sdict()
1344 self._Specification[Name] = Record[1]
1345 elif Name == 'LIBRARY_CLASS':
1346 if self._LibraryClass == None:
1347 self._LibraryClass = []
1348 ValueList = GetSplitValueList(Record[1])
1349 LibraryClass = ValueList[0]
1350 if len(ValueList) > 1:
1351 SupModuleList = GetSplitValueList(ValueList[1], ' ')
1352 else:
1353 SupModuleList = SUP_MODULE_LIST
1354 self._LibraryClass.append(LibraryClassObject(LibraryClass, SupModuleList))
1355 elif Name == 'ENTRY_POINT':
1356 if self._ModuleEntryPointList == None:
1357 self._ModuleEntryPointList = []
1358 self._ModuleEntryPointList.append(Record[1])
1359 elif Name == 'UNLOAD_IMAGE':
1360 if self._ModuleUnloadImageList == None:
1361 self._ModuleUnloadImageList = []
1362 if Record[1] == '':
1363 continue
1364 self._ModuleUnloadImageList.append(Record[1])
1365 elif Name == 'CONSTRUCTOR':
1366 if self._ConstructorList == None:
1367 self._ConstructorList = []
1368 if Record[1] == '':
1369 continue
1370 self._ConstructorList.append(Record[1])
1371 elif Name == 'DESTRUCTOR':
1372 if self._DestructorList == None:
1373 self._DestructorList = []
1374 if Record[1] == '':
1375 continue
1376 self._DestructorList.append(Record[1])
1377 elif Name == TAB_INF_DEFINES_CUSTOM_MAKEFILE:
1378 TokenList = GetSplitValueList(Record[1])
1379 if self._CustomMakefile == None:
1380 self._CustomMakefile = {}
1381 if len(TokenList) < 2:
1382 self._CustomMakefile['MSFT'] = TokenList[0]
1383 self._CustomMakefile['GCC'] = TokenList[0]
1384 else:
1385 if TokenList[0] not in ['MSFT', 'GCC']:
1386 EdkLogger.error("build", FORMAT_NOT_SUPPORTED,
1387 "No supported family [%s]" % TokenList[0],
1388 File=self.MetaFile, Line=Record[-1])
1389 self._CustomMakefile[TokenList[0]] = TokenList[1]
1390 else:
1391 if self._Defs == None:
1392 self._Defs = sdict()
1393 self._Defs[Name] = Record[1]
1394
1395 #
1396 # Retrieve information in sections specific to R8.x modules
1397 #
1398 if self._AutoGenVersion >= 0x00010005: # _AutoGenVersion may be None, which is less than anything
1399 if not self._ModuleType:
1400 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
1401 "MODULE_TYPE is not given", File=self.MetaFile)
1402 if (self._Specification == None) or (not 'PI_SPECIFICATION_VERSION' in self._Specification) or (self._Specification['PI_SPECIFICATION_VERSION'] < 0x0001000A):
1403 if self._ModuleType == SUP_MODULE_SMM_CORE:
1404 EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "SMM_CORE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x0001000A", File=self.MetaFile)
1405 if self._Defs and 'PCI_DEVICE_ID' in self._Defs and 'PCI_VENDOR_ID' in self._Defs \
1406 and 'PCI_CLASS_CODE' in self._Defs:
1407 self._BuildType = 'UEFI_OPTIONROM'
1408 elif self._Defs and 'UEFI_HII_RESOURCE_SECTION' in self._Defs \
1409 and self._Defs['UEFI_HII_RESOURCE_SECTION'] == 'TRUE':
1410 self._BuildType = 'UEFI_HII'
1411 else:
1412 self._BuildType = self._ModuleType.upper()
1413 else:
1414 self._BuildType = self._ComponentType.upper()
1415 if not self._ComponentType:
1416 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
1417 "COMPONENT_TYPE is not given", File=self.MetaFile)
1418 if self._ComponentType in self._MODULE_TYPE_:
1419 self._ModuleType = self._MODULE_TYPE_[self._ComponentType]
1420 if self._ComponentType == 'LIBRARY':
1421 self._LibraryClass = [LibraryClassObject(self._BaseName, SUP_MODULE_LIST)]
1422 # make use some [nmake] section macros
1423 RecordList = self._RawData[MODEL_META_DATA_NMAKE, self._Arch, self._Platform]
1424 for Name,Value,Dummy,Arch,Platform,ID,LineNo in RecordList:
1425 Value = Value.replace('$(PROCESSOR)', self._Arch)
1426 Name = Name.replace('$(PROCESSOR)', self._Arch)
1427 Name, Value = ReplaceMacros((Name, Value), GlobalData.gEdkGlobal, True)
1428 if Name == "IMAGE_ENTRY_POINT":
1429 if self._ModuleEntryPointList == None:
1430 self._ModuleEntryPointList = []
1431 self._ModuleEntryPointList.append(Value)
1432 elif Name == "DPX_SOURCE":
1433 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource}
1434 Macros.update(self._Macros)
1435 File = PathClass(NormPath(Value, Macros), self._ModuleDir, Arch=self._Arch)
1436 # check the file validation
1437 ErrorCode, ErrorInfo = File.Validate(".dxs", CaseSensitive=False)
1438 if ErrorCode != 0:
1439 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo,
1440 File=self.MetaFile, Line=LineNo)
1441 if self.Sources == None:
1442 self._Sources = []
1443 self._Sources.append(File)
1444 else:
1445 ToolList = self._NMAKE_FLAG_PATTERN_.findall(Name)
1446 if len(ToolList) == 0 or len(ToolList) != 1:
1447 pass
1448 # EdkLogger.warn("build", "Don't know how to do with macro [%s]" % Name,
1449 # File=self.MetaFile, Line=LineNo)
1450 else:
1451 if self._BuildOptions == None:
1452 self._BuildOptions = sdict()
1453
1454 if ToolList[0] in self._TOOL_CODE_:
1455 Tool = self._TOOL_CODE_[ToolList[0]]
1456 else:
1457 Tool = ToolList[0]
1458 ToolChain = "*_*_*_%s_FLAGS" % Tool
1459 ToolChainFamily = 'MSFT' # R8.x only support MSFT tool chain
1460 #ignore not replaced macros in value
1461 ValueList = GetSplitValueList(' ' + Value, '/D')
1462 Dummy = ValueList[0]
1463 for Index in range(1, len(ValueList)):
1464 if ValueList[Index][-1] == '=' or ValueList[Index] == '':
1465 continue
1466 Dummy = Dummy + ' /D ' + ValueList[Index]
1467 Value = Dummy.strip()
1468 if (ToolChainFamily, ToolChain) not in self._BuildOptions:
1469 self._BuildOptions[ToolChainFamily, ToolChain] = Value
1470 else:
1471 OptionString = self._BuildOptions[ToolChainFamily, ToolChain]
1472 self._BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Value
1473 # set _Header to non-None in order to avoid database re-querying
1474 self._Header_ = 'DUMMY'
1475
1476 ## Retrieve file version
1477 def _GetInfVersion(self):
1478 if self._AutoGenVersion == None:
1479 if self._Header_ == None:
1480 self._GetHeaderInfo()
1481 if self._AutoGenVersion == None:
1482 self._AutoGenVersion = 0x00010000
1483 return self._AutoGenVersion
1484
1485 ## Retrieve BASE_NAME
1486 def _GetBaseName(self):
1487 if self._BaseName == None:
1488 if self._Header_ == None:
1489 self._GetHeaderInfo()
1490 if self._BaseName == None:
1491 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No BASE_NAME name", File=self.MetaFile)
1492 return self._BaseName
1493
1494 ## Retrieve MODULE_TYPE
1495 def _GetModuleType(self):
1496 if self._ModuleType == None:
1497 if self._Header_ == None:
1498 self._GetHeaderInfo()
1499 if self._ModuleType == None:
1500 self._ModuleType = 'BASE'
1501 if self._ModuleType not in SUP_MODULE_LIST:
1502 self._ModuleType = "USER_DEFINED"
1503 return self._ModuleType
1504
1505 ## Retrieve COMPONENT_TYPE
1506 def _GetComponentType(self):
1507 if self._ComponentType == None:
1508 if self._Header_ == None:
1509 self._GetHeaderInfo()
1510 if self._ComponentType == None:
1511 self._ComponentType = 'USER_DEFINED'
1512 return self._ComponentType
1513
1514 ## Retrieve "BUILD_TYPE"
1515 def _GetBuildType(self):
1516 if self._BuildType == None:
1517 if self._Header_ == None:
1518 self._GetHeaderInfo()
1519 if not self._BuildType:
1520 self._BuildType = "BASE"
1521 return self._BuildType
1522
1523 ## Retrieve file guid
1524 def _GetFileGuid(self):
1525 if self._Guid == None:
1526 if self._Header_ == None:
1527 self._GetHeaderInfo()
1528 if self._Guid == None:
1529 self._Guid = '00000000-0000-0000-000000000000'
1530 return self._Guid
1531
1532 ## Retrieve module version
1533 def _GetVersion(self):
1534 if self._Version == None:
1535 if self._Header_ == None:
1536 self._GetHeaderInfo()
1537 if self._Version == None:
1538 self._Version = '0.0'
1539 return self._Version
1540
1541 ## Retrieve PCD_IS_DRIVER
1542 def _GetPcdIsDriver(self):
1543 if self._PcdIsDriver == None:
1544 if self._Header_ == None:
1545 self._GetHeaderInfo()
1546 if self._PcdIsDriver == None:
1547 self._PcdIsDriver = ''
1548 return self._PcdIsDriver
1549
1550 ## Retrieve SHADOW
1551 def _GetShadow(self):
1552 if self._Shadow == None:
1553 if self._Header_ == None:
1554 self._GetHeaderInfo()
1555 if self._Shadow != None and self._Shadow.upper() == 'TRUE':
1556 self._Shadow = True
1557 else:
1558 self._Shadow = False
1559 return self._Shadow
1560
1561 ## Retrieve CUSTOM_MAKEFILE
1562 def _GetMakefile(self):
1563 if self._CustomMakefile == None:
1564 if self._Header_ == None:
1565 self._GetHeaderInfo()
1566 if self._CustomMakefile == None:
1567 self._CustomMakefile = {}
1568 return self._CustomMakefile
1569
1570 ## Retrieve EFI_SPECIFICATION_VERSION
1571 def _GetSpec(self):
1572 if self._Specification == None:
1573 if self._Header_ == None:
1574 self._GetHeaderInfo()
1575 if self._Specification == None:
1576 self._Specification = {}
1577 return self._Specification
1578
1579 ## Retrieve LIBRARY_CLASS
1580 def _GetLibraryClass(self):
1581 if self._LibraryClass == None:
1582 if self._Header_ == None:
1583 self._GetHeaderInfo()
1584 if self._LibraryClass == None:
1585 self._LibraryClass = []
1586 return self._LibraryClass
1587
1588 ## Retrieve ENTRY_POINT
1589 def _GetEntryPoint(self):
1590 if self._ModuleEntryPointList == None:
1591 if self._Header_ == None:
1592 self._GetHeaderInfo()
1593 if self._ModuleEntryPointList == None:
1594 self._ModuleEntryPointList = []
1595 return self._ModuleEntryPointList
1596
1597 ## Retrieve UNLOAD_IMAGE
1598 def _GetUnloadImage(self):
1599 if self._ModuleUnloadImageList == None:
1600 if self._Header_ == None:
1601 self._GetHeaderInfo()
1602 if self._ModuleUnloadImageList == None:
1603 self._ModuleUnloadImageList = []
1604 return self._ModuleUnloadImageList
1605
1606 ## Retrieve CONSTRUCTOR
1607 def _GetConstructor(self):
1608 if self._ConstructorList == None:
1609 if self._Header_ == None:
1610 self._GetHeaderInfo()
1611 if self._ConstructorList == None:
1612 self._ConstructorList = []
1613 return self._ConstructorList
1614
1615 ## Retrieve DESTRUCTOR
1616 def _GetDestructor(self):
1617 if self._DestructorList == None:
1618 if self._Header_ == None:
1619 self._GetHeaderInfo()
1620 if self._DestructorList == None:
1621 self._DestructorList = []
1622 return self._DestructorList
1623
1624 ## Retrieve definies other than above ones
1625 def _GetDefines(self):
1626 if self._Defs == None:
1627 if self._Header_ == None:
1628 self._GetHeaderInfo()
1629 if self._Defs == None:
1630 self._Defs = sdict()
1631 return self._Defs
1632
1633 ## Retrieve binary files
1634 def _GetBinaryFiles(self):
1635 if self._Binaries == None:
1636 self._Binaries = []
1637 RecordList = self._RawData[MODEL_EFI_BINARY_FILE, self._Arch, self._Platform]
1638 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource, 'PROCESSOR':self._Arch}
1639 Macros.update(self._Macros)
1640 for Record in RecordList:
1641 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1642 FileType = Record[0]
1643 LineNo = Record[-1]
1644 Target = 'COMMON'
1645 FeatureFlag = []
1646 if Record[2]:
1647 TokenList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT)
1648 if TokenList:
1649 Target = TokenList[0]
1650 if len(TokenList) > 1:
1651 FeatureFlag = Record[1:]
1652
1653 File = PathClass(NormPath(Record[1], Macros), self._ModuleDir, '', FileType, True, self._Arch, '', Target)
1654 # check the file validation
1655 ErrorCode, ErrorInfo = File.Validate()
1656 if ErrorCode != 0:
1657 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
1658 self._Binaries.append(File)
1659 return self._Binaries
1660
1661 ## Retrieve source files
1662 def _GetSourceFiles(self):
1663 if self._Sources == None:
1664 self._Sources = []
1665 RecordList = self._RawData[MODEL_EFI_SOURCE_FILE, self._Arch, self._Platform]
1666 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource, 'PROCESSOR':self._Arch}
1667 Macros.update(self._Macros)
1668 for Record in RecordList:
1669 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1670 LineNo = Record[-1]
1671 ToolChainFamily = Record[1]
1672 TagName = Record[2]
1673 ToolCode = Record[3]
1674 FeatureFlag = Record[4]
1675 if self._AutoGenVersion < 0x00010005:
1676 # old module source files (R8)
1677 File = PathClass(NormPath(Record[0], Macros), self._ModuleDir, self._SourceOverridePath,
1678 '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode)
1679 # check the file validation
1680 ErrorCode, ErrorInfo = File.Validate(CaseSensitive=False)
1681 if ErrorCode != 0:
1682 if File.Ext.lower() == '.h':
1683 EdkLogger.warn('build', 'Include file not found', ExtraData=ErrorInfo,
1684 File=self.MetaFile, Line=LineNo)
1685 continue
1686 else:
1687 EdkLogger.error('build', ErrorCode, ExtraData=File, File=self.MetaFile, Line=LineNo)
1688 else:
1689 File = PathClass(NormPath(Record[0], Macros), self._ModuleDir, '',
1690 '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode)
1691 # check the file validation
1692 ErrorCode, ErrorInfo = File.Validate()
1693 if ErrorCode != 0:
1694 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
1695
1696 self._Sources.append(File)
1697 return self._Sources
1698
1699 ## Retrieve library classes employed by this module
1700 def _GetLibraryClassUses(self):
1701 if self._LibraryClasses == None:
1702 self._LibraryClasses = sdict()
1703 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, self._Platform]
1704 for Record in RecordList:
1705 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1706 Lib = Record[0]
1707 Instance = Record[1]
1708 if Instance != None and Instance != '':
1709 Instance = NormPath(Instance, self._Macros)
1710 self._LibraryClasses[Lib] = Instance
1711 return self._LibraryClasses
1712
1713 ## Retrieve library names (for R8.x style of modules)
1714 def _GetLibraryNames(self):
1715 if self._Libraries == None:
1716 self._Libraries = []
1717 RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch, self._Platform]
1718 for Record in RecordList:
1719 # in case of name with '.lib' extension, which is unusual in R8.x inf
1720 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1721 LibraryName = os.path.splitext(Record[0])[0]
1722 if LibraryName not in self._Libraries:
1723 self._Libraries.append(LibraryName)
1724 return self._Libraries
1725
1726 ## Retrieve protocols consumed/produced by this module
1727 def _GetProtocols(self):
1728 if self._Protocols == None:
1729 self._Protocols = sdict()
1730 RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch, self._Platform]
1731 for Record in RecordList:
1732 CName = Record[0]
1733 Value = ProtocolValue(CName, self.Packages)
1734 if Value == None:
1735 PackageList = "\n\t".join([str(P) for P in self.Packages])
1736 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
1737 "Value of Protocol [%s] is not found under [Protocols] section in" % CName,
1738 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
1739 self._Protocols[CName] = Value
1740 return self._Protocols
1741
1742 ## Retrieve PPIs consumed/produced by this module
1743 def _GetPpis(self):
1744 if self._Ppis == None:
1745 self._Ppis = sdict()
1746 RecordList = self._RawData[MODEL_EFI_PPI, self._Arch, self._Platform]
1747 for Record in RecordList:
1748 CName = Record[0]
1749 Value = PpiValue(CName, self.Packages)
1750 if Value == None:
1751 PackageList = "\n\t".join([str(P) for P in self.Packages])
1752 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
1753 "Value of PPI [%s] is not found under [Ppis] section in " % CName,
1754 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
1755 self._Ppis[CName] = Value
1756 return self._Ppis
1757
1758 ## Retrieve GUIDs consumed/produced by this module
1759 def _GetGuids(self):
1760 if self._Guids == None:
1761 self._Guids = sdict()
1762 RecordList = self._RawData[MODEL_EFI_GUID, self._Arch, self._Platform]
1763 for Record in RecordList:
1764 CName = Record[0]
1765 Value = GuidValue(CName, self.Packages)
1766 if Value == None:
1767 PackageList = "\n\t".join([str(P) for P in self.Packages])
1768 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
1769 "Value of Guid [%s] is not found under [Guids] section in" % CName,
1770 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
1771 self._Guids[CName] = Value
1772 return self._Guids
1773
1774 ## Retrieve include paths necessary for this module (for R8.x style of modules)
1775 def _GetIncludes(self):
1776 if self._Includes == None:
1777 self._Includes = []
1778 if self._SourceOverridePath:
1779 self._Includes.append(self._SourceOverridePath)
1780 RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch, self._Platform]
1781 # [includes] section must be used only in old (R8.x) inf file
1782 if self.AutoGenVersion >= 0x00010005 and len(RecordList) > 0:
1783 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, "No [include] section allowed",
1784 File=self.MetaFile, Line=RecordList[0][-1]-1)
1785 for Record in RecordList:
1786 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1787 Record[0] = Record[0].replace('$(PROCESSOR)', self._Arch)
1788 Record[0] = ReplaceMacro(Record[0], {'EFI_SOURCE' : GlobalData.gEfiSource}, False)
1789 if Record[0].find('EDK_SOURCE') > -1:
1790 File = NormPath(ReplaceMacro(Record[0], {'EDK_SOURCE' : GlobalData.gEcpSource}, False), self._Macros)
1791 if File[0] == '.':
1792 File = os.path.join(self._ModuleDir, File)
1793 else:
1794 File = os.path.join(GlobalData.gWorkspace, File)
1795 File = RealPath(os.path.normpath(File))
1796 if File:
1797 self._Includes.append(File)
1798
1799 #TRICK: let compiler to choose correct header file
1800 File = NormPath(ReplaceMacro(Record[0], {'EDK_SOURCE' : GlobalData.gEdkSource}, False), self._Macros)
1801 if File[0] == '.':
1802 File = os.path.join(self._ModuleDir, File)
1803 else:
1804 File = os.path.join(GlobalData.gWorkspace, File)
1805 File = RealPath(os.path.normpath(File))
1806 if File:
1807 self._Includes.append(File)
1808 else:
1809 File = NormPath(Record[0], self._Macros)
1810 if File[0] == '.':
1811 File = os.path.join(self._ModuleDir, File)
1812 else:
1813 File = os.path.join(GlobalData.gWorkspace, File)
1814 File = RealPath(os.path.normpath(File))
1815 if File:
1816 self._Includes.append(File)
1817 return self._Includes
1818
1819 ## Retrieve packages this module depends on
1820 def _GetPackages(self):
1821 if self._Packages == None:
1822 self._Packages = []
1823 RecordList = self._RawData[MODEL_META_DATA_PACKAGE, self._Arch, self._Platform]
1824 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource}
1825 Macros.update(self._Macros)
1826 for Record in RecordList:
1827 File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
1828 LineNo = Record[-1]
1829 # check the file validation
1830 ErrorCode, ErrorInfo = File.Validate('.dec')
1831 if ErrorCode != 0:
1832 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
1833 # parse this package now. we need it to get protocol/ppi/guid value
1834 Package = self._Bdb[File, self._Arch]
1835 self._Packages.append(Package)
1836 return self._Packages
1837
1838 ## Retrieve PCDs used in this module
1839 def _GetPcds(self):
1840 if self._Pcds == None:
1841 self._Pcds = {}
1842 self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
1843 self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
1844 self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
1845 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC))
1846 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
1847 return self._Pcds
1848
1849 ## Retrieve build options specific to this module
1850 def _GetBuildOptions(self):
1851 if self._BuildOptions == None:
1852 self._BuildOptions = sdict()
1853 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, self._Platform]
1854 for Record in RecordList:
1855 ToolChainFamily = Record[0]
1856 ToolChain = Record[1]
1857 Option = Record[2]
1858 if (ToolChainFamily, ToolChain) not in self._BuildOptions:
1859 self._BuildOptions[ToolChainFamily, ToolChain] = Option
1860 else:
1861 # concatenate the option string if they're for the same tool
1862 OptionString = self._BuildOptions[ToolChainFamily, ToolChain]
1863 self._BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option
1864 return self._BuildOptions
1865
1866 ## Retrieve depedency expression
1867 def _GetDepex(self):
1868 if self._Depex == None:
1869 self._Depex = tdict(False, 2)
1870 RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
1871
1872 # PEIM and DXE drivers must have a valid [Depex] section
1873 if len(self.LibraryClass) == 0 and len(RecordList) == 0:
1874 if self.ModuleType == 'DXE_DRIVER' or self.ModuleType == 'PEIM' or self.ModuleType == 'DXE_SMM_DRIVER' or \
1875 self.ModuleType == 'DXE_SAL_DRIVER' or self.ModuleType == 'DXE_RUNTIME_DRIVER':
1876 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No [Depex] section or no valid expression in [Depex] section for [%s] module" \
1877 % self.ModuleType, File=self.MetaFile)
1878
1879 Depex = {}
1880 for Record in RecordList:
1881 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1882 Arch = Record[3]
1883 ModuleType = Record[4]
1884 TokenList = Record[0].split()
1885 if (Arch, ModuleType) not in Depex:
1886 Depex[Arch, ModuleType] = []
1887 DepexList = Depex[Arch, ModuleType]
1888 for Token in TokenList:
1889 if Token in DEPEX_SUPPORTED_OPCODE:
1890 DepexList.append(Token)
1891 elif Token.endswith(".inf"): # module file name
1892 ModuleFile = os.path.normpath(Token)
1893 Module = self.BuildDatabase[ModuleFile]
1894 if Module == None:
1895 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "Module is not found in active platform",
1896 ExtraData=Token, File=self.MetaFile, Line=Record[-1])
1897 DepexList.append(Module.Guid)
1898 else:
1899 # get the GUID value now
1900 Value = ProtocolValue(Token, self.Packages)
1901 if Value == None:
1902 Value = PpiValue(Token, self.Packages)
1903 if Value == None:
1904 Value = GuidValue(Token, self.Packages)
1905 if Value == None:
1906 PackageList = "\n\t".join([str(P) for P in self.Packages])
1907 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
1908 "Value of [%s] is not found in" % Token,
1909 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
1910 DepexList.append(Value)
1911 for Arch, ModuleType in Depex:
1912 self._Depex[Arch, ModuleType] = Depex[Arch, ModuleType]
1913 return self._Depex
1914
1915 ## Retrieve depedency expression
1916 def _GetDepexExpression(self):
1917 if self._DepexExpression == None:
1918 self._DepexExpression = tdict(False, 2)
1919 RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
1920 DepexExpression = {}
1921 for Record in RecordList:
1922 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1923 Arch = Record[3]
1924 ModuleType = Record[4]
1925 TokenList = Record[0].split()
1926 if (Arch, ModuleType) not in DepexExpression:
1927 DepexExpression[Arch, ModuleType] = ''
1928 for Token in TokenList:
1929 DepexExpression[Arch, ModuleType] = DepexExpression[Arch, ModuleType] + Token.strip() + ' '
1930 for Arch, ModuleType in DepexExpression:
1931 self._DepexExpression[Arch, ModuleType] = DepexExpression[Arch, ModuleType]
1932 return self._DepexExpression
1933
1934 ## Retrieve PCD for given type
1935 def _GetPcd(self, Type):
1936 Pcds = {}
1937 PcdDict = tdict(True, 4)
1938 PcdSet = set()
1939 RecordList = self._RawData[Type, self._Arch, self._Platform]
1940 for TokenSpaceGuid, PcdCName, Setting, Arch, Platform, Dummy1, LineNo in RecordList:
1941 PcdDict[Arch, Platform, PcdCName, TokenSpaceGuid] = (Setting, LineNo)
1942 PcdSet.add((PcdCName, TokenSpaceGuid))
1943 # get the guid value
1944 if TokenSpaceGuid not in self.Guids:
1945 Value = GuidValue(TokenSpaceGuid, self.Packages)
1946 if Value == None:
1947 PackageList = "\n\t".join([str(P) for P in self.Packages])
1948 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
1949 "Value of Guid [%s] is not found under [Guids] section in" % TokenSpaceGuid,
1950 ExtraData=PackageList, File=self.MetaFile, Line=LineNo)
1951 self.Guids[TokenSpaceGuid] = Value
1952
1953 # resolve PCD type, value, datum info, etc. by getting its definition from package
1954 for PcdCName, TokenSpaceGuid in PcdSet:
1955 ValueList = ['', '']
1956 Setting, LineNo = PcdDict[self._Arch, self.Platform, PcdCName, TokenSpaceGuid]
1957 if Setting == None:
1958 continue
1959 TokenList = Setting.split(TAB_VALUE_SPLIT)
1960 ValueList[0:len(TokenList)] = TokenList
1961 DefaultValue = ValueList[0]
1962 Pcd = PcdClassObject(
1963 PcdCName,
1964 TokenSpaceGuid,
1965 '',
1966 '',
1967 DefaultValue,
1968 '',
1969 '',
1970 {},
1971 False,
1972 self.Guids[TokenSpaceGuid]
1973 )
1974
1975 # get necessary info from package declaring this PCD
1976 for Package in self.Packages:
1977 #
1978 # 'dynamic' in INF means its type is determined by platform;
1979 # if platform doesn't give its type, use 'lowest' one in the
1980 # following order, if any
1981 #
1982 # "FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx"
1983 #
1984 PcdType = self._PCD_TYPE_STRING_[Type]
1985 if Type == MODEL_PCD_DYNAMIC:
1986 Pcd.Pending = True
1987 for T in ["FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx"]:
1988 if (PcdCName, TokenSpaceGuid, T) in Package.Pcds:
1989 PcdType = T
1990 break
1991 else:
1992 Pcd.Pending = False
1993
1994 if (PcdCName, TokenSpaceGuid, PcdType) in Package.Pcds:
1995 PcdInPackage = Package.Pcds[PcdCName, TokenSpaceGuid, PcdType]
1996 Pcd.Type = PcdType
1997 Pcd.TokenValue = PcdInPackage.TokenValue
1998 Pcd.DatumType = PcdInPackage.DatumType
1999 Pcd.MaxDatumSize = PcdInPackage.MaxDatumSize
2000 Pcd.InfDefaultValue = Pcd.DefaultValue
2001 if Pcd.DefaultValue in [None, '']:
2002 Pcd.DefaultValue = PcdInPackage.DefaultValue
2003 break
2004 else:
2005 EdkLogger.error(
2006 'build',
2007 PARSER_ERROR,
2008 "PCD [%s.%s] in [%s] is not found in dependent packages:" % (TokenSpaceGuid, PcdCName, self.MetaFile),
2009 File =self.MetaFile, Line=LineNo,
2010 ExtraData="\t%s" % '\n\t'.join([str(P) for P in self.Packages])
2011 )
2012 Pcds[PcdCName, TokenSpaceGuid] = Pcd
2013 return Pcds
2014
2015 Arch = property(_GetArch, _SetArch)
2016 Platform = property(_GetPlatform, _SetPlatform)
2017
2018 AutoGenVersion = property(_GetInfVersion)
2019 BaseName = property(_GetBaseName)
2020 ModuleType = property(_GetModuleType)
2021 ComponentType = property(_GetComponentType)
2022 BuildType = property(_GetBuildType)
2023 Guid = property(_GetFileGuid)
2024 Version = property(_GetVersion)
2025 PcdIsDriver = property(_GetPcdIsDriver)
2026 Shadow = property(_GetShadow)
2027 CustomMakefile = property(_GetMakefile)
2028 Specification = property(_GetSpec)
2029 LibraryClass = property(_GetLibraryClass)
2030 ModuleEntryPointList = property(_GetEntryPoint)
2031 ModuleUnloadImageList = property(_GetUnloadImage)
2032 ConstructorList = property(_GetConstructor)
2033 DestructorList = property(_GetDestructor)
2034 Defines = property(_GetDefines)
2035
2036 Binaries = property(_GetBinaryFiles)
2037 Sources = property(_GetSourceFiles)
2038 LibraryClasses = property(_GetLibraryClassUses)
2039 Libraries = property(_GetLibraryNames)
2040 Protocols = property(_GetProtocols)
2041 Ppis = property(_GetPpis)
2042 Guids = property(_GetGuids)
2043 Includes = property(_GetIncludes)
2044 Packages = property(_GetPackages)
2045 Pcds = property(_GetPcds)
2046 BuildOptions = property(_GetBuildOptions)
2047 Depex = property(_GetDepex)
2048 DepexExpression = property(_GetDepexExpression)
2049
2050 ## Database
2051 #
2052 # This class defined the build database for all modules, packages and platform.
2053 # It will call corresponding parser for the given file if it cannot find it in
2054 # the database.
2055 #
2056 # @param DbPath Path of database file
2057 # @param GlobalMacros Global macros used for replacement during file parsing
2058 # @prarm RenewDb=False Create new database file if it's already there
2059 #
2060 class WorkspaceDatabase(object):
2061 # file parser
2062 _FILE_PARSER_ = {
2063 MODEL_FILE_INF : InfParser,
2064 MODEL_FILE_DEC : DecParser,
2065 MODEL_FILE_DSC : DscParser,
2066 MODEL_FILE_FDF : None, #FdfParser,
2067 MODEL_FILE_CIF : None
2068 }
2069
2070 # file table
2071 _FILE_TABLE_ = {
2072 MODEL_FILE_INF : ModuleTable,
2073 MODEL_FILE_DEC : PackageTable,
2074 MODEL_FILE_DSC : PlatformTable,
2075 }
2076
2077 # default database file path
2078 _DB_PATH_ = "Conf/.cache/build.db"
2079
2080 #
2081 # internal class used for call corresponding file parser and caching the result
2082 # to avoid unnecessary re-parsing
2083 #
2084 class BuildObjectFactory(object):
2085 _FILE_TYPE_ = {
2086 ".inf" : MODEL_FILE_INF,
2087 ".dec" : MODEL_FILE_DEC,
2088 ".dsc" : MODEL_FILE_DSC,
2089 ".fdf" : MODEL_FILE_FDF,
2090 }
2091
2092 # convert to xxxBuildData object
2093 _GENERATOR_ = {
2094 MODEL_FILE_INF : InfBuildData,
2095 MODEL_FILE_DEC : DecBuildData,
2096 MODEL_FILE_DSC : DscBuildData,
2097 MODEL_FILE_FDF : None #FlashDefTable,
2098 }
2099
2100 _CACHE_ = {} # (FilePath, Arch) : <object>
2101
2102 # constructor
2103 def __init__(self, WorkspaceDb):
2104 self.WorkspaceDb = WorkspaceDb
2105
2106 # key = (FilePath, Arch='COMMON')
2107 def __contains__(self, Key):
2108 FilePath = Key[0]
2109 Arch = 'COMMON'
2110 if len(Key) > 1:
2111 Arch = Key[1]
2112 return (FilePath, Arch) in self._CACHE_
2113
2114 # key = (FilePath, Arch='COMMON')
2115 def __getitem__(self, Key):
2116 FilePath = Key[0]
2117 Arch = 'COMMON'
2118 Platform = 'COMMON'
2119 if len(Key) > 1:
2120 Arch = Key[1]
2121 if len(Key) > 2:
2122 Platform = Key[2]
2123
2124 # if it's generated before, just return the cached one
2125 Key = (FilePath, Arch)
2126 if Key in self._CACHE_:
2127 return self._CACHE_[Key]
2128
2129 # check file type
2130 Ext = FilePath.Ext.lower()
2131 if Ext not in self._FILE_TYPE_:
2132 return None
2133 FileType = self._FILE_TYPE_[Ext]
2134 if FileType not in self._GENERATOR_:
2135 return None
2136
2137 # get table for current file
2138 MetaFile = self.WorkspaceDb[FilePath, FileType, self.WorkspaceDb._GlobalMacros]
2139 BuildObject = self._GENERATOR_[FileType](
2140 FilePath,
2141 MetaFile,
2142 self,
2143 Arch,
2144 Platform,
2145 self.WorkspaceDb._GlobalMacros,
2146 )
2147 self._CACHE_[Key] = BuildObject
2148 return BuildObject
2149
2150 # placeholder for file format conversion
2151 class TransformObjectFactory:
2152 def __init__(self, WorkspaceDb):
2153 self.WorkspaceDb = WorkspaceDb
2154
2155 # key = FilePath, Arch
2156 def __getitem__(self, Key):
2157 pass
2158
2159 ## Constructor of WorkspaceDatabase
2160 #
2161 # @param DbPath Path of database file
2162 # @param GlobalMacros Global macros used for replacement during file parsing
2163 # @prarm RenewDb=False Create new database file if it's already there
2164 #
2165 def __init__(self, DbPath, GlobalMacros={}, RenewDb=False):
2166 self._GlobalMacros = GlobalMacros
2167
2168 if DbPath == None or DbPath == '':
2169 DbPath = os.path.normpath(os.path.join(GlobalData.gWorkspace, self._DB_PATH_))
2170
2171 # don't create necessary path for db in memory
2172 if DbPath != ':memory:':
2173 DbDir = os.path.split(DbPath)[0]
2174 if not os.path.exists(DbDir):
2175 os.makedirs(DbDir)
2176
2177 # remove db file in case inconsistency between db and file in file system
2178 if self._CheckWhetherDbNeedRenew(RenewDb, DbPath):
2179 os.remove(DbPath)
2180
2181 # create db with optimized parameters
2182 self.Conn = sqlite3.connect(DbPath, isolation_level='DEFERRED')
2183 self.Conn.execute("PRAGMA synchronous=OFF")
2184 self.Conn.execute("PRAGMA temp_store=MEMORY")
2185 self.Conn.execute("PRAGMA count_changes=OFF")
2186 self.Conn.execute("PRAGMA cache_size=8192")
2187 #self.Conn.execute("PRAGMA page_size=8192")
2188
2189 # to avoid non-ascii character conversion issue
2190 self.Conn.text_factory = str
2191 self.Cur = self.Conn.cursor()
2192
2193 # create table for internal uses
2194 self.TblDataModel = TableDataModel(self.Cur)
2195 self.TblFile = TableFile(self.Cur)
2196
2197 # conversion object for build or file format conversion purpose
2198 self.BuildObject = WorkspaceDatabase.BuildObjectFactory(self)
2199 self.TransformObject = WorkspaceDatabase.TransformObjectFactory(self)
2200
2201 ## Check whether workspace database need to be renew.
2202 # The renew reason maybe:
2203 # 1) If user force to renew;
2204 # 2) If user do not force renew, and
2205 # a) If the time of last modified python source is newer than database file;
2206 # b) If the time of last modified frozen executable file is newer than database file;
2207 #
2208 # @param force User force renew database
2209 # @param DbPath The absolute path of workspace database file
2210 #
2211 # @return Bool value for whether need renew workspace databse
2212 #
2213 def _CheckWhetherDbNeedRenew (self, force, DbPath):
2214 DbDir = os.path.split(DbPath)[0]
2215 MacroFilePath = os.path.normpath(os.path.join(DbDir, "build.mac"))
2216 MacroMatch = False
2217 if os.path.exists(MacroFilePath) and os.path.isfile(MacroFilePath):
2218 LastMacros = None
2219 try:
2220 f = open(MacroFilePath,'r')
2221 LastMacros = pickle.load(f)
2222 f.close()
2223 except IOError:
2224 pass
2225 except:
2226 f.close()
2227
2228 if LastMacros != None and type(LastMacros) is DictType:
2229 if LastMacros == self._GlobalMacros:
2230 MacroMatch = True
2231 for Macro in LastMacros.keys():
2232 if not (Macro in self._GlobalMacros and LastMacros[Macro] == self._GlobalMacros[Macro]):
2233 MacroMatch = False;
2234 break;
2235
2236 if not MacroMatch:
2237 # save command line macros to file
2238 try:
2239 f = open(MacroFilePath,'w')
2240 pickle.dump(self._GlobalMacros, f, 2)
2241 f.close()
2242 except IOError:
2243 pass
2244 except:
2245 f.close()
2246
2247 force = True
2248
2249 # if database does not exist, we need do nothing
2250 if not os.path.exists(DbPath): return False
2251
2252 # if user force to renew database, then not check whether database is out of date
2253 if force: return True
2254
2255 #
2256 # Check the time of last modified source file or build.exe
2257 # if is newer than time of database, then database need to be re-created.
2258 #
2259 timeOfToolModified = 0
2260 if hasattr(sys, "frozen"):
2261 exePath = os.path.abspath(sys.executable)
2262 timeOfToolModified = os.stat(exePath).st_mtime
2263 else:
2264 curPath = os.path.dirname(__file__) # curPath is the path of WorkspaceDatabase.py
2265 rootPath = os.path.split(curPath)[0] # rootPath is root path of python source, such as /BaseTools/Source/Python
2266 if rootPath == "" or rootPath == None:
2267 EdkLogger.verbose("\nFail to find the root path of build.exe or python sources, so can not \
2268 determine whether database file is out of date!\n")
2269
2270 # walk the root path of source or build's binary to get the time last modified.
2271
2272 for root, dirs, files in os.walk (rootPath):
2273 for dir in dirs:
2274 # bypass source control folder
2275 if dir.lower() in [".svn", "_svn", "cvs"]:
2276 dirs.remove(dir)
2277
2278 for file in files:
2279 ext = os.path.splitext(file)[1]
2280 if ext.lower() == ".py": # only check .py files
2281 fd = os.stat(os.path.join(root, file))
2282 if timeOfToolModified < fd.st_mtime:
2283 timeOfToolModified = fd.st_mtime
2284 if timeOfToolModified > os.stat(DbPath).st_mtime:
2285 EdkLogger.verbose("\nWorkspace database is out of data!")
2286 return True
2287
2288 return False
2289
2290 ## Initialize build database
2291 def InitDatabase(self):
2292 EdkLogger.verbose("\nInitialize build database started ...")
2293
2294 #
2295 # Create new tables
2296 #
2297 self.TblDataModel.Create(False)
2298 self.TblFile.Create(False)
2299
2300 #
2301 # Initialize table DataModel
2302 #
2303 self.TblDataModel.InitTable()
2304 EdkLogger.verbose("Initialize build database ... DONE!")
2305
2306 ## Query a table
2307 #
2308 # @param Table: The instance of the table to be queried
2309 #
2310 def QueryTable(self, Table):
2311 Table.Query()
2312
2313 ## Close entire database
2314 #
2315 # Commit all first
2316 # Close the connection and cursor
2317 #
2318 def Close(self):
2319 self.Conn.commit()
2320 self.Cur.close()
2321 self.Conn.close()
2322
2323 ## Get unique file ID for the gvien file
2324 def GetFileId(self, FilePath):
2325 return self.TblFile.GetFileId(FilePath)
2326
2327 ## Get file type value for the gvien file ID
2328 def GetFileType(self, FileId):
2329 return self.TblFile.GetFileType(FileId)
2330
2331 ## Get time stamp stored in file table
2332 def GetTimeStamp(self, FileId):
2333 return self.TblFile.GetFileTimeStamp(FileId)
2334
2335 ## Update time stamp in file table
2336 def SetTimeStamp(self, FileId, TimeStamp):
2337 return self.TblFile.SetFileTimeStamp(FileId, TimeStamp)
2338
2339 ## Check if a table integrity flag exists or not
2340 def CheckIntegrity(self, TableName):
2341 try:
2342 Result = self.Cur.execute("select min(ID) from %s" % (TableName)).fetchall()
2343 if Result[0][0] != -1:
2344 return False
2345 #
2346 # Check whether the meta data file has external dependency by comparing the time stamp
2347 #
2348 Sql = "select Value1, Value2 from %s where Model=%d" % (TableName, MODEL_EXTERNAL_DEPENDENCY)
2349 for Dependency in self.Cur.execute(Sql).fetchall():
2350 if str(os.stat(Dependency[0])[8]) != Dependency[1]:
2351 return False
2352 except:
2353 return False
2354 return True
2355
2356 ## Compose table name for given file type and file ID
2357 def GetTableName(self, FileType, FileId):
2358 return "_%s_%s" % (FileType, FileId)
2359
2360 ## Return a temp table containing all content of the given file
2361 #
2362 # @param FileInfo The tuple containing path and type of a file
2363 #
2364 def __getitem__(self, FileInfo):
2365 FilePath, FileType, Macros = FileInfo
2366 if FileType not in self._FILE_TABLE_:
2367 return None
2368
2369 # flag used to indicate if it's parsed or not
2370 FilePath = str(FilePath)
2371 Parsed = False
2372 FileId = self.GetFileId(FilePath)
2373 if FileId != None:
2374 TimeStamp = os.stat(FilePath)[8]
2375 TableName = self.GetTableName(FileType, FileId)
2376 if TimeStamp != self.GetTimeStamp(FileId):
2377 # update the timestamp in database
2378 self.SetTimeStamp(FileId, TimeStamp)
2379 else:
2380 # if the table exists and is integrity, don't parse it
2381 Parsed = self.CheckIntegrity(TableName)
2382 else:
2383 FileId = self.TblFile.InsertFile(FilePath, FileType)
2384 TableName = self.GetTableName(FileType, FileId)
2385
2386 FileTable = self._FILE_TABLE_[FileType](self.Cur, TableName, FileId)
2387 FileTable.Create(not Parsed)
2388 Parser = self._FILE_PARSER_[FileType](FilePath, FileType, FileTable, Macros)
2389 # set the "Finished" flag in parser in order to avoid re-parsing (if parsed)
2390 Parser.Finished = Parsed
2391 return Parser
2392
2393 ## Summarize all packages in the database
2394 def _GetPackageList(self):
2395 PackageList = []
2396 for Module in self.ModuleList:
2397 for Package in Module.Packages:
2398 if Package not in PackageList:
2399 PackageList.append(Package)
2400 return PackageList
2401
2402 ## Summarize all platforms in the database
2403 def _GetPlatformList(self):
2404 PlatformList = []
2405 for PlatformFile in self.TblFile.GetFileList(MODEL_FILE_DSC):
2406 try:
2407 Platform = self.BuildObject[PathClass(PlatformFile), 'COMMON']
2408 except:
2409 Platform = None
2410 if Platform != None:
2411 PlatformList.append(Platform)
2412 return PlatformList
2413
2414 ## Summarize all modules in the database
2415 def _GetModuleList(self):
2416 ModuleList = []
2417 for ModuleFile in self.TblFile.GetFileList(MODEL_FILE_INF):
2418 try:
2419 Module = self.BuildObject[PathClass(ModuleFile), 'COMMON']
2420 except:
2421 Module = None
2422 if Module != None:
2423 ModuleList.append(Module)
2424 return ModuleList
2425
2426 PlatformList = property(_GetPlatformList)
2427 PackageList = property(_GetPackageList)
2428 ModuleList = property(_GetModuleList)
2429
2430 ##
2431 #
2432 # This acts like the main() function for the script, unless it is 'import'ed into another
2433 # script.
2434 #
2435 if __name__ == '__main__':
2436 pass
2437