# Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>\r
# Copyright (c) 2019, American Megatrends, Inc. All rights reserved.<BR>\r
#\r
-# This program and the accompanying materials\r
-# are licensed and made available under the terms and conditions of the BSD License\r
-# which accompanies this distribution. The full text of the license may be found at\r
-# http://opensource.org/licenses/bsd-license.php\r
-#\r
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
#\r
\r
## Import Modules\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
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
f.close()\r
m.update(Content)\r
SaveFileOnChange(HashFile, m.hexdigest(), False)\r
- GlobalData.gPackageHash[Pkg.Arch][Pkg.PackageName] = m.hexdigest()\r
+ GlobalData.gPackageHash[Pkg.PackageName] = m.hexdigest()\r
\r
def _GetMetaFiles(self, Target, Toolchain, Arch):\r
AllWorkSpaceMetaFiles = set()\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
# get the original module/package/platform objects\r
self.SourceDir = self.MetaFile.SubDir\r
self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir)\r
\r
- self.SourceOverrideDir = None\r
- # use overridden 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
RetVal = {}\r
for Type in self.Module.CustomMakefile:\r
MakeType = gMakeTypeMap[Type] if Type in gMakeTypeMap else 'nmake'\r
- if self.SourceOverrideDir is not None:\r
- File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])\r
- if not os.path.exists(File):\r
- File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])\r
- else:\r
- File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])\r
+ File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])\r
RetVal[MakeType] = File\r
return RetVal\r
\r
RetVal.append(PackageDir)\r
IncludesList = Package.Includes\r
if Package._PrivateIncludes:\r
- if not self.MetaFile.Path.startswith(PackageDir):\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
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
- ModuleFile = path.join(self.OutputDir, self.Name + '.inf')\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
- Ma = self.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
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
+ # If library or Module is binary do not skip by hash\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
+ 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
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
return RetVal\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
+\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
+\r
# Add Platform level hash\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
- if Pkg.PackageName in GlobalData.gPackageHash[self.Arch]:\r
- m.update(GlobalData.gPackageHash[self.Arch][Pkg.PackageName].encode('utf-8'))\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
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
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(), False)\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
- if GlobalData.gUseHashCache:\r
- return not self.GenModuleHash()\r
- return False\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