audk/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py
Feng, Bob C e8449e1d8e BaseTools: Decouple AutoGen Objects
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1875

1. Separate the AutoGen.py into 3 small py files.
One is for AutoGen base class, one is for WorkspaceAutoGen class
and PlatformAutoGen class, and the one for ModuleAutoGen class.
2. Create a new class DataPipe to store the Platform scope settings.
Create a new class PlatformInfo to provide the same interface
as PlatformAutoGen. PlatformInfo class is initialized by
DataPipe instance.
Create a new class WorkspaceInfo to provide the same interface
as WorkspaceAutoGen. WorkspaceInfo class is initialized by
DataPipe instance.
3. Change ModuleAutoGen to depends on DataPipe, PlatformInfo and
WorkspaceInfo. Remove the dependency of ModuleAutoGen to PlatformAutoGen.

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: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
Acked-by: Liming Gao <liming.gao@intel.com>
2019-08-09 23:15:52 +08:00

620 lines
28 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):
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
class PlatformInfo(AutoGenInfo):
def __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