summaryrefslogtreecommitdiff
path: root/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py
diff options
context:
space:
mode:
Diffstat (limited to 'BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py')
-rw-r--r--BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py1348
1 files changed, 674 insertions, 674 deletions
diff --git a/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py b/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py
index 036fdac3d7..09168047e1 100644
--- a/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py
+++ b/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py
@@ -1,674 +1,674 @@
-## @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
+## @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