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