]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/DecBuildData.py
BaseTools: fix imports
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / DecBuildData.py
1 ## @file
2 # This file is used to create a database used by build tool
3 #
4 # Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
5 # (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6 # This program and the accompanying materials
7 # are licensed and made available under the terms and conditions of the BSD License
8 # which accompanies this distribution. The full text of the license may be found at
9 # http://opensource.org/licenses/bsd-license.php
10 #
11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 #
14 from Common.StringUtils import *
15 from Common.DataType import *
16 from Common.Misc import *
17 from types import *
18 from collections import OrderedDict
19 from CommonDataClass.DataClass import *
20 from Workspace.BuildClassObject import PackageBuildClassObject, StructurePcd, PcdClassObject
21 from Common.GlobalData import gGlobalDefines, gEcpSource
22 from re import compile
23
24 ## Platform build information from DEC file
25 #
26 # This class is used to retrieve information stored in database and convert them
27 # into PackageBuildClassObject form for easier use for AutoGen.
28 #
29 class DecBuildData(PackageBuildClassObject):
30 # dict used to convert PCD type in database to string used by build tool
31 _PCD_TYPE_STRING_ = {
32 MODEL_PCD_FIXED_AT_BUILD : TAB_PCDS_FIXED_AT_BUILD,
33 MODEL_PCD_PATCHABLE_IN_MODULE : TAB_PCDS_PATCHABLE_IN_MODULE,
34 MODEL_PCD_FEATURE_FLAG : TAB_PCDS_FEATURE_FLAG,
35 MODEL_PCD_DYNAMIC : TAB_PCDS_DYNAMIC,
36 MODEL_PCD_DYNAMIC_DEFAULT : TAB_PCDS_DYNAMIC,
37 MODEL_PCD_DYNAMIC_HII : TAB_PCDS_DYNAMIC_HII,
38 MODEL_PCD_DYNAMIC_VPD : TAB_PCDS_DYNAMIC_VPD,
39 MODEL_PCD_DYNAMIC_EX : TAB_PCDS_DYNAMIC_EX,
40 MODEL_PCD_DYNAMIC_EX_DEFAULT : TAB_PCDS_DYNAMIC_EX,
41 MODEL_PCD_DYNAMIC_EX_HII : TAB_PCDS_DYNAMIC_EX_HII,
42 MODEL_PCD_DYNAMIC_EX_VPD : TAB_PCDS_DYNAMIC_EX_VPD,
43 }
44
45 # dict used to convert part of [Defines] to members of DecBuildData directly
46 _PROPERTY_ = {
47 #
48 # Required Fields
49 #
50 TAB_DEC_DEFINES_PACKAGE_NAME : "_PackageName",
51 TAB_DEC_DEFINES_PACKAGE_GUID : "_Guid",
52 TAB_DEC_DEFINES_PACKAGE_VERSION : "_Version",
53 TAB_DEC_DEFINES_PKG_UNI_FILE : "_PkgUniFile",
54 }
55
56
57 ## Constructor of DecBuildData
58 #
59 # Initialize object of DecBuildData
60 #
61 # @param FilePath The path of package description file
62 # @param RawData The raw data of DEC file
63 # @param BuildDataBase Database used to retrieve module information
64 # @param Arch The target architecture
65 # @param Platform (not used for DecBuildData)
66 # @param Macros Macros used for replacement in DSC file
67 #
68 def __init__(self, File, RawData, BuildDataBase, Arch=TAB_ARCH_COMMON, Target=None, Toolchain=None):
69 self.MetaFile = File
70 self._PackageDir = File.Dir
71 self._RawData = RawData
72 self._Bdb = BuildDataBase
73 self._Arch = Arch
74 self._Target = Target
75 self._Toolchain = Toolchain
76 self._Clear()
77
78 ## XXX[key] = value
79 def __setitem__(self, key, value):
80 self.__dict__[self._PROPERTY_[key]] = value
81
82 ## value = XXX[key]
83 def __getitem__(self, key):
84 return self.__dict__[self._PROPERTY_[key]]
85
86 ## "in" test support
87 def __contains__(self, key):
88 return key in self._PROPERTY_
89
90 ## Set all internal used members of DecBuildData to None
91 def _Clear(self):
92 self._Header = None
93 self._PackageName = None
94 self._Guid = None
95 self._Version = None
96 self._PkgUniFile = None
97 self._Protocols = None
98 self._Ppis = None
99 self._Guids = None
100 self._Includes = None
101 self._CommonIncludes = None
102 self._LibraryClasses = None
103 self._Pcds = None
104 self._MacroDict = None
105 self._PrivateProtocols = None
106 self._PrivatePpis = None
107 self._PrivateGuids = None
108 self._PrivateIncludes = None
109
110 ## Get current effective macros
111 @property
112 def _Macros(self):
113 if self._MacroDict is None:
114 self._MacroDict = dict(gGlobalDefines)
115 return self._MacroDict
116
117 ## Get architecture
118 @property
119 def Arch(self):
120 return self._Arch
121
122 ## Retrieve all information in [Defines] section
123 #
124 # (Retriving all [Defines] information in one-shot is just to save time.)
125 #
126 def _GetHeaderInfo(self):
127 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch]
128 for Record in RecordList:
129 Name = Record[1]
130 if Name in self:
131 self[Name] = Record[2]
132 self._Header = 'DUMMY'
133
134 ## Retrieve package name
135 @property
136 def PackageName(self):
137 if self._PackageName is None:
138 if self._Header is None:
139 self._GetHeaderInfo()
140 if self._PackageName is None:
141 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_NAME", File=self.MetaFile)
142 return self._PackageName
143
144 ## Retrieve file guid
145 @property
146 def PackageName(self):
147 if self._Guid is None:
148 if self._Header is None:
149 self._GetHeaderInfo()
150 if self._Guid is None:
151 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_GUID", File=self.MetaFile)
152 return self._Guid
153
154 ## Retrieve package version
155 @property
156 def Version(self):
157 if self._Version is None:
158 if self._Header is None:
159 self._GetHeaderInfo()
160 if self._Version is None:
161 self._Version = ''
162 return self._Version
163
164 ## Retrieve protocol definitions (name/value pairs)
165 @property
166 def Protocols(self):
167 if self._Protocols is None:
168 #
169 # tdict is a special kind of dict, used for selecting correct
170 # protocol defition for given ARCH
171 #
172 ProtocolDict = tdict(True)
173 PrivateProtocolDict = tdict(True)
174 NameList = []
175 PrivateNameList = []
176 PublicNameList = []
177 # find out all protocol definitions for specific and 'common' arch
178 RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch]
179 for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
180 if PrivateFlag == 'PRIVATE':
181 if Name not in PrivateNameList:
182 PrivateNameList.append(Name)
183 PrivateProtocolDict[Arch, Name] = Guid
184 if Name in PublicNameList:
185 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
186 else:
187 if Name not in PublicNameList:
188 PublicNameList.append(Name)
189 if Name in PrivateNameList:
190 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
191 if Name not in NameList:
192 NameList.append(Name)
193 ProtocolDict[Arch, Name] = Guid
194 # use OrderedDict to keep the order
195 self._Protocols = OrderedDict()
196 self._PrivateProtocols = OrderedDict()
197 for Name in NameList:
198 #
199 # limit the ARCH to self._Arch, if no self._Arch found, tdict
200 # will automatically turn to 'common' ARCH for trying
201 #
202 self._Protocols[Name] = ProtocolDict[self._Arch, Name]
203 for Name in PrivateNameList:
204 self._PrivateProtocols[Name] = PrivateProtocolDict[self._Arch, Name]
205 return self._Protocols
206
207 ## Retrieve PPI definitions (name/value pairs)
208 @property
209 def Ppis(self):
210 if self._Ppis is None:
211 #
212 # tdict is a special kind of dict, used for selecting correct
213 # PPI defition for given ARCH
214 #
215 PpiDict = tdict(True)
216 PrivatePpiDict = tdict(True)
217 NameList = []
218 PrivateNameList = []
219 PublicNameList = []
220 # find out all PPI definitions for specific arch and 'common' arch
221 RecordList = self._RawData[MODEL_EFI_PPI, self._Arch]
222 for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
223 if PrivateFlag == 'PRIVATE':
224 if Name not in PrivateNameList:
225 PrivateNameList.append(Name)
226 PrivatePpiDict[Arch, Name] = Guid
227 if Name in PublicNameList:
228 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
229 else:
230 if Name not in PublicNameList:
231 PublicNameList.append(Name)
232 if Name in PrivateNameList:
233 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
234 if Name not in NameList:
235 NameList.append(Name)
236 PpiDict[Arch, Name] = Guid
237 # use OrderedDict to keep the order
238 self._Ppis = OrderedDict()
239 self._PrivatePpis = OrderedDict()
240 for Name in NameList:
241 #
242 # limit the ARCH to self._Arch, if no self._Arch found, tdict
243 # will automatically turn to 'common' ARCH for trying
244 #
245 self._Ppis[Name] = PpiDict[self._Arch, Name]
246 for Name in PrivateNameList:
247 self._PrivatePpis[Name] = PrivatePpiDict[self._Arch, Name]
248 return self._Ppis
249
250 ## Retrieve GUID definitions (name/value pairs)
251 @property
252 def Guids(self):
253 if self._Guids is None:
254 #
255 # tdict is a special kind of dict, used for selecting correct
256 # GUID defition for given ARCH
257 #
258 GuidDict = tdict(True)
259 PrivateGuidDict = tdict(True)
260 NameList = []
261 PrivateNameList = []
262 PublicNameList = []
263 # find out all protocol definitions for specific and 'common' arch
264 RecordList = self._RawData[MODEL_EFI_GUID, self._Arch]
265 for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
266 if PrivateFlag == 'PRIVATE':
267 if Name not in PrivateNameList:
268 PrivateNameList.append(Name)
269 PrivateGuidDict[Arch, Name] = Guid
270 if Name in PublicNameList:
271 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
272 else:
273 if Name not in PublicNameList:
274 PublicNameList.append(Name)
275 if Name in PrivateNameList:
276 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
277 if Name not in NameList:
278 NameList.append(Name)
279 GuidDict[Arch, Name] = Guid
280 # use OrderedDict to keep the order
281 self._Guids = OrderedDict()
282 self._PrivateGuids = OrderedDict()
283 for Name in NameList:
284 #
285 # limit the ARCH to self._Arch, if no self._Arch found, tdict
286 # will automatically turn to 'common' ARCH for trying
287 #
288 self._Guids[Name] = GuidDict[self._Arch, Name]
289 for Name in PrivateNameList:
290 self._PrivateGuids[Name] = PrivateGuidDict[self._Arch, Name]
291 return self._Guids
292
293 ## Retrieve public include paths declared in this package
294 @property
295 def Includes(self):
296 if self._Includes is None or self._CommonIncludes is None:
297 self._CommonIncludes = []
298 self._Includes = []
299 self._PrivateIncludes = []
300 PublicInclues = []
301 RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch]
302 Macros = self._Macros
303 Macros["EDK_SOURCE"] = gEcpSource
304 for Record in RecordList:
305 File = PathClass(NormPath(Record[0], Macros), self._PackageDir, Arch=self._Arch)
306 LineNo = Record[-1]
307 # validate the path
308 ErrorCode, ErrorInfo = File.Validate()
309 if ErrorCode != 0:
310 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
311
312 # avoid duplicate include path
313 if File not in self._Includes:
314 self._Includes.append(File)
315 if Record[4] == 'PRIVATE':
316 if File not in self._PrivateIncludes:
317 self._PrivateIncludes.append(File)
318 if File in PublicInclues:
319 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % File, File=self.MetaFile, Line=LineNo)
320 else:
321 if File not in PublicInclues:
322 PublicInclues.append(File)
323 if File in self._PrivateIncludes:
324 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % File, File=self.MetaFile, Line=LineNo)
325 if Record[3] == TAB_COMMON:
326 self._CommonIncludes.append(File)
327 return self._Includes
328
329 ## Retrieve library class declarations (not used in build at present)
330 @property
331 def LibraryClasses(self):
332 if self._LibraryClasses is None:
333 #
334 # tdict is a special kind of dict, used for selecting correct
335 # library class declaration for given ARCH
336 #
337 LibraryClassDict = tdict(True)
338 LibraryClassSet = set()
339 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch]
340 Macros = self._Macros
341 for LibraryClass, File, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
342 File = PathClass(NormPath(File, Macros), self._PackageDir, Arch=self._Arch)
343 # check the file validation
344 ErrorCode, ErrorInfo = File.Validate()
345 if ErrorCode != 0:
346 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
347 LibraryClassSet.add(LibraryClass)
348 LibraryClassDict[Arch, LibraryClass] = File
349 self._LibraryClasses = OrderedDict()
350 for LibraryClass in LibraryClassSet:
351 self._LibraryClasses[LibraryClass] = LibraryClassDict[self._Arch, LibraryClass]
352 return self._LibraryClasses
353
354 ## Retrieve PCD declarations
355 @property
356 def Pcds(self):
357 if self._Pcds is None:
358 self._Pcds = OrderedDict()
359 self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
360 self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
361 self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
362 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC))
363 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
364 return self._Pcds
365
366 def ParsePcdName(self,TokenCName):
367 TokenCName = TokenCName.strip()
368 if TokenCName.startswith("["):
369 if "." in TokenCName:
370 Demesionattr = TokenCName[:TokenCName.index(".")]
371 Fields = TokenCName[TokenCName.index(".")+1:]
372 else:
373 Demesionattr = TokenCName
374 Fields = ""
375 else:
376 Demesionattr = ""
377 Fields = TokenCName
378
379 return Demesionattr,Fields
380
381 def ProcessStructurePcd(self, StructurePcdRawDataSet):
382 s_pcd_set = OrderedDict()
383 for s_pcd, LineNo in StructurePcdRawDataSet:
384 if s_pcd.TokenSpaceGuidCName not in s_pcd_set:
385 s_pcd_set[s_pcd.TokenSpaceGuidCName] = []
386 s_pcd_set[s_pcd.TokenSpaceGuidCName].append((s_pcd, LineNo))
387
388 str_pcd_set = []
389 for pcdname in s_pcd_set:
390 dep_pkgs = []
391 struct_pcd = StructurePcd()
392 for item, LineNo in s_pcd_set[pcdname]:
393 if not item.TokenCName:
394 continue
395 if "<HeaderFiles>" in item.TokenCName:
396 struct_pcd.StructuredPcdIncludeFile.append(item.DefaultValue)
397 elif "<Packages>" in item.TokenCName:
398 dep_pkgs.append(item.DefaultValue)
399 elif item.DatumType == item.TokenCName:
400 struct_pcd.copy(item)
401 struct_pcd.TokenValue = struct_pcd.TokenValue.strip("{").strip()
402 struct_pcd.TokenSpaceGuidCName, struct_pcd.TokenCName = pcdname.split(".")
403 struct_pcd.PcdDefineLineNo = LineNo
404 struct_pcd.PkgPath = self.MetaFile.File
405 struct_pcd.SetDecDefaultValue(item.DefaultValue)
406 else:
407 DemesionAttr, Fields = self.ParsePcdName(item.TokenCName)
408 struct_pcd.AddDefaultValue(Fields, item.DefaultValue, self.MetaFile.File, LineNo,DemesionAttr)
409
410 struct_pcd.PackageDecs = dep_pkgs
411 str_pcd_set.append(struct_pcd)
412 return str_pcd_set
413
414 ## Retrieve PCD declarations for given type
415 def _GetPcd(self, Type):
416 Pcds = OrderedDict()
417 #
418 # tdict is a special kind of dict, used for selecting correct
419 # PCD declaration for given ARCH
420 #
421 PcdDict = tdict(True, 3)
422 # for summarizing PCD
423 PcdSet = []
424 # find out all PCDs of the 'type'
425
426 StrPcdSet = []
427 RecordList = self._RawData[Type, self._Arch]
428 for TokenSpaceGuid, PcdCName, Setting, Arch, PrivateFlag, Dummy1, Dummy2 in RecordList:
429 PcdDict[Arch, PcdCName, TokenSpaceGuid] = (Setting, Dummy2)
430 if not (PcdCName, TokenSpaceGuid) in PcdSet:
431 PcdSet.append((PcdCName, TokenSpaceGuid))
432
433 DefinitionPosition = {}
434 for PcdCName, TokenSpaceGuid in PcdSet:
435 #
436 # limit the ARCH to self._Arch, if no self._Arch found, tdict
437 # will automatically turn to 'common' ARCH and try again
438 #
439 Setting, LineNo = PcdDict[self._Arch, PcdCName, TokenSpaceGuid]
440 if Setting is None:
441 continue
442
443 DefaultValue, DatumType, TokenNumber = AnalyzePcdData(Setting)
444 validateranges, validlists, expressions = self._RawData.GetValidExpression(TokenSpaceGuid, PcdCName)
445 PcdObj = PcdClassObject(
446 PcdCName,
447 TokenSpaceGuid,
448 self._PCD_TYPE_STRING_[Type],
449 DatumType,
450 DefaultValue,
451 TokenNumber,
452 '',
453 {},
454 False,
455 None,
456 list(validateranges),
457 list(validlists),
458 list(expressions)
459 )
460 DefinitionPosition[PcdObj] = (self.MetaFile.File, LineNo)
461 if "." in TokenSpaceGuid:
462 StrPcdSet.append((PcdObj, LineNo))
463 else:
464 Pcds[PcdCName, TokenSpaceGuid, self._PCD_TYPE_STRING_[Type]] = PcdObj
465
466 StructurePcds = self.ProcessStructurePcd(StrPcdSet)
467 for pcd in StructurePcds:
468 Pcds[pcd.TokenCName, pcd.TokenSpaceGuidCName, self._PCD_TYPE_STRING_[Type]] = pcd
469 StructPattern = compile(r'[_a-zA-Z][0-9A-Za-z_]*$')
470 for pcd in Pcds.values():
471 if pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
472 if not pcd.IsAggregateDatumType():
473 EdkLogger.error('build', FORMAT_INVALID, "DatumType only support BOOLEAN, UINT8, UINT16, UINT32, UINT64, VOID* or a valid struct name.", DefinitionPosition[pcd][0], DefinitionPosition[pcd][1])
474 elif not pcd.IsArray() and not pcd.StructuredPcdIncludeFile:
475 EdkLogger.error("build", PCD_STRUCTURE_PCD_ERROR, "The structure Pcd %s.%s header file is not found in %s line %s \n" % (pcd.TokenSpaceGuidCName, pcd.TokenCName, pcd.DefinitionPosition[0], pcd.DefinitionPosition[1] ))
476 return Pcds
477
478 @property
479 def CommonIncludes(self):
480 if self._CommonIncludes is None:
481 self.Includes
482 return self._CommonIncludes