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
)
191 self
.CreateLibModuelDirs()
193 def CreateLibModuelDirs(self
):
194 # no need to create makefile for the platform more than once
195 if self
.IsMakeFileCreated
:
198 # create library/module build dirs for platform
199 Makefile
= GenMake
.PlatformMakefile(self
)
200 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
201 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
203 self
.IsMakeFileCreated
= True
206 def AllPcdList(self
):
207 return self
.DynamicPcdList
+ self
.NonDynamicPcdList
208 ## Deal with Shared FixedAtBuild Pcds
210 def CollectFixedAtBuildPcds(self
):
211 for LibAuto
in self
.LibraryAutoGenList
:
212 FixedAtBuildPcds
= {}
213 ShareFixedAtBuildPcdsSameValue
= {}
214 for Module
in LibAuto
.ReferenceModules
:
215 for Pcd
in set(Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
):
216 DefaultValue
= Pcd
.DefaultValue
217 # Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib
218 if Pcd
in Module
.LibraryPcdList
:
219 Index
= Module
.LibraryPcdList
.index(Pcd
)
220 DefaultValue
= Module
.LibraryPcdList
[Index
].DefaultValue
221 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
222 if key
not in FixedAtBuildPcds
:
223 ShareFixedAtBuildPcdsSameValue
[key
] = True
224 FixedAtBuildPcds
[key
] = DefaultValue
226 if FixedAtBuildPcds
[key
] != DefaultValue
:
227 ShareFixedAtBuildPcdsSameValue
[key
] = False
228 for Pcd
in LibAuto
.FixedAtBuildPcds
:
229 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
230 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
233 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)]
234 if DscPcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
236 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
237 LibAuto
.ConstPcd
[key
] = FixedAtBuildPcds
[key
]
239 def CollectVariables(self
, DynamicPcdSet
):
242 if self
.Workspace
.FdfFile
:
243 FdDict
= self
.Workspace
.FdfProfile
.FdDict
[GlobalData
.gFdfParser
.CurrentFdName
]
244 for FdRegion
in FdDict
.RegionList
:
245 for item
in FdRegion
.RegionDataList
:
246 if self
.Platform
.VpdToolGuid
.strip() and self
.Platform
.VpdToolGuid
in item
:
247 VpdRegionSize
= FdRegion
.Size
248 VpdRegionBase
= FdRegion
.Offset
251 VariableInfo
= VariableMgr(self
.DscBuildDataObj
._GetDefaultStores
(), self
.DscBuildDataObj
.SkuIds
)
252 VariableInfo
.SetVpdRegionMaxSize(VpdRegionSize
)
253 VariableInfo
.SetVpdRegionOffset(VpdRegionBase
)
255 for Pcd
in DynamicPcdSet
:
256 pcdname
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
257 for SkuName
in Pcd
.SkuInfoList
:
258 Sku
= Pcd
.SkuInfoList
[SkuName
]
260 if SkuId
is None or SkuId
== '':
262 if len(Sku
.VariableName
) > 0:
263 if Sku
.VariableAttribute
and 'NV' not in Sku
.VariableAttribute
:
265 VariableGuidStructure
= Sku
.VariableGuidValue
266 VariableGuid
= GuidStructureStringToGuidString(VariableGuidStructure
)
267 for StorageName
in Sku
.DefaultStoreDict
:
268 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)))
272 def UpdateNVStoreMaxSize(self
, OrgVpdFile
):
273 if self
.VariableInfo
:
274 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
275 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
277 if PcdNvStoreDfBuffer
:
278 if os
.path
.exists(VpdMapFilePath
):
279 OrgVpdFile
.Read(VpdMapFilePath
)
280 PcdItems
= OrgVpdFile
.GetOffset(PcdNvStoreDfBuffer
[0])
281 NvStoreOffset
= list(PcdItems
.values())[0].strip() if PcdItems
else '0'
283 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
285 NvStoreOffset
= int(NvStoreOffset
, 16) if NvStoreOffset
.upper().startswith("0X") else int(NvStoreOffset
)
286 default_skuobj
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get(TAB_DEFAULT
)
287 maxsize
= self
.VariableInfo
.VpdRegionSize
- NvStoreOffset
if self
.VariableInfo
.VpdRegionSize
else len(default_skuobj
.DefaultValue
.split(","))
288 var_data
= self
.VariableInfo
.PatchNVStoreDefaultMaxSize(maxsize
)
290 if var_data
and default_skuobj
:
291 default_skuobj
.DefaultValue
= var_data
292 PcdNvStoreDfBuffer
[0].DefaultValue
= var_data
293 PcdNvStoreDfBuffer
[0].SkuInfoList
.clear()
294 PcdNvStoreDfBuffer
[0].SkuInfoList
[TAB_DEFAULT
] = default_skuobj
295 PcdNvStoreDfBuffer
[0].MaxDatumSize
= str(len(default_skuobj
.DefaultValue
.split(",")))
299 ## Collect dynamic PCDs
301 # Gather dynamic PCDs list from each module and their settings from platform
302 # This interface should be invoked explicitly when platform action is created.
304 def CollectPlatformDynamicPcds(self
):
306 self
.SortDynamicPcd()
308 def CategoryPcds(self
):
309 # Category Pcds into DynamicPcds and NonDynamicPcds
310 # for gathering error information
311 NoDatumTypePcdList
= set()
313 for InfName
in self
._AsBuildInfList
:
314 InfName
= mws
.join(self
.WorkspaceDir
, InfName
)
315 FdfModuleList
.append(os
.path
.normpath(InfName
))
316 for M
in self
._MbList
:
317 # F is the Module for which M is the module autogen
318 ModPcdList
= self
.ApplyPcdSetting(M
, M
.ModulePcdList
)
320 for lib
in M
.LibraryPcdList
:
321 LibPcdList
.extend(self
.ApplyPcdSetting(M
, M
.LibraryPcdList
[lib
], lib
))
322 for PcdFromModule
in ModPcdList
+ LibPcdList
:
324 # make sure that the "VOID*" kind of datum has MaxDatumSize set
325 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
326 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, M
.MetaFile
))
328 # Check the PCD from Binary INF or Source INF
329 if M
.IsBinaryModule
== True:
330 PcdFromModule
.IsFromBinaryInf
= True
332 # Check the PCD from DSC or not
333 PcdFromModule
.IsFromDsc
= (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
335 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
or PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
336 if M
.MetaFile
.Path
not in FdfModuleList
:
337 # If one of the Source built modules listed in the DSC is not listed
338 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
339 # access method (it is only listed in the DEC file that declares the
340 # PCD as PcdsDynamic), then build tool will report warning message
341 # notify the PI that they are attempting to build a module that must
342 # be included in a flash image in order to be functional. These Dynamic
343 # PCD will not be added into the Database unless it is used by other
344 # modules that are included in the FDF file.
345 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
and \
346 PcdFromModule
.IsFromBinaryInf
== False:
347 # Print warning message to let the developer make a determine.
349 # If one of the Source built modules listed in the DSC is not listed in
350 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
351 # access method (it is only listed in the DEC file that declares the
352 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
353 # PCD to the Platform's PCD Database.
354 if PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
357 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
358 # it should be stored in Pcd PEI database, If a dynamic only
359 # used by DXE module, it should be stored in DXE PCD database.
360 # The default Phase is DXE
362 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
363 PcdFromModule
.Phase
= "PEI"
364 if PcdFromModule
not in self
._DynaPcdList
_:
365 self
._DynaPcdList
_.append(PcdFromModule
)
366 elif PcdFromModule
.Phase
== 'PEI':
367 # overwrite any the same PCD existing, if Phase is PEI
368 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
369 self
._DynaPcdList
_[Index
] = PcdFromModule
370 elif PcdFromModule
not in self
._NonDynaPcdList
_:
371 self
._NonDynaPcdList
_.append(PcdFromModule
)
372 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
373 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
374 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
375 #The PCD from Binary INF will override the same one from source INF
376 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
377 PcdFromModule
.Pending
= False
378 self
._NonDynaPcdList
_.append (PcdFromModule
)
379 DscModuleSet
= {os
.path
.normpath(ModuleInf
.Path
) for ModuleInf
in self
.Platform
.Modules
}
380 # add the PCD from modules that listed in FDF but not in DSC to Database
381 for InfName
in FdfModuleList
:
382 if InfName
not in DscModuleSet
:
383 InfClass
= PathClass(InfName
)
384 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
385 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
386 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
387 # For binary module, if in current arch, we need to list the PCDs into database.
388 if not M
.IsBinaryModule
:
390 # Override the module PCD setting by platform setting
391 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
392 for PcdFromModule
in ModulePcdList
:
393 PcdFromModule
.IsFromBinaryInf
= True
394 PcdFromModule
.IsFromDsc
= False
395 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
396 if PcdFromModule
.Type
not in PCD_DYNAMIC_EX_TYPE_SET
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
397 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
399 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
400 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
401 # make sure that the "VOID*" kind of datum has MaxDatumSize set
402 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
403 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
404 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
405 PcdFromModule
.Phase
= "PEI"
406 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
407 self
._DynaPcdList
_.append(PcdFromModule
)
408 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
409 self
._NonDynaPcdList
_.append(PcdFromModule
)
410 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
411 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
412 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
413 # module & DXE module at a same time.
414 # Overwrite the type of the PCDs in source INF by the type of AsBuild
415 # INF file as DynamicEx.
416 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
417 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
418 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
419 for PcdFromModule
in self
._NonDynaPcdList
_:
420 # If a PCD is not listed in the DSC file, but binary INF files used by
421 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
422 # section, AND all source INF files used by this platform the build
423 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
424 # section, then the tools must NOT add the PCD to the Platform's PCD
425 # Database; the build must assign the access method for this PCD as
426 # PcdsPatchableInModule.
427 if PcdFromModule
not in self
._DynaPcdList
_:
429 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
430 if PcdFromModule
.IsFromDsc
== False and \
431 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
432 PcdFromModule
.IsFromBinaryInf
== True and \
433 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
434 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
435 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
437 # print out error information and break the build, if error found
438 if len(NoDatumTypePcdList
) > 0:
439 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
440 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
442 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
443 % NoDatumTypePcdListString
)
444 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
445 self
._DynamicPcdList
= self
._DynaPcdList
_
447 def SortDynamicPcd(self
):
449 # Sort dynamic PCD list to:
450 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
451 # try to be put header of dynamicd List
452 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
454 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
456 UnicodePcdArray
= set()
458 OtherPcdArray
= set()
460 VpdFile
= VpdInfoFile
.VpdInfoFile()
461 NeedProcessVpdMapFile
= False
463 for pcd
in self
.Platform
.Pcds
:
464 if pcd
not in self
._PlatformPcds
:
465 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
467 for item
in self
._PlatformPcds
:
468 if self
._PlatformPcds
[item
].DatumType
and self
._PlatformPcds
[item
].DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
469 self
._PlatformPcds
[item
].DatumType
= TAB_VOID
471 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
472 for Pcd
in self
._DynamicPcdList
:
473 # just pick the a value to determine whether is unicode string type
474 Sku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
475 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
477 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
478 Pcd
.DatumType
= TAB_VOID
480 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
481 # if found HII type PCD then insert to right of UnicodeIndex
482 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
483 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
485 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
486 PcdNvStoreDfBuffer
= VpdPcdDict
.get(("PcdNvStoreDefaultValueBuffer", "gEfiMdeModulePkgTokenSpaceGuid"))
487 if PcdNvStoreDfBuffer
:
488 self
.VariableInfo
= self
.CollectVariables(self
._DynamicPcdList
)
489 vardump
= self
.VariableInfo
.dump()
492 #According to PCD_DATABASE_INIT in edk2\MdeModulePkg\Include\Guid\PcdDataBaseSignatureGuid.h,
493 #the max size for string PCD should not exceed USHRT_MAX 65535(0xffff).
494 #typedef UINT16 SIZE_INFO;
495 #//SIZE_INFO SizeTable[];
496 if len(vardump
.split(",")) > 0xffff:
497 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(","))))
498 PcdNvStoreDfBuffer
.DefaultValue
= vardump
499 for skuname
in PcdNvStoreDfBuffer
.SkuInfoList
:
500 PcdNvStoreDfBuffer
.SkuInfoList
[skuname
].DefaultValue
= vardump
501 PcdNvStoreDfBuffer
.MaxDatumSize
= str(len(vardump
.split(",")))
503 #If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd
504 if [Pcd
for Pcd
in self
._DynamicPcdList
if Pcd
.UserDefinedDefaultStoresFlag
]:
505 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
)
506 PlatformPcds
= sorted(self
._PlatformPcds
.keys())
508 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
511 for PcdKey
in PlatformPcds
:
512 Pcd
= self
._PlatformPcds
[PcdKey
]
513 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
514 PcdKey
in VpdPcdDict
:
515 Pcd
= VpdPcdDict
[PcdKey
]
517 DefaultSku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
519 PcdValue
= DefaultSku
.DefaultValue
520 if PcdValue
not in SkuValueMap
:
521 SkuValueMap
[PcdValue
] = []
522 VpdFile
.Add(Pcd
, TAB_DEFAULT
, DefaultSku
.VpdOffset
)
523 SkuValueMap
[PcdValue
].append(DefaultSku
)
525 for (SkuName
, Sku
) in Pcd
.SkuInfoList
.items():
526 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
527 PcdValue
= Sku
.DefaultValue
529 PcdValue
= Pcd
.DefaultValue
530 if Sku
.VpdOffset
!= TAB_STAR
:
531 if PcdValue
.startswith("{"):
533 elif PcdValue
.startswith("L"):
538 VpdOffset
= int(Sku
.VpdOffset
)
541 VpdOffset
= int(Sku
.VpdOffset
, 16)
543 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
544 if VpdOffset
% Alignment
!= 0:
545 if PcdValue
.startswith("{"):
546 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
), File
=self
.MetaFile
)
548 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, Alignment
))
549 if PcdValue
not in SkuValueMap
:
550 SkuValueMap
[PcdValue
] = []
551 VpdFile
.Add(Pcd
, SkuName
, Sku
.VpdOffset
)
552 SkuValueMap
[PcdValue
].append(Sku
)
553 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
554 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== TAB_STAR
:
555 NeedProcessVpdMapFile
= True
556 if self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== '':
557 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
558 "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.")
560 VpdSkuMap
[PcdKey
] = SkuValueMap
562 # Fix the PCDs define in VPD PCD section that never referenced by module.
563 # An example is PCD for signature usage.
565 for DscPcd
in PlatformPcds
:
566 DscPcdEntry
= self
._PlatformPcds
[DscPcd
]
567 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
568 if not (self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== ''):
570 for VpdPcd
in VpdFile
._VpdArray
:
571 # This PCD has been referenced by module
572 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
573 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
576 # Not found, it should be signature
578 # just pick the a value to determine whether is unicode string type
580 SkuObjList
= list(DscPcdEntry
.SkuInfoList
.items())
581 DefaultSku
= DscPcdEntry
.SkuInfoList
.get(TAB_DEFAULT
)
583 defaultindex
= SkuObjList
.index((TAB_DEFAULT
, DefaultSku
))
584 SkuObjList
[0], SkuObjList
[defaultindex
] = SkuObjList
[defaultindex
], SkuObjList
[0]
585 for (SkuName
, Sku
) in SkuObjList
:
586 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
588 # Need to iterate DEC pcd information to get the value & datumtype
589 for eachDec
in self
.PackageList
:
590 for DecPcd
in eachDec
.Pcds
:
591 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
592 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
593 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
594 # Print warning message to let the developer make a determine.
595 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
596 File
=self
.MetaFile
, \
597 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
598 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
600 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
601 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
602 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
603 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
604 # Only fix the value while no value provided in DSC file.
605 if not Sku
.DefaultValue
:
606 DscPcdEntry
.SkuInfoList
[list(DscPcdEntry
.SkuInfoList
.keys())[0]].DefaultValue
= DecPcdEntry
.DefaultValue
608 if DscPcdEntry
not in self
._DynamicPcdList
:
609 self
._DynamicPcdList
.append(DscPcdEntry
)
610 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
611 PcdValue
= Sku
.DefaultValue
613 PcdValue
= DscPcdEntry
.DefaultValue
614 if Sku
.VpdOffset
!= TAB_STAR
:
615 if PcdValue
.startswith("{"):
617 elif PcdValue
.startswith("L"):
622 VpdOffset
= int(Sku
.VpdOffset
)
625 VpdOffset
= int(Sku
.VpdOffset
, 16)
627 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
))
628 if VpdOffset
% Alignment
!= 0:
629 if PcdValue
.startswith("{"):
630 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
), File
=self
.MetaFile
)
632 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, Alignment
))
633 if PcdValue
not in SkuValueMap
:
634 SkuValueMap
[PcdValue
] = []
635 VpdFile
.Add(DscPcdEntry
, SkuName
, Sku
.VpdOffset
)
636 SkuValueMap
[PcdValue
].append(Sku
)
637 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== TAB_STAR
:
638 NeedProcessVpdMapFile
= True
639 if DscPcdEntry
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
640 UnicodePcdArray
.add(DscPcdEntry
)
641 elif len(Sku
.VariableName
) > 0:
642 HiiPcdArray
.add(DscPcdEntry
)
644 OtherPcdArray
.add(DscPcdEntry
)
646 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
647 VpdSkuMap
[DscPcd
] = SkuValueMap
648 if (self
.Platform
.FlashDefinition
is None or self
.Platform
.FlashDefinition
== '') and \
649 VpdFile
.GetCount() != 0:
650 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
651 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
653 if VpdFile
.GetCount() != 0:
655 self
.FixVpdOffset(VpdFile
)
657 self
.FixVpdOffset(self
.UpdateNVStoreMaxSize(VpdFile
))
658 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
659 if PcdNvStoreDfBuffer
:
660 PcdName
,PcdGuid
= PcdNvStoreDfBuffer
[0].TokenCName
, PcdNvStoreDfBuffer
[0].TokenSpaceGuidCName
661 if (PcdName
,PcdGuid
) in VpdSkuMap
:
662 DefaultSku
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get(TAB_DEFAULT
)
663 VpdSkuMap
[(PcdName
,PcdGuid
)] = {DefaultSku
.DefaultValue
:[SkuObj
for SkuObj
in PcdNvStoreDfBuffer
[0].SkuInfoList
.values() ]}
665 # Process VPD map file generated by third party BPDG tool
666 if NeedProcessVpdMapFile
:
667 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
668 if os
.path
.exists(VpdMapFilePath
):
669 VpdFile
.Read(VpdMapFilePath
)
671 # Fixup TAB_STAR offset
672 for pcd
in VpdSkuMap
:
673 vpdinfo
= VpdFile
.GetVpdInfo(pcd
)
675 # just pick the a value to determine whether is unicode string type
677 for pcdvalue
in VpdSkuMap
[pcd
]:
678 for sku
in VpdSkuMap
[pcd
][pcdvalue
]:
680 if item
[2] == pcdvalue
:
681 sku
.VpdOffset
= item
[1]
683 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
685 # Delete the DynamicPcdList At the last time enter into this function
686 for Pcd
in self
._DynamicPcdList
:
687 # just pick the a value to determine whether is unicode string type
688 Sku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
689 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
691 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
692 Pcd
.DatumType
= TAB_VOID
694 PcdValue
= Sku
.DefaultValue
695 if Pcd
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
696 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
697 UnicodePcdArray
.add(Pcd
)
698 elif len(Sku
.VariableName
) > 0:
699 # if found HII type PCD then insert to right of UnicodeIndex
702 OtherPcdArray
.add(Pcd
)
703 del self
._DynamicPcdList
[:]
704 self
._DynamicPcdList
.extend(list(UnicodePcdArray
))
705 self
._DynamicPcdList
.extend(list(HiiPcdArray
))
706 self
._DynamicPcdList
.extend(list(OtherPcdArray
))
707 allskuset
= [(SkuName
, Sku
.SkuId
) for pcd
in self
._DynamicPcdList
for (SkuName
, Sku
) in pcd
.SkuInfoList
.items()]
708 for pcd
in self
._DynamicPcdList
:
709 if len(pcd
.SkuInfoList
) == 1:
710 for (SkuName
, SkuId
) in allskuset
:
711 if isinstance(SkuId
, str) and eval(SkuId
) == 0 or SkuId
== 0:
713 pcd
.SkuInfoList
[SkuName
] = copy
.deepcopy(pcd
.SkuInfoList
[TAB_DEFAULT
])
714 pcd
.SkuInfoList
[SkuName
].SkuId
= SkuId
715 pcd
.SkuInfoList
[SkuName
].SkuIdName
= SkuName
717 def FixVpdOffset(self
, VpdFile
):
718 FvPath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
719 if not os
.path
.exists(FvPath
):
723 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
725 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
727 if VpdFile
.Write(VpdFilePath
):
728 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
730 for ToolDef
in self
.ToolDefinition
.values():
731 if TAB_GUID
in ToolDef
and ToolDef
[TAB_GUID
] == self
.Platform
.VpdToolGuid
:
732 if "PATH" not in ToolDef
:
733 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
734 BPDGToolName
= ToolDef
["PATH"]
736 # Call third party GUID BPDG tool.
737 if BPDGToolName
is not None:
738 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
740 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.")
742 ## Return the platform build data object
745 return self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
747 ## Return platform name
750 return self
.Platform
.PlatformName
752 ## Return the meta file GUID
755 return self
.Platform
.Guid
757 ## Return the platform version
760 return self
.Platform
.Version
762 ## Return the FDF file name
765 if self
.Workspace
.FdfFile
:
766 RetVal
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
771 ## Return the build output directory platform specifies
774 return self
.Platform
.OutputDirectory
776 ## Return the directory to store all intermediate and final files built
779 if os
.path
.isabs(self
.OutputDir
):
780 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
781 path
.abspath(self
.OutputDir
),
782 self
.BuildTarget
+ "_" + self
.ToolChain
,
785 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
788 self
.BuildTarget
+ "_" + self
.ToolChain
,
792 ## Return directory of platform makefile
794 # @retval string Makefile directory
797 def MakeFileDir(self
):
798 return path
.join(self
.BuildDir
, self
.Arch
)
800 ## Return build command string
802 # @retval string Build command string
805 def BuildCommand(self
):
807 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
808 RetVal
+= _SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
809 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
810 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
812 RetVal
+= _SplitOption(NewOption
)
813 if "MAKE" in self
.EdkIIBuildOption
:
814 if "FLAGS" in self
.EdkIIBuildOption
["MAKE"]:
815 Flags
= self
.EdkIIBuildOption
["MAKE"]["FLAGS"]
816 if Flags
.startswith('='):
817 RetVal
= [RetVal
[0]] + [Flags
[1:]]
822 ## Get tool chain definition
824 # Get each tool definition for given tool chain from tools_def.txt and platform
827 def ToolDefinition(self
):
828 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
829 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
830 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
831 ExtraData
="[%s]" % self
.MetaFile
)
832 RetVal
= OrderedDict()
834 for Def
in ToolDefinition
:
835 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
836 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
839 Value
= ToolDefinition
[Def
]
840 # don't record the DLL
842 DllPathList
.add(Value
)
845 if Tool
not in RetVal
:
846 RetVal
[Tool
] = OrderedDict()
847 RetVal
[Tool
][Attr
] = Value
850 if GlobalData
.gOptions
.SilentMode
and "MAKE" in RetVal
:
851 if "FLAGS" not in RetVal
["MAKE"]:
852 RetVal
["MAKE"]["FLAGS"] = ""
853 RetVal
["MAKE"]["FLAGS"] += " -s"
856 for Attr
in RetVal
[Tool
]:
857 Value
= RetVal
[Tool
][Attr
]
858 if Tool
in self
._BuildOptionWithToolDef
(RetVal
) and Attr
in self
._BuildOptionWithToolDef
(RetVal
)[Tool
]:
859 # check if override is indicated
860 if self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
].startswith('='):
861 Value
= self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
][1:]
864 Value
+= " " + self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
866 Value
= self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
869 # Don't put MAKE definition in the file
871 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
873 # Don't put MAKE definition in the file
878 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
881 tool_def_file
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
882 SaveFileOnChange(tool_def_file
, ToolsDef
, False)
883 for DllPath
in DllPathList
:
884 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
885 os
.environ
["MAKE_FLAGS"] = MakeFlags
889 ## Return the paths of tools
891 def ToolDefinitionFile(self
):
892 tool_def_file
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
893 if not os
.path
.exists(tool_def_file
):
897 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
899 def ToolChainFamily(self
):
900 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
901 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
902 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
903 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
904 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
906 RetVal
= TAB_COMPILER_MSFT
908 RetVal
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
912 def BuildRuleFamily(self
):
913 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
914 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
915 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
916 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
917 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
919 return TAB_COMPILER_MSFT
921 return ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
923 ## Return the build options specific for all modules in this platform
925 def BuildOption(self
):
926 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
928 def _BuildOptionWithToolDef(self
, ToolDef
):
929 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, ToolDef
=ToolDef
)
931 ## Return the build options specific for EDK modules in this platform
933 def EdkBuildOption(self
):
934 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
936 ## Return the build options specific for EDKII modules in this platform
938 def EdkIIBuildOption(self
):
939 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
941 ## Parse build_rule.txt in Conf Directory.
943 # @retval BuildRule object
948 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
949 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
950 if not BuildRuleFile
:
951 BuildRuleFile
= gDefaultBuildRuleFile
952 RetVal
= BuildRule(BuildRuleFile
)
953 if RetVal
._FileVersion
== "":
954 RetVal
._FileVersion
= AutoGenReqBuildRuleVerNum
956 if RetVal
._FileVersion
< AutoGenReqBuildRuleVerNum
:
957 # If Build Rule's version is less than the version number required by the tools, halting the build.
958 EdkLogger
.error("build", AUTOGEN_ERROR
,
959 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])"\
960 % (RetVal
._FileVersion
, AutoGenReqBuildRuleVerNum
))
963 ## Summarize the packages used by modules in this platform
965 def PackageList(self
):
967 for Mb
in self
._MbList
:
968 RetVal
.update(Mb
.Packages
)
969 for lb
in Mb
.LibInstances
:
970 RetVal
.update(lb
.Packages
)
971 #Collect package set information from INF of FDF
972 for ModuleFile
in self
._AsBuildModuleList
:
973 if ModuleFile
in self
.Platform
.Modules
:
975 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
976 RetVal
.update(ModuleData
.Packages
)
980 def NonDynamicPcdDict(self
):
981 return {(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
):Pcd
for Pcd
in self
.NonDynamicPcdList
}
983 ## Get list of non-dynamic PCDs
985 def NonDynamicPcdList(self
):
986 if not self
._NonDynamicPcdList
:
987 self
.CollectPlatformDynamicPcds()
988 return self
._NonDynamicPcdList
990 ## Get list of dynamic PCDs
992 def DynamicPcdList(self
):
993 if not self
._DynamicPcdList
:
994 self
.CollectPlatformDynamicPcds()
995 return self
._DynamicPcdList
997 ## Generate Token Number for all PCD
999 def PcdTokenNumber(self
):
1000 RetVal
= OrderedDict()
1003 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
1007 # TokenNumber 0 ~ 10
1009 # TokeNumber 11 ~ 20
1011 for Pcd
in self
.DynamicPcdList
:
1012 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
1013 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1014 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1017 for Pcd
in self
.DynamicPcdList
:
1018 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1019 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1020 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1023 for Pcd
in self
.DynamicPcdList
:
1024 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
1025 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1026 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1029 for Pcd
in self
.DynamicPcdList
:
1030 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1031 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1032 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1035 for Pcd
in self
.NonDynamicPcdList
:
1036 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1042 return [self
.BuildDatabase
[m
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
] for m
in self
.Platform
.Modules
]
1046 for ModuleFile
in self
.Platform
.Modules
:
1056 self
.Platform
.Modules
[ModuleFile
].M
= Ma
1057 return [x
.M
for x
in self
.Platform
.Modules
.values()]
1059 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
1061 def ModuleAutoGenList(self
):
1063 for Ma
in self
._MaList
:
1064 if Ma
not in RetVal
:
1068 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
1070 def LibraryAutoGenList(self
):
1072 for Ma
in self
._MaList
:
1073 for La
in Ma
.LibraryAutoGenList
:
1074 if La
not in RetVal
:
1076 if Ma
not in La
.ReferenceModules
:
1077 La
.ReferenceModules
.append(Ma
)
1080 ## Test if a module is supported by the platform
1082 # An error will be raised directly if the module or its arch is not supported
1083 # by the platform or current configuration
1085 def ValidModule(self
, Module
):
1086 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
1087 or Module
in self
._AsBuildModuleList
1089 def GetAllModuleInfo(self
,WithoutPcd
=True):
1091 for m
in self
.Platform
.Modules
:
1092 module_obj
= self
.BuildDatabase
[m
,self
.Arch
,self
.BuildTarget
,self
.ToolChain
]
1093 if not bool(module_obj
.LibraryClass
):
1094 Libs
= GetModuleLibInstances(module_obj
, self
.Platform
, self
.BuildDatabase
, self
.Arch
,self
.BuildTarget
,self
.ToolChain
,self
.MetaFile
,EdkLogger
)
1097 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
]))
1098 if WithoutPcd
and module_obj
.PcdIsDriver
:
1100 ModuleLibs
.add((m
.File
,m
.Root
,m
.Path
,m
.BaseName
,m
.OriginalPath
,module_obj
.Arch
,bool(module_obj
.LibraryClass
)))
1104 ## Resolve the library classes in a module to library instances
1106 # This method will not only resolve library classes but also sort the library
1107 # instances according to the dependency-ship.
1109 # @param Module The module from which the library classes will be resolved
1111 # @retval library_list List of library instances sorted
1113 def ApplyLibraryInstance(self
, Module
):
1114 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
1115 if str(Module
) not in self
.Platform
.Modules
:
1118 return GetModuleLibInstances(Module
,
1127 ## Override PCD setting (type, value, ...)
1129 # @param ToPcd The PCD to be overridden
1130 # @param FromPcd The PCD overriding from
1132 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
="", Msg
="", Library
=""):
1134 # in case there's PCDs coming from FDF file, which have no type given.
1135 # at this point, ToPcd.Type has the type found from dependent
1138 TokenCName
= ToPcd
.TokenCName
1139 for PcdItem
in GlobalData
.MixedPcd
:
1140 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
1141 TokenCName
= PcdItem
[0]
1143 if FromPcd
is not None:
1144 if ToPcd
.Pending
and FromPcd
.Type
:
1145 ToPcd
.Type
= FromPcd
.Type
1146 elif ToPcd
.Type
and FromPcd
.Type\
1147 and ToPcd
.Type
!= FromPcd
.Type
and ToPcd
.Type
in FromPcd
.Type
:
1148 if ToPcd
.Type
.strip() == TAB_PCDS_DYNAMIC_EX
:
1149 ToPcd
.Type
= FromPcd
.Type
1150 elif ToPcd
.Type
and FromPcd
.Type \
1151 and ToPcd
.Type
!= FromPcd
.Type
:
1153 Module
= str(Module
) + " 's library file (" + str(Library
) + ")"
1154 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
1155 ExtraData
="%s.%s is used as [%s] in module %s, but as [%s] in %s."\
1156 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
1157 ToPcd
.Type
, Module
, FromPcd
.Type
, Msg
),
1160 if FromPcd
.MaxDatumSize
:
1161 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
1162 ToPcd
.MaxSizeUserSet
= FromPcd
.MaxDatumSize
1163 if FromPcd
.DefaultValue
:
1164 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
1165 if FromPcd
.TokenValue
:
1166 ToPcd
.TokenValue
= FromPcd
.TokenValue
1167 if FromPcd
.DatumType
:
1168 ToPcd
.DatumType
= FromPcd
.DatumType
1169 if FromPcd
.SkuInfoList
:
1170 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
1171 if FromPcd
.UserDefinedDefaultStoresFlag
:
1172 ToPcd
.UserDefinedDefaultStoresFlag
= FromPcd
.UserDefinedDefaultStoresFlag
1173 # Add Flexible PCD format parse
1174 if ToPcd
.DefaultValue
:
1176 ToPcd
.DefaultValue
= ValueExpressionEx(ToPcd
.DefaultValue
, ToPcd
.DatumType
, self
.Platform
._GuidDict
)(True)
1177 except BadExpression
as Value
:
1178 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
, ToPcd
.DefaultValue
, Value
),
1181 # check the validation of datum
1182 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
1184 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
1185 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
1186 ToPcd
.validateranges
= FromPcd
.validateranges
1187 ToPcd
.validlists
= FromPcd
.validlists
1188 ToPcd
.expressions
= FromPcd
.expressions
1189 ToPcd
.CustomAttribute
= FromPcd
.CustomAttribute
1191 if FromPcd
is not None and ToPcd
.DatumType
== TAB_VOID
and not ToPcd
.MaxDatumSize
:
1192 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
1193 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
1194 Value
= ToPcd
.DefaultValue
1196 ToPcd
.MaxDatumSize
= '1'
1197 elif Value
[0] == 'L':
1198 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
1199 elif Value
[0] == '{':
1200 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
1202 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
1204 # apply default SKU for dynamic PCDS if specified one is not available
1205 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_SET
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
) \
1206 and not ToPcd
.SkuInfoList
:
1207 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
1208 SkuName
= self
.Platform
.SkuName
1210 SkuName
= TAB_DEFAULT
1211 ToPcd
.SkuInfoList
= {
1212 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
][0], '', '', '', '', '', ToPcd
.DefaultValue
)
1215 ## Apply PCD setting defined platform to a module
1217 # @param Module The module from which the PCD setting will be overridden
1219 # @retval PCD_list The list PCDs with settings from platform
1221 def ApplyPcdSetting(self
, Module
, Pcds
, Library
=""):
1222 # for each PCD in module
1223 for Name
, Guid
in Pcds
:
1224 PcdInModule
= Pcds
[Name
, Guid
]
1225 # find out the PCD setting in platform
1226 if (Name
, Guid
) in self
.Platform
.Pcds
:
1227 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
1229 PcdInPlatform
= None
1230 # then override the settings if any
1231 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
, Msg
="DSC PCD sections", Library
=Library
)
1232 # resolve the VariableGuid value
1233 for SkuId
in PcdInModule
.SkuInfoList
:
1234 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
1235 if Sku
.VariableGuid
== '': continue
1236 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
1237 if Sku
.VariableGuidValue
is None:
1238 PackageList
= "\n\t".join(str(P
) for P
in self
.PackageList
)
1241 RESOURCE_NOT_AVAILABLE
,
1242 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
1243 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
1244 % (Guid
, Name
, str(Module
)),
1248 # override PCD settings with module specific setting
1249 if Module
in self
.Platform
.Modules
:
1250 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1251 for Key
in PlatformModule
.Pcds
:
1252 if GlobalData
.BuildOptionPcd
:
1253 for pcd
in GlobalData
.BuildOptionPcd
:
1254 (TokenSpaceGuidCName
, TokenCName
, FieldName
, pcdvalue
, _
) = pcd
1255 if (TokenCName
, TokenSpaceGuidCName
) == Key
and FieldName
=="":
1256 PlatformModule
.Pcds
[Key
].DefaultValue
= pcdvalue
1257 PlatformModule
.Pcds
[Key
].PcdValueFromComm
= pcdvalue
1263 elif Key
in GlobalData
.MixedPcd
:
1264 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
1266 ToPcd
= Pcds
[PcdItem
]
1270 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
, Msg
="DSC Components Module scoped PCD section", Library
=Library
)
1271 # use PCD value to calculate the MaxDatumSize when it is not specified
1272 for Name
, Guid
in Pcds
:
1273 Pcd
= Pcds
[Name
, Guid
]
1274 if Pcd
.DatumType
== TAB_VOID
and not Pcd
.MaxDatumSize
:
1275 Pcd
.MaxSizeUserSet
= None
1276 Value
= Pcd
.DefaultValue
1278 Pcd
.MaxDatumSize
= '1'
1279 elif Value
[0] == 'L':
1280 Pcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
1281 elif Value
[0] == '{':
1282 Pcd
.MaxDatumSize
= str(len(Value
.split(',')))
1284 Pcd
.MaxDatumSize
= str(len(Value
) - 1)
1285 return list(Pcds
.values())
1287 ## Append build options in platform to a module
1289 # @param Module The module to which the build options will be appended
1291 # @retval options The options appended with build options in platform
1293 def ApplyBuildOption(self
, Module
):
1294 # Get the different options for the different style module
1295 PlatformOptions
= self
.EdkIIBuildOption
1296 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
1297 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
1298 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
1299 if Module
in self
.Platform
.Modules
:
1300 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1301 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
1303 PlatformModuleOptions
= {}
1305 BuildRuleOrder
= None
1306 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
1307 for Tool
in Options
:
1308 for Attr
in Options
[Tool
]:
1309 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
1310 BuildRuleOrder
= Options
[Tool
][Attr
]
1312 AllTools
= set(list(ModuleOptions
.keys()) + list(PlatformOptions
.keys()) +
1313 list(PlatformModuleOptions
.keys()) + list(ModuleTypeOptions
.keys()) +
1314 list(self
.ToolDefinition
.keys()))
1315 BuildOptions
= defaultdict(lambda: defaultdict(str))
1316 for Tool
in AllTools
:
1317 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
1318 if Tool
not in Options
:
1320 for Attr
in Options
[Tool
]:
1322 # Do not generate it in Makefile
1324 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
1326 Value
= Options
[Tool
][Attr
]
1327 # check if override is indicated
1328 if Value
.startswith('='):
1329 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
[1:])
1332 BuildOptions
[Tool
][Attr
] += " " + mws
.handleWsMacro(Value
)
1334 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
)
1336 return BuildOptions
, BuildRuleOrder
1339 def GetGlobalBuildOptions(self
,Module
):
1340 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
1341 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
1343 if Module
in self
.Platform
.Modules
:
1344 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1345 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
1347 PlatformModuleOptions
= {}
1349 return ModuleTypeOptions
,PlatformModuleOptions
1350 def ModuleGuid(self
,Module
):
1351 if os
.path
.basename(Module
.MetaFile
.File
) != os
.path
.basename(Module
.MetaFile
.Path
):
1353 # Length of GUID is 36
1355 return os
.path
.basename(Module
.MetaFile
.Path
)[:36]
1358 def UniqueBaseName(self
):
1362 for Module
in self
._MbList
:
1363 unique_base_name
= '%s_%s' % (Module
.BaseName
,self
.ModuleGuid(Module
))
1364 if unique_base_name
not in ModuleNameDict
:
1365 ModuleNameDict
[unique_base_name
] = []
1366 ModuleNameDict
[unique_base_name
].append(Module
.MetaFile
)
1367 if Module
.BaseName
not in UniqueName
:
1368 UniqueName
[Module
.BaseName
] = set()
1369 UniqueName
[Module
.BaseName
].add((self
.ModuleGuid(Module
),Module
.MetaFile
))
1370 for module_paths
in ModuleNameDict
.values():
1371 if len(set(module_paths
))>1:
1372 samemodules
= list(set(module_paths
))
1373 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
1374 ' %s\n %s' % (samemodules
[0], samemodules
[1]))
1375 for name
in UniqueName
:
1376 Guid_Path
= UniqueName
[name
]
1377 if len(Guid_Path
) > 1:
1378 for guid
,mpath
in Guid_Path
:
1379 retVal
[(name
,mpath
)] = '%s_%s' % (name
,guid
)
1381 ## Expand * in build option key
1383 # @param Options Options to be expanded
1384 # @param ToolDef Use specified ToolDef instead of full version.
1385 # This is needed during initialization to prevent
1386 # infinite recursion betweeh BuildOptions,
1387 # ToolDefinition, and this function.
1389 # @retval options Options expanded
1391 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None, ToolDef
=None):
1393 ToolDef
= self
.ToolDefinition
1400 # Construct a list contain the build options which need override.
1404 # Key[0] -- tool family
1405 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1407 if (Key
[0] == self
.BuildRuleFamily
and
1408 (ModuleStyle
is None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
1409 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
1410 if (Target
== self
.BuildTarget
or Target
== TAB_STAR
) and\
1411 (ToolChain
== self
.ToolChain
or ToolChain
== TAB_STAR
) and\
1412 (Arch
== self
.Arch
or Arch
== TAB_STAR
) and\
1413 Options
[Key
].startswith("="):
1415 if OverrideList
.get(Key
[1]) is not None:
1416 OverrideList
.pop(Key
[1])
1417 OverrideList
[Key
[1]] = Options
[Key
]
1420 # Use the highest priority value.
1422 if (len(OverrideList
) >= 2):
1423 KeyList
= list(OverrideList
.keys())
1424 for Index
in range(len(KeyList
)):
1425 NowKey
= KeyList
[Index
]
1426 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
1427 for Index1
in range(len(KeyList
) - Index
- 1):
1428 NextKey
= KeyList
[Index1
+ Index
+ 1]
1430 # Compare two Key, if one is included by another, choose the higher priority one
1432 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
1433 if (Target1
== Target2
or Target1
== TAB_STAR
or Target2
== TAB_STAR
) and\
1434 (ToolChain1
== ToolChain2
or ToolChain1
== TAB_STAR
or ToolChain2
== TAB_STAR
) and\
1435 (Arch1
== Arch2
or Arch1
== TAB_STAR
or Arch2
== TAB_STAR
) and\
1436 (CommandType1
== CommandType2
or CommandType1
== TAB_STAR
or CommandType2
== TAB_STAR
) and\
1437 (Attr1
== Attr2
or Attr1
== TAB_STAR
or Attr2
== TAB_STAR
):
1439 if CalculatePriorityValue(NowKey
) > CalculatePriorityValue(NextKey
):
1440 if Options
.get((self
.BuildRuleFamily
, NextKey
)) is not None:
1441 Options
.pop((self
.BuildRuleFamily
, NextKey
))
1443 if Options
.get((self
.BuildRuleFamily
, NowKey
)) is not None:
1444 Options
.pop((self
.BuildRuleFamily
, NowKey
))
1447 if ModuleStyle
is not None and len (Key
) > 2:
1448 # Check Module style is EDK or EDKII.
1449 # Only append build option for the matched style module.
1450 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
1452 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
1455 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
1456 # if tool chain family doesn't match, skip it
1457 if Tool
in ToolDef
and Family
!= "":
1458 FamilyIsNull
= False
1459 if ToolDef
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
1460 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
1462 elif Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
1465 # expand any wildcard
1466 if Target
== TAB_STAR
or Target
== self
.BuildTarget
:
1467 if Tag
== TAB_STAR
or Tag
== self
.ToolChain
:
1468 if Arch
== TAB_STAR
or Arch
== self
.Arch
:
1469 if Tool
not in BuildOptions
:
1470 BuildOptions
[Tool
] = {}
1471 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
1472 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1474 # append options for the same tool except PATH
1476 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
1478 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1479 # Build Option Family has been checked, which need't to be checked again for family.
1480 if FamilyMatch
or FamilyIsNull
:
1484 if ModuleStyle
is not None and len (Key
) > 2:
1485 # Check Module style is EDK or EDKII.
1486 # Only append build option for the matched style module.
1487 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
1489 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
1492 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
1493 # if tool chain family doesn't match, skip it
1494 if Tool
not in ToolDef
or Family
== "":
1496 # option has been added before
1497 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
1500 # expand any wildcard
1501 if Target
== TAB_STAR
or Target
== self
.BuildTarget
:
1502 if Tag
== TAB_STAR
or Tag
== self
.ToolChain
:
1503 if Arch
== TAB_STAR
or Arch
== self
.Arch
:
1504 if Tool
not in BuildOptions
:
1505 BuildOptions
[Tool
] = {}
1506 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
1507 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1509 # append options for the same tool except PATH
1511 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
1513 BuildOptions
[Tool
][Attr
] = Options
[Key
]