]> git.proxmox.com Git - mirror_edk2.git/commitdiff
BaseTools: AutoGen refactor ModuleAutoGen caching
authorJaben Carsey <jaben.carsey@intel.com>
Fri, 3 Aug 2018 15:11:06 +0000 (23:11 +0800)
committerYonghong Zhu <yonghong.zhu@intel.com>
Mon, 20 Aug 2018 02:53:05 +0000 (10:53 +0800)
1) Add a new file Common/caching.py
    a. Allows for automated caching of repeated class functions, class
        properties, and non-class functions
    b. When called the first time the value is cached and if called a
        second time, the cached result is called, not the function.
    c. When used, this saves lots of memory since the actual function
        pointers are replaced with smaller data elements.
    d.  note that not all features are used yet.
2) Fix AutoGen/GenMake and AutoGen/GetC to not call into private member
    variables of ModuleAutoGen class
    a. use the existing accessor properties for the data
3) Change AutoGen classes to remove a exception for duplicate members in
    __new__ and use ?in? testing to speed up
4) Work on ModuleAutoGen class
    a. Change all properties that use caching to use @caching_property
        (see #1 above)
    b. Change all properties that do not use caching to use standard python
        decorator "@property"
    c. Change all cases where a dictionary/set/list/object was created
        and then immediately updated to use constructor parameters
    d. Refactor each property function to remove the internal variable
        that is no longer needed (this helps find items like #2 above)
    e.  Refactor _ApplyBuildRule with optional parameter to work around
        circular dependency with BinaryFileList.

Note that 4e was almost certainly unintended as the functions were acting on
incomplete information since they were directly accessing private instance
variables at the same time another function on the stack was creating the same
private isntance data.

This overall changes behavior slightly, but makes the codebase smaller and
easier to read.

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>
Reviewed-by: Yonghong Zhu <yonghong.zhu@intel.com>
BaseTools/Source/Python/AutoGen/AutoGen.py
BaseTools/Source/Python/AutoGen/GenC.py
BaseTools/Source/Python/AutoGen/GenMake.py
BaseTools/Source/Python/Common/caching.py [new file with mode: 0644]

index 9b303b69140f2971b7920a597a97eb7e69d6fa2d..3b1ddc74e839ecc4c8dbf563c2308f115a5cd9ea 100644 (file)
@@ -54,6 +54,8 @@ from collections import OrderedDict
 from collections import defaultdict\r
 from Workspace.WorkspaceCommon import OrderedListDict\r
 \r
+from Common.caching import cached_property\r
+\r
 ## Regular expression for splitting Dependency Expression string into tokens\r
 gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")\r
 \r
@@ -195,13 +197,12 @@ class AutoGen(object):
     def __new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
         # check if the object has been created\r
         Key = (Target, Toolchain, Arch, MetaFile)\r
-        try:\r
+        if Key in cls.__ObjectCache:\r
             # if it exists, just return it directly\r
             return cls.__ObjectCache[Key]\r
-        except:\r
             # it didnt exist. create it, cache it, then return it\r
-            cls.__ObjectCache[Key] = super(AutoGen, cls).__new__(cls)\r
-            return cls.__ObjectCache[Key]\r
+        RetVal = cls.__ObjectCache[Key] = super(AutoGen, cls).__new__(cls)\r
+        return RetVal\r
 \r
     def __init__ (self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
         super(AutoGen, self).__init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
@@ -236,9 +237,7 @@ class AutoGen(object):
 class WorkspaceAutoGen(AutoGen):\r
     # call super().__init__ then call the worker function with different parameter count\r
     def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
-        try:\r
-            self._Init\r
-        except:\r
+        if not hasattr(self, "_Init"):\r
             super(WorkspaceAutoGen, self).__init__(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
             self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
             self._Init = True\r
@@ -442,7 +441,7 @@ class WorkspaceAutoGen(AutoGen):
                                     MGen = ModuleAutoGen(self, BuildData.MetaFile, Target, Toolchain, Arch, self.MetaFile)\r
                                     if MGen and MGen.IsLibrary:\r
                                         if MGen in PGen.LibraryAutoGenList:\r
-                                            ReferenceModules = MGen._ReferenceModules\r
+                                            ReferenceModules = MGen.ReferenceModules\r
                                             for ReferenceModule in ReferenceModules:\r
                                                 if ReferenceModule.MetaFile in Platform.Modules:\r
                                                     RefPlatformModule = Platform.Modules[str(ReferenceModule.MetaFile)]\r
@@ -989,9 +988,7 @@ class WorkspaceAutoGen(AutoGen):
 class PlatformAutoGen(AutoGen):\r
     # call super().__init__ then call the worker function with different parameter count\r
     def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
-        try:\r
-            self._Init\r
-        except:\r
+        if not hasattr(self, "_Init"):\r
             super(PlatformAutoGen, self).__init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
             self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch)\r
             self._Init = True\r
@@ -1163,7 +1160,7 @@ class PlatformAutoGen(AutoGen):
         for LibAuto in self.LibraryAutoGenList:\r
             FixedAtBuildPcds = {}\r
             ShareFixedAtBuildPcdsSameValue = {}\r
-            for Module in LibAuto._ReferenceModules:\r
+            for Module in LibAuto.ReferenceModules:\r
                 for Pcd in set(Module.FixedAtBuildPcds + LibAuto.FixedAtBuildPcds):\r
                     DefaultValue = Pcd.DefaultValue\r
                     # Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib\r
@@ -2003,8 +2000,8 @@ class PlatformAutoGen(AutoGen):
             for La in Ma.LibraryAutoGenList:\r
                 if La not in self._LibraryAutoGenList:\r
                     self._LibraryAutoGenList.append(La)\r
-                if Ma not in La._ReferenceModules:\r
-                    La._ReferenceModules.append(Ma)\r
+                if Ma not in La.ReferenceModules:\r
+                    La.ReferenceModules.append(Ma)\r
 \r
     ## Summarize ModuleAutoGen objects of all modules to be built for this platform\r
     def _GetModuleAutoGenList(self):\r
@@ -2487,6 +2484,11 @@ def ExtendCopyDictionaryLists(CopyToDict, CopyFromDict):
     for Key in CopyFromDict:\r
         CopyToDict[Key].extend(CopyFromDict[Key])\r
 \r
+# Create a directory specified by a set of path elements and return the full path\r
+def _MakeDir(PathList):\r
+    RetVal = path.join(*PathList)\r
+    CreateDirectory(RetVal)\r
+    return RetVal\r
 \r
 ## ModuleAutoGen class\r
 #\r
@@ -2497,25 +2499,22 @@ def ExtendCopyDictionaryLists(CopyToDict, CopyFromDict):
 class ModuleAutoGen(AutoGen):\r
     # call super().__init__ then call the worker function with different parameter count\r
     def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
-        try:\r
-            self._Init\r
-        except:\r
+        if not hasattr(self, "_Init"):\r
             super(ModuleAutoGen, self).__init__(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
             self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args)\r
             self._Init = True\r
 \r
-    ## Cache the timestamps of metafiles of every module in a class variable\r
+    ## Cache the timestamps of metafiles of every module in a class attribute\r
     #\r
     TimeDict = {}\r
 \r
     def __new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
-        obj = super(ModuleAutoGen, cls).__new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
         # check if this module is employed by active platform\r
         if not PlatformAutoGen(Workspace, args[0], Target, Toolchain, Arch).ValidModule(MetaFile):\r
             EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \\r
                               % (MetaFile, Arch))\r
             return None\r
-        return obj\r
+        return super(ModuleAutoGen, cls).__new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
 \r
     ## Initialize ModuleAutoGen\r
     #\r
@@ -2559,100 +2558,45 @@ class ModuleAutoGen(AutoGen):
         self.BuildRuleOrder = None\r
         self.BuildTime      = 0\r
 \r
-        self._Module          = None\r
-        self._Name            = None\r
-        self._Guid            = None\r
-        self._Version         = None\r
-        self._ModuleType      = None\r
-        self._ComponentType   = None\r
-        self._PcdIsDriver     = None\r
-        self._AutoGenVersion  = None\r
-        self._LibraryFlag     = None\r
-        self._CustomMakefile  = None\r
-        self._Macro           = None\r
-\r
-        self._BuildDir        = None\r
-        self._OutputDir       = None\r
-        self._FfsOutputDir    = None\r
-        self._DebugDir        = None\r
-        self._MakeFileDir     = None\r
-\r
-        self._IncludePathList = None\r
-        self._AutoGenFileList = None\r
-        self._UnicodeFileList = None\r
-        self._VfrFileList = None\r
-        self._IdfFileList = None\r
-        self._SourceFileList  = None\r
-        self._ObjectFileList  = None\r
-        self._BinaryFileList  = None\r
-\r
-        self._DependentPackageList    = None\r
-        self._DependentLibraryList    = None\r
-        self._LibraryAutoGenList      = None\r
-        self._DerivedPackageList      = None\r
-        self._ModulePcdList           = None\r
-        self._LibraryPcdList          = None\r
         self._PcdComments = OrderedListDict()\r
-        self._GuidList                = None\r
-        self._GuidsUsedByPcd = None\r
         self._GuidComments = OrderedListDict()\r
-        self._ProtocolList            = None\r
         self._ProtocolComments = OrderedListDict()\r
-        self._PpiList                 = None\r
         self._PpiComments = OrderedListDict()\r
-        self._DepexDict               = None\r
-        self._DepexExpressionDict     = None\r
-        self._BuildOption             = None\r
-        self._BuildOptionIncPathList  = None\r
         self._BuildTargets            = None\r
         self._IntroBuildTargetList    = None\r
         self._FinalBuildTargetList    = None\r
         self._FileTypes               = None\r
-        self._BuildRules              = None\r
-\r
-        self._TimeStampPath           = None\r
 \r
         self.AutoGenDepSet = set()\r
-\r
-\r
-        ## The Modules referenced to this Library\r
-        #  Only Library has this attribute\r
-        self._ReferenceModules        = []\r
-\r
-        ## Store the FixedAtBuild Pcds\r
-        #\r
-        self._FixedAtBuildPcds         = []\r
+        self.ReferenceModules = []\r
         self.ConstPcd                  = {}\r
 \r
-        ##Store the VOID* type FixedAtBuild Pcds\r
-        #\r
-        self._FixedPcdVoidTypeDict = {}\r
 \r
     def __repr__(self):\r
         return "%s [%s]" % (self.MetaFile, self.Arch)\r
 \r
     # Get FixedAtBuild Pcds of this Module\r
-    def _GetFixedAtBuildPcds(self):\r
-        if self._FixedAtBuildPcds:\r
-            return self._FixedAtBuildPcds\r
+    @cached_property\r
+    def FixedAtBuildPcds(self):\r
+        RetVal = []\r
         for Pcd in self.ModulePcdList:\r
             if Pcd.Type != TAB_PCDS_FIXED_AT_BUILD:\r
                 continue\r
-            if Pcd not in self._FixedAtBuildPcds:\r
-                self._FixedAtBuildPcds.append(Pcd)\r
-\r
-        return self._FixedAtBuildPcds\r
-\r
-    def _GetFixedAtBuildVoidTypePcds(self):\r
-        if self._FixedPcdVoidTypeDict:\r
-            return self._FixedPcdVoidTypeDict\r
-        for Pcd in self.ModulePcdList:\r
-            if Pcd.Type == TAB_PCDS_FIXED_AT_BUILD and Pcd.DatumType == TAB_VOID:\r
-                if '{}.{}'.format(Pcd.TokenSpaceGuidCName, Pcd.TokenCName) not in self._FixedPcdVoidTypeDict:\r
-                    self._FixedPcdVoidTypeDict['{}.{}'.format(Pcd.TokenSpaceGuidCName, Pcd.TokenCName)] = Pcd.DefaultValue\r
-        return self._FixedPcdVoidTypeDict\r
-\r
-    def _GetUniqueBaseName(self):\r
+            if Pcd not in RetVal:\r
+                RetVal.append(Pcd)\r
+        return RetVal\r
+\r
+    @cached_property\r
+    def FixedVoidTypePcds(self):\r
+        RetVal = {}\r
+        for Pcd in self.FixedAtBuildPcds:\r
+            if Pcd.DatumType == TAB_VOID:\r
+                if '{}.{}'.format(Pcd.TokenSpaceGuidCName, Pcd.TokenCName) not in RetVal:\r
+                    RetVal['{}.{}'.format(Pcd.TokenSpaceGuidCName, Pcd.TokenCName)] = Pcd.DefaultValue\r
+        return RetVal\r
+\r
+    @property\r
+    def UniqueBaseName(self):\r
         BaseName = self.Name\r
         for Module in self.PlatformInfo.ModuleAutoGenList:\r
             if Module.MetaFile == self.MetaFile:\r
@@ -2665,65 +2609,60 @@ class ModuleAutoGen(AutoGen):
         return BaseName\r
 \r
     # Macros could be used in build_rule.txt (also Makefile)\r
-    def _GetMacros(self):\r
-        if self._Macro is None:\r
-            self._Macro = OrderedDict()\r
-            self._Macro["WORKSPACE"             ] = self.WorkspaceDir\r
-            self._Macro["MODULE_NAME"           ] = self.Name\r
-            self._Macro["MODULE_NAME_GUID"      ] = self.UniqueBaseName\r
-            self._Macro["MODULE_GUID"           ] = self.Guid\r
-            self._Macro["MODULE_VERSION"        ] = self.Version\r
-            self._Macro["MODULE_TYPE"           ] = self.ModuleType\r
-            self._Macro["MODULE_FILE"           ] = str(self.MetaFile)\r
-            self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName\r
-            self._Macro["MODULE_RELATIVE_DIR"   ] = self.SourceDir\r
-            self._Macro["MODULE_DIR"            ] = self.SourceDir\r
-\r
-            self._Macro["BASE_NAME"             ] = self.Name\r
-\r
-            self._Macro["ARCH"                  ] = self.Arch\r
-            self._Macro["TOOLCHAIN"             ] = self.ToolChain\r
-            self._Macro["TOOLCHAIN_TAG"         ] = self.ToolChain\r
-            self._Macro["TOOL_CHAIN_TAG"        ] = self.ToolChain\r
-            self._Macro["TARGET"                ] = self.BuildTarget\r
-\r
-            self._Macro["BUILD_DIR"             ] = self.PlatformInfo.BuildDir\r
-            self._Macro["BIN_DIR"               ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)\r
-            self._Macro["LIB_DIR"               ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)\r
-            self._Macro["MODULE_BUILD_DIR"      ] = self.BuildDir\r
-            self._Macro["OUTPUT_DIR"            ] = self.OutputDir\r
-            self._Macro["DEBUG_DIR"             ] = self.DebugDir\r
-            self._Macro["DEST_DIR_OUTPUT"       ] = self.OutputDir\r
-            self._Macro["DEST_DIR_DEBUG"        ] = self.DebugDir\r
-            self._Macro["PLATFORM_NAME"         ] = self.PlatformInfo.Name\r
-            self._Macro["PLATFORM_GUID"         ] = self.PlatformInfo.Guid\r
-            self._Macro["PLATFORM_VERSION"      ] = self.PlatformInfo.Version\r
-            self._Macro["PLATFORM_RELATIVE_DIR" ] = self.PlatformInfo.SourceDir\r
-            self._Macro["PLATFORM_DIR"          ] = mws.join(self.WorkspaceDir, self.PlatformInfo.SourceDir)\r
-            self._Macro["PLATFORM_OUTPUT_DIR"   ] = self.PlatformInfo.OutputDir\r
-            self._Macro["FFS_OUTPUT_DIR"        ] = self.FfsOutputDir\r
-        return self._Macro\r
+    @cached_property\r
+    def Macros(self):\r
+        return OrderedDict((\r
+            ("WORKSPACE" ,self.WorkspaceDir),\r
+            ("MODULE_NAME" ,self.Name),\r
+            ("MODULE_NAME_GUID" ,self.UniqueBaseName),\r
+            ("MODULE_GUID" ,self.Guid),\r
+            ("MODULE_VERSION" ,self.Version),\r
+            ("MODULE_TYPE" ,self.ModuleType),\r
+            ("MODULE_FILE" ,str(self.MetaFile)),\r
+            ("MODULE_FILE_BASE_NAME" ,self.MetaFile.BaseName),\r
+            ("MODULE_RELATIVE_DIR" ,self.SourceDir),\r
+            ("MODULE_DIR" ,self.SourceDir),\r
+            ("BASE_NAME" ,self.Name),\r
+            ("ARCH" ,self.Arch),\r
+            ("TOOLCHAIN" ,self.ToolChain),\r
+            ("TOOLCHAIN_TAG" ,self.ToolChain),\r
+            ("TOOL_CHAIN_TAG" ,self.ToolChain),\r
+            ("TARGET" ,self.BuildTarget),\r
+            ("BUILD_DIR" ,self.PlatformInfo.BuildDir),\r
+            ("BIN_DIR" ,os.path.join(self.PlatformInfo.BuildDir, self.Arch)),\r
+            ("LIB_DIR" ,os.path.join(self.PlatformInfo.BuildDir, self.Arch)),\r
+            ("MODULE_BUILD_DIR" ,self.BuildDir),\r
+            ("OUTPUT_DIR" ,self.OutputDir),\r
+            ("DEBUG_DIR" ,self.DebugDir),\r
+            ("DEST_DIR_OUTPUT" ,self.OutputDir),\r
+            ("DEST_DIR_DEBUG" ,self.DebugDir),\r
+            ("PLATFORM_NAME" ,self.PlatformInfo.Name),\r
+            ("PLATFORM_GUID" ,self.PlatformInfo.Guid),\r
+            ("PLATFORM_VERSION" ,self.PlatformInfo.Version),\r
+            ("PLATFORM_RELATIVE_DIR" ,self.PlatformInfo.SourceDir),\r
+            ("PLATFORM_DIR" ,mws.join(self.WorkspaceDir, self.PlatformInfo.SourceDir)),\r
+            ("PLATFORM_OUTPUT_DIR" ,self.PlatformInfo.OutputDir),\r
+            ("FFS_OUTPUT_DIR" ,self.FfsOutputDir)\r
+            ))\r
 \r
     ## Return the module build data object\r
-    def _GetModule(self):\r
-        if self._Module is None:\r
-            self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]\r
-        return self._Module\r
+    @cached_property\r
+    def Module(self):\r
+        return self.Workspace.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]\r
 \r
     ## Return the module name\r
-    def _GetBaseName(self):\r
+    @cached_property\r
+    def Name(self):\r
         return self.Module.BaseName\r
 \r
     ## Return the module DxsFile if exist\r
-    def _GetDxsFile(self):\r
+    @cached_property\r
+    def DxsFile(self):\r
         return self.Module.DxsFile\r
 \r
-    ## Return the module SourceOverridePath\r
-    def _GetSourceOverridePath(self):\r
-        return self.Module.SourceOverridePath\r
-\r
     ## Return the module meta-file GUID\r
-    def _GetGuid(self):\r
+    @cached_property\r
+    def Guid(self):\r
         #\r
         # To build same module more than once, the module path with FILE_GUID overridden has\r
         # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path\r
@@ -2737,111 +2676,109 @@ class ModuleAutoGen(AutoGen):
         return self.Module.Guid\r
 \r
     ## Return the module version\r
-    def _GetVersion(self):\r
+    @cached_property\r
+    def Version(self):\r
         return self.Module.Version\r
 \r
     ## Return the module type\r
-    def _GetModuleType(self):\r
+    @cached_property\r
+    def ModuleType(self):\r
         return self.Module.ModuleType\r
 \r
     ## Return the component type (for Edk.x style of module)\r
-    def _GetComponentType(self):\r
+    @cached_property\r
+    def ComponentType(self):\r
         return self.Module.ComponentType\r
 \r
     ## Return the build type\r
-    def _GetBuildType(self):\r
+    @cached_property\r
+    def BuildType(self):\r
         return self.Module.BuildType\r
 \r
     ## Return the PCD_IS_DRIVER setting\r
-    def _GetPcdIsDriver(self):\r
+    @cached_property\r
+    def PcdIsDriver(self):\r
         return self.Module.PcdIsDriver\r
 \r
     ## Return the autogen version, i.e. module meta-file version\r
-    def _GetAutoGenVersion(self):\r
+    @cached_property\r
+    def AutoGenVersion(self):\r
         return self.Module.AutoGenVersion\r
 \r
     ## Check if the module is library or not\r
-    def _IsLibrary(self):\r
-        if self._LibraryFlag is None:\r
-            self._LibraryFlag = True if self.Module.LibraryClass else False\r
-        return self._LibraryFlag\r
+    @cached_property\r
+    def IsLibrary(self):\r
+        return bool(self.Module.LibraryClass)\r
 \r
     ## Check if the module is binary module or not\r
-    def _IsBinaryModule(self):\r
+    @cached_property\r
+    def IsBinaryModule(self):\r
         return self.Module.IsBinaryModule\r
 \r
     ## Return the directory to store intermediate files of the module\r
-    def _GetBuildDir(self):\r
-        if self._BuildDir is None:\r
-            self._BuildDir = path.join(\r
+    @cached_property\r
+    def BuildDir(self):\r
+        return _MakeDir((\r
                                     self.PlatformInfo.BuildDir,\r
                                     self.Arch,\r
                                     self.SourceDir,\r
                                     self.MetaFile.BaseName\r
-                                    )\r
-            CreateDirectory(self._BuildDir)\r
-        return self._BuildDir\r
+            ))\r
 \r
     ## Return the directory to store the intermediate object files of the mdoule\r
-    def _GetOutputDir(self):\r
-        if self._OutputDir is None:\r
-            self._OutputDir = path.join(self.BuildDir, "OUTPUT")\r
-            CreateDirectory(self._OutputDir)\r
-        return self._OutputDir\r
-\r
-    ## Return the directory to store ffs file\r
-    def _GetFfsOutputDir(self):\r
-        if self._FfsOutputDir is None:\r
-            if GlobalData.gFdfParser is not None:\r
-                self._FfsOutputDir = path.join(self.PlatformInfo.BuildDir, TAB_FV_DIRECTORY, "Ffs", self.Guid + self.Name)\r
-            else:\r
-                self._FfsOutputDir = ''\r
-        return self._FfsOutputDir\r
+    @cached_property\r
+    def OutputDir(self):\r
+        return _MakeDir((self.BuildDir, "OUTPUT"))\r
+\r
+    ## Return the directory path to store ffs file\r
+    @cached_property\r
+    def FfsOutputDir(self):\r
+        if GlobalData.gFdfParser:\r
+            return path.join(self.PlatformInfo.BuildDir, TAB_FV_DIRECTORY, "Ffs", self.Guid + self.Name)\r
+        return ''\r
 \r
     ## Return the directory to store auto-gened source files of the mdoule\r
-    def _GetDebugDir(self):\r
-        if self._DebugDir is None:\r
-            self._DebugDir = path.join(self.BuildDir, "DEBUG")\r
-            CreateDirectory(self._DebugDir)\r
-        return self._DebugDir\r
+    @cached_property\r
+    def DebugDir(self):\r
+        return _MakeDir((self.BuildDir, "DEBUG"))\r
 \r
     ## Return the path of custom file\r
-    def _GetCustomMakefile(self):\r
-        if self._CustomMakefile is None:\r
-            self._CustomMakefile = {}\r
-            for Type in self.Module.CustomMakefile:\r
-                if Type in gMakeTypeMap:\r
-                    MakeType = gMakeTypeMap[Type]\r
-                else:\r
-                    MakeType = 'nmake'\r
-                if self.SourceOverrideDir is not None:\r
-                    File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])\r
-                    if not os.path.exists(File):\r
-                        File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])\r
-                else:\r
+    @cached_property\r
+    def CustomMakefile(self):\r
+        RetVal = {}\r
+        for Type in self.Module.CustomMakefile:\r
+            MakeType = gMakeTypeMap[Type] if Type in gMakeTypeMap else 'nmake'\r
+            if self.SourceOverrideDir is not None:\r
+                File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])\r
+                if not os.path.exists(File):\r
                     File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])\r
-                self._CustomMakefile[MakeType] = File\r
-        return self._CustomMakefile\r
+            else:\r
+                File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])\r
+            RetVal[MakeType] = File\r
+        return RetVal\r
 \r
     ## Return the directory of the makefile\r
     #\r
     #   @retval     string  The directory string of module's makefile\r
     #\r
-    def _GetMakeFileDir(self):\r
+    @cached_property\r
+    def MakeFileDir(self):\r
         return self.BuildDir\r
 \r
     ## Return build command string\r
     #\r
     #   @retval     string  Build command string\r
     #\r
-    def _GetBuildCommand(self):\r
+    @cached_property\r
+    def BuildCommand(self):\r
         return self.PlatformInfo.BuildCommand\r
 \r
     ## Get object list of all packages the module and its dependent libraries belong to\r
     #\r
     #   @retval     list    The list of package object\r
     #\r
-    def _GetDerivedPackageList(self):\r
+    @cached_property\r
+    def DerivedPackageList(self):\r
         PackageList = []\r
         for M in [self.Module] + self.DependentLibraryList:\r
             for Package in M.Packages:\r
@@ -2914,87 +2851,85 @@ class ModuleAutoGen(AutoGen):
     #\r
     #   @retval     list    The token list of the dependency expression after parsed\r
     #\r
-    def _GetDepexTokenList(self):\r
-        if self._DepexDict is None:\r
-            self._DepexDict = {}\r
-            if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:\r
-                return self._DepexDict\r
-\r
-            self._DepexDict[self.ModuleType] = []\r
-            self._GetFixedAtBuildVoidTypePcds()\r
-            for ModuleType in self._DepexDict:\r
-                DepexList = self._DepexDict[ModuleType]\r
-                #\r
-                # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion\r
-                #\r
-                for M in [self.Module] + self.DependentLibraryList:\r
-                    Inherited = False\r
-                    for D in M.Depex[self.Arch, ModuleType]:\r
-                        if DepexList != []:\r
-                            DepexList.append('AND')\r
-                        DepexList.append('(')\r
-                        #replace D with value if D is FixedAtBuild PCD\r
-                        NewList = []\r
-                        for item in D:\r
-                            if '.' not in item:\r
-                                NewList.append(item)\r
+    @cached_property\r
+    def DepexList(self):\r
+        if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:\r
+            return {}\r
+\r
+        RetVal = {self.ModuleType:[]}\r
+\r
+        for ModuleType in RetVal:\r
+            DepexList = RetVal[ModuleType]\r
+            #\r
+            # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion\r
+            #\r
+            for M in [self.Module] + self.DependentLibraryList:\r
+                Inherited = False\r
+                for D in M.Depex[self.Arch, ModuleType]:\r
+                    if DepexList != []:\r
+                        DepexList.append('AND')\r
+                    DepexList.append('(')\r
+                    #replace D with value if D is FixedAtBuild PCD\r
+                    NewList = []\r
+                    for item in D:\r
+                        if '.' not in item:\r
+                            NewList.append(item)\r
+                        else:\r
+                            if item not in self._FixedPcdVoidTypeDict:\r
+                                EdkLogger.error("build", FORMAT_INVALID, "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type in the module.".format(item))\r
                             else:\r
-                                if item not in self._FixedPcdVoidTypeDict:\r
-                                    EdkLogger.error("build", FORMAT_INVALID, "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type in the module.".format(item))\r
-                                else:\r
-                                    Value = self._FixedPcdVoidTypeDict[item]\r
-                                    if len(Value.split(',')) != 16:\r
-                                        EdkLogger.error("build", FORMAT_INVALID,\r
-                                                        "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type and 16 bytes in the module.".format(item))\r
-                                    NewList.append(Value)\r
-                        DepexList.extend(NewList)\r
-                        if DepexList[-1] == 'END':  # no need of a END at this time\r
-                            DepexList.pop()\r
-                        DepexList.append(')')\r
-                        Inherited = True\r
-                    if Inherited:\r
-                        EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))\r
-                    if 'BEFORE' in DepexList or 'AFTER' in DepexList:\r
-                        break\r
+                                Value = self._FixedPcdVoidTypeDict[item]\r
+                                if len(Value.split(',')) != 16:\r
+                                    EdkLogger.error("build", FORMAT_INVALID,\r
+                                                    "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type and 16 bytes in the module.".format(item))\r
+                                NewList.append(Value)\r
+                    DepexList.extend(NewList)\r
+                    if DepexList[-1] == 'END':  # no need of a END at this time\r
+                        DepexList.pop()\r
+                    DepexList.append(')')\r
+                    Inherited = True\r
+                if Inherited:\r
+                    EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))\r
+                if 'BEFORE' in DepexList or 'AFTER' in DepexList:\r
+                    break\r
                 if len(DepexList) > 0:\r
                     EdkLogger.verbose('')\r
-        return self._DepexDict\r
+        return RetVal\r
 \r
     ## Merge dependency expression\r
     #\r
     #   @retval     list    The token list of the dependency expression after parsed\r
     #\r
-    def _GetDepexExpressionTokenList(self):\r
-        if self._DepexExpressionDict is None:\r
-            self._DepexExpressionDict = {}\r
-            if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:\r
-                return self._DepexExpressionDict\r
+    @cached_property\r
+    def DepexExpressionTokenList(self):\r
+        if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:\r
+            return {}\r
 \r
-            self._DepexExpressionDict[self.ModuleType] = ''\r
+        RetVal = {self.ModuleType:''}\r
 \r
-            for ModuleType in self._DepexExpressionDict:\r
-                DepexExpressionString = self._DepexExpressionDict[ModuleType]\r
-                #\r
-                # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion\r
-                #\r
-                for M in [self.Module] + self.DependentLibraryList:\r
-                    Inherited = False\r
-                    for D in M.DepexExpression[self.Arch, ModuleType]:\r
-                        if DepexExpressionString != '':\r
-                            DepexExpressionString += ' AND '\r
-                        DepexExpressionString += '('\r
-                        DepexExpressionString += D\r
-                        DepexExpressionString = DepexExpressionString.rstrip('END').strip()\r
-                        DepexExpressionString += ')'\r
-                        Inherited = True\r
-                    if Inherited:\r
-                        EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionString))\r
-                    if 'BEFORE' in DepexExpressionString or 'AFTER' in DepexExpressionString:\r
-                        break\r
-                if len(DepexExpressionString) > 0:\r
-                    EdkLogger.verbose('')\r
-                self._DepexExpressionDict[ModuleType] = DepexExpressionString\r
-        return self._DepexExpressionDict\r
+        for ModuleType in RetVal:\r
+            DepexExpressionString = RetVal[ModuleType]\r
+            #\r
+            # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion\r
+            #\r
+            for M in [self.Module] + self.DependentLibraryList:\r
+                Inherited = False\r
+                for D in M.DepexExpression[self.Arch, ModuleType]:\r
+                    if DepexExpressionString != '':\r
+                        DepexExpressionString += ' AND '\r
+                    DepexExpressionString += '('\r
+                    DepexExpressionString += D\r
+                    DepexExpressionString = DepexExpressionString.rstrip('END').strip()\r
+                    DepexExpressionString += ')'\r
+                    Inherited = True\r
+                if Inherited:\r
+                    EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionString))\r
+                if 'BEFORE' in DepexExpressionString or 'AFTER' in DepexExpressionString:\r
+                    break\r
+            if len(DepexExpressionString) > 0:\r
+                EdkLogger.verbose('')\r
+            RetVal[ModuleType] = DepexExpressionString\r
+        return RetVal\r
 \r
     # Get the tiano core user extension, it is contain dependent library.\r
     # @retval: a list contain tiano core userextension.\r
@@ -3024,7 +2959,8 @@ class ModuleAutoGen(AutoGen):
     #\r
     #   @retval     list    The list of specification defined in module file\r
     #\r
-    def _GetSpecification(self):\r
+    @cached_property\r
+    def Specification(self):\r
         return self.Module.Specification\r
 \r
     ## Tool option for the module build\r
@@ -3032,111 +2968,105 @@ class ModuleAutoGen(AutoGen):
     #   @param      PlatformInfo    The object of PlatformBuildInfo\r
     #   @retval     dict            The dict containing valid options\r
     #\r
-    def _GetModuleBuildOption(self):\r
-        if self._BuildOption is None:\r
-            self._BuildOption, self.BuildRuleOrder = self.PlatformInfo.ApplyBuildOption(self.Module)\r
-            if self.BuildRuleOrder:\r
-                self.BuildRuleOrder = ['.%s' % Ext for Ext in self.BuildRuleOrder.split()]\r
-        return self._BuildOption\r
+    @cached_property\r
+    def BuildOption(self):\r
+        RetVal, self.BuildRuleOrder = self.PlatformInfo.ApplyBuildOption(self.Module)\r
+        if self.BuildRuleOrder:\r
+            self.BuildRuleOrder = ['.%s' % Ext for Ext in self.BuildRuleOrder.split()]\r
+        return RetVal\r
 \r
     ## Get include path list from tool option for the module build\r
     #\r
     #   @retval     list            The include path list\r
     #\r
-    def _GetBuildOptionIncPathList(self):\r
-        if self._BuildOptionIncPathList is None:\r
+    @cached_property\r
+    def BuildOptionIncPathList(self):\r
+        #\r
+        # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT\r
+        # is the former use /I , the Latter used -I to specify include directories\r
+        #\r
+        if self.PlatformInfo.ToolChainFamily in ('MSFT'):\r
+            BuildOptIncludeRegEx = gBuildOptIncludePatternMsft\r
+        elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):\r
+            BuildOptIncludeRegEx = gBuildOptIncludePatternOther\r
+        else:\r
             #\r
-            # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT\r
-            # is the former use /I , the Latter used -I to specify include directories\r
+            # New ToolChainFamily, don't known whether there is option to specify include directories\r
             #\r
-            if self.PlatformInfo.ToolChainFamily in ('MSFT'):\r
-                BuildOptIncludeRegEx = gBuildOptIncludePatternMsft\r
-            elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):\r
-                BuildOptIncludeRegEx = gBuildOptIncludePatternOther\r
-            else:\r
-                #\r
-                # New ToolChainFamily, don't known whether there is option to specify include directories\r
-                #\r
-                self._BuildOptionIncPathList = []\r
-                return self._BuildOptionIncPathList\r
-\r
-            BuildOptionIncPathList = []\r
-            for Tool in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):\r
-                try:\r
-                    FlagOption = self.BuildOption[Tool]['FLAGS']\r
-                except KeyError:\r
-                    FlagOption = ''\r
+            return []\r
 \r
-                if self.PlatformInfo.ToolChainFamily != 'RVCT':\r
-                    IncPathList = [NormPath(Path, self.Macros) for Path in BuildOptIncludeRegEx.findall(FlagOption)]\r
-                else:\r
-                    #\r
-                    # RVCT may specify a list of directory seperated by commas\r
-                    #\r
-                    IncPathList = []\r
-                    for Path in BuildOptIncludeRegEx.findall(FlagOption):\r
-                        PathList = GetSplitList(Path, TAB_COMMA_SPLIT)\r
-                        IncPathList.extend(NormPath(PathEntry, self.Macros) for PathEntry in PathList)\r
+        RetVal = []\r
+        for Tool in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):\r
+            try:\r
+                FlagOption = self.BuildOption[Tool]['FLAGS']\r
+            except KeyError:\r
+                FlagOption = ''\r
 \r
+            if self.PlatformInfo.ToolChainFamily != 'RVCT':\r
+                IncPathList = [NormPath(Path, self.Macros) for Path in BuildOptIncludeRegEx.findall(FlagOption)]\r
+            else:\r
                 #\r
-                # EDK II modules must not reference header files outside of the packages they depend on or\r
-                # within the module's directory tree. Report error if violation.\r
+                # RVCT may specify a list of directory seperated by commas\r
                 #\r
-                if self.AutoGenVersion >= 0x00010005:\r
-                    for Path in IncPathList:\r
-                        if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir):\r
-                            ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption)\r
-                            EdkLogger.error("build",\r
-                                            PARAMETER_INVALID,\r
-                                            ExtraData=ErrMsg,\r
-                                            File=str(self.MetaFile))\r
-\r
-\r
-                BuildOptionIncPathList += IncPathList\r
+                IncPathList = []\r
+                for Path in BuildOptIncludeRegEx.findall(FlagOption):\r
+                    PathList = GetSplitList(Path, TAB_COMMA_SPLIT)\r
+                    IncPathList.extend(NormPath(PathEntry, self.Macros) for PathEntry in PathList)\r
 \r
-            self._BuildOptionIncPathList = BuildOptionIncPathList\r
-\r
-        return self._BuildOptionIncPathList\r
+            #\r
+            # EDK II modules must not reference header files outside of the packages they depend on or\r
+            # within the module's directory tree. Report error if violation.\r
+            #\r
+            if self.AutoGenVersion >= 0x00010005:\r
+                for Path in IncPathList:\r
+                    if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir):\r
+                        ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption)\r
+                        EdkLogger.error("build",\r
+                                        PARAMETER_INVALID,\r
+                                        ExtraData=ErrMsg,\r
+                                        File=str(self.MetaFile))\r
+            RetVal += IncPathList\r
+        return RetVal\r
 \r
     ## Return a list of files which can be built from source\r
     #\r
     #  What kind of files can be built is determined by build rules in\r
     #  $(CONF_DIRECTORY)/build_rule.txt and toolchain family.\r
     #\r
-    def _GetSourceFileList(self):\r
-        if self._SourceFileList is None:\r
-            self._SourceFileList = []\r
-            ToolChainTagSet = {"", "*", self.ToolChain}\r
-            ToolChainFamilySet = {"", "*", self.ToolChainFamily, self.BuildRuleFamily}\r
-            for F in self.Module.Sources:\r
-                # match tool chain\r
-                if F.TagName not in ToolChainTagSet:\r
-                    EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "\r
-                                    "but [%s] is currently used" % (F.TagName, str(F), self.ToolChain))\r
-                    continue\r
-                # match tool chain family or build rule family\r
-                if F.ToolChainFamily not in ToolChainFamilySet:\r
-                    EdkLogger.debug(\r
-                                EdkLogger.DEBUG_0,\r
-                                "The file [%s] must be built by tools of [%s], " \\r
-                                "but current toolchain family is [%s], buildrule family is [%s]" \\r
-                                    % (str(F), F.ToolChainFamily, self.ToolChainFamily, self.BuildRuleFamily))\r
-                    continue\r
+    @cached_property\r
+    def SourceFileList(self):\r
+        RetVal = []\r
+        ToolChainTagSet = {"", "*", self.ToolChain}\r
+        ToolChainFamilySet = {"", "*", self.ToolChainFamily, self.BuildRuleFamily}\r
+        for F in self.Module.Sources:\r
+            # match tool chain\r
+            if F.TagName not in ToolChainTagSet:\r
+                EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "\r
+                                "but [%s] is currently used" % (F.TagName, str(F), self.ToolChain))\r
+                continue\r
+            # match tool chain family or build rule family\r
+            if F.ToolChainFamily not in ToolChainFamilySet:\r
+                EdkLogger.debug(\r
+                            EdkLogger.DEBUG_0,\r
+                            "The file [%s] must be built by tools of [%s], " \\r
+                            "but current toolchain family is [%s], buildrule family is [%s]" \\r
+                                % (str(F), F.ToolChainFamily, self.ToolChainFamily, self.BuildRuleFamily))\r
+                continue\r
 \r
-                # add the file path into search path list for file including\r
-                if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:\r
-                    self.IncludePathList.insert(0, F.Dir)\r
-                self._SourceFileList.append(F)\r
+            # add the file path into search path list for file including\r
+            if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:\r
+                self.IncludePathList.insert(0, F.Dir)\r
+            RetVal.append(F)\r
 \r
-            self._MatchBuildRuleOrder(self._SourceFileList)\r
+        self._MatchBuildRuleOrder(RetVal)\r
 \r
-            for F in self._SourceFileList:\r
-                self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)\r
-        return self._SourceFileList\r
+        for F in RetVal:\r
+            self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)\r
+        return RetVal\r
 \r
     def _MatchBuildRuleOrder(self, FileList):\r
         Order_Dict = {}\r
-        self._GetModuleBuildOption()\r
+        self.BuildOption\r
         for SingleFile in FileList:\r
             if self.BuildRuleOrder and SingleFile.Ext in self.BuildRuleOrder and SingleFile.Ext in self.BuildRules:\r
                 key = SingleFile.Path.split(SingleFile.Ext)[0]\r
@@ -3158,31 +3088,19 @@ class ModuleAutoGen(AutoGen):
         return FileList\r
 \r
     ## Return the list of unicode files\r
-    def _GetUnicodeFileList(self):\r
-        if self._UnicodeFileList is None:\r
-            if TAB_UNICODE_FILE in self.FileTypes:\r
-                self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]\r
-            else:\r
-                self._UnicodeFileList = []\r
-        return self._UnicodeFileList\r
+    @cached_property\r
+    def UnicodeFileList(self):\r
+        return self.FileTypes.get(TAB_UNICODE_FILE,[])\r
 \r
     ## Return the list of vfr files\r
-    def _GetVfrFileList(self):\r
-        if self._VfrFileList is None:\r
-            if TAB_VFR_FILE in self.FileTypes:\r
-                self._VfrFileList = self.FileTypes[TAB_VFR_FILE]\r
-            else:\r
-                self._VfrFileList = []\r
-        return self._VfrFileList\r
+    @cached_property\r
+    def VfrFileList(self):\r
+        return self.FileTypes.get(TAB_VFR_FILE, [])\r
 \r
     ## Return the list of Image Definition files\r
-    def _GetIdfFileList(self):\r
-        if self._IdfFileList is None:\r
-            if TAB_IMAGE_FILE in self.FileTypes:\r
-                self._IdfFileList = self.FileTypes[TAB_IMAGE_FILE]\r
-            else:\r
-                self._IdfFileList = []\r
-        return self._IdfFileList\r
+    @cached_property\r
+    def IdfFileList(self):\r
+        return self.FileTypes.get(TAB_IMAGE_FILE,[])\r
 \r
     ## Return a list of files which can be built from binary\r
     #\r
@@ -3190,50 +3108,52 @@ class ModuleAutoGen(AutoGen):
     #\r
     #   @retval     list            The list of files which can be built later\r
     #\r
-    def _GetBinaryFiles(self):\r
-        if self._BinaryFileList is None:\r
-            self._BinaryFileList = []\r
-            for F in self.Module.Binaries:\r
-                if F.Target not in [TAB_ARCH_COMMON, '*'] and F.Target != self.BuildTarget:\r
-                    continue\r
-                self._BinaryFileList.append(F)\r
-                self._ApplyBuildRule(F, F.Type)\r
-        return self._BinaryFileList\r
-\r
-    def _GetBuildRules(self):\r
-        if self._BuildRules is None:\r
-            BuildRules = {}\r
-            BuildRuleDatabase = self.PlatformInfo.BuildRule\r
-            for Type in BuildRuleDatabase.FileTypeList:\r
-                #first try getting build rule by BuildRuleFamily\r
-                RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]\r
+    @cached_property\r
+    def BinaryFileList(self):\r
+        RetVal = []\r
+        for F in self.Module.Binaries:\r
+            if F.Target not in [TAB_ARCH_COMMON, '*'] and F.Target != self.BuildTarget:\r
+                continue\r
+            RetVal.append(F)\r
+            self._ApplyBuildRule(F, F.Type, BinaryFileList=RetVal)\r
+        return RetVal\r
+\r
+    @cached_property\r
+    def BuildRules(self):\r
+        RetVal = {}\r
+        BuildRuleDatabase = self.PlatformInfo.BuildRule\r
+        for Type in BuildRuleDatabase.FileTypeList:\r
+            #first try getting build rule by BuildRuleFamily\r
+            RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]\r
+            if not RuleObject:\r
+                # build type is always module type, but ...\r
+                if self.ModuleType != self.BuildType:\r
+                    RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]\r
+            #second try getting build rule by ToolChainFamily\r
+            if not RuleObject:\r
+                RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]\r
                 if not RuleObject:\r
                     # build type is always module type, but ...\r
                     if self.ModuleType != self.BuildType:\r
-                        RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]\r
-                #second try getting build rule by ToolChainFamily\r
-                if not RuleObject:\r
-                    RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]\r
-                    if not RuleObject:\r
-                        # build type is always module type, but ...\r
-                        if self.ModuleType != self.BuildType:\r
-                            RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]\r
-                if not RuleObject:\r
-                    continue\r
-                RuleObject = RuleObject.Instantiate(self.Macros)\r
-                BuildRules[Type] = RuleObject\r
-                for Ext in RuleObject.SourceFileExtList:\r
-                    BuildRules[Ext] = RuleObject\r
-            self._BuildRules = BuildRules\r
-        return self._BuildRules\r
-\r
-    def _ApplyBuildRule(self, File, FileType):\r
+                        RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]\r
+            if not RuleObject:\r
+                continue\r
+            RuleObject = RuleObject.Instantiate(self.Macros)\r
+            RetVal[Type] = RuleObject\r
+            for Ext in RuleObject.SourceFileExtList:\r
+                RetVal[Ext] = RuleObject\r
+        return RetVal\r
+\r
+    def _ApplyBuildRule(self, File, FileType, BinaryFileList=None):\r
         if self._BuildTargets is None:\r
             self._IntroBuildTargetList = set()\r
             self._FinalBuildTargetList = set()\r
             self._BuildTargets = defaultdict(set)\r
             self._FileTypes = defaultdict(set)\r
 \r
+        if not BinaryFileList:\r
+            BinaryFileList = self.BinaryFileList\r
+\r
         SubDirectory = os.path.join(self.OutputDir, File.SubDir)\r
         if not os.path.exists(SubDirectory):\r
             CreateDirectory(SubDirectory)\r
@@ -3244,7 +3164,7 @@ class ModuleAutoGen(AutoGen):
         #\r
         # Make sure to get build rule order value\r
         #\r
-        self._GetModuleBuildOption()\r
+        self.BuildOption\r
 \r
         while Index < len(SourceList):\r
             Source = SourceList[Index]\r
@@ -3253,7 +3173,7 @@ class ModuleAutoGen(AutoGen):
             if Source != File:\r
                 CreateDirectory(Source.Dir)\r
 \r
-            if File.IsBinary and File == Source and self._BinaryFileList is not None and File in self._BinaryFileList:\r
+            if File.IsBinary and File == Source and File in BinaryFileList:\r
                 # Skip all files that are not binary libraries\r
                 if not self.IsLibrary:\r
                     continue\r
@@ -3300,230 +3220,222 @@ class ModuleAutoGen(AutoGen):
             LastTarget = Target\r
             FileType = TAB_UNKNOWN_FILE\r
 \r
-    def _GetTargets(self):\r
+    @cached_property\r
+    def Targets(self):\r
         if self._BuildTargets is None:\r
             self._IntroBuildTargetList = set()\r
             self._FinalBuildTargetList = set()\r
             self._BuildTargets = defaultdict(set)\r
             self._FileTypes = defaultdict(set)\r
 \r
-        #TRICK: call _GetSourceFileList to apply build rule for source files\r
-        if self.SourceFileList:\r
-            pass\r
+        #TRICK: call SourceFileList property to apply build rule for source files\r
+        self.SourceFileList\r
 \r
         #TRICK: call _GetBinaryFileList to apply build rule for binary files\r
-        if self.BinaryFileList:\r
-            pass\r
+        self.BinaryFileList\r
 \r
         return self._BuildTargets\r
 \r
-    def _GetIntroTargetList(self):\r
-        self._GetTargets()\r
+    @cached_property\r
+    def IntroTargetList(self):\r
+        self.Targets\r
         return self._IntroBuildTargetList\r
 \r
-    def _GetFinalTargetList(self):\r
-        self._GetTargets()\r
+    @cached_property\r
+    def CodaTargetList(self):\r
+        self.Targets\r
         return self._FinalBuildTargetList\r
 \r
-    def _GetFileTypes(self):\r
-        self._GetTargets()\r
+    @cached_property\r
+    def FileTypes(self):\r
+        self.Targets\r
         return self._FileTypes\r
 \r
     ## Get the list of package object the module depends on\r
     #\r
     #   @retval     list    The package object list\r
     #\r
-    def _GetDependentPackageList(self):\r
+    @cached_property\r
+    def DependentPackageList(self):\r
         return self.Module.Packages\r
 \r
     ## Return the list of auto-generated code file\r
     #\r
     #   @retval     list        The list of auto-generated file\r
     #\r
-    def _GetAutoGenFileList(self):\r
-        UniStringAutoGenC = True\r
-        IdfStringAutoGenC = True\r
+    @cached_property\r
+    def AutoGenFileList(self):\r
+        AutoGenUniIdf = self.BuildType != 'UEFI_HII'\r
         UniStringBinBuffer = BytesIO()\r
         IdfGenBinBuffer = BytesIO()\r
-        if self.BuildType == 'UEFI_HII':\r
-            UniStringAutoGenC = False\r
-            IdfStringAutoGenC = False\r
-        if self._AutoGenFileList is None:\r
-            self._AutoGenFileList = {}\r
-            AutoGenC = TemplateString()\r
-            AutoGenH = TemplateString()\r
-            StringH = TemplateString()\r
-            StringIdf = TemplateString()\r
-            GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, UniStringAutoGenC, UniStringBinBuffer, StringIdf, IdfStringAutoGenC, IdfGenBinBuffer)\r
-            #\r
-            # AutoGen.c is generated if there are library classes in inf, or there are object files\r
-            #\r
-            if str(AutoGenC) != "" and (len(self.Module.LibraryClasses) > 0\r
-                                        or TAB_OBJECT_FILE in self.FileTypes):\r
-                AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)\r
-                self._AutoGenFileList[AutoFile] = str(AutoGenC)\r
-                self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
-            if str(AutoGenH) != "":\r
-                AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)\r
-                self._AutoGenFileList[AutoFile] = str(AutoGenH)\r
-                self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
-            if str(StringH) != "":\r
-                AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)\r
-                self._AutoGenFileList[AutoFile] = str(StringH)\r
-                self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
-            if UniStringBinBuffer is not None and UniStringBinBuffer.getvalue() != "":\r
-                AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)\r
-                self._AutoGenFileList[AutoFile] = UniStringBinBuffer.getvalue()\r
-                AutoFile.IsBinary = True\r
-                self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
-            if UniStringBinBuffer is not None:\r
-                UniStringBinBuffer.close()\r
-            if str(StringIdf) != "":\r
-                AutoFile = PathClass(gAutoGenImageDefFileName % {"module_name":self.Name}, self.DebugDir)\r
-                self._AutoGenFileList[AutoFile] = str(StringIdf)\r
-                self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
-            if IdfGenBinBuffer is not None and IdfGenBinBuffer.getvalue() != "":\r
-                AutoFile = PathClass(gAutoGenIdfFileName % {"module_name":self.Name}, self.OutputDir)\r
-                self._AutoGenFileList[AutoFile] = IdfGenBinBuffer.getvalue()\r
-                AutoFile.IsBinary = True\r
-                self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
-            if IdfGenBinBuffer is not None:\r
-                IdfGenBinBuffer.close()\r
-        return self._AutoGenFileList\r
+        RetVal = {}\r
+        AutoGenC = TemplateString()\r
+        AutoGenH = TemplateString()\r
+        StringH = TemplateString()\r
+        StringIdf = TemplateString()\r
+        GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, AutoGenUniIdf, UniStringBinBuffer, StringIdf, AutoGenUniIdf, IdfGenBinBuffer)\r
+        #\r
+        # AutoGen.c is generated if there are library classes in inf, or there are object files\r
+        #\r
+        if str(AutoGenC) != "" and (len(self.Module.LibraryClasses) > 0\r
+                                    or TAB_OBJECT_FILE in self.FileTypes):\r
+            AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)\r
+            RetVal[AutoFile] = str(AutoGenC)\r
+            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
+        if str(AutoGenH) != "":\r
+            AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)\r
+            RetVal[AutoFile] = str(AutoGenH)\r
+            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
+        if str(StringH) != "":\r
+            AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)\r
+            RetVal[AutoFile] = str(StringH)\r
+            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
+        if UniStringBinBuffer is not None and UniStringBinBuffer.getvalue() != "":\r
+            AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)\r
+            RetVal[AutoFile] = UniStringBinBuffer.getvalue()\r
+            AutoFile.IsBinary = True\r
+            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
+        if UniStringBinBuffer is not None:\r
+            UniStringBinBuffer.close()\r
+        if str(StringIdf) != "":\r
+            AutoFile = PathClass(gAutoGenImageDefFileName % {"module_name":self.Name}, self.DebugDir)\r
+            RetVal[AutoFile] = str(StringIdf)\r
+            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
+        if IdfGenBinBuffer is not None and IdfGenBinBuffer.getvalue() != "":\r
+            AutoFile = PathClass(gAutoGenIdfFileName % {"module_name":self.Name}, self.OutputDir)\r
+            RetVal[AutoFile] = IdfGenBinBuffer.getvalue()\r
+            AutoFile.IsBinary = True\r
+            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
+        if IdfGenBinBuffer is not None:\r
+            IdfGenBinBuffer.close()\r
+        return RetVal\r
 \r
     ## Return the list of library modules explicitly or implicityly used by this module\r
-    def _GetLibraryList(self):\r
-        if self._DependentLibraryList is None:\r
-            # only merge library classes and PCD for non-library module\r
-            if self.IsLibrary:\r
-                self._DependentLibraryList = []\r
-            else:\r
-                if self.AutoGenVersion < 0x00010005:\r
-                    self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)\r
-                else:\r
-                    self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)\r
-        return self._DependentLibraryList\r
+    @cached_property\r
+    def DependentLibraryList(self):\r
+        # only merge library classes and PCD for non-library module\r
+        if self.IsLibrary:\r
+            return []\r
+        if self.AutoGenVersion < 0x00010005:\r
+            return self.PlatformInfo.ResolveLibraryReference(self.Module)\r
+        return self.PlatformInfo.ApplyLibraryInstance(self.Module)\r
 \r
     ## Get the list of PCDs from current module\r
     #\r
     #   @retval     list                    The list of PCD\r
     #\r
-    def _GetModulePcdList(self):\r
-        if self._ModulePcdList is None:\r
-            # apply PCD settings from platform\r
-            self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)\r
-            ExtendCopyDictionaryLists(self._PcdComments, self.Module.PcdComments)\r
-        return self._ModulePcdList\r
+    @cached_property\r
+    def ModulePcdList(self):\r
+        # apply PCD settings from platform\r
+        RetVal = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)\r
+        ExtendCopyDictionaryLists(self._PcdComments, self.Module.PcdComments)\r
+        return RetVal\r
 \r
     ## Get the list of PCDs from dependent libraries\r
     #\r
     #   @retval     list                    The list of PCD\r
     #\r
-    def _GetLibraryPcdList(self):\r
-        if self._LibraryPcdList is None:\r
-            Pcds = OrderedDict()\r
-            if not self.IsLibrary:\r
-                # get PCDs from dependent libraries\r
-                self._LibraryPcdList = []\r
-                for Library in self.DependentLibraryList:\r
-                    PcdsInLibrary = OrderedDict()\r
-                    ExtendCopyDictionaryLists(self._PcdComments, Library.PcdComments)\r
-                    for Key in Library.Pcds:\r
-                        # skip duplicated PCDs\r
-                        if Key in self.Module.Pcds or Key in Pcds:\r
-                            continue\r
-                        Pcds[Key] = copy.copy(Library.Pcds[Key])\r
-                        PcdsInLibrary[Key] = Pcds[Key]\r
-                    self._LibraryPcdList.extend(self.PlatformInfo.ApplyPcdSetting(self.Module, PcdsInLibrary, Library=Library))\r
-            else:\r
-                self._LibraryPcdList = []\r
-        return self._LibraryPcdList\r
+    @cached_property\r
+    def LibraryPcdList(self):\r
+        if self.IsLibrary:\r
+            return []\r
+        RetVal = []\r
+        Pcds = set()\r
+        # get PCDs from dependent libraries\r
+        for Library in self.DependentLibraryList:\r
+            PcdsInLibrary = OrderedDict()\r
+            ExtendCopyDictionaryLists(self._PcdComments, Library.PcdComments)\r
+            for Key in Library.Pcds:\r
+                # skip duplicated PCDs\r
+                if Key in self.Module.Pcds or Key in Pcds:\r
+                    continue\r
+                Pcds.add(Key)\r
+                PcdsInLibrary[Key] = copy.copy(Library.Pcds[Key])\r
+            RetVal.extend(self.PlatformInfo.ApplyPcdSetting(self.Module, PcdsInLibrary, Library=Library))\r
+        return RetVal\r
 \r
     ## Get the GUID value mapping\r
     #\r
     #   @retval     dict    The mapping between GUID cname and its value\r
     #\r
-    def _GetGuidList(self):\r
-        if self._GuidList is None:\r
-            self._GuidList = OrderedDict()\r
-            self._GuidList.update(self.Module.Guids)\r
-            for Library in self.DependentLibraryList:\r
-                self._GuidList.update(Library.Guids)\r
-                ExtendCopyDictionaryLists(self._GuidComments, Library.GuidComments)\r
-            ExtendCopyDictionaryLists(self._GuidComments, self.Module.GuidComments)\r
-        return self._GuidList\r
-\r
+    @cached_property\r
+    def GuidList(self):\r
+        RetVal = OrderedDict(self.Module.Guids)\r
+        for Library in self.DependentLibraryList:\r
+            RetVal.update(Library.Guids)\r
+            ExtendCopyDictionaryLists(self._GuidComments, Library.GuidComments)\r
+        ExtendCopyDictionaryLists(self._GuidComments, self.Module.GuidComments)\r
+        return RetVal\r
+\r
+    @cached_property\r
     def GetGuidsUsedByPcd(self):\r
-        if self._GuidsUsedByPcd is None:\r
-            self._GuidsUsedByPcd = OrderedDict()\r
-            self._GuidsUsedByPcd.update(self.Module.GetGuidsUsedByPcd())\r
-            for Library in self.DependentLibraryList:\r
-                self._GuidsUsedByPcd.update(Library.GetGuidsUsedByPcd())\r
-        return self._GuidsUsedByPcd\r
+        RetVal = OrderedDict(self.Module.GetGuidsUsedByPcd())\r
+        for Library in self.DependentLibraryList:\r
+            RetVal.update(Library.GetGuidsUsedByPcd())\r
+        return RetVal\r
     ## Get the protocol value mapping\r
     #\r
     #   @retval     dict    The mapping between protocol cname and its value\r
     #\r
-    def _GetProtocolList(self):\r
-        if self._ProtocolList is None:\r
-            self._ProtocolList = OrderedDict()\r
-            self._ProtocolList.update(self.Module.Protocols)\r
-            for Library in self.DependentLibraryList:\r
-                self._ProtocolList.update(Library.Protocols)\r
-                ExtendCopyDictionaryLists(self._ProtocolComments, Library.ProtocolComments)\r
-            ExtendCopyDictionaryLists(self._ProtocolComments, self.Module.ProtocolComments)\r
-        return self._ProtocolList\r
+    @cached_property\r
+    def ProtocolList(self):\r
+        RetVal = OrderedDict(self.Module.Protocols)\r
+        for Library in self.DependentLibraryList:\r
+            RetVal.update(Library.Protocols)\r
+            ExtendCopyDictionaryLists(self._ProtocolComments, Library.ProtocolComments)\r
+        ExtendCopyDictionaryLists(self._ProtocolComments, self.Module.ProtocolComments)\r
+        return RetVal\r
 \r
     ## Get the PPI value mapping\r
     #\r
     #   @retval     dict    The mapping between PPI cname and its value\r
     #\r
-    def _GetPpiList(self):\r
-        if self._PpiList is None:\r
-            self._PpiList = OrderedDict()\r
-            self._PpiList.update(self.Module.Ppis)\r
-            for Library in self.DependentLibraryList:\r
-                self._PpiList.update(Library.Ppis)\r
-                ExtendCopyDictionaryLists(self._PpiComments, Library.PpiComments)\r
-            ExtendCopyDictionaryLists(self._PpiComments, self.Module.PpiComments)\r
-        return self._PpiList\r
+    @cached_property\r
+    def PpiList(self):\r
+        RetVal = OrderedDict(self.Module.Ppis)\r
+        for Library in self.DependentLibraryList:\r
+            RetVal.update(Library.Ppis)\r
+            ExtendCopyDictionaryLists(self._PpiComments, Library.PpiComments)\r
+        ExtendCopyDictionaryLists(self._PpiComments, self.Module.PpiComments)\r
+        return RetVal\r
 \r
     ## Get the list of include search path\r
     #\r
     #   @retval     list                    The list path\r
     #\r
-    def _GetIncludePathList(self):\r
-        if self._IncludePathList is None:\r
-            self._IncludePathList = []\r
-            if self.AutoGenVersion < 0x00010005:\r
-                for Inc in self.Module.Includes:\r
-                    if Inc not in self._IncludePathList:\r
-                        self._IncludePathList.append(Inc)\r
-                    # for Edk modules\r
-                    Inc = path.join(Inc, self.Arch.capitalize())\r
-                    if os.path.exists(Inc) and Inc not in self._IncludePathList:\r
-                        self._IncludePathList.append(Inc)\r
-                # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time\r
-                self._IncludePathList.append(self.DebugDir)\r
-            else:\r
-                self._IncludePathList.append(self.MetaFile.Dir)\r
-                self._IncludePathList.append(self.DebugDir)\r
-\r
-            for Package in self.Module.Packages:\r
-                PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir)\r
-                if PackageDir not in self._IncludePathList:\r
-                    self._IncludePathList.append(PackageDir)\r
-                IncludesList = Package.Includes\r
-                if Package._PrivateIncludes:\r
-                    if not self.MetaFile.Path.startswith(PackageDir):\r
-                        IncludesList = list(set(Package.Includes).difference(set(Package._PrivateIncludes)))\r
-                for Inc in IncludesList:\r
-                    if Inc not in self._IncludePathList:\r
-                        self._IncludePathList.append(str(Inc))\r
-        return self._IncludePathList\r
-\r
-    def _GetIncludePathLength(self):\r
-        return sum(len(inc)+1 for inc in self._IncludePathList)\r
+    @cached_property\r
+    def IncludePathList(self):\r
+        RetVal = []\r
+        if self.AutoGenVersion < 0x00010005:\r
+            for Inc in self.Module.Includes:\r
+                if Inc not in RetVal:\r
+                    RetVal.append(Inc)\r
+                # for Edk modules\r
+                Inc = path.join(Inc, self.Arch.capitalize())\r
+                if os.path.exists(Inc) and Inc not in RetVal:\r
+                    RetVal.append(Inc)\r
+            # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time\r
+            RetVal.append(self.DebugDir)\r
+        else:\r
+            RetVal.append(self.MetaFile.Dir)\r
+            RetVal.append(self.DebugDir)\r
+\r
+        for Package in self.Module.Packages:\r
+            PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir)\r
+            if PackageDir not in RetVal:\r
+                RetVal.append(PackageDir)\r
+            IncludesList = Package.Includes\r
+            if Package._PrivateIncludes:\r
+                if not self.MetaFile.Path.startswith(PackageDir):\r
+                    IncludesList = list(set(Package.Includes).difference(set(Package._PrivateIncludes)))\r
+            for Inc in IncludesList:\r
+                if Inc not in RetVal:\r
+                    RetVal.append(str(Inc))\r
+        return RetVal\r
+\r
+    @cached_property\r
+    def IncludePathLength(self):\r
+        return sum(len(inc)+1 for inc in self.IncludePathList)\r
 \r
     ## Get HII EX PCDs which maybe used by VFR\r
     #\r
@@ -3704,9 +3616,8 @@ class ModuleAutoGen(AutoGen):
                     PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, TAB_PCDS_DYNAMIC_EX))\r
                     PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, TAB_PCDS_DYNAMIC))\r
                     PcdTokenSpaceList.append(Pcd.TokenSpaceGuidCName)\r
-        GuidList = OrderedDict()\r
-        GuidList.update(self.GuidList)\r
-        for TokenSpace in self.GetGuidsUsedByPcd():\r
+        GuidList = OrderedDict(self.GuidList)\r
+        for TokenSpace in self.GetGuidsUsedByPcd:\r
             # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list\r
             # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs\r
             if TokenSpace not in PcdTokenSpaceList and TokenSpace in GuidList:\r
@@ -4071,7 +3982,7 @@ class ModuleAutoGen(AutoGen):
             EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %\r
                             (self.Name, self.Arch))\r
 \r
-        self.CreateTimeStamp(Makefile)\r
+        self.CreateTimeStamp()\r
         self.IsMakeFileCreated = True\r
 \r
     def CopyBinaryFiles(self):\r
@@ -4151,11 +4062,11 @@ class ModuleAutoGen(AutoGen):
         return AutoGenList\r
 \r
     ## Summarize the ModuleAutoGen objects of all libraries used by this module\r
-    def _GetLibraryAutoGenList(self):\r
-        if self._LibraryAutoGenList is None:\r
-            self._LibraryAutoGenList = []\r
-            for Library in self.DependentLibraryList:\r
-                La = ModuleAutoGen(\r
+    @cached_property\r
+    def LibraryAutoGenList(self):\r
+        RetVal = []\r
+        for Library in self.DependentLibraryList:\r
+            La = ModuleAutoGen(\r
                         self.Workspace,\r
                         Library.MetaFile,\r
                         self.BuildTarget,\r
@@ -4163,11 +4074,11 @@ class ModuleAutoGen(AutoGen):
                         self.Arch,\r
                         self.PlatformInfo.MetaFile\r
                         )\r
-                if La not in self._LibraryAutoGenList:\r
-                    self._LibraryAutoGenList.append(La)\r
-                    for Lib in La.CodaTargetList:\r
-                        self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)\r
-        return self._LibraryAutoGenList\r
+            if La not in RetVal:\r
+                RetVal.append(La)\r
+                for Lib in La.CodaTargetList:\r
+                    self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)\r
+        return RetVal\r
 \r
     def GenModuleHash(self):\r
         if self.Arch not in GlobalData.gModuleHash:\r
@@ -4221,16 +4132,16 @@ class ModuleAutoGen(AutoGen):
     def CanSkip(self):\r
         if self.MakeFileDir in GlobalData.gSikpAutoGenCache:\r
             return True\r
-        if not os.path.exists(self.GetTimeStampPath()):\r
+        if not os.path.exists(self.TimeStampPath):\r
             return False\r
         #last creation time of the module\r
-        DstTimeStamp = os.stat(self.GetTimeStampPath())[8]\r
+        DstTimeStamp = os.stat(self.TimeStampPath)[8]\r
 \r
         SrcTimeStamp = self.Workspace._SrcTimeStamp\r
         if SrcTimeStamp > DstTimeStamp:\r
             return False\r
 \r
-        with open(self.GetTimeStampPath(), 'r') as f:\r
+        with open(self.TimeStampPath,'r') as f:\r
             for source in f:\r
                 source = source.rstrip('\n')\r
                 if not os.path.exists(source):\r
@@ -4242,12 +4153,11 @@ class ModuleAutoGen(AutoGen):
         GlobalData.gSikpAutoGenCache.add(self.MakeFileDir)\r
         return True\r
 \r
-    def GetTimeStampPath(self):\r
-        if self._TimeStampPath is None:\r
-            self._TimeStampPath = os.path.join(self.MakeFileDir, 'AutoGenTimeStamp')\r
-        return self._TimeStampPath\r
-    def CreateTimeStamp(self, Makefile):\r
+    @cached_property\r
+    def TimeStampPath(self):\r
+        return os.path.join(self.MakeFileDir, 'AutoGenTimeStamp')\r
 \r
+    def CreateTimeStamp(self):\r
         FileSet = {self.MetaFile.Path}\r
 \r
         for SourceFile in self.Module.Sources:\r
@@ -4259,69 +4169,8 @@ class ModuleAutoGen(AutoGen):
         for f in self.AutoGenDepSet:\r
             FileSet.add (f.Path)\r
 \r
-        if os.path.exists (self.GetTimeStampPath()):\r
-            os.remove (self.GetTimeStampPath())\r
-        with open(self.GetTimeStampPath(), 'w+') as file:\r
+        if os.path.exists (self.TimeStampPath):\r
+            os.remove (self.TimeStampPath)\r
+        with open(self.TimeStampPath, 'w+') as file:\r
             for f in FileSet:\r
                 print(f, file=file)\r
-\r
-    Module          = property(_GetModule)\r
-    Name            = property(_GetBaseName)\r
-    Guid            = property(_GetGuid)\r
-    Version         = property(_GetVersion)\r
-    ModuleType      = property(_GetModuleType)\r
-    ComponentType   = property(_GetComponentType)\r
-    BuildType       = property(_GetBuildType)\r
-    PcdIsDriver     = property(_GetPcdIsDriver)\r
-    AutoGenVersion  = property(_GetAutoGenVersion)\r
-    Macros          = property(_GetMacros)\r
-    Specification   = property(_GetSpecification)\r
-\r
-    IsLibrary       = property(_IsLibrary)\r
-    IsBinaryModule  = property(_IsBinaryModule)\r
-    BuildDir        = property(_GetBuildDir)\r
-    OutputDir       = property(_GetOutputDir)\r
-    FfsOutputDir    = property(_GetFfsOutputDir)\r
-    DebugDir        = property(_GetDebugDir)\r
-    MakeFileDir     = property(_GetMakeFileDir)\r
-    CustomMakefile  = property(_GetCustomMakefile)\r
-\r
-    IncludePathList = property(_GetIncludePathList)\r
-    IncludePathLength = property(_GetIncludePathLength)\r
-    AutoGenFileList = property(_GetAutoGenFileList)\r
-    UnicodeFileList = property(_GetUnicodeFileList)\r
-    VfrFileList     = property(_GetVfrFileList)\r
-    SourceFileList  = property(_GetSourceFileList)\r
-    BinaryFileList  = property(_GetBinaryFiles) # FileType : [File List]\r
-    Targets         = property(_GetTargets)\r
-    IntroTargetList = property(_GetIntroTargetList)\r
-    CodaTargetList  = property(_GetFinalTargetList)\r
-    FileTypes       = property(_GetFileTypes)\r
-    BuildRules      = property(_GetBuildRules)\r
-    IdfFileList     = property(_GetIdfFileList)\r
-\r
-    DependentPackageList    = property(_GetDependentPackageList)\r
-    DependentLibraryList    = property(_GetLibraryList)\r
-    LibraryAutoGenList      = property(_GetLibraryAutoGenList)\r
-    DerivedPackageList      = property(_GetDerivedPackageList)\r
-\r
-    ModulePcdList           = property(_GetModulePcdList)\r
-    LibraryPcdList          = property(_GetLibraryPcdList)\r
-    GuidList                = property(_GetGuidList)\r
-    ProtocolList            = property(_GetProtocolList)\r
-    PpiList                 = property(_GetPpiList)\r
-    DepexList               = property(_GetDepexTokenList)\r
-    DxsFile                 = property(_GetDxsFile)\r
-    DepexExpressionDict     = property(_GetDepexExpressionTokenList)\r
-    BuildOption             = property(_GetModuleBuildOption)\r
-    BuildOptionIncPathList  = property(_GetBuildOptionIncPathList)\r
-    BuildCommand            = property(_GetBuildCommand)\r
-\r
-    FixedAtBuildPcds         = property(_GetFixedAtBuildPcds)\r
-    UniqueBaseName          = property(_GetUniqueBaseName)\r
-    FixedVoidTypePcds       = property(_GetFixedAtBuildVoidTypePcds)\r
-\r
-# This acts like the main() function for the script, unless it is 'import'ed into another script.\r
-if __name__ == '__main__':\r
-    pass\r
-\r
index 8946e419a009b3a4119243e6d741f56820dd0741..f455f831e0dd1fa528e56670e7971ff3b45b7260 100644 (file)
@@ -1329,7 +1329,7 @@ def CreateLibraryPcdCode(Info, AutoGenC, AutoGenH, Pcd):
         AutoGenH.Append('//#define %s  ASSERT(FALSE)  // It is not allowed to set value for a FIXED_AT_BUILD PCD\n' % SetModeName)\r
 \r
         ConstFixedPcd = False\r
-        if PcdItemType == TAB_PCDS_FIXED_AT_BUILD and (key in Info.ConstPcd or (Info.IsLibrary and not Info._ReferenceModules)):\r
+        if PcdItemType == TAB_PCDS_FIXED_AT_BUILD and (key in Info.ConstPcd or (Info.IsLibrary and not Info.ReferenceModules)):\r
             ConstFixedPcd = True\r
             if key in Info.ConstPcd:\r
                 Pcd.DefaultValue = Info.ConstPcd[key]\r
index 3dc5ac2cf383ad0f0914f569511d5d3663d77777..55081acbd82233a0f561e08728df1472af64f3b9 100644 (file)
@@ -798,14 +798,14 @@ cleanlib:
                                     Tool = Flag\r
                                     break\r
                         if Tool:\r
-                            if 'PATH' not in self._AutoGenObject._BuildOption[Tool]:\r
+                            if 'PATH' not in self._AutoGenObject.BuildOption[Tool]:\r
                                 EdkLogger.error("build", AUTOGEN_ERROR, "%s_PATH doesn't exist in %s ToolChain and %s Arch." %(Tool, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch), ExtraData="[%s]" % str(self._AutoGenObject))\r
-                            SingleCommandLength += len(self._AutoGenObject._BuildOption[Tool]['PATH'])\r
+                            SingleCommandLength += len(self._AutoGenObject.BuildOption[Tool]['PATH'])\r
                             for item in SingleCommandList[1:]:\r
                                 if FlagDict[Tool]['Macro'] in item:\r
-                                    if 'FLAGS' not in self._AutoGenObject._BuildOption[Tool]:\r
+                                    if 'FLAGS' not in self._AutoGenObject.BuildOption[Tool]:\r
                                         EdkLogger.error("build", AUTOGEN_ERROR, "%s_FLAGS doesn't exist in %s ToolChain and %s Arch." %(Tool, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch), ExtraData="[%s]" % str(self._AutoGenObject))\r
-                                    Str = self._AutoGenObject._BuildOption[Tool]['FLAGS']\r
+                                    Str = self._AutoGenObject.BuildOption[Tool]['FLAGS']\r
                                     for Option in self._AutoGenObject.BuildOption:\r
                                         for Attr in self._AutoGenObject.BuildOption[Option]:\r
                                             if Str.find(Option + '_' + Attr) != -1:\r
@@ -820,7 +820,7 @@ cleanlib:
                                             break\r
                                     SingleCommandLength += len(Str)\r
                                 elif '$(INC)' in item:\r
-                                    SingleCommandLength += self._AutoGenObject.IncludePathLength + len(IncPrefix) * len(self._AutoGenObject._IncludePathList)\r
+                                    SingleCommandLength += self._AutoGenObject.IncludePathLength + len(IncPrefix) * len(self._AutoGenObject.IncludePathList)\r
                                 elif item.find('$(') != -1:\r
                                     Str = item\r
                                     for Option in self._AutoGenObject.BuildOption:\r
@@ -846,7 +846,7 @@ cleanlib:
                         Key = Flag + '_RESP'\r
                         RespMacro = FlagDict[Flag]['Macro'].replace('FLAGS', 'RESP')\r
                         Value = self._AutoGenObject.BuildOption[Flag]['FLAGS']\r
-                        for inc in self._AutoGenObject._IncludePathList:\r
+                        for inc in self._AutoGenObject.IncludePathList:\r
                             Value += ' ' + IncPrefix + inc\r
                         for Option in self._AutoGenObject.BuildOption:\r
                             for Attr in self._AutoGenObject.BuildOption[Option]:\r
diff --git a/BaseTools/Source/Python/Common/caching.py b/BaseTools/Source/Python/Common/caching.py
new file mode 100644 (file)
index 0000000..7cb4586
--- /dev/null
@@ -0,0 +1,47 @@
+## @file\r
+# help with caching in BaseTools\r
+#\r
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+## Import Modules\r
+#\r
+\r
+# for class function\r
+class cached_class_function(object):\r
+    def __init__(self, function):\r
+        self._function = function\r
+    def __get__(self, obj, cls):\r
+        def CallMeHere(*args,**kwargs):\r
+            Value = self._function(obj, *args,**kwargs)\r
+            obj.__dict__[self._function.__name__] = lambda *args,**kwargs:Value\r
+            return Value\r
+        return CallMeHere\r
+\r
+# for class property\r
+class cached_property(object):\r
+    def __init__(self, function):\r
+        self._function = function\r
+    def __get__(self, obj, cls):\r
+        Value = obj.__dict__[self._function.__name__] = self._function(obj)\r
+        return Value\r
+\r
+# for non-class function\r
+class cached_basic_function(object):\r
+    def __init__(self, function):\r
+        self._function = function\r
+    # wrapper to call _do since <class>.__dict__ doesn't support changing __call__\r
+    def __call__(self,*args,**kwargs):\r
+        return self._do(*args,**kwargs)\r
+    def _do(self,*args,**kwargs):\r
+        Value = self._function(*args,**kwargs)\r
+        self.__dict__['_do'] = lambda self,*args,**kwargs:Value\r
+        return Value\r