]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/DecBuildData.py
BaseTools: Update copyright year info of DSC/DEC/INF BuilData.py file
[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 - 2017, 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._LibraryClasses = None
99 self._Pcds = None
100 self.__Macros = None
101 self._PrivateProtocols = None
102 self._PrivatePpis = None
103 self._PrivateGuids = None
104 self._PrivateIncludes = None
105
106 ## Get current effective macros
107 def _GetMacros(self):
108 if self.__Macros == None:
109 self.__Macros = {}
110 self.__Macros.update(GlobalData.gGlobalDefines)
111 return self.__Macros
112
113 ## Get architecture
114 def _GetArch(self):
115 return self._Arch
116
117 ## Set architecture
118 #
119 # Changing the default ARCH to another may affect all other information
120 # because all information in a platform may be ARCH-related. That's
121 # why we need to clear all internal used members, in order to cause all
122 # information to be re-retrieved.
123 #
124 # @param Value The value of ARCH
125 #
126 def _SetArch(self, Value):
127 if self._Arch == Value:
128 return
129 self._Arch = Value
130 self._Clear()
131
132 ## Retrieve all information in [Defines] section
133 #
134 # (Retriving all [Defines] information in one-shot is just to save time.)
135 #
136 def _GetHeaderInfo(self):
137 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch]
138 for Record in RecordList:
139 Name = Record[1]
140 if Name in self:
141 self[Name] = Record[2]
142 self._Header = 'DUMMY'
143
144 ## Retrieve package name
145 def _GetPackageName(self):
146 if self._PackageName == None:
147 if self._Header == None:
148 self._GetHeaderInfo()
149 if self._PackageName == None:
150 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_NAME", File=self.MetaFile)
151 return self._PackageName
152
153 ## Retrieve file guid
154 def _GetFileGuid(self):
155 if self._Guid == None:
156 if self._Header == None:
157 self._GetHeaderInfo()
158 if self._Guid == None:
159 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_GUID", File=self.MetaFile)
160 return self._Guid
161
162 ## Retrieve package version
163 def _GetVersion(self):
164 if self._Version == None:
165 if self._Header == None:
166 self._GetHeaderInfo()
167 if self._Version == None:
168 self._Version = ''
169 return self._Version
170
171 ## Retrieve protocol definitions (name/value pairs)
172 def _GetProtocol(self):
173 if self._Protocols == None:
174 #
175 # tdict is a special kind of dict, used for selecting correct
176 # protocol defition for given ARCH
177 #
178 ProtocolDict = tdict(True)
179 PrivateProtocolDict = tdict(True)
180 NameList = []
181 PrivateNameList = []
182 PublicNameList = []
183 # find out all protocol definitions for specific and 'common' arch
184 RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch]
185 for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
186 if PrivateFlag == 'PRIVATE':
187 if Name not in PrivateNameList:
188 PrivateNameList.append(Name)
189 PrivateProtocolDict[Arch, Name] = Guid
190 if Name in PublicNameList:
191 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)
192 else:
193 if Name not in PublicNameList:
194 PublicNameList.append(Name)
195 if Name in PrivateNameList:
196 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)
197 if Name not in NameList:
198 NameList.append(Name)
199 ProtocolDict[Arch, Name] = Guid
200 # use sdict to keep the order
201 self._Protocols = sdict()
202 self._PrivateProtocols = sdict()
203 for Name in NameList:
204 #
205 # limit the ARCH to self._Arch, if no self._Arch found, tdict
206 # will automatically turn to 'common' ARCH for trying
207 #
208 self._Protocols[Name] = ProtocolDict[self._Arch, Name]
209 for Name in PrivateNameList:
210 self._PrivateProtocols[Name] = PrivateProtocolDict[self._Arch, Name]
211 return self._Protocols
212
213 ## Retrieve PPI definitions (name/value pairs)
214 def _GetPpi(self):
215 if self._Ppis == None:
216 #
217 # tdict is a special kind of dict, used for selecting correct
218 # PPI defition for given ARCH
219 #
220 PpiDict = tdict(True)
221 PrivatePpiDict = tdict(True)
222 NameList = []
223 PrivateNameList = []
224 PublicNameList = []
225 # find out all PPI definitions for specific arch and 'common' arch
226 RecordList = self._RawData[MODEL_EFI_PPI, self._Arch]
227 for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
228 if PrivateFlag == 'PRIVATE':
229 if Name not in PrivateNameList:
230 PrivateNameList.append(Name)
231 PrivatePpiDict[Arch, Name] = Guid
232 if Name in PublicNameList:
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 else:
235 if Name not in PublicNameList:
236 PublicNameList.append(Name)
237 if Name in PrivateNameList:
238 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)
239 if Name not in NameList:
240 NameList.append(Name)
241 PpiDict[Arch, Name] = Guid
242 # use sdict to keep the order
243 self._Ppis = sdict()
244 self._PrivatePpis = sdict()
245 for Name in NameList:
246 #
247 # limit the ARCH to self._Arch, if no self._Arch found, tdict
248 # will automatically turn to 'common' ARCH for trying
249 #
250 self._Ppis[Name] = PpiDict[self._Arch, Name]
251 for Name in PrivateNameList:
252 self._PrivatePpis[Name] = PrivatePpiDict[self._Arch, Name]
253 return self._Ppis
254
255 ## Retrieve GUID definitions (name/value pairs)
256 def _GetGuid(self):
257 if self._Guids == None:
258 #
259 # tdict is a special kind of dict, used for selecting correct
260 # GUID defition for given ARCH
261 #
262 GuidDict = tdict(True)
263 PrivateGuidDict = tdict(True)
264 NameList = []
265 PrivateNameList = []
266 PublicNameList = []
267 # find out all protocol definitions for specific and 'common' arch
268 RecordList = self._RawData[MODEL_EFI_GUID, self._Arch]
269 for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
270 if PrivateFlag == 'PRIVATE':
271 if Name not in PrivateNameList:
272 PrivateNameList.append(Name)
273 PrivateGuidDict[Arch, Name] = Guid
274 if Name in PublicNameList:
275 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)
276 else:
277 if Name not in PublicNameList:
278 PublicNameList.append(Name)
279 if Name in PrivateNameList:
280 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)
281 if Name not in NameList:
282 NameList.append(Name)
283 GuidDict[Arch, Name] = Guid
284 # use sdict to keep the order
285 self._Guids = sdict()
286 self._PrivateGuids = sdict()
287 for Name in NameList:
288 #
289 # limit the ARCH to self._Arch, if no self._Arch found, tdict
290 # will automatically turn to 'common' ARCH for trying
291 #
292 self._Guids[Name] = GuidDict[self._Arch, Name]
293 for Name in PrivateNameList:
294 self._PrivateGuids[Name] = PrivateGuidDict[self._Arch, Name]
295 return self._Guids
296
297 ## Retrieve public include paths declared in this package
298 def _GetInclude(self):
299 if self._Includes == None:
300 self._Includes = []
301 self._PrivateIncludes = []
302 PublicInclues = []
303 RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch]
304 Macros = self._Macros
305 Macros["EDK_SOURCE"] = GlobalData.gEcpSource
306 for Record in RecordList:
307 File = PathClass(NormPath(Record[0], Macros), self._PackageDir, Arch=self._Arch)
308 LineNo = Record[-1]
309 # validate the path
310 ErrorCode, ErrorInfo = File.Validate()
311 if ErrorCode != 0:
312 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
313
314 # avoid duplicate include path
315 if File not in self._Includes:
316 self._Includes.append(File)
317 if Record[4] == 'PRIVATE':
318 if File not in self._PrivateIncludes:
319 self._PrivateIncludes.append(File)
320 if File in PublicInclues:
321 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)
322 else:
323 if File not in PublicInclues:
324 PublicInclues.append(File)
325 if File in self._PrivateIncludes:
326 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)
327
328 return self._Includes
329
330 ## Retrieve library class declarations (not used in build at present)
331 def _GetLibraryClass(self):
332 if self._LibraryClasses == 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 = sdict()
350 for LibraryClass in LibraryClassSet:
351 self._LibraryClasses[LibraryClass] = LibraryClassDict[self._Arch, LibraryClass]
352 return self._LibraryClasses
353
354 ## Retrieve PCD declarations
355 def _GetPcds(self):
356 if self._Pcds == None:
357 self._Pcds = sdict()
358 self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
359 self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
360 self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
361 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC))
362 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
363 return self._Pcds
364
365
366 def ProcessStructurePcd(self, StructurePcdRawDataSet):
367 s_pcd_set = dict()
368 for s_pcd,LineNo in StructurePcdRawDataSet:
369 if s_pcd.TokenSpaceGuidCName not in s_pcd_set:
370 s_pcd_set[s_pcd.TokenSpaceGuidCName] = []
371 s_pcd_set[s_pcd.TokenSpaceGuidCName].append((s_pcd,LineNo))
372
373 str_pcd_set = []
374 for pcdname in s_pcd_set:
375 dep_pkgs = []
376 struct_pcd = StructurePcd()
377 for item,LineNo in s_pcd_set[pcdname]:
378 if "<HeaderFiles>" in item.TokenCName:
379 struct_pcd.StructuredPcdIncludeFile = item.DefaultValue
380 elif "<Packages>" in item.TokenCName:
381 dep_pkgs.append(item.DefaultValue)
382 elif item.DatumType == item.TokenCName:
383 struct_pcd.copy(item)
384 struct_pcd.TokenValue = struct_pcd.TokenValue.strip("{").strip()
385 struct_pcd.TokenSpaceGuidCName, struct_pcd.TokenCName = pcdname.split(".")
386 else:
387 struct_pcd.AddDefaultValue(item.TokenCName, item.DefaultValue,self.MetaFile.File,LineNo)
388
389 struct_pcd.PackageDecs = dep_pkgs
390
391 str_pcd_set.append(struct_pcd)
392
393 return str_pcd_set
394
395 ## Retrieve PCD declarations for given type
396 def _GetPcd(self, Type):
397 Pcds = sdict()
398 #
399 # tdict is a special kind of dict, used for selecting correct
400 # PCD declaration for given ARCH
401 #
402 PcdDict = tdict(True, 3)
403 # for summarizing PCD
404 PcdSet = []
405 # find out all PCDs of the 'type'
406
407 StrPcdSet = []
408 RecordList = self._RawData[Type, self._Arch]
409 for TokenSpaceGuid, PcdCName, Setting, Arch, PrivateFlag, Dummy1, Dummy2 in RecordList:
410 PcdDict[Arch, PcdCName, TokenSpaceGuid] = (Setting,Dummy2)
411 if not (PcdCName, TokenSpaceGuid) in PcdSet:
412 PcdSet.append((PcdCName, TokenSpaceGuid))
413
414 for PcdCName, TokenSpaceGuid in PcdSet:
415 #
416 # limit the ARCH to self._Arch, if no self._Arch found, tdict
417 # will automatically turn to 'common' ARCH and try again
418 #
419 Setting,LineNo = PcdDict[self._Arch, PcdCName, TokenSpaceGuid]
420 if Setting == None:
421 continue
422
423 DefaultValue, DatumType, TokenNumber = AnalyzePcdData(Setting)
424 validateranges, validlists, expressions = self._RawData.GetValidExpression(TokenSpaceGuid, PcdCName)
425 PcdObj = PcdClassObject(
426 PcdCName,
427 TokenSpaceGuid,
428 self._PCD_TYPE_STRING_[Type],
429 DatumType,
430 DefaultValue,
431 TokenNumber,
432 '',
433 {},
434 False,
435 None,
436 list(validateranges),
437 list(validlists),
438 list(expressions)
439 )
440 if "." in TokenSpaceGuid:
441 StrPcdSet.append((PcdObj,LineNo))
442 else:
443 Pcds[PcdCName, TokenSpaceGuid, self._PCD_TYPE_STRING_[Type]] = PcdObj
444
445 StructurePcds = self.ProcessStructurePcd(StrPcdSet)
446 for pcd in StructurePcds:
447 Pcds[pcd.TokenCName, pcd.TokenSpaceGuidCName, self._PCD_TYPE_STRING_[Type]] = pcd
448
449 return Pcds
450
451
452 _Macros = property(_GetMacros)
453 Arch = property(_GetArch, _SetArch)
454 PackageName = property(_GetPackageName)
455 Guid = property(_GetFileGuid)
456 Version = property(_GetVersion)
457
458 Protocols = property(_GetProtocol)
459 Ppis = property(_GetPpi)
460 Guids = property(_GetGuid)
461 Includes = property(_GetInclude)
462 LibraryClasses = property(_GetLibraryClass)
463 Pcds = property(_GetPcds)