#\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
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
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
# indicate there's a thread is available for another build task\r
BuildTask._RunningQueueLock.acquire()\r
BuildTask._RunningQueue.pop(self.BuildItem)\r
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
+ # 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
+\r
+ # The module failed to build or failed to start building, from this point on\r
+\r
+ # Remove .hash from build\r
+ if GlobalData.gUseHashCache:\r
+ ModuleHashFile = 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
+\r
## Build a module or platform\r
#\r
# Create autogen code and makefile for a module or platform, and the launch\r
# 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
GlobalData.gGlobalDefines['ARCH'] = Arch\r
# 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
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
+ if Ma is None:\r
+ continue\r
MaList.append(Ma)\r
if Ma.CanSkipbyHash():\r
self.HashSkipModules.append(Ma)\r
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
self.AutoGenTime += int(round((time.time() - AutoGenStart)))\r
MakeStart = time.time()\r
for Ma in self.BuildModules:\r
# 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
# 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
self.CreateAsBuiltInf()\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
#\r
self._SaveMapFile (MapBuffer, Wa)\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
# 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
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
self.Progress.Stop("done!")\r
self.AutoGenTime += int(round((time.time() - AutoGenStart)))\r
MakeStart = time.time()\r
# 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
# 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
# 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
RemoveDirectory(os.path.dirname(GlobalData.gDatabasePath), True)\r
\r
def CreateAsBuiltInf(self):\r
+ all_lib_set = set()\r
+ all_mod_set = set()\r
for Module in self.BuildModules:\r
Module.CreateAsBuiltInf()\r
+ all_mod_set.add(Module)\r
for Module in self.HashSkipModules:\r
Module.CreateAsBuiltInf(True)\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.CreateAsBuiltInf(True)\r
+ all_lib_set.clear()\r
+ all_mod_set.clear()\r
self.BuildModules = []\r
self.HashSkipModules = []\r
## Do some clean-up works when error occurred\r