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