2019-09-03 11:58:42 +02:00
## @file
# Create makefile for MS nmake and GNU make
#
# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
## Import Modules
#
from __future__ import print_function
from __future__ import absolute_import
import os . path as path
import copy
from collections import defaultdict
from . BuildEngine import BuildRule , gDefaultBuildRuleFile , AutoGenReqBuildRuleVerNum
from . GenVar import VariableMgr , var_info
from . import GenMake
from AutoGen . DataPipe import MemoryDataPipe
from AutoGen . ModuleAutoGen import ModuleAutoGen
from AutoGen . AutoGen import AutoGen
from AutoGen . AutoGen import CalculatePriorityValue
from Workspace . WorkspaceCommon import GetModuleLibInstances
from CommonDataClass . CommonClass import SkuInfoClass
from Common . caching import cached_class_function
from Common . Expression import ValueExpressionEx
from Common . StringUtils import StringToArray , NormPath
from Common . BuildToolError import *
from Common . DataType import *
from Common . Misc import *
import Common . VpdInfoFile as VpdInfoFile
## Split command line option string to list
#
# subprocess.Popen needs the args to be a sequence. Otherwise there's problem
# in non-windows platform to launch command
#
def _SplitOption ( OptionString ) :
OptionList = [ ]
LastChar = " "
OptionStart = 0
QuotationMark = " "
for Index in range ( 0 , len ( OptionString ) ) :
CurrentChar = OptionString [ Index ]
if CurrentChar in [ ' " ' , " ' " ] :
if QuotationMark == CurrentChar :
QuotationMark = " "
elif QuotationMark == " " :
QuotationMark = CurrentChar
continue
elif QuotationMark :
continue
if CurrentChar in [ " / " , " - " ] and LastChar in [ " " , " \t " , " \r " , " \n " ] :
if Index > OptionStart :
OptionList . append ( OptionString [ OptionStart : Index - 1 ] )
OptionStart = Index
LastChar = CurrentChar
OptionList . append ( OptionString [ OptionStart : ] )
return OptionList
## AutoGen class for platform
#
# PlatformAutoGen class will process the original information in platform
# file in order to generate makefile for platform.
#
class PlatformAutoGen ( AutoGen ) :
# call super().__init__ then call the worker function with different parameter count
def __init__ ( self , Workspace , MetaFile , Target , Toolchain , Arch , * args , * * kwargs ) :
if not hasattr ( self , " _Init " ) :
self . _InitWorker ( Workspace , MetaFile , Target , Toolchain , Arch )
self . _Init = True
#
# Used to store all PCDs for both PEI and DXE phase, in order to generate
# correct PCD database
#
_DynaPcdList_ = [ ]
_NonDynaPcdList_ = [ ]
_PlatformPcds = { }
## Initialize PlatformAutoGen
#
#
# @param Workspace WorkspaceAutoGen object
# @param PlatformFile Platform file (DSC file)
# @param Target Build target (DEBUG, RELEASE)
# @param Toolchain Name of tool chain
# @param Arch arch of the platform supports
#
def _InitWorker ( self , Workspace , PlatformFile , Target , Toolchain , Arch ) :
EdkLogger . debug ( EdkLogger . DEBUG_9 , " AutoGen platform [ %s ] [ %s ] " % ( PlatformFile , Arch ) )
GlobalData . gProcessingFile = " %s [ %s , %s , %s ] " % ( PlatformFile , Arch , Toolchain , Target )
self . MetaFile = PlatformFile
self . Workspace = Workspace
self . WorkspaceDir = Workspace . WorkspaceDir
self . ToolChain = Toolchain
self . BuildTarget = Target
self . Arch = Arch
self . SourceDir = PlatformFile . SubDir
self . FdTargetList = self . Workspace . FdTargetList
self . FvTargetList = self . Workspace . FvTargetList
# get the original module/package/platform objects
self . BuildDatabase = Workspace . BuildDatabase
self . DscBuildDataObj = Workspace . Platform
# flag indicating if the makefile/C-code file has been created or not
self . IsMakeFileCreated = False
self . _DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
self . _NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
self . _AsBuildInfList = [ ]
self . _AsBuildModuleList = [ ]
self . VariableInfo = None
if GlobalData . gFdfParser is not None :
self . _AsBuildInfList = GlobalData . gFdfParser . Profile . InfList
for Inf in self . _AsBuildInfList :
InfClass = PathClass ( NormPath ( Inf ) , GlobalData . gWorkspace , self . Arch )
M = self . BuildDatabase [ InfClass , self . Arch , self . BuildTarget , self . ToolChain ]
if not M . IsBinaryModule :
continue
self . _AsBuildModuleList . append ( InfClass )
# get library/modules for build
self . LibraryBuildDirectoryList = [ ]
self . ModuleBuildDirectoryList = [ ]
self . DataPipe = MemoryDataPipe ( self . BuildDir )
self . DataPipe . FillData ( self )
return True
def FillData_LibConstPcd ( self ) :
libConstPcd = { }
for LibAuto in self . LibraryAutoGenList :
if LibAuto . ConstPcd :
libConstPcd [ ( LibAuto . MetaFile . File , LibAuto . MetaFile . Root , LibAuto . Arch , LibAuto . MetaFile . Path ) ] = LibAuto . ConstPcd
self . DataPipe . DataContainer = { " LibConstPcd " : libConstPcd }
## hash() operator of PlatformAutoGen
#
# The platform file path and arch string will be used to represent
# hash value of this object
#
# @retval int Hash value of the platform file path and arch
#
@cached_class_function
def __hash__ ( self ) :
return hash ( ( self . MetaFile , self . Arch ) )
@cached_class_function
def __repr__ ( self ) :
return " %s [ %s ] " % ( self . MetaFile , self . Arch )
## Create autogen code for platform and modules
#
# Since there's no autogen code for platform, this method will do nothing
# if CreateModuleCodeFile is set to False.
#
# @param CreateModuleCodeFile Flag indicating if creating module's
# autogen code file or not
#
@cached_class_function
def CreateCodeFile ( self , CreateModuleCodeFile = False ) :
# only module has code to be created, so do nothing if CreateModuleCodeFile is False
if not CreateModuleCodeFile :
return
for Ma in self . ModuleAutoGenList :
Ma . CreateCodeFile ( CreateModuleCodeFile )
## Generate Fds Command
@cached_property
def GenFdsCommand ( self ) :
return self . Workspace . GenFdsCommand
## Create makefile for the platform and modules in it
#
# @param CreateModuleMakeFile Flag indicating if the makefile for
# modules will be created as well
#
def CreateMakeFile ( self , CreateModuleMakeFile = False , FfsCommand = { } ) :
if CreateModuleMakeFile :
for Ma in self . _MaList :
key = ( Ma . MetaFile . File , self . Arch )
if key in FfsCommand :
Ma . CreateMakeFile ( CreateModuleMakeFile , FfsCommand [ key ] )
else :
Ma . CreateMakeFile ( CreateModuleMakeFile )
2019-09-20 06:56:20 +02:00
self . CreateLibModuelDirs ( )
2019-09-03 11:58:42 +02:00
2019-09-20 06:56:20 +02:00
def CreateLibModuelDirs ( self ) :
2019-09-03 11:58:42 +02:00
# no need to create makefile for the platform more than once
if self . IsMakeFileCreated :
return
# create library/module build dirs for platform
Makefile = GenMake . PlatformMakefile ( self )
self . LibraryBuildDirectoryList = Makefile . GetLibraryBuildDirectoryList ( )
self . ModuleBuildDirectoryList = Makefile . GetModuleBuildDirectoryList ( )
self . IsMakeFileCreated = True
@property
def AllPcdList ( self ) :
return self . DynamicPcdList + self . NonDynamicPcdList
## Deal with Shared FixedAtBuild Pcds
#
def CollectFixedAtBuildPcds ( self ) :
for LibAuto in self . LibraryAutoGenList :
FixedAtBuildPcds = { }
ShareFixedAtBuildPcdsSameValue = { }
for Module in LibAuto . ReferenceModules :
for Pcd in set ( Module . FixedAtBuildPcds + LibAuto . FixedAtBuildPcds ) :
DefaultValue = Pcd . DefaultValue
# Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib
if Pcd in Module . LibraryPcdList :
Index = Module . LibraryPcdList . index ( Pcd )
DefaultValue = Module . LibraryPcdList [ Index ] . DefaultValue
key = " . " . join ( ( Pcd . TokenSpaceGuidCName , Pcd . TokenCName ) )
if key not in FixedAtBuildPcds :
ShareFixedAtBuildPcdsSameValue [ key ] = True
FixedAtBuildPcds [ key ] = DefaultValue
else :
if FixedAtBuildPcds [ key ] != DefaultValue :
ShareFixedAtBuildPcdsSameValue [ key ] = False
for Pcd in LibAuto . FixedAtBuildPcds :
key = " . " . join ( ( Pcd . TokenSpaceGuidCName , Pcd . TokenCName ) )
if ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName ) not in self . NonDynamicPcdDict :
continue
else :
DscPcd = self . NonDynamicPcdDict [ ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName ) ]
if DscPcd . Type != TAB_PCDS_FIXED_AT_BUILD :
continue
if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue [ key ] :
LibAuto . ConstPcd [ key ] = FixedAtBuildPcds [ key ]
def CollectVariables ( self , DynamicPcdSet ) :
VpdRegionSize = 0
VpdRegionBase = 0
if self . Workspace . FdfFile :
FdDict = self . Workspace . FdfProfile . FdDict [ GlobalData . gFdfParser . CurrentFdName ]
for FdRegion in FdDict . RegionList :
for item in FdRegion . RegionDataList :
if self . Platform . VpdToolGuid . strip ( ) and self . Platform . VpdToolGuid in item :
VpdRegionSize = FdRegion . Size
VpdRegionBase = FdRegion . Offset
break
VariableInfo = VariableMgr ( self . DscBuildDataObj . _GetDefaultStores ( ) , self . DscBuildDataObj . SkuIds )
VariableInfo . SetVpdRegionMaxSize ( VpdRegionSize )
VariableInfo . SetVpdRegionOffset ( VpdRegionBase )
Index = 0
for Pcd in DynamicPcdSet :
pcdname = " . " . join ( ( Pcd . TokenSpaceGuidCName , Pcd . TokenCName ) )
for SkuName in Pcd . SkuInfoList :
Sku = Pcd . SkuInfoList [ SkuName ]
SkuId = Sku . SkuId
if SkuId is None or SkuId == ' ' :
continue
if len ( Sku . VariableName ) > 0 :
if Sku . VariableAttribute and ' NV ' not in Sku . VariableAttribute :
continue
VariableGuidStructure = Sku . VariableGuidValue
VariableGuid = GuidStructureStringToGuidString ( VariableGuidStructure )
for StorageName in Sku . DefaultStoreDict :
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 ) ) )
Index + = 1
return VariableInfo
def UpdateNVStoreMaxSize ( self , OrgVpdFile ) :
if self . VariableInfo :
VpdMapFilePath = os . path . join ( self . BuildDir , TAB_FV_DIRECTORY , " %s .map " % self . Platform . VpdToolGuid )
PcdNvStoreDfBuffer = [ item for item in self . _DynamicPcdList if item . TokenCName == " PcdNvStoreDefaultValueBuffer " and item . TokenSpaceGuidCName == " gEfiMdeModulePkgTokenSpaceGuid " ]
if PcdNvStoreDfBuffer :
2019-09-20 06:56:20 +02:00
try :
2019-09-03 11:58:42 +02:00
OrgVpdFile . Read ( VpdMapFilePath )
PcdItems = OrgVpdFile . GetOffset ( PcdNvStoreDfBuffer [ 0 ] )
NvStoreOffset = list ( PcdItems . values ( ) ) [ 0 ] . strip ( ) if PcdItems else ' 0 '
2019-09-20 06:56:20 +02:00
except :
2019-09-03 11:58:42 +02:00
EdkLogger . error ( " build " , FILE_READ_FAILURE , " Can not find VPD map file %s to fix up VPD offset. " % VpdMapFilePath )
NvStoreOffset = int ( NvStoreOffset , 16 ) if NvStoreOffset . upper ( ) . startswith ( " 0X " ) else int ( NvStoreOffset )
default_skuobj = PcdNvStoreDfBuffer [ 0 ] . SkuInfoList . get ( TAB_DEFAULT )
maxsize = self . VariableInfo . VpdRegionSize - NvStoreOffset if self . VariableInfo . VpdRegionSize else len ( default_skuobj . DefaultValue . split ( " , " ) )
var_data = self . VariableInfo . PatchNVStoreDefaultMaxSize ( maxsize )
if var_data and default_skuobj :
default_skuobj . DefaultValue = var_data
PcdNvStoreDfBuffer [ 0 ] . DefaultValue = var_data
PcdNvStoreDfBuffer [ 0 ] . SkuInfoList . clear ( )
PcdNvStoreDfBuffer [ 0 ] . SkuInfoList [ TAB_DEFAULT ] = default_skuobj
PcdNvStoreDfBuffer [ 0 ] . MaxDatumSize = str ( len ( default_skuobj . DefaultValue . split ( " , " ) ) )
return OrgVpdFile
## Collect dynamic PCDs
#
# Gather dynamic PCDs list from each module and their settings from platform
# This interface should be invoked explicitly when platform action is created.
#
def CollectPlatformDynamicPcds ( self ) :
self . CategoryPcds ( )
self . SortDynamicPcd ( )
def CategoryPcds ( self ) :
# Category Pcds into DynamicPcds and NonDynamicPcds
# for gathering error information
NoDatumTypePcdList = set ( )
FdfModuleList = [ ]
for InfName in self . _AsBuildInfList :
InfName = mws . join ( self . WorkspaceDir , InfName )
FdfModuleList . append ( os . path . normpath ( InfName ) )
for M in self . _MbList :
# F is the Module for which M is the module autogen
ModPcdList = self . ApplyPcdSetting ( M , M . ModulePcdList )
LibPcdList = [ ]
for lib in M . LibraryPcdList :
LibPcdList . extend ( self . ApplyPcdSetting ( M , M . LibraryPcdList [ lib ] , lib ) )
for PcdFromModule in ModPcdList + LibPcdList :
# make sure that the "VOID*" kind of datum has MaxDatumSize set
if PcdFromModule . DatumType == TAB_VOID and not PcdFromModule . MaxDatumSize :
NoDatumTypePcdList . add ( " %s . %s [ %s ] " % ( PcdFromModule . TokenSpaceGuidCName , PcdFromModule . TokenCName , M . MetaFile ) )
# Check the PCD from Binary INF or Source INF
if M . IsBinaryModule == True :
PcdFromModule . IsFromBinaryInf = True
# Check the PCD from DSC or not
PcdFromModule . IsFromDsc = ( PcdFromModule . TokenCName , PcdFromModule . TokenSpaceGuidCName ) in self . Platform . Pcds
if PcdFromModule . Type in PCD_DYNAMIC_TYPE_SET or PcdFromModule . Type in PCD_DYNAMIC_EX_TYPE_SET :
if M . MetaFile . Path not in FdfModuleList :
# If one of the Source built modules listed in the DSC is not listed
# in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
# access method (it is only listed in the DEC file that declares the
# PCD as PcdsDynamic), then build tool will report warning message
# notify the PI that they are attempting to build a module that must
# be included in a flash image in order to be functional. These Dynamic
# PCD will not be added into the Database unless it is used by other
# modules that are included in the FDF file.
if PcdFromModule . Type in PCD_DYNAMIC_TYPE_SET and \
PcdFromModule . IsFromBinaryInf == False :
# Print warning message to let the developer make a determine.
continue
# If one of the Source built modules listed in the DSC is not listed in
# FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
# access method (it is only listed in the DEC file that declares the
# PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
# PCD to the Platform's PCD Database.
if PcdFromModule . Type in PCD_DYNAMIC_EX_TYPE_SET :
continue
#
# If a dynamic PCD used by a PEM module/PEI module & DXE module,
# it should be stored in Pcd PEI database, If a dynamic only
# used by DXE module, it should be stored in DXE PCD database.
# The default Phase is DXE
#
if M . ModuleType in SUP_MODULE_SET_PEI :
PcdFromModule . Phase = " PEI "
if PcdFromModule not in self . _DynaPcdList_ :
self . _DynaPcdList_ . append ( PcdFromModule )
elif PcdFromModule . Phase == ' PEI ' :
# overwrite any the same PCD existing, if Phase is PEI
Index = self . _DynaPcdList_ . index ( PcdFromModule )
self . _DynaPcdList_ [ Index ] = PcdFromModule
elif PcdFromModule not in self . _NonDynaPcdList_ :
self . _NonDynaPcdList_ . append ( PcdFromModule )
elif PcdFromModule in self . _NonDynaPcdList_ and PcdFromModule . IsFromBinaryInf == True :
Index = self . _NonDynaPcdList_ . index ( PcdFromModule )
if self . _NonDynaPcdList_ [ Index ] . IsFromBinaryInf == False :
#The PCD from Binary INF will override the same one from source INF
self . _NonDynaPcdList_ . remove ( self . _NonDynaPcdList_ [ Index ] )
PcdFromModule . Pending = False
self . _NonDynaPcdList_ . append ( PcdFromModule )
DscModuleSet = { os . path . normpath ( ModuleInf . Path ) for ModuleInf in self . Platform . Modules }
# add the PCD from modules that listed in FDF but not in DSC to Database
for InfName in FdfModuleList :
if InfName not in DscModuleSet :
InfClass = PathClass ( InfName )
M = self . BuildDatabase [ InfClass , self . Arch , self . BuildTarget , self . ToolChain ]
# If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
# for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
# For binary module, if in current arch, we need to list the PCDs into database.
if not M . IsBinaryModule :
continue
# Override the module PCD setting by platform setting
ModulePcdList = self . ApplyPcdSetting ( M , M . Pcds )
for PcdFromModule in ModulePcdList :
PcdFromModule . IsFromBinaryInf = True
PcdFromModule . IsFromDsc = False
# Only allow the DynamicEx and Patchable PCD in AsBuild INF
if PcdFromModule . Type not in PCD_DYNAMIC_EX_TYPE_SET and PcdFromModule . Type not in TAB_PCDS_PATCHABLE_IN_MODULE :
EdkLogger . error ( " build " , AUTOGEN_ERROR , " PCD setting error " ,
File = self . MetaFile ,
ExtraData = " \n \t Existed %s PCD %s in: \n \t \t %s \n "
% ( PcdFromModule . Type , PcdFromModule . TokenCName , InfName ) )
# make sure that the "VOID*" kind of datum has MaxDatumSize set
if PcdFromModule . DatumType == TAB_VOID and not PcdFromModule . MaxDatumSize :
NoDatumTypePcdList . add ( " %s . %s [ %s ] " % ( PcdFromModule . TokenSpaceGuidCName , PcdFromModule . TokenCName , InfName ) )
if M . ModuleType in SUP_MODULE_SET_PEI :
PcdFromModule . Phase = " PEI "
if PcdFromModule not in self . _DynaPcdList_ and PcdFromModule . Type in PCD_DYNAMIC_EX_TYPE_SET :
self . _DynaPcdList_ . append ( PcdFromModule )
elif PcdFromModule not in self . _NonDynaPcdList_ and PcdFromModule . Type in TAB_PCDS_PATCHABLE_IN_MODULE :
self . _NonDynaPcdList_ . append ( PcdFromModule )
if PcdFromModule in self . _DynaPcdList_ and PcdFromModule . Phase == ' PEI ' and PcdFromModule . Type in PCD_DYNAMIC_EX_TYPE_SET :
# Overwrite the phase of any the same PCD existing, if Phase is PEI.
# It is to solve the case that a dynamic PCD used by a PEM module/PEI
# module & DXE module at a same time.
# Overwrite the type of the PCDs in source INF by the type of AsBuild
# INF file as DynamicEx.
Index = self . _DynaPcdList_ . index ( PcdFromModule )
self . _DynaPcdList_ [ Index ] . Phase = PcdFromModule . Phase
self . _DynaPcdList_ [ Index ] . Type = PcdFromModule . Type
for PcdFromModule in self . _NonDynaPcdList_ :
# If a PCD is not listed in the DSC file, but binary INF files used by
# this platform all (that use this PCD) list the PCD in a [PatchPcds]
# section, AND all source INF files used by this platform the build
# that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
# section, then the tools must NOT add the PCD to the Platform's PCD
# Database; the build must assign the access method for this PCD as
# PcdsPatchableInModule.
if PcdFromModule not in self . _DynaPcdList_ :
continue
Index = self . _DynaPcdList_ . index ( PcdFromModule )
if PcdFromModule . IsFromDsc == False and \
PcdFromModule . Type in TAB_PCDS_PATCHABLE_IN_MODULE and \
PcdFromModule . IsFromBinaryInf == True and \
self . _DynaPcdList_ [ Index ] . IsFromBinaryInf == False :
Index = self . _DynaPcdList_ . index ( PcdFromModule )
self . _DynaPcdList_ . remove ( self . _DynaPcdList_ [ Index ] )
# print out error information and break the build, if error found
if len ( NoDatumTypePcdList ) > 0 :
NoDatumTypePcdListString = " \n \t \t " . join ( NoDatumTypePcdList )
EdkLogger . error ( " build " , AUTOGEN_ERROR , " PCD setting error " ,
File = self . MetaFile ,
ExtraData = " \n \t PCD(s) without MaxDatumSize: \n \t \t %s \n "
% NoDatumTypePcdListString )
2019-09-20 06:56:20 +02:00
self . _NonDynamicPcdList = sorted ( self . _NonDynaPcdList_ )
2019-09-03 11:58:42 +02:00
self . _DynamicPcdList = self . _DynaPcdList_
def SortDynamicPcd ( self ) :
#
# Sort dynamic PCD list to:
# 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
# try to be put header of dynamicd List
# 2) If PCD is HII type, the PCD item should be put after unicode type PCD
#
# The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
#
UnicodePcdArray = set ( )
HiiPcdArray = set ( )
OtherPcdArray = set ( )
VpdPcdDict = { }
VpdFile = VpdInfoFile . VpdInfoFile ( )
NeedProcessVpdMapFile = False
for pcd in self . Platform . Pcds :
if pcd not in self . _PlatformPcds :
self . _PlatformPcds [ pcd ] = self . Platform . Pcds [ pcd ]
for item in self . _PlatformPcds :
if self . _PlatformPcds [ item ] . DatumType and self . _PlatformPcds [ item ] . DatumType not in [ TAB_UINT8 , TAB_UINT16 , TAB_UINT32 , TAB_UINT64 , TAB_VOID , " BOOLEAN " ] :
self . _PlatformPcds [ item ] . DatumType = TAB_VOID
if ( self . Workspace . ArchList [ - 1 ] == self . Arch ) :
for Pcd in self . _DynamicPcdList :
# just pick the a value to determine whether is unicode string type
Sku = Pcd . SkuInfoList . get ( TAB_DEFAULT )
Sku . VpdOffset = Sku . VpdOffset . strip ( )
if Pcd . DatumType not in [ TAB_UINT8 , TAB_UINT16 , TAB_UINT32 , TAB_UINT64 , TAB_VOID , " BOOLEAN " ] :
Pcd . DatumType = TAB_VOID
# if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
# if found HII type PCD then insert to right of UnicodeIndex
if Pcd . Type in [ TAB_PCDS_DYNAMIC_VPD , TAB_PCDS_DYNAMIC_EX_VPD ] :
VpdPcdDict [ ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName ) ] = Pcd
#Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
PcdNvStoreDfBuffer = VpdPcdDict . get ( ( " PcdNvStoreDefaultValueBuffer " , " gEfiMdeModulePkgTokenSpaceGuid " ) )
if PcdNvStoreDfBuffer :
self . VariableInfo = self . CollectVariables ( self . _DynamicPcdList )
vardump = self . VariableInfo . dump ( )
if vardump :
#
#According to PCD_DATABASE_INIT in edk2\MdeModulePkg\Include\Guid\PcdDataBaseSignatureGuid.h,
#the max size for string PCD should not exceed USHRT_MAX 65535(0xffff).
#typedef UINT16 SIZE_INFO;
#//SIZE_INFO SizeTable[];
if len ( vardump . split ( " , " ) ) > 0xffff :
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 ( " , " ) ) ) )
PcdNvStoreDfBuffer . DefaultValue = vardump
for skuname in PcdNvStoreDfBuffer . SkuInfoList :
PcdNvStoreDfBuffer . SkuInfoList [ skuname ] . DefaultValue = vardump
PcdNvStoreDfBuffer . MaxDatumSize = str ( len ( vardump . split ( " , " ) ) )
else :
#If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd
if [ Pcd for Pcd in self . _DynamicPcdList if Pcd . UserDefinedDefaultStoresFlag ] :
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 )
PlatformPcds = sorted ( self . _PlatformPcds . keys ( ) )
#
# Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
#
VpdSkuMap = { }
for PcdKey in PlatformPcds :
Pcd = self . _PlatformPcds [ PcdKey ]
if Pcd . Type in [ TAB_PCDS_DYNAMIC_VPD , TAB_PCDS_DYNAMIC_EX_VPD ] and \
PcdKey in VpdPcdDict :
Pcd = VpdPcdDict [ PcdKey ]
SkuValueMap = { }
DefaultSku = Pcd . SkuInfoList . get ( TAB_DEFAULT )
if DefaultSku :
PcdValue = DefaultSku . DefaultValue
if PcdValue not in SkuValueMap :
SkuValueMap [ PcdValue ] = [ ]
VpdFile . Add ( Pcd , TAB_DEFAULT , DefaultSku . VpdOffset )
SkuValueMap [ PcdValue ] . append ( DefaultSku )
for ( SkuName , Sku ) in Pcd . SkuInfoList . items ( ) :
Sku . VpdOffset = Sku . VpdOffset . strip ( )
PcdValue = Sku . DefaultValue
if PcdValue == " " :
PcdValue = Pcd . DefaultValue
if Sku . VpdOffset != TAB_STAR :
if PcdValue . startswith ( " { " ) :
Alignment = 8
elif PcdValue . startswith ( " L " ) :
Alignment = 2
else :
Alignment = 1
try :
VpdOffset = int ( Sku . VpdOffset )
except :
try :
VpdOffset = int ( Sku . VpdOffset , 16 )
except :
EdkLogger . error ( " build " , FORMAT_INVALID , " Invalid offset value %s for PCD %s . %s . " % ( Sku . VpdOffset , Pcd . TokenSpaceGuidCName , Pcd . TokenCName ) )
if VpdOffset % Alignment != 0 :
if PcdValue . startswith ( " { " ) :
EdkLogger . warn ( " build " , " The offset value of PCD %s . %s is not 8-byte aligned! " % ( Pcd . TokenSpaceGuidCName , Pcd . TokenCName ) , File = self . MetaFile )
else :
EdkLogger . error ( " build " , FORMAT_INVALID , ' The offset value of PCD %s . %s should be %s -byte aligned. ' % ( Pcd . TokenSpaceGuidCName , Pcd . TokenCName , Alignment ) )
if PcdValue not in SkuValueMap :
SkuValueMap [ PcdValue ] = [ ]
VpdFile . Add ( Pcd , SkuName , Sku . VpdOffset )
SkuValueMap [ PcdValue ] . append ( Sku )
# if the offset of a VPD is *, then it need to be fixed up by third party tool.
if not NeedProcessVpdMapFile and Sku . VpdOffset == TAB_STAR :
NeedProcessVpdMapFile = True
if self . Platform . VpdToolGuid is None or self . Platform . VpdToolGuid == ' ' :
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. " )
VpdSkuMap [ PcdKey ] = SkuValueMap
#
# Fix the PCDs define in VPD PCD section that never referenced by module.
# An example is PCD for signature usage.
#
for DscPcd in PlatformPcds :
DscPcdEntry = self . _PlatformPcds [ DscPcd ]
if DscPcdEntry . Type in [ TAB_PCDS_DYNAMIC_VPD , TAB_PCDS_DYNAMIC_EX_VPD ] :
if not ( self . Platform . VpdToolGuid is None or self . Platform . VpdToolGuid == ' ' ) :
FoundFlag = False
for VpdPcd in VpdFile . _VpdArray :
# This PCD has been referenced by module
if ( VpdPcd . TokenSpaceGuidCName == DscPcdEntry . TokenSpaceGuidCName ) and \
( VpdPcd . TokenCName == DscPcdEntry . TokenCName ) :
FoundFlag = True
# Not found, it should be signature
if not FoundFlag :
# just pick the a value to determine whether is unicode string type
SkuValueMap = { }
SkuObjList = list ( DscPcdEntry . SkuInfoList . items ( ) )
DefaultSku = DscPcdEntry . SkuInfoList . get ( TAB_DEFAULT )
if DefaultSku :
defaultindex = SkuObjList . index ( ( TAB_DEFAULT , DefaultSku ) )
SkuObjList [ 0 ] , SkuObjList [ defaultindex ] = SkuObjList [ defaultindex ] , SkuObjList [ 0 ]
for ( SkuName , Sku ) in SkuObjList :
Sku . VpdOffset = Sku . VpdOffset . strip ( )
# Need to iterate DEC pcd information to get the value & datumtype
for eachDec in self . PackageList :
for DecPcd in eachDec . Pcds :
DecPcdEntry = eachDec . Pcds [ DecPcd ]
if ( DecPcdEntry . TokenSpaceGuidCName == DscPcdEntry . TokenSpaceGuidCName ) and \
( DecPcdEntry . TokenCName == DscPcdEntry . TokenCName ) :
# Print warning message to let the developer make a determine.
EdkLogger . warn ( " build " , " Unreferenced vpd pcd used! " ,
File = self . MetaFile , \
ExtraData = " PCD: %s . %s used in the DSC file %s is unreferenced. " \
% ( DscPcdEntry . TokenSpaceGuidCName , DscPcdEntry . TokenCName , self . Platform . MetaFile . Path ) )
DscPcdEntry . DatumType = DecPcdEntry . DatumType
DscPcdEntry . DefaultValue = DecPcdEntry . DefaultValue
DscPcdEntry . TokenValue = DecPcdEntry . TokenValue
DscPcdEntry . TokenSpaceGuidValue = eachDec . Guids [ DecPcdEntry . TokenSpaceGuidCName ]
# Only fix the value while no value provided in DSC file.
if not Sku . DefaultValue :
DscPcdEntry . SkuInfoList [ list ( DscPcdEntry . SkuInfoList . keys ( ) ) [ 0 ] ] . DefaultValue = DecPcdEntry . DefaultValue
if DscPcdEntry not in self . _DynamicPcdList :
self . _DynamicPcdList . append ( DscPcdEntry )
Sku . VpdOffset = Sku . VpdOffset . strip ( )
PcdValue = Sku . DefaultValue
if PcdValue == " " :
PcdValue = DscPcdEntry . DefaultValue
if Sku . VpdOffset != TAB_STAR :
if PcdValue . startswith ( " { " ) :
Alignment = 8
elif PcdValue . startswith ( " L " ) :
Alignment = 2
else :
Alignment = 1
try :
VpdOffset = int ( Sku . VpdOffset )
except :
try :
VpdOffset = int ( Sku . VpdOffset , 16 )
except :
EdkLogger . error ( " build " , FORMAT_INVALID , " Invalid offset value %s for PCD %s . %s . " % ( Sku . VpdOffset , DscPcdEntry . TokenSpaceGuidCName , DscPcdEntry . TokenCName ) )
if VpdOffset % Alignment != 0 :
if PcdValue . startswith ( " { " ) :
EdkLogger . warn ( " build " , " The offset value of PCD %s . %s is not 8-byte aligned! " % ( DscPcdEntry . TokenSpaceGuidCName , DscPcdEntry . TokenCName ) , File = self . MetaFile )
else :
EdkLogger . error ( " build " , FORMAT_INVALID , ' The offset value of PCD %s . %s should be %s -byte aligned. ' % ( DscPcdEntry . TokenSpaceGuidCName , DscPcdEntry . TokenCName , Alignment ) )
if PcdValue not in SkuValueMap :
SkuValueMap [ PcdValue ] = [ ]
VpdFile . Add ( DscPcdEntry , SkuName , Sku . VpdOffset )
SkuValueMap [ PcdValue ] . append ( Sku )
if not NeedProcessVpdMapFile and Sku . VpdOffset == TAB_STAR :
NeedProcessVpdMapFile = True
if DscPcdEntry . DatumType == TAB_VOID and PcdValue . startswith ( " L " ) :
UnicodePcdArray . add ( DscPcdEntry )
elif len ( Sku . VariableName ) > 0 :
HiiPcdArray . add ( DscPcdEntry )
else :
OtherPcdArray . add ( DscPcdEntry )
# if the offset of a VPD is *, then it need to be fixed up by third party tool.
VpdSkuMap [ DscPcd ] = SkuValueMap
if ( self . Platform . FlashDefinition is None or self . Platform . FlashDefinition == ' ' ) and \
VpdFile . GetCount ( ) != 0 :
EdkLogger . error ( " build " , ATTRIBUTE_NOT_AVAILABLE ,
" Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD. " % str ( self . Platform . MetaFile ) )
if VpdFile . GetCount ( ) != 0 :
self . FixVpdOffset ( VpdFile )
self . FixVpdOffset ( self . UpdateNVStoreMaxSize ( VpdFile ) )
PcdNvStoreDfBuffer = [ item for item in self . _DynamicPcdList if item . TokenCName == " PcdNvStoreDefaultValueBuffer " and item . TokenSpaceGuidCName == " gEfiMdeModulePkgTokenSpaceGuid " ]
if PcdNvStoreDfBuffer :
PcdName , PcdGuid = PcdNvStoreDfBuffer [ 0 ] . TokenCName , PcdNvStoreDfBuffer [ 0 ] . TokenSpaceGuidCName
if ( PcdName , PcdGuid ) in VpdSkuMap :
DefaultSku = PcdNvStoreDfBuffer [ 0 ] . SkuInfoList . get ( TAB_DEFAULT )
VpdSkuMap [ ( PcdName , PcdGuid ) ] = { DefaultSku . DefaultValue : [ SkuObj for SkuObj in PcdNvStoreDfBuffer [ 0 ] . SkuInfoList . values ( ) ] }
# Process VPD map file generated by third party BPDG tool
if NeedProcessVpdMapFile :
VpdMapFilePath = os . path . join ( self . BuildDir , TAB_FV_DIRECTORY , " %s .map " % self . Platform . VpdToolGuid )
2019-09-20 06:56:20 +02:00
try :
2019-09-03 11:58:42 +02:00
VpdFile . Read ( VpdMapFilePath )
# Fixup TAB_STAR offset
for pcd in VpdSkuMap :
vpdinfo = VpdFile . GetVpdInfo ( pcd )
if vpdinfo is None :
# just pick the a value to determine whether is unicode string type
continue
for pcdvalue in VpdSkuMap [ pcd ] :
for sku in VpdSkuMap [ pcd ] [ pcdvalue ] :
for item in vpdinfo :
if item [ 2 ] == pcdvalue :
sku . VpdOffset = item [ 1 ]
2019-09-20 06:56:20 +02:00
except :
2019-09-03 11:58:42 +02:00
EdkLogger . error ( " build " , FILE_READ_FAILURE , " Can not find VPD map file %s to fix up VPD offset. " % VpdMapFilePath )
# Delete the DynamicPcdList At the last time enter into this function
for Pcd in self . _DynamicPcdList :
# just pick the a value to determine whether is unicode string type
Sku = Pcd . SkuInfoList . get ( TAB_DEFAULT )
Sku . VpdOffset = Sku . VpdOffset . strip ( )
if Pcd . DatumType not in [ TAB_UINT8 , TAB_UINT16 , TAB_UINT32 , TAB_UINT64 , TAB_VOID , " BOOLEAN " ] :
Pcd . DatumType = TAB_VOID
PcdValue = Sku . DefaultValue
if Pcd . DatumType == TAB_VOID and PcdValue . startswith ( " L " ) :
# if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
UnicodePcdArray . add ( Pcd )
elif len ( Sku . VariableName ) > 0 :
# if found HII type PCD then insert to right of UnicodeIndex
HiiPcdArray . add ( Pcd )
else :
OtherPcdArray . add ( Pcd )
del self . _DynamicPcdList [ : ]
self . _DynamicPcdList . extend ( list ( UnicodePcdArray ) )
self . _DynamicPcdList . extend ( list ( HiiPcdArray ) )
self . _DynamicPcdList . extend ( list ( OtherPcdArray ) )
2019-09-20 06:56:20 +02:00
self . _DynamicPcdList . sort ( )
2019-09-03 11:58:42 +02:00
allskuset = [ ( SkuName , Sku . SkuId ) for pcd in self . _DynamicPcdList for ( SkuName , Sku ) in pcd . SkuInfoList . items ( ) ]
for pcd in self . _DynamicPcdList :
if len ( pcd . SkuInfoList ) == 1 :
for ( SkuName , SkuId ) in allskuset :
if isinstance ( SkuId , str ) and eval ( SkuId ) == 0 or SkuId == 0 :
continue
pcd . SkuInfoList [ SkuName ] = copy . deepcopy ( pcd . SkuInfoList [ TAB_DEFAULT ] )
pcd . SkuInfoList [ SkuName ] . SkuId = SkuId
pcd . SkuInfoList [ SkuName ] . SkuIdName = SkuName
def FixVpdOffset ( self , VpdFile ) :
FvPath = os . path . join ( self . BuildDir , TAB_FV_DIRECTORY )
if not os . path . exists ( FvPath ) :
try :
os . makedirs ( FvPath )
except :
EdkLogger . error ( " build " , FILE_WRITE_FAILURE , " Fail to create FV folder under %s " % self . BuildDir )
VpdFilePath = os . path . join ( FvPath , " %s .txt " % self . Platform . VpdToolGuid )
if VpdFile . Write ( VpdFilePath ) :
# retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
BPDGToolName = None
for ToolDef in self . ToolDefinition . values ( ) :
if TAB_GUID in ToolDef and ToolDef [ TAB_GUID ] == self . Platform . VpdToolGuid :
if " PATH " not in ToolDef :
EdkLogger . error ( " build " , ATTRIBUTE_NOT_AVAILABLE , " PATH attribute was not provided for BPDG guid tool %s in tools_def.txt " % self . Platform . VpdToolGuid )
BPDGToolName = ToolDef [ " PATH " ]
break
# Call third party GUID BPDG tool.
if BPDGToolName is not None :
VpdInfoFile . CallExtenalBPDGTool ( BPDGToolName , VpdFilePath )
else :
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. " )
## Return the platform build data object
@cached_property
def Platform ( self ) :
return self . BuildDatabase [ self . MetaFile , self . Arch , self . BuildTarget , self . ToolChain ]
## Return platform name
@cached_property
def Name ( self ) :
return self . Platform . PlatformName
## Return the meta file GUID
@cached_property
def Guid ( self ) :
return self . Platform . Guid
## Return the platform version
@cached_property
def Version ( self ) :
return self . Platform . Version
## Return the FDF file name
@cached_property
def FdfFile ( self ) :
if self . Workspace . FdfFile :
RetVal = mws . join ( self . WorkspaceDir , self . Workspace . FdfFile )
else :
RetVal = ' '
return RetVal
## Return the build output directory platform specifies
@cached_property
def OutputDir ( self ) :
return self . Platform . OutputDirectory
## Return the directory to store all intermediate and final files built
@cached_property
def BuildDir ( self ) :
if os . path . isabs ( self . OutputDir ) :
GlobalData . gBuildDirectory = RetVal = path . join (
path . abspath ( self . OutputDir ) ,
self . BuildTarget + " _ " + self . ToolChain ,
)
else :
GlobalData . gBuildDirectory = RetVal = path . join (
self . WorkspaceDir ,
self . OutputDir ,
self . BuildTarget + " _ " + self . ToolChain ,
)
return RetVal
## Return directory of platform makefile
#
# @retval string Makefile directory
#
@cached_property
def MakeFileDir ( self ) :
return path . join ( self . BuildDir , self . Arch )
## Return build command string
#
# @retval string Build command string
#
@cached_property
def BuildCommand ( self ) :
RetVal = [ ]
if " MAKE " in self . ToolDefinition and " PATH " in self . ToolDefinition [ " MAKE " ] :
RetVal + = _SplitOption ( self . ToolDefinition [ " MAKE " ] [ " PATH " ] )
if " FLAGS " in self . ToolDefinition [ " MAKE " ] :
NewOption = self . ToolDefinition [ " MAKE " ] [ " FLAGS " ] . strip ( )
if NewOption != ' ' :
RetVal + = _SplitOption ( NewOption )
if " MAKE " in self . EdkIIBuildOption :
if " FLAGS " in self . EdkIIBuildOption [ " MAKE " ] :
Flags = self . EdkIIBuildOption [ " MAKE " ] [ " FLAGS " ]
if Flags . startswith ( ' = ' ) :
RetVal = [ RetVal [ 0 ] ] + [ Flags [ 1 : ] ]
else :
RetVal . append ( Flags )
return RetVal
## Get tool chain definition
#
# Get each tool definition for given tool chain from tools_def.txt and platform
#
@cached_property
def ToolDefinition ( self ) :
ToolDefinition = self . Workspace . ToolDef . ToolsDefTxtDictionary
if TAB_TOD_DEFINES_COMMAND_TYPE not in self . Workspace . ToolDef . ToolsDefTxtDatabase :
EdkLogger . error ( ' build ' , RESOURCE_NOT_AVAILABLE , " No tools found in configuration " ,
ExtraData = " [ %s ] " % self . MetaFile )
RetVal = OrderedDict ( )
DllPathList = set ( )
for Def in ToolDefinition :
Target , Tag , Arch , Tool , Attr = Def . split ( " _ " )
if Target != self . BuildTarget or Tag != self . ToolChain or Arch != self . Arch :
continue
Value = ToolDefinition [ Def ]
# don't record the DLL
if Attr == " DLL " :
DllPathList . add ( Value )
continue
if Tool not in RetVal :
RetVal [ Tool ] = OrderedDict ( )
RetVal [ Tool ] [ Attr ] = Value
ToolsDef = ' '
if GlobalData . gOptions . SilentMode and " MAKE " in RetVal :
if " FLAGS " not in RetVal [ " MAKE " ] :
RetVal [ " MAKE " ] [ " FLAGS " ] = " "
RetVal [ " MAKE " ] [ " FLAGS " ] + = " -s "
MakeFlags = ' '
for Tool in RetVal :
for Attr in RetVal [ Tool ] :
Value = RetVal [ Tool ] [ Attr ]
if Tool in self . _BuildOptionWithToolDef ( RetVal ) and Attr in self . _BuildOptionWithToolDef ( RetVal ) [ Tool ] :
# check if override is indicated
if self . _BuildOptionWithToolDef ( RetVal ) [ Tool ] [ Attr ] . startswith ( ' = ' ) :
Value = self . _BuildOptionWithToolDef ( RetVal ) [ Tool ] [ Attr ] [ 1 : ]
else :
if Attr != ' PATH ' :
Value + = " " + self . _BuildOptionWithToolDef ( RetVal ) [ Tool ] [ Attr ]
else :
Value = self . _BuildOptionWithToolDef ( RetVal ) [ Tool ] [ Attr ]
if Attr == " PATH " :
# Don't put MAKE definition in the file
if Tool != " MAKE " :
ToolsDef + = " %s = %s \n " % ( Tool , Value )
elif Attr != " DLL " :
# Don't put MAKE definition in the file
if Tool == " MAKE " :
if Attr == " FLAGS " :
MakeFlags = Value
else :
ToolsDef + = " %s _ %s = %s \n " % ( Tool , Attr , Value )
ToolsDef + = " \n "
tool_def_file = os . path . join ( self . MakeFileDir , " TOOLS_DEF. " + self . Arch )
SaveFileOnChange ( tool_def_file , ToolsDef , False )
for DllPath in DllPathList :
os . environ [ " PATH " ] = DllPath + os . pathsep + os . environ [ " PATH " ]
os . environ [ " MAKE_FLAGS " ] = MakeFlags
return RetVal
## Return the paths of tools
@cached_property
def ToolDefinitionFile ( self ) :
tool_def_file = os . path . join ( self . MakeFileDir , " TOOLS_DEF. " + self . Arch )
if not os . path . exists ( tool_def_file ) :
self . ToolDefinition
return tool_def_file
## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
@cached_property
def ToolChainFamily ( self ) :
ToolDefinition = self . Workspace . ToolDef . ToolsDefTxtDatabase
if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
or self . ToolChain not in ToolDefinition [ TAB_TOD_DEFINES_FAMILY ] \
or not ToolDefinition [ TAB_TOD_DEFINES_FAMILY ] [ self . ToolChain ] :
EdkLogger . verbose ( " No tool chain family found in configuration for %s . Default to MSFT. " \
% self . ToolChain )
RetVal = TAB_COMPILER_MSFT
else :
RetVal = ToolDefinition [ TAB_TOD_DEFINES_FAMILY ] [ self . ToolChain ]
return RetVal
@cached_property
def BuildRuleFamily ( self ) :
ToolDefinition = self . Workspace . ToolDef . ToolsDefTxtDatabase
if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
or self . ToolChain not in ToolDefinition [ TAB_TOD_DEFINES_BUILDRULEFAMILY ] \
or not ToolDefinition [ TAB_TOD_DEFINES_BUILDRULEFAMILY ] [ self . ToolChain ] :
EdkLogger . verbose ( " No tool chain family found in configuration for %s . Default to MSFT. " \
% self . ToolChain )
return TAB_COMPILER_MSFT
return ToolDefinition [ TAB_TOD_DEFINES_BUILDRULEFAMILY ] [ self . ToolChain ]
## Return the build options specific for all modules in this platform
@cached_property
def BuildOption ( self ) :
return self . _ExpandBuildOption ( self . Platform . BuildOptions )
def _BuildOptionWithToolDef ( self , ToolDef ) :
return self . _ExpandBuildOption ( self . Platform . BuildOptions , ToolDef = ToolDef )
## Return the build options specific for EDK modules in this platform
@cached_property
def EdkBuildOption ( self ) :
return self . _ExpandBuildOption ( self . Platform . BuildOptions , EDK_NAME )
## Return the build options specific for EDKII modules in this platform
@cached_property
def EdkIIBuildOption ( self ) :
return self . _ExpandBuildOption ( self . Platform . BuildOptions , EDKII_NAME )
## Parse build_rule.txt in Conf Directory.
#
# @retval BuildRule object
#
@cached_property
def BuildRule ( self ) :
BuildRuleFile = None
if TAB_TAT_DEFINES_BUILD_RULE_CONF in self . Workspace . TargetTxt . TargetTxtDictionary :
BuildRuleFile = self . Workspace . TargetTxt . TargetTxtDictionary [ TAB_TAT_DEFINES_BUILD_RULE_CONF ]
if not BuildRuleFile :
BuildRuleFile = gDefaultBuildRuleFile
RetVal = BuildRule ( BuildRuleFile )
if RetVal . _FileVersion == " " :
RetVal . _FileVersion = AutoGenReqBuildRuleVerNum
else :
if RetVal . _FileVersion < AutoGenReqBuildRuleVerNum :
# If Build Rule's version is less than the version number required by the tools, halting the build.
EdkLogger . error ( " build " , AUTOGEN_ERROR ,
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 ]) " \
% ( RetVal . _FileVersion , AutoGenReqBuildRuleVerNum ) )
return RetVal
## Summarize the packages used by modules in this platform
@cached_property
def PackageList ( self ) :
RetVal = set ( )
for Mb in self . _MbList :
RetVal . update ( Mb . Packages )
for lb in Mb . LibInstances :
RetVal . update ( lb . Packages )
#Collect package set information from INF of FDF
for ModuleFile in self . _AsBuildModuleList :
if ModuleFile in self . Platform . Modules :
continue
ModuleData = self . BuildDatabase [ ModuleFile , self . Arch , self . BuildTarget , self . ToolChain ]
RetVal . update ( ModuleData . Packages )
return list ( RetVal )
@cached_property
def NonDynamicPcdDict ( self ) :
return { ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName ) : Pcd for Pcd in self . NonDynamicPcdList }
## Get list of non-dynamic PCDs
@property
def NonDynamicPcdList ( self ) :
if not self . _NonDynamicPcdList :
self . CollectPlatformDynamicPcds ( )
return self . _NonDynamicPcdList
## Get list of dynamic PCDs
@property
def DynamicPcdList ( self ) :
if not self . _DynamicPcdList :
self . CollectPlatformDynamicPcds ( )
return self . _DynamicPcdList
## Generate Token Number for all PCD
@cached_property
def PcdTokenNumber ( self ) :
RetVal = OrderedDict ( )
TokenNumber = 1
#
# Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
# Such as:
#
# Dynamic PCD:
# TokenNumber 0 ~ 10
# DynamicEx PCD:
# TokeNumber 11 ~ 20
#
for Pcd in self . DynamicPcdList :
if Pcd . Phase == " PEI " and Pcd . Type in PCD_DYNAMIC_TYPE_SET :
EdkLogger . debug ( EdkLogger . DEBUG_5 , " %s %s ( %s ) -> %d " % ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName , Pcd . Phase , TokenNumber ) )
RetVal [ Pcd . TokenCName , Pcd . TokenSpaceGuidCName ] = TokenNumber
TokenNumber + = 1
for Pcd in self . DynamicPcdList :
if Pcd . Phase == " PEI " and Pcd . Type in PCD_DYNAMIC_EX_TYPE_SET :
EdkLogger . debug ( EdkLogger . DEBUG_5 , " %s %s ( %s ) -> %d " % ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName , Pcd . Phase , TokenNumber ) )
RetVal [ Pcd . TokenCName , Pcd . TokenSpaceGuidCName ] = TokenNumber
TokenNumber + = 1
for Pcd in self . DynamicPcdList :
if Pcd . Phase == " DXE " and Pcd . Type in PCD_DYNAMIC_TYPE_SET :
EdkLogger . debug ( EdkLogger . DEBUG_5 , " %s %s ( %s ) -> %d " % ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName , Pcd . Phase , TokenNumber ) )
RetVal [ Pcd . TokenCName , Pcd . TokenSpaceGuidCName ] = TokenNumber
TokenNumber + = 1
for Pcd in self . DynamicPcdList :
if Pcd . Phase == " DXE " and Pcd . Type in PCD_DYNAMIC_EX_TYPE_SET :
EdkLogger . debug ( EdkLogger . DEBUG_5 , " %s %s ( %s ) -> %d " % ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName , Pcd . Phase , TokenNumber ) )
RetVal [ Pcd . TokenCName , Pcd . TokenSpaceGuidCName ] = TokenNumber
TokenNumber + = 1
for Pcd in self . NonDynamicPcdList :
RetVal [ Pcd . TokenCName , Pcd . TokenSpaceGuidCName ] = TokenNumber
TokenNumber + = 1
return RetVal
@cached_property
def _MbList ( self ) :
return [ self . BuildDatabase [ m , self . Arch , self . BuildTarget , self . ToolChain ] for m in self . Platform . Modules ]
@cached_property
def _MaList ( self ) :
for ModuleFile in self . Platform . Modules :
Ma = ModuleAutoGen (
self . Workspace ,
ModuleFile ,
self . BuildTarget ,
self . ToolChain ,
self . Arch ,
self . MetaFile ,
self . DataPipe
)
self . Platform . Modules [ ModuleFile ] . M = Ma
return [ x . M for x in self . Platform . Modules . values ( ) ]
## Summarize ModuleAutoGen objects of all modules to be built for this platform
@cached_property
def ModuleAutoGenList ( self ) :
RetVal = [ ]
for Ma in self . _MaList :
if Ma not in RetVal :
RetVal . append ( Ma )
return RetVal
## Summarize ModuleAutoGen objects of all libraries to be built for this platform
@cached_property
def LibraryAutoGenList ( self ) :
RetVal = [ ]
for Ma in self . _MaList :
for La in Ma . LibraryAutoGenList :
if La not in RetVal :
RetVal . append ( La )
if Ma not in La . ReferenceModules :
La . ReferenceModules . append ( Ma )
return RetVal
## Test if a module is supported by the platform
#
# An error will be raised directly if the module or its arch is not supported
# by the platform or current configuration
#
def ValidModule ( self , Module ) :
return Module in self . Platform . Modules or Module in self . Platform . LibraryInstances \
or Module in self . _AsBuildModuleList
@cached_property
def GetAllModuleInfo ( self , WithoutPcd = True ) :
ModuleLibs = set ( )
for m in self . Platform . Modules :
module_obj = self . BuildDatabase [ m , self . Arch , self . BuildTarget , self . ToolChain ]
if not bool ( module_obj . LibraryClass ) :
Libs = GetModuleLibInstances ( module_obj , self . Platform , self . BuildDatabase , self . Arch , self . BuildTarget , self . ToolChain , self . MetaFile , EdkLogger )
else :
Libs = [ ]
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 ] ) )
if WithoutPcd and module_obj . PcdIsDriver :
continue
ModuleLibs . add ( ( m . File , m . Root , m . Path , m . BaseName , m . OriginalPath , module_obj . Arch , bool ( module_obj . LibraryClass ) ) )
return ModuleLibs
## Resolve the library classes in a module to library instances
#
# This method will not only resolve library classes but also sort the library
# instances according to the dependency-ship.
#
# @param Module The module from which the library classes will be resolved
#
# @retval library_list List of library instances sorted
#
def ApplyLibraryInstance ( self , Module ) :
# Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
if str ( Module ) not in self . Platform . Modules :
return [ ]
return GetModuleLibInstances ( Module ,
self . Platform ,
self . BuildDatabase ,
self . Arch ,
self . BuildTarget ,
self . ToolChain ,
self . MetaFile ,
EdkLogger )
## Override PCD setting (type, value, ...)
#
# @param ToPcd The PCD to be overridden
# @param FromPcd The PCD overriding from
#
def _OverridePcd ( self , ToPcd , FromPcd , Module = " " , Msg = " " , Library = " " ) :
#
# in case there's PCDs coming from FDF file, which have no type given.
# at this point, ToPcd.Type has the type found from dependent
# package
#
TokenCName = ToPcd . TokenCName
for PcdItem in GlobalData . MixedPcd :
if ( ToPcd . TokenCName , ToPcd . TokenSpaceGuidCName ) in GlobalData . MixedPcd [ PcdItem ] :
TokenCName = PcdItem [ 0 ]
break
if FromPcd is not None :
if ToPcd . Pending and FromPcd . Type :
ToPcd . Type = FromPcd . Type
elif ToPcd . Type and FromPcd . Type \
and ToPcd . Type != FromPcd . Type and ToPcd . Type in FromPcd . Type :
if ToPcd . Type . strip ( ) == TAB_PCDS_DYNAMIC_EX :
ToPcd . Type = FromPcd . Type
elif ToPcd . Type and FromPcd . Type \
and ToPcd . Type != FromPcd . Type :
if Library :
Module = str ( Module ) + " ' s library file ( " + str ( Library ) + " ) "
EdkLogger . error ( " build " , OPTION_CONFLICT , " Mismatched PCD type " ,
ExtraData = " %s . %s is used as [ %s ] in module %s , but as [ %s ] in %s . " \
% ( ToPcd . TokenSpaceGuidCName , TokenCName ,
ToPcd . Type , Module , FromPcd . Type , Msg ) ,
File = self . MetaFile )
if FromPcd . MaxDatumSize :
ToPcd . MaxDatumSize = FromPcd . MaxDatumSize
ToPcd . MaxSizeUserSet = FromPcd . MaxDatumSize
if FromPcd . DefaultValue :
ToPcd . DefaultValue = FromPcd . DefaultValue
if FromPcd . TokenValue :
ToPcd . TokenValue = FromPcd . TokenValue
if FromPcd . DatumType :
ToPcd . DatumType = FromPcd . DatumType
if FromPcd . SkuInfoList :
ToPcd . SkuInfoList = FromPcd . SkuInfoList
if FromPcd . UserDefinedDefaultStoresFlag :
ToPcd . UserDefinedDefaultStoresFlag = FromPcd . UserDefinedDefaultStoresFlag
# Add Flexible PCD format parse
if ToPcd . DefaultValue :
try :
ToPcd . DefaultValue = ValueExpressionEx ( ToPcd . DefaultValue , ToPcd . DatumType , self . Platform . _GuidDict ) ( True )
except BadExpression as Value :
EdkLogger . error ( ' Parser ' , FORMAT_INVALID , ' PCD [ %s . %s ] Value " %s " , %s ' % ( ToPcd . TokenSpaceGuidCName , ToPcd . TokenCName , ToPcd . DefaultValue , Value ) ,
File = self . MetaFile )
# check the validation of datum
IsValid , Cause = CheckPcdDatum ( ToPcd . DatumType , ToPcd . DefaultValue )
if not IsValid :
EdkLogger . error ( ' build ' , FORMAT_INVALID , Cause , File = self . MetaFile ,
ExtraData = " %s . %s " % ( ToPcd . TokenSpaceGuidCName , TokenCName ) )
ToPcd . validateranges = FromPcd . validateranges
ToPcd . validlists = FromPcd . validlists
ToPcd . expressions = FromPcd . expressions
ToPcd . CustomAttribute = FromPcd . CustomAttribute
if FromPcd is not None and ToPcd . DatumType == TAB_VOID and not ToPcd . MaxDatumSize :
EdkLogger . debug ( EdkLogger . DEBUG_9 , " No MaxDatumSize specified for PCD %s . %s " \
% ( ToPcd . TokenSpaceGuidCName , TokenCName ) )
Value = ToPcd . DefaultValue
if not Value :
ToPcd . MaxDatumSize = ' 1 '
elif Value [ 0 ] == ' L ' :
ToPcd . MaxDatumSize = str ( ( len ( Value ) - 2 ) * 2 )
elif Value [ 0 ] == ' { ' :
ToPcd . MaxDatumSize = str ( len ( Value . split ( ' , ' ) ) )
else :
ToPcd . MaxDatumSize = str ( len ( Value ) - 1 )
# apply default SKU for dynamic PCDS if specified one is not available
if ( ToPcd . Type in PCD_DYNAMIC_TYPE_SET or ToPcd . Type in PCD_DYNAMIC_EX_TYPE_SET ) \
and not ToPcd . SkuInfoList :
if self . Platform . SkuName in self . Platform . SkuIds :
SkuName = self . Platform . SkuName
else :
SkuName = TAB_DEFAULT
ToPcd . SkuInfoList = {
SkuName : SkuInfoClass ( SkuName , self . Platform . SkuIds [ SkuName ] [ 0 ] , ' ' , ' ' , ' ' , ' ' , ' ' , ToPcd . DefaultValue )
}
## Apply PCD setting defined platform to a module
#
# @param Module The module from which the PCD setting will be overridden
#
# @retval PCD_list The list PCDs with settings from platform
#
def ApplyPcdSetting ( self , Module , Pcds , Library = " " ) :
# for each PCD in module
for Name , Guid in Pcds :
PcdInModule = Pcds [ Name , Guid ]
# find out the PCD setting in platform
if ( Name , Guid ) in self . Platform . Pcds :
PcdInPlatform = self . Platform . Pcds [ Name , Guid ]
else :
PcdInPlatform = None
# then override the settings if any
self . _OverridePcd ( PcdInModule , PcdInPlatform , Module , Msg = " DSC PCD sections " , Library = Library )
# resolve the VariableGuid value
for SkuId in PcdInModule . SkuInfoList :
Sku = PcdInModule . SkuInfoList [ SkuId ]
if Sku . VariableGuid == ' ' : continue
Sku . VariableGuidValue = GuidValue ( Sku . VariableGuid , self . PackageList , self . MetaFile . Path )
if Sku . VariableGuidValue is None :
PackageList = " \n \t " . join ( str ( P ) for P in self . PackageList )
EdkLogger . error (
' build ' ,
RESOURCE_NOT_AVAILABLE ,
" Value of GUID [ %s ] is not found in " % Sku . VariableGuid ,
ExtraData = PackageList + " \n \t (used with %s . %s from module %s ) " \
% ( Guid , Name , str ( Module ) ) ,
File = self . MetaFile
)
# override PCD settings with module specific setting
if Module in self . Platform . Modules :
PlatformModule = self . Platform . Modules [ str ( Module ) ]
for Key in PlatformModule . Pcds :
if GlobalData . BuildOptionPcd :
for pcd in GlobalData . BuildOptionPcd :
( TokenSpaceGuidCName , TokenCName , FieldName , pcdvalue , _ ) = pcd
if ( TokenCName , TokenSpaceGuidCName ) == Key and FieldName == " " :
PlatformModule . Pcds [ Key ] . DefaultValue = pcdvalue
PlatformModule . Pcds [ Key ] . PcdValueFromComm = pcdvalue
break
Flag = False
if Key in Pcds :
ToPcd = Pcds [ Key ]
Flag = True
elif Key in GlobalData . MixedPcd :
for PcdItem in GlobalData . MixedPcd [ Key ] :
if PcdItem in Pcds :
ToPcd = Pcds [ PcdItem ]
Flag = True
break
if Flag :
self . _OverridePcd ( ToPcd , PlatformModule . Pcds [ Key ] , Module , Msg = " DSC Components Module scoped PCD section " , Library = Library )
# use PCD value to calculate the MaxDatumSize when it is not specified
for Name , Guid in Pcds :
Pcd = Pcds [ Name , Guid ]
if Pcd . DatumType == TAB_VOID and not Pcd . MaxDatumSize :
Pcd . MaxSizeUserSet = None
Value = Pcd . DefaultValue
if not Value :
Pcd . MaxDatumSize = ' 1 '
elif Value [ 0 ] == ' L ' :
Pcd . MaxDatumSize = str ( ( len ( Value ) - 2 ) * 2 )
elif Value [ 0 ] == ' { ' :
Pcd . MaxDatumSize = str ( len ( Value . split ( ' , ' ) ) )
else :
Pcd . MaxDatumSize = str ( len ( Value ) - 1 )
return list ( Pcds . values ( ) )
## Append build options in platform to a module
#
# @param Module The module to which the build options will be appended
#
# @retval options The options appended with build options in platform
#
def ApplyBuildOption ( self , Module ) :
# Get the different options for the different style module
PlatformOptions = self . EdkIIBuildOption
ModuleTypeOptions = self . Platform . GetBuildOptionsByModuleType ( EDKII_NAME , Module . ModuleType )
ModuleTypeOptions = self . _ExpandBuildOption ( ModuleTypeOptions )
ModuleOptions = self . _ExpandBuildOption ( Module . BuildOptions )
if Module in self . Platform . Modules :
PlatformModule = self . Platform . Modules [ str ( Module ) ]
PlatformModuleOptions = self . _ExpandBuildOption ( PlatformModule . BuildOptions )
else :
PlatformModuleOptions = { }
BuildRuleOrder = None
for Options in [ self . ToolDefinition , ModuleOptions , PlatformOptions , ModuleTypeOptions , PlatformModuleOptions ] :
for Tool in Options :
for Attr in Options [ Tool ] :
if Attr == TAB_TOD_DEFINES_BUILDRULEORDER :
BuildRuleOrder = Options [ Tool ] [ Attr ]
AllTools = set ( list ( ModuleOptions . keys ( ) ) + list ( PlatformOptions . keys ( ) ) +
list ( PlatformModuleOptions . keys ( ) ) + list ( ModuleTypeOptions . keys ( ) ) +
list ( self . ToolDefinition . keys ( ) ) )
BuildOptions = defaultdict ( lambda : defaultdict ( str ) )
for Tool in AllTools :
for Options in [ self . ToolDefinition , ModuleOptions , PlatformOptions , ModuleTypeOptions , PlatformModuleOptions ] :
if Tool not in Options :
continue
for Attr in Options [ Tool ] :
#
# Do not generate it in Makefile
#
if Attr == TAB_TOD_DEFINES_BUILDRULEORDER :
continue
Value = Options [ Tool ] [ Attr ]
# check if override is indicated
if Value . startswith ( ' = ' ) :
BuildOptions [ Tool ] [ Attr ] = mws . handleWsMacro ( Value [ 1 : ] )
else :
if Attr != ' PATH ' :
BuildOptions [ Tool ] [ Attr ] + = " " + mws . handleWsMacro ( Value )
else :
BuildOptions [ Tool ] [ Attr ] = mws . handleWsMacro ( Value )
return BuildOptions , BuildRuleOrder
def GetGlobalBuildOptions ( self , Module ) :
ModuleTypeOptions = self . Platform . GetBuildOptionsByModuleType ( EDKII_NAME , Module . ModuleType )
ModuleTypeOptions = self . _ExpandBuildOption ( ModuleTypeOptions )
if Module in self . Platform . Modules :
PlatformModule = self . Platform . Modules [ str ( Module ) ]
PlatformModuleOptions = self . _ExpandBuildOption ( PlatformModule . BuildOptions )
else :
PlatformModuleOptions = { }
return ModuleTypeOptions , PlatformModuleOptions
def ModuleGuid ( self , Module ) :
if os . path . basename ( Module . MetaFile . File ) != os . path . basename ( Module . MetaFile . Path ) :
#
# Length of GUID is 36
#
return os . path . basename ( Module . MetaFile . Path ) [ : 36 ]
return Module . Guid
@cached_property
def UniqueBaseName ( self ) :
retVal = { }
ModuleNameDict = { }
UniqueName = { }
for Module in self . _MbList :
unique_base_name = ' %s _ %s ' % ( Module . BaseName , self . ModuleGuid ( Module ) )
if unique_base_name not in ModuleNameDict :
ModuleNameDict [ unique_base_name ] = [ ]
ModuleNameDict [ unique_base_name ] . append ( Module . MetaFile )
if Module . BaseName not in UniqueName :
UniqueName [ Module . BaseName ] = set ( )
UniqueName [ Module . BaseName ] . add ( ( self . ModuleGuid ( Module ) , Module . MetaFile ) )
for module_paths in ModuleNameDict . values ( ) :
if len ( set ( module_paths ) ) > 1 :
samemodules = list ( set ( module_paths ) )
EdkLogger . error ( " build " , FILE_DUPLICATED , ' Modules have same BaseName and FILE_GUID: \n '
' %s \n %s ' % ( samemodules [ 0 ] , samemodules [ 1 ] ) )
for name in UniqueName :
Guid_Path = UniqueName [ name ]
if len ( Guid_Path ) > 1 :
for guid , mpath in Guid_Path :
retVal [ ( name , mpath ) ] = ' %s _ %s ' % ( name , guid )
return retVal
## Expand * in build option key
#
# @param Options Options to be expanded
# @param ToolDef Use specified ToolDef instead of full version.
# This is needed during initialization to prevent
# infinite recursion betweeh BuildOptions,
# ToolDefinition, and this function.
#
# @retval options Options expanded
#
def _ExpandBuildOption ( self , Options , ModuleStyle = None , ToolDef = None ) :
if not ToolDef :
ToolDef = self . ToolDefinition
BuildOptions = { }
FamilyMatch = False
FamilyIsNull = True
OverrideList = { }
#
# Construct a list contain the build options which need override.
#
for Key in Options :
#
# Key[0] -- tool family
# Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
#
if ( Key [ 0 ] == self . BuildRuleFamily and
( ModuleStyle is None or len ( Key ) < 3 or ( len ( Key ) > 2 and Key [ 2 ] == ModuleStyle ) ) ) :
Target , ToolChain , Arch , CommandType , Attr = Key [ 1 ] . split ( ' _ ' )
if ( Target == self . BuildTarget or Target == TAB_STAR ) and \
( ToolChain == self . ToolChain or ToolChain == TAB_STAR ) and \
( Arch == self . Arch or Arch == TAB_STAR ) and \
Options [ Key ] . startswith ( " = " ) :
if OverrideList . get ( Key [ 1 ] ) is not None :
OverrideList . pop ( Key [ 1 ] )
OverrideList [ Key [ 1 ] ] = Options [ Key ]
#
# Use the highest priority value.
#
if ( len ( OverrideList ) > = 2 ) :
KeyList = list ( OverrideList . keys ( ) )
for Index in range ( len ( KeyList ) ) :
NowKey = KeyList [ Index ]
Target1 , ToolChain1 , Arch1 , CommandType1 , Attr1 = NowKey . split ( " _ " )
for Index1 in range ( len ( KeyList ) - Index - 1 ) :
NextKey = KeyList [ Index1 + Index + 1 ]
#
# Compare two Key, if one is included by another, choose the higher priority one
#
Target2 , ToolChain2 , Arch2 , CommandType2 , Attr2 = NextKey . split ( " _ " )
if ( Target1 == Target2 or Target1 == TAB_STAR or Target2 == TAB_STAR ) and \
( ToolChain1 == ToolChain2 or ToolChain1 == TAB_STAR or ToolChain2 == TAB_STAR ) and \
( Arch1 == Arch2 or Arch1 == TAB_STAR or Arch2 == TAB_STAR ) and \
( CommandType1 == CommandType2 or CommandType1 == TAB_STAR or CommandType2 == TAB_STAR ) and \
( Attr1 == Attr2 or Attr1 == TAB_STAR or Attr2 == TAB_STAR ) :
if CalculatePriorityValue ( NowKey ) > CalculatePriorityValue ( NextKey ) :
if Options . get ( ( self . BuildRuleFamily , NextKey ) ) is not None :
Options . pop ( ( self . BuildRuleFamily , NextKey ) )
else :
if Options . get ( ( self . BuildRuleFamily , NowKey ) ) is not None :
Options . pop ( ( self . BuildRuleFamily , NowKey ) )
for Key in Options :
if ModuleStyle is not None and len ( Key ) > 2 :
# Check Module style is EDK or EDKII.
# Only append build option for the matched style module.
if ModuleStyle == EDK_NAME and Key [ 2 ] != EDK_NAME :
continue
elif ModuleStyle == EDKII_NAME and Key [ 2 ] != EDKII_NAME :
continue
Family = Key [ 0 ]
Target , Tag , Arch , Tool , Attr = Key [ 1 ] . split ( " _ " )
# if tool chain family doesn't match, skip it
if Tool in ToolDef and Family != " " :
FamilyIsNull = False
if ToolDef [ Tool ] . get ( TAB_TOD_DEFINES_BUILDRULEFAMILY , " " ) != " " :
if Family != ToolDef [ Tool ] [ TAB_TOD_DEFINES_BUILDRULEFAMILY ] :
continue
elif Family != ToolDef [ Tool ] [ TAB_TOD_DEFINES_FAMILY ] :
continue
FamilyMatch = True
# expand any wildcard
if Target == TAB_STAR or Target == self . BuildTarget :
if Tag == TAB_STAR or Tag == self . ToolChain :
if Arch == TAB_STAR or Arch == self . Arch :
if Tool not in BuildOptions :
BuildOptions [ Tool ] = { }
if Attr != " FLAGS " or Attr not in BuildOptions [ Tool ] or Options [ Key ] . startswith ( ' = ' ) :
BuildOptions [ Tool ] [ Attr ] = Options [ Key ]
else :
# append options for the same tool except PATH
if Attr != ' PATH ' :
BuildOptions [ Tool ] [ Attr ] + = " " + Options [ Key ]
else :
BuildOptions [ Tool ] [ Attr ] = Options [ Key ]
# Build Option Family has been checked, which need't to be checked again for family.
if FamilyMatch or FamilyIsNull :
return BuildOptions
for Key in Options :
if ModuleStyle is not None and len ( Key ) > 2 :
# Check Module style is EDK or EDKII.
# Only append build option for the matched style module.
if ModuleStyle == EDK_NAME and Key [ 2 ] != EDK_NAME :
continue
elif ModuleStyle == EDKII_NAME and Key [ 2 ] != EDKII_NAME :
continue
Family = Key [ 0 ]
Target , Tag , Arch , Tool , Attr = Key [ 1 ] . split ( " _ " )
# if tool chain family doesn't match, skip it
if Tool not in ToolDef or Family == " " :
continue
# option has been added before
if Family != ToolDef [ Tool ] [ TAB_TOD_DEFINES_FAMILY ] :
continue
# expand any wildcard
if Target == TAB_STAR or Target == self . BuildTarget :
if Tag == TAB_STAR or Tag == self . ToolChain :
if Arch == TAB_STAR or Arch == self . Arch :
if Tool not in BuildOptions :
BuildOptions [ Tool ] = { }
if Attr != " FLAGS " or Attr not in BuildOptions [ Tool ] or Options [ Key ] . startswith ( ' = ' ) :
BuildOptions [ Tool ] [ Attr ] = Options [ Key ]
else :
# append options for the same tool except PATH
if Attr != ' PATH ' :
BuildOptions [ Tool ] [ Attr ] + = " " + Options [ Key ]
else :
BuildOptions [ Tool ] [ Attr ] = Options [ Key ]
return BuildOptions