mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-11-28 12:25:19 +01:00
02287fbb4b
Signed-off-by: SergeySlice <sergey.slice@gmail.com>
675 lines
30 KiB
Python
675 lines
30 KiB
Python
## @file
|
|
# Create makefile for MS nmake and GNU make
|
|
#
|
|
# Copyright (c) 2019 - 2021, Intel Corporation. All rights reserved.<BR>
|
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
#
|
|
from __future__ import absolute_import
|
|
from Workspace.WorkspaceDatabase import WorkspaceDatabase,BuildDB
|
|
from Common.caching import cached_property
|
|
from AutoGen.BuildEngine import BuildRule,AutoGenReqBuildRuleVerNum
|
|
from AutoGen.AutoGen import CalculatePriorityValue
|
|
from Common.Misc import CheckPcdDatum,GuidValue
|
|
from Common.Expression import ValueExpressionEx
|
|
from Common.DataType import *
|
|
from CommonDataClass.Exceptions import *
|
|
from CommonDataClass.CommonClass import SkuInfoClass
|
|
import Common.EdkLogger as EdkLogger
|
|
from Common.BuildToolError import OPTION_CONFLICT,FORMAT_INVALID,RESOURCE_NOT_AVAILABLE
|
|
from Common.MultipleWorkspace import MultipleWorkspace as mws
|
|
from collections import defaultdict
|
|
from Common.Misc import PathClass
|
|
import os
|
|
|
|
|
|
#
|
|
# The priority list while override build option
|
|
#
|
|
PrioList = {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
|
|
"0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
|
|
"0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
|
|
"0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
|
|
"0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
|
|
"0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
|
|
"0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
|
|
"0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
|
|
"0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
|
|
"0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
|
|
"0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
|
|
"0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
|
|
"0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
|
|
"0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
|
|
"0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
|
|
"0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
|
|
## Base class for AutoGen
|
|
#
|
|
# This class just implements the cache mechanism of AutoGen objects.
|
|
#
|
|
class AutoGenInfo(object):
|
|
# database to maintain the objects in each child class
|
|
__ObjectCache = {} # (BuildTarget, ToolChain, ARCH, platform file): AutoGen object
|
|
|
|
## Factory method
|
|
#
|
|
# @param Class class object of real AutoGen class
|
|
# (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
|
|
# @param Workspace Workspace directory or WorkspaceAutoGen object
|
|
# @param MetaFile The path of meta file
|
|
# @param Target Build target
|
|
# @param Toolchain Tool chain name
|
|
# @param Arch Target arch
|
|
# @param *args The specific class related parameters
|
|
# @param **kwargs The specific class related dict parameters
|
|
#
|
|
@classmethod
|
|
def GetCache(cls):
|
|
return cls.__ObjectCache
|
|
def __new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
|
|
# check if the object has been created
|
|
Key = (Target, Toolchain, Arch, MetaFile)
|
|
if Key in cls.__ObjectCache:
|
|
# if it exists, just return it directly
|
|
return cls.__ObjectCache[Key]
|
|
# it didnt exist. create it, cache it, then return it
|
|
RetVal = cls.__ObjectCache[Key] = super(AutoGenInfo, cls).__new__(cls)
|
|
return RetVal
|
|
|
|
|
|
## hash() operator
|
|
#
|
|
# The file path of platform file will be used to represent hash value of this object
|
|
#
|
|
# @retval int Hash value of the file path of platform file
|
|
#
|
|
def __hash__(self):
|
|
return hash(self.MetaFile)
|
|
|
|
## str() operator
|
|
#
|
|
# The file path of platform file will be used to represent this object
|
|
#
|
|
# @retval string String of platform file path
|
|
#
|
|
def __str__(self):
|
|
return str(self.MetaFile)
|
|
|
|
## "==" operator
|
|
def __eq__(self, Other):
|
|
return Other and self.MetaFile == Other
|
|
|
|
## 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 Family != "":
|
|
Found = False
|
|
if Tool in ToolDef:
|
|
FamilyIsNull = False
|
|
if TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDef[Tool]:
|
|
if Family == ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
|
|
FamilyMatch = True
|
|
Found = True
|
|
if TAB_STAR in ToolDef:
|
|
FamilyIsNull = False
|
|
if TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDef[TAB_STAR]:
|
|
if Family == ToolDef[TAB_STAR][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
|
|
FamilyMatch = True
|
|
Found = True
|
|
if not Found:
|
|
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]
|
|
# 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 Family == "":
|
|
continue
|
|
# option has been added before
|
|
Found = False
|
|
if Tool in ToolDef:
|
|
if TAB_TOD_DEFINES_FAMILY in ToolDef[Tool]:
|
|
if Family == ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
|
|
Found = True
|
|
if TAB_STAR in ToolDef:
|
|
if TAB_TOD_DEFINES_FAMILY in ToolDef[TAB_STAR]:
|
|
if Family == ToolDef[TAB_STAR][TAB_TOD_DEFINES_FAMILY]:
|
|
Found = True
|
|
if not Found:
|
|
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
|
|
#
|
|
#This class is the pruned WorkSpaceAutoGen for ModuleAutoGen in multiple thread
|
|
#
|
|
class WorkSpaceInfo(AutoGenInfo):
|
|
def __init__(self,Workspace, MetaFile, Target, ToolChain, Arch):
|
|
if not hasattr(self, "_Init"):
|
|
self.do_init(Workspace, MetaFile, Target, ToolChain, Arch)
|
|
self._Init = True
|
|
def do_init(self,Workspace, MetaFile, Target, ToolChain, Arch):
|
|
self._SrcTimeStamp = 0
|
|
self.Db = BuildDB
|
|
self.BuildDatabase = self.Db.BuildObject
|
|
self.Target = Target
|
|
self.ToolChain = ToolChain
|
|
self.WorkspaceDir = Workspace
|
|
self.ActivePlatform = MetaFile
|
|
self.ArchList = Arch
|
|
self.AutoGenObjectList = []
|
|
@property
|
|
def BuildDir(self):
|
|
return self.AutoGenObjectList[0].BuildDir
|
|
|
|
@property
|
|
def Name(self):
|
|
return self.AutoGenObjectList[0].Platform.PlatformName
|
|
|
|
@property
|
|
def FlashDefinition(self):
|
|
return self.AutoGenObjectList[0].Platform.FlashDefinition
|
|
@property
|
|
def GenFdsCommandDict(self):
|
|
FdsCommandDict = self.AutoGenObjectList[0].DataPipe.Get("FdsCommandDict")
|
|
if FdsCommandDict:
|
|
return FdsCommandDict
|
|
return {}
|
|
|
|
@cached_property
|
|
def FvDir(self):
|
|
return os.path.join(self.BuildDir, TAB_FV_DIRECTORY)
|
|
|
|
class PlatformInfo(AutoGenInfo):
|
|
def __init__(self, Workspace, MetaFile, Target, ToolChain, Arch,DataPipe):
|
|
if not hasattr(self, "_Init"):
|
|
self.do_init(Workspace, MetaFile, Target, ToolChain, Arch,DataPipe)
|
|
self._Init = True
|
|
def do_init(self,Workspace, MetaFile, Target, ToolChain, Arch,DataPipe):
|
|
self.Wa = Workspace
|
|
self.WorkspaceDir = self.Wa.WorkspaceDir
|
|
self.MetaFile = MetaFile
|
|
self.Arch = Arch
|
|
self.Target = Target
|
|
self.BuildTarget = Target
|
|
self.ToolChain = ToolChain
|
|
self.Platform = self.Wa.BuildDatabase[self.MetaFile, self.Arch, self.Target, self.ToolChain]
|
|
|
|
self.SourceDir = MetaFile.SubDir
|
|
self.DataPipe = DataPipe
|
|
@cached_property
|
|
def _AsBuildModuleList(self):
|
|
retVal = self.DataPipe.Get("AsBuildModuleList")
|
|
if retVal is None:
|
|
retVal = {}
|
|
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 ToolChainFamily(self):
|
|
retVal = self.DataPipe.Get("ToolChainFamily")
|
|
if retVal is None:
|
|
retVal = {}
|
|
return retVal
|
|
|
|
@cached_property
|
|
def BuildRuleFamily(self):
|
|
retVal = self.DataPipe.Get("BuildRuleFamily")
|
|
if retVal is None:
|
|
retVal = {}
|
|
return retVal
|
|
|
|
@cached_property
|
|
def _MbList(self):
|
|
return [self.Wa.BuildDatabase[m, self.Arch, self.BuildTarget, self.ToolChain] for m in self.Platform.Modules]
|
|
|
|
@cached_property
|
|
def PackageList(self):
|
|
RetVal = set()
|
|
for dec_file,Arch in self.DataPipe.Get("PackageList"):
|
|
RetVal.add(self.Wa.BuildDatabase[dec_file,Arch,self.BuildTarget, self.ToolChain])
|
|
return list(RetVal)
|
|
|
|
## Return the directory to store all intermediate and final files built
|
|
@cached_property
|
|
def BuildDir(self):
|
|
if os.path.isabs(self.OutputDir):
|
|
RetVal = os.path.join(
|
|
os.path.abspath(self.OutputDir),
|
|
self.Target + "_" + self.ToolChain,
|
|
)
|
|
else:
|
|
RetVal = os.path.join(
|
|
self.WorkspaceDir,
|
|
self.OutputDir,
|
|
self.Target + "_" + self.ToolChain,
|
|
)
|
|
return RetVal
|
|
|
|
## Return the build output directory platform specifies
|
|
@cached_property
|
|
def OutputDir(self):
|
|
return self.Platform.OutputDirectory
|
|
|
|
## Return platform name
|
|
@cached_property
|
|
def Name(self):
|
|
return self.Platform.PlatformName
|
|
|
|
## Return meta-file GUID
|
|
@cached_property
|
|
def Guid(self):
|
|
return self.Platform.Guid
|
|
|
|
## Return platform version
|
|
@cached_property
|
|
def Version(self):
|
|
return self.Platform.Version
|
|
|
|
## Return paths of tools
|
|
@cached_property
|
|
def ToolDefinition(self):
|
|
retVal = self.DataPipe.Get("TOOLDEF")
|
|
if retVal is None:
|
|
retVal = {}
|
|
return retVal
|
|
|
|
## Return build command string
|
|
#
|
|
# @retval string Build command string
|
|
#
|
|
@cached_property
|
|
def BuildCommand(self):
|
|
retVal = self.DataPipe.Get("BuildCommand")
|
|
if retVal is None:
|
|
retVal = []
|
|
return retVal
|
|
|
|
@cached_property
|
|
def PcdTokenNumber(self):
|
|
retVal = self.DataPipe.Get("PCD_TNUM")
|
|
if retVal is None:
|
|
retVal = {}
|
|
return retVal
|
|
|
|
## 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 self.MixedPcd:
|
|
if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in self.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._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)
|
|
}
|
|
|
|
def ApplyPcdSetting(self, Ma, Pcds, Library=""):
|
|
# for each PCD in module
|
|
Module=Ma.Module
|
|
for Name, Guid in Pcds:
|
|
PcdInModule = Pcds[Name, Guid]
|
|
# find out the PCD setting in platform
|
|
if (Name, Guid) in self.Pcds:
|
|
PcdInPlatform = self.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
|
|
ModuleScopePcds = self.DataPipe.Get("MOL_PCDS")
|
|
if Module in self.Platform.Modules:
|
|
PlatformModule = self.Platform.Modules[str(Module)]
|
|
PCD_DATA = ModuleScopePcds.get(Ma.Guid,{})
|
|
mPcds = {(pcd.TokenCName,pcd.TokenSpaceGuidCName): pcd for pcd in PCD_DATA}
|
|
for Key in mPcds:
|
|
if self.BuildOptionPcd:
|
|
for pcd in self.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 self.MixedPcd:
|
|
for PcdItem in self.MixedPcd[Key]:
|
|
if PcdItem in Pcds:
|
|
ToPcd = Pcds[PcdItem]
|
|
Flag = True
|
|
break
|
|
if Flag:
|
|
self._OverridePcd(ToPcd, mPcds[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())
|
|
|
|
@cached_property
|
|
def Pcds(self):
|
|
PlatformPcdData = self.DataPipe.Get("PLA_PCD")
|
|
# for pcd in PlatformPcdData:
|
|
# for skuid in pcd.SkuInfoList:
|
|
# pcd.SkuInfoList[skuid] = self.CreateSkuInfoFromDict(pcd.SkuInfoList[skuid])
|
|
return {(pcddata.TokenCName,pcddata.TokenSpaceGuidCName):pcddata for pcddata in PlatformPcdData}
|
|
|
|
def CreateSkuInfoFromDict(self,SkuInfoDict):
|
|
return SkuInfoClass(
|
|
SkuInfoDict.get("SkuIdName"),
|
|
SkuInfoDict.get("SkuId"),
|
|
SkuInfoDict.get("VariableName"),
|
|
SkuInfoDict.get("VariableGuid"),
|
|
SkuInfoDict.get("VariableOffset"),
|
|
SkuInfoDict.get("HiiDefaultValue"),
|
|
SkuInfoDict.get("VpdOffset"),
|
|
SkuInfoDict.get("DefaultValue"),
|
|
SkuInfoDict.get("VariableGuidValue"),
|
|
SkuInfoDict.get("VariableAttribute",""),
|
|
SkuInfoDict.get("DefaultStore",None)
|
|
)
|
|
@cached_property
|
|
def MixedPcd(self):
|
|
return self.DataPipe.Get("MixedPcd")
|
|
@cached_property
|
|
def _GuidDict(self):
|
|
RetVal = self.DataPipe.Get("GuidDict")
|
|
if RetVal is None:
|
|
RetVal = {}
|
|
return RetVal
|
|
@cached_property
|
|
def BuildOptionPcd(self):
|
|
return self.DataPipe.Get("BuildOptPcd")
|
|
def ApplyBuildOption(self,module):
|
|
PlatformOptions = self.DataPipe.Get("PLA_BO")
|
|
ModuleBuildOptions = self.DataPipe.Get("MOL_BO")
|
|
ModuleOptionFromDsc = ModuleBuildOptions.get((module.MetaFile.File,module.MetaFile.Root))
|
|
if ModuleOptionFromDsc:
|
|
ModuleTypeOptions, PlatformModuleOptions = ModuleOptionFromDsc["ModuleTypeOptions"],ModuleOptionFromDsc["PlatformModuleOptions"]
|
|
else:
|
|
ModuleTypeOptions, PlatformModuleOptions = {}, {}
|
|
ToolDefinition = self.DataPipe.Get("TOOLDEF")
|
|
ModuleOptions = self._ExpandBuildOption(module.BuildOptions)
|
|
BuildRuleOrder = None
|
|
for Options in [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(ToolDefinition.keys()))
|
|
BuildOptions = defaultdict(lambda: defaultdict(str))
|
|
for Tool in AllTools:
|
|
for Options in [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]
|
|
ToolList = [Tool]
|
|
if Tool == TAB_STAR:
|
|
ToolList = list(AllTools)
|
|
ToolList.remove(TAB_STAR)
|
|
for ExpandedTool in ToolList:
|
|
# check if override is indicated
|
|
if Value.startswith('='):
|
|
BuildOptions[ExpandedTool][Attr] = mws.handleWsMacro(Value[1:])
|
|
else:
|
|
if Attr != 'PATH':
|
|
BuildOptions[ExpandedTool][Attr] += " " + mws.handleWsMacro(Value)
|
|
else:
|
|
BuildOptions[ExpandedTool][Attr] = mws.handleWsMacro(Value)
|
|
|
|
return BuildOptions, BuildRuleOrder
|
|
|
|
def ApplyLibraryInstance(self,module):
|
|
alldeps = self.DataPipe.Get("DEPS")
|
|
if alldeps is None:
|
|
alldeps = {}
|
|
mod_libs = alldeps.get((module.MetaFile.File,module.MetaFile.Root,module.Arch,module.MetaFile.Path),[])
|
|
retVal = []
|
|
for (file_path,root,arch,abs_path) in mod_libs:
|
|
libMetaFile = PathClass(file_path,root)
|
|
libMetaFile.OriginalPath = PathClass(file_path,root)
|
|
libMetaFile.Path = abs_path
|
|
retVal.append(self.Wa.BuildDatabase[libMetaFile, arch, self.Target,self.ToolChain])
|
|
return retVal
|
|
|
|
## Parse build_rule.txt in Conf Directory.
|
|
#
|
|
# @retval BuildRule object
|
|
#
|
|
@cached_property
|
|
def BuildRule(self):
|
|
WInfo = self.DataPipe.Get("P_Info")
|
|
RetVal = WInfo.get("BuildRuleFile")
|
|
if RetVal._FileVersion == "":
|
|
RetVal._FileVersion = AutoGenReqBuildRuleVerNum
|
|
return RetVal
|