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 # 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
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.
14 from Common
.StringUtils
import *
15 from Common
.DataType
import *
16 from Common
.Misc
import *
18 from collections
import OrderedDict
20 from Workspace
.BuildClassObject
import PackageBuildClassObject
, StructurePcd
, PcdClassObject
22 ## Platform build information from DEC file
24 # This class is used to retrieve information stored in database and convert them
25 # into PackageBuildClassObject form for easier use for AutoGen.
27 class DecBuildData(PackageBuildClassObject
):
28 # dict used to convert PCD type in database to string used by build tool
30 MODEL_PCD_FIXED_AT_BUILD
: TAB_PCDS_FIXED_AT_BUILD
,
31 MODEL_PCD_PATCHABLE_IN_MODULE
: TAB_PCDS_PATCHABLE_IN_MODULE
,
32 MODEL_PCD_FEATURE_FLAG
: TAB_PCDS_FEATURE_FLAG
,
33 MODEL_PCD_DYNAMIC
: TAB_PCDS_DYNAMIC
,
34 MODEL_PCD_DYNAMIC_DEFAULT
: TAB_PCDS_DYNAMIC
,
35 MODEL_PCD_DYNAMIC_HII
: TAB_PCDS_DYNAMIC_HII
,
36 MODEL_PCD_DYNAMIC_VPD
: TAB_PCDS_DYNAMIC_VPD
,
37 MODEL_PCD_DYNAMIC_EX
: TAB_PCDS_DYNAMIC_EX
,
38 MODEL_PCD_DYNAMIC_EX_DEFAULT
: TAB_PCDS_DYNAMIC_EX
,
39 MODEL_PCD_DYNAMIC_EX_HII
: TAB_PCDS_DYNAMIC_EX_HII
,
40 MODEL_PCD_DYNAMIC_EX_VPD
: TAB_PCDS_DYNAMIC_EX_VPD
,
43 # dict used to convert part of [Defines] to members of DecBuildData directly
48 TAB_DEC_DEFINES_PACKAGE_NAME
: "_PackageName",
49 TAB_DEC_DEFINES_PACKAGE_GUID
: "_Guid",
50 TAB_DEC_DEFINES_PACKAGE_VERSION
: "_Version",
51 TAB_DEC_DEFINES_PKG_UNI_FILE
: "_PkgUniFile",
55 ## Constructor of DecBuildData
57 # Initialize object of DecBuildData
59 # @param FilePath The path of package description file
60 # @param RawData The raw data of DEC file
61 # @param BuildDataBase Database used to retrieve module information
62 # @param Arch The target architecture
63 # @param Platform (not used for DecBuildData)
64 # @param Macros Macros used for replacement in DSC file
66 def __init__(self
, File
, RawData
, BuildDataBase
, Arch
=TAB_ARCH_COMMON
, Target
=None, Toolchain
=None):
68 self
._PackageDir
= File
.Dir
69 self
._RawData
= RawData
70 self
._Bdb
= BuildDataBase
73 self
._Toolchain
= Toolchain
77 def __setitem__(self
, key
, value
):
78 self
.__dict
__[self
._PROPERTY
_[key
]] = value
81 def __getitem__(self
, key
):
82 return self
.__dict
__[self
._PROPERTY
_[key
]]
85 def __contains__(self
, key
):
86 return key
in self
._PROPERTY
_
88 ## Set all internal used members of DecBuildData to None
91 self
._PackageName
= None
94 self
._PkgUniFile
= None
95 self
._Protocols
= None
99 self
._CommonIncludes
= None
100 self
._LibraryClasses
= None
103 self
._PrivateProtocols
= None
104 self
._PrivatePpis
= None
105 self
._PrivateGuids
= None
106 self
._PrivateIncludes
= None
108 ## Get current effective macros
109 def _GetMacros(self
):
110 if self
.__Macros
is None:
112 self
.__Macros
.update(GlobalData
.gGlobalDefines
)
119 ## Retrieve all information in [Defines] section
121 # (Retriving all [Defines] information in one-shot is just to save time.)
123 def _GetHeaderInfo(self
):
124 RecordList
= self
._RawData
[MODEL_META_DATA_HEADER
, self
._Arch
]
125 for Record
in RecordList
:
128 self
[Name
] = Record
[2]
129 self
._Header
= 'DUMMY'
131 ## Retrieve package name
132 def _GetPackageName(self
):
133 if self
._PackageName
is None:
134 if self
._Header
is None:
135 self
._GetHeaderInfo
()
136 if self
._PackageName
is None:
137 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "No PACKAGE_NAME", File
=self
.MetaFile
)
138 return self
._PackageName
140 ## Retrieve file guid
141 def _GetFileGuid(self
):
142 if self
._Guid
is None:
143 if self
._Header
is None:
144 self
._GetHeaderInfo
()
145 if self
._Guid
is None:
146 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "No PACKAGE_GUID", File
=self
.MetaFile
)
149 ## Retrieve package version
150 def _GetVersion(self
):
151 if self
._Version
is None:
152 if self
._Header
is None:
153 self
._GetHeaderInfo
()
154 if self
._Version
is None:
158 ## Retrieve protocol definitions (name/value pairs)
159 def _GetProtocol(self
):
160 if self
._Protocols
is None:
162 # tdict is a special kind of dict, used for selecting correct
163 # protocol defition for given ARCH
165 ProtocolDict
= tdict(True)
166 PrivateProtocolDict
= tdict(True)
170 # find out all protocol definitions for specific and 'common' arch
171 RecordList
= self
._RawData
[MODEL_EFI_PROTOCOL
, self
._Arch
]
172 for Name
, Guid
, Dummy
, Arch
, PrivateFlag
, ID
, LineNo
in RecordList
:
173 if PrivateFlag
== 'PRIVATE':
174 if Name
not in PrivateNameList
:
175 PrivateNameList
.append(Name
)
176 PrivateProtocolDict
[Arch
, Name
] = Guid
177 if Name
in PublicNameList
:
178 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
)
180 if Name
not in PublicNameList
:
181 PublicNameList
.append(Name
)
182 if Name
in PrivateNameList
:
183 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
)
184 if Name
not in NameList
:
185 NameList
.append(Name
)
186 ProtocolDict
[Arch
, Name
] = Guid
187 # use OrderedDict to keep the order
188 self
._Protocols
= OrderedDict()
189 self
._PrivateProtocols
= OrderedDict()
190 for Name
in NameList
:
192 # limit the ARCH to self._Arch, if no self._Arch found, tdict
193 # will automatically turn to 'common' ARCH for trying
195 self
._Protocols
[Name
] = ProtocolDict
[self
._Arch
, Name
]
196 for Name
in PrivateNameList
:
197 self
._PrivateProtocols
[Name
] = PrivateProtocolDict
[self
._Arch
, Name
]
198 return self
._Protocols
200 ## Retrieve PPI definitions (name/value pairs)
202 if self
._Ppis
is None:
204 # tdict is a special kind of dict, used for selecting correct
205 # PPI defition for given ARCH
207 PpiDict
= tdict(True)
208 PrivatePpiDict
= tdict(True)
212 # find out all PPI definitions for specific arch and 'common' arch
213 RecordList
= self
._RawData
[MODEL_EFI_PPI
, self
._Arch
]
214 for Name
, Guid
, Dummy
, Arch
, PrivateFlag
, ID
, LineNo
in RecordList
:
215 if PrivateFlag
== 'PRIVATE':
216 if Name
not in PrivateNameList
:
217 PrivateNameList
.append(Name
)
218 PrivatePpiDict
[Arch
, Name
] = Guid
219 if Name
in PublicNameList
:
220 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
)
222 if Name
not in PublicNameList
:
223 PublicNameList
.append(Name
)
224 if Name
in PrivateNameList
:
225 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
)
226 if Name
not in NameList
:
227 NameList
.append(Name
)
228 PpiDict
[Arch
, Name
] = Guid
229 # use OrderedDict to keep the order
230 self
._Ppis
= OrderedDict()
231 self
._PrivatePpis
= OrderedDict()
232 for Name
in NameList
:
234 # limit the ARCH to self._Arch, if no self._Arch found, tdict
235 # will automatically turn to 'common' ARCH for trying
237 self
._Ppis
[Name
] = PpiDict
[self
._Arch
, Name
]
238 for Name
in PrivateNameList
:
239 self
._PrivatePpis
[Name
] = PrivatePpiDict
[self
._Arch
, Name
]
242 ## Retrieve GUID definitions (name/value pairs)
244 if self
._Guids
is None:
246 # tdict is a special kind of dict, used for selecting correct
247 # GUID defition for given ARCH
249 GuidDict
= tdict(True)
250 PrivateGuidDict
= tdict(True)
254 # find out all protocol definitions for specific and 'common' arch
255 RecordList
= self
._RawData
[MODEL_EFI_GUID
, self
._Arch
]
256 for Name
, Guid
, Dummy
, Arch
, PrivateFlag
, ID
, LineNo
in RecordList
:
257 if PrivateFlag
== 'PRIVATE':
258 if Name
not in PrivateNameList
:
259 PrivateNameList
.append(Name
)
260 PrivateGuidDict
[Arch
, Name
] = Guid
261 if Name
in PublicNameList
:
262 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
)
264 if Name
not in PublicNameList
:
265 PublicNameList
.append(Name
)
266 if Name
in PrivateNameList
:
267 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
)
268 if Name
not in NameList
:
269 NameList
.append(Name
)
270 GuidDict
[Arch
, Name
] = Guid
271 # use OrderedDict to keep the order
272 self
._Guids
= OrderedDict()
273 self
._PrivateGuids
= OrderedDict()
274 for Name
in NameList
:
276 # limit the ARCH to self._Arch, if no self._Arch found, tdict
277 # will automatically turn to 'common' ARCH for trying
279 self
._Guids
[Name
] = GuidDict
[self
._Arch
, Name
]
280 for Name
in PrivateNameList
:
281 self
._PrivateGuids
[Name
] = PrivateGuidDict
[self
._Arch
, Name
]
284 ## Retrieve public include paths declared in this package
285 def _GetInclude(self
):
286 if self
._Includes
is None or self
._CommonIncludes
is None:
287 self
._CommonIncludes
= []
289 self
._PrivateIncludes
= []
291 RecordList
= self
._RawData
[MODEL_EFI_INCLUDE
, self
._Arch
]
292 Macros
= self
._Macros
293 Macros
["EDK_SOURCE"] = GlobalData
.gEcpSource
294 for Record
in RecordList
:
295 File
= PathClass(NormPath(Record
[0], Macros
), self
._PackageDir
, Arch
=self
._Arch
)
298 ErrorCode
, ErrorInfo
= File
.Validate()
300 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
302 # avoid duplicate include path
303 if File
not in self
._Includes
:
304 self
._Includes
.append(File
)
305 if Record
[4] == 'PRIVATE':
306 if File
not in self
._PrivateIncludes
:
307 self
._PrivateIncludes
.append(File
)
308 if File
in PublicInclues
:
309 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
)
311 if File
not in PublicInclues
:
312 PublicInclues
.append(File
)
313 if File
in self
._PrivateIncludes
:
314 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
)
315 if Record
[3] == TAB_COMMON
:
316 self
._CommonIncludes
.append(File
)
317 return self
._Includes
319 ## Retrieve library class declarations (not used in build at present)
320 def _GetLibraryClass(self
):
321 if self
._LibraryClasses
is None:
323 # tdict is a special kind of dict, used for selecting correct
324 # library class declaration for given ARCH
326 LibraryClassDict
= tdict(True)
327 LibraryClassSet
= set()
328 RecordList
= self
._RawData
[MODEL_EFI_LIBRARY_CLASS
, self
._Arch
]
329 Macros
= self
._Macros
330 for LibraryClass
, File
, Dummy
, Arch
, PrivateFlag
, ID
, LineNo
in RecordList
:
331 File
= PathClass(NormPath(File
, Macros
), self
._PackageDir
, Arch
=self
._Arch
)
332 # check the file validation
333 ErrorCode
, ErrorInfo
= File
.Validate()
335 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
336 LibraryClassSet
.add(LibraryClass
)
337 LibraryClassDict
[Arch
, LibraryClass
] = File
338 self
._LibraryClasses
= OrderedDict()
339 for LibraryClass
in LibraryClassSet
:
340 self
._LibraryClasses
[LibraryClass
] = LibraryClassDict
[self
._Arch
, LibraryClass
]
341 return self
._LibraryClasses
343 ## Retrieve PCD declarations
345 if self
._Pcds
is None:
346 self
._Pcds
= OrderedDict()
347 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_FIXED_AT_BUILD
))
348 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_PATCHABLE_IN_MODULE
))
349 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_FEATURE_FLAG
))
350 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_DYNAMIC
))
351 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_DYNAMIC_EX
))
355 def ProcessStructurePcd(self
, StructurePcdRawDataSet
):
356 s_pcd_set
= OrderedDict()
357 for s_pcd
, LineNo
in StructurePcdRawDataSet
:
358 if s_pcd
.TokenSpaceGuidCName
not in s_pcd_set
:
359 s_pcd_set
[s_pcd
.TokenSpaceGuidCName
] = []
360 s_pcd_set
[s_pcd
.TokenSpaceGuidCName
].append((s_pcd
, LineNo
))
363 for pcdname
in s_pcd_set
:
365 struct_pcd
= StructurePcd()
366 for item
, LineNo
in s_pcd_set
[pcdname
]:
367 if "<HeaderFiles>" in item
.TokenCName
:
368 struct_pcd
.StructuredPcdIncludeFile
.append(item
.DefaultValue
)
369 elif "<Packages>" in item
.TokenCName
:
370 dep_pkgs
.append(item
.DefaultValue
)
371 elif item
.DatumType
== item
.TokenCName
:
372 struct_pcd
.copy(item
)
373 struct_pcd
.TokenValue
= struct_pcd
.TokenValue
.strip("{").strip()
374 struct_pcd
.TokenSpaceGuidCName
, struct_pcd
.TokenCName
= pcdname
.split(".")
375 struct_pcd
.PcdDefineLineNo
= LineNo
376 struct_pcd
.PkgPath
= self
.MetaFile
.File
377 struct_pcd
.SetDecDefaultValue(item
.DefaultValue
)
379 struct_pcd
.AddDefaultValue(item
.TokenCName
, item
.DefaultValue
, self
.MetaFile
.File
, LineNo
)
381 struct_pcd
.PackageDecs
= dep_pkgs
382 str_pcd_set
.append(struct_pcd
)
385 ## Retrieve PCD declarations for given type
386 def _GetPcd(self
, Type
):
389 # tdict is a special kind of dict, used for selecting correct
390 # PCD declaration for given ARCH
392 PcdDict
= tdict(True, 3)
393 # for summarizing PCD
395 # find out all PCDs of the 'type'
398 RecordList
= self
._RawData
[Type
, self
._Arch
]
399 for TokenSpaceGuid
, PcdCName
, Setting
, Arch
, PrivateFlag
, Dummy1
, Dummy2
in RecordList
:
400 PcdDict
[Arch
, PcdCName
, TokenSpaceGuid
] = (Setting
, Dummy2
)
401 if not (PcdCName
, TokenSpaceGuid
) in PcdSet
:
402 PcdSet
.append((PcdCName
, TokenSpaceGuid
))
404 for PcdCName
, TokenSpaceGuid
in PcdSet
:
406 # limit the ARCH to self._Arch, if no self._Arch found, tdict
407 # will automatically turn to 'common' ARCH and try again
409 Setting
, LineNo
= PcdDict
[self
._Arch
, PcdCName
, TokenSpaceGuid
]
413 DefaultValue
, DatumType
, TokenNumber
= AnalyzePcdData(Setting
)
414 validateranges
, validlists
, expressions
= self
._RawData
.GetValidExpression(TokenSpaceGuid
, PcdCName
)
415 PcdObj
= PcdClassObject(
418 self
._PCD
_TYPE
_STRING
_[Type
],
426 list(validateranges
),
430 PcdObj
.DefinitionPosition
= (self
.MetaFile
.File
, LineNo
)
431 if "." in TokenSpaceGuid
:
432 StrPcdSet
.append((PcdObj
, LineNo
))
434 Pcds
[PcdCName
, TokenSpaceGuid
, self
._PCD
_TYPE
_STRING
_[Type
]] = PcdObj
436 StructurePcds
= self
.ProcessStructurePcd(StrPcdSet
)
437 for pcd
in StructurePcds
:
438 Pcds
[pcd
.TokenCName
, pcd
.TokenSpaceGuidCName
, self
._PCD
_TYPE
_STRING
_[Type
]] = pcd
439 StructPattern
= re
.compile(r
'[_a-zA-Z][0-9A-Za-z_]*$')
440 for pcd
in Pcds
.values():
441 if pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
442 if StructPattern
.match(pcd
.DatumType
) is None:
443 EdkLogger
.error('build', FORMAT_INVALID
, "DatumType only support BOOLEAN, UINT8, UINT16, UINT32, UINT64, VOID* or a valid struct name.", pcd
.DefinitionPosition
[0], pcd
.DefinitionPosition
[1])
444 for struct_pcd
in Pcds
.values():
445 if isinstance(struct_pcd
, StructurePcd
) and not struct_pcd
.StructuredPcdIncludeFile
:
446 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
, struct_pcd
.DefinitionPosition
[0], struct_pcd
.DefinitionPosition
[1] ))
450 def CommonIncludes(self
):
451 if self
._CommonIncludes
is None:
453 return self
._CommonIncludes
456 _Macros
= property(_GetMacros
)
457 Arch
= property(_GetArch
)
458 PackageName
= property(_GetPackageName
)
459 Guid
= property(_GetFileGuid
)
460 Version
= property(_GetVersion
)
462 Protocols
= property(_GetProtocol
)
463 Ppis
= property(_GetPpi
)
464 Guids
= property(_GetGuid
)
465 Includes
= property(_GetInclude
)
466 LibraryClasses
= property(_GetLibraryClass
)
467 Pcds
= property(_GetPcds
)