]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/AutoGen/AutoGen.py
BaseTools:Change the path of the file that Binary Cache
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / AutoGen.py
index 6d76afd81ac121da87a07b1289f5cf7887a2318a..a5bef4f7c62a0ec3ab7346460bce44c61cc93349 100644 (file)
@@ -1,35 +1,31 @@
 ## @file\r
 # Generate AutoGen.h, AutoGen.c and *.depex files\r
 #\r
 ## @file\r
 # Generate AutoGen.h, AutoGen.c and *.depex files\r
 #\r
-# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>\r
 # Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>\r
 # Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>\r
+# Copyright (c) 2019, American Megatrends, Inc. All rights reserved.<BR>\r
 #\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
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
 #\r
 \r
 ## Import Modules\r
 #\r
 from __future__ import print_function\r
 #\r
 \r
 ## Import Modules\r
 #\r
 from __future__ import print_function\r
+from __future__ import absolute_import\r
 import Common.LongFilePathOs as os\r
 import re\r
 import os.path as path\r
 import copy\r
 import uuid\r
 \r
 import Common.LongFilePathOs as os\r
 import re\r
 import os.path as path\r
 import copy\r
 import uuid\r
 \r
-import GenC\r
-import GenMake\r
-import GenDepex\r
+from . import GenC\r
+from . import GenMake\r
+from . import GenDepex\r
 from io import BytesIO\r
 \r
 from io import BytesIO\r
 \r
-from StrGather import *\r
-from BuildEngine import BuildRule\r
-\r
+from .StrGather import *\r
+from .BuildEngine import BuildRule\r
+import shutil\r
 from Common.LongFilePathSupport import CopyLongFilePath\r
 from Common.BuildToolError import *\r
 from Common.DataType import *\r
 from Common.LongFilePathSupport import CopyLongFilePath\r
 from Common.BuildToolError import *\r
 from Common.DataType import *\r
@@ -38,20 +34,22 @@ from Common.StringUtils import *
 import Common.GlobalData as GlobalData\r
 from GenFds.FdfParser import *\r
 from CommonDataClass.CommonClass import SkuInfoClass\r
 import Common.GlobalData as GlobalData\r
 from GenFds.FdfParser import *\r
 from CommonDataClass.CommonClass import SkuInfoClass\r
-from Workspace.BuildClassObject import *\r
 from GenPatchPcdTable.GenPatchPcdTable import parsePcdInfoFromMapFile\r
 import Common.VpdInfoFile as VpdInfoFile\r
 from GenPatchPcdTable.GenPatchPcdTable import parsePcdInfoFromMapFile\r
 import Common.VpdInfoFile as VpdInfoFile\r
-from GenPcdDb import CreatePcdDatabaseCode\r
+from .GenPcdDb import CreatePcdDatabaseCode\r
 from Workspace.MetaFileCommentParser import UsageList\r
 from Workspace.WorkspaceCommon import GetModuleLibInstances\r
 from Common.MultipleWorkspace import MultipleWorkspace as mws\r
 from Workspace.MetaFileCommentParser import UsageList\r
 from Workspace.WorkspaceCommon import GetModuleLibInstances\r
 from Common.MultipleWorkspace import MultipleWorkspace as mws\r
-import InfSectionParser\r
+from . import InfSectionParser\r
 import datetime\r
 import hashlib\r
 import datetime\r
 import hashlib\r
-from GenVar import VariableMgr, var_info\r
+from .GenVar import VariableMgr, var_info\r
 from collections import OrderedDict\r
 from collections import defaultdict\r
 from Workspace.WorkspaceCommon import OrderedListDict\r
 from collections import OrderedDict\r
 from collections import defaultdict\r
 from Workspace.WorkspaceCommon import OrderedListDict\r
+from Common.ToolDefClassObject import gDefaultToolsDefFile\r
+\r
+from Common.caching import cached_property, cached_class_function\r
 \r
 ## Regular expression for splitting Dependency Expression string into tokens\r
 gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")\r
 \r
 ## Regular expression for splitting Dependency Expression string into tokens\r
 gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")\r
@@ -77,15 +75,12 @@ gEfiVarStoreNamePattern = re.compile("\s*name\s*=\s*(\w+)")
 gEfiVarStoreGuidPattern = re.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")\r
 \r
 ## Mapping Makefile type\r
 gEfiVarStoreGuidPattern = re.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")\r
 \r
 ## Mapping Makefile type\r
-gMakeTypeMap = {"MSFT":"nmake", "GCC":"gmake"}\r
+gMakeTypeMap = {TAB_COMPILER_MSFT:"nmake", "GCC":"gmake"}\r
 \r
 \r
 ## Build rule configuration file\r
 gDefaultBuildRuleFile = 'build_rule.txt'\r
 \r
 \r
 \r
 ## Build rule configuration file\r
 gDefaultBuildRuleFile = 'build_rule.txt'\r
 \r
-## Tools definition configuration file\r
-gDefaultToolsDefFile = 'tools_def.txt'\r
-\r
 ## Build rule default version\r
 AutoGenReqBuildRuleVerNum = "0.1"\r
 \r
 ## Build rule default version\r
 AutoGenReqBuildRuleVerNum = "0.1"\r
 \r
@@ -170,6 +165,73 @@ ${tail_comments}
 ## @AsBuilt${BEGIN}\r
 ##   ${flags_item}${END}\r
 """)\r
 ## @AsBuilt${BEGIN}\r
 ##   ${flags_item}${END}\r
 """)\r
+## Split command line option string to list\r
+#\r
+# subprocess.Popen needs the args to be a sequence. Otherwise there's problem\r
+# in non-windows platform to launch command\r
+#\r
+def _SplitOption(OptionString):\r
+    OptionList = []\r
+    LastChar = " "\r
+    OptionStart = 0\r
+    QuotationMark = ""\r
+    for Index in range(0, len(OptionString)):\r
+        CurrentChar = OptionString[Index]\r
+        if CurrentChar in ['"', "'"]:\r
+            if QuotationMark == CurrentChar:\r
+                QuotationMark = ""\r
+            elif QuotationMark == "":\r
+                QuotationMark = CurrentChar\r
+            continue\r
+        elif QuotationMark:\r
+            continue\r
+\r
+        if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]:\r
+            if Index > OptionStart:\r
+                OptionList.append(OptionString[OptionStart:Index - 1])\r
+            OptionStart = Index\r
+        LastChar = CurrentChar\r
+    OptionList.append(OptionString[OptionStart:])\r
+    return OptionList\r
+\r
+#\r
+# Convert string to C format array\r
+#\r
+def _ConvertStringToByteArray(Value):\r
+    Value = Value.strip()\r
+    if not Value:\r
+        return None\r
+    if Value[0] == '{':\r
+        if not Value.endswith('}'):\r
+            return None\r
+        Value = Value.replace(' ', '').replace('{', '').replace('}', '')\r
+        ValFields = Value.split(',')\r
+        try:\r
+            for Index in range(len(ValFields)):\r
+                ValFields[Index] = str(int(ValFields[Index], 0))\r
+        except ValueError:\r
+            return None\r
+        Value = '{' + ','.join(ValFields) + '}'\r
+        return Value\r
+\r
+    Unicode = False\r
+    if Value.startswith('L"'):\r
+        if not Value.endswith('"'):\r
+            return None\r
+        Value = Value[1:]\r
+        Unicode = True\r
+    elif not Value.startswith('"') or not Value.endswith('"'):\r
+        return None\r
+\r
+    Value = eval(Value)         # translate escape character\r
+    NewValue = '{'\r
+    for Index in range(0, len(Value)):\r
+        if Unicode:\r
+            NewValue = NewValue + str(ord(Value[Index]) % 0x10000) + ','\r
+        else:\r
+            NewValue = NewValue + str(ord(Value[Index]) % 0x100) + ','\r
+    Value = NewValue + '0}'\r
+    return Value\r
 \r
 ## Base class for AutoGen\r
 #\r
 \r
 ## Base class for AutoGen\r
 #\r
@@ -194,16 +256,13 @@ 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
     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
             # 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
             # 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
 \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
 \r
     ## hash() operator\r
     #\r
 \r
     ## hash() operator\r
     #\r
@@ -235,13 +294,10 @@ 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
 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
-            super(WorkspaceAutoGen, self).__init__(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
+        if not hasattr(self, "_Init"):\r
             self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
             self._Init = True\r
             self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
             self._Init = True\r
-    \r
+\r
     ## Initialize WorkspaceAutoGen\r
     #\r
     #   @param  WorkspaceDir            Root directory of workspace\r
     ## Initialize WorkspaceAutoGen\r
     #\r
     #   @param  WorkspaceDir            Root directory of workspace\r
@@ -279,10 +335,6 @@ class WorkspaceAutoGen(AutoGen):
         self.FvTargetList   = Fvs if Fvs else []\r
         self.CapTargetList  = Caps if Caps else []\r
         self.AutoGenObjectList = []\r
         self.FvTargetList   = Fvs if Fvs else []\r
         self.CapTargetList  = Caps if Caps else []\r
         self.AutoGenObjectList = []\r
-        self._BuildDir      = None\r
-        self._FvDir         = None\r
-        self._MakeFileDir   = None\r
-        self._BuildCommand  = None\r
         self._GuidDict = {}\r
 \r
         # there's many relative directory operations, so ...\r
         self._GuidDict = {}\r
 \r
         # there's many relative directory operations, so ...\r
@@ -310,7 +362,7 @@ class WorkspaceAutoGen(AutoGen):
                             ExtraData="Build target [%s] is not supported by the platform. [Valid target: %s]"\r
                                       % (self.BuildTarget, " ".join(self.Platform.BuildTargets)))\r
 \r
                             ExtraData="Build target [%s] is not supported by the platform. [Valid target: %s]"\r
                                       % (self.BuildTarget, " ".join(self.Platform.BuildTargets)))\r
 \r
-        \r
+\r
         # parse FDF file to get PCDs in it, if any\r
         if not self.FdfFile:\r
             self.FdfFile = self.Platform.FlashDefinition\r
         # parse FDF file to get PCDs in it, if any\r
         if not self.FdfFile:\r
             self.FdfFile = self.Platform.FlashDefinition\r
@@ -416,7 +468,7 @@ class WorkspaceAutoGen(AutoGen):
 \r
             # generate the SourcePcdDict and BinaryPcdDict\r
             PGen = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)\r
 \r
             # generate the SourcePcdDict and BinaryPcdDict\r
             PGen = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)\r
-            for BuildData in PGen.BuildDatabase._CACHE_.values():\r
+            for BuildData in list(PGen.BuildDatabase._CACHE_.values()):\r
                 if BuildData.Arch != Arch:\r
                     continue\r
                 if BuildData.MetaFile.Ext == '.inf':\r
                 if BuildData.Arch != Arch:\r
                     continue\r
                 if BuildData.MetaFile.Ext == '.inf':\r
@@ -441,7 +493,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
                                     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
                                             for ReferenceModule in ReferenceModules:\r
                                                 if ReferenceModule.MetaFile in Platform.Modules:\r
                                                     RefPlatformModule = Platform.Modules[str(ReferenceModule.MetaFile)]\r
@@ -522,7 +574,7 @@ class WorkspaceAutoGen(AutoGen):
                                 if NewPcd2 not in GlobalData.MixedPcd[item]:\r
                                     GlobalData.MixedPcd[item].append(NewPcd2)\r
 \r
                                 if NewPcd2 not in GlobalData.MixedPcd[item]:\r
                                     GlobalData.MixedPcd[item].append(NewPcd2)\r
 \r
-            for BuildData in PGen.BuildDatabase._CACHE_.values():\r
+            for BuildData in list(PGen.BuildDatabase._CACHE_.values()):\r
                 if BuildData.Arch != Arch:\r
                     continue\r
                 for key in BuildData.Pcds:\r
                 if BuildData.Arch != Arch:\r
                     continue\r
                 for key in BuildData.Pcds:\r
@@ -568,29 +620,28 @@ class WorkspaceAutoGen(AutoGen):
                     DecPcdsKey.add((Pcd[0], Pcd[1], Pcd[2]))\r
 \r
             Platform.SkuName = self.SkuId\r
                     DecPcdsKey.add((Pcd[0], Pcd[1], Pcd[2]))\r
 \r
             Platform.SkuName = self.SkuId\r
-            for Name, Guid in PcdSet:\r
+            for Name, Guid,Fileds in PcdSet:\r
                 if (Name, Guid) not in DecPcds:\r
                     EdkLogger.error(\r
                         'build',\r
                         PARSER_ERROR,\r
                         "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid, Name),\r
                 if (Name, Guid) not in DecPcds:\r
                     EdkLogger.error(\r
                         'build',\r
                         PARSER_ERROR,\r
                         "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid, Name),\r
-                        File = self.FdfProfile.PcdFileLineDict[Name, Guid][0],\r
-                        Line = self.FdfProfile.PcdFileLineDict[Name, Guid][1]\r
+                        File = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][0],\r
+                        Line = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][1]\r
                     )\r
                 else:\r
                     # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.\r
                     if (Name, Guid, TAB_PCDS_FIXED_AT_BUILD) in DecPcdsKey \\r
                         or (Name, Guid, TAB_PCDS_PATCHABLE_IN_MODULE) in DecPcdsKey \\r
                         or (Name, Guid, TAB_PCDS_FEATURE_FLAG) in DecPcdsKey:\r
                     )\r
                 else:\r
                     # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.\r
                     if (Name, Guid, TAB_PCDS_FIXED_AT_BUILD) in DecPcdsKey \\r
                         or (Name, Guid, TAB_PCDS_PATCHABLE_IN_MODULE) in DecPcdsKey \\r
                         or (Name, Guid, TAB_PCDS_FEATURE_FLAG) in DecPcdsKey:\r
-                        Platform.AddPcd(Name, Guid, PcdSet[Name, Guid])\r
                         continue\r
                     elif (Name, Guid, TAB_PCDS_DYNAMIC) in DecPcdsKey or (Name, Guid, TAB_PCDS_DYNAMIC_EX) in DecPcdsKey:\r
                         EdkLogger.error(\r
                                 'build',\r
                                 PARSER_ERROR,\r
                                 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid, Name),\r
                         continue\r
                     elif (Name, Guid, TAB_PCDS_DYNAMIC) in DecPcdsKey or (Name, Guid, TAB_PCDS_DYNAMIC_EX) in DecPcdsKey:\r
                         EdkLogger.error(\r
                                 'build',\r
                                 PARSER_ERROR,\r
                                 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid, Name),\r
-                                File = self.FdfProfile.PcdFileLineDict[Name, Guid][0],\r
-                                Line = self.FdfProfile.PcdFileLineDict[Name, Guid][1]\r
+                                File = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][0],\r
+                                Line = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][1]\r
                         )\r
 \r
             Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)\r
                         )\r
 \r
             Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)\r
@@ -604,7 +655,7 @@ class WorkspaceAutoGen(AutoGen):
             #\r
             # Generate Package level hash value\r
             #\r
             #\r
             # Generate Package level hash value\r
             #\r
-            GlobalData.gPackageHash[Arch] = {}\r
+            GlobalData.gPackageHash = {}\r
             if GlobalData.gUseHashCache:\r
                 for Pkg in Pkgs:\r
                     self._GenPkgLevelHash(Pkg)\r
             if GlobalData.gUseHashCache:\r
                 for Pkg in Pkgs:\r
                     self._GenPkgLevelHash(Pkg)\r
@@ -619,25 +670,22 @@ class WorkspaceAutoGen(AutoGen):
         #\r
         self._CheckPcdDefineAndType()\r
 \r
         #\r
         self._CheckPcdDefineAndType()\r
 \r
-#         if self.FdfFile:\r
-#             self._CheckDuplicateInFV(Fdf)\r
-\r
         #\r
         # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.\r
         #\r
         content = 'gCommandLineDefines: '\r
         content += str(GlobalData.gCommandLineDefines)\r
         #\r
         # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.\r
         #\r
         content = 'gCommandLineDefines: '\r
         content += str(GlobalData.gCommandLineDefines)\r
-        content += os.linesep\r
+        content += TAB_LINE_BREAK\r
         content += 'BuildOptionPcd: '\r
         content += str(GlobalData.BuildOptionPcd)\r
         content += 'BuildOptionPcd: '\r
         content += str(GlobalData.BuildOptionPcd)\r
-        content += os.linesep\r
+        content += TAB_LINE_BREAK\r
         content += 'Active Platform: '\r
         content += str(self.Platform)\r
         content += 'Active Platform: '\r
         content += str(self.Platform)\r
-        content += os.linesep\r
+        content += TAB_LINE_BREAK\r
         if self.FdfFile:\r
             content += 'Flash Image Definition: '\r
             content += str(self.FdfFile)\r
         if self.FdfFile:\r
             content += 'Flash Image Definition: '\r
             content += str(self.FdfFile)\r
-            content += os.linesep\r
+            content += TAB_LINE_BREAK\r
         SaveFileOnChange(os.path.join(self.BuildDir, 'BuildOptions'), content, False)\r
 \r
         #\r
         SaveFileOnChange(os.path.join(self.BuildDir, 'BuildOptions'), content, False)\r
 \r
         #\r
@@ -647,7 +695,7 @@ class WorkspaceAutoGen(AutoGen):
         if Pa.PcdTokenNumber:\r
             if Pa.DynamicPcdList:\r
                 for Pcd in Pa.DynamicPcdList:\r
         if Pa.PcdTokenNumber:\r
             if Pa.DynamicPcdList:\r
                 for Pcd in Pa.DynamicPcdList:\r
-                    PcdTokenNumber += os.linesep\r
+                    PcdTokenNumber += TAB_LINE_BREAK\r
                     PcdTokenNumber += str((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))\r
                     PcdTokenNumber += ' : '\r
                     PcdTokenNumber += str(Pa.PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName])\r
                     PcdTokenNumber += str((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))\r
                     PcdTokenNumber += ' : '\r
                     PcdTokenNumber += str(Pa.PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName])\r
@@ -672,11 +720,11 @@ class WorkspaceAutoGen(AutoGen):
             for files in AllWorkSpaceMetaFiles:\r
                 if files.endswith('.dec'):\r
                     continue\r
             for files in AllWorkSpaceMetaFiles:\r
                 if files.endswith('.dec'):\r
                     continue\r
-                f = open(files, 'r')\r
+                f = open(files, 'rb')\r
                 Content = f.read()\r
                 f.close()\r
                 m.update(Content)\r
                 Content = f.read()\r
                 f.close()\r
                 m.update(Content)\r
-            SaveFileOnChange(os.path.join(self.BuildDir, 'AutoGen.hash'), m.hexdigest(), True)\r
+            SaveFileOnChange(os.path.join(self.BuildDir, 'AutoGen.hash'), m.hexdigest(), False)\r
             GlobalData.gPlatformHash = m.hexdigest()\r
 \r
         #\r
             GlobalData.gPlatformHash = m.hexdigest()\r
 \r
         #\r
@@ -693,7 +741,7 @@ class WorkspaceAutoGen(AutoGen):
         return True\r
 \r
     def _GenPkgLevelHash(self, Pkg):\r
         return True\r
 \r
     def _GenPkgLevelHash(self, Pkg):\r
-        if Pkg.PackageName in GlobalData.gPackageHash[Pkg.Arch]:\r
+        if Pkg.PackageName in GlobalData.gPackageHash:\r
             return\r
 \r
         PkgDir = os.path.join(self.BuildDir, Pkg.Arch, Pkg.PackageName)\r
             return\r
 \r
         PkgDir = os.path.join(self.BuildDir, Pkg.Arch, Pkg.PackageName)\r
@@ -701,7 +749,7 @@ class WorkspaceAutoGen(AutoGen):
         HashFile = os.path.join(PkgDir, Pkg.PackageName + '.hash')\r
         m = hashlib.md5()\r
         # Get .dec file's hash value\r
         HashFile = os.path.join(PkgDir, Pkg.PackageName + '.hash')\r
         m = hashlib.md5()\r
         # Get .dec file's hash value\r
-        f = open(Pkg.MetaFile.Path, 'r')\r
+        f = open(Pkg.MetaFile.Path, 'rb')\r
         Content = f.read()\r
         f.close()\r
         m.update(Content)\r
         Content = f.read()\r
         f.close()\r
         m.update(Content)\r
@@ -711,12 +759,12 @@ class WorkspaceAutoGen(AutoGen):
                 for Root, Dirs, Files in os.walk(str(inc)):\r
                     for File in sorted(Files):\r
                         File_Path = os.path.join(Root, File)\r
                 for Root, Dirs, Files in os.walk(str(inc)):\r
                     for File in sorted(Files):\r
                         File_Path = os.path.join(Root, File)\r
-                        f = open(File_Path, 'r')\r
+                        f = open(File_Path, 'rb')\r
                         Content = f.read()\r
                         f.close()\r
                         m.update(Content)\r
                         Content = f.read()\r
                         f.close()\r
                         m.update(Content)\r
-        SaveFileOnChange(HashFile, m.hexdigest(), True)\r
-        GlobalData.gPackageHash[Pkg.Arch][Pkg.PackageName] = m.hexdigest()\r
+        SaveFileOnChange(HashFile, m.hexdigest(), False)\r
+        GlobalData.gPackageHash[Pkg.PackageName] = m.hexdigest()\r
 \r
     def _GetMetaFiles(self, Target, Toolchain, Arch):\r
         AllWorkSpaceMetaFiles = set()\r
 \r
     def _GetMetaFiles(self, Target, Toolchain, Arch):\r
         AllWorkSpaceMetaFiles = set()\r
@@ -761,131 +809,6 @@ class WorkspaceAutoGen(AutoGen):
 \r
         return AllWorkSpaceMetaFiles\r
 \r
 \r
         return AllWorkSpaceMetaFiles\r
 \r
-    ## _CheckDuplicateInFV() method\r
-    #\r
-    # Check whether there is duplicate modules/files exist in FV section. \r
-    # The check base on the file GUID;\r
-    #\r
-    def _CheckDuplicateInFV(self, Fdf):\r
-        for Fv in Fdf.Profile.FvDict:\r
-            _GuidDict = {}\r
-            for FfsFile in Fdf.Profile.FvDict[Fv].FfsList:\r
-                if FfsFile.InfFileName and FfsFile.NameGuid is None:\r
-                    #\r
-                    # Get INF file GUID\r
-                    #\r
-                    InfFoundFlag = False\r
-                    for Pa in self.AutoGenObjectList:\r
-                        if InfFoundFlag:\r
-                            break\r
-                        for Module in Pa.ModuleAutoGenList:\r
-                            if path.normpath(Module.MetaFile.File) == path.normpath(FfsFile.InfFileName):\r
-                                InfFoundFlag = True\r
-                                if Module.Guid.upper() not in _GuidDict:\r
-                                    _GuidDict[Module.Guid.upper()] = FfsFile\r
-                                    break\r
-                                else:\r
-                                    EdkLogger.error("build",\r
-                                                    FORMAT_INVALID,\r
-                                                    "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,\r
-                                                                                                                                   FfsFile.CurrentLineContent,\r
-                                                                                                                                   _GuidDict[Module.Guid.upper()].CurrentLineNum,\r
-                                                                                                                                   _GuidDict[Module.Guid.upper()].CurrentLineContent,\r
-                                                                                                                                   Module.Guid.upper()),\r
-                                                    ExtraData=self.FdfFile)\r
-                    #\r
-                    # Some INF files not have entity in DSC file. \r
-                    #\r
-                    if not InfFoundFlag:\r
-                        if FfsFile.InfFileName.find('$') == -1:\r
-                            InfPath = NormPath(FfsFile.InfFileName)\r
-                            if not os.path.exists(InfPath):\r
-                                EdkLogger.error('build', GENFDS_ERROR, "Non-existant Module %s !" % (FfsFile.InfFileName))\r
-\r
-                            PathClassObj = PathClass(FfsFile.InfFileName, self.WorkspaceDir)\r
-                            #\r
-                            # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use \r
-                            # BuildObject from one of AutoGenObjectList is enough.\r
-                            #\r
-                            InfObj = self.AutoGenObjectList[0].BuildDatabase.WorkspaceDb.BuildObject[PathClassObj, TAB_ARCH_COMMON, self.BuildTarget, self.ToolChain]\r
-                            if InfObj.Guid.upper() not in _GuidDict:\r
-                                _GuidDict[InfObj.Guid.upper()] = FfsFile\r
-                            else:\r
-                                EdkLogger.error("build",\r
-                                                FORMAT_INVALID,\r
-                                                "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,\r
-                                                                                                                               FfsFile.CurrentLineContent,\r
-                                                                                                                               _GuidDict[InfObj.Guid.upper()].CurrentLineNum,\r
-                                                                                                                               _GuidDict[InfObj.Guid.upper()].CurrentLineContent,\r
-                                                                                                                               InfObj.Guid.upper()),\r
-                                                ExtraData=self.FdfFile)\r
-                        InfFoundFlag = False\r
-\r
-                if FfsFile.NameGuid is not None:\r
-                    #\r
-                    # If the NameGuid reference a PCD name. \r
-                    # The style must match: PCD(xxxx.yyy)\r
-                    #\r
-                    if gPCDAsGuidPattern.match(FfsFile.NameGuid):\r
-                        #\r
-                        # Replace the PCD value.\r
-                        #\r
-                        _PcdName = FfsFile.NameGuid.lstrip("PCD(").rstrip(")")\r
-                        PcdFoundFlag = False\r
-                        for Pa in self.AutoGenObjectList:\r
-                            if not PcdFoundFlag:\r
-                                for PcdItem in Pa.AllPcdList:\r
-                                    if (PcdItem.TokenSpaceGuidCName + "." + PcdItem.TokenCName) == _PcdName:\r
-                                        #\r
-                                        # First convert from CFormatGuid to GUID string\r
-                                        #\r
-                                        _PcdGuidString = GuidStructureStringToGuidString(PcdItem.DefaultValue)\r
-\r
-                                        if not _PcdGuidString:\r
-                                            #\r
-                                            # Then try Byte array.\r
-                                            #\r
-                                            _PcdGuidString = GuidStructureByteArrayToGuidString(PcdItem.DefaultValue)\r
-\r
-                                        if not _PcdGuidString:\r
-                                            #\r
-                                            # Not Byte array or CFormat GUID, raise error.\r
-                                            #\r
-                                            EdkLogger.error("build",\r
-                                                            FORMAT_INVALID,\r
-                                                            "The format of PCD value is incorrect. PCD: %s , Value: %s\n" % (_PcdName, PcdItem.DefaultValue),\r
-                                                            ExtraData=self.FdfFile)\r
-\r
-                                        if _PcdGuidString.upper() not in _GuidDict:\r
-                                            _GuidDict[_PcdGuidString.upper()] = FfsFile\r
-                                            PcdFoundFlag = True\r
-                                            break\r
-                                        else:\r
-                                            EdkLogger.error("build",\r
-                                                            FORMAT_INVALID,\r
-                                                            "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,\r
-                                                                                                                                           FfsFile.CurrentLineContent,\r
-                                                                                                                                           _GuidDict[_PcdGuidString.upper()].CurrentLineNum,\r
-                                                                                                                                           _GuidDict[_PcdGuidString.upper()].CurrentLineContent,\r
-                                                                                                                                           FfsFile.NameGuid.upper()),\r
-                                                            ExtraData=self.FdfFile)\r
-\r
-                    if FfsFile.NameGuid.upper() not in _GuidDict:\r
-                        _GuidDict[FfsFile.NameGuid.upper()] = FfsFile\r
-                    else:\r
-                        #\r
-                        # Two raw file GUID conflict.\r
-                        #\r
-                        EdkLogger.error("build",\r
-                                        FORMAT_INVALID,\r
-                                        "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,\r
-                                                                                                                       FfsFile.CurrentLineContent,\r
-                                                                                                                       _GuidDict[FfsFile.NameGuid.upper()].CurrentLineNum,\r
-                                                                                                                       _GuidDict[FfsFile.NameGuid.upper()].CurrentLineContent,\r
-                                                                                                                       FfsFile.NameGuid.upper()),\r
-                                        ExtraData=self.FdfFile)\r
-\r
-\r
     def _CheckPcdDefineAndType(self):\r
         PcdTypeSet = {TAB_PCDS_FIXED_AT_BUILD,\r
             TAB_PCDS_PATCHABLE_IN_MODULE,\r
     def _CheckPcdDefineAndType(self):\r
         PcdTypeSet = {TAB_PCDS_FIXED_AT_BUILD,\r
             TAB_PCDS_PATCHABLE_IN_MODULE,\r
@@ -900,7 +823,7 @@ class WorkspaceAutoGen(AutoGen):
             for Pcd in Pa.Platform.Pcds:\r
                 PcdType = Pa.Platform.Pcds[Pcd].Type\r
 \r
             for Pcd in Pa.Platform.Pcds:\r
                 PcdType = Pa.Platform.Pcds[Pcd].Type\r
 \r
-                # If no PCD type, this PCD comes from FDF \r
+                # If no PCD type, this PCD comes from FDF\r
                 if not PcdType:\r
                     continue\r
 \r
                 if not PcdType:\r
                     continue\r
 \r
@@ -940,66 +863,68 @@ class WorkspaceAutoGen(AutoGen):
         return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))\r
 \r
     ## Return the directory to store FV files\r
         return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))\r
 \r
     ## Return the directory to store FV files\r
-    def _GetFvDir(self):\r
-        if self._FvDir is None:\r
-            self._FvDir = path.join(self.BuildDir, TAB_FV_DIRECTORY)\r
-        return self._FvDir\r
+    @cached_property\r
+    def FvDir(self):\r
+        return path.join(self.BuildDir, TAB_FV_DIRECTORY)\r
 \r
     ## Return the directory to store all intermediate and final files built\r
 \r
     ## Return the directory to store all intermediate and final files built\r
-    def _GetBuildDir(self):\r
-        if self._BuildDir is None:\r
-            return self.AutoGenObjectList[0].BuildDir\r
+    @cached_property\r
+    def BuildDir(self):\r
+        return self.AutoGenObjectList[0].BuildDir\r
 \r
     ## Return the build output directory platform specifies\r
 \r
     ## Return the build output directory platform specifies\r
-    def _GetOutputDir(self):\r
+    @cached_property\r
+    def OutputDir(self):\r
         return self.Platform.OutputDirectory\r
 \r
     ## Return platform name\r
         return self.Platform.OutputDirectory\r
 \r
     ## Return platform name\r
-    def _GetName(self):\r
+    @cached_property\r
+    def Name(self):\r
         return self.Platform.PlatformName\r
 \r
     ## Return meta-file GUID\r
         return self.Platform.PlatformName\r
 \r
     ## Return meta-file GUID\r
-    def _GetGuid(self):\r
+    @cached_property\r
+    def Guid(self):\r
         return self.Platform.Guid\r
 \r
     ## Return platform version\r
         return self.Platform.Guid\r
 \r
     ## Return platform version\r
-    def _GetVersion(self):\r
+    @cached_property\r
+    def Version(self):\r
         return self.Platform.Version\r
 \r
     ## Return paths of tools\r
         return self.Platform.Version\r
 \r
     ## Return paths of tools\r
-    def _GetToolDefinition(self):\r
+    @cached_property\r
+    def ToolDefinition(self):\r
         return self.AutoGenObjectList[0].ToolDefinition\r
 \r
     ## Return directory of platform makefile\r
     #\r
     #   @retval     string  Makefile directory\r
     #\r
         return self.AutoGenObjectList[0].ToolDefinition\r
 \r
     ## Return directory of platform makefile\r
     #\r
     #   @retval     string  Makefile directory\r
     #\r
-    def _GetMakeFileDir(self):\r
-        if self._MakeFileDir is None:\r
-            self._MakeFileDir = self.BuildDir\r
-        return self._MakeFileDir\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
 \r
     ## Return build command string\r
     #\r
     #   @retval     string  Build command string\r
     #\r
-    def _GetBuildCommand(self):\r
-        if self._BuildCommand is None:\r
-            # BuildCommand should be all the same. So just get one from platform AutoGen\r
-            self._BuildCommand = self.AutoGenObjectList[0].BuildCommand\r
-        return self._BuildCommand\r
+    @cached_property\r
+    def BuildCommand(self):\r
+        # BuildCommand should be all the same. So just get one from platform AutoGen\r
+        return self.AutoGenObjectList[0].BuildCommand\r
 \r
     ## Check the PCDs token value conflict in each DEC file.\r
     #\r
     # Will cause build break and raise error message while two PCDs conflict.\r
 \r
     ## Check the PCDs token value conflict in each DEC file.\r
     #\r
     # Will cause build break and raise error message while two PCDs conflict.\r
-    # \r
+    #\r
     # @return  None\r
     #\r
     def _CheckAllPcdsTokenValueConflict(self):\r
         for Pa in self.AutoGenObjectList:\r
             for Package in Pa.PackageList:\r
     # @return  None\r
     #\r
     def _CheckAllPcdsTokenValueConflict(self):\r
         for Pa in self.AutoGenObjectList:\r
             for Package in Pa.PackageList:\r
-                PcdList = Package.Pcds.values()\r
-                PcdList.sort(lambda x, y: cmp(int(x.TokenValue, 0), int(y.TokenValue, 0))) \r
+                PcdList = list(Package.Pcds.values())\r
+                PcdList.sort(key=lambda x: int(x.TokenValue, 0))\r
                 Count = 0\r
                 while (Count < len(PcdList) - 1) :\r
                     Item = PcdList[Count]\r
                 Count = 0\r
                 while (Count < len(PcdList) - 1) :\r
                     Item = PcdList[Count]\r
@@ -1020,7 +945,7 @@ class WorkspaceAutoGen(AutoGen):
                         #\r
                         # Sort same token value PCD list with TokenGuid and TokenCName\r
                         #\r
                         #\r
                         # Sort same token value PCD list with TokenGuid and TokenCName\r
                         #\r
-                        SameTokenValuePcdList.sort(lambda x, y: cmp("%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName), "%s.%s" % (y.TokenSpaceGuidCName, y.TokenCName)))\r
+                        SameTokenValuePcdList.sort(key=lambda x: "%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName))\r
                         SameTokenValuePcdListCount = 0\r
                         while (SameTokenValuePcdListCount < len(SameTokenValuePcdList) - 1):\r
                             Flag = False\r
                         SameTokenValuePcdListCount = 0\r
                         while (SameTokenValuePcdListCount < len(SameTokenValuePcdList) - 1):\r
                             Flag = False\r
@@ -1044,8 +969,8 @@ class WorkspaceAutoGen(AutoGen):
                         Count += SameTokenValuePcdListCount\r
                     Count += 1\r
 \r
                         Count += SameTokenValuePcdListCount\r
                     Count += 1\r
 \r
-                PcdList = Package.Pcds.values()\r
-                PcdList.sort(lambda x, y: cmp("%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName), "%s.%s" % (y.TokenSpaceGuidCName, y.TokenCName)))\r
+                PcdList = list(Package.Pcds.values())\r
+                PcdList.sort(key=lambda x: "%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName))\r
                 Count = 0\r
                 while (Count < len(PcdList) - 1) :\r
                     Item = PcdList[Count]\r
                 Count = 0\r
                 while (Count < len(PcdList) - 1) :\r
                     Item = PcdList[Count]\r
@@ -1063,9 +988,63 @@ class WorkspaceAutoGen(AutoGen):
                                     )\r
                     Count += 1\r
     ## Generate fds command\r
                                     )\r
                     Count += 1\r
     ## Generate fds command\r
-    def _GenFdsCommand(self):\r
+    @property\r
+    def GenFdsCommand(self):\r
         return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()\r
 \r
         return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()\r
 \r
+    @property\r
+    def GenFdsCommandDict(self):\r
+        FdsCommandDict = {}\r
+        LogLevel = EdkLogger.GetLevel()\r
+        if LogLevel == EdkLogger.VERBOSE:\r
+            FdsCommandDict["verbose"] = True\r
+        elif LogLevel <= EdkLogger.DEBUG_9:\r
+            FdsCommandDict["debug"] = LogLevel - 1\r
+        elif LogLevel == EdkLogger.QUIET:\r
+            FdsCommandDict["quiet"] = True\r
+\r
+        if GlobalData.gEnableGenfdsMultiThread:\r
+            FdsCommandDict["GenfdsMultiThread"] = True\r
+        if GlobalData.gIgnoreSource:\r
+            FdsCommandDict["IgnoreSources"] = True\r
+\r
+        FdsCommandDict["OptionPcd"] = []\r
+        for pcd in GlobalData.BuildOptionPcd:\r
+            if pcd[2]:\r
+                pcdname = '.'.join(pcd[0:3])\r
+            else:\r
+                pcdname = '.'.join(pcd[0:2])\r
+            if pcd[3].startswith('{'):\r
+                FdsCommandDict["OptionPcd"].append(pcdname + '=' + 'H' + '"' + pcd[3] + '"')\r
+            else:\r
+                FdsCommandDict["OptionPcd"].append(pcdname + '=' + pcd[3])\r
+\r
+        MacroList = []\r
+        # macros passed to GenFds\r
+        MacroDict = {}\r
+        MacroDict.update(GlobalData.gGlobalDefines)\r
+        MacroDict.update(GlobalData.gCommandLineDefines)\r
+        for MacroName in MacroDict:\r
+            if MacroDict[MacroName] != "":\r
+                MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))\r
+            else:\r
+                MacroList.append('"%s"' % MacroName)\r
+        FdsCommandDict["macro"] = MacroList\r
+\r
+        FdsCommandDict["fdf_file"] = [self.FdfFile]\r
+        FdsCommandDict["build_target"] = self.BuildTarget\r
+        FdsCommandDict["toolchain_tag"] = self.ToolChain\r
+        FdsCommandDict["active_platform"] = str(self)\r
+\r
+        FdsCommandDict["conf_directory"] = GlobalData.gConfDirectory\r
+        FdsCommandDict["build_architecture_list"] = ','.join(self.ArchList)\r
+        FdsCommandDict["platform_build_directory"] = self.BuildDir\r
+\r
+        FdsCommandDict["fd"] = self.FdTargetList\r
+        FdsCommandDict["fv"] = self.FvTargetList\r
+        FdsCommandDict["cap"] = self.CapTargetList\r
+        return FdsCommandDict\r
+\r
     ## Create makefile for the platform and modules in it\r
     #\r
     #   @param      CreateDepsMakeFile      Flag indicating if the makefile for\r
     ## Create makefile for the platform and modules in it\r
     #\r
     #   @param      CreateDepsMakeFile      Flag indicating if the makefile for\r
@@ -1096,18 +1075,6 @@ class WorkspaceAutoGen(AutoGen):
     def CreateAsBuiltInf(self):\r
         return\r
 \r
     def CreateAsBuiltInf(self):\r
         return\r
 \r
-    Name                = property(_GetName)\r
-    Guid                = property(_GetGuid)\r
-    Version             = property(_GetVersion)\r
-    OutputDir           = property(_GetOutputDir)\r
-\r
-    ToolDefinition      = property(_GetToolDefinition)       # toolcode : tool path\r
-\r
-    BuildDir            = property(_GetBuildDir)\r
-    FvDir               = property(_GetFvDir)\r
-    MakeFileDir         = property(_GetMakeFileDir)\r
-    BuildCommand        = property(_GetBuildCommand)\r
-    GenFdsCommand       = property(_GenFdsCommand)\r
 \r
 ## AutoGen class for platform\r
 #\r
 \r
 ## AutoGen class for platform\r
 #\r
@@ -1117,27 +1084,24 @@ 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
 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
-            super(PlatformAutoGen, self).__init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
+        if not hasattr(self, "_Init"):\r
             self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch)\r
             self._Init = True\r
     #\r
             self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch)\r
             self._Init = True\r
     #\r
-    # Used to store all PCDs for both PEI and DXE phase, in order to generate \r
+    # Used to store all PCDs for both PEI and DXE phase, in order to generate\r
     # correct PCD database\r
     # correct PCD database\r
-    # \r
+    #\r
     _DynaPcdList_ = []\r
     _NonDynaPcdList_ = []\r
     _PlatformPcds = {}\r
     _DynaPcdList_ = []\r
     _NonDynaPcdList_ = []\r
     _PlatformPcds = {}\r
-    \r
+\r
     #\r
     #\r
-    # The priority list while override build option \r
+    # The priority list while override build option\r
     #\r
     PrioList = {"0x11111"  : 16,     #  TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)\r
                 "0x01111"  : 15,     #  ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
                 "0x10111"  : 14,     #  TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE\r
     #\r
     PrioList = {"0x11111"  : 16,     #  TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)\r
                 "0x01111"  : 15,     #  ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
                 "0x10111"  : 14,     #  TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE\r
-                "0x00111"  : 13,     #  ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE \r
+                "0x00111"  : 13,     #  ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE\r
                 "0x11011"  : 12,     #  TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
                 "0x01011"  : 11,     #  ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
                 "0x10011"  : 10,     #  TARGET_*********_****_COMMANDTYPE_ATTRIBUTE\r
                 "0x11011"  : 12,     #  TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
                 "0x01011"  : 11,     #  ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
                 "0x10011"  : 10,     #  TARGET_*********_****_COMMANDTYPE_ATTRIBUTE\r
@@ -1171,48 +1135,18 @@ class PlatformAutoGen(AutoGen):
         self.BuildTarget = Target\r
         self.Arch = Arch\r
         self.SourceDir = PlatformFile.SubDir\r
         self.BuildTarget = Target\r
         self.Arch = Arch\r
         self.SourceDir = PlatformFile.SubDir\r
-        self.SourceOverrideDir = None\r
         self.FdTargetList = self.Workspace.FdTargetList\r
         self.FvTargetList = self.Workspace.FvTargetList\r
         self.FdTargetList = self.Workspace.FdTargetList\r
         self.FvTargetList = self.Workspace.FvTargetList\r
-        self.AllPcdList = []\r
         # get the original module/package/platform objects\r
         self.BuildDatabase = Workspace.BuildDatabase\r
         self.DscBuildDataObj = Workspace.Platform\r
         # get the original module/package/platform objects\r
         self.BuildDatabase = Workspace.BuildDatabase\r
         self.DscBuildDataObj = Workspace.Platform\r
-        self._GuidDict = Workspace._GuidDict\r
 \r
         # flag indicating if the makefile/C-code file has been created or not\r
         self.IsMakeFileCreated  = False\r
 \r
         # flag indicating if the makefile/C-code file has been created or not\r
         self.IsMakeFileCreated  = False\r
-        self.IsCodeFileCreated  = False\r
-\r
-        self._Platform   = None\r
-        self._Name       = None\r
-        self._Guid       = None\r
-        self._Version    = None\r
-\r
-        self._BuildRule = None\r
-        self._SourceDir = None\r
-        self._BuildDir = None\r
-        self._OutputDir = None\r
-        self._FvDir = None\r
-        self._MakeFileDir = None\r
-        self._FdfFile = None\r
-\r
-        self._PcdTokenNumber = None    # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber\r
+\r
         self._DynamicPcdList = None    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
         self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
         self._DynamicPcdList = None    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
         self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
-        self._NonDynamicPcdDict = {}\r
-\r
-        self._ToolDefinitions = None\r
-        self._ToolDefFile = None          # toolcode : tool path\r
-        self._ToolChainFamily = None\r
-        self._BuildRuleFamily = None\r
-        self._BuildOption = None          # toolcode : option\r
-        self._EdkBuildOption = None       # edktoolcode : option\r
-        self._EdkIIBuildOption = None     # edkiitoolcode : option\r
-        self._PackageList = None\r
-        self._ModuleAutoGenList  = None\r
-        self._LibraryAutoGenList = None\r
-        self._BuildCommand = None\r
+\r
         self._AsBuildInfList = []\r
         self._AsBuildModuleList = []\r
 \r
         self._AsBuildInfList = []\r
         self._AsBuildModuleList = []\r
 \r
@@ -1223,7 +1157,7 @@ class PlatformAutoGen(AutoGen):
             for Inf in self._AsBuildInfList:\r
                 InfClass = PathClass(NormPath(Inf), GlobalData.gWorkspace, self.Arch)\r
                 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
             for Inf in self._AsBuildInfList:\r
                 InfClass = PathClass(NormPath(Inf), GlobalData.gWorkspace, self.Arch)\r
                 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
-                if not M.IsSupportedArch:\r
+                if not M.IsBinaryModule:\r
                     continue\r
                 self._AsBuildModuleList.append(InfClass)\r
         # get library/modules for build\r
                     continue\r
                 self._AsBuildModuleList.append(InfClass)\r
         # get library/modules for build\r
@@ -1232,6 +1166,7 @@ class PlatformAutoGen(AutoGen):
 \r
         return True\r
 \r
 \r
         return True\r
 \r
+    @cached_class_function\r
     def __repr__(self):\r
         return "%s [%s]" % (self.MetaFile, self.Arch)\r
 \r
     def __repr__(self):\r
         return "%s [%s]" % (self.MetaFile, self.Arch)\r
 \r
@@ -1243,36 +1178,33 @@ class PlatformAutoGen(AutoGen):
     #   @param      CreateModuleCodeFile    Flag indicating if creating module's\r
     #                                       autogen code file or not\r
     #\r
     #   @param      CreateModuleCodeFile    Flag indicating if creating module's\r
     #                                       autogen code file or not\r
     #\r
+    @cached_class_function\r
     def CreateCodeFile(self, CreateModuleCodeFile=False):\r
     def CreateCodeFile(self, CreateModuleCodeFile=False):\r
-        # only module has code to be greated, so do nothing if CreateModuleCodeFile is False\r
-        if self.IsCodeFileCreated or not CreateModuleCodeFile:\r
+        # only module has code to be created, so do nothing if CreateModuleCodeFile is False\r
+        if not CreateModuleCodeFile:\r
             return\r
 \r
         for Ma in self.ModuleAutoGenList:\r
             Ma.CreateCodeFile(True)\r
 \r
             return\r
 \r
         for Ma in self.ModuleAutoGenList:\r
             Ma.CreateCodeFile(True)\r
 \r
-        # don't do this twice\r
-        self.IsCodeFileCreated = True\r
-\r
     ## Generate Fds Command\r
     ## Generate Fds Command\r
-    def _GenFdsCommand(self):\r
+    @cached_property\r
+    def GenFdsCommand(self):\r
         return self.Workspace.GenFdsCommand\r
 \r
         return self.Workspace.GenFdsCommand\r
 \r
-    ## Create makefile for the platform and mdoules in it\r
+    ## Create makefile for the platform and modules in it\r
     #\r
     #   @param      CreateModuleMakeFile    Flag indicating if the makefile for\r
     #                                       modules will be created as well\r
     #\r
     def CreateMakeFile(self, CreateModuleMakeFile=False, FfsCommand = {}):\r
         if CreateModuleMakeFile:\r
     #\r
     #   @param      CreateModuleMakeFile    Flag indicating if the makefile for\r
     #                                       modules will be created as well\r
     #\r
     def CreateMakeFile(self, CreateModuleMakeFile=False, FfsCommand = {}):\r
         if CreateModuleMakeFile:\r
-            for ModuleFile in self.Platform.Modules:\r
-                Ma = ModuleAutoGen(self.Workspace, ModuleFile, self.BuildTarget,\r
-                                   self.ToolChain, self.Arch, self.MetaFile)\r
-                if (ModuleFile.File, self.Arch) in FfsCommand:\r
-                    Ma.CreateMakeFile(True, FfsCommand[ModuleFile.File, self.Arch])\r
+            for Ma in self._MaList:\r
+                key = (Ma.MetaFile.File, self.Arch)\r
+                if key in FfsCommand:\r
+                    Ma.CreateMakeFile(True, FfsCommand[key])\r
                 else:\r
                     Ma.CreateMakeFile(True)\r
                 else:\r
                     Ma.CreateMakeFile(True)\r
-                #Ma.CreateAsBuiltInf()\r
 \r
         # no need to create makefile for the platform more than once\r
         if self.IsMakeFileCreated:\r
 \r
         # no need to create makefile for the platform more than once\r
         if self.IsMakeFileCreated:\r
@@ -1285,21 +1217,29 @@ class PlatformAutoGen(AutoGen):
 \r
         self.IsMakeFileCreated = True\r
 \r
 \r
         self.IsMakeFileCreated = True\r
 \r
+    @property\r
+    def AllPcdList(self):\r
+        return self.DynamicPcdList + self.NonDynamicPcdList\r
     ## Deal with Shared FixedAtBuild Pcds\r
     #\r
     def CollectFixedAtBuildPcds(self):\r
         for LibAuto in self.LibraryAutoGenList:\r
     ## Deal with Shared FixedAtBuild Pcds\r
     #\r
     def CollectFixedAtBuildPcds(self):\r
         for LibAuto in self.LibraryAutoGenList:\r
-            FixedAtBuildPcds = {}  \r
-            ShareFixedAtBuildPcdsSameValue = {} \r
-            for Module in LibAuto._ReferenceModules:                \r
-                for Pcd in Module.FixedAtBuildPcds + LibAuto.FixedAtBuildPcds:\r
+            FixedAtBuildPcds = {}\r
+            ShareFixedAtBuildPcdsSameValue = {}\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
+                    if Pcd in Module.LibraryPcdList:\r
+                        Index = Module.LibraryPcdList.index(Pcd)\r
+                        DefaultValue = Module.LibraryPcdList[Index].DefaultValue\r
                     key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
                     if key not in FixedAtBuildPcds:\r
                         ShareFixedAtBuildPcdsSameValue[key] = True\r
                     key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
                     if key not in FixedAtBuildPcds:\r
                         ShareFixedAtBuildPcdsSameValue[key] = True\r
-                        FixedAtBuildPcds[key] = Pcd.DefaultValue\r
+                        FixedAtBuildPcds[key] = DefaultValue\r
                     else:\r
                     else:\r
-                        if FixedAtBuildPcds[key] != Pcd.DefaultValue:\r
-                            ShareFixedAtBuildPcdsSameValue[key] = False      \r
+                        if FixedAtBuildPcds[key] != DefaultValue:\r
+                            ShareFixedAtBuildPcdsSameValue[key] = False\r
             for Pcd in LibAuto.FixedAtBuildPcds:\r
                 key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
                 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) not in self.NonDynamicPcdDict:\r
             for Pcd in LibAuto.FixedAtBuildPcds:\r
                 key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
                 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) not in self.NonDynamicPcdDict:\r
@@ -1308,11 +1248,10 @@ class PlatformAutoGen(AutoGen):
                     DscPcd = self.NonDynamicPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)]\r
                     if DscPcd.Type != TAB_PCDS_FIXED_AT_BUILD:\r
                         continue\r
                     DscPcd = self.NonDynamicPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)]\r
                     if DscPcd.Type != TAB_PCDS_FIXED_AT_BUILD:\r
                         continue\r
-                if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]:                    \r
+                if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]:\r
                     LibAuto.ConstPcd[key] = FixedAtBuildPcds[key]\r
 \r
     def CollectVariables(self, DynamicPcdSet):\r
                     LibAuto.ConstPcd[key] = FixedAtBuildPcds[key]\r
 \r
     def CollectVariables(self, DynamicPcdSet):\r
-\r
         VpdRegionSize = 0\r
         VpdRegionBase = 0\r
         if self.Workspace.FdfFile:\r
         VpdRegionSize = 0\r
         VpdRegionBase = 0\r
         if self.Workspace.FdfFile:\r
@@ -1324,8 +1263,7 @@ class PlatformAutoGen(AutoGen):
                         VpdRegionBase = FdRegion.Offset\r
                         break\r
 \r
                         VpdRegionBase = FdRegion.Offset\r
                         break\r
 \r
-\r
-        VariableInfo = VariableMgr(self.DscBuildDataObj._GetDefaultStores(), self.DscBuildDataObj._GetSkuIds())\r
+        VariableInfo = VariableMgr(self.DscBuildDataObj._GetDefaultStores(), self.DscBuildDataObj.SkuIds)\r
         VariableInfo.SetVpdRegionMaxSize(VpdRegionSize)\r
         VariableInfo.SetVpdRegionOffset(VpdRegionBase)\r
         Index = 0\r
         VariableInfo.SetVpdRegionMaxSize(VpdRegionSize)\r
         VariableInfo.SetVpdRegionOffset(VpdRegionBase)\r
         Index = 0\r
@@ -1337,10 +1275,12 @@ class PlatformAutoGen(AutoGen):
                 if SkuId is None or SkuId == '':\r
                     continue\r
                 if len(Sku.VariableName) > 0:\r
                 if SkuId is None or SkuId == '':\r
                     continue\r
                 if len(Sku.VariableName) > 0:\r
+                    if Sku.VariableAttribute and 'NV' not in Sku.VariableAttribute:\r
+                        continue\r
                     VariableGuidStructure = Sku.VariableGuidValue\r
                     VariableGuid = GuidStructureStringToGuidString(VariableGuidStructure)\r
                     for StorageName in Sku.DefaultStoreDict:\r
                     VariableGuidStructure = Sku.VariableGuidValue\r
                     VariableGuid = GuidStructureStringToGuidString(VariableGuidStructure)\r
                     for StorageName in Sku.DefaultStoreDict:\r
-                        VariableInfo.append_variable(var_info(Index, pcdname, StorageName, SkuName, StringToArray(Sku.VariableName), VariableGuid, Sku.VariableOffset, Sku.VariableAttribute, Sku.HiiDefaultValue, Sku.DefaultStoreDict[StorageName], Pcd.DatumType))\r
+                        VariableInfo.append_variable(var_info(Index, pcdname, StorageName, SkuName, StringToArray(Sku.VariableName), VariableGuid, Sku.VariableOffset, Sku.VariableAttribute, Sku.HiiDefaultValue, Sku.DefaultStoreDict[StorageName] if Pcd.DatumType in TAB_PCD_NUMERIC_TYPES else StringToArray(Sku.DefaultStoreDict[StorageName]), Pcd.DatumType, Pcd.CustomAttribute['DscPosition'], Pcd.CustomAttribute.get('IsStru',False)))\r
             Index += 1\r
         return VariableInfo\r
 \r
             Index += 1\r
         return VariableInfo\r
 \r
@@ -1353,7 +1293,7 @@ class PlatformAutoGen(AutoGen):
                 if os.path.exists(VpdMapFilePath):\r
                     OrgVpdFile.Read(VpdMapFilePath)\r
                     PcdItems = OrgVpdFile.GetOffset(PcdNvStoreDfBuffer[0])\r
                 if os.path.exists(VpdMapFilePath):\r
                     OrgVpdFile.Read(VpdMapFilePath)\r
                     PcdItems = OrgVpdFile.GetOffset(PcdNvStoreDfBuffer[0])\r
-                    NvStoreOffset = PcdItems.values()[0].strip() if PcdItems else '0'\r
+                    NvStoreOffset = list(PcdItems.values())[0].strip() if PcdItems else '0'\r
                 else:\r
                     EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)\r
 \r
                 else:\r
                     EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)\r
 \r
@@ -1377,7 +1317,6 @@ class PlatformAutoGen(AutoGen):
     #  This interface should be invoked explicitly when platform action is created.\r
     #\r
     def CollectPlatformDynamicPcds(self):\r
     #  This interface should be invoked explicitly when platform action is created.\r
     #\r
     def CollectPlatformDynamicPcds(self):\r
-\r
         for key in self.Platform.Pcds:\r
             for SinglePcd in GlobalData.MixedPcd:\r
                 if (self.Platform.Pcds[key].TokenCName, self.Platform.Pcds[key].TokenSpaceGuidCName) == SinglePcd:\r
         for key in self.Platform.Pcds:\r
             for SinglePcd in GlobalData.MixedPcd:\r
                 if (self.Platform.Pcds[key].TokenCName, self.Platform.Pcds[key].TokenSpaceGuidCName) == SinglePcd:\r
@@ -1402,42 +1341,38 @@ class PlatformAutoGen(AutoGen):
         for InfName in self._AsBuildInfList:\r
             InfName = mws.join(self.WorkspaceDir, InfName)\r
             FdfModuleList.append(os.path.normpath(InfName))\r
         for InfName in self._AsBuildInfList:\r
             InfName = mws.join(self.WorkspaceDir, InfName)\r
             FdfModuleList.append(os.path.normpath(InfName))\r
-        for F in self.Platform.Modules.keys():\r
-            M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self.MetaFile)\r
-            #GuidValue.update(M.Guids)\r
-            \r
-            self.Platform.Modules[F].M = M\r
-\r
+        for M in self._MaList:\r
+#            F is the Module for which M is the module autogen\r
             for PcdFromModule in M.ModulePcdList + M.LibraryPcdList:\r
                 # make sure that the "VOID*" kind of datum has MaxDatumSize set\r
                 if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:\r
             for PcdFromModule in M.ModulePcdList + M.LibraryPcdList:\r
                 # make sure that the "VOID*" kind of datum has MaxDatumSize set\r
                 if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:\r
-                    NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, F))\r
+                    NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, M.MetaFile))\r
 \r
                 # Check the PCD from Binary INF or Source INF\r
                 if M.IsBinaryModule == True:\r
                     PcdFromModule.IsFromBinaryInf = True\r
 \r
 \r
                 # Check the PCD from Binary INF or Source INF\r
                 if M.IsBinaryModule == True:\r
                     PcdFromModule.IsFromBinaryInf = True\r
 \r
-                # Check the PCD from DSC or not \r
+                # Check the PCD from DSC or not\r
                 PcdFromModule.IsFromDsc = (PcdFromModule.TokenCName, PcdFromModule.TokenSpaceGuidCName) in self.Platform.Pcds\r
 \r
                 if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET or PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
                 PcdFromModule.IsFromDsc = (PcdFromModule.TokenCName, PcdFromModule.TokenSpaceGuidCName) in self.Platform.Pcds\r
 \r
                 if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET or PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
-                    if F.Path not in FdfModuleList:\r
-                        # If one of the Source built modules listed in the DSC is not listed \r
-                        # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic \r
-                        # access method (it is only listed in the DEC file that declares the \r
+                    if M.MetaFile.Path not in FdfModuleList:\r
+                        # If one of the Source built modules listed in the DSC is not listed\r
+                        # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic\r
+                        # access method (it is only listed in the DEC file that declares the\r
                         # PCD as PcdsDynamic), then build tool will report warning message\r
                         # PCD as PcdsDynamic), then build tool will report warning message\r
-                        # notify the PI that they are attempting to build a module that must \r
-                        # be included in a flash image in order to be functional. These Dynamic \r
-                        # PCD will not be added into the Database unless it is used by other \r
+                        # notify the PI that they are attempting to build a module that must\r
+                        # be included in a flash image in order to be functional. These Dynamic\r
+                        # PCD will not be added into the Database unless it is used by other\r
                         # modules that are included in the FDF file.\r
                         if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET and \\r
                             PcdFromModule.IsFromBinaryInf == False:\r
                             # Print warning message to let the developer make a determine.\r
                             continue\r
                         # modules that are included in the FDF file.\r
                         if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET and \\r
                             PcdFromModule.IsFromBinaryInf == False:\r
                             # Print warning message to let the developer make a determine.\r
                             continue\r
-                        # If one of the Source built modules listed in the DSC is not listed in \r
-                        # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx \r
-                        # access method (it is only listed in the DEC file that declares the \r
-                        # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the \r
+                        # If one of the Source built modules listed in the DSC is not listed in\r
+                        # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx\r
+                        # access method (it is only listed in the DEC file that declares the\r
+                        # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the\r
                         # PCD to the Platform's PCD Database.\r
                         if PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
                             continue\r
                         # PCD to the Platform's PCD Database.\r
                         if PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
                             continue\r
@@ -1465,15 +1400,15 @@ class PlatformAutoGen(AutoGen):
                         PcdFromModule.Pending = False\r
                         self._NonDynaPcdList_.append (PcdFromModule)\r
         DscModuleSet = {os.path.normpath(ModuleInf.Path) for ModuleInf in self.Platform.Modules}\r
                         PcdFromModule.Pending = False\r
                         self._NonDynaPcdList_.append (PcdFromModule)\r
         DscModuleSet = {os.path.normpath(ModuleInf.Path) for ModuleInf in self.Platform.Modules}\r
-        # add the PCD from modules that listed in FDF but not in DSC to Database \r
+        # add the PCD from modules that listed in FDF but not in DSC to Database\r
         for InfName in FdfModuleList:\r
             if InfName not in DscModuleSet:\r
                 InfClass = PathClass(InfName)\r
                 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
         for InfName in FdfModuleList:\r
             if InfName not in DscModuleSet:\r
                 InfClass = PathClass(InfName)\r
                 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
-                # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source) \r
-                # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here. \r
-                # For binary module, if in current arch, we need to list the PCDs into database.   \r
-                if not M.IsSupportedArch:\r
+                # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)\r
+                # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.\r
+                # For binary module, if in current arch, we need to list the PCDs into database.\r
+                if not M.IsBinaryModule:\r
                     continue\r
                 # Override the module PCD setting by platform setting\r
                 ModulePcdList = self.ApplyPcdSetting(M, M.Pcds)\r
                     continue\r
                 # Override the module PCD setting by platform setting\r
                 ModulePcdList = self.ApplyPcdSetting(M, M.Pcds)\r
@@ -1497,20 +1432,20 @@ class PlatformAutoGen(AutoGen):
                         self._NonDynaPcdList_.append(PcdFromModule)\r
                     if PcdFromModule in self._DynaPcdList_ and PcdFromModule.Phase == 'PEI' and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
                         # Overwrite the phase of any the same PCD existing, if Phase is PEI.\r
                         self._NonDynaPcdList_.append(PcdFromModule)\r
                     if PcdFromModule in self._DynaPcdList_ and PcdFromModule.Phase == 'PEI' and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
                         # Overwrite the phase of any the same PCD existing, if Phase is PEI.\r
-                        # It is to solve the case that a dynamic PCD used by a PEM module/PEI \r
+                        # It is to solve the case that a dynamic PCD used by a PEM module/PEI\r
                         # module & DXE module at a same time.\r
                         # Overwrite the type of the PCDs in source INF by the type of AsBuild\r
                         # module & DXE module at a same time.\r
                         # Overwrite the type of the PCDs in source INF by the type of AsBuild\r
-                        # INF file as DynamicEx. \r
+                        # INF file as DynamicEx.\r
                         Index = self._DynaPcdList_.index(PcdFromModule)\r
                         self._DynaPcdList_[Index].Phase = PcdFromModule.Phase\r
                         self._DynaPcdList_[Index].Type = PcdFromModule.Type\r
         for PcdFromModule in self._NonDynaPcdList_:\r
                         Index = self._DynaPcdList_.index(PcdFromModule)\r
                         self._DynaPcdList_[Index].Phase = PcdFromModule.Phase\r
                         self._DynaPcdList_[Index].Type = PcdFromModule.Type\r
         for PcdFromModule in self._NonDynaPcdList_:\r
-            # If a PCD is not listed in the DSC file, but binary INF files used by \r
-            # this platform all (that use this PCD) list the PCD in a [PatchPcds] \r
-            # section, AND all source INF files used by this platform the build \r
-            # that use the PCD list the PCD in either a [Pcds] or [PatchPcds] \r
+            # If a PCD is not listed in the DSC file, but binary INF files used by\r
+            # this platform all (that use this PCD) list the PCD in a [PatchPcds]\r
+            # section, AND all source INF files used by this platform the build\r
+            # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]\r
             # section, then the tools must NOT add the PCD to the Platform's PCD\r
             # section, then the tools must NOT add the PCD to the Platform's PCD\r
-            # Database; the build must assign the access method for this PCD as \r
+            # Database; the build must assign the access method for this PCD as\r
             # PcdsPatchableInModule.\r
             if PcdFromModule not in self._DynaPcdList_:\r
                 continue\r
             # PcdsPatchableInModule.\r
             if PcdFromModule not in self._DynaPcdList_:\r
                 continue\r
@@ -1533,7 +1468,7 @@ class PlatformAutoGen(AutoGen):
         self._DynamicPcdList = self._DynaPcdList_\r
         #\r
         # Sort dynamic PCD list to:\r
         self._DynamicPcdList = self._DynaPcdList_\r
         #\r
         # Sort dynamic PCD list to:\r
-        # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should \r
+        # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should\r
         #    try to be put header of dynamicd List\r
         # 2) If PCD is HII type, the PCD item should be put after unicode type PCD\r
         #\r
         #    try to be put header of dynamicd List\r
         # 2) If PCD is HII type, the PCD item should be put after unicode type PCD\r
         #\r
@@ -1554,10 +1489,10 @@ class PlatformAutoGen(AutoGen):
             if self._PlatformPcds[item].DatumType and self._PlatformPcds[item].DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
                 self._PlatformPcds[item].DatumType = TAB_VOID\r
 \r
             if self._PlatformPcds[item].DatumType and self._PlatformPcds[item].DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
                 self._PlatformPcds[item].DatumType = TAB_VOID\r
 \r
-        if (self.Workspace.ArchList[-1] == self.Arch): \r
+        if (self.Workspace.ArchList[-1] == self.Arch):\r
             for Pcd in self._DynamicPcdList:\r
                 # just pick the a value to determine whether is unicode string type\r
             for Pcd in self._DynamicPcdList:\r
                 # just pick the a value to determine whether is unicode string type\r
-                Sku = Pcd.SkuInfoList.values()[0]\r
+                Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)\r
                 Sku.VpdOffset = Sku.VpdOffset.strip()\r
 \r
                 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
                 Sku.VpdOffset = Sku.VpdOffset.strip()\r
 \r
                 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
@@ -1574,11 +1509,21 @@ class PlatformAutoGen(AutoGen):
                 self.VariableInfo = self.CollectVariables(self._DynamicPcdList)\r
                 vardump = self.VariableInfo.dump()\r
                 if vardump:\r
                 self.VariableInfo = self.CollectVariables(self._DynamicPcdList)\r
                 vardump = self.VariableInfo.dump()\r
                 if vardump:\r
+                    #\r
+                    #According to PCD_DATABASE_INIT in edk2\MdeModulePkg\Include\Guid\PcdDataBaseSignatureGuid.h,\r
+                    #the max size for string PCD should not exceed USHRT_MAX 65535(0xffff).\r
+                    #typedef UINT16 SIZE_INFO;\r
+                    #//SIZE_INFO  SizeTable[];\r
+                    if len(vardump.split(",")) > 0xffff:\r
+                        EdkLogger.error("build", RESOURCE_OVERFLOW, 'The current length of PCD %s value is %d, it exceeds to the max size of String PCD.' %(".".join([PcdNvStoreDfBuffer.TokenSpaceGuidCName,PcdNvStoreDfBuffer.TokenCName]) ,len(vardump.split(","))))\r
                     PcdNvStoreDfBuffer.DefaultValue = vardump\r
                     for skuname in PcdNvStoreDfBuffer.SkuInfoList:\r
                         PcdNvStoreDfBuffer.SkuInfoList[skuname].DefaultValue = vardump\r
                         PcdNvStoreDfBuffer.MaxDatumSize = str(len(vardump.split(",")))\r
                     PcdNvStoreDfBuffer.DefaultValue = vardump\r
                     for skuname in PcdNvStoreDfBuffer.SkuInfoList:\r
                         PcdNvStoreDfBuffer.SkuInfoList[skuname].DefaultValue = vardump\r
                         PcdNvStoreDfBuffer.MaxDatumSize = str(len(vardump.split(",")))\r
-\r
+            else:\r
+                #If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd\r
+                if [Pcd for Pcd in self._DynamicPcdList if Pcd.UserDefinedDefaultStoresFlag]:\r
+                    EdkLogger.warn("build", "PcdNvStoreDefaultValueBuffer should be defined as PcdsDynamicExVpd in dsc file since the DefaultStores is enabled for this platform.\n%s" %self.Platform.MetaFile.Path)\r
             PlatformPcds = sorted(self._PlatformPcds.keys())\r
             #\r
             # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.\r
             PlatformPcds = sorted(self._PlatformPcds.keys())\r
             #\r
             # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.\r
@@ -1603,7 +1548,7 @@ class PlatformAutoGen(AutoGen):
                         PcdValue = Sku.DefaultValue\r
                         if PcdValue == "":\r
                             PcdValue  = Pcd.DefaultValue\r
                         PcdValue = Sku.DefaultValue\r
                         if PcdValue == "":\r
                             PcdValue  = Pcd.DefaultValue\r
-                        if Sku.VpdOffset != '*':\r
+                        if Sku.VpdOffset != TAB_STAR:\r
                             if PcdValue.startswith("{"):\r
                                 Alignment = 8\r
                             elif PcdValue.startswith("L"):\r
                             if PcdValue.startswith("{"):\r
                                 Alignment = 8\r
                             elif PcdValue.startswith("L"):\r
@@ -1627,7 +1572,7 @@ class PlatformAutoGen(AutoGen):
                             VpdFile.Add(Pcd, SkuName, Sku.VpdOffset)\r
                         SkuValueMap[PcdValue].append(Sku)\r
                         # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
                             VpdFile.Add(Pcd, SkuName, Sku.VpdOffset)\r
                         SkuValueMap[PcdValue].append(Sku)\r
                         # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
-                        if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":\r
+                        if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:\r
                             NeedProcessVpdMapFile = True\r
                             if self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == '':\r
                                 EdkLogger.error("Build", FILE_NOT_FOUND, \\r
                             NeedProcessVpdMapFile = True\r
                             if self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == '':\r
                                 EdkLogger.error("Build", FILE_NOT_FOUND, \\r
@@ -1637,7 +1582,7 @@ class PlatformAutoGen(AutoGen):
             #\r
             # Fix the PCDs define in VPD PCD section that never referenced by module.\r
             # An example is PCD for signature usage.\r
             #\r
             # Fix the PCDs define in VPD PCD section that never referenced by module.\r
             # An example is PCD for signature usage.\r
-            #            \r
+            #\r
             for DscPcd in PlatformPcds:\r
                 DscPcdEntry = self._PlatformPcds[DscPcd]\r
                 if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
             for DscPcd in PlatformPcds:\r
                 DscPcdEntry = self._PlatformPcds[DscPcd]\r
                 if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
@@ -1653,14 +1598,14 @@ class PlatformAutoGen(AutoGen):
                         if not FoundFlag :\r
                             # just pick the a value to determine whether is unicode string type\r
                             SkuValueMap = {}\r
                         if not FoundFlag :\r
                             # just pick the a value to determine whether is unicode string type\r
                             SkuValueMap = {}\r
-                            SkuObjList = DscPcdEntry.SkuInfoList.items()\r
+                            SkuObjList = list(DscPcdEntry.SkuInfoList.items())\r
                             DefaultSku = DscPcdEntry.SkuInfoList.get(TAB_DEFAULT)\r
                             if DefaultSku:\r
                                 defaultindex = SkuObjList.index((TAB_DEFAULT, DefaultSku))\r
                                 SkuObjList[0], SkuObjList[defaultindex] = SkuObjList[defaultindex], SkuObjList[0]\r
                             for (SkuName, Sku) in SkuObjList:\r
                             DefaultSku = DscPcdEntry.SkuInfoList.get(TAB_DEFAULT)\r
                             if DefaultSku:\r
                                 defaultindex = SkuObjList.index((TAB_DEFAULT, DefaultSku))\r
                                 SkuObjList[0], SkuObjList[defaultindex] = SkuObjList[defaultindex], SkuObjList[0]\r
                             for (SkuName, Sku) in SkuObjList:\r
-                                Sku.VpdOffset = Sku.VpdOffset.strip() \r
-                                \r
+                                Sku.VpdOffset = Sku.VpdOffset.strip()\r
+\r
                                 # Need to iterate DEC pcd information to get the value & datumtype\r
                                 for eachDec in self.PackageList:\r
                                     for DecPcd in eachDec.Pcds:\r
                                 # Need to iterate DEC pcd information to get the value & datumtype\r
                                 for eachDec in self.PackageList:\r
                                     for DecPcd in eachDec.Pcds:\r
@@ -1671,23 +1616,23 @@ class PlatformAutoGen(AutoGen):
                                             EdkLogger.warn("build", "Unreferenced vpd pcd used!",\r
                                                             File=self.MetaFile, \\r
                                                             ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \\r
                                             EdkLogger.warn("build", "Unreferenced vpd pcd used!",\r
                                                             File=self.MetaFile, \\r
                                                             ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \\r
-                                                            %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path))  \r
-                                                                                  \r
+                                                            %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path))\r
+\r
                                             DscPcdEntry.DatumType    = DecPcdEntry.DatumType\r
                                             DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue\r
                                             DscPcdEntry.TokenValue = DecPcdEntry.TokenValue\r
                                             DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName]\r
                                             # Only fix the value while no value provided in DSC file.\r
                                             if not Sku.DefaultValue:\r
                                             DscPcdEntry.DatumType    = DecPcdEntry.DatumType\r
                                             DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue\r
                                             DscPcdEntry.TokenValue = DecPcdEntry.TokenValue\r
                                             DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName]\r
                                             # Only fix the value while no value provided in DSC file.\r
                                             if not Sku.DefaultValue:\r
-                                                DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]].DefaultValue = DecPcdEntry.DefaultValue\r
-                                                                                                                    \r
+                                                DscPcdEntry.SkuInfoList[list(DscPcdEntry.SkuInfoList.keys())[0]].DefaultValue = DecPcdEntry.DefaultValue\r
+\r
                                 if DscPcdEntry not in self._DynamicPcdList:\r
                                     self._DynamicPcdList.append(DscPcdEntry)\r
                                 Sku.VpdOffset = Sku.VpdOffset.strip()\r
                                 PcdValue = Sku.DefaultValue\r
                                 if PcdValue == "":\r
                                     PcdValue  = DscPcdEntry.DefaultValue\r
                                 if DscPcdEntry not in self._DynamicPcdList:\r
                                     self._DynamicPcdList.append(DscPcdEntry)\r
                                 Sku.VpdOffset = Sku.VpdOffset.strip()\r
                                 PcdValue = Sku.DefaultValue\r
                                 if PcdValue == "":\r
                                     PcdValue  = DscPcdEntry.DefaultValue\r
-                                if Sku.VpdOffset != '*':\r
+                                if Sku.VpdOffset != TAB_STAR:\r
                                     if PcdValue.startswith("{"):\r
                                         Alignment = 8\r
                                     elif PcdValue.startswith("L"):\r
                                     if PcdValue.startswith("{"):\r
                                         Alignment = 8\r
                                     elif PcdValue.startswith("L"):\r
@@ -1710,8 +1655,8 @@ class PlatformAutoGen(AutoGen):
                                     SkuValueMap[PcdValue] = []\r
                                     VpdFile.Add(DscPcdEntry, SkuName, Sku.VpdOffset)\r
                                 SkuValueMap[PcdValue].append(Sku)\r
                                     SkuValueMap[PcdValue] = []\r
                                     VpdFile.Add(DscPcdEntry, SkuName, Sku.VpdOffset)\r
                                 SkuValueMap[PcdValue].append(Sku)\r
-                                if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":\r
-                                    NeedProcessVpdMapFile = True \r
+                                if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:\r
+                                    NeedProcessVpdMapFile = True\r
                             if DscPcdEntry.DatumType == TAB_VOID and PcdValue.startswith("L"):\r
                                 UnicodePcdArray.add(DscPcdEntry)\r
                             elif len(Sku.VariableName) > 0:\r
                             if DscPcdEntry.DatumType == TAB_VOID and PcdValue.startswith("L"):\r
                                 UnicodePcdArray.add(DscPcdEntry)\r
                             elif len(Sku.VariableName) > 0:\r
@@ -1723,7 +1668,7 @@ class PlatformAutoGen(AutoGen):
                             VpdSkuMap[DscPcd] = SkuValueMap\r
             if (self.Platform.FlashDefinition is None or self.Platform.FlashDefinition == '') and \\r
                VpdFile.GetCount() != 0:\r
                             VpdSkuMap[DscPcd] = SkuValueMap\r
             if (self.Platform.FlashDefinition is None or self.Platform.FlashDefinition == '') and \\r
                VpdFile.GetCount() != 0:\r
-                EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, \r
+                EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,\r
                                 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))\r
 \r
             if VpdFile.GetCount() != 0:\r
                                 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))\r
 \r
             if VpdFile.GetCount() != 0:\r
@@ -1731,6 +1676,12 @@ class PlatformAutoGen(AutoGen):
                 self.FixVpdOffset(VpdFile)\r
 \r
                 self.FixVpdOffset(self.UpdateNVStoreMaxSize(VpdFile))\r
                 self.FixVpdOffset(VpdFile)\r
 \r
                 self.FixVpdOffset(self.UpdateNVStoreMaxSize(VpdFile))\r
+                PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]\r
+                if PcdNvStoreDfBuffer:\r
+                    PcdName,PcdGuid = PcdNvStoreDfBuffer[0].TokenCName, PcdNvStoreDfBuffer[0].TokenSpaceGuidCName\r
+                    if (PcdName,PcdGuid) in VpdSkuMap:\r
+                        DefaultSku = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT)\r
+                        VpdSkuMap[(PcdName,PcdGuid)] = {DefaultSku.DefaultValue:[SkuObj for SkuObj in PcdNvStoreDfBuffer[0].SkuInfoList.values() ]}\r
 \r
                 # Process VPD map file generated by third party BPDG tool\r
                 if NeedProcessVpdMapFile:\r
 \r
                 # Process VPD map file generated by third party BPDG tool\r
                 if NeedProcessVpdMapFile:\r
@@ -1738,7 +1689,7 @@ class PlatformAutoGen(AutoGen):
                     if os.path.exists(VpdMapFilePath):\r
                         VpdFile.Read(VpdMapFilePath)\r
 \r
                     if os.path.exists(VpdMapFilePath):\r
                         VpdFile.Read(VpdMapFilePath)\r
 \r
-                        # Fixup "*" offset\r
+                        # Fixup TAB_STAR offset\r
                         for pcd in VpdSkuMap:\r
                             vpdinfo = VpdFile.GetVpdInfo(pcd)\r
                             if vpdinfo is None:\r
                         for pcd in VpdSkuMap:\r
                             vpdinfo = VpdFile.GetVpdInfo(pcd)\r
                             if vpdinfo is None:\r
@@ -1755,7 +1706,7 @@ class PlatformAutoGen(AutoGen):
             # Delete the DynamicPcdList At the last time enter into this function\r
             for Pcd in self._DynamicPcdList:\r
                 # just pick the a value to determine whether is unicode string type\r
             # Delete the DynamicPcdList At the last time enter into this function\r
             for Pcd in self._DynamicPcdList:\r
                 # just pick the a value to determine whether is unicode string type\r
-                Sku = Pcd.SkuInfoList.values()[0]\r
+                Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)\r
                 Sku.VpdOffset = Sku.VpdOffset.strip()\r
 \r
                 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
                 Sku.VpdOffset = Sku.VpdOffset.strip()\r
 \r
                 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
@@ -1778,11 +1729,11 @@ class PlatformAutoGen(AutoGen):
         for pcd in self._DynamicPcdList:\r
             if len(pcd.SkuInfoList) == 1:\r
                 for (SkuName, SkuId) in allskuset:\r
         for pcd in self._DynamicPcdList:\r
             if len(pcd.SkuInfoList) == 1:\r
                 for (SkuName, SkuId) in allskuset:\r
-                    if type(SkuId) in (str, unicode) and eval(SkuId) == 0 or SkuId == 0:\r
+                    if isinstance(SkuId, str) and eval(SkuId) == 0 or SkuId == 0:\r
                         continue\r
                     pcd.SkuInfoList[SkuName] = copy.deepcopy(pcd.SkuInfoList[TAB_DEFAULT])\r
                     pcd.SkuInfoList[SkuName].SkuId = SkuId\r
                         continue\r
                     pcd.SkuInfoList[SkuName] = copy.deepcopy(pcd.SkuInfoList[TAB_DEFAULT])\r
                     pcd.SkuInfoList[SkuName].SkuId = SkuId\r
-        self.AllPcdList = self._NonDynamicPcdList + self._DynamicPcdList\r
+                    pcd.SkuInfoList[SkuName].SkuIdName = SkuName\r
 \r
     def FixVpdOffset(self, VpdFile ):\r
         FvPath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY)\r
 \r
     def FixVpdOffset(self, VpdFile ):\r
         FvPath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY)\r
@@ -1810,336 +1761,333 @@ 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.")\r
 \r
     ## Return the platform build data object\r
                 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.")\r
 \r
     ## Return the platform build data object\r
-    def _GetPlatform(self):\r
-        if self._Platform is None:\r
-            self._Platform = self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]\r
-        return self._Platform\r
+    @cached_property\r
+    def Platform(self):\r
+        return self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]\r
 \r
     ## Return platform name\r
 \r
     ## Return platform name\r
-    def _GetName(self):\r
+    @cached_property\r
+    def Name(self):\r
         return self.Platform.PlatformName\r
 \r
     ## Return the meta file GUID\r
         return self.Platform.PlatformName\r
 \r
     ## Return the meta file GUID\r
-    def _GetGuid(self):\r
+    @cached_property\r
+    def Guid(self):\r
         return self.Platform.Guid\r
 \r
     ## Return the platform version\r
         return self.Platform.Guid\r
 \r
     ## Return the platform version\r
-    def _GetVersion(self):\r
+    @cached_property\r
+    def Version(self):\r
         return self.Platform.Version\r
 \r
     ## Return the FDF file name\r
         return self.Platform.Version\r
 \r
     ## Return the FDF file name\r
-    def _GetFdfFile(self):\r
-        if self._FdfFile is None:\r
-            if self.Workspace.FdfFile != "":\r
-                self._FdfFile= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)\r
-            else:\r
-                self._FdfFile = ''\r
-        return self._FdfFile\r
+    @cached_property\r
+    def FdfFile(self):\r
+        if self.Workspace.FdfFile:\r
+            RetVal= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)\r
+        else:\r
+            RetVal = ''\r
+        return RetVal\r
 \r
     ## Return the build output directory platform specifies\r
 \r
     ## Return the build output directory platform specifies\r
-    def _GetOutputDir(self):\r
+    @cached_property\r
+    def OutputDir(self):\r
         return self.Platform.OutputDirectory\r
 \r
     ## Return the directory to store all intermediate and final files built\r
         return self.Platform.OutputDirectory\r
 \r
     ## Return the directory to store all intermediate and final files built\r
-    def _GetBuildDir(self):\r
-        if self._BuildDir is None:\r
-            if os.path.isabs(self.OutputDir):\r
-                self._BuildDir = path.join(\r
-                                            path.abspath(self.OutputDir),\r
-                                            self.BuildTarget + "_" + self.ToolChain,\r
-                                            )\r
-            else:\r
-                self._BuildDir = path.join(\r
-                                            self.WorkspaceDir,\r
-                                            self.OutputDir,\r
-                                            self.BuildTarget + "_" + self.ToolChain,\r
-                                            )\r
-            GlobalData.gBuildDirectory = self._BuildDir\r
-        return self._BuildDir\r
+    @cached_property\r
+    def BuildDir(self):\r
+        if os.path.isabs(self.OutputDir):\r
+            GlobalData.gBuildDirectory = RetVal = path.join(\r
+                                        path.abspath(self.OutputDir),\r
+                                        self.BuildTarget + "_" + self.ToolChain,\r
+                                        )\r
+        else:\r
+            GlobalData.gBuildDirectory = RetVal = path.join(\r
+                                        self.WorkspaceDir,\r
+                                        self.OutputDir,\r
+                                        self.BuildTarget + "_" + self.ToolChain,\r
+                                        )\r
+        return RetVal\r
 \r
     ## Return directory of platform makefile\r
     #\r
     #   @retval     string  Makefile directory\r
     #\r
 \r
     ## Return directory of platform makefile\r
     #\r
     #   @retval     string  Makefile directory\r
     #\r
-    def _GetMakeFileDir(self):\r
-        if self._MakeFileDir is None:\r
-            self._MakeFileDir = path.join(self.BuildDir, self.Arch)\r
-        return self._MakeFileDir\r
+    @cached_property\r
+    def MakeFileDir(self):\r
+        return path.join(self.BuildDir, self.Arch)\r
 \r
     ## Return build command string\r
     #\r
     #   @retval     string  Build command string\r
     #\r
 \r
     ## Return build command string\r
     #\r
     #   @retval     string  Build command string\r
     #\r
-    def _GetBuildCommand(self):\r
-        if self._BuildCommand is None:\r
-            self._BuildCommand = []\r
-            if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:\r
-                self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"])\r
-                if "FLAGS" in self.ToolDefinition["MAKE"]:\r
-                    NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()\r
-                    if NewOption != '':\r
-                        self._BuildCommand += SplitOption(NewOption)\r
-                if "MAKE" in self.EdkIIBuildOption:\r
-                    if "FLAGS" in self.EdkIIBuildOption["MAKE"]:\r
-                        Flags = self.EdkIIBuildOption["MAKE"]["FLAGS"]\r
-                        if Flags.startswith('='):\r
-                            self._BuildCommand = [self._BuildCommand[0]] + [Flags[1:]]\r
-                        else:\r
-                            self._BuildCommand.append(Flags)\r
-        return self._BuildCommand\r
+    @cached_property\r
+    def BuildCommand(self):\r
+        RetVal = []\r
+        if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:\r
+            RetVal += _SplitOption(self.ToolDefinition["MAKE"]["PATH"])\r
+            if "FLAGS" in self.ToolDefinition["MAKE"]:\r
+                NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()\r
+                if NewOption != '':\r
+                    RetVal += _SplitOption(NewOption)\r
+            if "MAKE" in self.EdkIIBuildOption:\r
+                if "FLAGS" in self.EdkIIBuildOption["MAKE"]:\r
+                    Flags = self.EdkIIBuildOption["MAKE"]["FLAGS"]\r
+                    if Flags.startswith('='):\r
+                        RetVal = [RetVal[0]] + [Flags[1:]]\r
+                    else:\r
+                        RetVal.append(Flags)\r
+        return RetVal\r
 \r
     ## Get tool chain definition\r
     #\r
 \r
     ## Get tool chain definition\r
     #\r
-    #  Get each tool defition for given tool chain from tools_def.txt and platform\r
+    #  Get each tool definition for given tool chain from tools_def.txt and platform\r
     #\r
     #\r
-    def _GetToolDefinition(self):\r
-        if self._ToolDefinitions is None:\r
-            ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary\r
-            if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:\r
-                EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",\r
-                                ExtraData="[%s]" % self.MetaFile)\r
-            self._ToolDefinitions = {}\r
-            DllPathList = set()\r
-            for Def in ToolDefinition:\r
-                Target, Tag, Arch, Tool, Attr = Def.split("_")\r
-                if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:\r
-                    continue\r
+    @cached_property\r
+    def ToolDefinition(self):\r
+        ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary\r
+        if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:\r
+            EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",\r
+                            ExtraData="[%s]" % self.MetaFile)\r
+        RetVal = {}\r
+        DllPathList = set()\r
+        for Def in ToolDefinition:\r
+            Target, Tag, Arch, Tool, Attr = Def.split("_")\r
+            if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:\r
+                continue\r
 \r
 \r
-                Value = ToolDefinition[Def]\r
-                # don't record the DLL\r
-                if Attr == "DLL":\r
-                    DllPathList.add(Value)\r
-                    continue\r
+            Value = ToolDefinition[Def]\r
+            # don't record the DLL\r
+            if Attr == "DLL":\r
+                DllPathList.add(Value)\r
+                continue\r
 \r
 \r
-                if Tool not in self._ToolDefinitions:\r
-                    self._ToolDefinitions[Tool] = {}\r
-                self._ToolDefinitions[Tool][Attr] = Value\r
-\r
-            ToolsDef = ''\r
-            if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions:\r
-                if "FLAGS" not in self._ToolDefinitions["MAKE"]:\r
-                    self._ToolDefinitions["MAKE"]["FLAGS"] = ""\r
-                self._ToolDefinitions["MAKE"]["FLAGS"] += " -s"\r
-            MakeFlags = ''\r
-            for Tool in self._ToolDefinitions:\r
-                for Attr in self._ToolDefinitions[Tool]:\r
-                    Value = self._ToolDefinitions[Tool][Attr]\r
-                    if Tool in self.BuildOption and Attr in self.BuildOption[Tool]:\r
-                        # check if override is indicated\r
-                        if self.BuildOption[Tool][Attr].startswith('='):\r
-                            Value = self.BuildOption[Tool][Attr][1:]\r
-                        else:\r
-                            if Attr != 'PATH':\r
-                                Value += " " + self.BuildOption[Tool][Attr]\r
-                            else:\r
-                                Value = self.BuildOption[Tool][Attr]\r
-\r
-                    if Attr == "PATH":\r
-                        # Don't put MAKE definition in the file\r
-                        if Tool != "MAKE":\r
-                            ToolsDef += "%s = %s\n" % (Tool, Value)\r
-                    elif Attr != "DLL":\r
-                        # Don't put MAKE definition in the file\r
-                        if Tool == "MAKE":\r
-                            if Attr == "FLAGS":\r
-                                MakeFlags = Value\r
+            if Tool not in RetVal:\r
+                RetVal[Tool] = {}\r
+            RetVal[Tool][Attr] = Value\r
+\r
+        ToolsDef = ''\r
+        if GlobalData.gOptions.SilentMode and "MAKE" in RetVal:\r
+            if "FLAGS" not in RetVal["MAKE"]:\r
+                RetVal["MAKE"]["FLAGS"] = ""\r
+            RetVal["MAKE"]["FLAGS"] += " -s"\r
+        MakeFlags = ''\r
+        for Tool in RetVal:\r
+            for Attr in RetVal[Tool]:\r
+                Value = RetVal[Tool][Attr]\r
+                if Tool in self._BuildOptionWithToolDef(RetVal) and Attr in self._BuildOptionWithToolDef(RetVal)[Tool]:\r
+                    # check if override is indicated\r
+                    if self._BuildOptionWithToolDef(RetVal)[Tool][Attr].startswith('='):\r
+                        Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr][1:]\r
+                    else:\r
+                        if Attr != 'PATH':\r
+                            Value += " " + self._BuildOptionWithToolDef(RetVal)[Tool][Attr]\r
                         else:\r
                         else:\r
-                            ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)\r
-                ToolsDef += "\n"\r
+                            Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr]\r
+\r
+                if Attr == "PATH":\r
+                    # Don't put MAKE definition in the file\r
+                    if Tool != "MAKE":\r
+                        ToolsDef += "%s = %s\n" % (Tool, Value)\r
+                elif Attr != "DLL":\r
+                    # Don't put MAKE definition in the file\r
+                    if Tool == "MAKE":\r
+                        if Attr == "FLAGS":\r
+                            MakeFlags = Value\r
+                    else:\r
+                        ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)\r
+            ToolsDef += "\n"\r
 \r
 \r
-            SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)\r
-            for DllPath in DllPathList:\r
-                os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]\r
-            os.environ["MAKE_FLAGS"] = MakeFlags\r
+        SaveFileOnChange(self.ToolDefinitionFile, ToolsDef, False)\r
+        for DllPath in DllPathList:\r
+            os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]\r
+        os.environ["MAKE_FLAGS"] = MakeFlags\r
 \r
 \r
-        return self._ToolDefinitions\r
+        return RetVal\r
 \r
     ## Return the paths of tools\r
 \r
     ## Return the paths of tools\r
-    def _GetToolDefFile(self):\r
-        if self._ToolDefFile is None:\r
-            self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)\r
-        return self._ToolDefFile\r
+    @cached_property\r
+    def ToolDefinitionFile(self):\r
+        return os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)\r
 \r
     ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.\r
 \r
     ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.\r
-    def _GetToolChainFamily(self):\r
-        if self._ToolChainFamily is None:\r
-            ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
-            if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \\r
-               or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \\r
-               or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:\r
-                EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
-                                   % self.ToolChain)\r
-                self._ToolChainFamily = "MSFT"\r
-            else:\r
-                self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]\r
-        return self._ToolChainFamily\r
-\r
-    def _GetBuildRuleFamily(self):\r
-        if self._BuildRuleFamily is None:\r
-            ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
-            if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \\r
-               or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \\r
-               or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:\r
-                EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
-                                   % self.ToolChain)\r
-                self._BuildRuleFamily = "MSFT"\r
-            else:\r
-                self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]\r
-        return self._BuildRuleFamily\r
+    @cached_property\r
+    def ToolChainFamily(self):\r
+        ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
+        if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \\r
+           or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \\r
+           or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:\r
+            EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
+                               % self.ToolChain)\r
+            RetVal = TAB_COMPILER_MSFT\r
+        else:\r
+            RetVal = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]\r
+        return RetVal\r
+\r
+    @cached_property\r
+    def BuildRuleFamily(self):\r
+        ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
+        if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \\r
+           or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \\r
+           or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:\r
+            EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
+                               % self.ToolChain)\r
+            return TAB_COMPILER_MSFT\r
+\r
+        return ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]\r
 \r
     ## Return the build options specific for all modules in this platform\r
 \r
     ## Return the build options specific for all modules in this platform\r
-    def _GetBuildOptions(self):\r
-        if self._BuildOption is None:\r
-            self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)\r
-        return self._BuildOption\r
+    @cached_property\r
+    def BuildOption(self):\r
+        return self._ExpandBuildOption(self.Platform.BuildOptions)\r
+\r
+    def _BuildOptionWithToolDef(self, ToolDef):\r
+        return self._ExpandBuildOption(self.Platform.BuildOptions, ToolDef=ToolDef)\r
 \r
     ## Return the build options specific for EDK modules in this platform\r
 \r
     ## Return the build options specific for EDK modules in this platform\r
-    def _GetEdkBuildOptions(self):\r
-        if self._EdkBuildOption is None:\r
-            self._EdkBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)\r
-        return self._EdkBuildOption\r
+    @cached_property\r
+    def EdkBuildOption(self):\r
+        return self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)\r
 \r
     ## Return the build options specific for EDKII modules in this platform\r
 \r
     ## Return the build options specific for EDKII modules in this platform\r
-    def _GetEdkIIBuildOptions(self):\r
-        if self._EdkIIBuildOption is None:\r
-            self._EdkIIBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)\r
-        return self._EdkIIBuildOption\r
+    @cached_property\r
+    def EdkIIBuildOption(self):\r
+        return self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)\r
 \r
     ## Parse build_rule.txt in Conf Directory.\r
     #\r
     #   @retval     BuildRule object\r
     #\r
 \r
     ## Parse build_rule.txt in Conf Directory.\r
     #\r
     #   @retval     BuildRule object\r
     #\r
-    def _GetBuildRule(self):\r
-        if self._BuildRule is None:\r
-            BuildRuleFile = None\r
-            if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:\r
-                BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]\r
-            if not BuildRuleFile:\r
-                BuildRuleFile = gDefaultBuildRuleFile\r
-            self._BuildRule = BuildRule(BuildRuleFile)\r
-            if self._BuildRule._FileVersion == "":\r
-                self._BuildRule._FileVersion = AutoGenReqBuildRuleVerNum\r
-            else:\r
-                if self._BuildRule._FileVersion < AutoGenReqBuildRuleVerNum :\r
-                    # If Build Rule's version is less than the version number required by the tools, halting the build.\r
-                    EdkLogger.error("build", AUTOGEN_ERROR,\r
-                                    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])"\\r
-                                     % (self._BuildRule._FileVersion, AutoGenReqBuildRuleVerNum))\r
-\r
-        return self._BuildRule\r
+    @cached_property\r
+    def BuildRule(self):\r
+        BuildRuleFile = None\r
+        if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:\r
+            BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]\r
+        if not BuildRuleFile:\r
+            BuildRuleFile = gDefaultBuildRuleFile\r
+        RetVal = BuildRule(BuildRuleFile)\r
+        if RetVal._FileVersion == "":\r
+            RetVal._FileVersion = AutoGenReqBuildRuleVerNum\r
+        else:\r
+            if RetVal._FileVersion < AutoGenReqBuildRuleVerNum :\r
+                # If Build Rule's version is less than the version number required by the tools, halting the build.\r
+                EdkLogger.error("build", AUTOGEN_ERROR,\r
+                                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])"\\r
+                                 % (RetVal._FileVersion, AutoGenReqBuildRuleVerNum))\r
+        return RetVal\r
 \r
     ## Summarize the packages used by modules in this platform\r
 \r
     ## Summarize the packages used by modules in this platform\r
-    def _GetPackageList(self):\r
-        if self._PackageList is None:\r
-            self._PackageList = set()\r
-            for La in self.LibraryAutoGenList:\r
-                self._PackageList.update(La.DependentPackageList)\r
-            for Ma in self.ModuleAutoGenList:\r
-                self._PackageList.update(Ma.DependentPackageList)\r
-            #Collect package set information from INF of FDF\r
-            PkgSet = set()\r
-            for ModuleFile in self._AsBuildModuleList:\r
-                if ModuleFile in self.Platform.Modules:\r
-                    continue\r
-                ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]\r
-                PkgSet.update(ModuleData.Packages)\r
-            self._PackageList = list(self._PackageList) + list (PkgSet)\r
-        return self._PackageList\r
+    @cached_property\r
+    def PackageList(self):\r
+        RetVal = set()\r
+        for La in self.LibraryAutoGenList:\r
+            RetVal.update(La.DependentPackageList)\r
+        for Ma in self.ModuleAutoGenList:\r
+            RetVal.update(Ma.DependentPackageList)\r
+        #Collect package set information from INF of FDF\r
+        for ModuleFile in self._AsBuildModuleList:\r
+            if ModuleFile in self.Platform.Modules:\r
+                continue\r
+            ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]\r
+            RetVal.update(ModuleData.Packages)\r
+        return list(RetVal)\r
 \r
 \r
-    def _GetNonDynamicPcdDict(self):\r
-        if self._NonDynamicPcdDict:\r
-            return self._NonDynamicPcdDict\r
-        for Pcd in self.NonDynamicPcdList:\r
-            self._NonDynamicPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd\r
-        return self._NonDynamicPcdDict\r
+    @cached_property\r
+    def NonDynamicPcdDict(self):\r
+        return {(Pcd.TokenCName, Pcd.TokenSpaceGuidCName):Pcd for Pcd in self.NonDynamicPcdList}\r
 \r
     ## Get list of non-dynamic PCDs\r
 \r
     ## Get list of non-dynamic PCDs\r
-    def _GetNonDynamicPcdList(self):\r
-        if self._NonDynamicPcdList is None:\r
+    @property\r
+    def NonDynamicPcdList(self):\r
+        if not self._NonDynamicPcdList:\r
             self.CollectPlatformDynamicPcds()\r
         return self._NonDynamicPcdList\r
 \r
     ## Get list of dynamic PCDs\r
             self.CollectPlatformDynamicPcds()\r
         return self._NonDynamicPcdList\r
 \r
     ## Get list of dynamic PCDs\r
-    def _GetDynamicPcdList(self):\r
-        if self._DynamicPcdList is None:\r
+    @property\r
+    def DynamicPcdList(self):\r
+        if not self._DynamicPcdList:\r
             self.CollectPlatformDynamicPcds()\r
         return self._DynamicPcdList\r
 \r
     ## Generate Token Number for all PCD\r
             self.CollectPlatformDynamicPcds()\r
         return self._DynamicPcdList\r
 \r
     ## Generate Token Number for all PCD\r
-    def _GetPcdTokenNumbers(self):\r
-        if self._PcdTokenNumber is None:\r
-            self._PcdTokenNumber = OrderedDict()\r
-            TokenNumber = 1\r
-            #\r
-            # Make the Dynamic and DynamicEx PCD use within different TokenNumber area. \r
-            # Such as:\r
-            # \r
-            # Dynamic PCD:\r
-            # TokenNumber 0 ~ 10\r
-            # DynamicEx PCD:\r
-            # TokeNumber 11 ~ 20\r
-            #\r
-            for Pcd in self.DynamicPcdList:\r
-                if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:\r
-                    EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
-                    self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
-                    TokenNumber += 1\r
-\r
-            for Pcd in self.DynamicPcdList:\r
-                if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
-                    EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
-                    self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
-                    TokenNumber += 1\r
-\r
-            for Pcd in self.DynamicPcdList:\r
-                if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:\r
-                    EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
-                    self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
-                    TokenNumber += 1\r
-\r
-            for Pcd in self.DynamicPcdList:\r
-                if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
-                    EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
-                    self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
-                    TokenNumber += 1\r
-\r
-            for Pcd in self.NonDynamicPcdList:\r
-                self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
+    @cached_property\r
+    def PcdTokenNumber(self):\r
+        RetVal = OrderedDict()\r
+        TokenNumber = 1\r
+        #\r
+        # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.\r
+        # Such as:\r
+        #\r
+        # Dynamic PCD:\r
+        # TokenNumber 0 ~ 10\r
+        # DynamicEx PCD:\r
+        # TokeNumber 11 ~ 20\r
+        #\r
+        for Pcd in self.DynamicPcdList:\r
+            if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:\r
+                EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
+                RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
                 TokenNumber += 1\r
                 TokenNumber += 1\r
-        return self._PcdTokenNumber\r
 \r
 \r
-    ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform\r
-    def _GetAutoGenObjectList(self):\r
-        self._ModuleAutoGenList = []\r
-        self._LibraryAutoGenList = []\r
+        for Pcd in self.DynamicPcdList:\r
+            if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
+                EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
+                RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
+                TokenNumber += 1\r
+\r
+        for Pcd in self.DynamicPcdList:\r
+            if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:\r
+                EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
+                RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
+                TokenNumber += 1\r
+\r
+        for Pcd in self.DynamicPcdList:\r
+            if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
+                EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
+                RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
+                TokenNumber += 1\r
+\r
+        for Pcd in self.NonDynamicPcdList:\r
+            RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
+            TokenNumber += 1\r
+        return RetVal\r
+\r
+    @cached_property\r
+    def _MaList(self):\r
         for ModuleFile in self.Platform.Modules:\r
             Ma = ModuleAutoGen(\r
         for ModuleFile in self.Platform.Modules:\r
             Ma = ModuleAutoGen(\r
-                    self.Workspace,\r
-                    ModuleFile,\r
-                    self.BuildTarget,\r
-                    self.ToolChain,\r
-                    self.Arch,\r
-                    self.MetaFile\r
-                    )\r
-            if Ma not in self._ModuleAutoGenList:\r
-                self._ModuleAutoGenList.append(Ma)\r
-            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
+                  self.Workspace,\r
+                  ModuleFile,\r
+                  self.BuildTarget,\r
+                  self.ToolChain,\r
+                  self.Arch,\r
+                  self.MetaFile\r
+                  )\r
+            self.Platform.Modules[ModuleFile].M = Ma\r
+        return [x.M for x in self.Platform.Modules.values()]\r
 \r
     ## Summarize ModuleAutoGen objects of all modules to be built for this platform\r
 \r
     ## Summarize ModuleAutoGen objects of all modules to be built for this platform\r
-    def _GetModuleAutoGenList(self):\r
-        if self._ModuleAutoGenList is None:\r
-            self._GetAutoGenObjectList()\r
-        return self._ModuleAutoGenList\r
+    @cached_property\r
+    def ModuleAutoGenList(self):\r
+        RetVal = []\r
+        for Ma in self._MaList:\r
+            if Ma not in RetVal:\r
+                RetVal.append(Ma)\r
+        return RetVal\r
 \r
     ## Summarize ModuleAutoGen objects of all libraries to be built for this platform\r
 \r
     ## Summarize ModuleAutoGen objects of all libraries to be built for this platform\r
-    def _GetLibraryAutoGenList(self):\r
-        if self._LibraryAutoGenList is None:\r
-            self._GetAutoGenObjectList()\r
-        return self._LibraryAutoGenList\r
+    @cached_property\r
+    def LibraryAutoGenList(self):\r
+        RetVal = []\r
+        for Ma in self._MaList:\r
+            for La in Ma.LibraryAutoGenList:\r
+                if La not in RetVal:\r
+                    RetVal.append(La)\r
+                if Ma not in La.ReferenceModules:\r
+                    La.ReferenceModules.append(Ma)\r
+        return RetVal\r
 \r
     ## Test if a module is supported by the platform\r
     #\r
 \r
     ## Test if a module is supported by the platform\r
     #\r
@@ -2175,8 +2123,8 @@ class PlatformAutoGen(AutoGen):
 \r
     ## Override PCD setting (type, value, ...)\r
     #\r
 \r
     ## Override PCD setting (type, value, ...)\r
     #\r
-    #   @param  ToPcd       The PCD to be overrided\r
-    #   @param  FromPcd     The PCD overrideing from\r
+    #   @param  ToPcd       The PCD to be overridden\r
+    #   @param  FromPcd     The PCD overriding from\r
     #\r
     def _OverridePcd(self, ToPcd, FromPcd, Module="", Msg="", Library=""):\r
         #\r
     #\r
     def _OverridePcd(self, ToPcd, FromPcd, Module="", Msg="", Library=""):\r
         #\r
@@ -2217,10 +2165,12 @@ class PlatformAutoGen(AutoGen):
                 ToPcd.DatumType = FromPcd.DatumType\r
             if FromPcd.SkuInfoList:\r
                 ToPcd.SkuInfoList = FromPcd.SkuInfoList\r
                 ToPcd.DatumType = FromPcd.DatumType\r
             if FromPcd.SkuInfoList:\r
                 ToPcd.SkuInfoList = FromPcd.SkuInfoList\r
+            if FromPcd.UserDefinedDefaultStoresFlag:\r
+                ToPcd.UserDefinedDefaultStoresFlag = FromPcd.UserDefinedDefaultStoresFlag\r
             # Add Flexible PCD format parse\r
             if ToPcd.DefaultValue:\r
                 try:\r
             # Add Flexible PCD format parse\r
             if ToPcd.DefaultValue:\r
                 try:\r
-                    ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self._GuidDict)(True)\r
+                    ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self.Workspace._GuidDict)(True)\r
                 except BadExpression as Value:\r
                     EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),\r
                                         File=self.MetaFile)\r
                 except BadExpression as Value:\r
                     EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),\r
                                         File=self.MetaFile)\r
@@ -2233,6 +2183,7 @@ class PlatformAutoGen(AutoGen):
             ToPcd.validateranges = FromPcd.validateranges\r
             ToPcd.validlists = FromPcd.validlists\r
             ToPcd.expressions = FromPcd.expressions\r
             ToPcd.validateranges = FromPcd.validateranges\r
             ToPcd.validlists = FromPcd.validlists\r
             ToPcd.expressions = FromPcd.expressions\r
+            ToPcd.CustomAttribute = FromPcd.CustomAttribute\r
 \r
         if FromPcd is not None and ToPcd.DatumType == TAB_VOID and not ToPcd.MaxDatumSize:\r
             EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \\r
 \r
         if FromPcd is not None and ToPcd.DatumType == TAB_VOID and not ToPcd.MaxDatumSize:\r
             EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \\r
@@ -2260,7 +2211,7 @@ class PlatformAutoGen(AutoGen):
 \r
     ## Apply PCD setting defined platform to a module\r
     #\r
 \r
     ## Apply PCD setting defined platform to a module\r
     #\r
-    #   @param  Module  The module from which the PCD setting will be overrided\r
+    #   @param  Module  The module from which the PCD setting will be overridden\r
     #\r
     #   @retval PCD_list    The list PCDs with settings from platform\r
     #\r
     #\r
     #   @retval PCD_list    The list PCDs with settings from platform\r
     #\r
@@ -2295,6 +2246,13 @@ class PlatformAutoGen(AutoGen):
         if Module in self.Platform.Modules:\r
             PlatformModule = self.Platform.Modules[str(Module)]\r
             for Key  in PlatformModule.Pcds:\r
         if Module in self.Platform.Modules:\r
             PlatformModule = self.Platform.Modules[str(Module)]\r
             for Key  in PlatformModule.Pcds:\r
+                if GlobalData.BuildOptionPcd:\r
+                    for pcd in GlobalData.BuildOptionPcd:\r
+                        (TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue, _) = pcd\r
+                        if (TokenCName, TokenSpaceGuidCName) == Key and FieldName =="":\r
+                            PlatformModule.Pcds[Key].DefaultValue = pcdvalue\r
+                            PlatformModule.Pcds[Key].PcdValueFromComm = pcdvalue\r
+                            break\r
                 Flag = False\r
                 if Key in Pcds:\r
                     ToPcd = Pcds[Key]\r
                 Flag = False\r
                 if Key in Pcds:\r
                     ToPcd = Pcds[Key]\r
@@ -2321,44 +2279,9 @@ class PlatformAutoGen(AutoGen):
                     Pcd.MaxDatumSize = str(len(Value.split(',')))\r
                 else:\r
                     Pcd.MaxDatumSize = str(len(Value) - 1)\r
                     Pcd.MaxDatumSize = str(len(Value.split(',')))\r
                 else:\r
                     Pcd.MaxDatumSize = str(len(Value) - 1)\r
-        return Pcds.values()\r
+        return list(Pcds.values())\r
 \r
 \r
-    ## Resolve library names to library modules\r
-    #\r
-    # (for Edk.x modules)\r
-    #\r
-    #   @param  Module  The module from which the library names will be resolved\r
-    #\r
-    #   @retval library_list    The list of library modules\r
-    #\r
-    def ResolveLibraryReference(self, Module):\r
-        EdkLogger.verbose("")\r
-        EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))\r
-        LibraryConsumerList = [Module]\r
-\r
-        # "CompilerStub" is a must for Edk modules\r
-        if Module.Libraries:\r
-            Module.Libraries.append("CompilerStub")\r
-        LibraryList = []\r
-        while len(LibraryConsumerList) > 0:\r
-            M = LibraryConsumerList.pop()\r
-            for LibraryName in M.Libraries:\r
-                Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']\r
-                if Library is None:\r
-                    for Key in self.Platform.LibraryClasses.data:\r
-                        if LibraryName.upper() == Key.upper():\r
-                            Library = self.Platform.LibraryClasses[Key, ':dummy:']\r
-                            break\r
-                    if Library is None:\r
-                        EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),\r
-                            ExtraData="\t%s [%s]" % (str(Module), self.Arch))\r
-                        continue\r
 \r
 \r
-                if Library not in LibraryList:\r
-                    LibraryList.append(Library)\r
-                    LibraryConsumerList.append(Library)\r
-                    EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))\r
-        return LibraryList\r
 \r
     ## Calculate the priority value of the build option\r
     #\r
 \r
     ## Calculate the priority value of the build option\r
     #\r
@@ -2369,15 +2292,15 @@ class PlatformAutoGen(AutoGen):
     def CalculatePriorityValue(self, Key):\r
         Target, ToolChain, Arch, CommandType, Attr = Key.split('_')\r
         PriorityValue = 0x11111\r
     def CalculatePriorityValue(self, Key):\r
         Target, ToolChain, Arch, CommandType, Attr = Key.split('_')\r
         PriorityValue = 0x11111\r
-        if Target == "*":\r
+        if Target == TAB_STAR:\r
             PriorityValue &= 0x01111\r
             PriorityValue &= 0x01111\r
-        if ToolChain == "*":\r
+        if ToolChain == TAB_STAR:\r
             PriorityValue &= 0x10111\r
             PriorityValue &= 0x10111\r
-        if Arch == "*":\r
+        if Arch == TAB_STAR:\r
             PriorityValue &= 0x11011\r
             PriorityValue &= 0x11011\r
-        if CommandType == "*":\r
+        if CommandType == TAB_STAR:\r
             PriorityValue &= 0x11101\r
             PriorityValue &= 0x11101\r
-        if Attr == "*":\r
+        if Attr == TAB_STAR:\r
             PriorityValue &= 0x11110\r
 \r
         return self.PrioList["0x%0.5x" % PriorityValue]\r
             PriorityValue &= 0x11110\r
 \r
         return self.PrioList["0x%0.5x" % PriorityValue]\r
@@ -2386,10 +2309,16 @@ class PlatformAutoGen(AutoGen):
     ## Expand * in build option key\r
     #\r
     #   @param  Options     Options to be expanded\r
     ## Expand * in build option key\r
     #\r
     #   @param  Options     Options to be expanded\r
+    #   @param  ToolDef     Use specified ToolDef instead of full version.\r
+    #                       This is needed during initialization to prevent\r
+    #                       infinite recursion betweeh BuildOptions,\r
+    #                       ToolDefinition, and this function.\r
     #\r
     #   @retval options     Options expanded\r
     #\r
     #   @retval options     Options expanded\r
-    #      \r
-    def _ExpandBuildOption(self, Options, ModuleStyle=None):\r
+    #\r
+    def _ExpandBuildOption(self, Options, ModuleStyle=None, ToolDef=None):\r
+        if not ToolDef:\r
+            ToolDef = self.ToolDefinition\r
         BuildOptions = {}\r
         FamilyMatch  = False\r
         FamilyIsNull = True\r
         BuildOptions = {}\r
         FamilyMatch  = False\r
         FamilyIsNull = True\r
@@ -2406,20 +2335,20 @@ class PlatformAutoGen(AutoGen):
             if (Key[0] == self.BuildRuleFamily and\r
                 (ModuleStyle is None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):\r
                 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')\r
             if (Key[0] == self.BuildRuleFamily and\r
                 (ModuleStyle is None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):\r
                 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')\r
-                if (Target == self.BuildTarget or Target == "*") and\\r
-                    (ToolChain == self.ToolChain or ToolChain == "*") and\\r
-                    (Arch == self.Arch or Arch == "*") and\\r
+                if (Target == self.BuildTarget or Target == TAB_STAR) and\\r
+                    (ToolChain == self.ToolChain or ToolChain == TAB_STAR) and\\r
+                    (Arch == self.Arch or Arch == TAB_STAR) and\\r
                     Options[Key].startswith("="):\r
 \r
                     if OverrideList.get(Key[1]) is not None:\r
                         OverrideList.pop(Key[1])\r
                     OverrideList[Key[1]] = Options[Key]\r
                     Options[Key].startswith("="):\r
 \r
                     if OverrideList.get(Key[1]) is not None:\r
                         OverrideList.pop(Key[1])\r
                     OverrideList[Key[1]] = Options[Key]\r
-        \r
+\r
         #\r
         #\r
-        # Use the highest priority value. \r
+        # Use the highest priority value.\r
         #\r
         if (len(OverrideList) >= 2):\r
         #\r
         if (len(OverrideList) >= 2):\r
-            KeyList = OverrideList.keys()\r
+            KeyList = list(OverrideList.keys())\r
             for Index in range(len(KeyList)):\r
                 NowKey = KeyList[Index]\r
                 Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")\r
             for Index in range(len(KeyList)):\r
                 NowKey = KeyList[Index]\r
                 Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")\r
@@ -2427,13 +2356,13 @@ class PlatformAutoGen(AutoGen):
                     NextKey = KeyList[Index1 + Index + 1]\r
                     #\r
                     # Compare two Key, if one is included by another, choose the higher priority one\r
                     NextKey = KeyList[Index1 + Index + 1]\r
                     #\r
                     # Compare two Key, if one is included by another, choose the higher priority one\r
-                    #                    \r
+                    #\r
                     Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")\r
                     Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")\r
-                    if (Target1 == Target2 or Target1 == "*" or Target2 == "*") and\\r
-                        (ToolChain1 == ToolChain2 or ToolChain1 == "*" or ToolChain2 == "*") and\\r
-                        (Arch1 == Arch2 or Arch1 == "*" or Arch2 == "*") and\\r
-                        (CommandType1 == CommandType2 or CommandType1 == "*" or CommandType2 == "*") and\\r
-                        (Attr1 == Attr2 or Attr1 == "*" or Attr2 == "*"):\r
+                    if (Target1 == Target2 or Target1 == TAB_STAR or Target2 == TAB_STAR) and\\r
+                        (ToolChain1 == ToolChain2 or ToolChain1 == TAB_STAR or ToolChain2 == TAB_STAR) and\\r
+                        (Arch1 == Arch2 or Arch1 == TAB_STAR or Arch2 == TAB_STAR) and\\r
+                        (CommandType1 == CommandType2 or CommandType1 == TAB_STAR or CommandType2 == TAB_STAR) and\\r
+                        (Attr1 == Attr2 or Attr1 == TAB_STAR or Attr2 == TAB_STAR):\r
 \r
                         if self.CalculatePriorityValue(NowKey) > self.CalculatePriorityValue(NextKey):\r
                             if Options.get((self.BuildRuleFamily, NextKey)) is not None:\r
 \r
                         if self.CalculatePriorityValue(NowKey) > self.CalculatePriorityValue(NextKey):\r
                             if Options.get((self.BuildRuleFamily, NextKey)) is not None:\r
@@ -2441,7 +2370,7 @@ class PlatformAutoGen(AutoGen):
                         else:\r
                             if Options.get((self.BuildRuleFamily, NowKey)) is not None:\r
                                 Options.pop((self.BuildRuleFamily, NowKey))\r
                         else:\r
                             if Options.get((self.BuildRuleFamily, NowKey)) is not None:\r
                                 Options.pop((self.BuildRuleFamily, NowKey))\r
-                                                           \r
+\r
         for Key in Options:\r
             if ModuleStyle is not None and len (Key) > 2:\r
                 # Check Module style is EDK or EDKII.\r
         for Key in Options:\r
             if ModuleStyle is not None and len (Key) > 2:\r
                 # Check Module style is EDK or EDKII.\r
@@ -2453,18 +2382,18 @@ class PlatformAutoGen(AutoGen):
             Family = Key[0]\r
             Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
             # if tool chain family doesn't match, skip it\r
             Family = Key[0]\r
             Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
             # if tool chain family doesn't match, skip it\r
-            if Tool in self.ToolDefinition and Family != "":\r
+            if Tool in ToolDef and Family != "":\r
                 FamilyIsNull = False\r
                 FamilyIsNull = False\r
-                if self.ToolDefinition[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":\r
-                    if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:\r
+                if ToolDef[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":\r
+                    if Family != ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:\r
                         continue\r
                         continue\r
-                elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:\r
+                elif Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:\r
                     continue\r
                 FamilyMatch = True\r
             # expand any wildcard\r
                     continue\r
                 FamilyMatch = True\r
             # expand any wildcard\r
-            if Target == "*" or Target == self.BuildTarget:\r
-                if Tag == "*" or Tag == self.ToolChain:\r
-                    if Arch == "*" or Arch == self.Arch:\r
+            if Target == TAB_STAR or Target == self.BuildTarget:\r
+                if Tag == TAB_STAR or Tag == self.ToolChain:\r
+                    if Arch == TAB_STAR or Arch == self.Arch:\r
                         if Tool not in BuildOptions:\r
                             BuildOptions[Tool] = {}\r
                         if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
                         if Tool not in BuildOptions:\r
                             BuildOptions[Tool] = {}\r
                         if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
@@ -2490,16 +2419,16 @@ class PlatformAutoGen(AutoGen):
             Family = Key[0]\r
             Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
             # if tool chain family doesn't match, skip it\r
             Family = Key[0]\r
             Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
             # if tool chain family doesn't match, skip it\r
-            if Tool not in self.ToolDefinition or Family == "":\r
+            if Tool not in ToolDef or Family == "":\r
                 continue\r
             # option has been added before\r
                 continue\r
             # option has been added before\r
-            if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:\r
+            if Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:\r
                 continue\r
 \r
             # expand any wildcard\r
                 continue\r
 \r
             # expand any wildcard\r
-            if Target == "*" or Target == self.BuildTarget:\r
-                if Tag == "*" or Tag == self.ToolChain:\r
-                    if Arch == "*" or Arch == self.Arch:\r
+            if Target == TAB_STAR or Target == self.BuildTarget:\r
+                if Tag == TAB_STAR or Tag == self.ToolChain:\r
+                    if Arch == TAB_STAR or Arch == self.Arch:\r
                         if Tool not in BuildOptions:\r
                             BuildOptions[Tool] = {}\r
                         if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
                         if Tool not in BuildOptions:\r
                             BuildOptions[Tool] = {}\r
                         if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
@@ -2514,18 +2443,14 @@ class PlatformAutoGen(AutoGen):
 \r
     ## Append build options in platform to a module\r
     #\r
 \r
     ## Append build options in platform to a module\r
     #\r
-    #   @param  Module  The module to which the build options will be appened\r
+    #   @param  Module  The module to which the build options will be appended\r
     #\r
     #   @retval options     The options appended with build options in platform\r
     #\r
     def ApplyBuildOption(self, Module):\r
         # Get the different options for the different style module\r
     #\r
     #   @retval options     The options appended with build options in platform\r
     #\r
     def ApplyBuildOption(self, Module):\r
         # Get the different options for the different style module\r
-        if Module.AutoGenVersion < 0x00010005:\r
-            PlatformOptions = self.EdkBuildOption\r
-            ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDK_NAME, Module.ModuleType)\r
-        else:\r
-            PlatformOptions = self.EdkIIBuildOption\r
-            ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)\r
+        PlatformOptions = self.EdkIIBuildOption\r
+        ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)\r
         ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)\r
         ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)\r
         if Module in self.Platform.Modules:\r
         ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)\r
         ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)\r
         if Module in self.Platform.Modules:\r
@@ -2541,9 +2466,9 @@ class PlatformAutoGen(AutoGen):
                     if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
                         BuildRuleOrder = Options[Tool][Attr]\r
 \r
                     if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
                         BuildRuleOrder = Options[Tool][Attr]\r
 \r
-        AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() +\r
-                       PlatformModuleOptions.keys() + ModuleTypeOptions.keys() +\r
-                       self.ToolDefinition.keys())\r
+        AllTools = set(list(ModuleOptions.keys()) + list(PlatformOptions.keys()) +\r
+                       list(PlatformModuleOptions.keys()) + list(ModuleTypeOptions.keys()) +\r
+                       list(self.ToolDefinition.keys()))\r
         BuildOptions = defaultdict(lambda: defaultdict(str))\r
         for Tool in AllTools:\r
             for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
         BuildOptions = defaultdict(lambda: defaultdict(str))\r
         for Tool in AllTools:\r
             for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
@@ -2565,43 +2490,8 @@ class PlatformAutoGen(AutoGen):
                         else:\r
                             BuildOptions[Tool][Attr] = mws.handleWsMacro(Value)\r
 \r
                         else:\r
                             BuildOptions[Tool][Attr] = mws.handleWsMacro(Value)\r
 \r
-        if Module.AutoGenVersion < 0x00010005 and self.Workspace.UniFlag is not None:\r
-            #\r
-            # Override UNI flag only for EDK module.\r
-            #\r
-            BuildOptions['BUILD']['FLAGS'] = self.Workspace.UniFlag\r
         return BuildOptions, BuildRuleOrder\r
 \r
         return BuildOptions, BuildRuleOrder\r
 \r
-    Platform            = property(_GetPlatform)\r
-    Name                = property(_GetName)\r
-    Guid                = property(_GetGuid)\r
-    Version             = property(_GetVersion)\r
-\r
-    OutputDir           = property(_GetOutputDir)\r
-    BuildDir            = property(_GetBuildDir)\r
-    MakeFileDir         = property(_GetMakeFileDir)\r
-    FdfFile             = property(_GetFdfFile)\r
-\r
-    PcdTokenNumber      = property(_GetPcdTokenNumbers)    # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber\r
-    DynamicPcdList      = property(_GetDynamicPcdList)    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
-    NonDynamicPcdList   = property(_GetNonDynamicPcdList)    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
-    NonDynamicPcdDict   = property(_GetNonDynamicPcdDict)\r
-    PackageList         = property(_GetPackageList)\r
-\r
-    ToolDefinition      = property(_GetToolDefinition)    # toolcode : tool path\r
-    ToolDefinitionFile  = property(_GetToolDefFile)    # toolcode : lib path\r
-    ToolChainFamily     = property(_GetToolChainFamily)\r
-    BuildRuleFamily     = property(_GetBuildRuleFamily)\r
-    BuildOption         = property(_GetBuildOptions)    # toolcode : option\r
-    EdkBuildOption      = property(_GetEdkBuildOptions)   # edktoolcode : option\r
-    EdkIIBuildOption    = property(_GetEdkIIBuildOptions) # edkiitoolcode : option\r
-\r
-    BuildCommand        = property(_GetBuildCommand)\r
-    BuildRule           = property(_GetBuildRule)\r
-    ModuleAutoGenList   = property(_GetModuleAutoGenList)\r
-    LibraryAutoGenList  = property(_GetLibraryAutoGenList)\r
-    GenFdsCommand       = property(_GenFdsCommand)\r
-\r
 #\r
 # extend lists contained in a dictionary with lists stored in another dictionary\r
 # if CopyToDict is not derived from DefaultDict(list) then this may raise exception\r
 #\r
 # extend lists contained in a dictionary with lists stored in another dictionary\r
 # if CopyToDict is not derived from DefaultDict(list) then this may raise exception\r
@@ -2610,6 +2500,11 @@ def ExtendCopyDictionaryLists(CopyToDict, CopyFromDict):
     for Key in CopyFromDict:\r
         CopyToDict[Key].extend(CopyFromDict[Key])\r
 \r
     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
 \r
 ## ModuleAutoGen class\r
 #\r
@@ -2620,26 +2515,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
 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
-            super(ModuleAutoGen, self).__init__(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
+        if not hasattr(self, "_Init"):\r
             self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args)\r
             self._Init = True\r
 \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
     #\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
         # 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
-            \r
+        return super(ModuleAutoGen, cls).__new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
+\r
     ## Initialize ModuleAutoGen\r
     #\r
     #   @param      Workspace           EdkIIWorkspaceBuild object\r
     ## Initialize ModuleAutoGen\r
     #\r
     #   @param      Workspace           EdkIIWorkspaceBuild object\r
@@ -2655,25 +2546,18 @@ class ModuleAutoGen(AutoGen):
 \r
         self.Workspace = Workspace\r
         self.WorkspaceDir = Workspace.WorkspaceDir\r
 \r
         self.Workspace = Workspace\r
         self.WorkspaceDir = Workspace.WorkspaceDir\r
-        self._GuidDict = Workspace._GuidDict\r
         self.MetaFile = ModuleFile\r
         self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)\r
 \r
         self.SourceDir = self.MetaFile.SubDir\r
         self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir)\r
 \r
         self.MetaFile = ModuleFile\r
         self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)\r
 \r
         self.SourceDir = self.MetaFile.SubDir\r
         self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir)\r
 \r
-        self.SourceOverrideDir = None\r
-        # use overrided path defined in DSC file\r
-        if self.MetaFile.Key in GlobalData.gOverrideDir:\r
-            self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]\r
-\r
         self.ToolChain = Toolchain\r
         self.BuildTarget = Target\r
         self.Arch = Arch\r
         self.ToolChainFamily = self.PlatformInfo.ToolChainFamily\r
         self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily\r
 \r
         self.ToolChain = Toolchain\r
         self.BuildTarget = Target\r
         self.Arch = Arch\r
         self.ToolChainFamily = self.PlatformInfo.ToolChainFamily\r
         self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily\r
 \r
-        self.IsMakeFileCreated = False\r
         self.IsCodeFileCreated = False\r
         self.IsAsBuiltInfCreated = False\r
         self.DepexGenerated = False\r
         self.IsCodeFileCreated = False\r
         self.IsAsBuiltInfCreated = False\r
         self.DepexGenerated = False\r
@@ -2682,87 +2566,45 @@ class ModuleAutoGen(AutoGen):
         self.BuildRuleOrder = None\r
         self.BuildTime      = 0\r
 \r
         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._PcdComments = OrderedListDict()\r
-        self._GuidList                = None\r
-        self._GuidsUsedByPcd = None\r
         self._GuidComments = OrderedListDict()\r
         self._GuidComments = OrderedListDict()\r
-        self._ProtocolList            = None\r
         self._ProtocolComments = OrderedListDict()\r
         self._ProtocolComments = OrderedListDict()\r
-        self._PpiList                 = None\r
         self._PpiComments = OrderedListDict()\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._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
         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
         self.ConstPcd                  = {}\r
 \r
+\r
     def __repr__(self):\r
         return "%s [%s]" % (self.MetaFile, self.Arch)\r
 \r
     # Get FixedAtBuild Pcds of this Module\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
         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 _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
         BaseName = self.Name\r
         for Module in self.PlatformInfo.ModuleAutoGenList:\r
             if Module.MetaFile == self.MetaFile:\r
@@ -2775,68 +2617,63 @@ class ModuleAutoGen(AutoGen):
         return BaseName\r
 \r
     # Macros could be used in build_rule.txt (also Makefile)\r
         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
 \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.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]\r
 \r
     ## Return the module name\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
         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 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
     ## 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
         #\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
+        # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the real path\r
         # in DSC. The overridden GUID can be retrieved from file name\r
         #\r
         if os.path.basename(self.MetaFile.File) != os.path.basename(self.MetaFile.Path):\r
         # in DSC. The overridden GUID can be retrieved from file name\r
         #\r
         if os.path.basename(self.MetaFile.File) != os.path.basename(self.MetaFile.Path):\r
@@ -2847,111 +2684,104 @@ class ModuleAutoGen(AutoGen):
         return self.Module.Guid\r
 \r
     ## Return the module version\r
         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
         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
         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
         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
         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
         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
         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
 \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
         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
                                     self.PlatformInfo.BuildDir,\r
                                     self.Arch,\r
                                     self.SourceDir,\r
                                     self.MetaFile.BaseName\r
-                                    )\r
-            CreateDirectory(self._BuildDir)\r
-        return self._BuildDir\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
+            ))\r
+\r
+    ## Return the directory to store the intermediate object files of the module\r
+    @cached_property\r
+    def OutputDir(self):\r
+        return _MakeDir((self.BuildDir, "OUTPUT"))\r
 \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
+    ## 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 module\r
+    @cached_property\r
+    def DebugDir(self):\r
+        return _MakeDir((self.BuildDir, "DEBUG"))\r
 \r
     ## Return the path of custom file\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
-                    File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])\r
-                self._CustomMakefile[MakeType] = File\r
-        return self._CustomMakefile\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
+            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
 \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
         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
         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
         PackageList = []\r
         for M in [self.Module] + self.DependentLibraryList:\r
             for Package in M.Packages:\r
@@ -2959,10 +2789,10 @@ class ModuleAutoGen(AutoGen):
                     continue\r
                 PackageList.append(Package)\r
         return PackageList\r
                     continue\r
                 PackageList.append(Package)\r
         return PackageList\r
-    \r
+\r
     ## Get the depex string\r
     #\r
     ## Get the depex string\r
     #\r
-    # @return : a string contain all depex expresion.\r
+    # @return : a string contain all depex expression.\r
     def _GetDepexExpresionString(self):\r
         DepexStr = ''\r
         DepexList = []\r
     def _GetDepexExpresionString(self):\r
         DepexStr = ''\r
         DepexList = []\r
@@ -2972,11 +2802,11 @@ class ModuleAutoGen(AutoGen):
         for M in [self.Module] + self.DependentLibraryList:\r
             Filename = M.MetaFile.Path\r
             InfObj = InfSectionParser.InfSectionParser(Filename)\r
         for M in [self.Module] + self.DependentLibraryList:\r
             Filename = M.MetaFile.Path\r
             InfObj = InfSectionParser.InfSectionParser(Filename)\r
-            DepexExpresionList = InfObj.GetDepexExpresionList()\r
-            for DepexExpresion in DepexExpresionList:\r
-                for key in DepexExpresion:\r
+            DepexExpressionList = InfObj.GetDepexExpresionList()\r
+            for DepexExpression in DepexExpressionList:\r
+                for key in DepexExpression:\r
                     Arch, ModuleType = key\r
                     Arch, ModuleType = key\r
-                    DepexExpr = [x for x in DepexExpresion[key] if not str(x).startswith('#')]\r
+                    DepexExpr = [x for x in DepexExpression[key] if not str(x).startswith('#')]\r
                     # the type of build module is USER_DEFINED.\r
                     # All different DEPEX section tags would be copied into the As Built INF file\r
                     # and there would be separate DEPEX section tags\r
                     # the type of build module is USER_DEFINED.\r
                     # All different DEPEX section tags would be copied into the As Built INF file\r
                     # and there would be separate DEPEX section tags\r
@@ -2988,7 +2818,7 @@ class ModuleAutoGen(AutoGen):
                           (Arch.upper() == self.Arch.upper() and \\r
                           ModuleType.upper() in [TAB_ARCH_COMMON, self.ModuleType.upper()]):\r
                             DepexList.append({(Arch, ModuleType): DepexExpr})\r
                           (Arch.upper() == self.Arch.upper() and \\r
                           ModuleType.upper() in [TAB_ARCH_COMMON, self.ModuleType.upper()]):\r
                             DepexList.append({(Arch, ModuleType): DepexExpr})\r
-        \r
+\r
         #the type of build module is USER_DEFINED.\r
         if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:\r
             for Depex in DepexList:\r
         #the type of build module is USER_DEFINED.\r
         if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:\r
             for Depex in DepexList:\r
@@ -2999,7 +2829,7 @@ class ModuleAutoGen(AutoGen):
             if not DepexStr:\r
                 return '[Depex.%s]\n' % self.Arch\r
             return DepexStr\r
             if not DepexStr:\r
                 return '[Depex.%s]\n' % self.Arch\r
             return DepexStr\r
-        \r
+\r
         #the type of build module not is USER_DEFINED.\r
         Count = 0\r
         for Depex in DepexList:\r
         #the type of build module not is USER_DEFINED.\r
         Count = 0\r
         for Depex in DepexList:\r
@@ -3019,78 +2849,90 @@ class ModuleAutoGen(AutoGen):
         if not DepexStr:\r
             return '[Depex.%s]\n' % self.Arch\r
         return '[Depex.%s]\n#  ' % self.Arch + DepexStr\r
         if not DepexStr:\r
             return '[Depex.%s]\n' % self.Arch\r
         return '[Depex.%s]\n#  ' % self.Arch + DepexStr\r
-    \r
+\r
     ## Merge dependency expression\r
     #\r
     #   @retval     list    The token list of the dependency expression after parsed\r
     #\r
     ## Merge dependency expression\r
     #\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
+    @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
 \r
-            self._DepexDict[self.ModuleType] = []\r
-\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
-                        DepexList.extend(D)\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
+        DepexList = []\r
+        #\r
+        # Append depex from dependent libraries, if not "BEFORE", "AFTER" expression\r
+        #\r
+        for M in [self.Module] + self.DependentLibraryList:\r
+            Inherited = False\r
+            for D in M.Depex[self.Arch, self.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
+                        FixedVoidTypePcds = {}\r
+                        if item in self.FixedVoidTypePcds:\r
+                            FixedVoidTypePcds = self.FixedVoidTypePcds\r
+                        elif M in self.PlatformInfo.LibraryAutoGenList:\r
+                            Index = self.PlatformInfo.LibraryAutoGenList.index(M)\r
+                            FixedVoidTypePcds = self.PlatformInfo.LibraryAutoGenList[Index].FixedVoidTypePcds\r
+                        if item not in FixedVoidTypePcds:\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 = FixedVoidTypePcds[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.ModuleType:DepexList}\r
 \r
     ## Merge dependency expression\r
     #\r
     #   @retval     list    The token list of the dependency expression after parsed\r
     #\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 DepexExpressionDict(self):\r
+        if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:\r
+            return {}\r
 \r
 \r
-            self._DepexExpressionDict[self.ModuleType] = ''\r
+        DepexExpressionString = ''\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, self.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
 \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
+        return {self.ModuleType:DepexExpressionString}\r
 \r
     # Get the tiano core user extension, it is contain dependent library.\r
     # @retval: a list contain tiano core userextension.\r
 \r
     # Get the tiano core user extension, it is contain dependent library.\r
     # @retval: a list contain tiano core userextension.\r
@@ -3120,7 +2962,8 @@ class ModuleAutoGen(AutoGen):
     #\r
     #   @retval     list    The list of specification defined in module file\r
     #\r
     #\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
         return self.Module.Specification\r
 \r
     ## Tool option for the module build\r
@@ -3128,114 +2971,108 @@ class ModuleAutoGen(AutoGen):
     #   @param      PlatformInfo    The object of PlatformBuildInfo\r
     #   @retval     dict            The dict containing valid options\r
     #\r
     #   @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
 \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 (TAB_COMPILER_MSFT):\r
+            BuildOptIncludeRegEx = gBuildOptIncludePatternMsft\r
+        elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):\r
+            BuildOptIncludeRegEx = gBuildOptIncludePatternOther\r
+        else:\r
             #\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
             #\r
-            if self.PlatformInfo.ToolChainFamily in ('MSFT'):\r
-                BuildOptIncludeRegEx = gBuildOptIncludePatternMsft\r
-            elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):\r
-                BuildOptIncludeRegEx = gBuildOptIncludePatternOther\r
+            return []\r
+\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.ToolChainFamily != 'RVCT':\r
+                IncPathList = [NormPath(Path, self.Macros) for Path in BuildOptIncludeRegEx.findall(FlagOption)]\r
             else:\r
                 #\r
             else:\r
                 #\r
-                # New ToolChainFamily, don't known whether there is option to specify include directories\r
+                # RVCT may specify a list of directory seperated by commas\r
                 #\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
-                \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
+                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
+            #\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 GlobalData.gDisableIncludePathCheck == False:\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
 \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
-\r
-                \r
-                BuildOptionIncPathList += IncPathList\r
-            \r
-            self._BuildOptionIncPathList = BuildOptionIncPathList\r
-        \r
-        return self._BuildOptionIncPathList\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
     ## 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 needed" % (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 = {"", TAB_STAR, self.ToolChain}\r
+        ToolChainFamilySet = {"", TAB_STAR, 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
 \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:\r
+                self.IncludePathList.insert(0, F.Dir)\r
+            RetVal.append(F)\r
 \r
 \r
-            self._MatchBuildRuleOrder(self._SourceFileList)\r
+        self._MatchBuildRuleOrder(RetVal)\r
 \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
 \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
         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
+                key = SingleFile.Path.rsplit(SingleFile.Ext,1)[0]\r
                 if key in Order_Dict:\r
                     Order_Dict[key].append(SingleFile.Ext)\r
                 else:\r
                 if key in Order_Dict:\r
                     Order_Dict[key].append(SingleFile.Ext)\r
                 else:\r
@@ -3247,38 +3084,26 @@ class ModuleAutoGen(AutoGen):
                 Order_Dict[F].sort(key=lambda i: self.BuildRuleOrder.index(i))\r
                 for Ext in Order_Dict[F][1:]:\r
                     RemoveList.append(F + Ext)\r
                 Order_Dict[F].sort(key=lambda i: self.BuildRuleOrder.index(i))\r
                 for Ext in Order_Dict[F][1:]:\r
                     RemoveList.append(F + Ext)\r
-                   \r
+\r
         for item in RemoveList:\r
             FileList.remove(item)\r
 \r
         return FileList\r
 \r
     ## Return the list of unicode files\r
         for item in RemoveList:\r
             FileList.remove(item)\r
 \r
         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
 \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
 \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
 \r
     ## Return a list of files which can be built from binary\r
     #\r
@@ -3286,50 +3111,52 @@ class ModuleAutoGen(AutoGen):
     #\r
     #   @retval     list            The list of files which can be built later\r
     #\r
     #\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, TAB_STAR] 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
                 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 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
         SubDirectory = os.path.join(self.OutputDir, File.SubDir)\r
         if not os.path.exists(SubDirectory):\r
             CreateDirectory(SubDirectory)\r
@@ -3340,7 +3167,7 @@ class ModuleAutoGen(AutoGen):
         #\r
         # Make sure to get build rule order value\r
         #\r
         #\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
 \r
         while Index < len(SourceList):\r
             Source = SourceList[Index]\r
@@ -3349,7 +3176,7 @@ class ModuleAutoGen(AutoGen):
             if Source != File:\r
                 CreateDirectory(Source.Dir)\r
 \r
             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
                 # Skip all files that are not binary libraries\r
                 if not self.IsLibrary:\r
                     continue\r
@@ -3396,230 +3223,209 @@ class ModuleAutoGen(AutoGen):
             LastTarget = Target\r
             FileType = TAB_UNKNOWN_FILE\r
 \r
             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
         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
 \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
 \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
         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
         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
         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
         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
         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
-\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
+        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() != b"":\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() != b"":\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 implicitly used by this module\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
+        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
 \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
 \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
 \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
     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
     ## 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
 \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
 \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
+        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.OriginalPath.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
 \r
     ## Get HII EX PCDs which maybe used by VFR\r
     #\r
@@ -3664,7 +3470,7 @@ class ModuleAutoGen(AutoGen):
                 Guid = gEfiVarStoreGuidPattern.search(Content, Pos)\r
                 if not Guid:\r
                     break\r
                 Guid = gEfiVarStoreGuidPattern.search(Content, Pos)\r
                 if not Guid:\r
                     break\r
-                NameArray = ConvertStringToByteArray('L"' + Name.group(1) + '"')\r
+                NameArray = _ConvertStringToByteArray('L"' + Name.group(1) + '"')\r
                 NameGuids.add((NameArray, GuidStructureStringToGuidString(Guid.group(1))))\r
                 Pos = Content.find('efivarstore', Name.end())\r
         if not NameGuids:\r
                 NameGuids.add((NameArray, GuidStructureStringToGuidString(Guid.group(1))))\r
                 Pos = Content.find('efivarstore', Name.end())\r
         if not NameGuids:\r
@@ -3677,7 +3483,7 @@ class ModuleAutoGen(AutoGen):
                 Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList, self.MetaFile.Path)\r
                 if not Value:\r
                     continue\r
                 Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList, self.MetaFile.Path)\r
                 if not Value:\r
                     continue\r
-                Name = ConvertStringToByteArray(SkuInfo.VariableName)\r
+                Name = _ConvertStringToByteArray(SkuInfo.VariableName)\r
                 Guid = GuidStructureStringToGuidString(Value)\r
                 if (Name, Guid) in NameGuids and Pcd not in HiiExPcds:\r
                     HiiExPcds.append(Pcd)\r
                 Guid = GuidStructureStringToGuidString(Value)\r
                 if (Name, Guid) in NameGuids and Pcd not in HiiExPcds:\r
                     HiiExPcds.append(Pcd)\r
@@ -3690,12 +3496,12 @@ class ModuleAutoGen(AutoGen):
         for SourceFile in self.Module.Sources:\r
             if SourceFile.Type.upper() == ".VFR" :\r
                 #\r
         for SourceFile in self.Module.Sources:\r
             if SourceFile.Type.upper() == ".VFR" :\r
                 #\r
-                # search the .map file to find the offset of vfr binary in the PE32+/TE file. \r
+                # search the .map file to find the offset of vfr binary in the PE32+/TE file.\r
                 #\r
                 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")\r
             elif SourceFile.Type.upper() == ".UNI" :\r
                 #\r
                 #\r
                 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")\r
             elif SourceFile.Type.upper() == ".UNI" :\r
                 #\r
-                # search the .map file to find the offset of Uni strings binary in the PE32+/TE file. \r
+                # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.\r
                 #\r
                 VfrUniBaseName["UniOffsetName"] = (self.Name + "Strings")\r
 \r
                 #\r
                 VfrUniBaseName["UniOffsetName"] = (self.Name + "Strings")\r
 \r
@@ -3703,7 +3509,7 @@ class ModuleAutoGen(AutoGen):
             return None\r
         MapFileName = os.path.join(self.OutputDir, self.Name + ".map")\r
         EfiFileName = os.path.join(self.OutputDir, self.Name + ".efi")\r
             return None\r
         MapFileName = os.path.join(self.OutputDir, self.Name + ".map")\r
         EfiFileName = os.path.join(self.OutputDir, self.Name + ".efi")\r
-        VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, VfrUniBaseName.values())\r
+        VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, list(VfrUniBaseName.values()))\r
         if not VfrUniOffsetList:\r
             return None\r
 \r
         if not VfrUniOffsetList:\r
             return None\r
 \r
@@ -3716,7 +3522,7 @@ class ModuleAutoGen(AutoGen):
             EdkLogger.error("build", FILE_OPEN_FAILURE, "File open failed for %s" % UniVfrOffsetFileName, None)\r
 \r
         # Use a instance of BytesIO to cache data\r
             EdkLogger.error("build", FILE_OPEN_FAILURE, "File open failed for %s" % UniVfrOffsetFileName, None)\r
 \r
         # Use a instance of BytesIO to cache data\r
-        fStringIO = BytesIO('')\r
+        fStringIO = BytesIO()\r
 \r
         for Item in VfrUniOffsetList:\r
             if (Item[0].find("Strings") != -1):\r
 \r
         for Item in VfrUniOffsetList:\r
             if (Item[0].find("Strings") != -1):\r
@@ -3725,9 +3531,8 @@ class ModuleAutoGen(AutoGen):
                 # GUID + Offset\r
                 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }\r
                 #\r
                 # GUID + Offset\r
                 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }\r
                 #\r
-                UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]\r
-                UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]\r
-                fStringIO.write(''.join(UniGuid))            \r
+                UniGuid = b'\xe0\xc5\x13\x89\xf63\x86M\x9b\xf1C\xef\x89\xfc\x06f'\r
+                fStringIO.write(UniGuid)\r
                 UniValue = pack ('Q', int (Item[1], 16))\r
                 fStringIO.write (UniValue)\r
             else:\r
                 UniValue = pack ('Q', int (Item[1], 16))\r
                 fStringIO.write (UniValue)\r
             else:\r
@@ -3736,15 +3541,14 @@ class ModuleAutoGen(AutoGen):
                 # GUID + Offset\r
                 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };\r
                 #\r
                 # GUID + Offset\r
                 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };\r
                 #\r
-                VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]\r
-                VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]\r
-                fStringIO.write(''.join(VfrGuid))                   \r
+                VfrGuid = b'\xb4|\xbc\xd0Gj_I\xaa\x11q\x07F\xda\x06\xa2'\r
+                fStringIO.write(VfrGuid)\r
                 VfrValue = pack ('Q', int (Item[1], 16))\r
                 fStringIO.write (VfrValue)\r
         #\r
         # write data into file.\r
         #\r
                 VfrValue = pack ('Q', int (Item[1], 16))\r
                 fStringIO.write (VfrValue)\r
         #\r
         # write data into file.\r
         #\r
-        try :  \r
+        try :\r
             fInputfile.write (fStringIO.getvalue())\r
         except:\r
             EdkLogger.error("build", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the "\r
             fInputfile.write (fStringIO.getvalue())\r
         except:\r
             EdkLogger.error("build", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the "\r
@@ -3764,15 +3568,11 @@ class ModuleAutoGen(AutoGen):
 \r
         if self.IsAsBuiltInfCreated:\r
             return\r
 \r
         if self.IsAsBuiltInfCreated:\r
             return\r
-            \r
-        # Skip the following code for EDK I inf\r
-        if self.AutoGenVersion < 0x00010005:\r
-            return\r
-            \r
+\r
         # Skip the following code for libraries\r
         if self.IsLibrary:\r
             return\r
         # Skip the following code for libraries\r
         if self.IsLibrary:\r
             return\r
-            \r
+\r
         # Skip the following code for modules with no source files\r
         if not self.SourceFileList:\r
             return\r
         # Skip the following code for modules with no source files\r
         if not self.SourceFileList:\r
             return\r
@@ -3780,7 +3580,7 @@ class ModuleAutoGen(AutoGen):
         # Skip the following code for modules without any binary files\r
         if self.BinaryFileList:\r
             return\r
         # Skip the following code for modules without any binary files\r
         if self.BinaryFileList:\r
             return\r
-            \r
+\r
         ### TODO: How to handles mixed source and binary modules\r
 \r
         # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries\r
         ### TODO: How to handles mixed source and binary modules\r
 \r
         # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries\r
@@ -3800,9 +3600,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
                     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
             # 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
@@ -3903,6 +3702,10 @@ class ModuleAutoGen(AutoGen):
                 AsBuiltInfDict['binary_item'].append('PE32|' + self.Name + '.efi')\r
             else:\r
                 AsBuiltInfDict['binary_item'].append('BIN|' + File)\r
                 AsBuiltInfDict['binary_item'].append('PE32|' + self.Name + '.efi')\r
             else:\r
                 AsBuiltInfDict['binary_item'].append('BIN|' + File)\r
+        if not self.DepexGenerated:\r
+            DepexFile = os.path.join(self.OutputDir, self.Name + '.depex')\r
+            if os.path.exists(DepexFile):\r
+                self.DepexGenerated = True\r
         if self.DepexGenerated:\r
             self.OutputFile.add(self.Name + '.depex')\r
             if self.ModuleType in [SUP_MODULE_PEIM]:\r
         if self.DepexGenerated:\r
             self.OutputFile.add(self.Name + '.depex')\r
             if self.ModuleType in [SUP_MODULE_PEIM]:\r
@@ -3999,7 +3802,7 @@ class ModuleAutoGen(AutoGen):
                         Padding = '0x00, '\r
                         if Unicode:\r
                             Padding = Padding * 2\r
                         Padding = '0x00, '\r
                         if Unicode:\r
                             Padding = Padding * 2\r
-                            ArraySize = ArraySize / 2\r
+                            ArraySize = ArraySize // 2\r
                         if ArraySize < (len(PcdValue) + 1):\r
                             if Pcd.MaxSizeUserSet:\r
                                 EdkLogger.error("build", AUTOGEN_ERROR,\r
                         if ArraySize < (len(PcdValue) + 1):\r
                             if Pcd.MaxSizeUserSet:\r
                                 EdkLogger.error("build", AUTOGEN_ERROR,\r
@@ -4054,7 +3857,7 @@ class ModuleAutoGen(AutoGen):
                             UsageIndex = Index\r
                             break\r
                 if UsageIndex != -1:\r
                             UsageIndex = Index\r
                             break\r
                 if UsageIndex != -1:\r
-                    PcdCommentList[UsageIndex] = '## %s %s %s' % (UsageStr, HiiInfo, PcdCommentList[UsageIndex].replace(UsageStr, '')) \r
+                    PcdCommentList[UsageIndex] = '## %s %s %s' % (UsageStr, HiiInfo, PcdCommentList[UsageIndex].replace(UsageStr, ''))\r
                 else:\r
                     PcdCommentList.append('## UNDEFINED ' + HiiInfo)\r
             PcdComments = '\n  '.join(PcdCommentList)\r
                 else:\r
                     PcdCommentList.append('## UNDEFINED ' + HiiInfo)\r
             PcdComments = '\n  '.join(PcdCommentList)\r
@@ -4069,7 +3872,7 @@ class ModuleAutoGen(AutoGen):
         # Generated LibraryClasses section in comments.\r
         for Library in self.LibraryAutoGenList:\r
             AsBuiltInfDict['libraryclasses_item'].append(Library.MetaFile.File.replace('\\', '/'))\r
         # Generated LibraryClasses section in comments.\r
         for Library in self.LibraryAutoGenList:\r
             AsBuiltInfDict['libraryclasses_item'].append(Library.MetaFile.File.replace('\\', '/'))\r
-        \r
+\r
         # Generated UserExtensions TianoCore section.\r
         # All tianocore user extensions are copied.\r
         UserExtStr = ''\r
         # Generated UserExtensions TianoCore section.\r
         # All tianocore user extensions are copied.\r
         UserExtStr = ''\r
@@ -4081,29 +3884,30 @@ class ModuleAutoGen(AutoGen):
         AsBuiltInfDict['userextension_tianocore_item'] = UserExtStr\r
 \r
         # Generated depex expression section in comments.\r
         AsBuiltInfDict['userextension_tianocore_item'] = UserExtStr\r
 \r
         # Generated depex expression section in comments.\r
-        DepexExpresion = self._GetDepexExpresionString()\r
-        AsBuiltInfDict['depexsection_item'] = DepexExpresion if DepexExpresion else ''\r
-        \r
+        DepexExpression = self._GetDepexExpresionString()\r
+        AsBuiltInfDict['depexsection_item'] = DepexExpression if DepexExpression else ''\r
+\r
         AsBuiltInf = TemplateString()\r
         AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))\r
         AsBuiltInf = TemplateString()\r
         AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))\r
-        \r
+\r
         SaveFileOnChange(os.path.join(self.OutputDir, self.Name + '.inf'), str(AsBuiltInf), False)\r
         SaveFileOnChange(os.path.join(self.OutputDir, self.Name + '.inf'), str(AsBuiltInf), False)\r
-        \r
+\r
         self.IsAsBuiltInfCreated = True\r
         if GlobalData.gBinCacheDest:\r
             self.CopyModuleToCache()\r
 \r
     def CopyModuleToCache(self):\r
         self.IsAsBuiltInfCreated = True\r
         if GlobalData.gBinCacheDest:\r
             self.CopyModuleToCache()\r
 \r
     def CopyModuleToCache(self):\r
-        FileDir = path.join(GlobalData.gBinCacheDest, self.Arch, self.SourceDir, self.MetaFile.BaseName)\r
+        FileDir = path.join(GlobalData.gBinCacheDest, self.PlatformInfo.OutputDir, self.BuildTarget + "_" + self.ToolChain, self.Arch, self.SourceDir, self.MetaFile.BaseName)\r
         CreateDirectory (FileDir)\r
         HashFile = path.join(self.BuildDir, self.Name + '.hash')\r
         CreateDirectory (FileDir)\r
         HashFile = path.join(self.BuildDir, self.Name + '.hash')\r
-        ModuleFile = path.join(self.OutputDir, self.Name + '.inf')\r
         if os.path.exists(HashFile):\r
             shutil.copy2(HashFile, FileDir)\r
         if os.path.exists(HashFile):\r
             shutil.copy2(HashFile, FileDir)\r
-        if os.path.exists(ModuleFile):\r
-            shutil.copy2(ModuleFile, FileDir)\r
+        if not self.IsLibrary:\r
+            ModuleFile = path.join(self.OutputDir, self.Name + '.inf')\r
+            if os.path.exists(ModuleFile):\r
+                shutil.copy2(ModuleFile, FileDir)\r
         if not self.OutputFile:\r
         if not self.OutputFile:\r
-            Ma = self.Workspace.BuildDatabase[PathClass(ModuleFile), self.Arch, self.BuildTarget, self.ToolChain]\r
+            Ma = self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]\r
             self.OutputFile = Ma.Binaries\r
         if self.OutputFile:\r
             for File in self.OutputFile:\r
             self.OutputFile = Ma.Binaries\r
         if self.OutputFile:\r
             for File in self.OutputFile:\r
@@ -4111,17 +3915,27 @@ class ModuleAutoGen(AutoGen):
                 if not os.path.isabs(File):\r
                     File = os.path.join(self.OutputDir, File)\r
                 if os.path.exists(File):\r
                 if not os.path.isabs(File):\r
                     File = os.path.join(self.OutputDir, File)\r
                 if os.path.exists(File):\r
-                    shutil.copy2(File, FileDir)\r
+                    sub_dir = os.path.relpath(File, self.OutputDir)\r
+                    destination_file = os.path.join(FileDir, sub_dir)\r
+                    destination_dir = os.path.dirname(destination_file)\r
+                    CreateDirectory(destination_dir)\r
+                    shutil.copy2(File, destination_dir)\r
 \r
     def AttemptModuleCacheCopy(self):\r
 \r
     def AttemptModuleCacheCopy(self):\r
+        # If library or Module is binary do not skip by hash\r
         if self.IsBinaryModule:\r
             return False\r
         if self.IsBinaryModule:\r
             return False\r
-        FileDir = path.join(GlobalData.gBinCacheSource, self.Arch, self.SourceDir, self.MetaFile.BaseName)\r
+        # .inc is contains binary information so do not skip by hash as well\r
+        for f_ext in self.SourceFileList:\r
+            if '.inc' in str(f_ext):\r
+                return False\r
+        FileDir = path.join(GlobalData.gBinCacheSource, self.PlatformInfo.OutputDir, self.BuildTarget + "_" + self.ToolChain, self.Arch, self.SourceDir, self.MetaFile.BaseName)\r
         HashFile = path.join(FileDir, self.Name + '.hash')\r
         if os.path.exists(HashFile):\r
             f = open(HashFile, 'r')\r
             CacheHash = f.read()\r
             f.close()\r
         HashFile = path.join(FileDir, self.Name + '.hash')\r
         if os.path.exists(HashFile):\r
             f = open(HashFile, 'r')\r
             CacheHash = f.read()\r
             f.close()\r
+            self.GenModuleHash()\r
             if GlobalData.gModuleHash[self.Arch][self.Name]:\r
                 if CacheHash == GlobalData.gModuleHash[self.Arch][self.Name]:\r
                     for root, dir, files in os.walk(FileDir):\r
             if GlobalData.gModuleHash[self.Arch][self.Name]:\r
                 if CacheHash == GlobalData.gModuleHash[self.Arch][self.Name]:\r
                     for root, dir, files in os.walk(FileDir):\r
@@ -4130,7 +3944,11 @@ class ModuleAutoGen(AutoGen):
                                 shutil.copy2(HashFile, self.BuildDir)\r
                             else:\r
                                 File = path.join(root, f)\r
                                 shutil.copy2(HashFile, self.BuildDir)\r
                             else:\r
                                 File = path.join(root, f)\r
-                                shutil.copy2(File, self.OutputDir)\r
+                                sub_dir = os.path.relpath(File, FileDir)\r
+                                destination_file = os.path.join(self.OutputDir, sub_dir)\r
+                                destination_dir = os.path.dirname(destination_file)\r
+                                CreateDirectory(destination_dir)\r
+                                shutil.copy2(File, destination_dir)\r
                     if self.Name == "PcdPeim" or self.Name == "PcdDxe":\r
                         CreatePcdDatabaseCode(self, TemplateString(), TemplateString())\r
                     return True\r
                     if self.Name == "PcdPeim" or self.Name == "PcdDxe":\r
                         CreatePcdDatabaseCode(self, TemplateString(), TemplateString())\r
                     return True\r
@@ -4141,13 +3959,31 @@ class ModuleAutoGen(AutoGen):
     #   @param      CreateLibraryMakeFile   Flag indicating if or not the makefiles of\r
     #                                       dependent libraries will be created\r
     #\r
     #   @param      CreateLibraryMakeFile   Flag indicating if or not the makefiles of\r
     #                                       dependent libraries will be created\r
     #\r
+    @cached_class_function\r
     def CreateMakeFile(self, CreateLibraryMakeFile=True, GenFfsList = []):\r
     def CreateMakeFile(self, CreateLibraryMakeFile=True, GenFfsList = []):\r
+        # nest this function inside it's only caller.\r
+        def CreateTimeStamp():\r
+            FileSet = {self.MetaFile.Path}\r
+\r
+            for SourceFile in self.Module.Sources:\r
+                FileSet.add (SourceFile.Path)\r
+\r
+            for Lib in self.DependentLibraryList:\r
+                FileSet.add (Lib.MetaFile.Path)\r
+\r
+            for f in self.AutoGenDepSet:\r
+                FileSet.add (f.Path)\r
+\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
         # Ignore generating makefile when it is a binary module\r
         if self.IsBinaryModule:\r
             return\r
 \r
         # Ignore generating makefile when it is a binary module\r
         if self.IsBinaryModule:\r
             return\r
 \r
-        if self.IsMakeFileCreated:\r
-            return\r
         self.GenFfsList = GenFfsList\r
         if not self.IsLibrary and CreateLibraryMakeFile:\r
             for LibraryAutoGen in self.LibraryAutoGenList:\r
         self.GenFfsList = GenFfsList\r
         if not self.IsLibrary and CreateLibraryMakeFile:\r
             for LibraryAutoGen in self.LibraryAutoGenList:\r
@@ -4167,8 +4003,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
             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.IsMakeFileCreated = True\r
+        CreateTimeStamp()\r
 \r
     def CopyBinaryFiles(self):\r
         for File in self.Module.Binaries:\r
 \r
     def CopyBinaryFiles(self):\r
         for File in self.Module.Binaries:\r
@@ -4205,17 +4040,10 @@ class ModuleAutoGen(AutoGen):
 \r
         for File in self.AutoGenFileList:\r
             if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):\r
 \r
         for File in self.AutoGenFileList:\r
             if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):\r
-                #Ignore Edk AutoGen.c\r
-                if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':\r
-                        continue\r
-\r
                 AutoGenList.append(str(File))\r
             else:\r
                 IgoredAutoGenList.append(str(File))\r
 \r
                 AutoGenList.append(str(File))\r
             else:\r
                 IgoredAutoGenList.append(str(File))\r
 \r
-        # Skip the following code for EDK I inf\r
-        if self.AutoGenVersion < 0x00010005:\r
-            return\r
 \r
         for ModuleType in self.DepexList:\r
             # Ignore empty [depex] section or [depex] section for SUP_MODULE_USER_DEFINED module\r
 \r
         for ModuleType in self.DepexList:\r
             # Ignore empty [depex] section or [depex] section for SUP_MODULE_USER_DEFINED module\r
@@ -4247,11 +4075,11 @@ class ModuleAutoGen(AutoGen):
         return AutoGenList\r
 \r
     ## Summarize the ModuleAutoGen objects of all libraries used by this module\r
         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
                         self.Workspace,\r
                         Library.MetaFile,\r
                         self.BuildTarget,\r
@@ -4259,71 +4087,110 @@ class ModuleAutoGen(AutoGen):
                         self.Arch,\r
                         self.PlatformInfo.MetaFile\r
                         )\r
                         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
 \r
     def GenModuleHash(self):\r
+        # Initialize a dictionary for each arch type\r
         if self.Arch not in GlobalData.gModuleHash:\r
             GlobalData.gModuleHash[self.Arch] = {}\r
         if self.Arch not in GlobalData.gModuleHash:\r
             GlobalData.gModuleHash[self.Arch] = {}\r
+\r
+        # Early exit if module or library has been hashed and is in memory\r
+        if self.Name in GlobalData.gModuleHash[self.Arch]:\r
+            return GlobalData.gModuleHash[self.Arch][self.Name].encode('utf-8')\r
+\r
+        # Initialze hash object\r
         m = hashlib.md5()\r
         m = hashlib.md5()\r
+\r
         # Add Platform level hash\r
         # Add Platform level hash\r
-        m.update(GlobalData.gPlatformHash)\r
+        m.update(GlobalData.gPlatformHash.encode('utf-8'))\r
+\r
         # Add Package level hash\r
         if self.DependentPackageList:\r
             for Pkg in sorted(self.DependentPackageList, key=lambda x: x.PackageName):\r
         # Add Package level hash\r
         if self.DependentPackageList:\r
             for Pkg in sorted(self.DependentPackageList, key=lambda x: x.PackageName):\r
-                if Pkg.PackageName in GlobalData.gPackageHash[self.Arch]:\r
-                    m.update(GlobalData.gPackageHash[self.Arch][Pkg.PackageName])\r
+                if Pkg.PackageName in GlobalData.gPackageHash:\r
+                    m.update(GlobalData.gPackageHash[Pkg.PackageName].encode('utf-8'))\r
 \r
         # Add Library hash\r
         if self.LibraryAutoGenList:\r
             for Lib in sorted(self.LibraryAutoGenList, key=lambda x: x.Name):\r
                 if Lib.Name not in GlobalData.gModuleHash[self.Arch]:\r
                     Lib.GenModuleHash()\r
 \r
         # Add Library hash\r
         if self.LibraryAutoGenList:\r
             for Lib in sorted(self.LibraryAutoGenList, key=lambda x: x.Name):\r
                 if Lib.Name not in GlobalData.gModuleHash[self.Arch]:\r
                     Lib.GenModuleHash()\r
-                m.update(GlobalData.gModuleHash[self.Arch][Lib.Name])\r
+                m.update(GlobalData.gModuleHash[self.Arch][Lib.Name].encode('utf-8'))\r
 \r
         # Add Module self\r
 \r
         # Add Module self\r
-        f = open(str(self.MetaFile), 'r')\r
+        f = open(str(self.MetaFile), 'rb')\r
         Content = f.read()\r
         f.close()\r
         m.update(Content)\r
         Content = f.read()\r
         f.close()\r
         m.update(Content)\r
+\r
         # Add Module's source files\r
         if self.SourceFileList:\r
             for File in sorted(self.SourceFileList, key=lambda x: str(x)):\r
         # Add Module's source files\r
         if self.SourceFileList:\r
             for File in sorted(self.SourceFileList, key=lambda x: str(x)):\r
-                f = open(str(File), 'r')\r
+                f = open(str(File), 'rb')\r
                 Content = f.read()\r
                 f.close()\r
                 m.update(Content)\r
 \r
                 Content = f.read()\r
                 f.close()\r
                 m.update(Content)\r
 \r
-        ModuleHashFile = path.join(self.BuildDir, self.Name + ".hash")\r
-        if self.Name not in GlobalData.gModuleHash[self.Arch]:\r
-            GlobalData.gModuleHash[self.Arch][self.Name] = m.hexdigest()\r
-        if GlobalData.gBinCacheSource:\r
-            if self.AttemptModuleCacheCopy():\r
-                return False\r
-        return SaveFileOnChange(ModuleHashFile, m.hexdigest(), True)\r
+        GlobalData.gModuleHash[self.Arch][self.Name] = m.hexdigest()\r
+\r
+        return GlobalData.gModuleHash[self.Arch][self.Name].encode('utf-8')\r
 \r
     ## Decide whether we can skip the ModuleAutoGen process\r
     def CanSkipbyHash(self):\r
 \r
     ## Decide whether we can skip the ModuleAutoGen process\r
     def CanSkipbyHash(self):\r
-        if GlobalData.gUseHashCache:\r
-            return not self.GenModuleHash()\r
+        # Hashing feature is off\r
+        if not GlobalData.gUseHashCache:\r
+            return False\r
+\r
+        # Initialize a dictionary for each arch type\r
+        if self.Arch not in GlobalData.gBuildHashSkipTracking:\r
+            GlobalData.gBuildHashSkipTracking[self.Arch] = dict()\r
+\r
+        # If library or Module is binary do not skip by hash\r
+        if self.IsBinaryModule:\r
+            return False\r
+\r
+        # .inc is contains binary information so do not skip by hash as well\r
+        for f_ext in self.SourceFileList:\r
+            if '.inc' in str(f_ext):\r
+                return False\r
+\r
+        # Use Cache, if exists and if Module has a copy in cache\r
+        if GlobalData.gBinCacheSource and self.AttemptModuleCacheCopy():\r
+            return True\r
+\r
+        # Early exit for libraries that haven't yet finished building\r
+        HashFile = path.join(self.BuildDir, self.Name + ".hash")\r
+        if self.IsLibrary and not os.path.exists(HashFile):\r
+            return False\r
+\r
+        # Return a Boolean based on if can skip by hash, either from memory or from IO.\r
+        if self.Name not in GlobalData.gBuildHashSkipTracking[self.Arch]:\r
+            # If hashes are the same, SaveFileOnChange() will return False.\r
+            GlobalData.gBuildHashSkipTracking[self.Arch][self.Name] = not SaveFileOnChange(HashFile, self.GenModuleHash(), True)\r
+            return GlobalData.gBuildHashSkipTracking[self.Arch][self.Name]\r
+        else:\r
+            return GlobalData.gBuildHashSkipTracking[self.Arch][self.Name]\r
 \r
     ## Decide whether we can skip the ModuleAutoGen process\r
     #  If any source file is newer than the module than we cannot skip\r
     #\r
     def CanSkip(self):\r
 \r
     ## Decide whether we can skip the ModuleAutoGen process\r
     #  If any source file is newer than the module than we cannot skip\r
     #\r
     def CanSkip(self):\r
-        if not os.path.exists(self.GetTimeStampPath()):\r
+        if self.MakeFileDir in GlobalData.gSikpAutoGenCache:\r
+            return True\r
+        if not os.path.exists(self.TimeStampPath):\r
             return False\r
         #last creation time of the module\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
 \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
             for source in f:\r
                 source = source.rstrip('\n')\r
                 if not os.path.exists(source):\r
@@ -4332,87 +4199,9 @@ class ModuleAutoGen(AutoGen):
                     ModuleAutoGen.TimeDict[source] = os.stat(source)[8]\r
                 if ModuleAutoGen.TimeDict[source] > DstTimeStamp:\r
                     return False\r
                     ModuleAutoGen.TimeDict[source] = os.stat(source)[8]\r
                 if ModuleAutoGen.TimeDict[source] > DstTimeStamp:\r
                     return False\r
+        GlobalData.gSikpAutoGenCache.add(self.MakeFileDir)\r
         return True\r
 \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
-\r
-        FileSet = {self.MetaFile.Path}\r
-\r
-        for SourceFile in self.Module.Sources:\r
-            FileSet.add (SourceFile.Path)\r
-\r
-        for Lib in self.DependentLibraryList:\r
-            FileSet.add (Lib.MetaFile.Path)\r
-\r
-        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
-            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
-\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
+    @cached_property\r
+    def TimeStampPath(self):\r
+        return os.path.join(self.MakeFileDir, 'AutoGenTimeStamp')\r