2 # Create makefile for MS nmake and GNU make
4 # Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
5 # Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
11 from __future__
import print_function
12 from __future__
import absolute_import
13 import os
.path
as path
15 from collections
import defaultdict
17 from .BuildEngine
import BuildRule
,gDefaultBuildRuleFile
,AutoGenReqBuildRuleVerNum
18 from .GenVar
import VariableMgr
, var_info
20 from AutoGen
.DataPipe
import MemoryDataPipe
21 from AutoGen
.ModuleAutoGen
import ModuleAutoGen
22 from AutoGen
.AutoGen
import AutoGen
23 from AutoGen
.AutoGen
import CalculatePriorityValue
24 from Workspace
.WorkspaceCommon
import GetModuleLibInstances
25 from CommonDataClass
.CommonClass
import SkuInfoClass
26 from Common
.caching
import cached_class_function
27 from Common
.Expression
import ValueExpressionEx
28 from Common
.StringUtils
import StringToArray
,NormPath
29 from Common
.BuildToolError
import *
30 from Common
.DataType
import *
31 from Common
.Misc
import *
32 import Common
.VpdInfoFile
as VpdInfoFile
34 ## Split command line option string to list
36 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
37 # in non-windows platform to launch command
39 def _SplitOption(OptionString
):
44 for Index
in range(0, len(OptionString
)):
45 CurrentChar
= OptionString
[Index
]
46 if CurrentChar
in ['"', "'"]:
47 if QuotationMark
== CurrentChar
:
49 elif QuotationMark
== "":
50 QuotationMark
= CurrentChar
55 if CurrentChar
in ["/", "-"] and LastChar
in [" ", "\t", "\r", "\n"]:
56 if Index
> OptionStart
:
57 OptionList
.append(OptionString
[OptionStart
:Index
- 1])
59 LastChar
= CurrentChar
60 OptionList
.append(OptionString
[OptionStart
:])
63 ## AutoGen class for platform
65 # PlatformAutoGen class will process the original information in platform
66 # file in order to generate makefile for platform.
68 class PlatformAutoGen(AutoGen
):
69 # call super().__init__ then call the worker function with different parameter count
70 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
71 if not hasattr(self
, "_Init"):
72 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
)
75 # Used to store all PCDs for both PEI and DXE phase, in order to generate
76 # correct PCD database
84 ## Initialize PlatformAutoGen
87 # @param Workspace WorkspaceAutoGen object
88 # @param PlatformFile Platform file (DSC file)
89 # @param Target Build target (DEBUG, RELEASE)
90 # @param Toolchain Name of tool chain
91 # @param Arch arch of the platform supports
93 def _InitWorker(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
94 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
95 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
97 self
.MetaFile
= PlatformFile
98 self
.Workspace
= Workspace
99 self
.WorkspaceDir
= Workspace
.WorkspaceDir
100 self
.ToolChain
= Toolchain
101 self
.BuildTarget
= Target
103 self
.SourceDir
= PlatformFile
.SubDir
104 self
.FdTargetList
= self
.Workspace
.FdTargetList
105 self
.FvTargetList
= self
.Workspace
.FvTargetList
106 # get the original module/package/platform objects
107 self
.BuildDatabase
= Workspace
.BuildDatabase
108 self
.DscBuildDataObj
= Workspace
.Platform
110 # MakeFileName is used to get the Makefile name and as a flag
111 # indicating whether the file has been created.
112 self
.MakeFileName
= ""
114 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
115 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
117 self
._AsBuildInfList
= []
118 self
._AsBuildModuleList
= []
120 self
.VariableInfo
= None
122 if GlobalData
.gFdfParser
is not None:
123 self
._AsBuildInfList
= GlobalData
.gFdfParser
.Profile
.InfList
124 for Inf
in self
._AsBuildInfList
:
125 InfClass
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, self
.Arch
)
126 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
127 if not M
.IsBinaryModule
:
129 self
._AsBuildModuleList
.append(InfClass
)
130 # get library/modules for build
131 self
.LibraryBuildDirectoryList
= []
132 self
.ModuleBuildDirectoryList
= []
134 self
.DataPipe
= MemoryDataPipe(self
.BuildDir
)
135 self
.DataPipe
.FillData(self
)
138 def FillData_LibConstPcd(self
):
140 for LibAuto
in self
.LibraryAutoGenList
:
142 libConstPcd
[(LibAuto
.MetaFile
.File
,LibAuto
.MetaFile
.Root
,LibAuto
.Arch
,LibAuto
.MetaFile
.Path
)] = LibAuto
.ConstPcd
143 self
.DataPipe
.DataContainer
= {"LibConstPcd":libConstPcd
}
144 ## hash() operator of PlatformAutoGen
146 # The platform file path and arch string will be used to represent
147 # hash value of this object
149 # @retval int Hash value of the platform file path and arch
151 @cached_class_function
153 return hash((self
.MetaFile
, self
.Arch
,self
.ToolChain
,self
.BuildTarget
))
154 @cached_class_function
156 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
158 ## Create autogen code for platform and modules
160 # Since there's no autogen code for platform, this method will do nothing
161 # if CreateModuleCodeFile is set to False.
163 # @param CreateModuleCodeFile Flag indicating if creating module's
164 # autogen code file or not
166 @cached_class_function
167 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
168 # only module has code to be created, so do nothing if CreateModuleCodeFile is False
169 if not CreateModuleCodeFile
:
172 for Ma
in self
.ModuleAutoGenList
:
173 Ma
.CreateCodeFile(CreateModuleCodeFile
)
175 ## Generate Fds Command
177 def GenFdsCommand(self
):
178 return self
.Workspace
.GenFdsCommand
180 ## Create makefile for the platform and modules in it
182 # @param CreateModuleMakeFile Flag indicating if the makefile for
183 # modules will be created as well
185 def CreateMakeFile(self
, CreateModuleMakeFile
=False, FfsCommand
= {}):
186 if CreateModuleMakeFile
:
187 for Ma
in self
._MaList
:
188 key
= (Ma
.MetaFile
.File
, self
.Arch
)
189 if key
in FfsCommand
:
190 Ma
.CreateMakeFile(CreateModuleMakeFile
, FfsCommand
[key
])
192 Ma
.CreateMakeFile(CreateModuleMakeFile
)
193 self
.CreateLibModuelDirs()
195 def CreateLibModuelDirs(self
):
196 # No need to create makefile for the platform more than once.
197 if self
.MakeFileName
:
200 # create library/module build dirs for platform
201 Makefile
= GenMake
.PlatformMakefile(self
)
202 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
203 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
204 self
.MakeFileName
= Makefile
.getMakefileName()
207 def AllPcdList(self
):
208 return self
.DynamicPcdList
+ self
.NonDynamicPcdList
209 ## Deal with Shared FixedAtBuild Pcds
211 def CollectFixedAtBuildPcds(self
):
212 for LibAuto
in self
.LibraryAutoGenList
:
213 FixedAtBuildPcds
= {}
214 ShareFixedAtBuildPcdsSameValue
= {}
215 for Module
in LibAuto
.ReferenceModules
:
216 for Pcd
in set(Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
):
217 DefaultValue
= Pcd
.DefaultValue
218 # Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib
219 if Pcd
in Module
.LibraryPcdList
:
220 Index
= Module
.LibraryPcdList
.index(Pcd
)
221 DefaultValue
= Module
.LibraryPcdList
[Index
].DefaultValue
222 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
223 if key
not in FixedAtBuildPcds
:
224 ShareFixedAtBuildPcdsSameValue
[key
] = True
225 FixedAtBuildPcds
[key
] = DefaultValue
227 if FixedAtBuildPcds
[key
] != DefaultValue
:
228 ShareFixedAtBuildPcdsSameValue
[key
] = False
229 for Pcd
in LibAuto
.FixedAtBuildPcds
:
230 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
231 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
234 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)]
235 if DscPcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
237 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
238 LibAuto
.ConstPcd
[key
] = FixedAtBuildPcds
[key
]
240 def CollectVariables(self
, DynamicPcdSet
):
243 if self
.Workspace
.FdfFile
:
244 FdDict
= self
.Workspace
.FdfProfile
.FdDict
[GlobalData
.gFdfParser
.CurrentFdName
]
245 for FdRegion
in FdDict
.RegionList
:
246 for item
in FdRegion
.RegionDataList
:
247 if self
.Platform
.VpdToolGuid
.strip() and self
.Platform
.VpdToolGuid
in item
:
248 VpdRegionSize
= FdRegion
.Size
249 VpdRegionBase
= FdRegion
.Offset
252 VariableInfo
= VariableMgr(self
.DscBuildDataObj
._GetDefaultStores
(), self
.DscBuildDataObj
.SkuIds
)
253 VariableInfo
.SetVpdRegionMaxSize(VpdRegionSize
)
254 VariableInfo
.SetVpdRegionOffset(VpdRegionBase
)
256 for Pcd
in sorted(DynamicPcdSet
):
257 pcdname
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
258 for SkuName
in Pcd
.SkuInfoList
:
259 Sku
= Pcd
.SkuInfoList
[SkuName
]
261 if SkuId
is None or SkuId
== '':
263 if len(Sku
.VariableName
) > 0:
264 if Sku
.VariableAttribute
and 'NV' not in Sku
.VariableAttribute
:
266 VariableGuidStructure
= Sku
.VariableGuidValue
267 VariableGuid
= GuidStructureStringToGuidString(VariableGuidStructure
)
268 for StorageName
in Sku
.DefaultStoreDict
:
269 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)))
273 def UpdateNVStoreMaxSize(self
, OrgVpdFile
):
274 if self
.VariableInfo
:
275 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
276 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
278 if PcdNvStoreDfBuffer
:
280 OrgVpdFile
.Read(VpdMapFilePath
)
281 PcdItems
= OrgVpdFile
.GetOffset(PcdNvStoreDfBuffer
[0])
282 NvStoreOffset
= list(PcdItems
.values())[0].strip() if PcdItems
else '0'
284 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
286 NvStoreOffset
= int(NvStoreOffset
, 16) if NvStoreOffset
.upper().startswith("0X") else int(NvStoreOffset
)
287 default_skuobj
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get(TAB_DEFAULT
)
288 maxsize
= self
.VariableInfo
.VpdRegionSize
- NvStoreOffset
if self
.VariableInfo
.VpdRegionSize
else len(default_skuobj
.DefaultValue
.split(","))
289 var_data
= self
.VariableInfo
.PatchNVStoreDefaultMaxSize(maxsize
)
291 if var_data
and default_skuobj
:
292 default_skuobj
.DefaultValue
= var_data
293 PcdNvStoreDfBuffer
[0].DefaultValue
= var_data
294 PcdNvStoreDfBuffer
[0].SkuInfoList
.clear()
295 PcdNvStoreDfBuffer
[0].SkuInfoList
[TAB_DEFAULT
] = default_skuobj
296 PcdNvStoreDfBuffer
[0].MaxDatumSize
= str(len(default_skuobj
.DefaultValue
.split(",")))
300 ## Collect dynamic PCDs
302 # Gather dynamic PCDs list from each module and their settings from platform
303 # This interface should be invoked explicitly when platform action is created.
305 def CollectPlatformDynamicPcds(self
):
307 self
.SortDynamicPcd()
309 def CategoryPcds(self
):
310 # Category Pcds into DynamicPcds and NonDynamicPcds
311 # for gathering error information
312 NoDatumTypePcdList
= set()
314 for InfName
in self
._AsBuildInfList
:
315 InfName
= mws
.join(self
.WorkspaceDir
, InfName
)
316 FdfModuleList
.append(os
.path
.normpath(InfName
))
317 for M
in self
._MbList
:
318 # F is the Module for which M is the module autogen
319 ModPcdList
= self
.ApplyPcdSetting(M
, M
.ModulePcdList
)
321 for lib
in M
.LibraryPcdList
:
322 LibPcdList
.extend(self
.ApplyPcdSetting(M
, M
.LibraryPcdList
[lib
], lib
))
323 for PcdFromModule
in ModPcdList
+ LibPcdList
:
325 # make sure that the "VOID*" kind of datum has MaxDatumSize set
326 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
327 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, M
.MetaFile
))
329 # Check the PCD from Binary INF or Source INF
330 if M
.IsBinaryModule
== True:
331 PcdFromModule
.IsFromBinaryInf
= True
333 # Check the PCD from DSC or not
334 PcdFromModule
.IsFromDsc
= (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
336 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
or PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
337 if M
.MetaFile
.Path
not in FdfModuleList
:
338 # If one of the Source built modules listed in the DSC is not listed
339 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
340 # access method (it is only listed in the DEC file that declares the
341 # PCD as PcdsDynamic), then build tool will report warning message
342 # notify the PI that they are attempting to build a module that must
343 # be included in a flash image in order to be functional. These Dynamic
344 # PCD will not be added into the Database unless it is used by other
345 # modules that are included in the FDF file.
346 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
and \
347 PcdFromModule
.IsFromBinaryInf
== False:
348 # Print warning message to let the developer make a determine.
350 # If one of the Source built modules listed in the DSC is not listed in
351 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
352 # access method (it is only listed in the DEC file that declares the
353 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
354 # PCD to the Platform's PCD Database.
355 if PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
358 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
359 # it should be stored in Pcd PEI database, If a dynamic only
360 # used by DXE module, it should be stored in DXE PCD database.
361 # The default Phase is DXE
363 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
364 PcdFromModule
.Phase
= "PEI"
365 if PcdFromModule
not in self
._DynaPcdList
_:
366 self
._DynaPcdList
_.append(PcdFromModule
)
367 elif PcdFromModule
.Phase
== 'PEI':
368 # overwrite any the same PCD existing, if Phase is PEI
369 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
370 self
._DynaPcdList
_[Index
] = PcdFromModule
371 elif PcdFromModule
not in self
._NonDynaPcdList
_:
372 self
._NonDynaPcdList
_.append(PcdFromModule
)
373 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
374 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
375 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
376 #The PCD from Binary INF will override the same one from source INF
377 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
378 PcdFromModule
.Pending
= False
379 self
._NonDynaPcdList
_.append (PcdFromModule
)
380 DscModuleSet
= {os
.path
.normpath(ModuleInf
.Path
) for ModuleInf
in self
.Platform
.Modules
}
381 # add the PCD from modules that listed in FDF but not in DSC to Database
382 for InfName
in FdfModuleList
:
383 if InfName
not in DscModuleSet
:
384 InfClass
= PathClass(InfName
)
385 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
386 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
387 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
388 # For binary module, if in current arch, we need to list the PCDs into database.
389 if not M
.IsBinaryModule
:
391 # Override the module PCD setting by platform setting
392 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
393 for PcdFromModule
in ModulePcdList
:
394 PcdFromModule
.IsFromBinaryInf
= True
395 PcdFromModule
.IsFromDsc
= False
396 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
397 if PcdFromModule
.Type
not in PCD_DYNAMIC_EX_TYPE_SET
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
398 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
400 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
401 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
402 # make sure that the "VOID*" kind of datum has MaxDatumSize set
403 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
404 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
405 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
406 PcdFromModule
.Phase
= "PEI"
407 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
408 self
._DynaPcdList
_.append(PcdFromModule
)
409 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
410 self
._NonDynaPcdList
_.append(PcdFromModule
)
411 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
412 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
413 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
414 # module & DXE module at a same time.
415 # Overwrite the type of the PCDs in source INF by the type of AsBuild
416 # INF file as DynamicEx.
417 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
418 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
419 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
420 for PcdFromModule
in self
._NonDynaPcdList
_:
421 # If a PCD is not listed in the DSC file, but binary INF files used by
422 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
423 # section, AND all source INF files used by this platform the build
424 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
425 # section, then the tools must NOT add the PCD to the Platform's PCD
426 # Database; the build must assign the access method for this PCD as
427 # PcdsPatchableInModule.
428 if PcdFromModule
not in self
._DynaPcdList
_:
430 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
431 if PcdFromModule
.IsFromDsc
== False and \
432 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
433 PcdFromModule
.IsFromBinaryInf
== True and \
434 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
435 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
436 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
438 # print out error information and break the build, if error found
439 if len(NoDatumTypePcdList
) > 0:
440 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
441 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
443 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
444 % NoDatumTypePcdListString
)
445 self
._NonDynamicPcdList
= sorted(self
._NonDynaPcdList
_)
446 self
._DynamicPcdList
= self
._DynaPcdList
_
448 def SortDynamicPcd(self
):
450 # Sort dynamic PCD list to:
451 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
452 # try to be put header of dynamicd List
453 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
455 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
457 UnicodePcdArray
= set()
459 OtherPcdArray
= set()
461 VpdFile
= VpdInfoFile
.VpdInfoFile()
462 NeedProcessVpdMapFile
= False
464 for pcd
in self
.Platform
.Pcds
:
465 if pcd
not in self
._PlatformPcds
:
466 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
468 for item
in self
._PlatformPcds
:
469 if self
._PlatformPcds
[item
].DatumType
and self
._PlatformPcds
[item
].DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
470 self
._PlatformPcds
[item
].DatumType
= TAB_VOID
472 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
473 for Pcd
in self
._DynamicPcdList
:
474 # just pick the a value to determine whether is unicode string type
475 Sku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
476 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
478 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
479 Pcd
.DatumType
= TAB_VOID
481 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
482 # if found HII type PCD then insert to right of UnicodeIndex
483 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
484 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
486 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
487 PcdNvStoreDfBuffer
= VpdPcdDict
.get(("PcdNvStoreDefaultValueBuffer", "gEfiMdeModulePkgTokenSpaceGuid"))
488 if PcdNvStoreDfBuffer
:
489 self
.VariableInfo
= self
.CollectVariables(self
._DynamicPcdList
)
490 vardump
= self
.VariableInfo
.dump()
493 #According to PCD_DATABASE_INIT in edk2\MdeModulePkg\Include\Guid\PcdDataBaseSignatureGuid.h,
494 #the max size for string PCD should not exceed USHRT_MAX 65535(0xffff).
495 #typedef UINT16 SIZE_INFO;
496 #//SIZE_INFO SizeTable[];
497 if len(vardump
.split(",")) > 0xffff:
498 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(","))))
499 PcdNvStoreDfBuffer
.DefaultValue
= vardump
500 for skuname
in PcdNvStoreDfBuffer
.SkuInfoList
:
501 PcdNvStoreDfBuffer
.SkuInfoList
[skuname
].DefaultValue
= vardump
502 PcdNvStoreDfBuffer
.MaxDatumSize
= str(len(vardump
.split(",")))
504 #If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd
505 if [Pcd
for Pcd
in self
._DynamicPcdList
if Pcd
.UserDefinedDefaultStoresFlag
]:
506 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
)
507 PlatformPcds
= sorted(self
._PlatformPcds
.keys())
509 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
512 for PcdKey
in PlatformPcds
:
513 Pcd
= self
._PlatformPcds
[PcdKey
]
514 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
515 PcdKey
in VpdPcdDict
:
516 Pcd
= VpdPcdDict
[PcdKey
]
518 DefaultSku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
520 PcdValue
= DefaultSku
.DefaultValue
521 if PcdValue
not in SkuValueMap
:
522 SkuValueMap
[PcdValue
] = []
523 VpdFile
.Add(Pcd
, TAB_DEFAULT
, DefaultSku
.VpdOffset
)
524 SkuValueMap
[PcdValue
].append(DefaultSku
)
526 for (SkuName
, Sku
) in Pcd
.SkuInfoList
.items():
527 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
528 PcdValue
= Sku
.DefaultValue
530 PcdValue
= Pcd
.DefaultValue
531 if Sku
.VpdOffset
!= TAB_STAR
:
532 if PcdValue
.startswith("{"):
534 elif PcdValue
.startswith("L"):
539 VpdOffset
= int(Sku
.VpdOffset
)
542 VpdOffset
= int(Sku
.VpdOffset
, 16)
544 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
545 if VpdOffset
% Alignment
!= 0:
546 if PcdValue
.startswith("{"):
547 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
), File
=self
.MetaFile
)
549 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, Alignment
))
550 if PcdValue
not in SkuValueMap
:
551 SkuValueMap
[PcdValue
] = []
552 VpdFile
.Add(Pcd
, SkuName
, Sku
.VpdOffset
)
553 SkuValueMap
[PcdValue
].append(Sku
)
554 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
555 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== TAB_STAR
:
556 NeedProcessVpdMapFile
= True
557 if self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== '':
558 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
559 "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.")
561 VpdSkuMap
[PcdKey
] = SkuValueMap
563 # Fix the PCDs define in VPD PCD section that never referenced by module.
564 # An example is PCD for signature usage.
566 for DscPcd
in PlatformPcds
:
567 DscPcdEntry
= self
._PlatformPcds
[DscPcd
]
568 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
569 if not (self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== ''):
571 for VpdPcd
in VpdFile
._VpdArray
:
572 # This PCD has been referenced by module
573 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
574 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
577 # Not found, it should be signature
579 # just pick the a value to determine whether is unicode string type
581 SkuObjList
= list(DscPcdEntry
.SkuInfoList
.items())
582 DefaultSku
= DscPcdEntry
.SkuInfoList
.get(TAB_DEFAULT
)
584 defaultindex
= SkuObjList
.index((TAB_DEFAULT
, DefaultSku
))
585 SkuObjList
[0], SkuObjList
[defaultindex
] = SkuObjList
[defaultindex
], SkuObjList
[0]
586 for (SkuName
, Sku
) in SkuObjList
:
587 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
589 # Need to iterate DEC pcd information to get the value & datumtype
590 for eachDec
in self
.PackageList
:
591 for DecPcd
in eachDec
.Pcds
:
592 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
593 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
594 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
595 # Print warning message to let the developer make a determine.
596 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
597 File
=self
.MetaFile
, \
598 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
599 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
601 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
602 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
603 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
604 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
605 # Only fix the value while no value provided in DSC file.
606 if not Sku
.DefaultValue
:
607 DscPcdEntry
.SkuInfoList
[list(DscPcdEntry
.SkuInfoList
.keys())[0]].DefaultValue
= DecPcdEntry
.DefaultValue
609 if DscPcdEntry
not in self
._DynamicPcdList
:
610 self
._DynamicPcdList
.append(DscPcdEntry
)
611 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
612 PcdValue
= Sku
.DefaultValue
614 PcdValue
= DscPcdEntry
.DefaultValue
615 if Sku
.VpdOffset
!= TAB_STAR
:
616 if PcdValue
.startswith("{"):
618 elif PcdValue
.startswith("L"):
623 VpdOffset
= int(Sku
.VpdOffset
)
626 VpdOffset
= int(Sku
.VpdOffset
, 16)
628 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
))
629 if VpdOffset
% Alignment
!= 0:
630 if PcdValue
.startswith("{"):
631 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
), File
=self
.MetaFile
)
633 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, Alignment
))
634 if PcdValue
not in SkuValueMap
:
635 SkuValueMap
[PcdValue
] = []
636 VpdFile
.Add(DscPcdEntry
, SkuName
, Sku
.VpdOffset
)
637 SkuValueMap
[PcdValue
].append(Sku
)
638 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== TAB_STAR
:
639 NeedProcessVpdMapFile
= True
640 if DscPcdEntry
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
641 UnicodePcdArray
.add(DscPcdEntry
)
642 elif len(Sku
.VariableName
) > 0:
643 HiiPcdArray
.add(DscPcdEntry
)
645 OtherPcdArray
.add(DscPcdEntry
)
647 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
648 VpdSkuMap
[DscPcd
] = SkuValueMap
649 if (self
.Platform
.FlashDefinition
is None or self
.Platform
.FlashDefinition
== '') and \
650 VpdFile
.GetCount() != 0:
651 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
652 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
654 if VpdFile
.GetCount() != 0:
656 self
.FixVpdOffset(VpdFile
)
658 self
.FixVpdOffset(self
.UpdateNVStoreMaxSize(VpdFile
))
659 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
660 if PcdNvStoreDfBuffer
:
661 PcdName
,PcdGuid
= PcdNvStoreDfBuffer
[0].TokenCName
, PcdNvStoreDfBuffer
[0].TokenSpaceGuidCName
662 if (PcdName
,PcdGuid
) in VpdSkuMap
:
663 DefaultSku
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get(TAB_DEFAULT
)
664 VpdSkuMap
[(PcdName
,PcdGuid
)] = {DefaultSku
.DefaultValue
:[SkuObj
for SkuObj
in PcdNvStoreDfBuffer
[0].SkuInfoList
.values() ]}
666 # Process VPD map file generated by third party BPDG tool
667 if NeedProcessVpdMapFile
:
668 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
670 VpdFile
.Read(VpdMapFilePath
)
672 # Fixup TAB_STAR offset
673 for pcd
in VpdSkuMap
:
674 vpdinfo
= VpdFile
.GetVpdInfo(pcd
)
676 # just pick the a value to determine whether is unicode string type
678 for pcdvalue
in VpdSkuMap
[pcd
]:
679 for sku
in VpdSkuMap
[pcd
][pcdvalue
]:
681 if item
[2] == pcdvalue
:
682 sku
.VpdOffset
= item
[1]
684 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
686 # Delete the DynamicPcdList At the last time enter into this function
687 for Pcd
in self
._DynamicPcdList
:
688 # just pick the a value to determine whether is unicode string type
689 Sku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
690 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
692 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
693 Pcd
.DatumType
= TAB_VOID
695 PcdValue
= Sku
.DefaultValue
696 if Pcd
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
697 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
698 UnicodePcdArray
.add(Pcd
)
699 elif len(Sku
.VariableName
) > 0:
700 # if found HII type PCD then insert to right of UnicodeIndex
703 OtherPcdArray
.add(Pcd
)
704 del self
._DynamicPcdList
[:]
705 self
._DynamicPcdList
.extend(list(UnicodePcdArray
))
706 self
._DynamicPcdList
.extend(list(HiiPcdArray
))
707 self
._DynamicPcdList
.extend(list(OtherPcdArray
))
708 self
._DynamicPcdList
.sort()
709 allskuset
= [(SkuName
, Sku
.SkuId
) for pcd
in self
._DynamicPcdList
for (SkuName
, Sku
) in pcd
.SkuInfoList
.items()]
710 for pcd
in self
._DynamicPcdList
:
711 if len(pcd
.SkuInfoList
) == 1:
712 for (SkuName
, SkuId
) in allskuset
:
713 if isinstance(SkuId
, str) and eval(SkuId
) == 0 or SkuId
== 0:
715 pcd
.SkuInfoList
[SkuName
] = copy
.deepcopy(pcd
.SkuInfoList
[TAB_DEFAULT
])
716 pcd
.SkuInfoList
[SkuName
].SkuId
= SkuId
717 pcd
.SkuInfoList
[SkuName
].SkuIdName
= SkuName
719 def FixVpdOffset(self
, VpdFile
):
720 FvPath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
721 if not os
.path
.exists(FvPath
):
725 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
727 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
729 if VpdFile
.Write(VpdFilePath
):
730 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
732 for ToolDef
in self
.ToolDefinition
.values():
733 if TAB_GUID
in ToolDef
and ToolDef
[TAB_GUID
] == self
.Platform
.VpdToolGuid
:
734 if "PATH" not in ToolDef
:
735 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
736 BPDGToolName
= ToolDef
["PATH"]
738 # Call third party GUID BPDG tool.
739 if BPDGToolName
is not None:
740 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
742 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.")
744 ## Return the platform build data object
747 return self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
749 ## Return platform name
752 return self
.Platform
.PlatformName
754 ## Return the meta file GUID
757 return self
.Platform
.Guid
759 ## Return the platform version
762 return self
.Platform
.Version
764 ## Return the FDF file name
767 if self
.Workspace
.FdfFile
:
768 RetVal
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
773 ## Return the build output directory platform specifies
776 return self
.Platform
.OutputDirectory
778 ## Return the directory to store all intermediate and final files built
781 if os
.path
.isabs(self
.OutputDir
):
782 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
783 path
.abspath(self
.OutputDir
),
784 self
.BuildTarget
+ "_" + self
.ToolChain
,
787 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
790 self
.BuildTarget
+ "_" + self
.ToolChain
,
794 ## Return directory of platform makefile
796 # @retval string Makefile directory
799 def MakeFileDir(self
):
800 return path
.join(self
.BuildDir
, self
.Arch
)
802 ## Return build command string
804 # @retval string Build command string
807 def BuildCommand(self
):
809 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
810 RetVal
+= _SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
811 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
812 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
814 RetVal
+= _SplitOption(NewOption
)
815 if "MAKE" in self
.EdkIIBuildOption
:
816 if "FLAGS" in self
.EdkIIBuildOption
["MAKE"]:
817 Flags
= self
.EdkIIBuildOption
["MAKE"]["FLAGS"]
818 if Flags
.startswith('='):
819 RetVal
= [RetVal
[0]] + [Flags
[1:]]
824 ## Get tool chain definition
826 # Get each tool definition for given tool chain from tools_def.txt and platform
829 def ToolDefinition(self
):
830 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
831 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
832 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
833 ExtraData
="[%s]" % self
.MetaFile
)
834 RetVal
= OrderedDict()
836 for Def
in ToolDefinition
:
837 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
838 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
841 Value
= ToolDefinition
[Def
]
842 # don't record the DLL
844 DllPathList
.add(Value
)
847 if Tool
not in RetVal
:
848 RetVal
[Tool
] = OrderedDict()
849 RetVal
[Tool
][Attr
] = Value
852 if GlobalData
.gOptions
.SilentMode
and "MAKE" in RetVal
:
853 if "FLAGS" not in RetVal
["MAKE"]:
854 RetVal
["MAKE"]["FLAGS"] = ""
855 RetVal
["MAKE"]["FLAGS"] += " -s"
858 for Attr
in RetVal
[Tool
]:
859 Value
= RetVal
[Tool
][Attr
]
860 if Tool
in self
._BuildOptionWithToolDef
(RetVal
) and Attr
in self
._BuildOptionWithToolDef
(RetVal
)[Tool
]:
861 # check if override is indicated
862 if self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
].startswith('='):
863 Value
= self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
][1:]
866 Value
+= " " + self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
868 Value
= self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
869 Def
= '_'.join([self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Tool
, Attr
])
870 self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
[Def
] = Value
872 # Don't put MAKE definition in the file
874 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
876 # Don't put MAKE definition in the file
881 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
884 tool_def_file
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
885 SaveFileOnChange(tool_def_file
, ToolsDef
, False)
886 for DllPath
in DllPathList
:
887 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
888 os
.environ
["MAKE_FLAGS"] = MakeFlags
892 ## Return the paths of tools
894 def ToolDefinitionFile(self
):
895 tool_def_file
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
896 if not os
.path
.exists(tool_def_file
):
900 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
902 def ToolChainFamily(self
):
903 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
904 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
905 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
906 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
907 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
909 RetVal
= TAB_COMPILER_MSFT
911 RetVal
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
915 def BuildRuleFamily(self
):
916 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
917 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
918 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
919 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
920 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
922 return TAB_COMPILER_MSFT
924 return ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
926 ## Return the build options specific for all modules in this platform
928 def BuildOption(self
):
929 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
931 def _BuildOptionWithToolDef(self
, ToolDef
):
932 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, ToolDef
=ToolDef
)
934 ## Return the build options specific for EDK modules in this platform
936 def EdkBuildOption(self
):
937 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
939 ## Return the build options specific for EDKII modules in this platform
941 def EdkIIBuildOption(self
):
942 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
944 ## Parse build_rule.txt in Conf Directory.
946 # @retval BuildRule object
951 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
952 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
953 if not BuildRuleFile
:
954 BuildRuleFile
= gDefaultBuildRuleFile
955 RetVal
= BuildRule(BuildRuleFile
)
956 if RetVal
._FileVersion
== "":
957 RetVal
._FileVersion
= AutoGenReqBuildRuleVerNum
959 if RetVal
._FileVersion
< AutoGenReqBuildRuleVerNum
:
960 # If Build Rule's version is less than the version number required by the tools, halting the build.
961 EdkLogger
.error("build", AUTOGEN_ERROR
,
962 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])"\
963 % (RetVal
._FileVersion
, AutoGenReqBuildRuleVerNum
))
966 ## Summarize the packages used by modules in this platform
968 def PackageList(self
):
970 for Mb
in self
._MbList
:
971 RetVal
.update(Mb
.Packages
)
972 for lb
in Mb
.LibInstances
:
973 RetVal
.update(lb
.Packages
)
974 #Collect package set information from INF of FDF
975 for ModuleFile
in self
._AsBuildModuleList
:
976 if ModuleFile
in self
.Platform
.Modules
:
978 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
979 RetVal
.update(ModuleData
.Packages
)
980 RetVal
.update(self
.Platform
.Packages
)
984 def NonDynamicPcdDict(self
):
985 return {(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
):Pcd
for Pcd
in self
.NonDynamicPcdList
}
987 ## Get list of non-dynamic PCDs
989 def NonDynamicPcdList(self
):
990 if not self
._NonDynamicPcdList
:
991 self
.CollectPlatformDynamicPcds()
992 return self
._NonDynamicPcdList
994 ## Get list of dynamic PCDs
996 def DynamicPcdList(self
):
997 if not self
._DynamicPcdList
:
998 self
.CollectPlatformDynamicPcds()
999 return self
._DynamicPcdList
1001 ## Generate Token Number for all PCD
1003 def PcdTokenNumber(self
):
1004 RetVal
= OrderedDict()
1007 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
1011 # TokenNumber 0 ~ 10
1013 # TokeNumber 11 ~ 20
1015 for Pcd
in self
.DynamicPcdList
:
1016 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_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
1021 for Pcd
in self
.DynamicPcdList
:
1022 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_EX_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
1027 for Pcd
in self
.DynamicPcdList
:
1028 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_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
1033 for Pcd
in self
.DynamicPcdList
:
1034 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1035 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1036 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1039 for Pcd
in self
.NonDynamicPcdList
:
1040 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1047 for m
in self
.Platform
.Modules
:
1048 component
= self
.Platform
.Modules
[m
]
1049 module
= self
.BuildDatabase
[m
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1050 module
.Guid
= component
.Guid
1051 ModuleList
.append(module
)
1056 for ModuleFile
in self
.Platform
.Modules
:
1066 self
.Platform
.Modules
[ModuleFile
].M
= Ma
1067 return [x
.M
for x
in self
.Platform
.Modules
.values()]
1069 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
1071 def ModuleAutoGenList(self
):
1073 for Ma
in self
._MaList
:
1074 if Ma
not in RetVal
:
1078 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
1080 def LibraryAutoGenList(self
):
1082 for Ma
in self
._MaList
:
1083 for La
in Ma
.LibraryAutoGenList
:
1084 if La
not in RetVal
:
1086 if Ma
not in La
.ReferenceModules
:
1087 La
.ReferenceModules
.append(Ma
)
1090 ## Test if a module is supported by the platform
1092 # An error will be raised directly if the module or its arch is not supported
1093 # by the platform or current configuration
1095 def ValidModule(self
, Module
):
1096 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
1097 or Module
in self
._AsBuildModuleList
1099 def GetAllModuleInfo(self
,WithoutPcd
=True):
1101 for m
in self
.Platform
.Modules
:
1102 module_obj
= self
.BuildDatabase
[m
,self
.Arch
,self
.BuildTarget
,self
.ToolChain
]
1103 if not bool(module_obj
.LibraryClass
):
1104 Libs
= GetModuleLibInstances(module_obj
, self
.Platform
, self
.BuildDatabase
, self
.Arch
,self
.BuildTarget
,self
.ToolChain
,self
.MetaFile
,EdkLogger
)
1107 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
]))
1108 if WithoutPcd
and module_obj
.PcdIsDriver
:
1110 ModuleLibs
.add((m
.File
,m
.Root
,m
.Path
,m
.BaseName
,m
.OriginalPath
,module_obj
.Arch
,bool(module_obj
.LibraryClass
)))
1114 ## Resolve the library classes in a module to library instances
1116 # This method will not only resolve library classes but also sort the library
1117 # instances according to the dependency-ship.
1119 # @param Module The module from which the library classes will be resolved
1121 # @retval library_list List of library instances sorted
1123 def ApplyLibraryInstance(self
, Module
):
1124 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
1125 if str(Module
) not in self
.Platform
.Modules
:
1128 return GetModuleLibInstances(Module
,
1137 ## Override PCD setting (type, value, ...)
1139 # @param ToPcd The PCD to be overridden
1140 # @param FromPcd The PCD overriding from
1142 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
="", Msg
="", Library
=""):
1144 # in case there's PCDs coming from FDF file, which have no type given.
1145 # at this point, ToPcd.Type has the type found from dependent
1148 TokenCName
= ToPcd
.TokenCName
1149 for PcdItem
in GlobalData
.MixedPcd
:
1150 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
1151 TokenCName
= PcdItem
[0]
1153 if FromPcd
is not None:
1154 if ToPcd
.Pending
and FromPcd
.Type
:
1155 ToPcd
.Type
= FromPcd
.Type
1156 elif ToPcd
.Type
and FromPcd
.Type\
1157 and ToPcd
.Type
!= FromPcd
.Type
and ToPcd
.Type
in FromPcd
.Type
:
1158 if ToPcd
.Type
.strip() == TAB_PCDS_DYNAMIC_EX
:
1159 ToPcd
.Type
= FromPcd
.Type
1160 elif ToPcd
.Type
and FromPcd
.Type \
1161 and ToPcd
.Type
!= FromPcd
.Type
:
1163 Module
= str(Module
) + " 's library file (" + str(Library
) + ")"
1164 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
1165 ExtraData
="%s.%s is used as [%s] in module %s, but as [%s] in %s."\
1166 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
1167 ToPcd
.Type
, Module
, FromPcd
.Type
, Msg
),
1170 if FromPcd
.MaxDatumSize
:
1171 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
1172 ToPcd
.MaxSizeUserSet
= FromPcd
.MaxDatumSize
1173 if FromPcd
.DefaultValue
:
1174 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
1175 if FromPcd
.TokenValue
:
1176 ToPcd
.TokenValue
= FromPcd
.TokenValue
1177 if FromPcd
.DatumType
:
1178 ToPcd
.DatumType
= FromPcd
.DatumType
1179 if FromPcd
.SkuInfoList
:
1180 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
1181 if FromPcd
.UserDefinedDefaultStoresFlag
:
1182 ToPcd
.UserDefinedDefaultStoresFlag
= FromPcd
.UserDefinedDefaultStoresFlag
1183 # Add Flexible PCD format parse
1184 if ToPcd
.DefaultValue
:
1186 ToPcd
.DefaultValue
= ValueExpressionEx(ToPcd
.DefaultValue
, ToPcd
.DatumType
, self
.Platform
._GuidDict
)(True)
1187 except BadExpression
as Value
:
1188 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
, ToPcd
.DefaultValue
, Value
),
1191 # check the validation of datum
1192 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
1194 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
1195 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
1196 ToPcd
.validateranges
= FromPcd
.validateranges
1197 ToPcd
.validlists
= FromPcd
.validlists
1198 ToPcd
.expressions
= FromPcd
.expressions
1199 ToPcd
.CustomAttribute
= FromPcd
.CustomAttribute
1201 if FromPcd
is not None and ToPcd
.DatumType
== TAB_VOID
and not ToPcd
.MaxDatumSize
:
1202 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
1203 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
1204 Value
= ToPcd
.DefaultValue
1206 ToPcd
.MaxDatumSize
= '1'
1207 elif Value
[0] == 'L':
1208 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
1209 elif Value
[0] == '{':
1210 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
1212 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
1214 # apply default SKU for dynamic PCDS if specified one is not available
1215 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_SET
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
) \
1216 and not ToPcd
.SkuInfoList
:
1217 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
1218 SkuName
= self
.Platform
.SkuName
1220 SkuName
= TAB_DEFAULT
1221 ToPcd
.SkuInfoList
= {
1222 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
][0], '', '', '', '', '', ToPcd
.DefaultValue
)
1225 ## Apply PCD setting defined platform to a module
1227 # @param Module The module from which the PCD setting will be overridden
1229 # @retval PCD_list The list PCDs with settings from platform
1231 def ApplyPcdSetting(self
, Module
, Pcds
, Library
=""):
1232 # for each PCD in module
1233 for Name
, Guid
in Pcds
:
1234 PcdInModule
= Pcds
[Name
, Guid
]
1235 # find out the PCD setting in platform
1236 if (Name
, Guid
) in self
.Platform
.Pcds
:
1237 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
1239 PcdInPlatform
= None
1240 # then override the settings if any
1241 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
, Msg
="DSC PCD sections", Library
=Library
)
1242 # resolve the VariableGuid value
1243 for SkuId
in PcdInModule
.SkuInfoList
:
1244 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
1245 if Sku
.VariableGuid
== '': continue
1246 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
1247 if Sku
.VariableGuidValue
is None:
1248 PackageList
= "\n\t".join(str(P
) for P
in self
.PackageList
)
1251 RESOURCE_NOT_AVAILABLE
,
1252 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
1253 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
1254 % (Guid
, Name
, str(Module
)),
1258 # override PCD settings with module specific setting
1259 if Module
in self
.Platform
.Modules
:
1260 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1261 for Key
in PlatformModule
.Pcds
:
1262 if GlobalData
.BuildOptionPcd
:
1263 for pcd
in GlobalData
.BuildOptionPcd
:
1264 (TokenSpaceGuidCName
, TokenCName
, FieldName
, pcdvalue
, _
) = pcd
1265 if (TokenCName
, TokenSpaceGuidCName
) == Key
and FieldName
=="":
1266 PlatformModule
.Pcds
[Key
].DefaultValue
= pcdvalue
1267 PlatformModule
.Pcds
[Key
].PcdValueFromComm
= pcdvalue
1273 elif Key
in GlobalData
.MixedPcd
:
1274 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
1276 ToPcd
= Pcds
[PcdItem
]
1280 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
, Msg
="DSC Components Module scoped PCD section", Library
=Library
)
1281 # use PCD value to calculate the MaxDatumSize when it is not specified
1282 for Name
, Guid
in Pcds
:
1283 Pcd
= Pcds
[Name
, Guid
]
1284 if Pcd
.DatumType
== TAB_VOID
and not Pcd
.MaxDatumSize
:
1285 Pcd
.MaxSizeUserSet
= None
1286 Value
= Pcd
.DefaultValue
1288 Pcd
.MaxDatumSize
= '1'
1289 elif Value
[0] == 'L':
1290 Pcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
1291 elif Value
[0] == '{':
1292 Pcd
.MaxDatumSize
= str(len(Value
.split(',')))
1294 Pcd
.MaxDatumSize
= str(len(Value
) - 1)
1295 return list(Pcds
.values())
1297 ## Append build options in platform to a module
1299 # @param Module The module to which the build options will be appended
1301 # @retval options The options appended with build options in platform
1303 def ApplyBuildOption(self
, Module
):
1304 # Get the different options for the different style module
1305 PlatformOptions
= self
.EdkIIBuildOption
1306 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
1307 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
1308 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
1309 if Module
in self
.Platform
.Modules
:
1310 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1311 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
1313 PlatformModuleOptions
= {}
1315 BuildRuleOrder
= None
1316 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
1317 for Tool
in Options
:
1318 for Attr
in Options
[Tool
]:
1319 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
1320 BuildRuleOrder
= Options
[Tool
][Attr
]
1322 AllTools
= set(list(ModuleOptions
.keys()) + list(PlatformOptions
.keys()) +
1323 list(PlatformModuleOptions
.keys()) + list(ModuleTypeOptions
.keys()) +
1324 list(self
.ToolDefinition
.keys()))
1325 BuildOptions
= defaultdict(lambda: defaultdict(str))
1326 for Tool
in AllTools
:
1327 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
1328 if Tool
not in Options
:
1330 for Attr
in Options
[Tool
]:
1332 # Do not generate it in Makefile
1334 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
1336 Value
= Options
[Tool
][Attr
]
1337 # check if override is indicated
1338 if Value
.startswith('='):
1339 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
[1:])
1342 BuildOptions
[Tool
][Attr
] += " " + mws
.handleWsMacro(Value
)
1344 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
)
1346 return BuildOptions
, BuildRuleOrder
1349 def GetGlobalBuildOptions(self
,Module
):
1350 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
1351 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
1353 if Module
in self
.Platform
.Modules
:
1354 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1355 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
1357 PlatformModuleOptions
= {}
1359 return ModuleTypeOptions
,PlatformModuleOptions
1360 def ModuleGuid(self
,Module
):
1361 if os
.path
.basename(Module
.MetaFile
.File
) != os
.path
.basename(Module
.MetaFile
.Path
):
1363 # Length of GUID is 36
1365 return os
.path
.basename(Module
.MetaFile
.Path
)[:36]
1368 def UniqueBaseName(self
):
1372 for Module
in self
._MbList
:
1373 unique_base_name
= '%s_%s' % (Module
.BaseName
,self
.ModuleGuid(Module
))
1374 if unique_base_name
not in ModuleNameDict
:
1375 ModuleNameDict
[unique_base_name
] = []
1376 ModuleNameDict
[unique_base_name
].append(Module
.MetaFile
)
1377 if Module
.BaseName
not in UniqueName
:
1378 UniqueName
[Module
.BaseName
] = set()
1379 UniqueName
[Module
.BaseName
].add((self
.ModuleGuid(Module
),Module
.MetaFile
))
1380 for module_paths
in ModuleNameDict
.values():
1381 if len(set(module_paths
))>1:
1382 samemodules
= list(set(module_paths
))
1383 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
1384 ' %s\n %s' % (samemodules
[0], samemodules
[1]))
1385 for name
in UniqueName
:
1386 Guid_Path
= UniqueName
[name
]
1387 if len(Guid_Path
) > 1:
1388 for guid
,mpath
in Guid_Path
:
1389 retVal
[(name
,mpath
)] = '%s_%s' % (name
,guid
)
1391 ## Expand * in build option key
1393 # @param Options Options to be expanded
1394 # @param ToolDef Use specified ToolDef instead of full version.
1395 # This is needed during initialization to prevent
1396 # infinite recursion betweeh BuildOptions,
1397 # ToolDefinition, and this function.
1399 # @retval options Options expanded
1401 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None, ToolDef
=None):
1403 ToolDef
= self
.ToolDefinition
1410 # Construct a list contain the build options which need override.
1414 # Key[0] -- tool family
1415 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1417 if (Key
[0] == self
.BuildRuleFamily
and
1418 (ModuleStyle
is None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
1419 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
1420 if (Target
== self
.BuildTarget
or Target
== TAB_STAR
) and\
1421 (ToolChain
== self
.ToolChain
or ToolChain
== TAB_STAR
) and\
1422 (Arch
== self
.Arch
or Arch
== TAB_STAR
) and\
1423 Options
[Key
].startswith("="):
1425 if OverrideList
.get(Key
[1]) is not None:
1426 OverrideList
.pop(Key
[1])
1427 OverrideList
[Key
[1]] = Options
[Key
]
1430 # Use the highest priority value.
1432 if (len(OverrideList
) >= 2):
1433 KeyList
= list(OverrideList
.keys())
1434 for Index
in range(len(KeyList
)):
1435 NowKey
= KeyList
[Index
]
1436 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
1437 for Index1
in range(len(KeyList
) - Index
- 1):
1438 NextKey
= KeyList
[Index1
+ Index
+ 1]
1440 # Compare two Key, if one is included by another, choose the higher priority one
1442 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
1443 if (Target1
== Target2
or Target1
== TAB_STAR
or Target2
== TAB_STAR
) and\
1444 (ToolChain1
== ToolChain2
or ToolChain1
== TAB_STAR
or ToolChain2
== TAB_STAR
) and\
1445 (Arch1
== Arch2
or Arch1
== TAB_STAR
or Arch2
== TAB_STAR
) and\
1446 (CommandType1
== CommandType2
or CommandType1
== TAB_STAR
or CommandType2
== TAB_STAR
) and\
1447 (Attr1
== Attr2
or Attr1
== TAB_STAR
or Attr2
== TAB_STAR
):
1449 if CalculatePriorityValue(NowKey
) > CalculatePriorityValue(NextKey
):
1450 if Options
.get((self
.BuildRuleFamily
, NextKey
)) is not None:
1451 Options
.pop((self
.BuildRuleFamily
, NextKey
))
1453 if Options
.get((self
.BuildRuleFamily
, NowKey
)) is not None:
1454 Options
.pop((self
.BuildRuleFamily
, NowKey
))
1457 if ModuleStyle
is not None and len (Key
) > 2:
1458 # Check Module style is EDK or EDKII.
1459 # Only append build option for the matched style module.
1460 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
1462 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
1465 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
1466 # if tool chain family doesn't match, skip it
1467 if Tool
in ToolDef
and Family
!= "":
1468 FamilyIsNull
= False
1469 if ToolDef
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
1470 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
1472 elif Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
1475 # expand any wildcard
1476 if Target
== TAB_STAR
or Target
== self
.BuildTarget
:
1477 if Tag
== TAB_STAR
or Tag
== self
.ToolChain
:
1478 if Arch
== TAB_STAR
or Arch
== self
.Arch
:
1479 if Tool
not in BuildOptions
:
1480 BuildOptions
[Tool
] = {}
1481 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
1482 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1484 # append options for the same tool except PATH
1486 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
1488 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1489 # Build Option Family has been checked, which need't to be checked again for family.
1490 if FamilyMatch
or FamilyIsNull
:
1494 if ModuleStyle
is not None and len (Key
) > 2:
1495 # Check Module style is EDK or EDKII.
1496 # Only append build option for the matched style module.
1497 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
1499 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
1502 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
1503 # if tool chain family doesn't match, skip it
1504 if Tool
not in ToolDef
or Family
== "":
1506 # option has been added before
1507 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
1510 # expand any wildcard
1511 if Target
== TAB_STAR
or Target
== self
.BuildTarget
:
1512 if Tag
== TAB_STAR
or Tag
== self
.ToolChain
:
1513 if Arch
== TAB_STAR
or Arch
== self
.Arch
:
1514 if Tool
not in BuildOptions
:
1515 BuildOptions
[Tool
] = {}
1516 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
1517 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1519 # append options for the same tool except PATH
1521 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
1523 BuildOptions
[Tool
][Attr
] = Options
[Key
]