# 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 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 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
#\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
#\r
@cached_class_function\r
def CreateCodeFile(self, CreateModuleCodeFile=False):\r
- # only module has code to be greated, so do nothing if CreateModuleCodeFile is False\r
+ # only module has code to be created, so do nothing if CreateModuleCodeFile is False\r
if not CreateModuleCodeFile:\r
return\r
\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:[DefaultSku]}\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
## 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
@cached_property\r
def ToolDefinition(self):\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
## 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
## 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
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
def Guid(self):\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
self.MetaFile.BaseName\r
))\r
\r
- ## Return the directory to store the intermediate object files of the mdoule\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
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 mdoule\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
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
\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
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
- 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
\r
DepexList = []\r
#\r
- # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion\r
+ # Append depex from dependent libraries, if not "BEFORE", "AFTER" expression\r
#\r
for M in [self.Module] + self.DependentLibraryList:\r
Inherited = False\r
if '.' not in item:\r
NewList.append(item)\r
else:\r
- if item not in self.FixedVoidTypePcds:\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 = self.FixedVoidTypePcds[item]\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
# 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
- 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
+ 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
IdfGenBinBuffer.close()\r
return RetVal\r
\r
- ## Return the list of library modules explicitly or implicityly used by this module\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
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
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
+ DepexExpression = self._GetDepexExpresionString()\r
+ AsBuiltInfDict['depexsection_item'] = DepexExpression if DepexExpression else ''\r
\r
AsBuiltInf = TemplateString()\r
AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))\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