| ## @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 |