2 # This file is used to create a database used by build tool
4 # Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
5 # (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
8 from Common
.StringUtils
import *
9 from Common
.DataType
import *
10 from Common
.Misc
import *
12 from collections
import OrderedDict
13 from CommonDataClass
.DataClass
import *
14 from Workspace
.BuildClassObject
import PackageBuildClassObject
, StructurePcd
, PcdClassObject
15 from Common
.GlobalData
import gGlobalDefines
16 from re
import compile
18 ## Platform build information from DEC file
20 # This class is used to retrieve information stored in database and convert them
21 # into PackageBuildClassObject form for easier use for AutoGen.
23 class DecBuildData(PackageBuildClassObject
):
25 # dict used to convert part of [Defines] to members of DecBuildData directly
30 TAB_DEC_DEFINES_PACKAGE_NAME
: "_PackageName",
31 TAB_DEC_DEFINES_PACKAGE_GUID
: "_Guid",
32 TAB_DEC_DEFINES_PACKAGE_VERSION
: "_Version",
33 TAB_DEC_DEFINES_PKG_UNI_FILE
: "_PkgUniFile",
36 ## Constructor of DecBuildData
38 # Initialize object of DecBuildData
40 # @param FilePath The path of package description file
41 # @param RawData The raw data of DEC file
42 # @param BuildDataBase Database used to retrieve module information
43 # @param Arch The target architecture
44 # @param Platform (not used for DecBuildData)
45 # @param Macros Macros used for replacement in DSC file
47 def __init__(self
, File
, RawData
, BuildDataBase
, Arch
=TAB_ARCH_COMMON
, Target
=None, Toolchain
=None):
49 self
._PackageDir
= File
.Dir
50 self
._RawData
= RawData
51 self
._Bdb
= BuildDataBase
54 self
._Toolchain
= Toolchain
56 self
.UpdatePcdTypeDict()
59 def __setitem__(self
, key
, value
):
60 self
.__dict
__[self
._PROPERTY
_[key
]] = value
63 def __getitem__(self
, key
):
64 return self
.__dict
__[self
._PROPERTY
_[key
]]
67 def __contains__(self
, key
):
68 return key
in self
._PROPERTY
_
70 ## Set all internal used members of DecBuildData to None
73 self
._PackageName
= None
76 self
._PkgUniFile
= None
77 self
._Protocols
= None
81 self
._CommonIncludes
= None
82 self
._LibraryClasses
= None
84 self
._MacroDict
= None
85 self
._PrivateProtocols
= None
86 self
._PrivatePpis
= None
87 self
._PrivateGuids
= None
88 self
._PrivateIncludes
= None
90 ## Get current effective macros
93 if self
._MacroDict
is None:
94 self
._MacroDict
= dict(gGlobalDefines
)
95 return self
._MacroDict
102 ## Retrieve all information in [Defines] section
104 # (Retrieving all [Defines] information in one-shot is just to save time.)
106 def _GetHeaderInfo(self
):
107 RecordList
= self
._RawData
[MODEL_META_DATA_HEADER
, self
._Arch
]
108 for Record
in RecordList
:
111 self
[Name
] = Record
[2]
112 self
._Header
= 'DUMMY'
114 ## Retrieve package name
116 def PackageName(self
):
117 if self
._PackageName
is None:
118 if self
._Header
is None:
119 self
._GetHeaderInfo
()
120 if self
._PackageName
is None:
121 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "No PACKAGE_NAME", File
=self
.MetaFile
)
122 return self
._PackageName
124 ## Retrieve file guid
126 def PackageName(self
):
127 if self
._Guid
is None:
128 if self
._Header
is None:
129 self
._GetHeaderInfo
()
130 if self
._Guid
is None:
131 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "No PACKAGE_GUID", File
=self
.MetaFile
)
134 ## Retrieve package version
137 if self
._Version
is None:
138 if self
._Header
is None:
139 self
._GetHeaderInfo
()
140 if self
._Version
is None:
144 ## Retrieve protocol definitions (name/value pairs)
147 if self
._Protocols
is None:
149 # tdict is a special kind of dict, used for selecting correct
150 # protocol definition for given ARCH
152 ProtocolDict
= tdict(True)
153 PrivateProtocolDict
= tdict(True)
157 # find out all protocol definitions for specific and 'common' arch
158 RecordList
= self
._RawData
[MODEL_EFI_PROTOCOL
, self
._Arch
]
159 for Name
, Guid
, Dummy
, Arch
, PrivateFlag
, ID
, LineNo
in RecordList
:
160 if PrivateFlag
== 'PRIVATE':
161 if Name
not in PrivateNameList
:
162 PrivateNameList
.append(Name
)
163 PrivateProtocolDict
[Arch
, Name
] = Guid
164 if Name
in PublicNameList
:
165 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
)
167 if Name
not in PublicNameList
:
168 PublicNameList
.append(Name
)
169 if Name
in PrivateNameList
:
170 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
)
171 if Name
not in NameList
:
172 NameList
.append(Name
)
173 ProtocolDict
[Arch
, Name
] = Guid
174 # use OrderedDict to keep the order
175 self
._Protocols
= OrderedDict()
176 self
._PrivateProtocols
= OrderedDict()
177 for Name
in NameList
:
179 # limit the ARCH to self._Arch, if no self._Arch found, tdict
180 # will automatically turn to 'common' ARCH for trying
182 self
._Protocols
[Name
] = ProtocolDict
[self
._Arch
, Name
]
183 for Name
in PrivateNameList
:
184 self
._PrivateProtocols
[Name
] = PrivateProtocolDict
[self
._Arch
, Name
]
185 return self
._Protocols
187 ## Retrieve PPI definitions (name/value pairs)
190 if self
._Ppis
is None:
192 # tdict is a special kind of dict, used for selecting correct
193 # PPI definition for given ARCH
195 PpiDict
= tdict(True)
196 PrivatePpiDict
= tdict(True)
200 # find out all PPI definitions for specific arch and 'common' arch
201 RecordList
= self
._RawData
[MODEL_EFI_PPI
, self
._Arch
]
202 for Name
, Guid
, Dummy
, Arch
, PrivateFlag
, ID
, LineNo
in RecordList
:
203 if PrivateFlag
== 'PRIVATE':
204 if Name
not in PrivateNameList
:
205 PrivateNameList
.append(Name
)
206 PrivatePpiDict
[Arch
, Name
] = Guid
207 if Name
in PublicNameList
:
208 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
)
210 if Name
not in PublicNameList
:
211 PublicNameList
.append(Name
)
212 if Name
in PrivateNameList
:
213 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
)
214 if Name
not in NameList
:
215 NameList
.append(Name
)
216 PpiDict
[Arch
, Name
] = Guid
217 # use OrderedDict to keep the order
218 self
._Ppis
= OrderedDict()
219 self
._PrivatePpis
= OrderedDict()
220 for Name
in NameList
:
222 # limit the ARCH to self._Arch, if no self._Arch found, tdict
223 # will automatically turn to 'common' ARCH for trying
225 self
._Ppis
[Name
] = PpiDict
[self
._Arch
, Name
]
226 for Name
in PrivateNameList
:
227 self
._PrivatePpis
[Name
] = PrivatePpiDict
[self
._Arch
, Name
]
230 ## Retrieve GUID definitions (name/value pairs)
233 if self
._Guids
is None:
235 # tdict is a special kind of dict, used for selecting correct
236 # GUID definition for given ARCH
238 GuidDict
= tdict(True)
239 PrivateGuidDict
= tdict(True)
243 # find out all protocol definitions for specific and 'common' arch
244 RecordList
= self
._RawData
[MODEL_EFI_GUID
, self
._Arch
]
245 for Name
, Guid
, Dummy
, Arch
, PrivateFlag
, ID
, LineNo
in RecordList
:
246 if PrivateFlag
== 'PRIVATE':
247 if Name
not in PrivateNameList
:
248 PrivateNameList
.append(Name
)
249 PrivateGuidDict
[Arch
, Name
] = Guid
250 if Name
in PublicNameList
:
251 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
)
253 if Name
not in PublicNameList
:
254 PublicNameList
.append(Name
)
255 if Name
in PrivateNameList
:
256 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
)
257 if Name
not in NameList
:
258 NameList
.append(Name
)
259 GuidDict
[Arch
, Name
] = Guid
260 # use OrderedDict to keep the order
261 self
._Guids
= OrderedDict()
262 self
._PrivateGuids
= OrderedDict()
263 for Name
in NameList
:
265 # limit the ARCH to self._Arch, if no self._Arch found, tdict
266 # will automatically turn to 'common' ARCH for trying
268 self
._Guids
[Name
] = GuidDict
[self
._Arch
, Name
]
269 for Name
in PrivateNameList
:
270 self
._PrivateGuids
[Name
] = PrivateGuidDict
[self
._Arch
, Name
]
273 ## Retrieve public include paths declared in this package
276 if self
._Includes
is None or self
._CommonIncludes
is None:
277 self
._CommonIncludes
= []
279 self
._PrivateIncludes
= []
281 RecordList
= self
._RawData
[MODEL_EFI_INCLUDE
, self
._Arch
]
282 Macros
= self
._Macros
283 for Record
in RecordList
:
284 File
= PathClass(NormPath(Record
[0], Macros
), self
._PackageDir
, Arch
=self
._Arch
)
287 ErrorCode
, ErrorInfo
= File
.Validate()
289 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
291 # avoid duplicate include path
292 if File
not in self
._Includes
:
293 self
._Includes
.append(File
)
294 if Record
[4] == 'PRIVATE':
295 if File
not in self
._PrivateIncludes
:
296 self
._PrivateIncludes
.append(File
)
297 if File
in PublicInclues
:
298 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
)
300 if File
not in PublicInclues
:
301 PublicInclues
.append(File
)
302 if File
in self
._PrivateIncludes
:
303 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
)
304 if Record
[3] == TAB_COMMON
:
305 self
._CommonIncludes
.append(File
)
306 return self
._Includes
308 ## Retrieve library class declarations (not used in build at present)
310 def LibraryClasses(self
):
311 if self
._LibraryClasses
is None:
313 # tdict is a special kind of dict, used for selecting correct
314 # library class declaration for given ARCH
316 LibraryClassDict
= tdict(True)
317 LibraryClassSet
= set()
318 RecordList
= self
._RawData
[MODEL_EFI_LIBRARY_CLASS
, self
._Arch
]
319 Macros
= self
._Macros
320 for LibraryClass
, File
, Dummy
, Arch
, PrivateFlag
, ID
, LineNo
in RecordList
:
321 File
= PathClass(NormPath(File
, Macros
), self
._PackageDir
, Arch
=self
._Arch
)
322 # check the file validation
323 ErrorCode
, ErrorInfo
= File
.Validate()
325 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
326 LibraryClassSet
.add(LibraryClass
)
327 LibraryClassDict
[Arch
, LibraryClass
] = File
328 self
._LibraryClasses
= OrderedDict()
329 for LibraryClass
in LibraryClassSet
:
330 self
._LibraryClasses
[LibraryClass
] = LibraryClassDict
[self
._Arch
, LibraryClass
]
331 return self
._LibraryClasses
333 ## Retrieve PCD declarations
336 if self
._Pcds
is None:
337 self
._Pcds
= OrderedDict()
338 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_FIXED_AT_BUILD
))
339 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_PATCHABLE_IN_MODULE
))
340 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_FEATURE_FLAG
))
341 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_DYNAMIC
))
342 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_DYNAMIC_EX
))
345 def ParsePcdName(self
,TokenCName
):
346 TokenCName
= TokenCName
.strip()
347 if TokenCName
.startswith("["):
348 if "." in TokenCName
:
349 Demesionattr
= TokenCName
[:TokenCName
.index(".")]
350 Fields
= TokenCName
[TokenCName
.index(".")+1:]
352 Demesionattr
= TokenCName
358 return Demesionattr
,Fields
360 def ProcessStructurePcd(self
, StructurePcdRawDataSet
):
361 s_pcd_set
= OrderedDict()
362 for s_pcd
, LineNo
in StructurePcdRawDataSet
:
363 if s_pcd
.TokenSpaceGuidCName
not in s_pcd_set
:
364 s_pcd_set
[s_pcd
.TokenSpaceGuidCName
] = []
365 s_pcd_set
[s_pcd
.TokenSpaceGuidCName
].append((s_pcd
, LineNo
))
368 for pcdname
in s_pcd_set
:
370 struct_pcd
= StructurePcd()
371 for item
, LineNo
in s_pcd_set
[pcdname
]:
372 if not item
.TokenCName
:
374 if "<HeaderFiles>" in item
.TokenCName
:
375 struct_pcd
.StructuredPcdIncludeFile
.append(item
.DefaultValue
)
376 elif "<Packages>" in item
.TokenCName
:
377 dep_pkgs
.append(item
.DefaultValue
)
378 elif item
.DatumType
== item
.TokenCName
:
379 struct_pcd
.copy(item
)
380 struct_pcd
.TokenValue
= struct_pcd
.TokenValue
.strip("{").strip()
381 struct_pcd
.TokenSpaceGuidCName
, struct_pcd
.TokenCName
= pcdname
.split(".")
382 struct_pcd
.PcdDefineLineNo
= LineNo
383 struct_pcd
.PkgPath
= self
.MetaFile
.File
384 struct_pcd
.SetDecDefaultValue(item
.DefaultValue
,self
.MetaFile
.File
,LineNo
)
386 DemesionAttr
, Fields
= self
.ParsePcdName(item
.TokenCName
)
387 struct_pcd
.AddDefaultValue(Fields
, item
.DefaultValue
, self
.MetaFile
.File
, LineNo
,DemesionAttr
)
389 struct_pcd
.PackageDecs
= dep_pkgs
390 str_pcd_set
.append(struct_pcd
)
393 ## Retrieve PCD declarations for given type
394 def _GetPcd(self
, Type
):
397 # tdict is a special kind of dict, used for selecting correct
398 # PCD declaration for given ARCH
400 PcdDict
= tdict(True, 3)
401 # for summarizing PCD
403 # find out all PCDs of the 'type'
406 RecordList
= self
._RawData
[Type
, self
._Arch
]
407 for TokenSpaceGuid
, PcdCName
, Setting
, Arch
, PrivateFlag
, Dummy1
, Dummy2
in RecordList
:
408 PcdDict
[Arch
, PcdCName
, TokenSpaceGuid
] = (Setting
, Dummy2
)
409 if not (PcdCName
, TokenSpaceGuid
) in PcdSet
:
410 PcdSet
.append((PcdCName
, TokenSpaceGuid
))
412 DefinitionPosition
= {}
413 for PcdCName
, TokenSpaceGuid
in PcdSet
:
415 # limit the ARCH to self._Arch, if no self._Arch found, tdict
416 # will automatically turn to 'common' ARCH and try again
418 Setting
, LineNo
= PcdDict
[self
._Arch
, PcdCName
, TokenSpaceGuid
]
422 DefaultValue
, DatumType
, TokenNumber
= AnalyzePcdData(Setting
)
423 validateranges
, validlists
, expressions
= self
._RawData
.GetValidExpression(TokenSpaceGuid
, PcdCName
)
424 PcdObj
= PcdClassObject(
427 self
._PCD
_TYPE
_STRING
_[Type
],
435 list(validateranges
),
439 DefinitionPosition
[PcdObj
] = (self
.MetaFile
.File
, LineNo
)
440 if "." in TokenSpaceGuid
:
441 StrPcdSet
.append((PcdObj
, LineNo
))
443 Pcds
[PcdCName
, TokenSpaceGuid
, self
._PCD
_TYPE
_STRING
_[Type
]] = PcdObj
445 StructurePcds
= self
.ProcessStructurePcd(StrPcdSet
)
446 for pcd
in StructurePcds
:
447 Pcds
[pcd
.TokenCName
, pcd
.TokenSpaceGuidCName
, self
._PCD
_TYPE
_STRING
_[Type
]] = pcd
448 StructPattern
= compile(r
'[_a-zA-Z][0-9A-Za-z_]*$')
449 for pcd
in Pcds
.values():
450 if pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
451 if not pcd
.IsAggregateDatumType():
452 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])
453 elif not pcd
.IsArray() and not pcd
.StructuredPcdIncludeFile
:
454 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] ))
458 def CommonIncludes(self
):
459 if self
._CommonIncludes
is None:
461 return self
._CommonIncludes