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
.String
import *
15 from Common
.DataType
import *
16 from Common
.Misc
import *
19 from Workspace
.BuildClassObject
import PackageBuildClassObject
, StructurePcd
, PcdClassObject
21 ## Platform build information from DEC file
23 # This class is used to retrieve information stored in database and convert them
24 # into PackageBuildClassObject form for easier use for AutoGen.
26 class DecBuildData(PackageBuildClassObject
):
27 # dict used to convert PCD type in database to string used by build tool
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",
42 # dict used to convert part of [Defines] to members of DecBuildData directly
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",
54 ## Constructor of DecBuildData
56 # Initialize object of DecBuildData
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
65 def __init__(self
, File
, RawData
, BuildDataBase
, Arch
='COMMON', Target
=None, Toolchain
=None):
67 self
._PackageDir
= File
.Dir
68 self
._RawData
= RawData
69 self
._Bdb
= BuildDataBase
72 self
._Toolchain
= Toolchain
76 def __setitem__(self
, key
, value
):
77 self
.__dict
__[self
._PROPERTY
_[key
]] = value
80 def __getitem__(self
, key
):
81 return self
.__dict
__[self
._PROPERTY
_[key
]]
84 def __contains__(self
, key
):
85 return key
in self
._PROPERTY
_
87 ## Set all internal used members of DecBuildData to None
90 self
._PackageName
= None
93 self
._PkgUniFile
= None
94 self
._Protocols
= None
98 self
._CommonIncludes
= None
99 self
._LibraryClasses
= None
102 self
._PrivateProtocols
= None
103 self
._PrivatePpis
= None
104 self
._PrivateGuids
= None
105 self
._PrivateIncludes
= None
107 ## Get current effective macros
108 def _GetMacros(self
):
109 if self
.__Macros
== None:
111 self
.__Macros
.update(GlobalData
.gGlobalDefines
)
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.
125 # @param Value The value of ARCH
127 def _SetArch(self
, Value
):
128 if self
._Arch
== Value
:
133 ## Retrieve all information in [Defines] section
135 # (Retriving all [Defines] information in one-shot is just to save time.)
137 def _GetHeaderInfo(self
):
138 RecordList
= self
._RawData
[MODEL_META_DATA_HEADER
, self
._Arch
]
139 for Record
in RecordList
:
142 self
[Name
] = Record
[2]
143 self
._Header
= 'DUMMY'
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
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
)
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:
172 ## Retrieve protocol definitions (name/value pairs)
173 def _GetProtocol(self
):
174 if self
._Protocols
== None:
176 # tdict is a special kind of dict, used for selecting correct
177 # protocol defition for given ARCH
179 ProtocolDict
= tdict(True)
180 PrivateProtocolDict
= tdict(True)
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
)
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
:
206 # limit the ARCH to self._Arch, if no self._Arch found, tdict
207 # will automatically turn to 'common' ARCH for trying
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
214 ## Retrieve PPI definitions (name/value pairs)
216 if self
._Ppis
== None:
218 # tdict is a special kind of dict, used for selecting correct
219 # PPI defition for given ARCH
221 PpiDict
= tdict(True)
222 PrivatePpiDict
= tdict(True)
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
)
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
245 self
._PrivatePpis
= sdict()
246 for Name
in NameList
:
248 # limit the ARCH to self._Arch, if no self._Arch found, tdict
249 # will automatically turn to 'common' ARCH for trying
251 self
._Ppis
[Name
] = PpiDict
[self
._Arch
, Name
]
252 for Name
in PrivateNameList
:
253 self
._PrivatePpis
[Name
] = PrivatePpiDict
[self
._Arch
, Name
]
256 ## Retrieve GUID definitions (name/value pairs)
258 if self
._Guids
== None:
260 # tdict is a special kind of dict, used for selecting correct
261 # GUID defition for given ARCH
263 GuidDict
= tdict(True)
264 PrivateGuidDict
= tdict(True)
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
)
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
:
290 # limit the ARCH to self._Arch, if no self._Arch found, tdict
291 # will automatically turn to 'common' ARCH for trying
293 self
._Guids
[Name
] = GuidDict
[self
._Arch
, Name
]
294 for Name
in PrivateNameList
:
295 self
._PrivateGuids
[Name
] = PrivateGuidDict
[self
._Arch
, Name
]
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
= []
303 self
._PrivateIncludes
= []
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
)
312 ErrorCode
, ErrorInfo
= File
.Validate()
314 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
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
)
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
333 ## Retrieve library class declarations (not used in build at present)
334 def _GetLibraryClass(self
):
335 if self
._LibraryClasses
== None:
337 # tdict is a special kind of dict, used for selecting correct
338 # library class declaration for given ARCH
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()
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
357 ## Retrieve PCD declarations
359 if self
._Pcds
== None:
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
))
369 def ProcessStructurePcd(self
, StructurePcdRawDataSet
):
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
))
377 for pcdname
in s_pcd_set
:
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
)
393 struct_pcd
.AddDefaultValue(item
.TokenCName
, item
.DefaultValue
,self
.MetaFile
.File
,LineNo
)
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
))
399 str_pcd_set
.append(struct_pcd
)
403 ## Retrieve PCD declarations for given type
404 def _GetPcd(self
, Type
):
407 # tdict is a special kind of dict, used for selecting correct
408 # PCD declaration for given ARCH
410 PcdDict
= tdict(True, 3)
411 # for summarizing PCD
413 # find out all PCDs of the 'type'
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
))
422 for PcdCName
, TokenSpaceGuid
in PcdSet
:
424 # limit the ARCH to self._Arch, if no self._Arch found, tdict
425 # will automatically turn to 'common' ARCH and try again
427 Setting
,LineNo
= PcdDict
[self
._Arch
, PcdCName
, TokenSpaceGuid
]
431 DefaultValue
, DatumType
, TokenNumber
= AnalyzePcdData(Setting
)
432 validateranges
, validlists
, expressions
= self
._RawData
.GetValidExpression(TokenSpaceGuid
, PcdCName
)
433 PcdObj
= PcdClassObject(
436 self
._PCD
_TYPE
_STRING
_[Type
],
444 list(validateranges
),
448 if "." in TokenSpaceGuid
:
449 StrPcdSet
.append((PcdObj
,LineNo
))
451 Pcds
[PcdCName
, TokenSpaceGuid
, self
._PCD
_TYPE
_STRING
_[Type
]] = PcdObj
453 StructurePcds
= self
.ProcessStructurePcd(StrPcdSet
)
454 for pcd
in StructurePcds
:
455 Pcds
[pcd
.TokenCName
, pcd
.TokenSpaceGuidCName
, self
._PCD
_TYPE
_STRING
_[Type
]] = pcd
459 def CommonIncludes(self
):
460 if self
._CommonIncludes
is None:
462 return self
._CommonIncludes
465 _Macros
= property(_GetMacros
)
466 Arch
= property(_GetArch
, _SetArch
)
467 PackageName
= property(_GetPackageName
)
468 Guid
= property(_GetFileGuid
)
469 Version
= property(_GetVersion
)
471 Protocols
= property(_GetProtocol
)
472 Ppis
= property(_GetPpi
)
473 Guids
= property(_GetGuid
)
474 Includes
= property(_GetInclude
)
475 LibraryClasses
= property(_GetLibraryClass
)
476 Pcds
= property(_GetPcds
)