]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/build/build.py
BaseTools: Decouple AutoGen Objects
[mirror_edk2.git] / BaseTools / Source / Python / build / build.py
index 587370caaf0286fb8c8fce718979ca292e3affbc..3d083f4eaade6239f8b1df766f0fa4b288f05770 100644 (file)
 # Import Modules\r
 #\r
 from __future__ import print_function\r
-import Common.LongFilePathOs as os\r
-import re\r
+from __future__ import absolute_import\r
+import os.path as path\r
 import sys\r
+import os\r
+import re\r
 import glob\r
 import time\r
 import platform\r
 import traceback\r
-import encodings.ascii\r
 import multiprocessing\r
-\r
-from struct import *\r
-from threading import *\r
+from threading import Thread,Event,BoundedSemaphore\r
 import threading\r
+from subprocess import Popen,PIPE\r
+from collections import OrderedDict, defaultdict\r
 from optparse import OptionParser\r
-from subprocess import *\r
+from AutoGen.PlatformAutoGen import PlatformAutoGen\r
+from AutoGen.ModuleAutoGen import ModuleAutoGen\r
+from AutoGen.WorkspaceAutoGen import WorkspaceAutoGen\r
+from AutoGen import GenMake\r
 from Common import Misc as Utils\r
 \r
-from Common.LongFilePathSupport import OpenLongFilePath as open\r
-from Common.TargetTxtClassObject import TargetTxtClassObject\r
-from Common.ToolDefClassObject import ToolDefClassObject\r
+from Common.TargetTxtClassObject import TargetTxt\r
+from Common.ToolDefClassObject import ToolDef\r
+from Common.Misc import PathClass,SaveFileOnChange,RemoveDirectory\r
+from Common.StringUtils import NormPath\r
+from Common.MultipleWorkspace import MultipleWorkspace as mws\r
+from Common.BuildToolError import *\r
 from Common.DataType import *\r
+import Common.EdkLogger as EdkLogger\r
 from Common.BuildVersion import gBUILD_VERSION\r
-from AutoGen.AutoGen import *\r
-from Common.BuildToolError import *\r
-from Workspace.WorkspaceDatabase import WorkspaceDatabase\r
-from Common.MultipleWorkspace import MultipleWorkspace as mws\r
+from Workspace.WorkspaceDatabase import BuildDB\r
 \r
 from BuildReport import BuildReport\r
-from GenPatchPcdTable.GenPatchPcdTable import *\r
-from PatchPcdValue.PatchPcdValue import *\r
+from GenPatchPcdTable.GenPatchPcdTable import PeImageClass,parsePcdInfoFromMapFile\r
+from PatchPcdValue.PatchPcdValue import PatchBinaryFile\r
 \r
-import Common.EdkLogger\r
 import Common.GlobalData as GlobalData\r
 from GenFds.GenFds import GenFds, GenFdsApi\r
 \r
-from collections import OrderedDict, defaultdict\r
 \r
 # Version and Copyright\r
 VersionNumber = "0.60" + ' ' + gBUILD_VERSION\r
@@ -593,7 +596,7 @@ class BuildTask:
     #\r
     def AddDependency(self, Dependency):\r
         for Dep in Dependency:\r
-            if not Dep.BuildObject.IsBinaryModule:\r
+            if not Dep.BuildObject.IsBinaryModule and not Dep.BuildObject.CanSkipbyHash():\r
                 self.DependencyList.append(BuildTask.New(Dep))    # BuildTask list\r
 \r
     ## The thread wrapper of LaunchCommand function\r
@@ -605,6 +608,11 @@ class BuildTask:
         try:\r
             self.BuildItem.BuildObject.BuildTime = LaunchCommand(Command, WorkingDir)\r
             self.CompleteFlag = True\r
+\r
+            # Run hash operation post dependency, to account for libs\r
+            if GlobalData.gUseHashCache and self.BuildItem.BuildObject.IsLibrary:\r
+                HashFile = path.join(self.BuildItem.BuildObject.BuildDir, self.BuildItem.BuildObject.Name + ".hash")\r
+                SaveFileOnChange(HashFile, self.BuildItem.BuildObject.GenModuleHash(), True)\r
         except:\r
             #\r
             # TRICK: hide the output of threads left running, so that the user can\r
@@ -620,6 +628,16 @@ class BuildTask:
             BuildTask._ErrorFlag.set()\r
             BuildTask._ErrorMessage = "%s broken\n    %s [%s]" % \\r
                                       (threading.currentThread().getName(), Command, WorkingDir)\r
+\r
+        # Set the value used by hash invalidation flow in GlobalData.gModuleBuildTracking to 'SUCCESS'\r
+        # If Module or Lib is being tracked, it did not fail header check test, and built successfully\r
+        if (self.BuildItem.BuildObject.Arch in GlobalData.gModuleBuildTracking and\r
+           self.BuildItem.BuildObject in GlobalData.gModuleBuildTracking[self.BuildItem.BuildObject.Arch] and\r
+           GlobalData.gModuleBuildTracking[self.BuildItem.BuildObject.Arch][self.BuildItem.BuildObject] != 'FAIL_METAFILE' and\r
+           not BuildTask._ErrorFlag.isSet()\r
+           ):\r
+            GlobalData.gModuleBuildTracking[self.BuildItem.BuildObject.Arch][self.BuildItem.BuildObject] = 'SUCCESS'\r
+\r
         # indicate there's a thread is available for another build task\r
         BuildTask._RunningQueueLock.acquire()\r
         BuildTask._RunningQueue.pop(self.BuildItem)\r
@@ -701,8 +719,8 @@ class Build():
         self.ConfDirectory = BuildOptions.ConfDirectory\r
         self.SpawnMode      = True\r
         self.BuildReport    = BuildReport(BuildOptions.ReportFile, BuildOptions.ReportType)\r
-        self.TargetTxt      = TargetTxtClassObject()\r
-        self.ToolDef        = ToolDefClassObject()\r
+        self.TargetTxt      = TargetTxt\r
+        self.ToolDef        = ToolDef\r
         self.AutoGenTime    = 0\r
         self.MakeTime       = 0\r
         self.GenFdsTime     = 0\r
@@ -758,8 +776,9 @@ class Build():
                 ConfDirectoryPath = mws.join(self.WorkspaceDir, 'Conf')\r
         GlobalData.gConfDirectory = ConfDirectoryPath\r
         GlobalData.gDatabasePath = os.path.normpath(os.path.join(ConfDirectoryPath, GlobalData.gDatabasePath))\r
-\r
-        self.Db = WorkspaceDatabase()\r
+        if not os.path.exists(os.path.join(GlobalData.gConfDirectory, '.cache')):\r
+            os.makedirs(os.path.join(GlobalData.gConfDirectory, '.cache'))\r
+        self.Db = BuildDB\r
         self.BuildDatabase = self.Db.BuildObject\r
         self.Platform = None\r
         self.ToolChainFamily = None\r
@@ -800,8 +819,8 @@ class Build():
             EdkLogger.quiet("%-16s = %s" % ("POSTBUILD", self.Postbuild))\r
         if self.Prebuild:\r
             self.LaunchPrebuild()\r
-            self.TargetTxt = TargetTxtClassObject()\r
-            self.ToolDef   = ToolDefClassObject()\r
+            self.TargetTxt = TargetTxt\r
+            self.ToolDef   = ToolDef\r
         if not (self.LaunchPrebuildFlag and os.path.exists(self.PlatformBuildPath)):\r
             self.InitBuild()\r
 \r
@@ -813,23 +832,6 @@ class Build():
     #   This method will parse target.txt and get the build configurations.\r
     #\r
     def LoadConfiguration(self):\r
-        #\r
-        # Check target.txt and tools_def.txt and Init them\r
-        #\r
-        BuildConfigurationFile = os.path.normpath(os.path.join(GlobalData.gConfDirectory, gBuildConfiguration))\r
-        if os.path.isfile(BuildConfigurationFile) == True:\r
-            StatusCode = self.TargetTxt.LoadTargetTxtFile(BuildConfigurationFile)\r
-\r
-            ToolDefinitionFile = self.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_TOOL_CHAIN_CONF]\r
-            if ToolDefinitionFile == '':\r
-                ToolDefinitionFile = gToolsDefinition\r
-                ToolDefinitionFile = os.path.normpath(mws.join(self.WorkspaceDir, 'Conf', ToolDefinitionFile))\r
-            if os.path.isfile(ToolDefinitionFile) == True:\r
-                StatusCode = self.ToolDef.LoadToolDefFile(ToolDefinitionFile)\r
-            else:\r
-                EdkLogger.error("build", FILE_NOT_FOUND, ExtraData=ToolDefinitionFile)\r
-        else:\r
-            EdkLogger.error("build", FILE_NOT_FOUND, ExtraData=BuildConfigurationFile)\r
 \r
         # if no ARCH given in command line, get it from target.txt\r
         if not self.ArchList:\r
@@ -1138,6 +1140,40 @@ class Build():
             if Process.returncode != 0 :\r
                 EdkLogger.error("Postbuild", POSTBUILD_ERROR, 'Postbuild process is not success!')\r
             EdkLogger.info("\n- Postbuild Done -\n")\r
+\r
+    ## Error handling for hash feature\r
+    #\r
+    # On BuildTask error, iterate through the Module Build tracking\r
+    # dictionary to determine wheather a module failed to build. Invalidate\r
+    # the hash associated with that module by removing it from storage.\r
+    #\r
+    #\r
+    def invalidateHash(self):\r
+        # Only for hashing feature\r
+        if not GlobalData.gUseHashCache:\r
+            return\r
+\r
+        # GlobalData.gModuleBuildTracking contains only modules or libs that cannot be skipped by hash\r
+        for moduleAutoGenObjArch in GlobalData.gModuleBuildTracking.keys():\r
+            for moduleAutoGenObj in GlobalData.gModuleBuildTracking[moduleAutoGenObjArch].keys():\r
+                # Skip invalidating for Successful Module/Lib builds\r
+                if GlobalData.gModuleBuildTracking[moduleAutoGenObjArch][moduleAutoGenObj] == 'SUCCESS':\r
+                    continue\r
+\r
+                # The module failed to build, failed to start building, or failed the header check test from this point on\r
+\r
+                # Remove .hash from build\r
+                ModuleHashFile = os.path.join(moduleAutoGenObj.BuildDir, moduleAutoGenObj.Name + ".hash")\r
+                if os.path.exists(ModuleHashFile):\r
+                    os.remove(ModuleHashFile)\r
+\r
+                # Remove .hash file from cache\r
+                if GlobalData.gBinCacheDest:\r
+                    FileDir = os.path.join(GlobalData.gBinCacheDest, moduleAutoGenObj.Arch, moduleAutoGenObj.SourceDir, moduleAutoGenObj.MetaFile.BaseName)\r
+                    HashFile = os.path.join(FileDir, moduleAutoGenObj.Name + '.hash')\r
+                    if os.path.exists(HashFile):\r
+                        os.remove(HashFile)\r
+\r
     ## Build a module or platform\r
     #\r
     # Create autogen code and makefile for a module or platform, and the launch\r
@@ -1194,10 +1230,6 @@ class Build():
 \r
         # run\r
         if Target == 'run':\r
-            RunDir = os.path.normpath(os.path.join(AutoGenObject.BuildDir, GlobalData.gGlobalDefines['ARCH']))\r
-            Command = '.\SecMain'\r
-            os.chdir(RunDir)\r
-            LaunchCommand(Command, RunDir)\r
             return True\r
 \r
         # build modules\r
@@ -1205,6 +1237,9 @@ class Build():
             BuildCommand = BuildCommand + [Target]\r
             LaunchCommand(BuildCommand, AutoGenObject.MakeFileDir)\r
             self.CreateAsBuiltInf()\r
+            if GlobalData.gBinCacheDest:\r
+                self.UpdateBuildCache()\r
+            self.BuildModules = []\r
             return True\r
 \r
         # build library\r
@@ -1223,6 +1258,9 @@ class Build():
                 NewBuildCommand = BuildCommand + ['-f', os.path.normpath(os.path.join(Mod, makefile)), 'pbuild']\r
                 LaunchCommand(NewBuildCommand, AutoGenObject.MakeFileDir)\r
             self.CreateAsBuiltInf()\r
+            if GlobalData.gBinCacheDest:\r
+                self.UpdateBuildCache()\r
+            self.BuildModules = []\r
             return True\r
 \r
         # cleanlib\r
@@ -1316,6 +1354,9 @@ class Build():
                 BuildCommand = BuildCommand + [Target]\r
             AutoGenObject.BuildTime = LaunchCommand(BuildCommand, AutoGenObject.MakeFileDir)\r
             self.CreateAsBuiltInf()\r
+            if GlobalData.gBinCacheDest:\r
+                self.UpdateBuildCache()\r
+            self.BuildModules = []\r
             return True\r
 \r
         # genfds\r
@@ -1326,10 +1367,6 @@ class Build():
 \r
         # run\r
         if Target == 'run':\r
-            RunDir = os.path.normpath(os.path.join(AutoGenObject.BuildDir, GlobalData.gGlobalDefines['ARCH']))\r
-            Command = '.\SecMain'\r
-            os.chdir(RunDir)\r
-            LaunchCommand(Command, RunDir)\r
             return True\r
 \r
         # build library\r
@@ -1449,7 +1486,7 @@ class Build():
         if self.Fdf:\r
             # First get the XIP base address for FV map file.\r
             GuidPattern = re.compile("[-a-fA-F0-9]+")\r
-            GuidName = re.compile("\(GUID=[-a-fA-F0-9]+")\r
+            GuidName = re.compile(r"\(GUID=[-a-fA-F0-9]+")\r
             for FvName in Wa.FdfProfile.FvDict:\r
                 FvMapBuffer = os.path.join(Wa.FvDir, FvName + '.Fv.map')\r
                 if not os.path.exists(FvMapBuffer):\r
@@ -1663,16 +1700,20 @@ class Build():
                 # Add ffs build to makefile\r
                 CmdListDict = {}\r
                 if GlobalData.gEnableGenfdsMultiThread and self.Fdf:\r
-                    CmdListDict = self._GenFfsCmd()\r
+                    CmdListDict = self._GenFfsCmd(Wa.ArchList)\r
 \r
                 for Arch in Wa.ArchList:\r
+                    PcdMaList    = []\r
                     GlobalData.gGlobalDefines['ARCH'] = Arch\r
                     Pa = PlatformAutoGen(Wa, self.PlatformFile, BuildTarget, ToolChain, Arch)\r
                     for Module in Pa.Platform.Modules:\r
                         # Get ModuleAutoGen object to generate C code file and makefile\r
-                        Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile)\r
+                        Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile,Pa.DataPipe)\r
                         if Ma is None:\r
                             continue\r
+                        if Ma.PcdIsDriver:\r
+                            Ma.PlatformInfo = Pa\r
+                            PcdMaList.append(Ma)\r
                         self.BuildModules.append(Ma)\r
                     self._BuildPa(self.Target, Pa, FfsCommand=CmdListDict)\r
 \r
@@ -1756,7 +1797,7 @@ class Build():
                 # Add ffs build to makefile\r
                 CmdListDict = None\r
                 if GlobalData.gEnableGenfdsMultiThread and self.Fdf:\r
-                    CmdListDict = self._GenFfsCmd()\r
+                    CmdListDict = self._GenFfsCmd(Wa.ArchList)\r
                 self.Progress.Stop("done!")\r
                 MaList = []\r
                 ExitFlag = threading.Event()\r
@@ -1768,12 +1809,18 @@ class Build():
                     Pa = PlatformAutoGen(Wa, self.PlatformFile, BuildTarget, ToolChain, Arch)\r
                     for Module in Pa.Platform.Modules:\r
                         if self.ModuleFile.Dir == Module.Dir and self.ModuleFile.Name == Module.Name:\r
-                            Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile)\r
-                            if Ma is None: continue\r
+                            Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile,Pa.DataPipe)\r
+                            if Ma is None:\r
+                                continue\r
                             MaList.append(Ma)\r
                             if Ma.CanSkipbyHash():\r
                                 self.HashSkipModules.append(Ma)\r
+                                if GlobalData.gBinCacheSource:\r
+                                    EdkLogger.quiet("cache hit: %s[%s]" % (Ma.MetaFile.Path, Ma.Arch))\r
                                 continue\r
+                            else:\r
+                                if GlobalData.gBinCacheSource:\r
+                                    EdkLogger.quiet("cache miss: %s[%s]" % (Ma.MetaFile.Path, Ma.Arch))\r
                             # Not to auto-gen for targets 'clean', 'cleanlib', 'cleanall', 'run', 'fds'\r
                             if self.Target not in ['clean', 'cleanlib', 'cleanall', 'run', 'fds']:\r
                                 # for target which must generate AutoGen code and makefile\r
@@ -1794,6 +1841,11 @@ class Build():
                                 if self.Target == "genmake":\r
                                     return True\r
                             self.BuildModules.append(Ma)\r
+                            # Initialize all modules in tracking to 'FAIL'\r
+                            if Ma.Arch not in GlobalData.gModuleBuildTracking:\r
+                                GlobalData.gModuleBuildTracking[Ma.Arch] = dict()\r
+                            if Ma not in GlobalData.gModuleBuildTracking[Ma.Arch]:\r
+                                GlobalData.gModuleBuildTracking[Ma.Arch][Ma] = 'FAIL'\r
                     self.AutoGenTime += int(round((time.time() - AutoGenStart)))\r
                     MakeStart = time.time()\r
                     for Ma in self.BuildModules:\r
@@ -1804,6 +1856,7 @@ class Build():
                             # we need a full version of makefile for platform\r
                             ExitFlag.set()\r
                             BuildTask.WaitForComplete()\r
+                            self.invalidateHash()\r
                             Pa.CreateMakeFile(False)\r
                             EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
                         # Start task scheduler\r
@@ -1813,6 +1866,7 @@ class Build():
                     # in case there's an interruption. we need a full version of makefile for platform\r
                     Pa.CreateMakeFile(False)\r
                     if BuildTask.HasError():\r
+                        self.invalidateHash()\r
                         EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
                     self.MakeTime += int(round((time.time() - MakeStart)))\r
 \r
@@ -1820,8 +1874,12 @@ class Build():
                 ExitFlag.set()\r
                 BuildTask.WaitForComplete()\r
                 self.CreateAsBuiltInf()\r
+                if GlobalData.gBinCacheDest:\r
+                    self.UpdateBuildCache()\r
+                self.BuildModules = []\r
                 self.MakeTime += int(round((time.time() - MakeContiue)))\r
                 if BuildTask.HasError():\r
+                    self.invalidateHash()\r
                     EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
 \r
                 self.BuildReport.AddPlatformReport(Wa, MaList)\r
@@ -1874,12 +1932,13 @@ class Build():
                     # Save MAP buffer into MAP file.\r
                     #\r
                     self._SaveMapFile (MapBuffer, Wa)\r
+        self.invalidateHash()\r
 \r
-    def _GenFfsCmd(self):\r
+    def _GenFfsCmd(self,ArchList):\r
         # convert dictionary of Cmd:(Inf,Arch)\r
         # to a new dictionary of (Inf,Arch):Cmd,Cmd,Cmd...\r
         CmdSetDict = defaultdict(set)\r
-        GenFfsDict = GenFds.GenFfsMakefile('', GlobalData.gFdfParser, self, self.ArchList, GlobalData)\r
+        GenFfsDict = GenFds.GenFfsMakefile('', GlobalData.gFdfParser, self, ArchList, GlobalData)\r
         for Cmd in GenFfsDict:\r
             tmpInf, tmpArch = GenFfsDict[Cmd]\r
             CmdSetDict[tmpInf, tmpArch].add(Cmd)\r
@@ -1923,13 +1982,14 @@ class Build():
                 # Add ffs build to makefile\r
                 CmdListDict = None\r
                 if GlobalData.gEnableGenfdsMultiThread and self.Fdf:\r
-                    CmdListDict = self._GenFfsCmd()\r
+                    CmdListDict = self._GenFfsCmd(Wa.ArchList)\r
 \r
                 # multi-thread exit flag\r
                 ExitFlag = threading.Event()\r
                 ExitFlag.clear()\r
                 self.AutoGenTime += int(round((time.time() - WorkspaceAutoGenTime)))\r
                 for Arch in Wa.ArchList:\r
+                    PcdMaList    = []\r
                     AutoGenStart = time.time()\r
                     GlobalData.gGlobalDefines['ARCH'] = Arch\r
                     Pa = PlatformAutoGen(Wa, self.PlatformFile, BuildTarget, ToolChain, Arch)\r
@@ -1947,13 +2007,21 @@ class Build():
                             ModuleList.append(Inf)\r
                     for Module in ModuleList:\r
                         # Get ModuleAutoGen object to generate C code file and makefile\r
-                        Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile)\r
+                        Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile,Pa.DataPipe)\r
 \r
                         if Ma is None:\r
                             continue\r
+                        if Ma.PcdIsDriver:\r
+                            Ma.PlatformInfo = Pa\r
+                            PcdMaList.append(Ma)\r
                         if Ma.CanSkipbyHash():\r
                             self.HashSkipModules.append(Ma)\r
+                            if GlobalData.gBinCacheSource:\r
+                                EdkLogger.quiet("cache hit: %s[%s]" % (Ma.MetaFile.Path, Ma.Arch))\r
                             continue\r
+                        else:\r
+                            if GlobalData.gBinCacheSource:\r
+                                EdkLogger.quiet("cache miss: %s[%s]" % (Ma.MetaFile.Path, Ma.Arch))\r
 \r
                         # Not to auto-gen for targets 'clean', 'cleanlib', 'cleanall', 'run', 'fds'\r
                         if self.Target not in ['clean', 'cleanlib', 'cleanall', 'run', 'fds']:\r
@@ -1972,6 +2040,11 @@ class Build():
                             if self.Target == "genmake":\r
                                 continue\r
                         self.BuildModules.append(Ma)\r
+                        # Initialize all modules in tracking to 'FAIL'\r
+                        if Ma.Arch not in GlobalData.gModuleBuildTracking:\r
+                            GlobalData.gModuleBuildTracking[Ma.Arch] = dict()\r
+                        if Ma not in GlobalData.gModuleBuildTracking[Ma.Arch]:\r
+                            GlobalData.gModuleBuildTracking[Ma.Arch][Ma] = 'FAIL'\r
                     self.Progress.Stop("done!")\r
                     self.AutoGenTime += int(round((time.time() - AutoGenStart)))\r
                     MakeStart = time.time()\r
@@ -1984,6 +2057,7 @@ class Build():
                             # we need a full version of makefile for platform\r
                             ExitFlag.set()\r
                             BuildTask.WaitForComplete()\r
+                            self.invalidateHash()\r
                             Pa.CreateMakeFile(False)\r
                             EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
                         # Start task scheduler\r
@@ -1993,6 +2067,7 @@ class Build():
                     # in case there's an interruption. we need a full version of makefile for platform\r
                     Pa.CreateMakeFile(False)\r
                     if BuildTask.HasError():\r
+                        self.invalidateHash()\r
                         EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
                     self.MakeTime += int(round((time.time() - MakeStart)))\r
 \r
@@ -2006,12 +2081,16 @@ class Build():
                 ExitFlag.set()\r
                 BuildTask.WaitForComplete()\r
                 self.CreateAsBuiltInf()\r
+                if GlobalData.gBinCacheDest:\r
+                    self.UpdateBuildCache()\r
+                self.BuildModules = []\r
                 self.MakeTime += int(round((time.time() - MakeContiue)))\r
                 #\r
                 # Check for build error, and raise exception if one\r
                 # has been signaled.\r
                 #\r
                 if BuildTask.HasError():\r
+                    self.invalidateHash()\r
                     EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
 \r
                 # Create MAP file when Load Fix Address is enabled.\r
@@ -2056,6 +2135,7 @@ class Build():
                     # Save MAP buffer into MAP file.\r
                     #\r
                     self._SaveMapFile(MapBuffer, Wa)\r
+        self.invalidateHash()\r
 \r
     ## Generate GuidedSectionTools.txt in the FV directories.\r
     #\r
@@ -2145,9 +2225,23 @@ class Build():
     def CreateAsBuiltInf(self):\r
         for Module in self.BuildModules:\r
             Module.CreateAsBuiltInf()\r
+\r
+    def UpdateBuildCache(self):\r
+        all_lib_set = set()\r
+        all_mod_set = set()\r
+        for Module in self.BuildModules:\r
+            Module.CopyModuleToCache()\r
+            all_mod_set.add(Module)\r
         for Module in self.HashSkipModules:\r
-            Module.CreateAsBuiltInf(True)\r
-        self.BuildModules = []\r
+            Module.CopyModuleToCache()\r
+            all_mod_set.add(Module)\r
+        for Module in all_mod_set:\r
+            for lib in Module.LibraryAutoGenList:\r
+                all_lib_set.add(lib)\r
+        for lib in all_lib_set:\r
+            lib.CopyModuleToCache()\r
+        all_lib_set.clear()\r
+        all_mod_set.clear()\r
         self.HashSkipModules = []\r
     ## Do some clean-up works when error occurred\r
     def Relinquish(self):\r
@@ -2423,7 +2517,7 @@ def Main():
                     "\nbuild",\r
                     CODE_ERROR,\r
                     "Unknown fatal error when processing [%s]" % MetaFile,\r
-                    ExtraData="\n(Please send email to edk2-devel@lists.01.org for help, attaching following call stack trace!)\n",\r
+                    ExtraData="\n(Please send email to %s for help, attaching following call stack trace!)\n" % MSG_EDKII_MAIL_ADDR,\r
                     RaiseError=False\r
                     )\r
         EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())\r