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