BaseTools: Refactor hash tracking after checking for Sources section
authorRodriguez, Christian <christian.rodriguez@intel.com>
Wed, 29 May 2019 16:26:49 +0000 (00:26 +0800)
committerFeng, Bob C <bob.c.feng@intel.com>
Mon, 10 Jun 2019 11:48:51 +0000 (19:48 +0800)
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1804

After adding a check to see if [Sources] section lists all the header
type files of a module, track module and library hashes for --hash
feature. If above check is not in compilance for a library or module,
force hash invalidation on that library or module.

Signed-off-by: Christian Rodriguez <christian.rodriguez@intel.com>
Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Reviewed-by: Bob Feng <bob.c.feng@intel.com>
BaseTools/Source/Python/AutoGen/AutoGen.py
BaseTools/Source/Python/AutoGen/GenMake.py
BaseTools/Source/Python/Common/GlobalData.py
BaseTools/Source/Python/build/build.py

index f1b8f93..3f41fbb 100644 (file)
@@ -3995,7 +3995,8 @@ class ModuleAutoGen(AutoGen):
             for LibraryAutoGen in self.LibraryAutoGenList:\r
                 LibraryAutoGen.CreateMakeFile()\r
 \r
-        if self.CanSkip():\r
+        # Don't enable if hash feature enabled, CanSkip uses timestamps to determine build skipping\r
+        if not GlobalData.gUseHashCache and self.CanSkip():\r
             return\r
 \r
         if len(self.CustomMakefile) == 0:\r
@@ -4038,7 +4039,8 @@ class ModuleAutoGen(AutoGen):
             for LibraryAutoGen in self.LibraryAutoGenList:\r
                 LibraryAutoGen.CreateCodeFile()\r
 \r
-        if self.CanSkip():\r
+        # Don't enable if hash feature enabled, CanSkip uses timestamps to determine build skipping\r
+        if not GlobalData.gUseHashCache and self.CanSkip():\r
             return\r
 \r
         AutoGenList = []\r
index 5c992d7..212ca0f 100644 (file)
@@ -935,10 +935,16 @@ cleanlib:
                     continue\r
                 headerFileDependencySet.add(aFileName)\r
 \r
+        # Ensure that gModuleBuildTracking has been initialized per architecture\r
+        if self._AutoGenObject.Arch not in GlobalData.gModuleBuildTracking:\r
+            GlobalData.gModuleBuildTracking[self._AutoGenObject.Arch] = dict()\r
+\r
         # Check if a module dependency header file is missing from the module's MetaFile\r
         for aFile in headerFileDependencySet:\r
             if aFile in headerFilesInMetaFileSet:\r
                 continue\r
+            if GlobalData.gUseHashCache:\r
+                GlobalData.gModuleBuildTracking[self._AutoGenObject.Arch][self._AutoGenObject] = 'FAIL_METAFILE'\r
             EdkLogger.warn("build","Module MetaFile [Sources] is missing local header!",\r
                         ExtraData = "Local Header: " + aFile + " not found in " + self._AutoGenObject.MetaFile.Path\r
                         )\r
index 95e28a9..bd45a43 100644 (file)
@@ -110,7 +110,8 @@ gEnableGenfdsMultiThread = False
 gSikpAutoGenCache = set()\r
 \r
 # Dictionary for tracking Module build status as success or failure\r
-# False -> Fail : True -> Success\r
+# Top Dict:     Key: Arch Type              Value: Dictionary\r
+# Second Dict:  Key: AutoGen Obj    Value: 'SUCCESS'\'FAIL'\'FAIL_METAFILE'\r
 gModuleBuildTracking = dict()\r
 \r
 # Dictionary of booleans that dictate whether a module or\r
index 80ceb98..0855d45 100644 (file)
@@ -625,8 +625,16 @@ class BuildTask:
             BuildTask._ErrorFlag.set()\r
             BuildTask._ErrorMessage = "%s broken\n    %s [%s]" % \\r
                                       (threading.currentThread().getName(), Command, WorkingDir)\r
-        if self.BuildItem.BuildObject in GlobalData.gModuleBuildTracking and not BuildTask._ErrorFlag.isSet():\r
-            GlobalData.gModuleBuildTracking[self.BuildItem.BuildObject] = True\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
@@ -1154,27 +1162,30 @@ class Build():
     #\r
     #\r
     def invalidateHash(self):\r
-        # GlobalData.gModuleBuildTracking contains only modules that cannot be skipped by hash\r
-        for moduleAutoGenObj in GlobalData.gModuleBuildTracking.keys():\r
-            # False == FAIL : True == Success\r
-            # Skip invalidating for Successful module builds\r
-            if GlobalData.gModuleBuildTracking[moduleAutoGenObj] == True:\r
-                continue\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 or failed to start building, from this point on\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
-            if GlobalData.gUseHashCache:\r
-                ModuleHashFile = path.join(moduleAutoGenObj.BuildDir, moduleAutoGenObj.Name + ".hash")\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 = path.join(GlobalData.gBinCacheDest, moduleAutoGenObj.Arch, moduleAutoGenObj.SourceDir, moduleAutoGenObj.MetaFile.BaseName)\r
-                HashFile = path.join(FileDir, moduleAutoGenObj.Name + '.hash')\r
-                if os.path.exists(HashFile):\r
-                    os.remove(HashFile)\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
@@ -1825,9 +1836,11 @@ class Build():
                                 if self.Target == "genmake":\r
                                     return True\r
                             self.BuildModules.append(Ma)\r
-                            # Initialize all modules in tracking to False (FAIL)\r
-                            if Ma not in GlobalData.gModuleBuildTracking:\r
-                                GlobalData.gModuleBuildTracking[Ma] = False\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
@@ -1911,6 +1924,7 @@ class Build():
                     # Save MAP buffer into MAP file.\r
                     #\r
                     self._SaveMapFile (MapBuffer, Wa)\r
+        self.invalidateHash()\r
 \r
     def _GenFfsCmd(self,ArchList):\r
         # convert dictionary of Cmd:(Inf,Arch)\r
@@ -2009,9 +2023,11 @@ class Build():
                             if self.Target == "genmake":\r
                                 continue\r
                         self.BuildModules.append(Ma)\r
-                        # Initialize all modules in tracking to False (FAIL)\r
-                        if Ma not in GlobalData.gModuleBuildTracking:\r
-                            GlobalData.gModuleBuildTracking[Ma] = False\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
@@ -2099,6 +2115,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