2 # Create makefile for MS nmake and GNU make
4 # Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
5 # SPDX-License-Identifier: BSD-2-Clause-Patent
10 from __future__
import print_function
11 from __future__
import absolute_import
12 import os
.path
as path
14 from collections
import defaultdict
16 from .BuildEngine
import BuildRule
,gDefaultBuildRuleFile
,AutoGenReqBuildRuleVerNum
17 from .GenVar
import VariableMgr
, var_info
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
33 ## Split command line option string to list
35 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
36 # in non-windows platform to launch command
38 def _SplitOption(OptionString
):
43 for Index
in range(0, len(OptionString
)):
44 CurrentChar
= OptionString
[Index
]
45 if CurrentChar
in ['"', "'"]:
46 if QuotationMark
== CurrentChar
:
48 elif QuotationMark
== "":
49 QuotationMark
= CurrentChar
54 if CurrentChar
in ["/", "-"] and LastChar
in [" ", "\t", "\r", "\n"]:
55 if Index
> OptionStart
:
56 OptionList
.append(OptionString
[OptionStart
:Index
- 1])
58 LastChar
= CurrentChar
59 OptionList
.append(OptionString
[OptionStart
:])
62 ## AutoGen class for platform
64 # PlatformAutoGen class will process the original information in platform
65 # file in order to generate makefile for platform.
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
)
74 # Used to store all PCDs for both PEI and DXE phase, in order to generate
75 # correct PCD database
83 ## Initialize PlatformAutoGen
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
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
)
96 self
.MetaFile
= PlatformFile
97 self
.Workspace
= Workspace
98 self
.WorkspaceDir
= Workspace
.WorkspaceDir
99 self
.ToolChain
= Toolchain
100 self
.BuildTarget
= Target
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
109 # flag indicating if the makefile/C-code file has been created or not
110 self
.IsMakeFileCreated
= False
112 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
113 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
115 self
._AsBuildInfList
= []
116 self
._AsBuildModuleList
= []
118 self
.VariableInfo
= None
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
:
127 self
._AsBuildModuleList
.append(InfClass
)
128 # get library/modules for build
129 self
.LibraryBuildDirectoryList
= []
130 self
.ModuleBuildDirectoryList
= []
132 self
.DataPipe
= MemoryDataPipe(self
.BuildDir
)
133 self
.DataPipe
.FillData(self
)
136 def FillData_LibConstPcd(self
):
138 for LibAuto
in self
.LibraryAutoGenList
:
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
144 # The platform file path and arch string will be used to represent
145 # hash value of this object
147 # @retval int Hash value of the platform file path and arch
149 @cached_class_function
151 return hash((self
.MetaFile
, self
.Arch
))
152 @cached_class_function
154 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
156 ## Create autogen code for platform and modules
158 # Since there's no autogen code for platform, this method will do nothing
159 # if CreateModuleCodeFile is set to False.
161 # @param CreateModuleCodeFile Flag indicating if creating module's
162 # autogen code file or not
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
:
170 for Ma
in self
.ModuleAutoGenList
:
171 Ma
.CreateCodeFile(CreateModuleCodeFile
)
173 ## Generate Fds Command
175 def GenFdsCommand(self
):
176 return self
.Workspace
.GenFdsCommand
178 ## Create makefile for the platform and modules in it
180 # @param CreateModuleMakeFile Flag indicating if the makefile for
181 # modules will be created as well
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
])
190 Ma
.CreateMakeFile(CreateModuleMakeFile
)
192 # no need to create makefile for the platform more than once
193 if self
.IsMakeFileCreated
:
196 # create library/module build dirs for platform
197 Makefile
= GenMake
.PlatformMakefile(self
)
198 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
199 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
201 self
.IsMakeFileCreated
= True
204 def AllPcdList(self
):
205 return self
.DynamicPcdList
+ self
.NonDynamicPcdList
206 ## Deal with Shared FixedAtBuild Pcds
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
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
:
231 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)]
232 if DscPcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
234 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
235 LibAuto
.ConstPcd
[key
] = FixedAtBuildPcds
[key
]
237 def CollectVariables(self
, DynamicPcdSet
):
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
249 VariableInfo
= VariableMgr(self
.DscBuildDataObj
._GetDefaultStores
(), self
.DscBuildDataObj
.SkuIds
)
250 VariableInfo
.SetVpdRegionMaxSize(VpdRegionSize
)
251 VariableInfo
.SetVpdRegionOffset(VpdRegionBase
)
253 for Pcd
in DynamicPcdSet
:
254 pcdname
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
255 for SkuName
in Pcd
.SkuInfoList
:
256 Sku
= Pcd
.SkuInfoList
[SkuName
]
258 if SkuId
is None or SkuId
== '':
260 if len(Sku
.VariableName
) > 0:
261 if Sku
.VariableAttribute
and 'NV' not in Sku
.VariableAttribute
:
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)))
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"]
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'
281 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
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
)
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(",")))
297 ## Collect dynamic PCDs
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.
302 def CollectPlatformDynamicPcds(self
):
304 self
.SortDynamicPcd()
306 def CategoryPcds(self
):
307 # Category Pcds into DynamicPcds and NonDynamicPcds
308 # for gathering error information
309 NoDatumTypePcdList
= set()
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
)
318 for lib
in M
.LibraryPcdList
:
319 LibPcdList
.extend(self
.ApplyPcdSetting(M
, M
.LibraryPcdList
[lib
], lib
))
320 for PcdFromModule
in ModPcdList
+ LibPcdList
:
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
))
326 # Check the PCD from Binary INF or Source INF
327 if M
.IsBinaryModule
== True:
328 PcdFromModule
.IsFromBinaryInf
= True
330 # Check the PCD from DSC or not
331 PcdFromModule
.IsFromDsc
= (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
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.
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
:
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
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
:
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",
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
_:
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
])
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",
440 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
441 % NoDatumTypePcdListString
)
442 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
443 self
._DynamicPcdList
= self
._DynaPcdList
_
445 def SortDynamicPcd(self
):
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
452 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
454 UnicodePcdArray
= set()
456 OtherPcdArray
= set()
458 VpdFile
= VpdInfoFile
.VpdInfoFile()
459 NeedProcessVpdMapFile
= False
461 for pcd
in self
.Platform
.Pcds
:
462 if pcd
not in self
._PlatformPcds
:
463 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
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
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()
475 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
476 Pcd
.DatumType
= TAB_VOID
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
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()
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(",")))
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())
506 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
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
]
515 DefaultSku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
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
)
523 for (SkuName
, Sku
) in Pcd
.SkuInfoList
.items():
524 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
525 PcdValue
= Sku
.DefaultValue
527 PcdValue
= Pcd
.DefaultValue
528 if Sku
.VpdOffset
!= TAB_STAR
:
529 if PcdValue
.startswith("{"):
531 elif PcdValue
.startswith("L"):
536 VpdOffset
= int(Sku
.VpdOffset
)
539 VpdOffset
= int(Sku
.VpdOffset
, 16)
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
)
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.")
558 VpdSkuMap
[PcdKey
] = SkuValueMap
560 # Fix the PCDs define in VPD PCD section that never referenced by module.
561 # An example is PCD for signature usage.
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
== ''):
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
):
574 # Not found, it should be signature
576 # just pick the a value to determine whether is unicode string type
578 SkuObjList
= list(DscPcdEntry
.SkuInfoList
.items())
579 DefaultSku
= DscPcdEntry
.SkuInfoList
.get(TAB_DEFAULT
)
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()
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
))
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
606 if DscPcdEntry
not in self
._DynamicPcdList
:
607 self
._DynamicPcdList
.append(DscPcdEntry
)
608 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
609 PcdValue
= Sku
.DefaultValue
611 PcdValue
= DscPcdEntry
.DefaultValue
612 if Sku
.VpdOffset
!= TAB_STAR
:
613 if PcdValue
.startswith("{"):
615 elif PcdValue
.startswith("L"):
620 VpdOffset
= int(Sku
.VpdOffset
)
623 VpdOffset
= int(Sku
.VpdOffset
, 16)
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
)
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
)
642 OtherPcdArray
.add(DscPcdEntry
)
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
))
651 if VpdFile
.GetCount() != 0:
653 self
.FixVpdOffset(VpdFile
)
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() ]}
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
)
669 # Fixup TAB_STAR offset
670 for pcd
in VpdSkuMap
:
671 vpdinfo
= VpdFile
.GetVpdInfo(pcd
)
673 # just pick the a value to determine whether is unicode string type
675 for pcdvalue
in VpdSkuMap
[pcd
]:
676 for sku
in VpdSkuMap
[pcd
][pcdvalue
]:
678 if item
[2] == pcdvalue
:
679 sku
.VpdOffset
= item
[1]
681 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
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()
689 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
690 Pcd
.DatumType
= TAB_VOID
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
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:
711 pcd
.SkuInfoList
[SkuName
] = copy
.deepcopy(pcd
.SkuInfoList
[TAB_DEFAULT
])
712 pcd
.SkuInfoList
[SkuName
].SkuId
= SkuId
713 pcd
.SkuInfoList
[SkuName
].SkuIdName
= SkuName
715 def FixVpdOffset(self
, VpdFile
):
716 FvPath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
717 if not os
.path
.exists(FvPath
):
721 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
723 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
725 if VpdFile
.Write(VpdFilePath
):
726 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
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"]
734 # Call third party GUID BPDG tool.
735 if BPDGToolName
is not None:
736 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
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.")
740 ## Return the platform build data object
743 return self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
745 ## Return platform name
748 return self
.Platform
.PlatformName
750 ## Return the meta file GUID
753 return self
.Platform
.Guid
755 ## Return the platform version
758 return self
.Platform
.Version
760 ## Return the FDF file name
763 if self
.Workspace
.FdfFile
:
764 RetVal
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
769 ## Return the build output directory platform specifies
772 return self
.Platform
.OutputDirectory
774 ## Return the directory to store all intermediate and final files built
777 if os
.path
.isabs(self
.OutputDir
):
778 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
779 path
.abspath(self
.OutputDir
),
780 self
.BuildTarget
+ "_" + self
.ToolChain
,
783 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
786 self
.BuildTarget
+ "_" + self
.ToolChain
,
790 ## Return directory of platform makefile
792 # @retval string Makefile directory
795 def MakeFileDir(self
):
796 return path
.join(self
.BuildDir
, self
.Arch
)
798 ## Return build command string
800 # @retval string Build command string
803 def BuildCommand(self
):
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()
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:]]
820 ## Get tool chain definition
822 # Get each tool definition for given tool chain from tools_def.txt and platform
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()
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
:
837 Value
= ToolDefinition
[Def
]
838 # don't record the DLL
840 DllPathList
.add(Value
)
843 if Tool
not in RetVal
:
844 RetVal
[Tool
] = OrderedDict()
845 RetVal
[Tool
][Attr
] = Value
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"
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:]
862 Value
+= " " + self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
864 Value
= self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
867 # Don't put MAKE definition in the file
869 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
871 # Don't put MAKE definition in the file
876 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
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
887 ## Return the paths of tools
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
):
895 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
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." \
904 RetVal
= TAB_COMPILER_MSFT
906 RetVal
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
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." \
917 return TAB_COMPILER_MSFT
919 return ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
921 ## Return the build options specific for all modules in this platform
923 def BuildOption(self
):
924 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
926 def _BuildOptionWithToolDef(self
, ToolDef
):
927 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, ToolDef
=ToolDef
)
929 ## Return the build options specific for EDK modules in this platform
931 def EdkBuildOption(self
):
932 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
934 ## Return the build options specific for EDKII modules in this platform
936 def EdkIIBuildOption(self
):
937 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
939 ## Parse build_rule.txt in Conf Directory.
941 # @retval BuildRule object
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
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
))
961 ## Summarize the packages used by modules in this platform
963 def PackageList(self
):
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
:
973 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
974 RetVal
.update(ModuleData
.Packages
)
978 def NonDynamicPcdDict(self
):
979 return {(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
):Pcd
for Pcd
in self
.NonDynamicPcdList
}
981 ## Get list of non-dynamic PCDs
983 def NonDynamicPcdList(self
):
984 if not self
._NonDynamicPcdList
:
985 self
.CollectPlatformDynamicPcds()
986 return self
._NonDynamicPcdList
988 ## Get list of dynamic PCDs
990 def DynamicPcdList(self
):
991 if not self
._DynamicPcdList
:
992 self
.CollectPlatformDynamicPcds()
993 return self
._DynamicPcdList
995 ## Generate Token Number for all PCD
997 def PcdTokenNumber(self
):
998 RetVal
= OrderedDict()
1001 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
1005 # TokenNumber 0 ~ 10
1007 # TokeNumber 11 ~ 20
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
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
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
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
1033 for Pcd
in self
.NonDynamicPcdList
:
1034 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1040 return [self
.BuildDatabase
[m
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
] for m
in self
.Platform
.Modules
]
1044 for ModuleFile
in self
.Platform
.Modules
:
1054 self
.Platform
.Modules
[ModuleFile
].M
= Ma
1055 return [x
.M
for x
in self
.Platform
.Modules
.values()]
1057 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
1059 def ModuleAutoGenList(self
):
1061 for Ma
in self
._MaList
:
1062 if Ma
not in RetVal
:
1066 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
1068 def LibraryAutoGenList(self
):
1070 for Ma
in self
._MaList
:
1071 for La
in Ma
.LibraryAutoGenList
:
1072 if La
not in RetVal
:
1074 if Ma
not in La
.ReferenceModules
:
1075 La
.ReferenceModules
.append(Ma
)
1078 ## Test if a module is supported by the platform
1080 # An error will be raised directly if the module or its arch is not supported
1081 # by the platform or current configuration
1083 def ValidModule(self
, Module
):
1084 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
1085 or Module
in self
._AsBuildModuleList
1087 def GetAllModuleInfo(self
,WithoutPcd
=True):
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
,self
.MetaFile
,EdkLogger
)
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
:
1098 ModuleLibs
.add((m
.File
,m
.Root
,m
.Path
,m
.BaseName
,m
.OriginalPath
,module_obj
.Arch
,bool(module_obj
.LibraryClass
)))
1102 ## Resolve the library classes in a module to library instances
1104 # This method will not only resolve library classes but also sort the library
1105 # instances according to the dependency-ship.
1107 # @param Module The module from which the library classes will be resolved
1109 # @retval library_list List of library instances sorted
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
:
1116 return GetModuleLibInstances(Module
,
1125 ## Override PCD setting (type, value, ...)
1127 # @param ToPcd The PCD to be overridden
1128 # @param FromPcd The PCD overriding from
1130 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
="", Msg
="", Library
=""):
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
1136 TokenCName
= ToPcd
.TokenCName
1137 for PcdItem
in GlobalData
.MixedPcd
:
1138 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
1139 TokenCName
= PcdItem
[0]
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
:
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
),
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
:
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
),
1179 # check the validation of datum
1180 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
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
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
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(',')))
1200 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
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
1208 SkuName
= TAB_DEFAULT
1209 ToPcd
.SkuInfoList
= {
1210 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
][0], '', '', '', '', '', ToPcd
.DefaultValue
)
1213 ## Apply PCD setting defined platform to a module
1215 # @param Module The module from which the PCD setting will be overridden
1217 # @retval PCD_list The list PCDs with settings from platform
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
]
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
)
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
)),
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
1261 elif Key
in GlobalData
.MixedPcd
:
1262 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
1264 ToPcd
= Pcds
[PcdItem
]
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
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(',')))
1282 Pcd
.MaxDatumSize
= str(len(Value
) - 1)
1283 return list(Pcds
.values())
1285 ## Append build options in platform to a module
1287 # @param Module The module to which the build options will be appended
1289 # @retval options The options appended with build options in platform
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
)
1301 PlatformModuleOptions
= {}
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
]
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
:
1318 for Attr
in Options
[Tool
]:
1320 # Do not generate it in Makefile
1322 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
1324 Value
= Options
[Tool
][Attr
]
1325 # check if override is indicated
1326 if Value
.startswith('='):
1327 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
[1:])
1330 BuildOptions
[Tool
][Attr
] += " " + mws
.handleWsMacro(Value
)
1332 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
)
1334 return BuildOptions
, BuildRuleOrder
1337 def GetGlobalBuildOptions(self
,Module
):
1338 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
1339 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
1341 if Module
in self
.Platform
.Modules
:
1342 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1343 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
1345 PlatformModuleOptions
= {}
1347 return ModuleTypeOptions
,PlatformModuleOptions
1348 def ModuleGuid(self
,Module
):
1349 if os
.path
.basename(Module
.MetaFile
.File
) != os
.path
.basename(Module
.MetaFile
.Path
):
1351 # Length of GUID is 36
1353 return os
.path
.basename(Module
.MetaFile
.Path
)[:36]
1356 def UniqueBaseName(self
):
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
)
1379 ## Expand * in build option key
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.
1387 # @retval options Options expanded
1389 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None, ToolDef
=None):
1391 ToolDef
= self
.ToolDefinition
1398 # Construct a list contain the build options which need override.
1402 # Key[0] -- tool family
1403 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
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("="):
1413 if OverrideList
.get(Key
[1]) is not None:
1414 OverrideList
.pop(Key
[1])
1415 OverrideList
[Key
[1]] = Options
[Key
]
1418 # Use the highest priority value.
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]
1428 # Compare two Key, if one is included by another, choose the higher priority one
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
):
1437 if CalculatePriorityValue(NowKey
) > CalculatePriorityValue(NextKey
):
1438 if Options
.get((self
.BuildRuleFamily
, NextKey
)) is not None:
1439 Options
.pop((self
.BuildRuleFamily
, NextKey
))
1441 if Options
.get((self
.BuildRuleFamily
, NowKey
)) is not None:
1442 Options
.pop((self
.BuildRuleFamily
, NowKey
))
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
:
1450 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
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
]:
1460 elif Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
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
]
1472 # append options for the same tool except PATH
1474 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
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
:
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
:
1487 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
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
== "":
1494 # option has been added before
1495 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
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
]
1507 # append options for the same tool except PATH
1509 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
1511 BuildOptions
[Tool
][Attr
] = Options
[Key
]