https://bugzilla.tianocore.org/show_bug.cgi?id=2080 This patch is to improve build -u option to re-use GlobalVar_<platformguid>_<arch>.bin file which is introduced by multiple-process-autogen feature. Cc: Liming Gao <liming.gao@intel.com> Cc: Steven Shi <steven.shi@intel.com> Signed-off-by: Bob Feng <bob.c.feng@intel.com> Acked-by: Liming Gao <liming.gao@intel.com>
		
			
				
	
	
		
			649 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			649 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| ## @file
 | |
| # Create makefile for MS nmake and GNU make
 | |
| #
 | |
| # Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
 | |
| # SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| #
 | |
| 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 Tool in ToolDef and Family != "":
 | |
|                 FamilyIsNull = False
 | |
|                 if ToolDef[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
 | |
|                     if Family != ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
 | |
|                         continue
 | |
|                 elif Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
 | |
|                     continue
 | |
|                 FamilyMatch = True
 | |
|             # expand any wildcard
 | |
|             if Target == TAB_STAR or Target == self.BuildTarget:
 | |
|                 if Tag == TAB_STAR or Tag == self.ToolChain:
 | |
|                     if Arch == TAB_STAR or Arch == self.Arch:
 | |
|                         if Tool not in BuildOptions:
 | |
|                             BuildOptions[Tool] = {}
 | |
|                         if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
 | |
|                             BuildOptions[Tool][Attr] = Options[Key]
 | |
|                         else:
 | |
|                             # append options for the same tool except PATH
 | |
|                             if Attr != 'PATH':
 | |
|                                 BuildOptions[Tool][Attr] += " " + Options[Key]
 | |
|                             else:
 | |
|                                 BuildOptions[Tool][Attr] = Options[Key]
 | |
|         # Build Option Family has been checked, which need't to be checked again for family.
 | |
|         if FamilyMatch or FamilyIsNull:
 | |
|             return BuildOptions
 | |
| 
 | |
|         for Key in Options:
 | |
|             if ModuleStyle is not None and len (Key) > 2:
 | |
|                 # Check Module style is EDK or EDKII.
 | |
|                 # Only append build option for the matched style module.
 | |
|                 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
 | |
|                     continue
 | |
|                 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
 | |
|                     continue
 | |
|             Family = Key[0]
 | |
|             Target, Tag, Arch, Tool, Attr = Key[1].split("_")
 | |
|             # if tool chain family doesn't match, skip it
 | |
|             if Tool not in ToolDef or Family == "":
 | |
|                 continue
 | |
|             # option has been added before
 | |
|             if Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
 | |
|                 continue
 | |
| 
 | |
|             # expand any wildcard
 | |
|             if Target == TAB_STAR or Target == self.BuildTarget:
 | |
|                 if Tag == TAB_STAR or Tag == self.ToolChain:
 | |
|                     if Arch == TAB_STAR or Arch == self.Arch:
 | |
|                         if Tool not in BuildOptions:
 | |
|                             BuildOptions[Tool] = {}
 | |
|                         if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
 | |
|                             BuildOptions[Tool][Attr] = Options[Key]
 | |
|                         else:
 | |
|                             # append options for the same tool except PATH
 | |
|                             if Attr != 'PATH':
 | |
|                                 BuildOptions[Tool][Attr] += " " + Options[Key]
 | |
|                             else:
 | |
|                                 BuildOptions[Tool][Attr] = Options[Key]
 | |
|         return BuildOptions
 | |
| #
 | |
| #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, Module, Pcds, Library=""):
 | |
|         # for each PCD in module
 | |
|         for Name, Guid in Pcds:
 | |
|             PcdInModule = Pcds[Name, Guid]
 | |
|             # find out the PCD setting in platform
 | |
|             if (Name, Guid) in self.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
 | |
|         if Module in self.Platform.Modules:
 | |
|             PlatformModule = self.Platform.Modules[str(Module)]
 | |
|             for Key  in PlatformModule.Pcds:
 | |
|                 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, PlatformModule.Pcds[Key], Module, Msg="DSC Components Module scoped PCD section", Library=Library)
 | |
|         # use PCD value to calculate the MaxDatumSize when it is not specified
 | |
|         for Name, Guid in Pcds:
 | |
|             Pcd = Pcds[Name, Guid]
 | |
|             if Pcd.DatumType == TAB_VOID and not Pcd.MaxDatumSize:
 | |
|                 Pcd.MaxSizeUserSet = None
 | |
|                 Value = Pcd.DefaultValue
 | |
|                 if not Value:
 | |
|                     Pcd.MaxDatumSize = '1'
 | |
|                 elif Value[0] == 'L':
 | |
|                     Pcd.MaxDatumSize = str((len(Value) - 2) * 2)
 | |
|                 elif Value[0] == '{':
 | |
|                     Pcd.MaxDatumSize = str(len(Value.split(',')))
 | |
|                 else:
 | |
|                     Pcd.MaxDatumSize = str(len(Value) - 1)
 | |
|         return list(Pcds.values())
 | |
| 
 | |
|     @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]
 | |
|                     # check if override is indicated
 | |
|                     if Value.startswith('='):
 | |
|                         BuildOptions[Tool][Attr] = mws.handleWsMacro(Value[1:])
 | |
|                     else:
 | |
|                         if Attr != 'PATH':
 | |
|                             BuildOptions[Tool][Attr] += " " + mws.handleWsMacro(Value)
 | |
|                         else:
 | |
|                             BuildOptions[Tool][Attr] = mws.handleWsMacro(Value)
 | |
| 
 | |
|         return BuildOptions, BuildRuleOrder
 | |
| 
 | |
|     def 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
 |