public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v2 0/9] BaseTools: refactor Workspace classes
@ 2018-09-10 22:18 Jaben Carsey
  2018-09-10 22:18 ` [PATCH v2 1/9] BaseTools: Refactor PlatformAutoGen Jaben Carsey
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: Jaben Carsey @ 2018-09-10 22:18 UTC (permalink / raw)
  To: edk2-devel

update the classes for the following:
1) use decorators for property
2) use decorators for caching property and caching function
  - this allows for objects to reduce in size as they get used
3) remove unused variables and properties
4) use tuple instead of custom class when apropriate
5) remove callers from accessing "private" data and use the existing 
properties
6) removed a circular dependency between APIs

v2:
fix error where class attribute M was accidentally removed.

Jaben Carsey (9):
  BaseTools: Refactor PlatformAutoGen
  BaseTools: AutoGen refactor WorkspaceAutoGen class
  BaseTools: AutoGen - refactor class properties
  BaseTools: refactor class properties
  BaseTools: Workspace classes refactor properties
  BaseTools: refactor Build Database objects
  BaseTools: Don't save unused workspace data
  BaseTools: refactor to not overcreate ModuleAutoGen objects
  BaseTools: refactor to cache InfBuildData data

 BaseTools/Source/Python/AutoGen/AutoGen.py             | 692 +++++++-------
 BaseTools/Source/Python/AutoGen/GenMake.py             |  20 +-
 BaseTools/Source/Python/Common/Misc.py                 |  90 +-
 BaseTools/Source/Python/GenFds/FfsInfStatement.py      |   4 +-
 BaseTools/Source/Python/Workspace/BuildClassObject.py  |  39 +-
 BaseTools/Source/Python/Workspace/DecBuildData.py      |  65 +-
 BaseTools/Source/Python/Workspace/DscBuildData.py      | 151 ++--
 BaseTools/Source/Python/Workspace/InfBuildData.py      | 954 +++++++++-----------
 BaseTools/Source/Python/Workspace/MetaFileParser.py    |  18 +-
 BaseTools/Source/Python/Workspace/WorkspaceDatabase.py |  16 +-
 BaseTools/Source/Python/build/build.py                 |   4 +-
 11 files changed, 933 insertions(+), 1120 deletions(-)

-- 
2.16.2.windows.1



^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 1/9] BaseTools: Refactor PlatformAutoGen
  2018-09-10 22:18 [PATCH v2 0/9] BaseTools: refactor Workspace classes Jaben Carsey
@ 2018-09-10 22:18 ` Jaben Carsey
  2018-09-10 22:18 ` [PATCH v2 2/9] BaseTools: AutoGen refactor WorkspaceAutoGen class Jaben Carsey
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Jaben Carsey @ 2018-09-10 22:18 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Yonghong Zhu, Bob Feng

use decorators for property and automatic caching
remove circular dependency between some APIs

Cc: Liming Gao <liming.gao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Cc: Bob Feng <Bob.c.Feng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jaben Carsey <jaben.carsey@intel.com>
---
 BaseTools/Source/Python/AutoGen/AutoGen.py | 587 +++++++++-----------
 1 file changed, 264 insertions(+), 323 deletions(-)

diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py b/BaseTools/Source/Python/AutoGen/AutoGen.py
index 95370d182157..726b1c98f5bc 100644
--- a/BaseTools/Source/Python/AutoGen/AutoGen.py
+++ b/BaseTools/Source/Python/AutoGen/AutoGen.py
@@ -1046,41 +1046,13 @@ class PlatformAutoGen(AutoGen):
         # get the original module/package/platform objects
         self.BuildDatabase = Workspace.BuildDatabase
         self.DscBuildDataObj = Workspace.Platform
-        self._GuidDict = Workspace._GuidDict
 
         # flag indicating if the makefile/C-code file has been created or not
         self.IsMakeFileCreated  = False
-        self.IsCodeFileCreated  = False
 
-        self._Platform   = None
-        self._Name       = None
-        self._Guid       = None
-        self._Version    = None
-
-        self._BuildRule = None
-        self._SourceDir = None
-        self._BuildDir = None
-        self._OutputDir = None
-        self._FvDir = None
-        self._MakeFileDir = None
-        self._FdfFile = None
-
-        self._PcdTokenNumber = None    # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
         self._DynamicPcdList = None    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
         self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
-        self._NonDynamicPcdDict = {}
 
-        self._ToolDefinitions = None
-        self._ToolDefFile = None          # toolcode : tool path
-        self._ToolChainFamily = None
-        self._BuildRuleFamily = None
-        self._BuildOption = None          # toolcode : option
-        self._EdkBuildOption = None       # edktoolcode : option
-        self._EdkIIBuildOption = None     # edkiitoolcode : option
-        self._PackageList = None
-        self._ModuleAutoGenList  = None
-        self._LibraryAutoGenList = None
-        self._BuildCommand = None
         self._AsBuildInfList = []
         self._AsBuildModuleList = []
 
@@ -1100,6 +1072,7 @@ class PlatformAutoGen(AutoGen):
 
         return True
 
+    @cached_class_function
     def __repr__(self):
         return "%s [%s]" % (self.MetaFile, self.Arch)
 
@@ -1111,19 +1084,18 @@ class PlatformAutoGen(AutoGen):
     #   @param      CreateModuleCodeFile    Flag indicating if creating module's
     #                                       autogen code file or not
     #
+    @cached_class_function
     def CreateCodeFile(self, CreateModuleCodeFile=False):
         # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
-        if self.IsCodeFileCreated or not CreateModuleCodeFile:
+        if not CreateModuleCodeFile:
             return
 
         for Ma in self.ModuleAutoGenList:
             Ma.CreateCodeFile(True)
 
-        # don't do this twice
-        self.IsCodeFileCreated = True
-
     ## Generate Fds Command
-    def _GenFdsCommand(self):
+    @cached_property
+    def GenFdsCommand(self):
         return self.Workspace.GenFdsCommand
 
     ## Create makefile for the platform and mdoules in it
@@ -1185,7 +1157,6 @@ class PlatformAutoGen(AutoGen):
                     LibAuto.ConstPcd[key] = FixedAtBuildPcds[key]
 
     def CollectVariables(self, DynamicPcdSet):
-
         VpdRegionSize = 0
         VpdRegionBase = 0
         if self.Workspace.FdfFile:
@@ -1197,7 +1168,6 @@ class PlatformAutoGen(AutoGen):
                         VpdRegionBase = FdRegion.Offset
                         break
 
-
         VariableInfo = VariableMgr(self.DscBuildDataObj._GetDefaultStores(), self.DscBuildDataObj._GetSkuIds())
         VariableInfo.SetVpdRegionMaxSize(VpdRegionSize)
         VariableInfo.SetVpdRegionOffset(VpdRegionBase)
@@ -1250,7 +1220,6 @@ class PlatformAutoGen(AutoGen):
     #  This interface should be invoked explicitly when platform action is created.
     #
     def CollectPlatformDynamicPcds(self):
-
         for key in self.Platform.Pcds:
             for SinglePcd in GlobalData.MixedPcd:
                 if (self.Platform.Pcds[key].TokenCName, self.Platform.Pcds[key].TokenSpaceGuidCName) == SinglePcd:
@@ -1683,308 +1652,318 @@ class PlatformAutoGen(AutoGen):
                 EdkLogger.error("Build", FILE_NOT_FOUND, "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")
 
     ## Return the platform build data object
-    def _GetPlatform(self):
-        if self._Platform is None:
-            self._Platform = self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
-        return self._Platform
+    @cached_property
+    def Platform(self):
+        return self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
 
     ## Return platform name
-    def _GetName(self):
+    @cached_property
+    def Name(self):
         return self.Platform.PlatformName
 
     ## Return the meta file GUID
-    def _GetGuid(self):
+    @cached_property
+    def Guid(self):
         return self.Platform.Guid
 
     ## Return the platform version
-    def _GetVersion(self):
+    @cached_property
+    def Version(self):
         return self.Platform.Version
 
     ## Return the FDF file name
-    def _GetFdfFile(self):
-        if self._FdfFile is None:
-            if self.Workspace.FdfFile != "":
-                self._FdfFile= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)
-            else:
-                self._FdfFile = ''
-        return self._FdfFile
+    @cached_property
+    def FdfFile(self):
+        if self.Workspace.FdfFile:
+            RetVal= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)
+        else:
+            RetVal = ''
+        return RetVal
 
     ## Return the build output directory platform specifies
-    def _GetOutputDir(self):
+    @cached_property
+    def OutputDir(self):
         return self.Platform.OutputDirectory
 
     ## Return the directory to store all intermediate and final files built
-    def _GetBuildDir(self):
-        if self._BuildDir is None:
-            if os.path.isabs(self.OutputDir):
-                self._BuildDir = path.join(
-                                            path.abspath(self.OutputDir),
-                                            self.BuildTarget + "_" + self.ToolChain,
-                                            )
-            else:
-                self._BuildDir = path.join(
-                                            self.WorkspaceDir,
-                                            self.OutputDir,
-                                            self.BuildTarget + "_" + self.ToolChain,
-                                            )
-            GlobalData.gBuildDirectory = self._BuildDir
-        return self._BuildDir
+    @cached_property
+    def BuildDir(self):
+        if os.path.isabs(self.OutputDir):
+            GlobalData.gBuildDirectory = RetVal = path.join(
+                                        path.abspath(self.OutputDir),
+                                        self.BuildTarget + "_" + self.ToolChain,
+                                        )
+        else:
+            GlobalData.gBuildDirectory = RetVal = path.join(
+                                        self.WorkspaceDir,
+                                        self.OutputDir,
+                                        self.BuildTarget + "_" + self.ToolChain,
+                                        )
+        return RetVal
 
     ## Return directory of platform makefile
     #
     #   @retval     string  Makefile directory
     #
-    def _GetMakeFileDir(self):
-        if self._MakeFileDir is None:
-            self._MakeFileDir = path.join(self.BuildDir, self.Arch)
-        return self._MakeFileDir
+    @cached_property
+    def MakeFileDir(self):
+        return path.join(self.BuildDir, self.Arch)
 
     ## Return build command string
     #
     #   @retval     string  Build command string
     #
-    def _GetBuildCommand(self):
-        if self._BuildCommand is None:
-            self._BuildCommand = []
-            if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
-                self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"])
-                if "FLAGS" in self.ToolDefinition["MAKE"]:
-                    NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
-                    if NewOption != '':
-                        self._BuildCommand += SplitOption(NewOption)
-                if "MAKE" in self.EdkIIBuildOption:
-                    if "FLAGS" in self.EdkIIBuildOption["MAKE"]:
-                        Flags = self.EdkIIBuildOption["MAKE"]["FLAGS"]
-                        if Flags.startswith('='):
-                            self._BuildCommand = [self._BuildCommand[0]] + [Flags[1:]]
-                        else:
-                            self._BuildCommand.append(Flags)
-        return self._BuildCommand
+    @cached_property
+    def BuildCommand(self):
+        RetVal = []
+        if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
+            RetVal += SplitOption(self.ToolDefinition["MAKE"]["PATH"])
+            if "FLAGS" in self.ToolDefinition["MAKE"]:
+                NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
+                if NewOption != '':
+                    RetVal += SplitOption(NewOption)
+            if "MAKE" in self.EdkIIBuildOption:
+                if "FLAGS" in self.EdkIIBuildOption["MAKE"]:
+                    Flags = self.EdkIIBuildOption["MAKE"]["FLAGS"]
+                    if Flags.startswith('='):
+                        RetVal = [RetVal[0]] + [Flags[1:]]
+                    else:
+                        RetVal.append(Flags)
+        return RetVal
 
     ## Get tool chain definition
     #
     #  Get each tool defition for given tool chain from tools_def.txt and platform
     #
-    def _GetToolDefinition(self):
-        if self._ToolDefinitions is None:
-            ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
-            if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:
-                EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",
-                                ExtraData="[%s]" % self.MetaFile)
-            self._ToolDefinitions = {}
-            DllPathList = set()
-            for Def in ToolDefinition:
-                Target, Tag, Arch, Tool, Attr = Def.split("_")
-                if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:
-                    continue
+    @cached_property
+    def ToolDefinition(self):
+        ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
+        if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:
+            EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",
+                            ExtraData="[%s]" % self.MetaFile)
+        RetVal = {}
+        DllPathList = set()
+        for Def in ToolDefinition:
+            Target, Tag, Arch, Tool, Attr = Def.split("_")
+            if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:
+                continue
 
-                Value = ToolDefinition[Def]
-                # don't record the DLL
-                if Attr == "DLL":
-                    DllPathList.add(Value)
-                    continue
+            Value = ToolDefinition[Def]
+            # don't record the DLL
+            if Attr == "DLL":
+                DllPathList.add(Value)
+                continue
 
-                if Tool not in self._ToolDefinitions:
-                    self._ToolDefinitions[Tool] = {}
-                self._ToolDefinitions[Tool][Attr] = Value
+            if Tool not in RetVal:
+                RetVal[Tool] = {}
+            RetVal[Tool][Attr] = Value
 
-            ToolsDef = ''
-            if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions:
-                if "FLAGS" not in self._ToolDefinitions["MAKE"]:
-                    self._ToolDefinitions["MAKE"]["FLAGS"] = ""
-                self._ToolDefinitions["MAKE"]["FLAGS"] += " -s"
-            MakeFlags = ''
-            for Tool in self._ToolDefinitions:
-                for Attr in self._ToolDefinitions[Tool]:
-                    Value = self._ToolDefinitions[Tool][Attr]
-                    if Tool in self.BuildOption and Attr in self.BuildOption[Tool]:
-                        # check if override is indicated
-                        if self.BuildOption[Tool][Attr].startswith('='):
-                            Value = self.BuildOption[Tool][Attr][1:]
+        ToolsDef = ''
+        if GlobalData.gOptions.SilentMode and "MAKE" in RetVal:
+            if "FLAGS" not in RetVal["MAKE"]:
+                RetVal["MAKE"]["FLAGS"] = ""
+            RetVal["MAKE"]["FLAGS"] += " -s"
+        MakeFlags = ''
+        for Tool in RetVal:
+            for Attr in RetVal[Tool]:
+                Value = RetVal[Tool][Attr]
+                if Tool in self._BuildOptionWithToolDef(RetVal) and Attr in self._BuildOptionWithToolDef(RetVal)[Tool]:
+                    # check if override is indicated
+                    if self._BuildOptionWithToolDef(RetVal)[Tool][Attr].startswith('='):
+                        Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr][1:]
+                    else:
+                        if Attr != 'PATH':
+                            Value += " " + self._BuildOptionWithToolDef(RetVal)[Tool][Attr]
                         else:
-                            if Attr != 'PATH':
-                                Value += " " + self.BuildOption[Tool][Attr]
-                            else:
-                                Value = self.BuildOption[Tool][Attr]
+                            Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr]
 
-                    if Attr == "PATH":
-                        # Don't put MAKE definition in the file
-                        if Tool != "MAKE":
-                            ToolsDef += "%s = %s\n" % (Tool, Value)
-                    elif Attr != "DLL":
-                        # Don't put MAKE definition in the file
-                        if Tool == "MAKE":
-                            if Attr == "FLAGS":
-                                MakeFlags = Value
-                        else:
-                            ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
-                ToolsDef += "\n"
+                if Attr == "PATH":
+                    # Don't put MAKE definition in the file
+                    if Tool != "MAKE":
+                        ToolsDef += "%s = %s\n" % (Tool, Value)
+                elif Attr != "DLL":
+                    # Don't put MAKE definition in the file
+                    if Tool == "MAKE":
+                        if Attr == "FLAGS":
+                            MakeFlags = Value
+                    else:
+                        ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
+            ToolsDef += "\n"
 
-            SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)
-            for DllPath in DllPathList:
-                os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]
-            os.environ["MAKE_FLAGS"] = MakeFlags
+        SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)
+        for DllPath in DllPathList:
+            os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]
+        os.environ["MAKE_FLAGS"] = MakeFlags
 
-        return self._ToolDefinitions
+        return RetVal
 
     ## Return the paths of tools
-    def _GetToolDefFile(self):
-        if self._ToolDefFile is None:
-            self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
-        return self._ToolDefFile
+    @cached_property
+    def ToolDefinitionFile(self):
+        return os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
 
     ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
-    def _GetToolChainFamily(self):
-        if self._ToolChainFamily is None:
-            ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
-            if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
-               or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
-               or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:
-                EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
-                                   % self.ToolChain)
-                self._ToolChainFamily = TAB_COMPILER_MSFT
-            else:
-                self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]
-        return self._ToolChainFamily
+    @cached_property
+    def ToolChainFamily(self):
+        ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
+        if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
+           or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
+           or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:
+            EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
+                               % self.ToolChain)
+            RetVal = TAB_COMPILER_MSFT
+        else:
+            RetVal = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]
+        return RetVal
 
-    def _GetBuildRuleFamily(self):
-        if self._BuildRuleFamily is None:
-            ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
-            if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
-               or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \
-               or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:
-                EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
-                                   % self.ToolChain)
-                self._BuildRuleFamily = TAB_COMPILER_MSFT
-            else:
-                self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]
-        return self._BuildRuleFamily
+    @cached_property
+    def BuildRuleFamily(self):
+        ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
+        if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
+           or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \
+           or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:
+            EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
+                               % self.ToolChain)
+            return TAB_COMPILER_MSFT
+
+        return ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]
 
     ## Return the build options specific for all modules in this platform
-    def _GetBuildOptions(self):
-        if self._BuildOption is None:
-            self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)
-        return self._BuildOption
+    @cached_property
+    def BuildOption(self):
+        return self._ExpandBuildOption(self.Platform.BuildOptions)
+
+    def _BuildOptionWithToolDef(self, ToolDef):
+        return self._ExpandBuildOption(self.Platform.BuildOptions, ToolDef=ToolDef)
 
     ## Return the build options specific for EDK modules in this platform
-    def _GetEdkBuildOptions(self):
-        if self._EdkBuildOption is None:
-            self._EdkBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)
-        return self._EdkBuildOption
+    @cached_property
+    def EdkBuildOption(self):
+        return self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)
 
     ## Return the build options specific for EDKII modules in this platform
-    def _GetEdkIIBuildOptions(self):
-        if self._EdkIIBuildOption is None:
-            self._EdkIIBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)
-        return self._EdkIIBuildOption
+    @cached_property
+    def EdkIIBuildOption(self):
+        return self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)
 
     ## Parse build_rule.txt in Conf Directory.
     #
     #   @retval     BuildRule object
     #
-    def _GetBuildRule(self):
-        if self._BuildRule is None:
-            BuildRuleFile = None
-            if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:
-                BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
-            if not BuildRuleFile:
-                BuildRuleFile = gDefaultBuildRuleFile
-            self._BuildRule = BuildRule(BuildRuleFile)
-            if self._BuildRule._FileVersion == "":
-                self._BuildRule._FileVersion = AutoGenReqBuildRuleVerNum
-            else:
-                if self._BuildRule._FileVersion < AutoGenReqBuildRuleVerNum :
-                    # If Build Rule's version is less than the version number required by the tools, halting the build.
-                    EdkLogger.error("build", AUTOGEN_ERROR,
-                                    ExtraData="The version number [%s] of build_rule.txt is less than the version number required by the AutoGen.(the minimum required version number is [%s])"\
-                                     % (self._BuildRule._FileVersion, AutoGenReqBuildRuleVerNum))
-
-        return self._BuildRule
+    @cached_property
+    def BuildRule(self):
+        BuildRuleFile = None
+        if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:
+            BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
+        if not BuildRuleFile:
+            BuildRuleFile = gDefaultBuildRuleFile
+        RetVal = BuildRule(BuildRuleFile)
+        if RetVal._FileVersion == "":
+            RetVal._FileVersion = AutoGenReqBuildRuleVerNum
+        else:
+            if RetVal._FileVersion < AutoGenReqBuildRuleVerNum :
+                # If Build Rule's version is less than the version number required by the tools, halting the build.
+                EdkLogger.error("build", AUTOGEN_ERROR,
+                                ExtraData="The version number [%s] of build_rule.txt is less than the version number required by the AutoGen.(the minimum required version number is [%s])"\
+                                 % (RetVal._FileVersion, AutoGenReqBuildRuleVerNum))
+        return RetVal
 
     ## Summarize the packages used by modules in this platform
-    def _GetPackageList(self):
-        if self._PackageList is None:
-            self._PackageList = set()
-            for La in self.LibraryAutoGenList:
-                self._PackageList.update(La.DependentPackageList)
-            for Ma in self.ModuleAutoGenList:
-                self._PackageList.update(Ma.DependentPackageList)
-            #Collect package set information from INF of FDF
-            PkgSet = set()
-            for ModuleFile in self._AsBuildModuleList:
-                if ModuleFile in self.Platform.Modules:
-                    continue
-                ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]
-                PkgSet.update(ModuleData.Packages)
-            self._PackageList = list(self._PackageList) + list (PkgSet)
-        return self._PackageList
+    @cached_property
+    def PackageList(self):
+        RetVal = set()
+        for La in self.LibraryAutoGenList:
+            RetVal.update(La.DependentPackageList)
+        for Ma in self.ModuleAutoGenList:
+            RetVal.update(Ma.DependentPackageList)
+        #Collect package set information from INF of FDF
+        for ModuleFile in self._AsBuildModuleList:
+            if ModuleFile in self.Platform.Modules:
+                continue
+            ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]
+            RetVal.update(ModuleData.Packages)
+        return list(RetVal)
 
-    def _GetNonDynamicPcdDict(self):
-        if self._NonDynamicPcdDict:
-            return self._NonDynamicPcdDict
-        for Pcd in self.NonDynamicPcdList:
-            self._NonDynamicPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd
-        return self._NonDynamicPcdDict
+    @cached_property
+    def NonDynamicPcdDict(self):
+        return {(Pcd.TokenCName, Pcd.TokenSpaceGuidCName):Pcd for Pcd in self.NonDynamicPcdList}
 
     ## Get list of non-dynamic PCDs
-    def _GetNonDynamicPcdList(self):
-        if self._NonDynamicPcdList is None:
-            self.CollectPlatformDynamicPcds()
+    @cached_property
+    def NonDynamicPcdList(self):
+        self.CollectPlatformDynamicPcds()
         return self._NonDynamicPcdList
 
     ## Get list of dynamic PCDs
-    def _GetDynamicPcdList(self):
-        if self._DynamicPcdList is None:
-            self.CollectPlatformDynamicPcds()
+    @cached_property
+    def DynamicPcdList(self):
+        self.CollectPlatformDynamicPcds()
         return self._DynamicPcdList
 
     ## Generate Token Number for all PCD
-    def _GetPcdTokenNumbers(self):
-        if self._PcdTokenNumber is None:
-            self._PcdTokenNumber = OrderedDict()
-            TokenNumber = 1
-            #
-            # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
-            # Such as:
-            #
-            # Dynamic PCD:
-            # TokenNumber 0 ~ 10
-            # DynamicEx PCD:
-            # TokeNumber 11 ~ 20
-            #
-            for Pcd in self.DynamicPcdList:
-                if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:
-                    EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
-                    self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
-                    TokenNumber += 1
-
-            for Pcd in self.DynamicPcdList:
-                if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
-                    EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
-                    self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
-                    TokenNumber += 1
+    @cached_property
+    def PcdTokenNumber(self):
+        RetVal = OrderedDict()
+        TokenNumber = 1
+        #
+        # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
+        # Such as:
+        #
+        # Dynamic PCD:
+        # TokenNumber 0 ~ 10
+        # DynamicEx PCD:
+        # TokeNumber 11 ~ 20
+        #
+        for Pcd in self.DynamicPcdList:
+            if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:
+                EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
+                RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
+                TokenNumber += 1
 
-            for Pcd in self.DynamicPcdList:
-                if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:
-                    EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
-                    self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
-                    TokenNumber += 1
+        for Pcd in self.DynamicPcdList:
+            if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
+                EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
+                RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
+                TokenNumber += 1
 
-            for Pcd in self.DynamicPcdList:
-                if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
-                    EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
-                    self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
-                    TokenNumber += 1
+        for Pcd in self.DynamicPcdList:
+            if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:
+                EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
+                RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
+                TokenNumber += 1
 
-            for Pcd in self.NonDynamicPcdList:
-                self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
+        for Pcd in self.DynamicPcdList:
+            if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
+                EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
+                RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
                 TokenNumber += 1
-        return self._PcdTokenNumber
 
-    ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
-    def _GetAutoGenObjectList(self):
-        self._ModuleAutoGenList = []
-        self._LibraryAutoGenList = []
+        for Pcd in self.NonDynamicPcdList:
+            RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
+            TokenNumber += 1
+        return RetVal
+
+    ## Summarize ModuleAutoGen objects of all modules to be built for this platform
+    @cached_property
+    def ModuleAutoGenList(self):
+        RetVal = []
+        for ModuleFile in self.Platform.Modules:
+            Ma = ModuleAutoGen(
+                    self.Workspace,
+                    ModuleFile,
+                    self.BuildTarget,
+                    self.ToolChain,
+                    self.Arch,
+                    self.MetaFile
+                    )
+            if Ma not in RetVal:
+                RetVal.append(Ma)
+        return RetVal
+
+    ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
+    @cached_property
+    def LibraryAutoGenList(self):
+        RetVal = []
         for ModuleFile in self.Platform.Modules:
             Ma = ModuleAutoGen(
                     self.Workspace,
@@ -1994,25 +1973,12 @@ class PlatformAutoGen(AutoGen):
                     self.Arch,
                     self.MetaFile
                     )
-            if Ma not in self._ModuleAutoGenList:
-                self._ModuleAutoGenList.append(Ma)
             for La in Ma.LibraryAutoGenList:
-                if La not in self._LibraryAutoGenList:
-                    self._LibraryAutoGenList.append(La)
+                if La not in RetVal:
+                    RetVal.append(La)
                 if Ma not in La.ReferenceModules:
                     La.ReferenceModules.append(Ma)
-
-    ## Summarize ModuleAutoGen objects of all modules to be built for this platform
-    def _GetModuleAutoGenList(self):
-        if self._ModuleAutoGenList is None:
-            self._GetAutoGenObjectList()
-        return self._ModuleAutoGenList
-
-    ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
-    def _GetLibraryAutoGenList(self):
-        if self._LibraryAutoGenList is None:
-            self._GetAutoGenObjectList()
-        return self._LibraryAutoGenList
+        return RetVal
 
     ## Test if a module is supported by the platform
     #
@@ -2093,7 +2059,7 @@ class PlatformAutoGen(AutoGen):
             # Add Flexible PCD format parse
             if ToPcd.DefaultValue:
                 try:
-                    ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self._GuidDict)(True)
+                    ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self.Workspace._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)
@@ -2259,10 +2225,16 @@ class PlatformAutoGen(AutoGen):
     ## 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):
+    def _ExpandBuildOption(self, Options, ModuleStyle=None, ToolDef=None):
+        if not ToolDef:
+            ToolDef = self.ToolDefinition
         BuildOptions = {}
         FamilyMatch  = False
         FamilyIsNull = True
@@ -2326,12 +2298,12 @@ class PlatformAutoGen(AutoGen):
             Family = Key[0]
             Target, Tag, Arch, Tool, Attr = Key[1].split("_")
             # if tool chain family doesn't match, skip it
-            if Tool in self.ToolDefinition and Family != "":
+            if Tool in ToolDef and Family != "":
                 FamilyIsNull = False
-                if self.ToolDefinition[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
-                    if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
+                if ToolDef[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
+                    if Family != ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
                         continue
-                elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
+                elif Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
                     continue
                 FamilyMatch = True
             # expand any wildcard
@@ -2363,10 +2335,10 @@ class PlatformAutoGen(AutoGen):
             Family = Key[0]
             Target, Tag, Arch, Tool, Attr = Key[1].split("_")
             # if tool chain family doesn't match, skip it
-            if Tool not in self.ToolDefinition or Family == "":
+            if Tool not in ToolDef or Family == "":
                 continue
             # option has been added before
-            if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
+            if Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
                 continue
 
             # expand any wildcard
@@ -2445,36 +2417,6 @@ class PlatformAutoGen(AutoGen):
             BuildOptions['BUILD']['FLAGS'] = self.Workspace.UniFlag
         return BuildOptions, BuildRuleOrder
 
-    Platform            = property(_GetPlatform)
-    Name                = property(_GetName)
-    Guid                = property(_GetGuid)
-    Version             = property(_GetVersion)
-
-    OutputDir           = property(_GetOutputDir)
-    BuildDir            = property(_GetBuildDir)
-    MakeFileDir         = property(_GetMakeFileDir)
-    FdfFile             = property(_GetFdfFile)
-
-    PcdTokenNumber      = property(_GetPcdTokenNumbers)    # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
-    DynamicPcdList      = property(_GetDynamicPcdList)    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
-    NonDynamicPcdList   = property(_GetNonDynamicPcdList)    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
-    NonDynamicPcdDict   = property(_GetNonDynamicPcdDict)
-    PackageList         = property(_GetPackageList)
-
-    ToolDefinition      = property(_GetToolDefinition)    # toolcode : tool path
-    ToolDefinitionFile  = property(_GetToolDefFile)    # toolcode : lib path
-    ToolChainFamily     = property(_GetToolChainFamily)
-    BuildRuleFamily     = property(_GetBuildRuleFamily)
-    BuildOption         = property(_GetBuildOptions)    # toolcode : option
-    EdkBuildOption      = property(_GetEdkBuildOptions)   # edktoolcode : option
-    EdkIIBuildOption    = property(_GetEdkIIBuildOptions) # edkiitoolcode : option
-
-    BuildCommand        = property(_GetBuildCommand)
-    BuildRule           = property(_GetBuildRule)
-    ModuleAutoGenList   = property(_GetModuleAutoGenList)
-    LibraryAutoGenList  = property(_GetLibraryAutoGenList)
-    GenFdsCommand       = property(_GenFdsCommand)
-
 #
 # extend lists contained in a dictionary with lists stored in another dictionary
 # if CopyToDict is not derived from DefaultDict(list) then this may raise exception
@@ -2530,7 +2472,6 @@ class ModuleAutoGen(AutoGen):
 
         self.Workspace = Workspace
         self.WorkspaceDir = Workspace.WorkspaceDir
-        self._GuidDict = Workspace._GuidDict
         self.MetaFile = ModuleFile
         self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)
 
-- 
2.16.2.windows.1



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 2/9] BaseTools: AutoGen refactor WorkspaceAutoGen class
  2018-09-10 22:18 [PATCH v2 0/9] BaseTools: refactor Workspace classes Jaben Carsey
  2018-09-10 22:18 ` [PATCH v2 1/9] BaseTools: Refactor PlatformAutoGen Jaben Carsey
@ 2018-09-10 22:18 ` Jaben Carsey
  2018-09-10 22:18 ` [PATCH v2 3/9] BaseTools: AutoGen - refactor class properties Jaben Carsey
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Jaben Carsey @ 2018-09-10 22:18 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Yonghong Zhu, Bob Feng

Update the WorkspaceAutoGen class to use caching decorators and remove
the no longer needed private variables.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Cc: Bob Feng <bob.c.feng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jaben Carsey <jaben.carsey@intel.com>
---
 BaseTools/Source/Python/AutoGen/AutoGen.py | 69 ++++++++------------
 1 file changed, 28 insertions(+), 41 deletions(-)

diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py b/BaseTools/Source/Python/AutoGen/AutoGen.py
index 726b1c98f5bc..35dab75785eb 100644
--- a/BaseTools/Source/Python/AutoGen/AutoGen.py
+++ b/BaseTools/Source/Python/AutoGen/AutoGen.py
@@ -278,10 +278,6 @@ class WorkspaceAutoGen(AutoGen):
         self.FvTargetList   = Fvs if Fvs else []
         self.CapTargetList  = Caps if Caps else []
         self.AutoGenObjectList = []
-        self._BuildDir      = None
-        self._FvDir         = None
-        self._MakeFileDir   = None
-        self._BuildCommand  = None
         self._GuidDict = {}
 
         # there's many relative directory operations, so ...
@@ -810,54 +806,56 @@ class WorkspaceAutoGen(AutoGen):
         return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))
 
     ## Return the directory to store FV files
-    def _GetFvDir(self):
-        if self._FvDir is None:
-            self._FvDir = path.join(self.BuildDir, TAB_FV_DIRECTORY)
-        return self._FvDir
+    @cached_property
+    def FvDir(self):
+        return path.join(self.BuildDir, TAB_FV_DIRECTORY)
 
     ## Return the directory to store all intermediate and final files built
-    def _GetBuildDir(self):
-        if self._BuildDir is None:
-            return self.AutoGenObjectList[0].BuildDir
+    @cached_property
+    def BuildDir(self):
+        return self.AutoGenObjectList[0].BuildDir
 
     ## Return the build output directory platform specifies
-    def _GetOutputDir(self):
+    @cached_property
+    def OutputDir(self):
         return self.Platform.OutputDirectory
 
     ## Return platform name
-    def _GetName(self):
+    @cached_property
+    def Name(self):
         return self.Platform.PlatformName
 
     ## Return meta-file GUID
-    def _GetGuid(self):
+    @cached_property
+    def Guid(self):
         return self.Platform.Guid
 
     ## Return platform version
-    def _GetVersion(self):
+    @cached_property
+    def Version(self):
         return self.Platform.Version
 
     ## Return paths of tools
-    def _GetToolDefinition(self):
+    @cached_property
+    def ToolDefinition(self):
         return self.AutoGenObjectList[0].ToolDefinition
 
     ## Return directory of platform makefile
     #
     #   @retval     string  Makefile directory
     #
-    def _GetMakeFileDir(self):
-        if self._MakeFileDir is None:
-            self._MakeFileDir = self.BuildDir
-        return self._MakeFileDir
+    @cached_property
+    def MakeFileDir(self):
+        return self.BuildDir
 
     ## Return build command string
     #
     #   @retval     string  Build command string
     #
-    def _GetBuildCommand(self):
-        if self._BuildCommand is None:
-            # BuildCommand should be all the same. So just get one from platform AutoGen
-            self._BuildCommand = self.AutoGenObjectList[0].BuildCommand
-        return self._BuildCommand
+    @cached_property
+    def BuildCommand(self):
+        # BuildCommand should be all the same. So just get one from platform AutoGen
+        return self.AutoGenObjectList[0].BuildCommand
 
     ## Check the PCDs token value conflict in each DEC file.
     #
@@ -933,7 +931,8 @@ class WorkspaceAutoGen(AutoGen):
                                     )
                     Count += 1
     ## Generate fds command
-    def _GenFdsCommand(self):
+    @property
+    def GenFdsCommand(self):
         return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()
 
     ## Create makefile for the platform and modules in it
@@ -966,18 +965,6 @@ class WorkspaceAutoGen(AutoGen):
     def CreateAsBuiltInf(self):
         return
 
-    Name                = property(_GetName)
-    Guid                = property(_GetGuid)
-    Version             = property(_GetVersion)
-    OutputDir           = property(_GetOutputDir)
-
-    ToolDefinition      = property(_GetToolDefinition)       # toolcode : tool path
-
-    BuildDir            = property(_GetBuildDir)
-    FvDir               = property(_GetFvDir)
-    MakeFileDir         = property(_GetMakeFileDir)
-    BuildCommand        = property(_GetBuildCommand)
-    GenFdsCommand       = property(_GenFdsCommand)
 
 ## AutoGen class for platform
 #
@@ -2587,7 +2574,7 @@ class ModuleAutoGen(AutoGen):
     ## Return the module build data object
     @cached_property
     def Module(self):
-        return self.Workspace.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
+        return self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
 
     ## Return the module name
     @cached_property
@@ -2935,7 +2922,7 @@ class ModuleAutoGen(AutoGen):
             except KeyError:
                 FlagOption = ''
 
-            if self.PlatformInfo.ToolChainFamily != 'RVCT':
+            if self.ToolChainFamily != 'RVCT':
                 IncPathList = [NormPath(Path, self.Macros) for Path in BuildOptIncludeRegEx.findall(FlagOption)]
             else:
                 #
@@ -3851,7 +3838,7 @@ class ModuleAutoGen(AutoGen):
         if os.path.exists(ModuleFile):
             shutil.copy2(ModuleFile, FileDir)
         if not self.OutputFile:
-            Ma = self.Workspace.BuildDatabase[PathClass(ModuleFile), self.Arch, self.BuildTarget, self.ToolChain]
+            Ma = self.BuildDatabase[PathClass(ModuleFile), self.Arch, self.BuildTarget, self.ToolChain]
             self.OutputFile = Ma.Binaries
         if self.OutputFile:
             for File in self.OutputFile:
-- 
2.16.2.windows.1



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 3/9] BaseTools: AutoGen - refactor class properties
  2018-09-10 22:18 [PATCH v2 0/9] BaseTools: refactor Workspace classes Jaben Carsey
  2018-09-10 22:18 ` [PATCH v2 1/9] BaseTools: Refactor PlatformAutoGen Jaben Carsey
  2018-09-10 22:18 ` [PATCH v2 2/9] BaseTools: AutoGen refactor WorkspaceAutoGen class Jaben Carsey
@ 2018-09-10 22:18 ` Jaben Carsey
  2018-09-10 22:18 ` [PATCH v2 4/9] BaseTools: " Jaben Carsey
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Jaben Carsey @ 2018-09-10 22:18 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Yonghong Zhu

use function decorators

Cc: Liming Gao <liming.gao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jaben Carsey <jaben.carsey@intel.com>
---
 BaseTools/Source/Python/AutoGen/GenMake.py | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/BaseTools/Source/Python/AutoGen/GenMake.py b/BaseTools/Source/Python/AutoGen/GenMake.py
index 35ee98c82bb1..b4377eef17d7 100644
--- a/BaseTools/Source/Python/AutoGen/GenMake.py
+++ b/BaseTools/Source/Python/AutoGen/GenMake.py
@@ -455,7 +455,8 @@ cleanlib:
         self.FfsOutputFileList = []
 
     # Compose a dict object containing information used to do replacement in template
-    def _CreateTemplateDict(self):
+    @property
+    def _TemplateDict(self):
         if self._FileType not in self._SEP_:
             EdkLogger.error("build", PARAMETER_INVALID, "Invalid Makefile type [%s]" % self._FileType,
                             ExtraData="[%s]" % str(self._AutoGenObject))
@@ -1095,8 +1096,6 @@ cleanlib:
 
         return DependencyList
 
-    _TemplateDict = property(_CreateTemplateDict)
-
 ## CustomMakefile class
 #
 #  This class encapsules makefie and its generation for module. It uses template to generate
@@ -1205,7 +1204,8 @@ ${BEGIN}\t-@${create_directory_command}\n${END}\
         self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
 
     # Compose a dict object containing information used to do replacement in template
-    def _CreateTemplateDict(self):
+    @property
+    def _TemplateDict(self):
         Separator = self._SEP_[self._FileType]
         MyAgo = self._AutoGenObject
         if self._FileType not in MyAgo.CustomMakefile:
@@ -1278,8 +1278,6 @@ ${BEGIN}\t-@${create_directory_command}\n${END}\
 
         return MakefileTemplateDict
 
-    _TemplateDict = property(_CreateTemplateDict)
-
 ## PlatformMakefile class
 #
 #  This class encapsules makefie and its generation for platform. It uses
@@ -1396,7 +1394,8 @@ cleanlib:
         self.LibraryMakeCommandList = []
 
     # Compose a dict object containing information used to do replacement in template
-    def _CreateTemplateDict(self):
+    @property
+    def _TemplateDict(self):
         Separator = self._SEP_[self._FileType]
 
         MyAgo = self._AutoGenObject
@@ -1481,8 +1480,6 @@ cleanlib:
                 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
         return DirList
 
-    _TemplateDict = property(_CreateTemplateDict)
-
 ## TopLevelMakefile class
 #
 #  This class encapsules makefie and its generation for entrance makefile. It
@@ -1502,7 +1499,8 @@ class TopLevelMakefile(BuildFile):
         self.IntermediateDirectoryList = []
 
     # Compose a dict object containing information used to do replacement in template
-    def _CreateTemplateDict(self):
+    @property
+    def _TemplateDict(self):
         Separator = self._SEP_[self._FileType]
 
         # any platform autogen object is ok because we just need common information
@@ -1622,8 +1620,6 @@ class TopLevelMakefile(BuildFile):
                 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
         return DirList
 
-    _TemplateDict = property(_CreateTemplateDict)
-
 # This acts like the main() function for the script, unless it is 'import'ed into another script.
 if __name__ == '__main__':
     pass
-- 
2.16.2.windows.1



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 4/9] BaseTools: refactor class properties
  2018-09-10 22:18 [PATCH v2 0/9] BaseTools: refactor Workspace classes Jaben Carsey
                   ` (2 preceding siblings ...)
  2018-09-10 22:18 ` [PATCH v2 3/9] BaseTools: AutoGen - refactor class properties Jaben Carsey
@ 2018-09-10 22:18 ` Jaben Carsey
  2018-09-10 22:18 ` [PATCH v2 5/9] BaseTools: Workspace classes refactor properties Jaben Carsey
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Jaben Carsey @ 2018-09-10 22:18 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Yonghong Zhu

use decorators and auto cache those that were cached manually
remove properties never used

Cc: Liming Gao <liming.gao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jaben Carsey <jaben.carsey@intel.com>
---
 BaseTools/Source/Python/Common/Misc.py | 90 +++++++++-----------
 1 file changed, 38 insertions(+), 52 deletions(-)

diff --git a/BaseTools/Source/Python/Common/Misc.py b/BaseTools/Source/Python/Common/Misc.py
index 2cf9574326d5..372fdf01805b 100644
--- a/BaseTools/Source/Python/Common/Misc.py
+++ b/BaseTools/Source/Python/Common/Misc.py
@@ -38,6 +38,7 @@ from Common.LongFilePathSupport import OpenLongFilePath as open
 from Common.MultipleWorkspace import MultipleWorkspace as mws
 import uuid
 from CommonDataClass.Exceptions import BadExpression
+from Common.caching import cached_property
 import subprocess
 ## Regular expression used to find out place holders in string template
 gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE | re.UNICODE)
@@ -1719,8 +1720,6 @@ class PathClass(object):
         self.ToolCode = ToolCode
         self.ToolChainFamily = ToolChainFamily
 
-        self._Key = None
-
     ## Convert the object of this class to a string
     #
     #  Convert member Path of the class to a string
@@ -1773,12 +1772,12 @@ class PathClass(object):
     def __hash__(self):
         return hash(self.Path)
 
-    def _GetFileKey(self):
-        if self._Key is None:
-            self._Key = self.Path.upper()   # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target
-        return self._Key
+    @cached_property
+    def Key(self):
+        return self.Path.upper()
 
-    def _GetTimeStamp(self):
+    @property
+    def TimeStamp(self):
         return os.stat(self.Path)[8]
 
     def Validate(self, Type='', CaseSensitive=True):
@@ -1817,9 +1816,6 @@ class PathClass(object):
             self.Path = os.path.join(RealRoot, RealFile)
         return ErrorCode, ErrorInfo
 
-    Key = property(_GetFileKey)
-    TimeStamp = property(_GetTimeStamp)
-
 ## Parse PE image to get the required PE informaion.
 #
 class PeImageClass():
@@ -1929,8 +1925,8 @@ class DefaultStore():
         for sid, name in self.DefaultStores.values():
             if sid == minid:
                 return name
+
 class SkuClass():
-
     DEFAULT = 0
     SINGLE = 1
     MULTIPLE =2
@@ -1951,8 +1947,8 @@ class SkuClass():
         self.SkuIdSet = []
         self.SkuIdNumberSet = []
         self.SkuData = SkuIds
-        self.__SkuInherit = {}
-        self.__SkuIdentifier = SkuIdentifier
+        self._SkuInherit = {}
+        self._SkuIdentifier = SkuIdentifier
         if SkuIdentifier == '' or SkuIdentifier is None:
             self.SkuIdSet = ['DEFAULT']
             self.SkuIdNumberSet = ['0U']
@@ -1976,7 +1972,7 @@ class SkuClass():
                 EdkLogger.error("build", PARAMETER_INVALID,
                             ExtraData="SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"
                                       % (each, " | ".join(SkuIds.keys())))
-        if self.SkuUsageType != self.SINGLE:
+        if self.SkuUsageType != SkuClass.SINGLE:
             self.AvailableSkuIds.update({'DEFAULT':0, 'COMMON':0})
         if self.SkuIdSet:
             GlobalData.gSkuids = (self.SkuIdSet)
@@ -1990,11 +1986,11 @@ class SkuClass():
                 GlobalData.gSkuids.sort()
 
     def GetNextSkuId(self, skuname):
-        if not self.__SkuInherit:
-            self.__SkuInherit = {}
+        if not self._SkuInherit:
+            self._SkuInherit = {}
             for item in self.SkuData.values():
-                self.__SkuInherit[item[1]]=item[2] if item[2] else "DEFAULT"
-        return self.__SkuInherit.get(skuname, "DEFAULT")
+                self._SkuInherit[item[1]]=item[2] if item[2] else "DEFAULT"
+        return self._SkuInherit.get(skuname, "DEFAULT")
 
     def GetSkuChain(self, sku):
         if sku == "DEFAULT":
@@ -2024,55 +2020,45 @@ class SkuClass():
 
         return skuorder
 
-    def __SkuUsageType(self):
-
-        if self.__SkuIdentifier.upper() == "ALL":
+    @property
+    def SkuUsageType(self):
+        if self._SkuIdentifier.upper() == "ALL":
             return SkuClass.MULTIPLE
 
         if len(self.SkuIdSet) == 1:
             if self.SkuIdSet[0] == 'DEFAULT':
                 return SkuClass.DEFAULT
-            else:
-                return SkuClass.SINGLE
-        elif len(self.SkuIdSet) == 2:
-            if 'DEFAULT' in self.SkuIdSet:
-                return SkuClass.SINGLE
-            else:
-                return SkuClass.MULTIPLE
-        else:
-            return SkuClass.MULTIPLE
+            return SkuClass.SINGLE
+        if len(self.SkuIdSet) == 2 and 'DEFAULT' in self.SkuIdSet:
+            return SkuClass.SINGLE
+        return SkuClass.MULTIPLE
+
     def DumpSkuIdArrary(self):
-
+        if self.SkuUsageType == SkuClass.SINGLE:
+            return "{0x0}"
         ArrayStrList = []
-        if self.SkuUsageType == SkuClass.SINGLE:
-            ArrayStr = "{0x0}"
-        else:
-            for skuname in self.AvailableSkuIds:
-                if skuname == "COMMON":
-                    continue
-                while skuname != "DEFAULT":
-                    ArrayStrList.append(hex(int(self.AvailableSkuIds[skuname])))
-                    skuname = self.GetNextSkuId(skuname)
-                ArrayStrList.append("0x0")
-            ArrayStr = "{" + ",".join(ArrayStrList) +  "}"
-        return ArrayStr
-    def __GetAvailableSkuIds(self):
+        for skuname in self.AvailableSkuIds:
+            if skuname == "COMMON":
+                continue
+            while skuname != "DEFAULT":
+                ArrayStrList.append(hex(int(self.AvailableSkuIds[skuname])))
+                skuname = self.GetNextSkuId(skuname)
+            ArrayStrList.append("0x0")
+        return "{{{myList}}}".format(myList=",".join(ArrayStrList))
+
+    @property
+    def AvailableSkuIdSet(self):
         return self.AvailableSkuIds
 
-    def __GetSystemSkuID(self):
-        if self.__SkuUsageType() == SkuClass.SINGLE:
+    @property
+    def SystemSkuId(self):
+        if self.SkuUsageType == SkuClass.SINGLE:
             if len(self.SkuIdSet) == 1:
                 return self.SkuIdSet[0]
             else:
                 return self.SkuIdSet[0] if self.SkuIdSet[0] != 'DEFAULT' else self.SkuIdSet[1]
         else:
             return 'DEFAULT'
-    def __GetAvailableSkuIdNumber(self):
-        return self.SkuIdNumberSet
-    SystemSkuId = property(__GetSystemSkuID)
-    AvailableSkuIdSet = property(__GetAvailableSkuIds)
-    SkuUsageType = property(__SkuUsageType)
-    AvailableSkuIdNumSet = property(__GetAvailableSkuIdNumber)
 
 #
 # Pack a registry format GUID
-- 
2.16.2.windows.1



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 5/9] BaseTools: Workspace classes refactor properties
  2018-09-10 22:18 [PATCH v2 0/9] BaseTools: refactor Workspace classes Jaben Carsey
                   ` (3 preceding siblings ...)
  2018-09-10 22:18 ` [PATCH v2 4/9] BaseTools: " Jaben Carsey
@ 2018-09-10 22:18 ` Jaben Carsey
  2018-09-10 22:18 ` [PATCH v2 6/9] BaseTools: refactor Build Database objects Jaben Carsey
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Jaben Carsey @ 2018-09-10 22:18 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Yonghong Zhu

1) use decorators
2) also change some private functions to public when all callers are
external
3) change external callers to use functions instead of directly
accessing private data.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jaben Carsey <jaben.carsey@intel.com>
---
 BaseTools/Source/Python/GenFds/FfsInfStatement.py      |   4 +-
 BaseTools/Source/Python/Workspace/DecBuildData.py      |  58 +++---
 BaseTools/Source/Python/Workspace/DscBuildData.py      | 151 +++++++-------
 BaseTools/Source/Python/Workspace/InfBuildData.py      | 212 ++++++++++----------
 BaseTools/Source/Python/Workspace/MetaFileParser.py    |  18 +-
 BaseTools/Source/Python/Workspace/WorkspaceDatabase.py |  16 +-
 BaseTools/Source/Python/build/build.py                 |   4 +-
 7 files changed, 228 insertions(+), 235 deletions(-)

diff --git a/BaseTools/Source/Python/GenFds/FfsInfStatement.py b/BaseTools/Source/Python/GenFds/FfsInfStatement.py
index 56bb966698ad..6149bc81b4ef 100644
--- a/BaseTools/Source/Python/GenFds/FfsInfStatement.py
+++ b/BaseTools/Source/Python/GenFds/FfsInfStatement.py
@@ -341,9 +341,7 @@ class FfsInfStatement(FfsInfStatementClassObject):
         self.InfModule = Inf
         self.PcdIsDriver = Inf.PcdIsDriver
         self.IsBinaryModule = Inf.IsBinaryModule
-        Inf._GetDepex()
-        Inf._GetDepexExpression()
-        if len(Inf._Depex.data) > 0 and len(Inf._DepexExpression.data) > 0:
+        if len(Inf.Depex.data) > 0 and len(Inf.DepexExpression.data) > 0:
             self.Depex = True
 
         GenFdsGlobalVariable.VerboseLogger("BaseName : %s" % self.BaseName)
diff --git a/BaseTools/Source/Python/Workspace/DecBuildData.py b/BaseTools/Source/Python/Workspace/DecBuildData.py
index 45beaebc63ef..1f74e898f2ef 100644
--- a/BaseTools/Source/Python/Workspace/DecBuildData.py
+++ b/BaseTools/Source/Python/Workspace/DecBuildData.py
@@ -99,21 +99,22 @@ class DecBuildData(PackageBuildClassObject):
         self._CommonIncludes    = None
         self._LibraryClasses    = None
         self._Pcds              = None
-        self.__Macros           = None
+        self._MacroDict         = None
         self._PrivateProtocols  = None
         self._PrivatePpis       = None
         self._PrivateGuids      = None
         self._PrivateIncludes   = None
 
     ## Get current effective macros
-    def _GetMacros(self):
-        if self.__Macros is None:
-            self.__Macros = {}
-            self.__Macros.update(GlobalData.gGlobalDefines)
-        return self.__Macros
+    @property
+    def _Macros(self):
+        if self._MacroDict is None:
+            self._MacroDict = dict(GlobalData.gGlobalDefines)
+        return self._MacroDict
 
     ## Get architecture
-    def _GetArch(self):
+    @property
+    def Arch(self):
         return self._Arch
 
     ## Retrieve all information in [Defines] section
@@ -129,7 +130,8 @@ class DecBuildData(PackageBuildClassObject):
         self._Header = 'DUMMY'
 
     ## Retrieve package name
-    def _GetPackageName(self):
+    @property
+    def PackageName(self):
         if self._PackageName is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -138,7 +140,8 @@ class DecBuildData(PackageBuildClassObject):
         return self._PackageName
 
     ## Retrieve file guid
-    def _GetFileGuid(self):
+    @property
+    def PackageName(self):
         if self._Guid is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -147,7 +150,8 @@ class DecBuildData(PackageBuildClassObject):
         return self._Guid
 
     ## Retrieve package version
-    def _GetVersion(self):
+    @property
+    def Version(self):
         if self._Version is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -156,7 +160,8 @@ class DecBuildData(PackageBuildClassObject):
         return self._Version
 
     ## Retrieve protocol definitions (name/value pairs)
-    def _GetProtocol(self):
+    @property
+    def Protocols(self):
         if self._Protocols is None:
             #
             # tdict is a special kind of dict, used for selecting correct
@@ -198,7 +203,8 @@ class DecBuildData(PackageBuildClassObject):
         return self._Protocols
 
     ## Retrieve PPI definitions (name/value pairs)
-    def _GetPpi(self):
+    @property
+    def Ppis(self):
         if self._Ppis is None:
             #
             # tdict is a special kind of dict, used for selecting correct
@@ -240,7 +246,8 @@ class DecBuildData(PackageBuildClassObject):
         return self._Ppis
 
     ## Retrieve GUID definitions (name/value pairs)
-    def _GetGuid(self):
+    @property
+    def Guids(self):
         if self._Guids is None:
             #
             # tdict is a special kind of dict, used for selecting correct
@@ -282,7 +289,8 @@ class DecBuildData(PackageBuildClassObject):
         return self._Guids
 
     ## Retrieve public include paths declared in this package
-    def _GetInclude(self):
+    @property
+    def Includes(self):
         if self._Includes is None or self._CommonIncludes is None:
             self._CommonIncludes = []
             self._Includes = []
@@ -317,7 +325,8 @@ class DecBuildData(PackageBuildClassObject):
         return self._Includes
 
     ## Retrieve library class declarations (not used in build at present)
-    def _GetLibraryClass(self):
+    @property
+    def LibraryClasses(self):
         if self._LibraryClasses is None:
             #
             # tdict is a special kind of dict, used for selecting correct
@@ -341,7 +350,8 @@ class DecBuildData(PackageBuildClassObject):
         return self._LibraryClasses
 
     ## Retrieve PCD declarations
-    def _GetPcds(self):
+    @property
+    def Pcds(self):
         if self._Pcds is None:
             self._Pcds = OrderedDict()
             self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
@@ -351,7 +361,6 @@ class DecBuildData(PackageBuildClassObject):
             self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
         return self._Pcds
 
-
     def ProcessStructurePcd(self, StructurePcdRawDataSet):
         s_pcd_set = OrderedDict()
         for s_pcd, LineNo in StructurePcdRawDataSet:
@@ -446,22 +455,9 @@ class DecBuildData(PackageBuildClassObject):
                 EdkLogger.error("build", PCD_STRUCTURE_PCD_ERROR, "The structure Pcd %s.%s header file is not found in %s line %s \n" % (struct_pcd.TokenSpaceGuidCName, struct_pcd.TokenCName, struct_pcd.DefinitionPosition[0], struct_pcd.DefinitionPosition[1] ))
 
         return Pcds
+
     @property
     def CommonIncludes(self):
         if self._CommonIncludes is None:
             self.Includes
         return self._CommonIncludes
-
-
-    _Macros = property(_GetMacros)
-    Arch = property(_GetArch)
-    PackageName = property(_GetPackageName)
-    Guid = property(_GetFileGuid)
-    Version = property(_GetVersion)
-
-    Protocols = property(_GetProtocol)
-    Ppis = property(_GetPpi)
-    Guids = property(_GetGuid)
-    Includes = property(_GetInclude)
-    LibraryClasses = property(_GetLibraryClass)
-    Pcds = property(_GetPcds)
diff --git a/BaseTools/Source/Python/Workspace/DscBuildData.py b/BaseTools/Source/Python/Workspace/DscBuildData.py
index aaef404772e9..ffc71a9f2dc9 100644
--- a/BaseTools/Source/Python/Workspace/DscBuildData.py
+++ b/BaseTools/Source/Python/Workspace/DscBuildData.py
@@ -222,6 +222,7 @@ class DscBuildData(PlatformBuildClassObject):
         self.WorkspaceDir = os.getenv("WORKSPACE") if os.getenv("WORKSPACE") else ""
         self.DefaultStores = None
         self.SkuIdMgr = SkuClass(self.SkuName, self.SkuIds)
+
     @property
     def OutputPath(self):
         if os.getenv("WORKSPACE"):
@@ -273,10 +274,9 @@ class DscBuildData(PlatformBuildClassObject):
         self._RFCLanguages      = None
         self._ISOLanguages      = None
         self._VpdToolGuid       = None
-        self.__Macros           = None
+        self._MacroDict         = None
         self.DefaultStores      = None
 
-
     ## handle Override Path of Module
     def _HandleOverridePath(self):
         RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch]
@@ -296,16 +296,18 @@ class DscBuildData(PlatformBuildClassObject):
                 GlobalData.gOverrideDir[ModuleFile.Key] = SourceOverridePath
 
     ## Get current effective macros
-    def _GetMacros(self):
-        if self.__Macros is None:
-            self.__Macros = {}
-            self.__Macros.update(GlobalData.gPlatformDefines)
-            self.__Macros.update(GlobalData.gGlobalDefines)
-            self.__Macros.update(GlobalData.gCommandLineDefines)
-        return self.__Macros
+    @property
+    def _Macros(self):
+        if self._MacroDict is None:
+            self._MacroDict = {}
+            self._MacroDict.update(GlobalData.gPlatformDefines)
+            self._MacroDict.update(GlobalData.gGlobalDefines)
+            self._MacroDict.update(GlobalData.gCommandLineDefines)
+        return self._MacroDict
 
     ## Get architecture
-    def _GetArch(self):
+    @property
+    def Arch(self):
         return self._Arch
 
     ## Retrieve all information in [Defines] section
@@ -410,7 +412,8 @@ class DscBuildData(PlatformBuildClassObject):
         self._Header = 'DUMMY'
 
     ## Retrieve platform name
-    def _GetPlatformName(self):
+    @property
+    def PlatformName(self):
         if self._PlatformName is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -418,8 +421,13 @@ class DscBuildData(PlatformBuildClassObject):
                 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_NAME", File=self.MetaFile)
         return self._PlatformName
 
+    @property
+    def Platform(self):
+        return self.PlatformName
+
     ## Retrieve file guid
-    def _GetFileGuid(self):
+    @property
+    def Guid(self):
         if self._Guid is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -428,7 +436,8 @@ class DscBuildData(PlatformBuildClassObject):
         return self._Guid
 
     ## Retrieve platform version
-    def _GetVersion(self):
+    @property
+    def Version(self):
         if self._Version is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -437,7 +446,8 @@ class DscBuildData(PlatformBuildClassObject):
         return self._Version
 
     ## Retrieve platform description file version
-    def _GetDscSpec(self):
+    @property
+    def DscSpecification(self):
         if self._DscSpecification is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -446,7 +456,8 @@ class DscBuildData(PlatformBuildClassObject):
         return self._DscSpecification
 
     ## Retrieve OUTPUT_DIRECTORY
-    def _GetOutpuDir(self):
+    @property
+    def OutputDirectory(self):
         if self._OutputDirectory is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -455,7 +466,8 @@ class DscBuildData(PlatformBuildClassObject):
         return self._OutputDirectory
 
     ## Retrieve SUPPORTED_ARCHITECTURES
-    def _GetSupArch(self):
+    @property
+    def SupArchList(self):
         if self._SupArchList is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -464,7 +476,8 @@ class DscBuildData(PlatformBuildClassObject):
         return self._SupArchList
 
     ## Retrieve BUILD_TARGETS
-    def _GetBuildTarget(self):
+    @property
+    def BuildTargets(self):
         if self._BuildTargets is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -472,14 +485,17 @@ class DscBuildData(PlatformBuildClassObject):
                 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No BUILD_TARGETS", File=self.MetaFile)
         return self._BuildTargets
 
-    def _GetPcdInfoFlag(self):
+    @property
+    def PcdInfoFlag(self):
         if self._PcdInfoFlag is None or self._PcdInfoFlag.upper() == 'FALSE':
             return False
         elif self._PcdInfoFlag.upper() == 'TRUE':
             return True
         else:
             return False
-    def _GetVarCheckFlag(self):
+
+    @property
+    def VarCheckFlag(self):
         if self._VarCheckFlag is None or self._VarCheckFlag.upper() == 'FALSE':
             return False
         elif self._VarCheckFlag.upper() == 'TRUE':
@@ -488,7 +504,8 @@ class DscBuildData(PlatformBuildClassObject):
             return False
 
     # # Retrieve SKUID_IDENTIFIER
-    def _GetSkuName(self):
+    @property
+    def SkuName(self):
         if self._SkuName is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -497,10 +514,12 @@ class DscBuildData(PlatformBuildClassObject):
         return self._SkuName
 
     ## Override SKUID_IDENTIFIER
-    def _SetSkuName(self, Value):
+    @SkuName.setter
+    def SkuName(self, Value):
         self._SkuName = Value
 
-    def _GetFdfFile(self):
+    @property
+    def FlashDefinition(self):
         if self._FlashDefinition is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -508,7 +527,8 @@ class DscBuildData(PlatformBuildClassObject):
                 self._FlashDefinition = ''
         return self._FlashDefinition
 
-    def _GetPrebuild(self):
+    @property
+    def Prebuild(self):
         if self._Prebuild is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -516,7 +536,8 @@ class DscBuildData(PlatformBuildClassObject):
                 self._Prebuild = ''
         return self._Prebuild
 
-    def _GetPostbuild(self):
+    @property
+    def Postbuild(self):
         if self._Postbuild is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -525,7 +546,8 @@ class DscBuildData(PlatformBuildClassObject):
         return self._Postbuild
 
     ## Retrieve FLASH_DEFINITION
-    def _GetBuildNumber(self):
+    @property
+    def BuildNumber(self):
         if self._BuildNumber is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -534,7 +556,8 @@ class DscBuildData(PlatformBuildClassObject):
         return self._BuildNumber
 
     ## Retrieve MAKEFILE_NAME
-    def _GetMakefileName(self):
+    @property
+    def MakefileName(self):
         if self._MakefileName is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -543,7 +566,8 @@ class DscBuildData(PlatformBuildClassObject):
         return self._MakefileName
 
     ## Retrieve BsBaseAddress
-    def _GetBsBaseAddress(self):
+    @property
+    def BsBaseAddress(self):
         if self._BsBaseAddress is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -552,7 +576,8 @@ class DscBuildData(PlatformBuildClassObject):
         return self._BsBaseAddress
 
     ## Retrieve RtBaseAddress
-    def _GetRtBaseAddress(self):
+    @property
+    def RtBaseAddress(self):
         if self._RtBaseAddress is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -561,7 +586,8 @@ class DscBuildData(PlatformBuildClassObject):
         return self._RtBaseAddress
 
     ## Retrieve the top address for the load fix address
-    def _GetLoadFixAddress(self):
+    @property
+    def LoadFixAddress(self):
         if self._LoadFixAddress is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -591,7 +617,8 @@ class DscBuildData(PlatformBuildClassObject):
         return self._LoadFixAddress
 
     ## Retrieve RFCLanguage filter
-    def _GetRFCLanguages(self):
+    @property
+    def RFCLanguages(self):
         if self._RFCLanguages is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -600,15 +627,18 @@ class DscBuildData(PlatformBuildClassObject):
         return self._RFCLanguages
 
     ## Retrieve ISOLanguage filter
-    def _GetISOLanguages(self):
+    @property
+    def ISOLanguages(self):
         if self._ISOLanguages is None:
             if self._Header is None:
                 self._GetHeaderInfo()
             if self._ISOLanguages is None:
                 self._ISOLanguages = []
         return self._ISOLanguages
+
     ## Retrieve the GUID string for VPD tool
-    def _GetVpdToolGuid(self):
+    @property
+    def VpdToolGuid(self):
         if self._VpdToolGuid is None:
             if self._Header is None:
                 self._GetHeaderInfo()
@@ -617,7 +647,8 @@ class DscBuildData(PlatformBuildClassObject):
         return self._VpdToolGuid
 
     ## Retrieve [SkuIds] section information
-    def _GetSkuIds(self):
+    @property
+    def SkuIds(self):
         if self._SkuIds is None:
             self._SkuIds = OrderedDict()
             RecordList = self._RawData[MODEL_EFI_SKU_ID, self._Arch]
@@ -669,7 +700,8 @@ class DscBuildData(PlatformBuildClassObject):
         return self.DefaultStores
 
     ## Retrieve [Components] section information
-    def _GetModules(self):
+    @property
+    def Modules(self):
         if self._Modules is not None:
             return self._Modules
 
@@ -768,13 +800,15 @@ class DscBuildData(PlatformBuildClassObject):
         return self._Modules
 
     ## Retrieve all possible library instances used in this platform
-    def _GetLibraryInstances(self):
+    @property
+    def LibraryInstances(self):
         if self._LibraryInstances is None:
-            self._GetLibraryClasses()
+            self.LibraryClasses
         return self._LibraryInstances
 
     ## Retrieve [LibraryClasses] information
-    def _GetLibraryClasses(self):
+    @property
+    def LibraryClasses(self):
         if self._LibraryClasses is None:
             self._LibraryInstances = []
             #
@@ -922,6 +956,7 @@ class DscBuildData(PlatformBuildClassObject):
                 if isinstance(pcd, StructurePcd) and pcd.SkuOverrideValues:
                     Pcds[pcdname].SkuOverrideValues = {skuid:pcd.SkuOverrideValues[skuid] for skuid in pcd.SkuOverrideValues if skuid in available_sku}
         return Pcds
+
     def CompleteHiiPcdsDefaultStores(self, Pcds):
         HiiPcd = [Pcds[pcd] for pcd in Pcds if Pcds[pcd].Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]]
         DefaultStoreMgr = DefaultStore(self.DefaultStores)
@@ -1102,7 +1137,8 @@ class DscBuildData(PlatformBuildClassObject):
         return PcdValue
 
     ## Retrieve all PCD settings in platform
-    def _GetPcds(self):
+    @property
+    def Pcds(self):
         if self._Pcds is None:
             self._Pcds = OrderedDict()
             self.__ParsePcdFromCommandLine()
@@ -1127,7 +1163,8 @@ class DscBuildData(PlatformBuildClassObject):
         return self._Pcds
 
     ## Retrieve [BuildOptions]
-    def _GetBuildOptions(self):
+    @property
+    def BuildOptions(self):
         if self._BuildOptions is None:
             self._BuildOptions = OrderedDict()
             #
@@ -1226,7 +1263,6 @@ class DscBuildData(PlatformBuildClassObject):
                 Pcd.PcdFieldValueFromComm[field][2] = FieldValues[field][1][1]
         return StruPcds
 
-
     def OverrideByCommOverAll(self,AllPcds):
         def CheckStructureInComm(commpcds):
             if not commpcds:
@@ -2789,7 +2825,8 @@ class DscBuildData(PlatformBuildClassObject):
             Module.MetaFile = FilePath
             self.Modules.append(Module)
 
-    def _GetToolChainFamily(self):
+    @property
+    def ToolChainFamily(self):
         self._ToolChainFamily = TAB_COMPILER_MSFT
         BuildConfigurationFile = os.path.normpath(os.path.join(GlobalData.gConfDirectory, "target.txt"))
         if os.path.isfile(BuildConfigurationFile) == True:
@@ -2824,6 +2861,7 @@ class DscBuildData(PlatformBuildClassObject):
         if (Name, Guid) not in self.Pcds:
             self.Pcds[Name, Guid] = PcdClassObject(Name, Guid, '', '', '', '', '', {}, False, None)
         self.Pcds[Name, Guid].DefaultValue = Value
+
     @property
     def DecPcds(self):
         if self._DecPcds is None:
@@ -2839,34 +2877,3 @@ class DscBuildData(PlatformBuildClassObject):
                 PkgSet.update(ModuleData.Packages)
             self._DecPcds, self._GuidDict = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain, PkgSet)
         return self._DecPcds
-    _Macros             = property(_GetMacros)
-    Arch                = property(_GetArch)
-    Platform            = property(_GetPlatformName)
-    PlatformName        = property(_GetPlatformName)
-    Guid                = property(_GetFileGuid)
-    Version             = property(_GetVersion)
-    DscSpecification    = property(_GetDscSpec)
-    OutputDirectory     = property(_GetOutpuDir)
-    SupArchList         = property(_GetSupArch)
-    BuildTargets        = property(_GetBuildTarget)
-    SkuName             = property(_GetSkuName, _SetSkuName)
-    PcdInfoFlag         = property(_GetPcdInfoFlag)
-    VarCheckFlag        = property(_GetVarCheckFlag)
-    FlashDefinition     = property(_GetFdfFile)
-    Prebuild            = property(_GetPrebuild)
-    Postbuild           = property(_GetPostbuild)
-    BuildNumber         = property(_GetBuildNumber)
-    MakefileName        = property(_GetMakefileName)
-    BsBaseAddress       = property(_GetBsBaseAddress)
-    RtBaseAddress       = property(_GetRtBaseAddress)
-    LoadFixAddress      = property(_GetLoadFixAddress)
-    RFCLanguages        = property(_GetRFCLanguages)
-    ISOLanguages        = property(_GetISOLanguages)
-    VpdToolGuid         = property(_GetVpdToolGuid)
-    SkuIds              = property(_GetSkuIds)
-    Modules             = property(_GetModules)
-    LibraryInstances    = property(_GetLibraryInstances)
-    LibraryClasses      = property(_GetLibraryClasses)
-    Pcds                = property(_GetPcds)
-    BuildOptions        = property(_GetBuildOptions)
-    ToolChainFamily     = property(_GetToolChainFamily)
diff --git a/BaseTools/Source/Python/Workspace/InfBuildData.py b/BaseTools/Source/Python/Workspace/InfBuildData.py
index d666c092a6de..0016cd30ce7a 100644
--- a/BaseTools/Source/Python/Workspace/InfBuildData.py
+++ b/BaseTools/Source/Python/Workspace/InfBuildData.py
@@ -157,40 +157,42 @@ class InfBuildData(ModuleBuildClassObject):
         self._BuildOptions          = None
         self._Depex                 = None
         self._DepexExpression       = None
-        self.__Macros               = None
+        self._MacroDict             = None
 
     ## Get current effective macros
-    def _GetMacros(self):
-        if self.__Macros is None:
-            self.__Macros = {}
+    @property
+    def _Macros(self):
+        if self._MacroDict is None:
+            self._MacroDict = {}
             # EDK_GLOBAL defined macros can be applied to EDK module
             if self.AutoGenVersion < 0x00010005:
-                self.__Macros.update(GlobalData.gEdkGlobal)
-                self.__Macros.update(GlobalData.gGlobalDefines)
-        return self.__Macros
+                self._MacroDict.update(GlobalData.gEdkGlobal)
+                self._MacroDict.update(GlobalData.gGlobalDefines)
+        return self._MacroDict
 
     ## Get architecture
-    def _GetArch(self):
+    @property
+    def Arch(self):
         return self._Arch
 
     ## Return the name of platform employing this module
-    def _GetPlatform(self):
+    @property
+    def Platform(self):
         return self._Platform
 
-    def _GetHeaderComments(self):
+
+    @property
+    def HeaderComments(self):
         if not self._HeaderComments:
-            self._HeaderComments = []
-            RecordList = self._RawData[MODEL_META_DATA_HEADER_COMMENT]
-            for Record in RecordList:
-                self._HeaderComments.append(Record[0])
+            self._HeaderComments = [a[0] for a in self._RawData[MODEL_META_DATA_HEADER_COMMENT]]
         return self._HeaderComments
-    def _GetTailComments(self):
+
+    @property
+    def TailComments(self):
         if not self._TailComments:
-            self._TailComments = []
-            RecordList = self._RawData[MODEL_META_DATA_TAIL_COMMENT]
-            for Record in RecordList:
-                self._TailComments.append(Record[0])
+            self._TailComments = [a[0] for a in self._RawData[MODEL_META_DATA_TAIL_COMMENT]]
         return self._TailComments
+
     ## Retrieve all information in [Defines] section
     #
     #   (Retriving all [Defines] information in one-shot is just to save time.)
@@ -371,7 +373,8 @@ class InfBuildData(ModuleBuildClassObject):
         self._Header_ = 'DUMMY'
 
     ## Retrieve file version
-    def _GetInfVersion(self):
+    @property
+    def AutoGenVersion(self):
         if self._AutoGenVersion is None:
             RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform]
             for Record in RecordList:
@@ -389,7 +392,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._AutoGenVersion
 
     ## Retrieve BASE_NAME
-    def _GetBaseName(self):
+    @property
+    def BaseName(self):
         if self._BaseName is None:
             if self._Header_ is None:
                 self._GetHeaderInfo()
@@ -398,7 +402,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._BaseName
 
     ## Retrieve DxsFile
-    def _GetDxsFile(self):
+    @property
+    def DxsFile(self):
         if self._DxsFile is None:
             if self._Header_ is None:
                 self._GetHeaderInfo()
@@ -407,7 +412,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._DxsFile
 
     ## Retrieve MODULE_TYPE
-    def _GetModuleType(self):
+    @property
+    def ModuleType(self):
         if self._ModuleType is None:
             if self._Header_ is None:
                 self._GetHeaderInfo()
@@ -418,7 +424,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._ModuleType
 
     ## Retrieve COMPONENT_TYPE
-    def _GetComponentType(self):
+    @property
+    def ComponentType(self):
         if self._ComponentType is None:
             if self._Header_ is None:
                 self._GetHeaderInfo()
@@ -427,7 +434,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._ComponentType
 
     ## Retrieve "BUILD_TYPE"
-    def _GetBuildType(self):
+    @property
+    def BuildType(self):
         if self._BuildType is None:
             if self._Header_ is None:
                 self._GetHeaderInfo()
@@ -436,7 +444,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._BuildType
 
     ## Retrieve file guid
-    def _GetFileGuid(self):
+    @property
+    def Guid(self):
         if self._Guid is None:
             if self._Header_ is None:
                 self._GetHeaderInfo()
@@ -445,7 +454,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._Guid
 
     ## Retrieve module version
-    def _GetVersion(self):
+    @property
+    def Version(self):
         if self._Version is None:
             if self._Header_ is None:
                 self._GetHeaderInfo()
@@ -454,7 +464,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._Version
 
     ## Retrieve PCD_IS_DRIVER
-    def _GetPcdIsDriver(self):
+    @property
+    def PcdIsDriver(self):
         if self._PcdIsDriver is None:
             if self._Header_ is None:
                 self._GetHeaderInfo()
@@ -463,7 +474,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._PcdIsDriver
 
     ## Retrieve SHADOW
-    def _GetShadow(self):
+    @property
+    def Shadow(self):
         if self._Shadow is None:
             if self._Header_ is None:
                 self._GetHeaderInfo()
@@ -474,7 +486,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._Shadow
 
     ## Retrieve CUSTOM_MAKEFILE
-    def _GetMakefile(self):
+    @property
+    def CustomMakefile(self):
         if self._CustomMakefile is None:
             if self._Header_ is None:
                 self._GetHeaderInfo()
@@ -483,7 +496,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._CustomMakefile
 
     ## Retrieve EFI_SPECIFICATION_VERSION
-    def _GetSpec(self):
+    @property
+    def Specification(self):
         if self._Specification is None:
             if self._Header_ is None:
                 self._GetHeaderInfo()
@@ -492,7 +506,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._Specification
 
     ## Retrieve LIBRARY_CLASS
-    def _GetLibraryClass(self):
+    @property
+    def LibraryClass(self):
         if self._LibraryClass is None:
             if self._Header_ is None:
                 self._GetHeaderInfo()
@@ -501,7 +516,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._LibraryClass
 
     ## Retrieve ENTRY_POINT
-    def _GetEntryPoint(self):
+    @property
+    def ModuleEntryPointList(self):
         if self._ModuleEntryPointList is None:
             if self._Header_ is None:
                 self._GetHeaderInfo()
@@ -510,7 +526,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._ModuleEntryPointList
 
     ## Retrieve UNLOAD_IMAGE
-    def _GetUnloadImage(self):
+    @property
+    def ModuleUnloadImageList(self):
         if self._ModuleUnloadImageList is None:
             if self._Header_ is None:
                 self._GetHeaderInfo()
@@ -519,7 +536,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._ModuleUnloadImageList
 
     ## Retrieve CONSTRUCTOR
-    def _GetConstructor(self):
+    @property
+    def ConstructorList(self):
         if self._ConstructorList is None:
             if self._Header_ is None:
                 self._GetHeaderInfo()
@@ -528,7 +546,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._ConstructorList
 
     ## Retrieve DESTRUCTOR
-    def _GetDestructor(self):
+    @property
+    def DestructorList(self):
         if self._DestructorList is None:
             if self._Header_ is None:
                 self._GetHeaderInfo()
@@ -537,7 +556,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._DestructorList
 
     ## Retrieve definies other than above ones
-    def _GetDefines(self):
+    @property
+    def Defines(self):
         if len(self._Defs) == 0 and self._Header_ is None:
             self._GetHeaderInfo()
         return self._Defs
@@ -571,7 +591,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._Binaries
 
     ## Retrieve binary files with error check.
-    def _GetBinaryFiles(self):
+    @property
+    def Binaries(self):
         Binaries = self._GetBinaries()
         if GlobalData.gIgnoreSource and Binaries == []:
             ErrorInfo = "The INF file does not contain any Binaries to use in creating the image\n"
@@ -580,7 +601,8 @@ class InfBuildData(ModuleBuildClassObject):
         return Binaries
 
     ## Retrieve source files
-    def _GetSourceFiles(self):
+    @property
+    def Sources(self):
         # Ignore all source files in a binary build mode
         if GlobalData.gIgnoreSource:
             self._Sources = []
@@ -626,7 +648,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._Sources
 
     ## Retrieve library classes employed by this module
-    def _GetLibraryClassUses(self):
+    @property
+    def LibraryClasses(self):
         if self._LibraryClasses is None:
             self._LibraryClasses = OrderedDict()
             RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, self._Platform]
@@ -639,7 +662,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._LibraryClasses
 
     ## Retrieve library names (for Edk.x style of modules)
-    def _GetLibraryNames(self):
+    @property
+    def Libraries(self):
         if self._Libraries is None:
             self._Libraries = []
             RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch, self._Platform]
@@ -651,11 +675,14 @@ class InfBuildData(ModuleBuildClassObject):
                     self._Libraries.append(LibraryName)
         return self._Libraries
 
-    def _GetProtocolComments(self):
-        self._GetProtocols()
+    @property
+    def ProtocolComments(self):
+        self.Protocols
         return self._ProtocolComments
+
     ## Retrieve protocols consumed/produced by this module
-    def _GetProtocols(self):
+    @property
+    def Protocols(self):
         if self._Protocols is None:
             self._Protocols = OrderedDict()
             self._ProtocolComments = OrderedDict()
@@ -676,11 +703,14 @@ class InfBuildData(ModuleBuildClassObject):
                 self._ProtocolComments[CName] = Comments
         return self._Protocols
 
-    def _GetPpiComments(self):
-        self._GetPpis()
+    @property
+    def PpiComments(self):
+        self.Ppis
         return self._PpiComments
+
     ## Retrieve PPIs consumed/produced by this module
-    def _GetPpis(self):
+    @property
+    def Ppis(self):
         if self._Ppis is None:
             self._Ppis = OrderedDict()
             self._PpiComments = OrderedDict()
@@ -701,11 +731,14 @@ class InfBuildData(ModuleBuildClassObject):
                 self._PpiComments[CName] = Comments
         return self._Ppis
 
-    def _GetGuidComments(self):
-        self._GetGuids()
+    @property
+    def GuidComments(self):
+        self.Guids
         return self._GuidComments
+
     ## Retrieve GUIDs consumed/produced by this module
-    def _GetGuids(self):
+    @property
+    def Guids(self):
         if self._Guids is None:
             self._Guids = OrderedDict()
             self._GuidComments = OrderedDict()
@@ -727,7 +760,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._Guids
 
     ## Retrieve include paths necessary for this module (for Edk.x style of modules)
-    def _GetIncludes(self):
+    @property
+    def Includes(self):
         if self._Includes is None:
             self._Includes = []
             if self._SourceOverridePath:
@@ -781,7 +815,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._Includes
 
     ## Retrieve packages this module depends on
-    def _GetPackages(self):
+    @property
+    def Packages(self):
         if self._Packages is None:
             self._Packages = []
             RecordList = self._RawData[MODEL_META_DATA_PACKAGE, self._Arch, self._Platform]
@@ -800,11 +835,14 @@ class InfBuildData(ModuleBuildClassObject):
         return self._Packages
 
     ## Retrieve PCD comments
-    def _GetPcdComments(self):
-        self._GetPcds()
+    @property
+    def PcdComments(self):
+        self.Pcds
         return self._PcdComments
+
     ## Retrieve PCDs used in this module
-    def _GetPcds(self):
+    @property
+    def Pcds(self):
         if self._Pcds is None:
             self._Pcds = OrderedDict()
             self._PcdComments = OrderedDict()
@@ -816,7 +854,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._Pcds
 
     ## Retrieve build options specific to this module
-    def _GetBuildOptions(self):
+    @property
+    def BuildOptions(self):
         if self._BuildOptions is None:
             self._BuildOptions = OrderedDict()
             RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, self._Platform]
@@ -833,7 +872,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._BuildOptions
 
     ## Retrieve dependency expression
-    def _GetDepex(self):
+    @property
+    def Depex(self):
         if self._Depex is None:
             self._Depex = tdict(False, 2)
             RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
@@ -904,7 +944,8 @@ class InfBuildData(ModuleBuildClassObject):
         return self._Depex
 
     ## Retrieve depedency expression
-    def _GetDepexExpression(self):
+    @property
+    def DepexExpression(self):
         if self._DepexExpression is None:
             self._DepexExpression = tdict(False, 2)
             RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
@@ -924,6 +965,7 @@ class InfBuildData(ModuleBuildClassObject):
 
     def GetGuidsUsedByPcd(self):
         return self._GuidsUsedByPcd
+
     ## Retrieve PCD for given type
     def _GetPcd(self, Type):
         Pcds = OrderedDict()
@@ -1114,54 +1156,8 @@ class InfBuildData(ModuleBuildClassObject):
         return Pcds
 
     ## check whether current module is binary module
-    def _IsBinaryModule(self):
-        if self.Binaries and not self.Sources:
+    @property
+    def IsBinaryModule(self):
+        if (self.Binaries and not self.Sources) or GlobalData.gIgnoreSource:
             return True
-        elif GlobalData.gIgnoreSource:
-            return True
-        else:
-            return False
-
-    _Macros = property(_GetMacros)
-    Arch = property(_GetArch)
-    Platform = property(_GetPlatform)
-
-    HeaderComments = property(_GetHeaderComments)
-    TailComments = property(_GetTailComments)
-    AutoGenVersion          = property(_GetInfVersion)
-    BaseName                = property(_GetBaseName)
-    ModuleType              = property(_GetModuleType)
-    ComponentType           = property(_GetComponentType)
-    BuildType               = property(_GetBuildType)
-    Guid                    = property(_GetFileGuid)
-    Version                 = property(_GetVersion)
-    PcdIsDriver             = property(_GetPcdIsDriver)
-    Shadow                  = property(_GetShadow)
-    CustomMakefile          = property(_GetMakefile)
-    Specification           = property(_GetSpec)
-    LibraryClass            = property(_GetLibraryClass)
-    ModuleEntryPointList    = property(_GetEntryPoint)
-    ModuleUnloadImageList   = property(_GetUnloadImage)
-    ConstructorList         = property(_GetConstructor)
-    DestructorList          = property(_GetDestructor)
-    Defines                 = property(_GetDefines)
-    DxsFile                 = property(_GetDxsFile)
-
-    Binaries                = property(_GetBinaryFiles)
-    Sources                 = property(_GetSourceFiles)
-    LibraryClasses          = property(_GetLibraryClassUses)
-    Libraries               = property(_GetLibraryNames)
-    Protocols               = property(_GetProtocols)
-    ProtocolComments        = property(_GetProtocolComments)
-    Ppis                    = property(_GetPpis)
-    PpiComments             = property(_GetPpiComments)
-    Guids                   = property(_GetGuids)
-    GuidComments            = property(_GetGuidComments)
-    Includes                = property(_GetIncludes)
-    Packages                = property(_GetPackages)
-    Pcds                    = property(_GetPcds)
-    PcdComments             = property(_GetPcdComments)
-    BuildOptions            = property(_GetBuildOptions)
-    Depex                   = property(_GetDepex)
-    DepexExpression         = property(_GetDepexExpression)
-    IsBinaryModule          = property(_IsBinaryModule)
+        return False
diff --git a/BaseTools/Source/Python/Workspace/MetaFileParser.py b/BaseTools/Source/Python/Workspace/MetaFileParser.py
index 79e3180d5e77..f1707c06feb9 100644
--- a/BaseTools/Source/Python/Workspace/MetaFileParser.py
+++ b/BaseTools/Source/Python/Workspace/MetaFileParser.py
@@ -213,11 +213,13 @@ class MetaFileParser(object):
         self._PostProcessed = True
 
     ## Get the parse complete flag
-    def _GetFinished(self):
+    @property
+    def Finished(self):
         return self._Finished
 
     ## Set the complete flag
-    def _SetFinished(self, Value):
+    @Finished.setter
+    def Finished(self, Value):
         self._Finished = Value
 
     ## Remove records that do not match given Filter Arch
@@ -416,7 +418,9 @@ class MetaFileParser(object):
                 )
     def GetValidExpression(self, TokenSpaceGuid, PcdCName):
         return self._Table.GetValidExpression(TokenSpaceGuid, PcdCName)
-    def _GetMacros(self):
+
+    @property
+    def _Macros(self):
         Macros = {}
         Macros.update(self._FileLocalMacros)
         Macros.update(self._GetApplicableSectionMacro())
@@ -478,9 +482,6 @@ class MetaFileParser(object):
         return Macros
 
     _SectionParser = {}
-    Finished = property(_GetFinished, _SetFinished)
-    _Macros = property(_GetMacros)
-
 
 ## INF file parser class
 #
@@ -1252,7 +1253,8 @@ class DscParser(MetaFileParser):
                 )
 
     ## Override parent's method since we'll do all macro replacements in parser
-    def _GetMacros(self):
+    @property
+    def _Macros(self):
         Macros = {}
         Macros.update(self._FileLocalMacros)
         Macros.update(self._GetApplicableSectionMacro())
@@ -1673,8 +1675,6 @@ class DscParser(MetaFileParser):
         MODEL_META_DATA_SUBSECTION_HEADER               :   _SubsectionHeaderParser,
     }
 
-    _Macros = property(_GetMacros)
-
 ## DEC file parser class
 #
 #   @param      FilePath        The path of platform description file
diff --git a/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py b/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
index e2f373745fc0..3bb287b8b24c 100644
--- a/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
+++ b/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
@@ -302,25 +302,21 @@ determine whether database file is out of date!\n")
         return PackageList
 
     ## Summarize all platforms in the database
-    def _GetPlatformList(self):
-        PlatformList = []
+    def PlatformList(self):
+        RetVal = []
         for PlatformFile in self.TblFile.GetFileList(MODEL_FILE_DSC):
             try:
-                Platform = self.BuildObject[PathClass(PlatformFile), TAB_COMMON]
+                RetVal.append(self.BuildObject[PathClass(PlatformFile), TAB_COMMON])
             except:
-                Platform = None
-            if Platform is not None:
-                PlatformList.append(Platform)
-        return PlatformList
+                pass
+        return RetVal
 
-    def _MapPlatform(self, Dscfile):
+    def MapPlatform(self, Dscfile):
         Platform = self.BuildObject[PathClass(Dscfile), TAB_COMMON]
         if Platform is None:
             EdkLogger.error('build', PARSER_ERROR, "Failed to parser DSC file: %s" % Dscfile)
         return Platform
 
-    PlatformList = property(_GetPlatformList)
-
 ##
 #
 # This acts like the main() function for the script, unless it is 'import'ed into another
diff --git a/BaseTools/Source/Python/build/build.py b/BaseTools/Source/Python/build/build.py
index e6a9c6ef7199..d74082fc2666 100644
--- a/BaseTools/Source/Python/build/build.py
+++ b/BaseTools/Source/Python/build/build.py
@@ -1006,7 +1006,7 @@ class Build():
         else:
             self.Db.InitDatabase()
             self.Db_Flag = True
-            Platform = self.Db._MapPlatform(str(self.PlatformFile))
+            Platform = self.Db.MapPlatform(str(self.PlatformFile))
             self.Prebuild = str(Platform.Prebuild)
         if self.Prebuild:
             PrebuildList = []
@@ -1045,7 +1045,7 @@ class Build():
         if 'POSTBUILD' in GlobalData.gCommandLineDefines:
             self.Postbuild = GlobalData.gCommandLineDefines.get('POSTBUILD')
         else:
-            Platform = self.Db._MapPlatform(str(self.PlatformFile))
+            Platform = self.Db.MapPlatform(str(self.PlatformFile))
             self.Postbuild = str(Platform.Postbuild)
         if self.Postbuild:
             PostbuildList = []
-- 
2.16.2.windows.1



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 6/9] BaseTools: refactor Build Database objects
  2018-09-10 22:18 [PATCH v2 0/9] BaseTools: refactor Workspace classes Jaben Carsey
                   ` (4 preceding siblings ...)
  2018-09-10 22:18 ` [PATCH v2 5/9] BaseTools: Workspace classes refactor properties Jaben Carsey
@ 2018-09-10 22:18 ` Jaben Carsey
  2018-09-10 22:18 ` [PATCH v2 7/9] BaseTools: Don't save unused workspace data Jaben Carsey
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Jaben Carsey @ 2018-09-10 22:18 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Yonghong Zhu

1) use namedtuple instead of custom class when apropriate
2) rename collections.OrderedDict to OrderedDict since we import it already

Cc: Liming Gao <liming.gao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jaben Carsey <jaben.carsey@intel.com>
---
 BaseTools/Source/Python/Workspace/BuildClassObject.py | 32 ++++++--------------
 1 file changed, 9 insertions(+), 23 deletions(-)

diff --git a/BaseTools/Source/Python/Workspace/BuildClassObject.py b/BaseTools/Source/Python/Workspace/BuildClassObject.py
index 88465c59ea30..e7259b2d3d50 100644
--- a/BaseTools/Source/Python/Workspace/BuildClassObject.py
+++ b/BaseTools/Source/Python/Workspace/BuildClassObject.py
@@ -11,8 +11,8 @@
 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #
 
+from collections import OrderedDict, namedtuple
 from Common.DataType import *
-import collections
 
 ## PcdClassObject
 #
@@ -165,17 +165,17 @@ class StructurePcd(PcdClassObject):
         self.StructuredPcdIncludeFile = [] if StructuredPcdIncludeFile is None else StructuredPcdIncludeFile
         self.PackageDecs = Packages
         self.DefaultStoreName = [default_store]
-        self.DefaultValues = collections.OrderedDict()
+        self.DefaultValues = OrderedDict()
         self.PcdMode = None
-        self.SkuOverrideValues = collections.OrderedDict()
+        self.SkuOverrideValues = OrderedDict()
         self.FlexibleFieldName = None
         self.StructName = None
         self.PcdDefineLineNo = 0
         self.PkgPath = ""
         self.DefaultValueFromDec = ""
         self.ValueChain = set()
-        self.PcdFieldValueFromComm = collections.OrderedDict()
-        self.PcdFieldValueFromFdf = collections.OrderedDict()
+        self.PcdFieldValueFromComm = OrderedDict()
+        self.PcdFieldValueFromFdf = OrderedDict()
     def __repr__(self):
         return self.TypeName
 
@@ -189,9 +189,9 @@ class StructurePcd(PcdClassObject):
         self.DefaultValueFromDec = DefaultValue
     def AddOverrideValue (self, FieldName, Value, SkuName, DefaultStoreName, FileName="", LineNo=0):
         if SkuName not in self.SkuOverrideValues:
-            self.SkuOverrideValues[SkuName] = collections.OrderedDict()
+            self.SkuOverrideValues[SkuName] = OrderedDict()
         if DefaultStoreName not in self.SkuOverrideValues[SkuName]:
-            self.SkuOverrideValues[SkuName][DefaultStoreName] = collections.OrderedDict()
+            self.SkuOverrideValues[SkuName][DefaultStoreName] = OrderedDict()
         if FieldName in self.SkuOverrideValues[SkuName][DefaultStoreName]:
             del self.SkuOverrideValues[SkuName][DefaultStoreName][FieldName]
         self.SkuOverrideValues[SkuName][DefaultStoreName][FieldName] = [Value.strip(), FileName, LineNo]
@@ -241,21 +241,7 @@ class StructurePcd(PcdClassObject):
             self.PcdFieldValueFromComm = PcdObject.PcdFieldValueFromComm if PcdObject.PcdFieldValueFromComm else self.PcdFieldValueFromComm
             self.PcdFieldValueFromFdf = PcdObject.PcdFieldValueFromFdf if PcdObject.PcdFieldValueFromFdf else self.PcdFieldValueFromFdf
 
-## LibraryClassObject
-#
-# This Class defines LibraryClassObject used in BuildDatabase
-#
-# @param object:      Inherited from object class
-# @param Name:        Input value for LibraryClassName, default is None
-# @param SupModList:  Input value for SupModList, default is []
-#
-# @var LibraryClass:  To store value for LibraryClass
-# @var SupModList:    To store value for SupModList
-#
-class LibraryClassObject(object):
-    def __init__(self, Name = None, SupModList = []):
-        self.LibraryClass = Name
-        self.SupModList = SupModList
+LibraryClassObject = namedtuple('LibraryClassObject', ['LibraryClass','SupModList'], verbose=False)
 
 ## ModuleBuildClassObject
 #
@@ -323,7 +309,7 @@ class ModuleBuildClassObject(object):
 
         self.Binaries                = []
         self.Sources                 = []
-        self.LibraryClasses          = collections.OrderedDict()
+        self.LibraryClasses          = OrderedDict()
         self.Libraries               = []
         self.Protocols               = []
         self.Ppis                    = []
-- 
2.16.2.windows.1



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 7/9] BaseTools: Don't save unused workspace data
  2018-09-10 22:18 [PATCH v2 0/9] BaseTools: refactor Workspace classes Jaben Carsey
                   ` (5 preceding siblings ...)
  2018-09-10 22:18 ` [PATCH v2 6/9] BaseTools: refactor Build Database objects Jaben Carsey
@ 2018-09-10 22:18 ` Jaben Carsey
  2018-09-10 22:18 ` [PATCH v2 8/9] BaseTools: refactor to not overcreate ModuleAutoGen objects Jaben Carsey
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Jaben Carsey @ 2018-09-10 22:18 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Yonghong Zhu

  FlexibleFieldName was never used not set.
  DefinitionPosition (file and line number) are recalculated
and never used outside the function.  remove the saving of the
data.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jaben Carsey <jaben.carsey@intel.com>
---
 BaseTools/Source/Python/Workspace/BuildClassObject.py | 7 -------
 BaseTools/Source/Python/Workspace/DecBuildData.py     | 7 ++++---
 2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/BaseTools/Source/Python/Workspace/BuildClassObject.py b/BaseTools/Source/Python/Workspace/BuildClassObject.py
index e7259b2d3d50..f4ffd05324f4 100644
--- a/BaseTools/Source/Python/Workspace/BuildClassObject.py
+++ b/BaseTools/Source/Python/Workspace/BuildClassObject.py
@@ -66,7 +66,6 @@ class PcdClassObject(object):
             self.DscDefaultValue = Value
         self.PcdValueFromComm = ""
         self.PcdValueFromFdf = ""
-        self.DefinitionPosition = ("","")
 
     ## Get the maximum number of bytes
     def GetPcdMaxSize(self):
@@ -168,7 +167,6 @@ class StructurePcd(PcdClassObject):
         self.DefaultValues = OrderedDict()
         self.PcdMode = None
         self.SkuOverrideValues = OrderedDict()
-        self.FlexibleFieldName = None
         self.StructName = None
         self.PcdDefineLineNo = 0
         self.PkgPath = ""
@@ -200,9 +198,6 @@ class StructurePcd(PcdClassObject):
     def SetPcdMode (self, PcdMode):
         self.PcdMode = PcdMode
 
-    def SetFlexibleFieldName (self, FlexibleFieldName):
-        self.FlexibleFieldName = FlexibleFieldName
-
     def copy(self, PcdObject):
         self.TokenCName = PcdObject.TokenCName if PcdObject.TokenCName else self.TokenCName
         self.TokenSpaceGuidCName = PcdObject.TokenSpaceGuidCName if PcdObject.TokenSpaceGuidCName else PcdObject.TokenSpaceGuidCName
@@ -224,7 +219,6 @@ class StructurePcd(PcdClassObject):
         self.DscRawValue = PcdObject.DscRawValue if PcdObject.DscRawValue else self.DscRawValue
         self.PcdValueFromComm = PcdObject.PcdValueFromComm if PcdObject.PcdValueFromComm else self.PcdValueFromComm
         self.PcdValueFromFdf = PcdObject.PcdValueFromFdf if PcdObject.PcdValueFromFdf else self.PcdValueFromFdf
-        self.DefinitionPosition = PcdObject.DefinitionPosition if PcdObject.DefinitionPosition else self.DefinitionPosition
         if isinstance(PcdObject, StructurePcd):
             self.StructuredPcdIncludeFile = PcdObject.StructuredPcdIncludeFile if PcdObject.StructuredPcdIncludeFile else self.StructuredPcdIncludeFile
             self.PackageDecs = PcdObject.PackageDecs if PcdObject.PackageDecs else self.PackageDecs
@@ -233,7 +227,6 @@ class StructurePcd(PcdClassObject):
             self.DefaultFromDSC=None
             self.DefaultValueFromDec = PcdObject.DefaultValueFromDec if PcdObject.DefaultValueFromDec else self.DefaultValueFromDec
             self.SkuOverrideValues = PcdObject.SkuOverrideValues if PcdObject.SkuOverrideValues else self.SkuOverrideValues
-            self.FlexibleFieldName = PcdObject.FlexibleFieldName if PcdObject.FlexibleFieldName else self.FlexibleFieldName
             self.StructName = PcdObject.DatumType if PcdObject.DatumType else self.StructName
             self.PcdDefineLineNo = PcdObject.PcdDefineLineNo if PcdObject.PcdDefineLineNo else self.PcdDefineLineNo
             self.PkgPath = PcdObject.PkgPath if PcdObject.PkgPath else self.PkgPath
diff --git a/BaseTools/Source/Python/Workspace/DecBuildData.py b/BaseTools/Source/Python/Workspace/DecBuildData.py
index 1f74e898f2ef..31ee13eca91f 100644
--- a/BaseTools/Source/Python/Workspace/DecBuildData.py
+++ b/BaseTools/Source/Python/Workspace/DecBuildData.py
@@ -410,6 +410,7 @@ class DecBuildData(PackageBuildClassObject):
             if not (PcdCName, TokenSpaceGuid) in PcdSet:
                 PcdSet.append((PcdCName, TokenSpaceGuid))
 
+        DefinitionPosition = {}
         for PcdCName, TokenSpaceGuid in PcdSet:
             #
             # limit the ARCH to self._Arch, if no self._Arch found, tdict
@@ -436,7 +437,7 @@ class DecBuildData(PackageBuildClassObject):
                                         list(validlists),
                                         list(expressions)
                                         )
-            PcdObj.DefinitionPosition = (self.MetaFile.File, LineNo)
+            DefinitionPosition[PcdObj] = (self.MetaFile.File, LineNo)
             if "." in TokenSpaceGuid:
                 StrPcdSet.append((PcdObj, LineNo))
             else:
@@ -449,10 +450,10 @@ class DecBuildData(PackageBuildClassObject):
         for pcd in Pcds.values():
             if pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
                 if StructPattern.match(pcd.DatumType) is None:
-                    EdkLogger.error('build', FORMAT_INVALID, "DatumType only support BOOLEAN, UINT8, UINT16, UINT32, UINT64, VOID* or a valid struct name.", pcd.DefinitionPosition[0], pcd.DefinitionPosition[1])
+                    EdkLogger.error('build', FORMAT_INVALID, "DatumType only support BOOLEAN, UINT8, UINT16, UINT32, UINT64, VOID* or a valid struct name.", DefinitionPosition[pcd][0], DefinitionPosition[pcd][1])
         for struct_pcd in Pcds.values():
             if isinstance(struct_pcd, StructurePcd) and not struct_pcd.StructuredPcdIncludeFile:
-                EdkLogger.error("build", PCD_STRUCTURE_PCD_ERROR, "The structure Pcd %s.%s header file is not found in %s line %s \n" % (struct_pcd.TokenSpaceGuidCName, struct_pcd.TokenCName, struct_pcd.DefinitionPosition[0], struct_pcd.DefinitionPosition[1] ))
+                EdkLogger.error("build", PCD_STRUCTURE_PCD_ERROR, "The structure Pcd %s.%s header file is not found in %s line %s \n" % (struct_pcd.TokenSpaceGuidCName, struct_pcd.TokenCName, DefinitionPosition[struct_pcd][0], DefinitionPosition[struct_pcd][1] ))
 
         return Pcds
 
-- 
2.16.2.windows.1



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 8/9] BaseTools: refactor to not overcreate ModuleAutoGen objects
  2018-09-10 22:18 [PATCH v2 0/9] BaseTools: refactor Workspace classes Jaben Carsey
                   ` (6 preceding siblings ...)
  2018-09-10 22:18 ` [PATCH v2 7/9] BaseTools: Don't save unused workspace data Jaben Carsey
@ 2018-09-10 22:18 ` Jaben Carsey
  2018-09-10 22:18 ` [PATCH v2 9/9] BaseTools: refactor to cache InfBuildData data Jaben Carsey
  2018-09-20  7:01 ` [PATCH v2 0/9] BaseTools: refactor Workspace classes Zhu, Yonghong
  9 siblings, 0 replies; 11+ messages in thread
From: Jaben Carsey @ 2018-09-10 22:18 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Yonghong Zhu, Bob Feng

currently created for 3 different purposes and saved once.
this makes it created once and saved and then referenced.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Cc: Bob Feng <bob.c.feng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jaben Carsey <jaben.carsey@intel.com>
---
 BaseTools/Source/Python/AutoGen/AutoGen.py | 58 +++++++++-----------
 1 file changed, 25 insertions(+), 33 deletions(-)

diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py b/BaseTools/Source/Python/AutoGen/AutoGen.py
index 35dab75785eb..4e9fc54dbaf3 100644
--- a/BaseTools/Source/Python/AutoGen/AutoGen.py
+++ b/BaseTools/Source/Python/AutoGen/AutoGen.py
@@ -1085,21 +1085,19 @@ class PlatformAutoGen(AutoGen):
     def GenFdsCommand(self):
         return self.Workspace.GenFdsCommand
 
-    ## Create makefile for the platform and mdoules in it
+    ## Create makefile for the platform and modules in it
     #
     #   @param      CreateModuleMakeFile    Flag indicating if the makefile for
     #                                       modules will be created as well
     #
     def CreateMakeFile(self, CreateModuleMakeFile=False, FfsCommand = {}):
         if CreateModuleMakeFile:
-            for ModuleFile in self.Platform.Modules:
-                Ma = ModuleAutoGen(self.Workspace, ModuleFile, self.BuildTarget,
-                                   self.ToolChain, self.Arch, self.MetaFile)
-                if (ModuleFile.File, self.Arch) in FfsCommand:
-                    Ma.CreateMakeFile(True, FfsCommand[ModuleFile.File, self.Arch])
+            for Ma in self._MaList:
+                key = (Ma.MetaFile.File, self.Arch)
+                if key in FfsCommand:
+                    Ma.CreateMakeFile(True, FfsCommand[key])
                 else:
                     Ma.CreateMakeFile(True)
-                #Ma.CreateAsBuiltInf()
 
         # no need to create makefile for the platform more than once
         if self.IsMakeFileCreated:
@@ -1231,16 +1229,12 @@ class PlatformAutoGen(AutoGen):
         for InfName in self._AsBuildInfList:
             InfName = mws.join(self.WorkspaceDir, InfName)
             FdfModuleList.append(os.path.normpath(InfName))
-        for F in self.Platform.Modules.keys():
-            M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self.MetaFile)
-            #GuidValue.update(M.Guids)
-
-            self.Platform.Modules[F].M = M
-
+        for M in self._MaList:
+#            F is the Module for which M is the module autogen
             for PcdFromModule in M.ModulePcdList + M.LibraryPcdList:
                 # make sure that the "VOID*" kind of datum has MaxDatumSize set
                 if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:
-                    NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, F))
+                    NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, M.MetaFile))
 
                 # Check the PCD from Binary INF or Source INF
                 if M.IsBinaryModule == True:
@@ -1250,7 +1244,7 @@ class PlatformAutoGen(AutoGen):
                 PcdFromModule.IsFromDsc = (PcdFromModule.TokenCName, PcdFromModule.TokenSpaceGuidCName) in self.Platform.Pcds
 
                 if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET or PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
-                    if F.Path not in FdfModuleList:
+                    if M.MetaFile.Path not in FdfModuleList:
                         # If one of the Source built modules listed in the DSC is not listed
                         # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
                         # access method (it is only listed in the DEC file that declares the
@@ -1930,19 +1924,25 @@ class PlatformAutoGen(AutoGen):
             TokenNumber += 1
         return RetVal
 
+    @cached_property
+    def _MaList(self):
+        for ModuleFile in self.Platform.Modules:
+            Ma = ModuleAutoGen(
+                  self.Workspace,
+                  ModuleFile,
+                  self.BuildTarget,
+                  self.ToolChain,
+                  self.Arch,
+                  self.MetaFile
+                  )
+            self.Platform.Modules[ModuleFile].M = Ma
+        return [x.M for x in self.Platform.Modules.values()]
+
     ## Summarize ModuleAutoGen objects of all modules to be built for this platform
     @cached_property
     def ModuleAutoGenList(self):
         RetVal = []
-        for ModuleFile in self.Platform.Modules:
-            Ma = ModuleAutoGen(
-                    self.Workspace,
-                    ModuleFile,
-                    self.BuildTarget,
-                    self.ToolChain,
-                    self.Arch,
-                    self.MetaFile
-                    )
+        for Ma in self._MaList:
             if Ma not in RetVal:
                 RetVal.append(Ma)
         return RetVal
@@ -1951,15 +1951,7 @@ class PlatformAutoGen(AutoGen):
     @cached_property
     def LibraryAutoGenList(self):
         RetVal = []
-        for ModuleFile in self.Platform.Modules:
-            Ma = ModuleAutoGen(
-                    self.Workspace,
-                    ModuleFile,
-                    self.BuildTarget,
-                    self.ToolChain,
-                    self.Arch,
-                    self.MetaFile
-                    )
+        for Ma in self._MaList:
             for La in Ma.LibraryAutoGenList:
                 if La not in RetVal:
                     RetVal.append(La)
-- 
2.16.2.windows.1



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 9/9] BaseTools: refactor to cache InfBuildData data
  2018-09-10 22:18 [PATCH v2 0/9] BaseTools: refactor Workspace classes Jaben Carsey
                   ` (7 preceding siblings ...)
  2018-09-10 22:18 ` [PATCH v2 8/9] BaseTools: refactor to not overcreate ModuleAutoGen objects Jaben Carsey
@ 2018-09-10 22:18 ` Jaben Carsey
  2018-09-20  7:01 ` [PATCH v2 0/9] BaseTools: refactor Workspace classes Zhu, Yonghong
  9 siblings, 0 replies; 11+ messages in thread
From: Jaben Carsey @ 2018-09-10 22:18 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Yonghong Zhu, Bob Feng

use Common.caching and auto cache properties and functions of InfBuildData

Cc: Liming Gao <liming.gao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Cc: Bob Feng <bob.c.feng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jaben Carsey <jaben.carsey@intel.com>
---
 BaseTools/Source/Python/Workspace/InfBuildData.py | 840 +++++++++-----------
 1 file changed, 389 insertions(+), 451 deletions(-)

diff --git a/BaseTools/Source/Python/Workspace/InfBuildData.py b/BaseTools/Source/Python/Workspace/InfBuildData.py
index 0016cd30ce7a..44d44d24eb6b 100644
--- a/BaseTools/Source/Python/Workspace/InfBuildData.py
+++ b/BaseTools/Source/Python/Workspace/InfBuildData.py
@@ -13,14 +13,14 @@
 #
 
 from __future__ import absolute_import
-from Common.StringUtils import *
 from Common.DataType import *
 from Common.Misc import *
+from Common.caching import cached_property, cached_class_function
 from types import *
 from .MetaFileParser import *
 from collections import OrderedDict
-
 from Workspace.BuildClassObject import ModuleBuildClassObject, LibraryClassObject, PcdClassObject
+
 ## Module build information from INF file
 #
 #  This class is used to retrieve information stored in database and convert them
@@ -77,9 +77,9 @@ class InfBuildData(ModuleBuildClassObject):
     }
 
 
-    ## Constructor of DscBuildData
+    ## Constructor of InfBuildData
     #
-    #  Initialize object of DscBuildData
+    #  Initialize object of InfBuildData
     #
     #   @param      FilePath        The path of platform description file
     #   @param      RawData         The raw data of DSC file
@@ -97,10 +97,37 @@ class InfBuildData(ModuleBuildClassObject):
         self._Target = Target
         self._Toolchain = Toolchain
         self._Platform = TAB_COMMON
-        self._SourceOverridePath = None
         if FilePath.Key in GlobalData.gOverrideDir:
             self._SourceOverridePath = GlobalData.gOverrideDir[FilePath.Key]
-        self._Clear()
+        else:
+            self._SourceOverridePath = None
+        self._TailComments = None
+        self._BaseName = None
+        self._DxsFile = None
+        self._ModuleType = None
+        self._ComponentType = None
+        self._BuildType = None
+        self._Guid = None
+        self._Version = None
+        self._PcdIsDriver = None
+        self._BinaryModule = None
+        self._Shadow = None
+        self._MakefileName = None
+        self._CustomMakefile = None
+        self._Specification = None
+        self._LibraryClass = None
+        self._ModuleEntryPointList = None
+        self._ModuleUnloadImageList = None
+        self._ConstructorList = None
+        self._DestructorList = None
+        self._Defs = OrderedDict()
+        self._ProtocolComments = None
+        self._PpiComments = None
+        self._GuidsUsedByPcd = OrderedDict()
+        self._GuidComments = None
+        self._PcdComments = None
+        self._BuildOptions = None
+        self._DependencyFileList = None
 
     ## XXX[key] = value
     def __setitem__(self, key, value):
@@ -114,89 +141,39 @@ class InfBuildData(ModuleBuildClassObject):
     def __contains__(self, key):
         return key in self._PROPERTY_
 
-    ## Set all internal used members of InfBuildData to None
-    def _Clear(self):
-        self._HeaderComments = None
-        self._TailComments = None
-        self._Header_               = None
-        self._AutoGenVersion        = None
-        self._BaseName              = None
-        self._DxsFile               = None
-        self._ModuleType            = None
-        self._ComponentType         = None
-        self._BuildType             = None
-        self._Guid                  = None
-        self._Version               = None
-        self._PcdIsDriver           = None
-        self._BinaryModule          = None
-        self._Shadow                = None
-        self._MakefileName          = None
-        self._CustomMakefile        = None
-        self._Specification         = None
-        self._LibraryClass          = None
-        self._ModuleEntryPointList  = None
-        self._ModuleUnloadImageList = None
-        self._ConstructorList       = None
-        self._DestructorList        = None
-        self._Defs                  = OrderedDict()
-        self._Binaries              = None
-        self._Sources               = None
-        self._LibraryClasses        = None
-        self._Libraries             = None
-        self._Protocols             = None
-        self._ProtocolComments      = None
-        self._Ppis                  = None
-        self._PpiComments           = None
-        self._Guids                 = None
-        self._GuidsUsedByPcd        = OrderedDict()
-        self._GuidComments          = None
-        self._Includes              = None
-        self._Packages              = None
-        self._Pcds                  = None
-        self._PcdComments           = None
-        self._BuildOptions          = None
-        self._Depex                 = None
-        self._DepexExpression       = None
-        self._MacroDict             = None
-
     ## Get current effective macros
-    @property
+    @cached_property
     def _Macros(self):
-        if self._MacroDict is None:
-            self._MacroDict = {}
-            # EDK_GLOBAL defined macros can be applied to EDK module
-            if self.AutoGenVersion < 0x00010005:
-                self._MacroDict.update(GlobalData.gEdkGlobal)
-                self._MacroDict.update(GlobalData.gGlobalDefines)
-        return self._MacroDict
+        RetVal = {}
+        # EDK_GLOBAL defined macros can be applied to EDK module
+        if self.AutoGenVersion < 0x00010005:
+            RetVal.update(GlobalData.gEdkGlobal)
+            RetVal.update(GlobalData.gGlobalDefines)
+        return RetVal
 
     ## Get architecture
-    @property
+    @cached_property
     def Arch(self):
         return self._Arch
 
     ## Return the name of platform employing this module
-    @property
+    @cached_property
     def Platform(self):
         return self._Platform
 
-
-    @property
+    @cached_property
     def HeaderComments(self):
-        if not self._HeaderComments:
-            self._HeaderComments = [a[0] for a in self._RawData[MODEL_META_DATA_HEADER_COMMENT]]
-        return self._HeaderComments
+        return [a[0] for a in self._RawData[MODEL_META_DATA_HEADER_COMMENT]]
 
-    @property
+    @cached_property
     def TailComments(self):
-        if not self._TailComments:
-            self._TailComments = [a[0] for a in self._RawData[MODEL_META_DATA_TAIL_COMMENT]]
-        return self._TailComments
+        return [a[0] for a in self._RawData[MODEL_META_DATA_TAIL_COMMENT]]
 
     ## Retrieve all information in [Defines] section
     #
     #   (Retriving all [Defines] information in one-shot is just to save time.)
     #
+    @cached_class_function
     def _GetHeaderInfo(self):
         RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform]
         for Record in RecordList:
@@ -311,9 +288,9 @@ class InfBuildData(ModuleBuildClassObject):
                 if ErrorCode != 0:
                     EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo,
                                     File=self.MetaFile, Line=LineNo)
-                if self.Sources is None:
-                    self._Sources = []
-                self._Sources.append(File)
+                if not self._DependencyFileList:
+                    self._DependencyFileList = []
+                self._DependencyFileList.append(File)
         else:
             if not self._ComponentType:
                 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
@@ -341,9 +318,9 @@ class InfBuildData(ModuleBuildClassObject):
                     if ErrorCode != 0:
                         EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo,
                                         File=self.MetaFile, Line=LineNo)
-                    if self.Sources is None:
-                        self._Sources = []
-                    self._Sources.append(File)
+                    if not self._DependencyFileList:
+                        self._DependencyFileList = []
+                    self._DependencyFileList.append(File)
                 else:
                     ToolList = self._NMAKE_FLAG_PATTERN_.findall(Name)
                     if len(ToolList) == 1:
@@ -369,54 +346,47 @@ class InfBuildData(ModuleBuildClassObject):
                         else:
                             OptionString = self._BuildOptions[TAB_COMPILER_MSFT, ToolChain]
                             self._BuildOptions[TAB_COMPILER_MSFT, ToolChain] = OptionString + " " + Value
-        # set _Header to non-None in order to avoid database re-querying
-        self._Header_ = 'DUMMY'
 
     ## Retrieve file version
-    @property
+    @cached_property
     def AutoGenVersion(self):
-        if self._AutoGenVersion is None:
-            RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform]
-            for Record in RecordList:
-                if Record[1] == TAB_INF_DEFINES_INF_VERSION:
-                    if '.' in Record[2]:
-                        ValueList = Record[2].split('.')
-                        Major = '%04o' % int(ValueList[0], 0)
-                        Minor = '%04o' % int(ValueList[1], 0)
-                        self._AutoGenVersion = int('0x' + Major + Minor, 0)
-                    else:
-                        self._AutoGenVersion = int(Record[2], 0)
-                    break
-            if self._AutoGenVersion is None:
-                self._AutoGenVersion = 0x00010000
-        return self._AutoGenVersion
+        RetVal = 0x00010000
+        RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform]
+        for Record in RecordList:
+            if Record[1] == TAB_INF_DEFINES_INF_VERSION:
+                if '.' in Record[2]:
+                    ValueList = Record[2].split('.')
+                    Major = '%04o' % int(ValueList[0], 0)
+                    Minor = '%04o' % int(ValueList[1], 0)
+                    RetVal = int('0x' + Major + Minor, 0)
+                else:
+                    RetVal = int(Record[2], 0)
+                break
+        return RetVal
 
     ## Retrieve BASE_NAME
-    @property
+    @cached_property
     def BaseName(self):
         if self._BaseName is None:
-            if self._Header_ is None:
-                self._GetHeaderInfo()
+            self._GetHeaderInfo()
             if self._BaseName is None:
                 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No BASE_NAME name", File=self.MetaFile)
         return self._BaseName
 
     ## Retrieve DxsFile
-    @property
+    @cached_property
     def DxsFile(self):
         if self._DxsFile is None:
-            if self._Header_ is None:
-                self._GetHeaderInfo()
+            self._GetHeaderInfo()
             if self._DxsFile is None:
                 self._DxsFile = ''
         return self._DxsFile
 
     ## Retrieve MODULE_TYPE
-    @property
+    @cached_property
     def ModuleType(self):
         if self._ModuleType is None:
-            if self._Header_ is None:
-                self._GetHeaderInfo()
+            self._GetHeaderInfo()
             if self._ModuleType is None:
                 self._ModuleType = SUP_MODULE_BASE
             if self._ModuleType not in SUP_MODULE_LIST:
@@ -424,437 +394,406 @@ class InfBuildData(ModuleBuildClassObject):
         return self._ModuleType
 
     ## Retrieve COMPONENT_TYPE
-    @property
+    @cached_property
     def ComponentType(self):
         if self._ComponentType is None:
-            if self._Header_ is None:
-                self._GetHeaderInfo()
+            self._GetHeaderInfo()
             if self._ComponentType is None:
                 self._ComponentType = SUP_MODULE_USER_DEFINED
         return self._ComponentType
 
     ## Retrieve "BUILD_TYPE"
-    @property
+    @cached_property
     def BuildType(self):
         if self._BuildType is None:
-            if self._Header_ is None:
-                self._GetHeaderInfo()
+            self._GetHeaderInfo()
             if not self._BuildType:
                 self._BuildType = SUP_MODULE_BASE
         return self._BuildType
 
     ## Retrieve file guid
-    @property
+    @cached_property
     def Guid(self):
         if self._Guid is None:
-            if self._Header_ is None:
-                self._GetHeaderInfo()
+            self._GetHeaderInfo()
             if self._Guid is None:
                 self._Guid = '00000000-0000-0000-0000-000000000000'
         return self._Guid
 
     ## Retrieve module version
-    @property
+    @cached_property
     def Version(self):
         if self._Version is None:
-            if self._Header_ is None:
-                self._GetHeaderInfo()
+            self._GetHeaderInfo()
             if self._Version is None:
                 self._Version = '0.0'
         return self._Version
 
     ## Retrieve PCD_IS_DRIVER
-    @property
+    @cached_property
     def PcdIsDriver(self):
         if self._PcdIsDriver is None:
-            if self._Header_ is None:
-                self._GetHeaderInfo()
+            self._GetHeaderInfo()
             if self._PcdIsDriver is None:
                 self._PcdIsDriver = ''
         return self._PcdIsDriver
 
     ## Retrieve SHADOW
-    @property
+    @cached_property
     def Shadow(self):
         if self._Shadow is None:
-            if self._Header_ is None:
-                self._GetHeaderInfo()
-            if self._Shadow is not None and self._Shadow.upper() == 'TRUE':
+            self._GetHeaderInfo()
+            if self._Shadow and self._Shadow.upper() == 'TRUE':
                 self._Shadow = True
             else:
                 self._Shadow = False
         return self._Shadow
 
     ## Retrieve CUSTOM_MAKEFILE
-    @property
+    @cached_property
     def CustomMakefile(self):
         if self._CustomMakefile is None:
-            if self._Header_ is None:
-                self._GetHeaderInfo()
+            self._GetHeaderInfo()
             if self._CustomMakefile is None:
                 self._CustomMakefile = {}
         return self._CustomMakefile
 
     ## Retrieve EFI_SPECIFICATION_VERSION
-    @property
+    @cached_property
     def Specification(self):
         if self._Specification is None:
-            if self._Header_ is None:
-                self._GetHeaderInfo()
+            self._GetHeaderInfo()
             if self._Specification is None:
                 self._Specification = {}
         return self._Specification
 
     ## Retrieve LIBRARY_CLASS
-    @property
+    @cached_property
     def LibraryClass(self):
         if self._LibraryClass is None:
-            if self._Header_ is None:
-                self._GetHeaderInfo()
+            self._GetHeaderInfo()
             if self._LibraryClass is None:
                 self._LibraryClass = []
         return self._LibraryClass
 
     ## Retrieve ENTRY_POINT
-    @property
+    @cached_property
     def ModuleEntryPointList(self):
         if self._ModuleEntryPointList is None:
-            if self._Header_ is None:
-                self._GetHeaderInfo()
+            self._GetHeaderInfo()
             if self._ModuleEntryPointList is None:
                 self._ModuleEntryPointList = []
         return self._ModuleEntryPointList
 
     ## Retrieve UNLOAD_IMAGE
-    @property
+    @cached_property
     def ModuleUnloadImageList(self):
         if self._ModuleUnloadImageList is None:
-            if self._Header_ is None:
-                self._GetHeaderInfo()
+            self._GetHeaderInfo()
             if self._ModuleUnloadImageList is None:
                 self._ModuleUnloadImageList = []
         return self._ModuleUnloadImageList
 
     ## Retrieve CONSTRUCTOR
-    @property
+    @cached_property
     def ConstructorList(self):
         if self._ConstructorList is None:
-            if self._Header_ is None:
-                self._GetHeaderInfo()
+            self._GetHeaderInfo()
             if self._ConstructorList is None:
                 self._ConstructorList = []
         return self._ConstructorList
 
     ## Retrieve DESTRUCTOR
-    @property
+    @cached_property
     def DestructorList(self):
         if self._DestructorList is None:
-            if self._Header_ is None:
-                self._GetHeaderInfo()
+            self._GetHeaderInfo()
             if self._DestructorList is None:
                 self._DestructorList = []
         return self._DestructorList
 
     ## Retrieve definies other than above ones
-    @property
+    @cached_property
     def Defines(self):
-        if len(self._Defs) == 0 and self._Header_ is None:
-            self._GetHeaderInfo()
+        self._GetHeaderInfo()
         return self._Defs
 
     ## Retrieve binary files
+    @cached_class_function
     def _GetBinaries(self):
-        if self._Binaries is None:
-            self._Binaries = []
-            RecordList = self._RawData[MODEL_EFI_BINARY_FILE, self._Arch, self._Platform]
-            Macros = self._Macros
-            Macros["EDK_SOURCE"] = GlobalData.gEcpSource
-            Macros['PROCESSOR'] = self._Arch
-            for Record in RecordList:
-                FileType = Record[0]
-                LineNo = Record[-1]
-                Target = TAB_COMMON
-                FeatureFlag = []
-                if Record[2]:
-                    TokenList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT)
-                    if TokenList:
-                        Target = TokenList[0]
-                    if len(TokenList) > 1:
-                        FeatureFlag = Record[1:]
+        RetVal = []
+        RecordList = self._RawData[MODEL_EFI_BINARY_FILE, self._Arch, self._Platform]
+        Macros = self._Macros
+        Macros["EDK_SOURCE"] = GlobalData.gEcpSource
+        Macros['PROCESSOR'] = self._Arch
+        for Record in RecordList:
+            FileType = Record[0]
+            LineNo = Record[-1]
+            Target = TAB_COMMON
+            FeatureFlag = []
+            if Record[2]:
+                TokenList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT)
+                if TokenList:
+                    Target = TokenList[0]
+                if len(TokenList) > 1:
+                    FeatureFlag = Record[1:]
 
-                File = PathClass(NormPath(Record[1], Macros), self._ModuleDir, '', FileType, True, self._Arch, '', Target)
-                # check the file validation
-                ErrorCode, ErrorInfo = File.Validate()
-                if ErrorCode != 0:
-                    EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
-                self._Binaries.append(File)
-        return self._Binaries
+            File = PathClass(NormPath(Record[1], Macros), self._ModuleDir, '', FileType, True, self._Arch, '', Target)
+            # check the file validation
+            ErrorCode, ErrorInfo = File.Validate()
+            if ErrorCode != 0:
+                EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
+            RetVal.append(File)
+        return RetVal
 
     ## Retrieve binary files with error check.
-    @property
+    @cached_property
     def Binaries(self):
-        Binaries = self._GetBinaries()
-        if GlobalData.gIgnoreSource and Binaries == []:
-            ErrorInfo = "The INF file does not contain any Binaries to use in creating the image\n"
+        RetVal = self._GetBinaries()
+        if GlobalData.gIgnoreSource and not RetVal:
+            ErrorInfo = "The INF file does not contain any RetVal to use in creating the image\n"
             EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, ExtraData=ErrorInfo, File=self.MetaFile)
 
-        return Binaries
+        return RetVal
 
     ## Retrieve source files
-    @property
+    @cached_property
     def Sources(self):
+        self._GetHeaderInfo()
         # Ignore all source files in a binary build mode
         if GlobalData.gIgnoreSource:
-            self._Sources = []
-            return self._Sources
+            return []
 
-        if self._Sources is None:
-            self._Sources = []
-            RecordList = self._RawData[MODEL_EFI_SOURCE_FILE, self._Arch, self._Platform]
-            Macros = self._Macros
-            for Record in RecordList:
-                LineNo = Record[-1]
-                ToolChainFamily = Record[1]
-                TagName = Record[2]
-                ToolCode = Record[3]
-                FeatureFlag = Record[4]
-                if self.AutoGenVersion < 0x00010005:
-                    Macros["EDK_SOURCE"] = GlobalData.gEcpSource
-                    Macros['PROCESSOR'] = self._Arch
-                    SourceFile = NormPath(Record[0], Macros)
-                    if SourceFile[0] == os.path.sep:
-                        SourceFile = mws.join(GlobalData.gWorkspace, SourceFile[1:])
-                    # old module source files (Edk)
-                    File = PathClass(SourceFile, self._ModuleDir, self._SourceOverridePath,
-                                     '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode)
-                    # check the file validation
-                    ErrorCode, ErrorInfo = File.Validate(CaseSensitive=False)
-                    if ErrorCode != 0:
-                        if File.Ext.lower() == '.h':
-                            EdkLogger.warn('build', 'Include file not found', ExtraData=ErrorInfo,
-                                           File=self.MetaFile, Line=LineNo)
-                            continue
-                        else:
-                            EdkLogger.error('build', ErrorCode, ExtraData=File, File=self.MetaFile, Line=LineNo)
-                else:
-                    File = PathClass(NormPath(Record[0], Macros), self._ModuleDir, '',
-                                     '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode)
-                    # check the file validation
-                    ErrorCode, ErrorInfo = File.Validate()
-                    if ErrorCode != 0:
-                        EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
+        RetVal = []
+        RecordList = self._RawData[MODEL_EFI_SOURCE_FILE, self._Arch, self._Platform]
+        Macros = self._Macros
+        for Record in RecordList:
+            LineNo = Record[-1]
+            ToolChainFamily = Record[1]
+            TagName = Record[2]
+            ToolCode = Record[3]
+            if self.AutoGenVersion < 0x00010005:
+                Macros["EDK_SOURCE"] = GlobalData.gEcpSource
+                Macros['PROCESSOR'] = self._Arch
+                SourceFile = NormPath(Record[0], Macros)
+                if SourceFile[0] == os.path.sep:
+                    SourceFile = mws.join(GlobalData.gWorkspace, SourceFile[1:])
+                # old module source files (Edk)
+                File = PathClass(SourceFile, self._ModuleDir, self._SourceOverridePath,
+                                 '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode)
+                # check the file validation
+                ErrorCode, ErrorInfo = File.Validate(CaseSensitive=False)
+                if ErrorCode != 0:
+                    if File.Ext.lower() == '.h':
+                        EdkLogger.warn('build', 'Include file not found', ExtraData=ErrorInfo,
+                                       File=self.MetaFile, Line=LineNo)
+                        continue
+                    else:
+                        EdkLogger.error('build', ErrorCode, ExtraData=File, File=self.MetaFile, Line=LineNo)
+            else:
+                File = PathClass(NormPath(Record[0], Macros), self._ModuleDir, '',
+                                 '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode)
+                # check the file validation
+                ErrorCode, ErrorInfo = File.Validate()
+                if ErrorCode != 0:
+                    EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
 
-                self._Sources.append(File)
-        return self._Sources
+            RetVal.append(File)
+        # add any previously found dependency files to the source list
+        if self._DependencyFileList:
+            RetVal.extend(self._DependencyFileList)
+        return RetVal
 
     ## Retrieve library classes employed by this module
-    @property
+    @cached_property
     def LibraryClasses(self):
-        if self._LibraryClasses is None:
-            self._LibraryClasses = OrderedDict()
-            RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, self._Platform]
-            for Record in RecordList:
-                Lib = Record[0]
-                Instance = Record[1]
-                if Instance:
-                    Instance = NormPath(Instance, self._Macros)
-                self._LibraryClasses[Lib] = Instance
-        return self._LibraryClasses
+        RetVal = OrderedDict()
+        RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, self._Platform]
+        for Record in RecordList:
+            Lib = Record[0]
+            Instance = Record[1]
+            if Instance:
+                Instance = NormPath(Instance, self._Macros)
+            RetVal[Lib] = Instance
+        return RetVal
 
     ## Retrieve library names (for Edk.x style of modules)
-    @property
+    @cached_property
     def Libraries(self):
-        if self._Libraries is None:
-            self._Libraries = []
-            RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch, self._Platform]
-            for Record in RecordList:
-                LibraryName = ReplaceMacro(Record[0], self._Macros, False)
-                # in case of name with '.lib' extension, which is unusual in Edk.x inf
-                LibraryName = os.path.splitext(LibraryName)[0]
-                if LibraryName not in self._Libraries:
-                    self._Libraries.append(LibraryName)
-        return self._Libraries
+        RetVal = []
+        RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch, self._Platform]
+        for Record in RecordList:
+            LibraryName = ReplaceMacro(Record[0], self._Macros, False)
+            # in case of name with '.lib' extension, which is unusual in Edk.x inf
+            LibraryName = os.path.splitext(LibraryName)[0]
+            if LibraryName not in RetVal:
+                RetVal.append(LibraryName)
+        return RetVal
 
-    @property
+    @cached_property
     def ProtocolComments(self):
         self.Protocols
         return self._ProtocolComments
 
     ## Retrieve protocols consumed/produced by this module
-    @property
+    @cached_property
     def Protocols(self):
-        if self._Protocols is None:
-            self._Protocols = OrderedDict()
-            self._ProtocolComments = OrderedDict()
-            RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch, self._Platform]
-            for Record in RecordList:
-                CName = Record[0]
-                Value = ProtocolValue(CName, self.Packages, self.MetaFile.Path)
-                if Value is None:
-                    PackageList = "\n\t".join(str(P) for P in self.Packages)
-                    EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
-                                    "Value of Protocol [%s] is not found under [Protocols] section in" % CName,
-                                    ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
-                self._Protocols[CName] = Value
-                CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]]
-                Comments = []
-                for CmtRec in CommentRecords:
-                    Comments.append(CmtRec[0])
-                self._ProtocolComments[CName] = Comments
-        return self._Protocols
+        RetVal = OrderedDict()
+        self._ProtocolComments = OrderedDict()
+        RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch, self._Platform]
+        for Record in RecordList:
+            CName = Record[0]
+            Value = ProtocolValue(CName, self.Packages, self.MetaFile.Path)
+            if Value is None:
+                PackageList = "\n\t".join(str(P) for P in self.Packages)
+                EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
+                                "Value of Protocol [%s] is not found under [Protocols] section in" % CName,
+                                ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
+            RetVal[CName] = Value
+            CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]]
+            self._ProtocolComments[CName] = [a[0] for a in CommentRecords]
+        return RetVal
 
-    @property
+    @cached_property
     def PpiComments(self):
         self.Ppis
         return self._PpiComments
 
     ## Retrieve PPIs consumed/produced by this module
-    @property
+    @cached_property
     def Ppis(self):
-        if self._Ppis is None:
-            self._Ppis = OrderedDict()
-            self._PpiComments = OrderedDict()
-            RecordList = self._RawData[MODEL_EFI_PPI, self._Arch, self._Platform]
-            for Record in RecordList:
-                CName = Record[0]
-                Value = PpiValue(CName, self.Packages, self.MetaFile.Path)
-                if Value is None:
-                    PackageList = "\n\t".join(str(P) for P in self.Packages)
-                    EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
-                                    "Value of PPI [%s] is not found under [Ppis] section in " % CName,
-                                    ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
-                self._Ppis[CName] = Value
-                CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]]
-                Comments = []
-                for CmtRec in CommentRecords:
-                    Comments.append(CmtRec[0])
-                self._PpiComments[CName] = Comments
-        return self._Ppis
+        RetVal = OrderedDict()
+        self._PpiComments = OrderedDict()
+        RecordList = self._RawData[MODEL_EFI_PPI, self._Arch, self._Platform]
+        for Record in RecordList:
+            CName = Record[0]
+            Value = PpiValue(CName, self.Packages, self.MetaFile.Path)
+            if Value is None:
+                PackageList = "\n\t".join(str(P) for P in self.Packages)
+                EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
+                                "Value of PPI [%s] is not found under [Ppis] section in " % CName,
+                                ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
+            RetVal[CName] = Value
+            CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]]
+            self._PpiComments[CName] = [a[0] for a in CommentRecords]
+        return RetVal
 
-    @property
+    @cached_property
     def GuidComments(self):
         self.Guids
         return self._GuidComments
 
     ## Retrieve GUIDs consumed/produced by this module
-    @property
+    @cached_property
     def Guids(self):
-        if self._Guids is None:
-            self._Guids = OrderedDict()
-            self._GuidComments = OrderedDict()
-            RecordList = self._RawData[MODEL_EFI_GUID, self._Arch, self._Platform]
-            for Record in RecordList:
-                CName = Record[0]
-                Value = GuidValue(CName, self.Packages, self.MetaFile.Path)
-                if Value is None:
-                    PackageList = "\n\t".join(str(P) for P in self.Packages)
-                    EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
-                                    "Value of Guid [%s] is not found under [Guids] section in" % CName,
-                                    ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
-                self._Guids[CName] = Value
-                CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]]
-                Comments = []
-                for CmtRec in CommentRecords:
-                    Comments.append(CmtRec[0])
-                self._GuidComments[CName] = Comments
-        return self._Guids
+        RetVal = OrderedDict()
+        self._GuidComments = OrderedDict()
+        RecordList = self._RawData[MODEL_EFI_GUID, self._Arch, self._Platform]
+        for Record in RecordList:
+            CName = Record[0]
+            Value = GuidValue(CName, self.Packages, self.MetaFile.Path)
+            if Value is None:
+                PackageList = "\n\t".join(str(P) for P in self.Packages)
+                EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
+                                "Value of Guid [%s] is not found under [Guids] section in" % CName,
+                                ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
+            RetVal[CName] = Value
+            CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]]
+            self._GuidComments[CName] = [a[0] for a in CommentRecords]
+        return RetVal
 
     ## Retrieve include paths necessary for this module (for Edk.x style of modules)
-    @property
+    @cached_property
     def Includes(self):
-        if self._Includes is None:
-            self._Includes = []
-            if self._SourceOverridePath:
-                self._Includes.append(self._SourceOverridePath)
+        RetVal = []
+        if self._SourceOverridePath:
+            RetVal.append(self._SourceOverridePath)
 
-            Macros = self._Macros
-            Macros['PROCESSOR'] = GlobalData.gEdkGlobal.get('PROCESSOR', self._Arch)
-            RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch, self._Platform]
-            for Record in RecordList:
-                if Record[0].find('EDK_SOURCE') > -1:
-                    Macros['EDK_SOURCE'] = GlobalData.gEcpSource
-                    File = NormPath(Record[0], self._Macros)
-                    if File[0] == '.':
-                        File = os.path.join(self._ModuleDir, File)
-                    else:
-                        File = os.path.join(GlobalData.gWorkspace, File)
-                    File = RealPath(os.path.normpath(File))
-                    if File:
-                        self._Includes.append(File)
+        Macros = self._Macros
+        Macros['PROCESSOR'] = GlobalData.gEdkGlobal.get('PROCESSOR', self._Arch)
+        RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch, self._Platform]
+        for Record in RecordList:
+            if Record[0].find('EDK_SOURCE') > -1:
+                Macros['EDK_SOURCE'] = GlobalData.gEcpSource
+                File = NormPath(Record[0], self._Macros)
+                if File[0] == '.':
+                    File = os.path.join(self._ModuleDir, File)
+                else:
+                    File = os.path.join(GlobalData.gWorkspace, File)
+                File = RealPath(os.path.normpath(File))
+                if File:
+                    RetVal.append(File)
 
-                    # TRICK: let compiler to choose correct header file
-                    Macros['EDK_SOURCE'] = GlobalData.gEdkSource
-                    File = NormPath(Record[0], self._Macros)
-                    if File[0] == '.':
-                        File = os.path.join(self._ModuleDir, File)
-                    else:
-                        File = os.path.join(GlobalData.gWorkspace, File)
-                    File = RealPath(os.path.normpath(File))
-                    if File:
-                        self._Includes.append(File)
+                # TRICK: let compiler to choose correct header file
+                Macros['EDK_SOURCE'] = GlobalData.gEdkSource
+                File = NormPath(Record[0], self._Macros)
+                if File[0] == '.':
+                    File = os.path.join(self._ModuleDir, File)
+                else:
+                    File = os.path.join(GlobalData.gWorkspace, File)
+                File = RealPath(os.path.normpath(File))
+                if File:
+                    RetVal.append(File)
+            else:
+                File = NormPath(Record[0], Macros)
+                if File[0] == '.':
+                    File = os.path.join(self._ModuleDir, File)
                 else:
+                    File = mws.join(GlobalData.gWorkspace, File)
+                File = RealPath(os.path.normpath(File))
+                if File:
+                    RetVal.append(File)
+                if not File and Record[0].find('EFI_SOURCE') > -1:
+                    # tricky to regard WorkSpace as EFI_SOURCE
+                    Macros['EFI_SOURCE'] = GlobalData.gWorkspace
                     File = NormPath(Record[0], Macros)
                     if File[0] == '.':
                         File = os.path.join(self._ModuleDir, File)
                     else:
-                        File = mws.join(GlobalData.gWorkspace, File)
+                        File = os.path.join(GlobalData.gWorkspace, File)
                     File = RealPath(os.path.normpath(File))
                     if File:
-                        self._Includes.append(File)
-                    if not File and Record[0].find('EFI_SOURCE') > -1:
-                        # tricky to regard WorkSpace as EFI_SOURCE
-                        Macros['EFI_SOURCE'] = GlobalData.gWorkspace
-                        File = NormPath(Record[0], Macros)
-                        if File[0] == '.':
-                            File = os.path.join(self._ModuleDir, File)
-                        else:
-                            File = os.path.join(GlobalData.gWorkspace, File)
-                        File = RealPath(os.path.normpath(File))
-                        if File:
-                            self._Includes.append(File)
-        return self._Includes
+                        RetVal.append(File)
+        return RetVal
 
     ## Retrieve packages this module depends on
-    @property
+    @cached_property
     def Packages(self):
-        if self._Packages is None:
-            self._Packages = []
-            RecordList = self._RawData[MODEL_META_DATA_PACKAGE, self._Arch, self._Platform]
-            Macros = self._Macros
-            Macros['EDK_SOURCE'] = GlobalData.gEcpSource
-            for Record in RecordList:
-                File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
+        RetVal = []
+        RecordList = self._RawData[MODEL_META_DATA_PACKAGE, self._Arch, self._Platform]
+        Macros = self._Macros
+        Macros['EDK_SOURCE'] = GlobalData.gEcpSource
+        for Record in RecordList:
+            File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
+            # check the file validation
+            ErrorCode, ErrorInfo = File.Validate('.dec')
+            if ErrorCode != 0:
                 LineNo = Record[-1]
-                # check the file validation
-                ErrorCode, ErrorInfo = File.Validate('.dec')
-                if ErrorCode != 0:
-                    EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
-                # parse this package now. we need it to get protocol/ppi/guid value
-                Package = self._Bdb[File, self._Arch, self._Target, self._Toolchain]
-                self._Packages.append(Package)
-        return self._Packages
+                EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
+            # parse this package now. we need it to get protocol/ppi/guid value
+            RetVal.append(self._Bdb[File, self._Arch, self._Target, self._Toolchain])
+        return RetVal
 
     ## Retrieve PCD comments
-    @property
+    @cached_property
     def PcdComments(self):
         self.Pcds
         return self._PcdComments
 
     ## Retrieve PCDs used in this module
-    @property
+    @cached_property
     def Pcds(self):
-        if self._Pcds is None:
-            self._Pcds = OrderedDict()
-            self._PcdComments = OrderedDict()
-            self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
-            self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
-            self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
-            self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC))
-            self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
-        return self._Pcds
+        self._PcdComments = OrderedDict()
+        RetVal = OrderedDict()
+        RetVal.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
+        RetVal.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
+        RetVal.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
+        RetVal.update(self._GetPcd(MODEL_PCD_DYNAMIC))
+        RetVal.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
+        return RetVal
 
     ## Retrieve build options specific to this module
-    @property
+    @cached_property
     def BuildOptions(self):
         if self._BuildOptions is None:
             self._BuildOptions = OrderedDict()
@@ -872,98 +811,97 @@ class InfBuildData(ModuleBuildClassObject):
         return self._BuildOptions
 
     ## Retrieve dependency expression
-    @property
+    @cached_property
     def Depex(self):
-        if self._Depex is None:
-            self._Depex = tdict(False, 2)
-            RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
+        RetVal = tdict(False, 2)
 
-            # If the module has only Binaries and no Sources, then ignore [Depex]
-            if self.Sources is None or self.Sources == []:
-                if self.Binaries is not None and self.Binaries != []:
-                    return self._Depex
+        # If the module has only Binaries and no Sources, then ignore [Depex]
+        if not self.Sources and self.Binaries:
+            return RetVal
 
-            # PEIM and DXE drivers must have a valid [Depex] section
-            if len(self.LibraryClass) == 0 and len(RecordList) == 0:
-                if self.ModuleType == SUP_MODULE_DXE_DRIVER or self.ModuleType == SUP_MODULE_PEIM or self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER or \
-                    self.ModuleType == SUP_MODULE_DXE_SAL_DRIVER or self.ModuleType == SUP_MODULE_DXE_RUNTIME_DRIVER:
-                    EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No [Depex] section or no valid expression in [Depex] section for [%s] module" \
-                                    % self.ModuleType, File=self.MetaFile)
+        RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
+        # PEIM and DXE drivers must have a valid [Depex] section
+        if len(self.LibraryClass) == 0 and len(RecordList) == 0:
+            if self.ModuleType == SUP_MODULE_DXE_DRIVER or self.ModuleType == SUP_MODULE_PEIM or self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER or \
+                self.ModuleType == SUP_MODULE_DXE_SAL_DRIVER or self.ModuleType == SUP_MODULE_DXE_RUNTIME_DRIVER:
+                EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No [Depex] section or no valid expression in [Depex] section for [%s] module" \
+                                % self.ModuleType, File=self.MetaFile)
 
-            if len(RecordList) != 0 and self.ModuleType == SUP_MODULE_USER_DEFINED:
-                for Record in RecordList:
-                    if Record[4] not in [SUP_MODULE_PEIM, SUP_MODULE_DXE_DRIVER, SUP_MODULE_DXE_SMM_DRIVER]:
-                        EdkLogger.error('build', FORMAT_INVALID,
-                                        "'%s' module must specify the type of [Depex] section" % self.ModuleType,
-                                        File=self.MetaFile)
-
-            Depex = OrderedDict()
+        if len(RecordList) != 0 and self.ModuleType == SUP_MODULE_USER_DEFINED:
             for Record in RecordList:
-                DepexStr = ReplaceMacro(Record[0], self._Macros, False)
-                Arch = Record[3]
-                ModuleType = Record[4]
-                TokenList = DepexStr.split()
-                if (Arch, ModuleType) not in Depex:
-                    Depex[Arch, ModuleType] = []
-                DepexList = Depex[Arch, ModuleType]
-                for Token in TokenList:
-                    if Token in DEPEX_SUPPORTED_OPCODE_SET:
-                        DepexList.append(Token)
-                    elif Token.endswith(".inf"):  # module file name
-                        ModuleFile = os.path.normpath(Token)
-                        Module = self.BuildDatabase[ModuleFile]
-                        if Module is None:
-                            EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "Module is not found in active platform",
-                                            ExtraData=Token, File=self.MetaFile, Line=Record[-1])
-                        DepexList.append(Module.Guid)
-                    else:
-                        # it use the Fixed PCD format
-                        if '.' in Token:
-                            if tuple(Token.split('.')[::-1]) not in self.Pcds:
-                                EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "PCD [{}] used in [Depex] section should be listed in module PCD section".format(Token), File=self.MetaFile, Line=Record[-1])
-                            else:
-                                if self.Pcds[tuple(Token.split('.')[::-1])].DatumType != TAB_VOID:
-                                    EdkLogger.error('build', FORMAT_INVALID, "PCD [{}] used in [Depex] section should be VOID* datum type".format(Token), File=self.MetaFile, Line=Record[-1])
-                            Value = Token
+                if Record[4] not in [SUP_MODULE_PEIM, SUP_MODULE_DXE_DRIVER, SUP_MODULE_DXE_SMM_DRIVER]:
+                    EdkLogger.error('build', FORMAT_INVALID,
+                                    "'%s' module must specify the type of [Depex] section" % self.ModuleType,
+                                    File=self.MetaFile)
+
+        TemporaryDictionary = OrderedDict()
+        for Record in RecordList:
+            DepexStr = ReplaceMacro(Record[0], self._Macros, False)
+            Arch = Record[3]
+            ModuleType = Record[4]
+            TokenList = DepexStr.split()
+            if (Arch, ModuleType) not in TemporaryDictionary:
+                TemporaryDictionary[Arch, ModuleType] = []
+            DepexList = TemporaryDictionary[Arch, ModuleType]
+            for Token in TokenList:
+                if Token in DEPEX_SUPPORTED_OPCODE_SET:
+                    DepexList.append(Token)
+                elif Token.endswith(".inf"):  # module file name
+                    ModuleFile = os.path.normpath(Token)
+                    Module = self.BuildDatabase[ModuleFile]
+                    if Module is None:
+                        EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "Module is not found in active platform",
+                                        ExtraData=Token, File=self.MetaFile, Line=Record[-1])
+                    DepexList.append(Module.Guid)
+                else:
+                    # it use the Fixed PCD format
+                    if '.' in Token:
+                        if tuple(Token.split('.')[::-1]) not in self.Pcds:
+                            EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "PCD [{}] used in [Depex] section should be listed in module PCD section".format(Token), File=self.MetaFile, Line=Record[-1])
                         else:
-                            # get the GUID value now
-                            Value = ProtocolValue(Token, self.Packages, self.MetaFile.Path)
-                            if Value is None:
-                                Value = PpiValue(Token, self.Packages, self.MetaFile.Path)
-                                if Value is None:
-                                    Value = GuidValue(Token, self.Packages, self.MetaFile.Path)
-
+                            if self.Pcds[tuple(Token.split('.')[::-1])].DatumType != TAB_VOID:
+                                EdkLogger.error('build', FORMAT_INVALID, "PCD [{}] used in [Depex] section should be VOID* datum type".format(Token), File=self.MetaFile, Line=Record[-1])
+                        Value = Token
+                    else:
+                        # get the GUID value now
+                        Value = ProtocolValue(Token, self.Packages, self.MetaFile.Path)
                         if Value is None:
-                            PackageList = "\n\t".join(str(P) for P in self.Packages)
-                            EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
-                                            "Value of [%s] is not found in" % Token,
-                                            ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
-                        DepexList.append(Value)
-            for Arch, ModuleType in Depex:
-                self._Depex[Arch, ModuleType] = Depex[Arch, ModuleType]
-        return self._Depex
+                            Value = PpiValue(Token, self.Packages, self.MetaFile.Path)
+                            if Value is None:
+                                Value = GuidValue(Token, self.Packages, self.MetaFile.Path)
+
+                    if Value is None:
+                        PackageList = "\n\t".join(str(P) for P in self.Packages)
+                        EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
+                                        "Value of [%s] is not found in" % Token,
+                                        ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
+                    DepexList.append(Value)
+        for Arch, ModuleType in TemporaryDictionary:
+            RetVal[Arch, ModuleType] = TemporaryDictionary[Arch, ModuleType]
+        return RetVal
 
     ## Retrieve depedency expression
-    @property
+    @cached_property
     def DepexExpression(self):
-        if self._DepexExpression is None:
-            self._DepexExpression = tdict(False, 2)
-            RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
-            DepexExpression = OrderedDict()
-            for Record in RecordList:
-                DepexStr = ReplaceMacro(Record[0], self._Macros, False)
-                Arch = Record[3]
-                ModuleType = Record[4]
-                TokenList = DepexStr.split()
-                if (Arch, ModuleType) not in DepexExpression:
-                    DepexExpression[Arch, ModuleType] = ''
-                for Token in TokenList:
-                    DepexExpression[Arch, ModuleType] = DepexExpression[Arch, ModuleType] + Token.strip() + ' '
-            for Arch, ModuleType in DepexExpression:
-                self._DepexExpression[Arch, ModuleType] = DepexExpression[Arch, ModuleType]
-        return self._DepexExpression
+        RetVal = tdict(False, 2)
+        RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
+        TemporaryDictionary = OrderedDict()
+        for Record in RecordList:
+            DepexStr = ReplaceMacro(Record[0], self._Macros, False)
+            Arch = Record[3]
+            ModuleType = Record[4]
+            TokenList = DepexStr.split()
+            if (Arch, ModuleType) not in TemporaryDictionary:
+                TemporaryDictionary[Arch, ModuleType] = ''
+            for Token in TokenList:
+                TemporaryDictionary[Arch, ModuleType] = TemporaryDictionary[Arch, ModuleType] + Token.strip() + ' '
+        for Arch, ModuleType in TemporaryDictionary:
+            RetVal[Arch, ModuleType] = TemporaryDictionary[Arch, ModuleType]
+        return RetVal
 
+    @cached_class_function
     def GetGuidsUsedByPcd(self):
+        self.Pcds
         return self._GuidsUsedByPcd
 
     ## Retrieve PCD for given type
-- 
2.16.2.windows.1



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 0/9] BaseTools: refactor Workspace classes
  2018-09-10 22:18 [PATCH v2 0/9] BaseTools: refactor Workspace classes Jaben Carsey
                   ` (8 preceding siblings ...)
  2018-09-10 22:18 ` [PATCH v2 9/9] BaseTools: refactor to cache InfBuildData data Jaben Carsey
@ 2018-09-20  7:01 ` Zhu, Yonghong
  9 siblings, 0 replies; 11+ messages in thread
From: Zhu, Yonghong @ 2018-09-20  7:01 UTC (permalink / raw)
  To: Carsey, Jaben, edk2-devel@lists.01.org

Reviewed-by: Yonghong Zhu <yonghong.zhu@intel.com> 

Best Regards,
Zhu Yonghong

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Jaben Carsey
Sent: Tuesday, September 11, 2018 6:18 AM
To: edk2-devel@lists.01.org
Subject: [edk2] [PATCH v2 0/9] BaseTools: refactor Workspace classes

update the classes for the following:
1) use decorators for property
2) use decorators for caching property and caching function
  - this allows for objects to reduce in size as they get used
3) remove unused variables and properties
4) use tuple instead of custom class when apropriate
5) remove callers from accessing "private" data and use the existing properties
6) removed a circular dependency between APIs

v2:
fix error where class attribute M was accidentally removed.

Jaben Carsey (9):
  BaseTools: Refactor PlatformAutoGen
  BaseTools: AutoGen refactor WorkspaceAutoGen class
  BaseTools: AutoGen - refactor class properties
  BaseTools: refactor class properties
  BaseTools: Workspace classes refactor properties
  BaseTools: refactor Build Database objects
  BaseTools: Don't save unused workspace data
  BaseTools: refactor to not overcreate ModuleAutoGen objects
  BaseTools: refactor to cache InfBuildData data

 BaseTools/Source/Python/AutoGen/AutoGen.py             | 692 +++++++-------
 BaseTools/Source/Python/AutoGen/GenMake.py             |  20 +-
 BaseTools/Source/Python/Common/Misc.py                 |  90 +-
 BaseTools/Source/Python/GenFds/FfsInfStatement.py      |   4 +-
 BaseTools/Source/Python/Workspace/BuildClassObject.py  |  39 +-
 BaseTools/Source/Python/Workspace/DecBuildData.py      |  65 +-
 BaseTools/Source/Python/Workspace/DscBuildData.py      | 151 ++--
 BaseTools/Source/Python/Workspace/InfBuildData.py      | 954 +++++++++-----------
 BaseTools/Source/Python/Workspace/MetaFileParser.py    |  18 +-
 BaseTools/Source/Python/Workspace/WorkspaceDatabase.py |  16 +-
 BaseTools/Source/Python/build/build.py                 |   4 +-
 11 files changed, 933 insertions(+), 1120 deletions(-)

--
2.16.2.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2018-09-20  7:01 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-09-10 22:18 [PATCH v2 0/9] BaseTools: refactor Workspace classes Jaben Carsey
2018-09-10 22:18 ` [PATCH v2 1/9] BaseTools: Refactor PlatformAutoGen Jaben Carsey
2018-09-10 22:18 ` [PATCH v2 2/9] BaseTools: AutoGen refactor WorkspaceAutoGen class Jaben Carsey
2018-09-10 22:18 ` [PATCH v2 3/9] BaseTools: AutoGen - refactor class properties Jaben Carsey
2018-09-10 22:18 ` [PATCH v2 4/9] BaseTools: " Jaben Carsey
2018-09-10 22:18 ` [PATCH v2 5/9] BaseTools: Workspace classes refactor properties Jaben Carsey
2018-09-10 22:18 ` [PATCH v2 6/9] BaseTools: refactor Build Database objects Jaben Carsey
2018-09-10 22:18 ` [PATCH v2 7/9] BaseTools: Don't save unused workspace data Jaben Carsey
2018-09-10 22:18 ` [PATCH v2 8/9] BaseTools: refactor to not overcreate ModuleAutoGen objects Jaben Carsey
2018-09-10 22:18 ` [PATCH v2 9/9] BaseTools: refactor to cache InfBuildData data Jaben Carsey
2018-09-20  7:01 ` [PATCH v2 0/9] BaseTools: refactor Workspace classes Zhu, Yonghong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox