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