]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/PlatformAutoGen.py
BaseTools: Fixed issue of incorrect Module Unique Name
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / PlatformAutoGen.py
1 ## @file
2 # Create makefile for MS nmake and GNU make
3 #
4 # Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
5 # SPDX-License-Identifier: BSD-2-Clause-Patent
6 #
7
8 ## Import Modules
9 #
10 from __future__ import print_function
11 from __future__ import absolute_import
12 import os.path as path
13 import copy
14 from collections import defaultdict
15
16 from .BuildEngine import BuildRule,gDefaultBuildRuleFile,AutoGenReqBuildRuleVerNum
17 from .GenVar import VariableMgr, var_info
18 from . import GenMake
19 from AutoGen.DataPipe import MemoryDataPipe
20 from AutoGen.ModuleAutoGen import ModuleAutoGen
21 from AutoGen.AutoGen import AutoGen
22 from AutoGen.AutoGen import CalculatePriorityValue
23 from Workspace.WorkspaceCommon import GetModuleLibInstances
24 from CommonDataClass.CommonClass import SkuInfoClass
25 from Common.caching import cached_class_function
26 from Common.Expression import ValueExpressionEx
27 from Common.StringUtils import StringToArray,NormPath
28 from Common.BuildToolError import *
29 from Common.DataType import *
30 from Common.Misc import *
31 import Common.VpdInfoFile as VpdInfoFile
32
33 ## Split command line option string to list
34 #
35 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
36 # in non-windows platform to launch command
37 #
38 def _SplitOption(OptionString):
39 OptionList = []
40 LastChar = " "
41 OptionStart = 0
42 QuotationMark = ""
43 for Index in range(0, len(OptionString)):
44 CurrentChar = OptionString[Index]
45 if CurrentChar in ['"', "'"]:
46 if QuotationMark == CurrentChar:
47 QuotationMark = ""
48 elif QuotationMark == "":
49 QuotationMark = CurrentChar
50 continue
51 elif QuotationMark:
52 continue
53
54 if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]:
55 if Index > OptionStart:
56 OptionList.append(OptionString[OptionStart:Index - 1])
57 OptionStart = Index
58 LastChar = CurrentChar
59 OptionList.append(OptionString[OptionStart:])
60 return OptionList
61
62 ## AutoGen class for platform
63 #
64 # PlatformAutoGen class will process the original information in platform
65 # file in order to generate makefile for platform.
66 #
67 class PlatformAutoGen(AutoGen):
68 # call super().__init__ then call the worker function with different parameter count
69 def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
70 if not hasattr(self, "_Init"):
71 self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch)
72 self._Init = True
73 #
74 # Used to store all PCDs for both PEI and DXE phase, in order to generate
75 # correct PCD database
76 #
77 _DynaPcdList_ = []
78 _NonDynaPcdList_ = []
79 _PlatformPcds = {}
80
81
82
83 ## Initialize PlatformAutoGen
84 #
85 #
86 # @param Workspace WorkspaceAutoGen object
87 # @param PlatformFile Platform file (DSC file)
88 # @param Target Build target (DEBUG, RELEASE)
89 # @param Toolchain Name of tool chain
90 # @param Arch arch of the platform supports
91 #
92 def _InitWorker(self, Workspace, PlatformFile, Target, Toolchain, Arch):
93 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))
94 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)
95
96 self.MetaFile = PlatformFile
97 self.Workspace = Workspace
98 self.WorkspaceDir = Workspace.WorkspaceDir
99 self.ToolChain = Toolchain
100 self.BuildTarget = Target
101 self.Arch = Arch
102 self.SourceDir = PlatformFile.SubDir
103 self.FdTargetList = self.Workspace.FdTargetList
104 self.FvTargetList = self.Workspace.FvTargetList
105 # get the original module/package/platform objects
106 self.BuildDatabase = Workspace.BuildDatabase
107 self.DscBuildDataObj = Workspace.Platform
108
109 # flag indicating if the makefile/C-code file has been created or not
110 self.IsMakeFileCreated = False
111
112 self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
113 self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
114
115 self._AsBuildInfList = []
116 self._AsBuildModuleList = []
117
118 self.VariableInfo = None
119
120 if GlobalData.gFdfParser is not None:
121 self._AsBuildInfList = GlobalData.gFdfParser.Profile.InfList
122 for Inf in self._AsBuildInfList:
123 InfClass = PathClass(NormPath(Inf), GlobalData.gWorkspace, self.Arch)
124 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]
125 if not M.IsBinaryModule:
126 continue
127 self._AsBuildModuleList.append(InfClass)
128 # get library/modules for build
129 self.LibraryBuildDirectoryList = []
130 self.ModuleBuildDirectoryList = []
131
132 self.DataPipe = MemoryDataPipe(self.BuildDir)
133 self.DataPipe.FillData(self)
134
135 return True
136 def FillData_LibConstPcd(self):
137 libConstPcd = {}
138 for LibAuto in self.LibraryAutoGenList:
139 if LibAuto.ConstPcd:
140 libConstPcd[(LibAuto.MetaFile.File,LibAuto.MetaFile.Root,LibAuto.Arch,LibAuto.MetaFile.Path)] = LibAuto.ConstPcd
141 self.DataPipe.DataContainer = {"LibConstPcd":libConstPcd}
142 ## hash() operator of PlatformAutoGen
143 #
144 # The platform file path and arch string will be used to represent
145 # hash value of this object
146 #
147 # @retval int Hash value of the platform file path and arch
148 #
149 @cached_class_function
150 def __hash__(self):
151 return hash((self.MetaFile, self.Arch))
152 @cached_class_function
153 def __repr__(self):
154 return "%s [%s]" % (self.MetaFile, self.Arch)
155
156 ## Create autogen code for platform and modules
157 #
158 # Since there's no autogen code for platform, this method will do nothing
159 # if CreateModuleCodeFile is set to False.
160 #
161 # @param CreateModuleCodeFile Flag indicating if creating module's
162 # autogen code file or not
163 #
164 @cached_class_function
165 def CreateCodeFile(self, CreateModuleCodeFile=False):
166 # only module has code to be created, so do nothing if CreateModuleCodeFile is False
167 if not CreateModuleCodeFile:
168 return
169
170 for Ma in self.ModuleAutoGenList:
171 Ma.CreateCodeFile(CreateModuleCodeFile)
172
173 ## Generate Fds Command
174 @cached_property
175 def GenFdsCommand(self):
176 return self.Workspace.GenFdsCommand
177
178 ## Create makefile for the platform and modules in it
179 #
180 # @param CreateModuleMakeFile Flag indicating if the makefile for
181 # modules will be created as well
182 #
183 def CreateMakeFile(self, CreateModuleMakeFile=False, FfsCommand = {}):
184 if CreateModuleMakeFile:
185 for Ma in self._MaList:
186 key = (Ma.MetaFile.File, self.Arch)
187 if key in FfsCommand:
188 Ma.CreateMakeFile(CreateModuleMakeFile, FfsCommand[key])
189 else:
190 Ma.CreateMakeFile(CreateModuleMakeFile)
191
192 # no need to create makefile for the platform more than once
193 if self.IsMakeFileCreated:
194 return
195
196 # create library/module build dirs for platform
197 Makefile = GenMake.PlatformMakefile(self)
198 self.LibraryBuildDirectoryList = Makefile.GetLibraryBuildDirectoryList()
199 self.ModuleBuildDirectoryList = Makefile.GetModuleBuildDirectoryList()
200
201 self.IsMakeFileCreated = True
202
203 @property
204 def AllPcdList(self):
205 return self.DynamicPcdList + self.NonDynamicPcdList
206 ## Deal with Shared FixedAtBuild Pcds
207 #
208 def CollectFixedAtBuildPcds(self):
209 for LibAuto in self.LibraryAutoGenList:
210 FixedAtBuildPcds = {}
211 ShareFixedAtBuildPcdsSameValue = {}
212 for Module in LibAuto.ReferenceModules:
213 for Pcd in set(Module.FixedAtBuildPcds + LibAuto.FixedAtBuildPcds):
214 DefaultValue = Pcd.DefaultValue
215 # Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib
216 if Pcd in Module.LibraryPcdList:
217 Index = Module.LibraryPcdList.index(Pcd)
218 DefaultValue = Module.LibraryPcdList[Index].DefaultValue
219 key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
220 if key not in FixedAtBuildPcds:
221 ShareFixedAtBuildPcdsSameValue[key] = True
222 FixedAtBuildPcds[key] = DefaultValue
223 else:
224 if FixedAtBuildPcds[key] != DefaultValue:
225 ShareFixedAtBuildPcdsSameValue[key] = False
226 for Pcd in LibAuto.FixedAtBuildPcds:
227 key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
228 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) not in self.NonDynamicPcdDict:
229 continue
230 else:
231 DscPcd = self.NonDynamicPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)]
232 if DscPcd.Type != TAB_PCDS_FIXED_AT_BUILD:
233 continue
234 if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]:
235 LibAuto.ConstPcd[key] = FixedAtBuildPcds[key]
236
237 def CollectVariables(self, DynamicPcdSet):
238 VpdRegionSize = 0
239 VpdRegionBase = 0
240 if self.Workspace.FdfFile:
241 FdDict = self.Workspace.FdfProfile.FdDict[GlobalData.gFdfParser.CurrentFdName]
242 for FdRegion in FdDict.RegionList:
243 for item in FdRegion.RegionDataList:
244 if self.Platform.VpdToolGuid.strip() and self.Platform.VpdToolGuid in item:
245 VpdRegionSize = FdRegion.Size
246 VpdRegionBase = FdRegion.Offset
247 break
248
249 VariableInfo = VariableMgr(self.DscBuildDataObj._GetDefaultStores(), self.DscBuildDataObj.SkuIds)
250 VariableInfo.SetVpdRegionMaxSize(VpdRegionSize)
251 VariableInfo.SetVpdRegionOffset(VpdRegionBase)
252 Index = 0
253 for Pcd in DynamicPcdSet:
254 pcdname = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
255 for SkuName in Pcd.SkuInfoList:
256 Sku = Pcd.SkuInfoList[SkuName]
257 SkuId = Sku.SkuId
258 if SkuId is None or SkuId == '':
259 continue
260 if len(Sku.VariableName) > 0:
261 if Sku.VariableAttribute and 'NV' not in Sku.VariableAttribute:
262 continue
263 VariableGuidStructure = Sku.VariableGuidValue
264 VariableGuid = GuidStructureStringToGuidString(VariableGuidStructure)
265 for StorageName in Sku.DefaultStoreDict:
266 VariableInfo.append_variable(var_info(Index, pcdname, StorageName, SkuName, StringToArray(Sku.VariableName), VariableGuid, Sku.VariableOffset, Sku.VariableAttribute, Sku.HiiDefaultValue, Sku.DefaultStoreDict[StorageName] if Pcd.DatumType in TAB_PCD_NUMERIC_TYPES else StringToArray(Sku.DefaultStoreDict[StorageName]), Pcd.DatumType, Pcd.CustomAttribute['DscPosition'], Pcd.CustomAttribute.get('IsStru',False)))
267 Index += 1
268 return VariableInfo
269
270 def UpdateNVStoreMaxSize(self, OrgVpdFile):
271 if self.VariableInfo:
272 VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)
273 PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]
274
275 if PcdNvStoreDfBuffer:
276 if os.path.exists(VpdMapFilePath):
277 OrgVpdFile.Read(VpdMapFilePath)
278 PcdItems = OrgVpdFile.GetOffset(PcdNvStoreDfBuffer[0])
279 NvStoreOffset = list(PcdItems.values())[0].strip() if PcdItems else '0'
280 else:
281 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)
282
283 NvStoreOffset = int(NvStoreOffset, 16) if NvStoreOffset.upper().startswith("0X") else int(NvStoreOffset)
284 default_skuobj = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT)
285 maxsize = self.VariableInfo.VpdRegionSize - NvStoreOffset if self.VariableInfo.VpdRegionSize else len(default_skuobj.DefaultValue.split(","))
286 var_data = self.VariableInfo.PatchNVStoreDefaultMaxSize(maxsize)
287
288 if var_data and default_skuobj:
289 default_skuobj.DefaultValue = var_data
290 PcdNvStoreDfBuffer[0].DefaultValue = var_data
291 PcdNvStoreDfBuffer[0].SkuInfoList.clear()
292 PcdNvStoreDfBuffer[0].SkuInfoList[TAB_DEFAULT] = default_skuobj
293 PcdNvStoreDfBuffer[0].MaxDatumSize = str(len(default_skuobj.DefaultValue.split(",")))
294
295 return OrgVpdFile
296
297 ## Collect dynamic PCDs
298 #
299 # Gather dynamic PCDs list from each module and their settings from platform
300 # This interface should be invoked explicitly when platform action is created.
301 #
302 def CollectPlatformDynamicPcds(self):
303 self.CategoryPcds()
304 self.SortDynamicPcd()
305
306 def CategoryPcds(self):
307 # Category Pcds into DynamicPcds and NonDynamicPcds
308 # for gathering error information
309 NoDatumTypePcdList = set()
310 FdfModuleList = []
311 for InfName in self._AsBuildInfList:
312 InfName = mws.join(self.WorkspaceDir, InfName)
313 FdfModuleList.append(os.path.normpath(InfName))
314 for M in self._MbList:
315 # F is the Module for which M is the module autogen
316 ModPcdList = self.ApplyPcdSetting(M, M.ModulePcdList)
317 LibPcdList = []
318 for lib in M.LibraryPcdList:
319 LibPcdList.extend(self.ApplyPcdSetting(M, M.LibraryPcdList[lib], lib))
320 for PcdFromModule in ModPcdList + LibPcdList:
321
322 # make sure that the "VOID*" kind of datum has MaxDatumSize set
323 if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:
324 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, M.MetaFile))
325
326 # Check the PCD from Binary INF or Source INF
327 if M.IsBinaryModule == True:
328 PcdFromModule.IsFromBinaryInf = True
329
330 # Check the PCD from DSC or not
331 PcdFromModule.IsFromDsc = (PcdFromModule.TokenCName, PcdFromModule.TokenSpaceGuidCName) in self.Platform.Pcds
332
333 if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET or PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
334 if M.MetaFile.Path not in FdfModuleList:
335 # If one of the Source built modules listed in the DSC is not listed
336 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
337 # access method (it is only listed in the DEC file that declares the
338 # PCD as PcdsDynamic), then build tool will report warning message
339 # notify the PI that they are attempting to build a module that must
340 # be included in a flash image in order to be functional. These Dynamic
341 # PCD will not be added into the Database unless it is used by other
342 # modules that are included in the FDF file.
343 if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET and \
344 PcdFromModule.IsFromBinaryInf == False:
345 # Print warning message to let the developer make a determine.
346 continue
347 # If one of the Source built modules listed in the DSC is not listed in
348 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
349 # access method (it is only listed in the DEC file that declares the
350 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
351 # PCD to the Platform's PCD Database.
352 if PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
353 continue
354 #
355 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
356 # it should be stored in Pcd PEI database, If a dynamic only
357 # used by DXE module, it should be stored in DXE PCD database.
358 # The default Phase is DXE
359 #
360 if M.ModuleType in SUP_MODULE_SET_PEI:
361 PcdFromModule.Phase = "PEI"
362 if PcdFromModule not in self._DynaPcdList_:
363 self._DynaPcdList_.append(PcdFromModule)
364 elif PcdFromModule.Phase == 'PEI':
365 # overwrite any the same PCD existing, if Phase is PEI
366 Index = self._DynaPcdList_.index(PcdFromModule)
367 self._DynaPcdList_[Index] = PcdFromModule
368 elif PcdFromModule not in self._NonDynaPcdList_:
369 self._NonDynaPcdList_.append(PcdFromModule)
370 elif PcdFromModule in self._NonDynaPcdList_ and PcdFromModule.IsFromBinaryInf == True:
371 Index = self._NonDynaPcdList_.index(PcdFromModule)
372 if self._NonDynaPcdList_[Index].IsFromBinaryInf == False:
373 #The PCD from Binary INF will override the same one from source INF
374 self._NonDynaPcdList_.remove (self._NonDynaPcdList_[Index])
375 PcdFromModule.Pending = False
376 self._NonDynaPcdList_.append (PcdFromModule)
377 DscModuleSet = {os.path.normpath(ModuleInf.Path) for ModuleInf in self.Platform.Modules}
378 # add the PCD from modules that listed in FDF but not in DSC to Database
379 for InfName in FdfModuleList:
380 if InfName not in DscModuleSet:
381 InfClass = PathClass(InfName)
382 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]
383 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
384 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
385 # For binary module, if in current arch, we need to list the PCDs into database.
386 if not M.IsBinaryModule:
387 continue
388 # Override the module PCD setting by platform setting
389 ModulePcdList = self.ApplyPcdSetting(M, M.Pcds)
390 for PcdFromModule in ModulePcdList:
391 PcdFromModule.IsFromBinaryInf = True
392 PcdFromModule.IsFromDsc = False
393 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
394 if PcdFromModule.Type not in PCD_DYNAMIC_EX_TYPE_SET and PcdFromModule.Type not in TAB_PCDS_PATCHABLE_IN_MODULE:
395 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
396 File=self.MetaFile,
397 ExtraData="\n\tExisted %s PCD %s in:\n\t\t%s\n"
398 % (PcdFromModule.Type, PcdFromModule.TokenCName, InfName))
399 # make sure that the "VOID*" kind of datum has MaxDatumSize set
400 if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:
401 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, InfName))
402 if M.ModuleType in SUP_MODULE_SET_PEI:
403 PcdFromModule.Phase = "PEI"
404 if PcdFromModule not in self._DynaPcdList_ and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
405 self._DynaPcdList_.append(PcdFromModule)
406 elif PcdFromModule not in self._NonDynaPcdList_ and PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE:
407 self._NonDynaPcdList_.append(PcdFromModule)
408 if PcdFromModule in self._DynaPcdList_ and PcdFromModule.Phase == 'PEI' and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
409 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
410 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
411 # module & DXE module at a same time.
412 # Overwrite the type of the PCDs in source INF by the type of AsBuild
413 # INF file as DynamicEx.
414 Index = self._DynaPcdList_.index(PcdFromModule)
415 self._DynaPcdList_[Index].Phase = PcdFromModule.Phase
416 self._DynaPcdList_[Index].Type = PcdFromModule.Type
417 for PcdFromModule in self._NonDynaPcdList_:
418 # If a PCD is not listed in the DSC file, but binary INF files used by
419 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
420 # section, AND all source INF files used by this platform the build
421 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
422 # section, then the tools must NOT add the PCD to the Platform's PCD
423 # Database; the build must assign the access method for this PCD as
424 # PcdsPatchableInModule.
425 if PcdFromModule not in self._DynaPcdList_:
426 continue
427 Index = self._DynaPcdList_.index(PcdFromModule)
428 if PcdFromModule.IsFromDsc == False and \
429 PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE and \
430 PcdFromModule.IsFromBinaryInf == True and \
431 self._DynaPcdList_[Index].IsFromBinaryInf == False:
432 Index = self._DynaPcdList_.index(PcdFromModule)
433 self._DynaPcdList_.remove (self._DynaPcdList_[Index])
434
435 # print out error information and break the build, if error found
436 if len(NoDatumTypePcdList) > 0:
437 NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)
438 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
439 File=self.MetaFile,
440 ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
441 % NoDatumTypePcdListString)
442 self._NonDynamicPcdList = self._NonDynaPcdList_
443 self._DynamicPcdList = self._DynaPcdList_
444
445 def SortDynamicPcd(self):
446 #
447 # Sort dynamic PCD list to:
448 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
449 # try to be put header of dynamicd List
450 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
451 #
452 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
453 #
454 UnicodePcdArray = set()
455 HiiPcdArray = set()
456 OtherPcdArray = set()
457 VpdPcdDict = {}
458 VpdFile = VpdInfoFile.VpdInfoFile()
459 NeedProcessVpdMapFile = False
460
461 for pcd in self.Platform.Pcds:
462 if pcd not in self._PlatformPcds:
463 self._PlatformPcds[pcd] = self.Platform.Pcds[pcd]
464
465 for item in self._PlatformPcds:
466 if self._PlatformPcds[item].DatumType and self._PlatformPcds[item].DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
467 self._PlatformPcds[item].DatumType = TAB_VOID
468
469 if (self.Workspace.ArchList[-1] == self.Arch):
470 for Pcd in self._DynamicPcdList:
471 # just pick the a value to determine whether is unicode string type
472 Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)
473 Sku.VpdOffset = Sku.VpdOffset.strip()
474
475 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
476 Pcd.DatumType = TAB_VOID
477
478 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
479 # if found HII type PCD then insert to right of UnicodeIndex
480 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
481 VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd
482
483 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
484 PcdNvStoreDfBuffer = VpdPcdDict.get(("PcdNvStoreDefaultValueBuffer", "gEfiMdeModulePkgTokenSpaceGuid"))
485 if PcdNvStoreDfBuffer:
486 self.VariableInfo = self.CollectVariables(self._DynamicPcdList)
487 vardump = self.VariableInfo.dump()
488 if vardump:
489 #
490 #According to PCD_DATABASE_INIT in edk2\MdeModulePkg\Include\Guid\PcdDataBaseSignatureGuid.h,
491 #the max size for string PCD should not exceed USHRT_MAX 65535(0xffff).
492 #typedef UINT16 SIZE_INFO;
493 #//SIZE_INFO SizeTable[];
494 if len(vardump.split(",")) > 0xffff:
495 EdkLogger.error("build", RESOURCE_OVERFLOW, 'The current length of PCD %s value is %d, it exceeds to the max size of String PCD.' %(".".join([PcdNvStoreDfBuffer.TokenSpaceGuidCName,PcdNvStoreDfBuffer.TokenCName]) ,len(vardump.split(","))))
496 PcdNvStoreDfBuffer.DefaultValue = vardump
497 for skuname in PcdNvStoreDfBuffer.SkuInfoList:
498 PcdNvStoreDfBuffer.SkuInfoList[skuname].DefaultValue = vardump
499 PcdNvStoreDfBuffer.MaxDatumSize = str(len(vardump.split(",")))
500 else:
501 #If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd
502 if [Pcd for Pcd in self._DynamicPcdList if Pcd.UserDefinedDefaultStoresFlag]:
503 EdkLogger.warn("build", "PcdNvStoreDefaultValueBuffer should be defined as PcdsDynamicExVpd in dsc file since the DefaultStores is enabled for this platform.\n%s" %self.Platform.MetaFile.Path)
504 PlatformPcds = sorted(self._PlatformPcds.keys())
505 #
506 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
507 #
508 VpdSkuMap = {}
509 for PcdKey in PlatformPcds:
510 Pcd = self._PlatformPcds[PcdKey]
511 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD] and \
512 PcdKey in VpdPcdDict:
513 Pcd = VpdPcdDict[PcdKey]
514 SkuValueMap = {}
515 DefaultSku = Pcd.SkuInfoList.get(TAB_DEFAULT)
516 if DefaultSku:
517 PcdValue = DefaultSku.DefaultValue
518 if PcdValue not in SkuValueMap:
519 SkuValueMap[PcdValue] = []
520 VpdFile.Add(Pcd, TAB_DEFAULT, DefaultSku.VpdOffset)
521 SkuValueMap[PcdValue].append(DefaultSku)
522
523 for (SkuName, Sku) in Pcd.SkuInfoList.items():
524 Sku.VpdOffset = Sku.VpdOffset.strip()
525 PcdValue = Sku.DefaultValue
526 if PcdValue == "":
527 PcdValue = Pcd.DefaultValue
528 if Sku.VpdOffset != TAB_STAR:
529 if PcdValue.startswith("{"):
530 Alignment = 8
531 elif PcdValue.startswith("L"):
532 Alignment = 2
533 else:
534 Alignment = 1
535 try:
536 VpdOffset = int(Sku.VpdOffset)
537 except:
538 try:
539 VpdOffset = int(Sku.VpdOffset, 16)
540 except:
541 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
542 if VpdOffset % Alignment != 0:
543 if PcdValue.startswith("{"):
544 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName), File=self.MetaFile)
545 else:
546 EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Alignment))
547 if PcdValue not in SkuValueMap:
548 SkuValueMap[PcdValue] = []
549 VpdFile.Add(Pcd, SkuName, Sku.VpdOffset)
550 SkuValueMap[PcdValue].append(Sku)
551 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
552 if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:
553 NeedProcessVpdMapFile = True
554 if self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == '':
555 EdkLogger.error("Build", FILE_NOT_FOUND, \
556 "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")
557
558 VpdSkuMap[PcdKey] = SkuValueMap
559 #
560 # Fix the PCDs define in VPD PCD section that never referenced by module.
561 # An example is PCD for signature usage.
562 #
563 for DscPcd in PlatformPcds:
564 DscPcdEntry = self._PlatformPcds[DscPcd]
565 if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
566 if not (self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == ''):
567 FoundFlag = False
568 for VpdPcd in VpdFile._VpdArray:
569 # This PCD has been referenced by module
570 if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
571 (VpdPcd.TokenCName == DscPcdEntry.TokenCName):
572 FoundFlag = True
573
574 # Not found, it should be signature
575 if not FoundFlag :
576 # just pick the a value to determine whether is unicode string type
577 SkuValueMap = {}
578 SkuObjList = list(DscPcdEntry.SkuInfoList.items())
579 DefaultSku = DscPcdEntry.SkuInfoList.get(TAB_DEFAULT)
580 if DefaultSku:
581 defaultindex = SkuObjList.index((TAB_DEFAULT, DefaultSku))
582 SkuObjList[0], SkuObjList[defaultindex] = SkuObjList[defaultindex], SkuObjList[0]
583 for (SkuName, Sku) in SkuObjList:
584 Sku.VpdOffset = Sku.VpdOffset.strip()
585
586 # Need to iterate DEC pcd information to get the value & datumtype
587 for eachDec in self.PackageList:
588 for DecPcd in eachDec.Pcds:
589 DecPcdEntry = eachDec.Pcds[DecPcd]
590 if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
591 (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):
592 # Print warning message to let the developer make a determine.
593 EdkLogger.warn("build", "Unreferenced vpd pcd used!",
594 File=self.MetaFile, \
595 ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \
596 %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path))
597
598 DscPcdEntry.DatumType = DecPcdEntry.DatumType
599 DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue
600 DscPcdEntry.TokenValue = DecPcdEntry.TokenValue
601 DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName]
602 # Only fix the value while no value provided in DSC file.
603 if not Sku.DefaultValue:
604 DscPcdEntry.SkuInfoList[list(DscPcdEntry.SkuInfoList.keys())[0]].DefaultValue = DecPcdEntry.DefaultValue
605
606 if DscPcdEntry not in self._DynamicPcdList:
607 self._DynamicPcdList.append(DscPcdEntry)
608 Sku.VpdOffset = Sku.VpdOffset.strip()
609 PcdValue = Sku.DefaultValue
610 if PcdValue == "":
611 PcdValue = DscPcdEntry.DefaultValue
612 if Sku.VpdOffset != TAB_STAR:
613 if PcdValue.startswith("{"):
614 Alignment = 8
615 elif PcdValue.startswith("L"):
616 Alignment = 2
617 else:
618 Alignment = 1
619 try:
620 VpdOffset = int(Sku.VpdOffset)
621 except:
622 try:
623 VpdOffset = int(Sku.VpdOffset, 16)
624 except:
625 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName))
626 if VpdOffset % Alignment != 0:
627 if PcdValue.startswith("{"):
628 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName), File=self.MetaFile)
629 else:
630 EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, Alignment))
631 if PcdValue not in SkuValueMap:
632 SkuValueMap[PcdValue] = []
633 VpdFile.Add(DscPcdEntry, SkuName, Sku.VpdOffset)
634 SkuValueMap[PcdValue].append(Sku)
635 if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:
636 NeedProcessVpdMapFile = True
637 if DscPcdEntry.DatumType == TAB_VOID and PcdValue.startswith("L"):
638 UnicodePcdArray.add(DscPcdEntry)
639 elif len(Sku.VariableName) > 0:
640 HiiPcdArray.add(DscPcdEntry)
641 else:
642 OtherPcdArray.add(DscPcdEntry)
643
644 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
645 VpdSkuMap[DscPcd] = SkuValueMap
646 if (self.Platform.FlashDefinition is None or self.Platform.FlashDefinition == '') and \
647 VpdFile.GetCount() != 0:
648 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
649 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))
650
651 if VpdFile.GetCount() != 0:
652
653 self.FixVpdOffset(VpdFile)
654
655 self.FixVpdOffset(self.UpdateNVStoreMaxSize(VpdFile))
656 PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]
657 if PcdNvStoreDfBuffer:
658 PcdName,PcdGuid = PcdNvStoreDfBuffer[0].TokenCName, PcdNvStoreDfBuffer[0].TokenSpaceGuidCName
659 if (PcdName,PcdGuid) in VpdSkuMap:
660 DefaultSku = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT)
661 VpdSkuMap[(PcdName,PcdGuid)] = {DefaultSku.DefaultValue:[SkuObj for SkuObj in PcdNvStoreDfBuffer[0].SkuInfoList.values() ]}
662
663 # Process VPD map file generated by third party BPDG tool
664 if NeedProcessVpdMapFile:
665 VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)
666 if os.path.exists(VpdMapFilePath):
667 VpdFile.Read(VpdMapFilePath)
668
669 # Fixup TAB_STAR offset
670 for pcd in VpdSkuMap:
671 vpdinfo = VpdFile.GetVpdInfo(pcd)
672 if vpdinfo is None:
673 # just pick the a value to determine whether is unicode string type
674 continue
675 for pcdvalue in VpdSkuMap[pcd]:
676 for sku in VpdSkuMap[pcd][pcdvalue]:
677 for item in vpdinfo:
678 if item[2] == pcdvalue:
679 sku.VpdOffset = item[1]
680 else:
681 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)
682
683 # Delete the DynamicPcdList At the last time enter into this function
684 for Pcd in self._DynamicPcdList:
685 # just pick the a value to determine whether is unicode string type
686 Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)
687 Sku.VpdOffset = Sku.VpdOffset.strip()
688
689 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
690 Pcd.DatumType = TAB_VOID
691
692 PcdValue = Sku.DefaultValue
693 if Pcd.DatumType == TAB_VOID and PcdValue.startswith("L"):
694 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
695 UnicodePcdArray.add(Pcd)
696 elif len(Sku.VariableName) > 0:
697 # if found HII type PCD then insert to right of UnicodeIndex
698 HiiPcdArray.add(Pcd)
699 else:
700 OtherPcdArray.add(Pcd)
701 del self._DynamicPcdList[:]
702 self._DynamicPcdList.extend(list(UnicodePcdArray))
703 self._DynamicPcdList.extend(list(HiiPcdArray))
704 self._DynamicPcdList.extend(list(OtherPcdArray))
705 allskuset = [(SkuName, Sku.SkuId) for pcd in self._DynamicPcdList for (SkuName, Sku) in pcd.SkuInfoList.items()]
706 for pcd in self._DynamicPcdList:
707 if len(pcd.SkuInfoList) == 1:
708 for (SkuName, SkuId) in allskuset:
709 if isinstance(SkuId, str) and eval(SkuId) == 0 or SkuId == 0:
710 continue
711 pcd.SkuInfoList[SkuName] = copy.deepcopy(pcd.SkuInfoList[TAB_DEFAULT])
712 pcd.SkuInfoList[SkuName].SkuId = SkuId
713 pcd.SkuInfoList[SkuName].SkuIdName = SkuName
714
715 def FixVpdOffset(self, VpdFile ):
716 FvPath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY)
717 if not os.path.exists(FvPath):
718 try:
719 os.makedirs(FvPath)
720 except:
721 EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)
722
723 VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)
724
725 if VpdFile.Write(VpdFilePath):
726 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
727 BPDGToolName = None
728 for ToolDef in self.ToolDefinition.values():
729 if TAB_GUID in ToolDef and ToolDef[TAB_GUID] == self.Platform.VpdToolGuid:
730 if "PATH" not in ToolDef:
731 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)
732 BPDGToolName = ToolDef["PATH"]
733 break
734 # Call third party GUID BPDG tool.
735 if BPDGToolName is not None:
736 VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)
737 else:
738 EdkLogger.error("Build", FILE_NOT_FOUND, "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")
739
740 ## Return the platform build data object
741 @cached_property
742 def Platform(self):
743 return self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
744
745 ## Return platform name
746 @cached_property
747 def Name(self):
748 return self.Platform.PlatformName
749
750 ## Return the meta file GUID
751 @cached_property
752 def Guid(self):
753 return self.Platform.Guid
754
755 ## Return the platform version
756 @cached_property
757 def Version(self):
758 return self.Platform.Version
759
760 ## Return the FDF file name
761 @cached_property
762 def FdfFile(self):
763 if self.Workspace.FdfFile:
764 RetVal= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)
765 else:
766 RetVal = ''
767 return RetVal
768
769 ## Return the build output directory platform specifies
770 @cached_property
771 def OutputDir(self):
772 return self.Platform.OutputDirectory
773
774 ## Return the directory to store all intermediate and final files built
775 @cached_property
776 def BuildDir(self):
777 if os.path.isabs(self.OutputDir):
778 GlobalData.gBuildDirectory = RetVal = path.join(
779 path.abspath(self.OutputDir),
780 self.BuildTarget + "_" + self.ToolChain,
781 )
782 else:
783 GlobalData.gBuildDirectory = RetVal = path.join(
784 self.WorkspaceDir,
785 self.OutputDir,
786 self.BuildTarget + "_" + self.ToolChain,
787 )
788 return RetVal
789
790 ## Return directory of platform makefile
791 #
792 # @retval string Makefile directory
793 #
794 @cached_property
795 def MakeFileDir(self):
796 return path.join(self.BuildDir, self.Arch)
797
798 ## Return build command string
799 #
800 # @retval string Build command string
801 #
802 @cached_property
803 def BuildCommand(self):
804 RetVal = []
805 if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
806 RetVal += _SplitOption(self.ToolDefinition["MAKE"]["PATH"])
807 if "FLAGS" in self.ToolDefinition["MAKE"]:
808 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
809 if NewOption != '':
810 RetVal += _SplitOption(NewOption)
811 if "MAKE" in self.EdkIIBuildOption:
812 if "FLAGS" in self.EdkIIBuildOption["MAKE"]:
813 Flags = self.EdkIIBuildOption["MAKE"]["FLAGS"]
814 if Flags.startswith('='):
815 RetVal = [RetVal[0]] + [Flags[1:]]
816 else:
817 RetVal.append(Flags)
818 return RetVal
819
820 ## Get tool chain definition
821 #
822 # Get each tool definition for given tool chain from tools_def.txt and platform
823 #
824 @cached_property
825 def ToolDefinition(self):
826 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
827 if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:
828 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",
829 ExtraData="[%s]" % self.MetaFile)
830 RetVal = OrderedDict()
831 DllPathList = set()
832 for Def in ToolDefinition:
833 Target, Tag, Arch, Tool, Attr = Def.split("_")
834 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:
835 continue
836
837 Value = ToolDefinition[Def]
838 # don't record the DLL
839 if Attr == "DLL":
840 DllPathList.add(Value)
841 continue
842
843 if Tool not in RetVal:
844 RetVal[Tool] = OrderedDict()
845 RetVal[Tool][Attr] = Value
846
847 ToolsDef = ''
848 if GlobalData.gOptions.SilentMode and "MAKE" in RetVal:
849 if "FLAGS" not in RetVal["MAKE"]:
850 RetVal["MAKE"]["FLAGS"] = ""
851 RetVal["MAKE"]["FLAGS"] += " -s"
852 MakeFlags = ''
853 for Tool in RetVal:
854 for Attr in RetVal[Tool]:
855 Value = RetVal[Tool][Attr]
856 if Tool in self._BuildOptionWithToolDef(RetVal) and Attr in self._BuildOptionWithToolDef(RetVal)[Tool]:
857 # check if override is indicated
858 if self._BuildOptionWithToolDef(RetVal)[Tool][Attr].startswith('='):
859 Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr][1:]
860 else:
861 if Attr != 'PATH':
862 Value += " " + self._BuildOptionWithToolDef(RetVal)[Tool][Attr]
863 else:
864 Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr]
865
866 if Attr == "PATH":
867 # Don't put MAKE definition in the file
868 if Tool != "MAKE":
869 ToolsDef += "%s = %s\n" % (Tool, Value)
870 elif Attr != "DLL":
871 # Don't put MAKE definition in the file
872 if Tool == "MAKE":
873 if Attr == "FLAGS":
874 MakeFlags = Value
875 else:
876 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
877 ToolsDef += "\n"
878
879 tool_def_file = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
880 SaveFileOnChange(tool_def_file, ToolsDef, False)
881 for DllPath in DllPathList:
882 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]
883 os.environ["MAKE_FLAGS"] = MakeFlags
884
885 return RetVal
886
887 ## Return the paths of tools
888 @cached_property
889 def ToolDefinitionFile(self):
890 tool_def_file = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
891 if not os.path.exists(tool_def_file):
892 self.ToolDefinition
893 return tool_def_file
894
895 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
896 @cached_property
897 def ToolChainFamily(self):
898 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
899 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
900 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
901 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:
902 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
903 % self.ToolChain)
904 RetVal = TAB_COMPILER_MSFT
905 else:
906 RetVal = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]
907 return RetVal
908
909 @cached_property
910 def BuildRuleFamily(self):
911 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
912 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
913 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \
914 or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:
915 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
916 % self.ToolChain)
917 return TAB_COMPILER_MSFT
918
919 return ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]
920
921 ## Return the build options specific for all modules in this platform
922 @cached_property
923 def BuildOption(self):
924 return self._ExpandBuildOption(self.Platform.BuildOptions)
925
926 def _BuildOptionWithToolDef(self, ToolDef):
927 return self._ExpandBuildOption(self.Platform.BuildOptions, ToolDef=ToolDef)
928
929 ## Return the build options specific for EDK modules in this platform
930 @cached_property
931 def EdkBuildOption(self):
932 return self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)
933
934 ## Return the build options specific for EDKII modules in this platform
935 @cached_property
936 def EdkIIBuildOption(self):
937 return self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)
938
939 ## Parse build_rule.txt in Conf Directory.
940 #
941 # @retval BuildRule object
942 #
943 @cached_property
944 def BuildRule(self):
945 BuildRuleFile = None
946 if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:
947 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
948 if not BuildRuleFile:
949 BuildRuleFile = gDefaultBuildRuleFile
950 RetVal = BuildRule(BuildRuleFile)
951 if RetVal._FileVersion == "":
952 RetVal._FileVersion = AutoGenReqBuildRuleVerNum
953 else:
954 if RetVal._FileVersion < AutoGenReqBuildRuleVerNum :
955 # If Build Rule's version is less than the version number required by the tools, halting the build.
956 EdkLogger.error("build", AUTOGEN_ERROR,
957 ExtraData="The version number [%s] of build_rule.txt is less than the version number required by the AutoGen.(the minimum required version number is [%s])"\
958 % (RetVal._FileVersion, AutoGenReqBuildRuleVerNum))
959 return RetVal
960
961 ## Summarize the packages used by modules in this platform
962 @cached_property
963 def PackageList(self):
964 RetVal = set()
965 for Mb in self._MbList:
966 RetVal.update(Mb.Packages)
967 for lb in Mb.LibInstances:
968 RetVal.update(lb.Packages)
969 #Collect package set information from INF of FDF
970 for ModuleFile in self._AsBuildModuleList:
971 if ModuleFile in self.Platform.Modules:
972 continue
973 ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]
974 RetVal.update(ModuleData.Packages)
975 return list(RetVal)
976
977 @cached_property
978 def NonDynamicPcdDict(self):
979 return {(Pcd.TokenCName, Pcd.TokenSpaceGuidCName):Pcd for Pcd in self.NonDynamicPcdList}
980
981 ## Get list of non-dynamic PCDs
982 @property
983 def NonDynamicPcdList(self):
984 if not self._NonDynamicPcdList:
985 self.CollectPlatformDynamicPcds()
986 return self._NonDynamicPcdList
987
988 ## Get list of dynamic PCDs
989 @property
990 def DynamicPcdList(self):
991 if not self._DynamicPcdList:
992 self.CollectPlatformDynamicPcds()
993 return self._DynamicPcdList
994
995 ## Generate Token Number for all PCD
996 @cached_property
997 def PcdTokenNumber(self):
998 RetVal = OrderedDict()
999 TokenNumber = 1
1000 #
1001 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
1002 # Such as:
1003 #
1004 # Dynamic PCD:
1005 # TokenNumber 0 ~ 10
1006 # DynamicEx PCD:
1007 # TokeNumber 11 ~ 20
1008 #
1009 for Pcd in self.DynamicPcdList:
1010 if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:
1011 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
1012 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1013 TokenNumber += 1
1014
1015 for Pcd in self.DynamicPcdList:
1016 if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
1017 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
1018 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1019 TokenNumber += 1
1020
1021 for Pcd in self.DynamicPcdList:
1022 if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:
1023 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
1024 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1025 TokenNumber += 1
1026
1027 for Pcd in self.DynamicPcdList:
1028 if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
1029 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
1030 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1031 TokenNumber += 1
1032
1033 for Pcd in self.NonDynamicPcdList:
1034 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1035 TokenNumber += 1
1036 return RetVal
1037
1038 @cached_property
1039 def _MbList(self):
1040 return [self.BuildDatabase[m, self.Arch, self.BuildTarget, self.ToolChain] for m in self.Platform.Modules]
1041
1042 @cached_property
1043 def _MaList(self):
1044 for ModuleFile in self.Platform.Modules:
1045 Ma = ModuleAutoGen(
1046 self.Workspace,
1047 ModuleFile,
1048 self.BuildTarget,
1049 self.ToolChain,
1050 self.Arch,
1051 self.MetaFile,
1052 self.DataPipe
1053 )
1054 self.Platform.Modules[ModuleFile].M = Ma
1055 return [x.M for x in self.Platform.Modules.values()]
1056
1057 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
1058 @cached_property
1059 def ModuleAutoGenList(self):
1060 RetVal = []
1061 for Ma in self._MaList:
1062 if Ma not in RetVal:
1063 RetVal.append(Ma)
1064 return RetVal
1065
1066 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
1067 @cached_property
1068 def LibraryAutoGenList(self):
1069 RetVal = []
1070 for Ma in self._MaList:
1071 for La in Ma.LibraryAutoGenList:
1072 if La not in RetVal:
1073 RetVal.append(La)
1074 if Ma not in La.ReferenceModules:
1075 La.ReferenceModules.append(Ma)
1076 return RetVal
1077
1078 ## Test if a module is supported by the platform
1079 #
1080 # An error will be raised directly if the module or its arch is not supported
1081 # by the platform or current configuration
1082 #
1083 def ValidModule(self, Module):
1084 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \
1085 or Module in self._AsBuildModuleList
1086 @cached_property
1087 def GetAllModuleInfo(self,WithoutPcd=True):
1088 ModuleLibs = set()
1089 for m in self.Platform.Modules:
1090 module_obj = self.BuildDatabase[m,self.Arch,self.BuildTarget,self.ToolChain]
1091 if not bool(module_obj.LibraryClass):
1092 Libs = GetModuleLibInstances(module_obj, self.Platform, self.BuildDatabase, self.Arch,self.BuildTarget,self.ToolChain)
1093 else:
1094 Libs = []
1095 ModuleLibs.update( set([(l.MetaFile.File,l.MetaFile.Root,l.MetaFile.Path,l.MetaFile.BaseName,l.MetaFile.OriginalPath,l.Arch,True) for l in Libs]))
1096 if WithoutPcd and module_obj.PcdIsDriver:
1097 continue
1098 ModuleLibs.add((m.File,m.Root,m.Path,m.BaseName,m.OriginalPath,module_obj.Arch,bool(module_obj.LibraryClass)))
1099
1100 return ModuleLibs
1101
1102 ## Resolve the library classes in a module to library instances
1103 #
1104 # This method will not only resolve library classes but also sort the library
1105 # instances according to the dependency-ship.
1106 #
1107 # @param Module The module from which the library classes will be resolved
1108 #
1109 # @retval library_list List of library instances sorted
1110 #
1111 def ApplyLibraryInstance(self, Module):
1112 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
1113 if str(Module) not in self.Platform.Modules:
1114 return []
1115
1116 return GetModuleLibInstances(Module,
1117 self.Platform,
1118 self.BuildDatabase,
1119 self.Arch,
1120 self.BuildTarget,
1121 self.ToolChain,
1122 self.MetaFile,
1123 EdkLogger)
1124
1125 ## Override PCD setting (type, value, ...)
1126 #
1127 # @param ToPcd The PCD to be overridden
1128 # @param FromPcd The PCD overriding from
1129 #
1130 def _OverridePcd(self, ToPcd, FromPcd, Module="", Msg="", Library=""):
1131 #
1132 # in case there's PCDs coming from FDF file, which have no type given.
1133 # at this point, ToPcd.Type has the type found from dependent
1134 # package
1135 #
1136 TokenCName = ToPcd.TokenCName
1137 for PcdItem in GlobalData.MixedPcd:
1138 if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
1139 TokenCName = PcdItem[0]
1140 break
1141 if FromPcd is not None:
1142 if ToPcd.Pending and FromPcd.Type:
1143 ToPcd.Type = FromPcd.Type
1144 elif ToPcd.Type and FromPcd.Type\
1145 and ToPcd.Type != FromPcd.Type and ToPcd.Type in FromPcd.Type:
1146 if ToPcd.Type.strip() == TAB_PCDS_DYNAMIC_EX:
1147 ToPcd.Type = FromPcd.Type
1148 elif ToPcd.Type and FromPcd.Type \
1149 and ToPcd.Type != FromPcd.Type:
1150 if Library:
1151 Module = str(Module) + " 's library file (" + str(Library) + ")"
1152 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",
1153 ExtraData="%s.%s is used as [%s] in module %s, but as [%s] in %s."\
1154 % (ToPcd.TokenSpaceGuidCName, TokenCName,
1155 ToPcd.Type, Module, FromPcd.Type, Msg),
1156 File=self.MetaFile)
1157
1158 if FromPcd.MaxDatumSize:
1159 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
1160 ToPcd.MaxSizeUserSet = FromPcd.MaxDatumSize
1161 if FromPcd.DefaultValue:
1162 ToPcd.DefaultValue = FromPcd.DefaultValue
1163 if FromPcd.TokenValue:
1164 ToPcd.TokenValue = FromPcd.TokenValue
1165 if FromPcd.DatumType:
1166 ToPcd.DatumType = FromPcd.DatumType
1167 if FromPcd.SkuInfoList:
1168 ToPcd.SkuInfoList = FromPcd.SkuInfoList
1169 if FromPcd.UserDefinedDefaultStoresFlag:
1170 ToPcd.UserDefinedDefaultStoresFlag = FromPcd.UserDefinedDefaultStoresFlag
1171 # Add Flexible PCD format parse
1172 if ToPcd.DefaultValue:
1173 try:
1174 ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self.Platform._GuidDict)(True)
1175 except BadExpression as Value:
1176 EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),
1177 File=self.MetaFile)
1178
1179 # check the validation of datum
1180 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)
1181 if not IsValid:
1182 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
1183 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, TokenCName))
1184 ToPcd.validateranges = FromPcd.validateranges
1185 ToPcd.validlists = FromPcd.validlists
1186 ToPcd.expressions = FromPcd.expressions
1187 ToPcd.CustomAttribute = FromPcd.CustomAttribute
1188
1189 if FromPcd is not None and ToPcd.DatumType == TAB_VOID and not ToPcd.MaxDatumSize:
1190 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \
1191 % (ToPcd.TokenSpaceGuidCName, TokenCName))
1192 Value = ToPcd.DefaultValue
1193 if not Value:
1194 ToPcd.MaxDatumSize = '1'
1195 elif Value[0] == 'L':
1196 ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)
1197 elif Value[0] == '{':
1198 ToPcd.MaxDatumSize = str(len(Value.split(',')))
1199 else:
1200 ToPcd.MaxDatumSize = str(len(Value) - 1)
1201
1202 # apply default SKU for dynamic PCDS if specified one is not available
1203 if (ToPcd.Type in PCD_DYNAMIC_TYPE_SET or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_SET) \
1204 and not ToPcd.SkuInfoList:
1205 if self.Platform.SkuName in self.Platform.SkuIds:
1206 SkuName = self.Platform.SkuName
1207 else:
1208 SkuName = TAB_DEFAULT
1209 ToPcd.SkuInfoList = {
1210 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName][0], '', '', '', '', '', ToPcd.DefaultValue)
1211 }
1212
1213 ## Apply PCD setting defined platform to a module
1214 #
1215 # @param Module The module from which the PCD setting will be overridden
1216 #
1217 # @retval PCD_list The list PCDs with settings from platform
1218 #
1219 def ApplyPcdSetting(self, Module, Pcds, Library=""):
1220 # for each PCD in module
1221 for Name, Guid in Pcds:
1222 PcdInModule = Pcds[Name, Guid]
1223 # find out the PCD setting in platform
1224 if (Name, Guid) in self.Platform.Pcds:
1225 PcdInPlatform = self.Platform.Pcds[Name, Guid]
1226 else:
1227 PcdInPlatform = None
1228 # then override the settings if any
1229 self._OverridePcd(PcdInModule, PcdInPlatform, Module, Msg="DSC PCD sections", Library=Library)
1230 # resolve the VariableGuid value
1231 for SkuId in PcdInModule.SkuInfoList:
1232 Sku = PcdInModule.SkuInfoList[SkuId]
1233 if Sku.VariableGuid == '': continue
1234 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList, self.MetaFile.Path)
1235 if Sku.VariableGuidValue is None:
1236 PackageList = "\n\t".join(str(P) for P in self.PackageList)
1237 EdkLogger.error(
1238 'build',
1239 RESOURCE_NOT_AVAILABLE,
1240 "Value of GUID [%s] is not found in" % Sku.VariableGuid,
1241 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \
1242 % (Guid, Name, str(Module)),
1243 File=self.MetaFile
1244 )
1245
1246 # override PCD settings with module specific setting
1247 if Module in self.Platform.Modules:
1248 PlatformModule = self.Platform.Modules[str(Module)]
1249 for Key in PlatformModule.Pcds:
1250 if GlobalData.BuildOptionPcd:
1251 for pcd in GlobalData.BuildOptionPcd:
1252 (TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue, _) = pcd
1253 if (TokenCName, TokenSpaceGuidCName) == Key and FieldName =="":
1254 PlatformModule.Pcds[Key].DefaultValue = pcdvalue
1255 PlatformModule.Pcds[Key].PcdValueFromComm = pcdvalue
1256 break
1257 Flag = False
1258 if Key in Pcds:
1259 ToPcd = Pcds[Key]
1260 Flag = True
1261 elif Key in GlobalData.MixedPcd:
1262 for PcdItem in GlobalData.MixedPcd[Key]:
1263 if PcdItem in Pcds:
1264 ToPcd = Pcds[PcdItem]
1265 Flag = True
1266 break
1267 if Flag:
1268 self._OverridePcd(ToPcd, PlatformModule.Pcds[Key], Module, Msg="DSC Components Module scoped PCD section", Library=Library)
1269 # use PCD value to calculate the MaxDatumSize when it is not specified
1270 for Name, Guid in Pcds:
1271 Pcd = Pcds[Name, Guid]
1272 if Pcd.DatumType == TAB_VOID and not Pcd.MaxDatumSize:
1273 Pcd.MaxSizeUserSet = None
1274 Value = Pcd.DefaultValue
1275 if not Value:
1276 Pcd.MaxDatumSize = '1'
1277 elif Value[0] == 'L':
1278 Pcd.MaxDatumSize = str((len(Value) - 2) * 2)
1279 elif Value[0] == '{':
1280 Pcd.MaxDatumSize = str(len(Value.split(',')))
1281 else:
1282 Pcd.MaxDatumSize = str(len(Value) - 1)
1283 return list(Pcds.values())
1284
1285 ## Append build options in platform to a module
1286 #
1287 # @param Module The module to which the build options will be appended
1288 #
1289 # @retval options The options appended with build options in platform
1290 #
1291 def ApplyBuildOption(self, Module):
1292 # Get the different options for the different style module
1293 PlatformOptions = self.EdkIIBuildOption
1294 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)
1295 ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)
1296 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)
1297 if Module in self.Platform.Modules:
1298 PlatformModule = self.Platform.Modules[str(Module)]
1299 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
1300 else:
1301 PlatformModuleOptions = {}
1302
1303 BuildRuleOrder = None
1304 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
1305 for Tool in Options:
1306 for Attr in Options[Tool]:
1307 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
1308 BuildRuleOrder = Options[Tool][Attr]
1309
1310 AllTools = set(list(ModuleOptions.keys()) + list(PlatformOptions.keys()) +
1311 list(PlatformModuleOptions.keys()) + list(ModuleTypeOptions.keys()) +
1312 list(self.ToolDefinition.keys()))
1313 BuildOptions = defaultdict(lambda: defaultdict(str))
1314 for Tool in AllTools:
1315 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
1316 if Tool not in Options:
1317 continue
1318 for Attr in Options[Tool]:
1319 #
1320 # Do not generate it in Makefile
1321 #
1322 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
1323 continue
1324 Value = Options[Tool][Attr]
1325 # check if override is indicated
1326 if Value.startswith('='):
1327 BuildOptions[Tool][Attr] = mws.handleWsMacro(Value[1:])
1328 else:
1329 if Attr != 'PATH':
1330 BuildOptions[Tool][Attr] += " " + mws.handleWsMacro(Value)
1331 else:
1332 BuildOptions[Tool][Attr] = mws.handleWsMacro(Value)
1333
1334 return BuildOptions, BuildRuleOrder
1335
1336
1337 def GetGlobalBuildOptions(self,Module):
1338 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)
1339 ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)
1340
1341 if Module in self.Platform.Modules:
1342 PlatformModule = self.Platform.Modules[str(Module)]
1343 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
1344 else:
1345 PlatformModuleOptions = {}
1346
1347 return ModuleTypeOptions,PlatformModuleOptions
1348 def ModuleGuid(self,Module):
1349 if os.path.basename(Module.MetaFile.File) != os.path.basename(Module.MetaFile.Path):
1350 #
1351 # Length of GUID is 36
1352 #
1353 return os.path.basename(Module.MetaFile.Path)[:36]
1354 return Module.Guid
1355 @cached_property
1356 def UniqueBaseName(self):
1357 retVal ={}
1358 ModuleNameDict = {}
1359 UniqueName = {}
1360 for Module in self._MbList:
1361 unique_base_name = '%s_%s' % (Module.BaseName,self.ModuleGuid(Module))
1362 if unique_base_name not in ModuleNameDict:
1363 ModuleNameDict[unique_base_name] = []
1364 ModuleNameDict[unique_base_name].append(Module.MetaFile)
1365 if Module.BaseName not in UniqueName:
1366 UniqueName[Module.BaseName] = set()
1367 UniqueName[Module.BaseName].add((self.ModuleGuid(Module),Module.MetaFile))
1368 for module_paths in ModuleNameDict.values():
1369 if len(set(module_paths))>1:
1370 samemodules = list(set(module_paths))
1371 EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'
1372 ' %s\n %s' % (samemodules[0], samemodules[1]))
1373 for name in UniqueName:
1374 Guid_Path = UniqueName[name]
1375 if len(Guid_Path) > 1:
1376 for guid,mpath in Guid_Path:
1377 retVal[(name,mpath)] = '%s_%s' % (name,guid)
1378 return retVal
1379 ## Expand * in build option key
1380 #
1381 # @param Options Options to be expanded
1382 # @param ToolDef Use specified ToolDef instead of full version.
1383 # This is needed during initialization to prevent
1384 # infinite recursion betweeh BuildOptions,
1385 # ToolDefinition, and this function.
1386 #
1387 # @retval options Options expanded
1388 #
1389 def _ExpandBuildOption(self, Options, ModuleStyle=None, ToolDef=None):
1390 if not ToolDef:
1391 ToolDef = self.ToolDefinition
1392 BuildOptions = {}
1393 FamilyMatch = False
1394 FamilyIsNull = True
1395
1396 OverrideList = {}
1397 #
1398 # Construct a list contain the build options which need override.
1399 #
1400 for Key in Options:
1401 #
1402 # Key[0] -- tool family
1403 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1404 #
1405 if (Key[0] == self.BuildRuleFamily and
1406 (ModuleStyle is None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):
1407 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')
1408 if (Target == self.BuildTarget or Target == TAB_STAR) and\
1409 (ToolChain == self.ToolChain or ToolChain == TAB_STAR) and\
1410 (Arch == self.Arch or Arch == TAB_STAR) and\
1411 Options[Key].startswith("="):
1412
1413 if OverrideList.get(Key[1]) is not None:
1414 OverrideList.pop(Key[1])
1415 OverrideList[Key[1]] = Options[Key]
1416
1417 #
1418 # Use the highest priority value.
1419 #
1420 if (len(OverrideList) >= 2):
1421 KeyList = list(OverrideList.keys())
1422 for Index in range(len(KeyList)):
1423 NowKey = KeyList[Index]
1424 Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")
1425 for Index1 in range(len(KeyList) - Index - 1):
1426 NextKey = KeyList[Index1 + Index + 1]
1427 #
1428 # Compare two Key, if one is included by another, choose the higher priority one
1429 #
1430 Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")
1431 if (Target1 == Target2 or Target1 == TAB_STAR or Target2 == TAB_STAR) and\
1432 (ToolChain1 == ToolChain2 or ToolChain1 == TAB_STAR or ToolChain2 == TAB_STAR) and\
1433 (Arch1 == Arch2 or Arch1 == TAB_STAR or Arch2 == TAB_STAR) and\
1434 (CommandType1 == CommandType2 or CommandType1 == TAB_STAR or CommandType2 == TAB_STAR) and\
1435 (Attr1 == Attr2 or Attr1 == TAB_STAR or Attr2 == TAB_STAR):
1436
1437 if CalculatePriorityValue(NowKey) > CalculatePriorityValue(NextKey):
1438 if Options.get((self.BuildRuleFamily, NextKey)) is not None:
1439 Options.pop((self.BuildRuleFamily, NextKey))
1440 else:
1441 if Options.get((self.BuildRuleFamily, NowKey)) is not None:
1442 Options.pop((self.BuildRuleFamily, NowKey))
1443
1444 for Key in Options:
1445 if ModuleStyle is not None and len (Key) > 2:
1446 # Check Module style is EDK or EDKII.
1447 # Only append build option for the matched style module.
1448 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
1449 continue
1450 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
1451 continue
1452 Family = Key[0]
1453 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
1454 # if tool chain family doesn't match, skip it
1455 if Tool in ToolDef and Family != "":
1456 FamilyIsNull = False
1457 if ToolDef[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
1458 if Family != ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
1459 continue
1460 elif Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
1461 continue
1462 FamilyMatch = True
1463 # expand any wildcard
1464 if Target == TAB_STAR or Target == self.BuildTarget:
1465 if Tag == TAB_STAR or Tag == self.ToolChain:
1466 if Arch == TAB_STAR or Arch == self.Arch:
1467 if Tool not in BuildOptions:
1468 BuildOptions[Tool] = {}
1469 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
1470 BuildOptions[Tool][Attr] = Options[Key]
1471 else:
1472 # append options for the same tool except PATH
1473 if Attr != 'PATH':
1474 BuildOptions[Tool][Attr] += " " + Options[Key]
1475 else:
1476 BuildOptions[Tool][Attr] = Options[Key]
1477 # Build Option Family has been checked, which need't to be checked again for family.
1478 if FamilyMatch or FamilyIsNull:
1479 return BuildOptions
1480
1481 for Key in Options:
1482 if ModuleStyle is not None and len (Key) > 2:
1483 # Check Module style is EDK or EDKII.
1484 # Only append build option for the matched style module.
1485 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
1486 continue
1487 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
1488 continue
1489 Family = Key[0]
1490 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
1491 # if tool chain family doesn't match, skip it
1492 if Tool not in ToolDef or Family == "":
1493 continue
1494 # option has been added before
1495 if Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
1496 continue
1497
1498 # expand any wildcard
1499 if Target == TAB_STAR or Target == self.BuildTarget:
1500 if Tag == TAB_STAR or Tag == self.ToolChain:
1501 if Arch == TAB_STAR or Arch == self.Arch:
1502 if Tool not in BuildOptions:
1503 BuildOptions[Tool] = {}
1504 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
1505 BuildOptions[Tool][Attr] = Options[Key]
1506 else:
1507 # append options for the same tool except PATH
1508 if Attr != 'PATH':
1509 BuildOptions[Tool][Attr] += " " + Options[Key]
1510 else:
1511 BuildOptions[Tool][Attr] = Options[Key]
1512 return BuildOptions