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 ## hash() operator of PlatformAutoGen
138 # The platform file path and arch string will be used to represent
139 # hash value of this object
141 # @retval int Hash value of the platform file path and arch
143 @cached_class_function
145 return hash((self
.MetaFile
, self
.Arch
))
146 @cached_class_function
148 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
150 ## Create autogen code for platform and modules
152 # Since there's no autogen code for platform, this method will do nothing
153 # if CreateModuleCodeFile is set to False.
155 # @param CreateModuleCodeFile Flag indicating if creating module's
156 # autogen code file or not
158 @cached_class_function
159 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
160 # only module has code to be created, so do nothing if CreateModuleCodeFile is False
161 if not CreateModuleCodeFile
:
164 for Ma
in self
.ModuleAutoGenList
:
165 Ma
.CreateCodeFile(True)
167 ## Generate Fds Command
169 def GenFdsCommand(self
):
170 return self
.Workspace
.GenFdsCommand
172 ## Create makefile for the platform and modules in it
174 # @param CreateModuleMakeFile Flag indicating if the makefile for
175 # modules will be created as well
177 def CreateMakeFile(self
, CreateModuleMakeFile
=False, FfsCommand
= {}):
178 if CreateModuleMakeFile
:
179 for Ma
in self
._MaList
:
180 key
= (Ma
.MetaFile
.File
, self
.Arch
)
181 if key
in FfsCommand
:
182 Ma
.CreateMakeFile(True, FfsCommand
[key
])
184 Ma
.CreateMakeFile(True)
186 # no need to create makefile for the platform more than once
187 if self
.IsMakeFileCreated
:
190 # create library/module build dirs for platform
191 Makefile
= GenMake
.PlatformMakefile(self
)
192 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
193 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
195 self
.IsMakeFileCreated
= True
198 def AllPcdList(self
):
199 return self
.DynamicPcdList
+ self
.NonDynamicPcdList
200 ## Deal with Shared FixedAtBuild Pcds
202 def CollectFixedAtBuildPcds(self
):
203 for LibAuto
in self
.LibraryAutoGenList
:
204 FixedAtBuildPcds
= {}
205 ShareFixedAtBuildPcdsSameValue
= {}
206 for Module
in LibAuto
.ReferenceModules
:
207 for Pcd
in set(Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
):
208 DefaultValue
= Pcd
.DefaultValue
209 # Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib
210 if Pcd
in Module
.LibraryPcdList
:
211 Index
= Module
.LibraryPcdList
.index(Pcd
)
212 DefaultValue
= Module
.LibraryPcdList
[Index
].DefaultValue
213 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
214 if key
not in FixedAtBuildPcds
:
215 ShareFixedAtBuildPcdsSameValue
[key
] = True
216 FixedAtBuildPcds
[key
] = DefaultValue
218 if FixedAtBuildPcds
[key
] != DefaultValue
:
219 ShareFixedAtBuildPcdsSameValue
[key
] = False
220 for Pcd
in LibAuto
.FixedAtBuildPcds
:
221 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
222 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
225 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)]
226 if DscPcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
228 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
229 LibAuto
.ConstPcd
[key
] = FixedAtBuildPcds
[key
]
231 def CollectVariables(self
, DynamicPcdSet
):
234 if self
.Workspace
.FdfFile
:
235 FdDict
= self
.Workspace
.FdfProfile
.FdDict
[GlobalData
.gFdfParser
.CurrentFdName
]
236 for FdRegion
in FdDict
.RegionList
:
237 for item
in FdRegion
.RegionDataList
:
238 if self
.Platform
.VpdToolGuid
.strip() and self
.Platform
.VpdToolGuid
in item
:
239 VpdRegionSize
= FdRegion
.Size
240 VpdRegionBase
= FdRegion
.Offset
243 VariableInfo
= VariableMgr(self
.DscBuildDataObj
._GetDefaultStores
(), self
.DscBuildDataObj
.SkuIds
)
244 VariableInfo
.SetVpdRegionMaxSize(VpdRegionSize
)
245 VariableInfo
.SetVpdRegionOffset(VpdRegionBase
)
247 for Pcd
in DynamicPcdSet
:
248 pcdname
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
249 for SkuName
in Pcd
.SkuInfoList
:
250 Sku
= Pcd
.SkuInfoList
[SkuName
]
252 if SkuId
is None or SkuId
== '':
254 if len(Sku
.VariableName
) > 0:
255 if Sku
.VariableAttribute
and 'NV' not in Sku
.VariableAttribute
:
257 VariableGuidStructure
= Sku
.VariableGuidValue
258 VariableGuid
= GuidStructureStringToGuidString(VariableGuidStructure
)
259 for StorageName
in Sku
.DefaultStoreDict
:
260 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)))
264 def UpdateNVStoreMaxSize(self
, OrgVpdFile
):
265 if self
.VariableInfo
:
266 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
267 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
269 if PcdNvStoreDfBuffer
:
270 if os
.path
.exists(VpdMapFilePath
):
271 OrgVpdFile
.Read(VpdMapFilePath
)
272 PcdItems
= OrgVpdFile
.GetOffset(PcdNvStoreDfBuffer
[0])
273 NvStoreOffset
= list(PcdItems
.values())[0].strip() if PcdItems
else '0'
275 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
277 NvStoreOffset
= int(NvStoreOffset
, 16) if NvStoreOffset
.upper().startswith("0X") else int(NvStoreOffset
)
278 default_skuobj
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get(TAB_DEFAULT
)
279 maxsize
= self
.VariableInfo
.VpdRegionSize
- NvStoreOffset
if self
.VariableInfo
.VpdRegionSize
else len(default_skuobj
.DefaultValue
.split(","))
280 var_data
= self
.VariableInfo
.PatchNVStoreDefaultMaxSize(maxsize
)
282 if var_data
and default_skuobj
:
283 default_skuobj
.DefaultValue
= var_data
284 PcdNvStoreDfBuffer
[0].DefaultValue
= var_data
285 PcdNvStoreDfBuffer
[0].SkuInfoList
.clear()
286 PcdNvStoreDfBuffer
[0].SkuInfoList
[TAB_DEFAULT
] = default_skuobj
287 PcdNvStoreDfBuffer
[0].MaxDatumSize
= str(len(default_skuobj
.DefaultValue
.split(",")))
291 ## Collect dynamic PCDs
293 # Gather dynamic PCDs list from each module and their settings from platform
294 # This interface should be invoked explicitly when platform action is created.
296 def CollectPlatformDynamicPcds(self
):
298 self
.SortDynamicPcd()
300 def CategoryPcds(self
):
301 # Category Pcds into DynamicPcds and NonDynamicPcds
302 # for gathering error information
303 NoDatumTypePcdList
= set()
305 for InfName
in self
._AsBuildInfList
:
306 InfName
= mws
.join(self
.WorkspaceDir
, InfName
)
307 FdfModuleList
.append(os
.path
.normpath(InfName
))
308 for M
in self
._MbList
:
309 # F is the Module for which M is the module autogen
310 ModPcdList
= self
.ApplyPcdSetting(M
, M
.ModulePcdList
)
312 for lib
in M
.LibraryPcdList
:
313 LibPcdList
.extend(self
.ApplyPcdSetting(M
, M
.LibraryPcdList
[lib
], lib
))
314 for PcdFromModule
in ModPcdList
+ LibPcdList
:
316 # make sure that the "VOID*" kind of datum has MaxDatumSize set
317 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
318 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, M
.MetaFile
))
320 # Check the PCD from Binary INF or Source INF
321 if M
.IsBinaryModule
== True:
322 PcdFromModule
.IsFromBinaryInf
= True
324 # Check the PCD from DSC or not
325 PcdFromModule
.IsFromDsc
= (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
327 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
or PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
328 if M
.MetaFile
.Path
not in FdfModuleList
:
329 # If one of the Source built modules listed in the DSC is not listed
330 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
331 # access method (it is only listed in the DEC file that declares the
332 # PCD as PcdsDynamic), then build tool will report warning message
333 # notify the PI that they are attempting to build a module that must
334 # be included in a flash image in order to be functional. These Dynamic
335 # PCD will not be added into the Database unless it is used by other
336 # modules that are included in the FDF file.
337 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
and \
338 PcdFromModule
.IsFromBinaryInf
== False:
339 # Print warning message to let the developer make a determine.
341 # If one of the Source built modules listed in the DSC is not listed in
342 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
343 # access method (it is only listed in the DEC file that declares the
344 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
345 # PCD to the Platform's PCD Database.
346 if PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
349 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
350 # it should be stored in Pcd PEI database, If a dynamic only
351 # used by DXE module, it should be stored in DXE PCD database.
352 # The default Phase is DXE
354 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
355 PcdFromModule
.Phase
= "PEI"
356 if PcdFromModule
not in self
._DynaPcdList
_:
357 self
._DynaPcdList
_.append(PcdFromModule
)
358 elif PcdFromModule
.Phase
== 'PEI':
359 # overwrite any the same PCD existing, if Phase is PEI
360 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
361 self
._DynaPcdList
_[Index
] = PcdFromModule
362 elif PcdFromModule
not in self
._NonDynaPcdList
_:
363 self
._NonDynaPcdList
_.append(PcdFromModule
)
364 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
365 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
366 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
367 #The PCD from Binary INF will override the same one from source INF
368 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
369 PcdFromModule
.Pending
= False
370 self
._NonDynaPcdList
_.append (PcdFromModule
)
371 DscModuleSet
= {os
.path
.normpath(ModuleInf
.Path
) for ModuleInf
in self
.Platform
.Modules
}
372 # add the PCD from modules that listed in FDF but not in DSC to Database
373 for InfName
in FdfModuleList
:
374 if InfName
not in DscModuleSet
:
375 InfClass
= PathClass(InfName
)
376 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
377 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
378 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
379 # For binary module, if in current arch, we need to list the PCDs into database.
380 if not M
.IsBinaryModule
:
382 # Override the module PCD setting by platform setting
383 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
384 for PcdFromModule
in ModulePcdList
:
385 PcdFromModule
.IsFromBinaryInf
= True
386 PcdFromModule
.IsFromDsc
= False
387 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
388 if PcdFromModule
.Type
not in PCD_DYNAMIC_EX_TYPE_SET
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
389 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
391 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
392 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
393 # make sure that the "VOID*" kind of datum has MaxDatumSize set
394 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
395 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
396 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
397 PcdFromModule
.Phase
= "PEI"
398 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
399 self
._DynaPcdList
_.append(PcdFromModule
)
400 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
401 self
._NonDynaPcdList
_.append(PcdFromModule
)
402 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
403 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
404 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
405 # module & DXE module at a same time.
406 # Overwrite the type of the PCDs in source INF by the type of AsBuild
407 # INF file as DynamicEx.
408 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
409 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
410 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
411 for PcdFromModule
in self
._NonDynaPcdList
_:
412 # If a PCD is not listed in the DSC file, but binary INF files used by
413 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
414 # section, AND all source INF files used by this platform the build
415 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
416 # section, then the tools must NOT add the PCD to the Platform's PCD
417 # Database; the build must assign the access method for this PCD as
418 # PcdsPatchableInModule.
419 if PcdFromModule
not in self
._DynaPcdList
_:
421 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
422 if PcdFromModule
.IsFromDsc
== False and \
423 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
424 PcdFromModule
.IsFromBinaryInf
== True and \
425 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
426 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
427 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
429 # print out error information and break the build, if error found
430 if len(NoDatumTypePcdList
) > 0:
431 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
432 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
434 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
435 % NoDatumTypePcdListString
)
436 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
437 self
._DynamicPcdList
= self
._DynaPcdList
_
439 def SortDynamicPcd(self
):
441 # Sort dynamic PCD list to:
442 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
443 # try to be put header of dynamicd List
444 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
446 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
448 UnicodePcdArray
= set()
450 OtherPcdArray
= set()
452 VpdFile
= VpdInfoFile
.VpdInfoFile()
453 NeedProcessVpdMapFile
= False
455 for pcd
in self
.Platform
.Pcds
:
456 if pcd
not in self
._PlatformPcds
:
457 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
459 for item
in self
._PlatformPcds
:
460 if self
._PlatformPcds
[item
].DatumType
and self
._PlatformPcds
[item
].DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
461 self
._PlatformPcds
[item
].DatumType
= TAB_VOID
463 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
464 for Pcd
in self
._DynamicPcdList
:
465 # just pick the a value to determine whether is unicode string type
466 Sku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
467 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
469 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
470 Pcd
.DatumType
= TAB_VOID
472 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
473 # if found HII type PCD then insert to right of UnicodeIndex
474 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
475 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
477 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
478 PcdNvStoreDfBuffer
= VpdPcdDict
.get(("PcdNvStoreDefaultValueBuffer", "gEfiMdeModulePkgTokenSpaceGuid"))
479 if PcdNvStoreDfBuffer
:
480 self
.VariableInfo
= self
.CollectVariables(self
._DynamicPcdList
)
481 vardump
= self
.VariableInfo
.dump()
484 #According to PCD_DATABASE_INIT in edk2\MdeModulePkg\Include\Guid\PcdDataBaseSignatureGuid.h,
485 #the max size for string PCD should not exceed USHRT_MAX 65535(0xffff).
486 #typedef UINT16 SIZE_INFO;
487 #//SIZE_INFO SizeTable[];
488 if len(vardump
.split(",")) > 0xffff:
489 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(","))))
490 PcdNvStoreDfBuffer
.DefaultValue
= vardump
491 for skuname
in PcdNvStoreDfBuffer
.SkuInfoList
:
492 PcdNvStoreDfBuffer
.SkuInfoList
[skuname
].DefaultValue
= vardump
493 PcdNvStoreDfBuffer
.MaxDatumSize
= str(len(vardump
.split(",")))
495 #If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd
496 if [Pcd
for Pcd
in self
._DynamicPcdList
if Pcd
.UserDefinedDefaultStoresFlag
]:
497 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
)
498 PlatformPcds
= sorted(self
._PlatformPcds
.keys())
500 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
503 for PcdKey
in PlatformPcds
:
504 Pcd
= self
._PlatformPcds
[PcdKey
]
505 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
506 PcdKey
in VpdPcdDict
:
507 Pcd
= VpdPcdDict
[PcdKey
]
509 DefaultSku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
511 PcdValue
= DefaultSku
.DefaultValue
512 if PcdValue
not in SkuValueMap
:
513 SkuValueMap
[PcdValue
] = []
514 VpdFile
.Add(Pcd
, TAB_DEFAULT
, DefaultSku
.VpdOffset
)
515 SkuValueMap
[PcdValue
].append(DefaultSku
)
517 for (SkuName
, Sku
) in Pcd
.SkuInfoList
.items():
518 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
519 PcdValue
= Sku
.DefaultValue
521 PcdValue
= Pcd
.DefaultValue
522 if Sku
.VpdOffset
!= TAB_STAR
:
523 if PcdValue
.startswith("{"):
525 elif PcdValue
.startswith("L"):
530 VpdOffset
= int(Sku
.VpdOffset
)
533 VpdOffset
= int(Sku
.VpdOffset
, 16)
535 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
536 if VpdOffset
% Alignment
!= 0:
537 if PcdValue
.startswith("{"):
538 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
), File
=self
.MetaFile
)
540 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, Alignment
))
541 if PcdValue
not in SkuValueMap
:
542 SkuValueMap
[PcdValue
] = []
543 VpdFile
.Add(Pcd
, SkuName
, Sku
.VpdOffset
)
544 SkuValueMap
[PcdValue
].append(Sku
)
545 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
546 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== TAB_STAR
:
547 NeedProcessVpdMapFile
= True
548 if self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== '':
549 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
550 "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.")
552 VpdSkuMap
[PcdKey
] = SkuValueMap
554 # Fix the PCDs define in VPD PCD section that never referenced by module.
555 # An example is PCD for signature usage.
557 for DscPcd
in PlatformPcds
:
558 DscPcdEntry
= self
._PlatformPcds
[DscPcd
]
559 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
560 if not (self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== ''):
562 for VpdPcd
in VpdFile
._VpdArray
:
563 # This PCD has been referenced by module
564 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
565 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
568 # Not found, it should be signature
570 # just pick the a value to determine whether is unicode string type
572 SkuObjList
= list(DscPcdEntry
.SkuInfoList
.items())
573 DefaultSku
= DscPcdEntry
.SkuInfoList
.get(TAB_DEFAULT
)
575 defaultindex
= SkuObjList
.index((TAB_DEFAULT
, DefaultSku
))
576 SkuObjList
[0], SkuObjList
[defaultindex
] = SkuObjList
[defaultindex
], SkuObjList
[0]
577 for (SkuName
, Sku
) in SkuObjList
:
578 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
580 # Need to iterate DEC pcd information to get the value & datumtype
581 for eachDec
in self
.PackageList
:
582 for DecPcd
in eachDec
.Pcds
:
583 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
584 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
585 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
586 # Print warning message to let the developer make a determine.
587 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
588 File
=self
.MetaFile
, \
589 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
590 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
592 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
593 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
594 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
595 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
596 # Only fix the value while no value provided in DSC file.
597 if not Sku
.DefaultValue
:
598 DscPcdEntry
.SkuInfoList
[list(DscPcdEntry
.SkuInfoList
.keys())[0]].DefaultValue
= DecPcdEntry
.DefaultValue
600 if DscPcdEntry
not in self
._DynamicPcdList
:
601 self
._DynamicPcdList
.append(DscPcdEntry
)
602 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
603 PcdValue
= Sku
.DefaultValue
605 PcdValue
= DscPcdEntry
.DefaultValue
606 if Sku
.VpdOffset
!= TAB_STAR
:
607 if PcdValue
.startswith("{"):
609 elif PcdValue
.startswith("L"):
614 VpdOffset
= int(Sku
.VpdOffset
)
617 VpdOffset
= int(Sku
.VpdOffset
, 16)
619 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
))
620 if VpdOffset
% Alignment
!= 0:
621 if PcdValue
.startswith("{"):
622 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
), File
=self
.MetaFile
)
624 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, Alignment
))
625 if PcdValue
not in SkuValueMap
:
626 SkuValueMap
[PcdValue
] = []
627 VpdFile
.Add(DscPcdEntry
, SkuName
, Sku
.VpdOffset
)
628 SkuValueMap
[PcdValue
].append(Sku
)
629 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== TAB_STAR
:
630 NeedProcessVpdMapFile
= True
631 if DscPcdEntry
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
632 UnicodePcdArray
.add(DscPcdEntry
)
633 elif len(Sku
.VariableName
) > 0:
634 HiiPcdArray
.add(DscPcdEntry
)
636 OtherPcdArray
.add(DscPcdEntry
)
638 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
639 VpdSkuMap
[DscPcd
] = SkuValueMap
640 if (self
.Platform
.FlashDefinition
is None or self
.Platform
.FlashDefinition
== '') and \
641 VpdFile
.GetCount() != 0:
642 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
643 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
645 if VpdFile
.GetCount() != 0:
647 self
.FixVpdOffset(VpdFile
)
649 self
.FixVpdOffset(self
.UpdateNVStoreMaxSize(VpdFile
))
650 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
651 if PcdNvStoreDfBuffer
:
652 PcdName
,PcdGuid
= PcdNvStoreDfBuffer
[0].TokenCName
, PcdNvStoreDfBuffer
[0].TokenSpaceGuidCName
653 if (PcdName
,PcdGuid
) in VpdSkuMap
:
654 DefaultSku
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get(TAB_DEFAULT
)
655 VpdSkuMap
[(PcdName
,PcdGuid
)] = {DefaultSku
.DefaultValue
:[SkuObj
for SkuObj
in PcdNvStoreDfBuffer
[0].SkuInfoList
.values() ]}
657 # Process VPD map file generated by third party BPDG tool
658 if NeedProcessVpdMapFile
:
659 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
660 if os
.path
.exists(VpdMapFilePath
):
661 VpdFile
.Read(VpdMapFilePath
)
663 # Fixup TAB_STAR offset
664 for pcd
in VpdSkuMap
:
665 vpdinfo
= VpdFile
.GetVpdInfo(pcd
)
667 # just pick the a value to determine whether is unicode string type
669 for pcdvalue
in VpdSkuMap
[pcd
]:
670 for sku
in VpdSkuMap
[pcd
][pcdvalue
]:
672 if item
[2] == pcdvalue
:
673 sku
.VpdOffset
= item
[1]
675 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
677 # Delete the DynamicPcdList At the last time enter into this function
678 for Pcd
in self
._DynamicPcdList
:
679 # just pick the a value to determine whether is unicode string type
680 Sku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
681 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
683 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
684 Pcd
.DatumType
= TAB_VOID
686 PcdValue
= Sku
.DefaultValue
687 if Pcd
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
688 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
689 UnicodePcdArray
.add(Pcd
)
690 elif len(Sku
.VariableName
) > 0:
691 # if found HII type PCD then insert to right of UnicodeIndex
694 OtherPcdArray
.add(Pcd
)
695 del self
._DynamicPcdList
[:]
696 self
._DynamicPcdList
.extend(list(UnicodePcdArray
))
697 self
._DynamicPcdList
.extend(list(HiiPcdArray
))
698 self
._DynamicPcdList
.extend(list(OtherPcdArray
))
699 allskuset
= [(SkuName
, Sku
.SkuId
) for pcd
in self
._DynamicPcdList
for (SkuName
, Sku
) in pcd
.SkuInfoList
.items()]
700 for pcd
in self
._DynamicPcdList
:
701 if len(pcd
.SkuInfoList
) == 1:
702 for (SkuName
, SkuId
) in allskuset
:
703 if isinstance(SkuId
, str) and eval(SkuId
) == 0 or SkuId
== 0:
705 pcd
.SkuInfoList
[SkuName
] = copy
.deepcopy(pcd
.SkuInfoList
[TAB_DEFAULT
])
706 pcd
.SkuInfoList
[SkuName
].SkuId
= SkuId
707 pcd
.SkuInfoList
[SkuName
].SkuIdName
= SkuName
709 def FixVpdOffset(self
, VpdFile
):
710 FvPath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
711 if not os
.path
.exists(FvPath
):
715 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
717 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
719 if VpdFile
.Write(VpdFilePath
):
720 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
722 for ToolDef
in self
.ToolDefinition
.values():
723 if TAB_GUID
in ToolDef
and ToolDef
[TAB_GUID
] == self
.Platform
.VpdToolGuid
:
724 if "PATH" not in ToolDef
:
725 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
726 BPDGToolName
= ToolDef
["PATH"]
728 # Call third party GUID BPDG tool.
729 if BPDGToolName
is not None:
730 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
732 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.")
734 ## Return the platform build data object
737 return self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
739 ## Return platform name
742 return self
.Platform
.PlatformName
744 ## Return the meta file GUID
747 return self
.Platform
.Guid
749 ## Return the platform version
752 return self
.Platform
.Version
754 ## Return the FDF file name
757 if self
.Workspace
.FdfFile
:
758 RetVal
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
763 ## Return the build output directory platform specifies
766 return self
.Platform
.OutputDirectory
768 ## Return the directory to store all intermediate and final files built
771 if os
.path
.isabs(self
.OutputDir
):
772 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
773 path
.abspath(self
.OutputDir
),
774 self
.BuildTarget
+ "_" + self
.ToolChain
,
777 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
780 self
.BuildTarget
+ "_" + self
.ToolChain
,
784 ## Return directory of platform makefile
786 # @retval string Makefile directory
789 def MakeFileDir(self
):
790 return path
.join(self
.BuildDir
, self
.Arch
)
792 ## Return build command string
794 # @retval string Build command string
797 def BuildCommand(self
):
799 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
800 RetVal
+= _SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
801 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
802 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
804 RetVal
+= _SplitOption(NewOption
)
805 if "MAKE" in self
.EdkIIBuildOption
:
806 if "FLAGS" in self
.EdkIIBuildOption
["MAKE"]:
807 Flags
= self
.EdkIIBuildOption
["MAKE"]["FLAGS"]
808 if Flags
.startswith('='):
809 RetVal
= [RetVal
[0]] + [Flags
[1:]]
814 ## Get tool chain definition
816 # Get each tool definition for given tool chain from tools_def.txt and platform
819 def ToolDefinition(self
):
820 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
821 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
822 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
823 ExtraData
="[%s]" % self
.MetaFile
)
824 RetVal
= OrderedDict()
826 for Def
in ToolDefinition
:
827 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
828 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
831 Value
= ToolDefinition
[Def
]
832 # don't record the DLL
834 DllPathList
.add(Value
)
837 if Tool
not in RetVal
:
838 RetVal
[Tool
] = OrderedDict()
839 RetVal
[Tool
][Attr
] = Value
842 if GlobalData
.gOptions
.SilentMode
and "MAKE" in RetVal
:
843 if "FLAGS" not in RetVal
["MAKE"]:
844 RetVal
["MAKE"]["FLAGS"] = ""
845 RetVal
["MAKE"]["FLAGS"] += " -s"
848 for Attr
in RetVal
[Tool
]:
849 Value
= RetVal
[Tool
][Attr
]
850 if Tool
in self
._BuildOptionWithToolDef
(RetVal
) and Attr
in self
._BuildOptionWithToolDef
(RetVal
)[Tool
]:
851 # check if override is indicated
852 if self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
].startswith('='):
853 Value
= self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
][1:]
856 Value
+= " " + self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
858 Value
= self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
861 # Don't put MAKE definition in the file
863 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
865 # Don't put MAKE definition in the file
870 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
873 tool_def_file
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
874 SaveFileOnChange(tool_def_file
, ToolsDef
, False)
875 for DllPath
in DllPathList
:
876 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
877 os
.environ
["MAKE_FLAGS"] = MakeFlags
881 ## Return the paths of tools
883 def ToolDefinitionFile(self
):
884 tool_def_file
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
885 if not os
.path
.exists(tool_def_file
):
889 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
891 def ToolChainFamily(self
):
892 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
893 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
894 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
895 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
896 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
898 RetVal
= TAB_COMPILER_MSFT
900 RetVal
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
904 def BuildRuleFamily(self
):
905 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
906 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
907 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
908 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
909 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
911 return TAB_COMPILER_MSFT
913 return ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
915 ## Return the build options specific for all modules in this platform
917 def BuildOption(self
):
918 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
920 def _BuildOptionWithToolDef(self
, ToolDef
):
921 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, ToolDef
=ToolDef
)
923 ## Return the build options specific for EDK modules in this platform
925 def EdkBuildOption(self
):
926 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
928 ## Return the build options specific for EDKII modules in this platform
930 def EdkIIBuildOption(self
):
931 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
933 ## Parse build_rule.txt in Conf Directory.
935 # @retval BuildRule object
940 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
941 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
942 if not BuildRuleFile
:
943 BuildRuleFile
= gDefaultBuildRuleFile
944 RetVal
= BuildRule(BuildRuleFile
)
945 if RetVal
._FileVersion
== "":
946 RetVal
._FileVersion
= AutoGenReqBuildRuleVerNum
948 if RetVal
._FileVersion
< AutoGenReqBuildRuleVerNum
:
949 # If Build Rule's version is less than the version number required by the tools, halting the build.
950 EdkLogger
.error("build", AUTOGEN_ERROR
,
951 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])"\
952 % (RetVal
._FileVersion
, AutoGenReqBuildRuleVerNum
))
955 ## Summarize the packages used by modules in this platform
957 def PackageList(self
):
959 for Mb
in self
._MbList
:
960 RetVal
.update(Mb
.Packages
)
961 for lb
in Mb
.LibInstances
:
962 RetVal
.update(lb
.Packages
)
963 #Collect package set information from INF of FDF
964 for ModuleFile
in self
._AsBuildModuleList
:
965 if ModuleFile
in self
.Platform
.Modules
:
967 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
968 RetVal
.update(ModuleData
.Packages
)
972 def NonDynamicPcdDict(self
):
973 return {(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
):Pcd
for Pcd
in self
.NonDynamicPcdList
}
975 ## Get list of non-dynamic PCDs
977 def NonDynamicPcdList(self
):
978 if not self
._NonDynamicPcdList
:
979 self
.CollectPlatformDynamicPcds()
980 return self
._NonDynamicPcdList
982 ## Get list of dynamic PCDs
984 def DynamicPcdList(self
):
985 if not self
._DynamicPcdList
:
986 self
.CollectPlatformDynamicPcds()
987 return self
._DynamicPcdList
989 ## Generate Token Number for all PCD
991 def PcdTokenNumber(self
):
992 RetVal
= OrderedDict()
995 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
1001 # TokeNumber 11 ~ 20
1003 for Pcd
in self
.DynamicPcdList
:
1004 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
1005 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1006 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1009 for Pcd
in self
.DynamicPcdList
:
1010 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_EX_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
== "DXE" 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
== "DXE" 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
.NonDynamicPcdList
:
1028 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1034 return [self
.BuildDatabase
[m
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
] for m
in self
.Platform
.Modules
]
1038 for ModuleFile
in self
.Platform
.Modules
:
1048 self
.Platform
.Modules
[ModuleFile
].M
= Ma
1049 return [x
.M
for x
in self
.Platform
.Modules
.values()]
1051 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
1053 def ModuleAutoGenList(self
):
1055 for Ma
in self
._MaList
:
1056 if Ma
not in RetVal
:
1060 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
1062 def LibraryAutoGenList(self
):
1064 for Ma
in self
._MaList
:
1065 for La
in Ma
.LibraryAutoGenList
:
1066 if La
not in RetVal
:
1068 if Ma
not in La
.ReferenceModules
:
1069 La
.ReferenceModules
.append(Ma
)
1072 ## Test if a module is supported by the platform
1074 # An error will be raised directly if the module or its arch is not supported
1075 # by the platform or current configuration
1077 def ValidModule(self
, Module
):
1078 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
1079 or Module
in self
._AsBuildModuleList
1081 def GetAllModuleInfo(self
,WithoutPcd
=True):
1083 for m
in self
.Platform
.Modules
:
1084 module_obj
= self
.BuildDatabase
[m
,self
.Arch
,self
.BuildTarget
,self
.ToolChain
]
1085 if not bool(module_obj
.LibraryClass
):
1086 Libs
= GetModuleLibInstances(module_obj
, self
.Platform
, self
.BuildDatabase
, self
.Arch
,self
.BuildTarget
,self
.ToolChain
)
1089 ModuleLibs
.update( set([(l
.MetaFile
.File
,l
.MetaFile
.Root
,l
.Arch
,True) for l
in Libs
]))
1090 if WithoutPcd
and module_obj
.PcdIsDriver
:
1092 ModuleLibs
.add((m
.File
,m
.Root
,module_obj
.Arch
,False))
1096 ## Resolve the library classes in a module to library instances
1098 # This method will not only resolve library classes but also sort the library
1099 # instances according to the dependency-ship.
1101 # @param Module The module from which the library classes will be resolved
1103 # @retval library_list List of library instances sorted
1105 def ApplyLibraryInstance(self
, Module
):
1106 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
1107 if str(Module
) not in self
.Platform
.Modules
:
1110 return GetModuleLibInstances(Module
,
1119 ## Override PCD setting (type, value, ...)
1121 # @param ToPcd The PCD to be overridden
1122 # @param FromPcd The PCD overriding from
1124 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
="", Msg
="", Library
=""):
1126 # in case there's PCDs coming from FDF file, which have no type given.
1127 # at this point, ToPcd.Type has the type found from dependent
1130 TokenCName
= ToPcd
.TokenCName
1131 for PcdItem
in GlobalData
.MixedPcd
:
1132 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
1133 TokenCName
= PcdItem
[0]
1135 if FromPcd
is not None:
1136 if ToPcd
.Pending
and FromPcd
.Type
:
1137 ToPcd
.Type
= FromPcd
.Type
1138 elif ToPcd
.Type
and FromPcd
.Type\
1139 and ToPcd
.Type
!= FromPcd
.Type
and ToPcd
.Type
in FromPcd
.Type
:
1140 if ToPcd
.Type
.strip() == TAB_PCDS_DYNAMIC_EX
:
1141 ToPcd
.Type
= FromPcd
.Type
1142 elif ToPcd
.Type
and FromPcd
.Type \
1143 and ToPcd
.Type
!= FromPcd
.Type
:
1145 Module
= str(Module
) + " 's library file (" + str(Library
) + ")"
1146 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
1147 ExtraData
="%s.%s is used as [%s] in module %s, but as [%s] in %s."\
1148 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
1149 ToPcd
.Type
, Module
, FromPcd
.Type
, Msg
),
1152 if FromPcd
.MaxDatumSize
:
1153 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
1154 ToPcd
.MaxSizeUserSet
= FromPcd
.MaxDatumSize
1155 if FromPcd
.DefaultValue
:
1156 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
1157 if FromPcd
.TokenValue
:
1158 ToPcd
.TokenValue
= FromPcd
.TokenValue
1159 if FromPcd
.DatumType
:
1160 ToPcd
.DatumType
= FromPcd
.DatumType
1161 if FromPcd
.SkuInfoList
:
1162 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
1163 if FromPcd
.UserDefinedDefaultStoresFlag
:
1164 ToPcd
.UserDefinedDefaultStoresFlag
= FromPcd
.UserDefinedDefaultStoresFlag
1165 # Add Flexible PCD format parse
1166 if ToPcd
.DefaultValue
:
1168 ToPcd
.DefaultValue
= ValueExpressionEx(ToPcd
.DefaultValue
, ToPcd
.DatumType
, self
.Platform
._GuidDict
)(True)
1169 except BadExpression
as Value
:
1170 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
, ToPcd
.DefaultValue
, Value
),
1173 # check the validation of datum
1174 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
1176 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
1177 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
1178 ToPcd
.validateranges
= FromPcd
.validateranges
1179 ToPcd
.validlists
= FromPcd
.validlists
1180 ToPcd
.expressions
= FromPcd
.expressions
1181 ToPcd
.CustomAttribute
= FromPcd
.CustomAttribute
1183 if FromPcd
is not None and ToPcd
.DatumType
== TAB_VOID
and not ToPcd
.MaxDatumSize
:
1184 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
1185 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
1186 Value
= ToPcd
.DefaultValue
1188 ToPcd
.MaxDatumSize
= '1'
1189 elif Value
[0] == 'L':
1190 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
1191 elif Value
[0] == '{':
1192 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
1194 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
1196 # apply default SKU for dynamic PCDS if specified one is not available
1197 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_SET
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
) \
1198 and not ToPcd
.SkuInfoList
:
1199 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
1200 SkuName
= self
.Platform
.SkuName
1202 SkuName
= TAB_DEFAULT
1203 ToPcd
.SkuInfoList
= {
1204 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
][0], '', '', '', '', '', ToPcd
.DefaultValue
)
1207 ## Apply PCD setting defined platform to a module
1209 # @param Module The module from which the PCD setting will be overridden
1211 # @retval PCD_list The list PCDs with settings from platform
1213 def ApplyPcdSetting(self
, Module
, Pcds
, Library
=""):
1214 # for each PCD in module
1215 for Name
, Guid
in Pcds
:
1216 PcdInModule
= Pcds
[Name
, Guid
]
1217 # find out the PCD setting in platform
1218 if (Name
, Guid
) in self
.Platform
.Pcds
:
1219 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
1221 PcdInPlatform
= None
1222 # then override the settings if any
1223 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
, Msg
="DSC PCD sections", Library
=Library
)
1224 # resolve the VariableGuid value
1225 for SkuId
in PcdInModule
.SkuInfoList
:
1226 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
1227 if Sku
.VariableGuid
== '': continue
1228 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
1229 if Sku
.VariableGuidValue
is None:
1230 PackageList
= "\n\t".join(str(P
) for P
in self
.PackageList
)
1233 RESOURCE_NOT_AVAILABLE
,
1234 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
1235 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
1236 % (Guid
, Name
, str(Module
)),
1240 # override PCD settings with module specific setting
1241 if Module
in self
.Platform
.Modules
:
1242 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1243 for Key
in PlatformModule
.Pcds
:
1244 if GlobalData
.BuildOptionPcd
:
1245 for pcd
in GlobalData
.BuildOptionPcd
:
1246 (TokenSpaceGuidCName
, TokenCName
, FieldName
, pcdvalue
, _
) = pcd
1247 if (TokenCName
, TokenSpaceGuidCName
) == Key
and FieldName
=="":
1248 PlatformModule
.Pcds
[Key
].DefaultValue
= pcdvalue
1249 PlatformModule
.Pcds
[Key
].PcdValueFromComm
= pcdvalue
1255 elif Key
in GlobalData
.MixedPcd
:
1256 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
1258 ToPcd
= Pcds
[PcdItem
]
1262 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
, Msg
="DSC Components Module scoped PCD section", Library
=Library
)
1263 # use PCD value to calculate the MaxDatumSize when it is not specified
1264 for Name
, Guid
in Pcds
:
1265 Pcd
= Pcds
[Name
, Guid
]
1266 if Pcd
.DatumType
== TAB_VOID
and not Pcd
.MaxDatumSize
:
1267 Pcd
.MaxSizeUserSet
= None
1268 Value
= Pcd
.DefaultValue
1270 Pcd
.MaxDatumSize
= '1'
1271 elif Value
[0] == 'L':
1272 Pcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
1273 elif Value
[0] == '{':
1274 Pcd
.MaxDatumSize
= str(len(Value
.split(',')))
1276 Pcd
.MaxDatumSize
= str(len(Value
) - 1)
1277 return list(Pcds
.values())
1279 ## Append build options in platform to a module
1281 # @param Module The module to which the build options will be appended
1283 # @retval options The options appended with build options in platform
1285 def ApplyBuildOption(self
, Module
):
1286 # Get the different options for the different style module
1287 PlatformOptions
= self
.EdkIIBuildOption
1288 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
1289 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
1290 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
1291 if Module
in self
.Platform
.Modules
:
1292 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1293 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
1295 PlatformModuleOptions
= {}
1297 BuildRuleOrder
= None
1298 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
1299 for Tool
in Options
:
1300 for Attr
in Options
[Tool
]:
1301 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
1302 BuildRuleOrder
= Options
[Tool
][Attr
]
1304 AllTools
= set(list(ModuleOptions
.keys()) + list(PlatformOptions
.keys()) +
1305 list(PlatformModuleOptions
.keys()) + list(ModuleTypeOptions
.keys()) +
1306 list(self
.ToolDefinition
.keys()))
1307 BuildOptions
= defaultdict(lambda: defaultdict(str))
1308 for Tool
in AllTools
:
1309 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
1310 if Tool
not in Options
:
1312 for Attr
in Options
[Tool
]:
1314 # Do not generate it in Makefile
1316 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
1318 Value
= Options
[Tool
][Attr
]
1319 # check if override is indicated
1320 if Value
.startswith('='):
1321 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
[1:])
1324 BuildOptions
[Tool
][Attr
] += " " + mws
.handleWsMacro(Value
)
1326 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
)
1328 return BuildOptions
, BuildRuleOrder
1331 def GetGlobalBuildOptions(self
,Module
):
1332 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
1333 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
1335 if Module
in self
.Platform
.Modules
:
1336 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1337 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
1339 PlatformModuleOptions
= {}
1341 return ModuleTypeOptions
,PlatformModuleOptions
1342 def ModuleGuid(self
,Module
):
1343 if os
.path
.basename(Module
.MetaFile
.File
) != os
.path
.basename(Module
.MetaFile
.Path
):
1345 # Length of GUID is 36
1347 return os
.path
.basename(Module
.MetaFile
.Path
)[:36]
1350 def UniqueBaseName(self
):
1354 for Module
in self
._MbList
:
1355 unique_base_name
= '%s_%s' % (Module
.BaseName
,self
.ModuleGuid(Module
))
1356 if unique_base_name
not in ModuleNameDict
:
1357 ModuleNameDict
[unique_base_name
] = []
1358 ModuleNameDict
[unique_base_name
].append(Module
.MetaFile
)
1359 if Module
.BaseName
not in UniqueName
:
1360 UniqueName
[Module
.BaseName
] = set()
1361 UniqueName
[Module
.BaseName
].add((self
.ModuleGuid(Module
),Module
.MetaFile
))
1362 for module_paths
in ModuleNameDict
.values():
1363 if len(module_paths
) > 1 and len(set(module_paths
))>1:
1364 samemodules
= list(set(module_paths
))
1365 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
1366 ' %s\n %s' % (samemodules
[0], samemodules
[1]))
1367 for name
in UniqueName
:
1368 Guid_Path
= UniqueName
[name
]
1369 if len(Guid_Path
) > 1:
1370 retVal
[name
] = '%s_%s' % (name
,Guid_Path
.pop()[0])
1372 ## Expand * in build option key
1374 # @param Options Options to be expanded
1375 # @param ToolDef Use specified ToolDef instead of full version.
1376 # This is needed during initialization to prevent
1377 # infinite recursion betweeh BuildOptions,
1378 # ToolDefinition, and this function.
1380 # @retval options Options expanded
1382 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None, ToolDef
=None):
1384 ToolDef
= self
.ToolDefinition
1391 # Construct a list contain the build options which need override.
1395 # Key[0] -- tool family
1396 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1398 if (Key
[0] == self
.BuildRuleFamily
and
1399 (ModuleStyle
is None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
1400 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
1401 if (Target
== self
.BuildTarget
or Target
== TAB_STAR
) and\
1402 (ToolChain
== self
.ToolChain
or ToolChain
== TAB_STAR
) and\
1403 (Arch
== self
.Arch
or Arch
== TAB_STAR
) and\
1404 Options
[Key
].startswith("="):
1406 if OverrideList
.get(Key
[1]) is not None:
1407 OverrideList
.pop(Key
[1])
1408 OverrideList
[Key
[1]] = Options
[Key
]
1411 # Use the highest priority value.
1413 if (len(OverrideList
) >= 2):
1414 KeyList
= list(OverrideList
.keys())
1415 for Index
in range(len(KeyList
)):
1416 NowKey
= KeyList
[Index
]
1417 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
1418 for Index1
in range(len(KeyList
) - Index
- 1):
1419 NextKey
= KeyList
[Index1
+ Index
+ 1]
1421 # Compare two Key, if one is included by another, choose the higher priority one
1423 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
1424 if (Target1
== Target2
or Target1
== TAB_STAR
or Target2
== TAB_STAR
) and\
1425 (ToolChain1
== ToolChain2
or ToolChain1
== TAB_STAR
or ToolChain2
== TAB_STAR
) and\
1426 (Arch1
== Arch2
or Arch1
== TAB_STAR
or Arch2
== TAB_STAR
) and\
1427 (CommandType1
== CommandType2
or CommandType1
== TAB_STAR
or CommandType2
== TAB_STAR
) and\
1428 (Attr1
== Attr2
or Attr1
== TAB_STAR
or Attr2
== TAB_STAR
):
1430 if CalculatePriorityValue(NowKey
) > CalculatePriorityValue(NextKey
):
1431 if Options
.get((self
.BuildRuleFamily
, NextKey
)) is not None:
1432 Options
.pop((self
.BuildRuleFamily
, NextKey
))
1434 if Options
.get((self
.BuildRuleFamily
, NowKey
)) is not None:
1435 Options
.pop((self
.BuildRuleFamily
, NowKey
))
1438 if ModuleStyle
is not None and len (Key
) > 2:
1439 # Check Module style is EDK or EDKII.
1440 # Only append build option for the matched style module.
1441 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
1443 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
1446 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
1447 # if tool chain family doesn't match, skip it
1448 if Tool
in ToolDef
and Family
!= "":
1449 FamilyIsNull
= False
1450 if ToolDef
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
1451 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
1453 elif Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
1456 # expand any wildcard
1457 if Target
== TAB_STAR
or Target
== self
.BuildTarget
:
1458 if Tag
== TAB_STAR
or Tag
== self
.ToolChain
:
1459 if Arch
== TAB_STAR
or Arch
== self
.Arch
:
1460 if Tool
not in BuildOptions
:
1461 BuildOptions
[Tool
] = {}
1462 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
1463 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1465 # append options for the same tool except PATH
1467 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
1469 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1470 # Build Option Family has been checked, which need't to be checked again for family.
1471 if FamilyMatch
or FamilyIsNull
:
1475 if ModuleStyle
is not None and len (Key
) > 2:
1476 # Check Module style is EDK or EDKII.
1477 # Only append build option for the matched style module.
1478 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
1480 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
1483 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
1484 # if tool chain family doesn't match, skip it
1485 if Tool
not in ToolDef
or Family
== "":
1487 # option has been added before
1488 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
1491 # expand any wildcard
1492 if Target
== TAB_STAR
or Target
== self
.BuildTarget
:
1493 if Tag
== TAB_STAR
or Tag
== self
.ToolChain
:
1494 if Arch
== TAB_STAR
or Arch
== self
.Arch
:
1495 if Tool
not in BuildOptions
:
1496 BuildOptions
[Tool
] = {}
1497 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
1498 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1500 # append options for the same tool except PATH
1502 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
1504 BuildOptions
[Tool
][Attr
] = Options
[Key
]