X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=BaseTools%2FSource%2FPython%2FAutoGen%2FAutoGen.py;h=a5bef4f7c62a0ec3ab7346460bce44c61cc93349;hp=cfe2d290992860d3e3e8073ea90457454bd864ac;hb=c0fd7f734e2d33e22215899b40a47b843129541d;hpb=822925013278733ac7f03c35fece2df3e8bc3614 diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py b/BaseTools/Source/Python/AutoGen/AutoGen.py index cfe2d29099..a5bef4f7c6 100644 --- a/BaseTools/Source/Python/AutoGen/AutoGen.py +++ b/BaseTools/Source/Python/AutoGen/AutoGen.py @@ -3,14 +3,9 @@ # # Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.
# Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.
+# Copyright (c) 2019, American Megatrends, Inc. All rights reserved.
# -# This program and the accompanying materials -# are licensed and made available under the terms and conditions of the BSD License -# which accompanies this distribution. The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php -# -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# SPDX-License-Identifier: BSD-2-Clause-Patent # ## Import Modules @@ -30,7 +25,7 @@ from io import BytesIO from .StrGather import * from .BuildEngine import BuildRule - +import shutil from Common.LongFilePathSupport import CopyLongFilePath from Common.BuildToolError import * from Common.DataType import * @@ -170,6 +165,73 @@ ${tail_comments} ## @AsBuilt${BEGIN} ## ${flags_item}${END} """) +## Split command line option string to list +# +# subprocess.Popen needs the args to be a sequence. Otherwise there's problem +# in non-windows platform to launch command +# +def _SplitOption(OptionString): + OptionList = [] + LastChar = " " + OptionStart = 0 + QuotationMark = "" + for Index in range(0, len(OptionString)): + CurrentChar = OptionString[Index] + if CurrentChar in ['"', "'"]: + if QuotationMark == CurrentChar: + QuotationMark = "" + elif QuotationMark == "": + QuotationMark = CurrentChar + continue + elif QuotationMark: + continue + + if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]: + if Index > OptionStart: + OptionList.append(OptionString[OptionStart:Index - 1]) + OptionStart = Index + LastChar = CurrentChar + OptionList.append(OptionString[OptionStart:]) + return OptionList + +# +# Convert string to C format array +# +def _ConvertStringToByteArray(Value): + Value = Value.strip() + if not Value: + return None + if Value[0] == '{': + if not Value.endswith('}'): + return None + Value = Value.replace(' ', '').replace('{', '').replace('}', '') + ValFields = Value.split(',') + try: + for Index in range(len(ValFields)): + ValFields[Index] = str(int(ValFields[Index], 0)) + except ValueError: + return None + Value = '{' + ','.join(ValFields) + '}' + return Value + + Unicode = False + if Value.startswith('L"'): + if not Value.endswith('"'): + return None + Value = Value[1:] + Unicode = True + elif not Value.startswith('"') or not Value.endswith('"'): + return None + + Value = eval(Value) # translate escape character + NewValue = '{' + for Index in range(0, len(Value)): + if Unicode: + NewValue = NewValue + str(ord(Value[Index]) % 0x10000) + ',' + else: + NewValue = NewValue + str(ord(Value[Index]) % 0x100) + ',' + Value = NewValue + '0}' + return Value ## Base class for AutoGen # @@ -201,8 +263,6 @@ class AutoGen(object): RetVal = cls.__ObjectCache[Key] = super(AutoGen, cls).__new__(cls) return RetVal - def __init__ (self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs): - super(AutoGen, self).__init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs) ## hash() operator # @@ -235,7 +295,6 @@ class WorkspaceAutoGen(AutoGen): # call super().__init__ then call the worker function with different parameter count def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs): if not hasattr(self, "_Init"): - super(WorkspaceAutoGen, self).__init__(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs) self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs) self._Init = True @@ -409,7 +468,7 @@ class WorkspaceAutoGen(AutoGen): # generate the SourcePcdDict and BinaryPcdDict PGen = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch) - for BuildData in PGen.BuildDatabase._CACHE_.values(): + for BuildData in list(PGen.BuildDatabase._CACHE_.values()): if BuildData.Arch != Arch: continue if BuildData.MetaFile.Ext == '.inf': @@ -515,7 +574,7 @@ class WorkspaceAutoGen(AutoGen): if NewPcd2 not in GlobalData.MixedPcd[item]: GlobalData.MixedPcd[item].append(NewPcd2) - for BuildData in PGen.BuildDatabase._CACHE_.values(): + for BuildData in list(PGen.BuildDatabase._CACHE_.values()): if BuildData.Arch != Arch: continue for key in BuildData.Pcds: @@ -596,7 +655,7 @@ class WorkspaceAutoGen(AutoGen): # # Generate Package level hash value # - GlobalData.gPackageHash[Arch] = {} + GlobalData.gPackageHash = {} if GlobalData.gUseHashCache: for Pkg in Pkgs: self._GenPkgLevelHash(Pkg) @@ -616,17 +675,17 @@ class WorkspaceAutoGen(AutoGen): # content = 'gCommandLineDefines: ' content += str(GlobalData.gCommandLineDefines) - content += os.linesep + content += TAB_LINE_BREAK content += 'BuildOptionPcd: ' content += str(GlobalData.BuildOptionPcd) - content += os.linesep + content += TAB_LINE_BREAK content += 'Active Platform: ' content += str(self.Platform) - content += os.linesep + content += TAB_LINE_BREAK if self.FdfFile: content += 'Flash Image Definition: ' content += str(self.FdfFile) - content += os.linesep + content += TAB_LINE_BREAK SaveFileOnChange(os.path.join(self.BuildDir, 'BuildOptions'), content, False) # @@ -636,7 +695,7 @@ class WorkspaceAutoGen(AutoGen): if Pa.PcdTokenNumber: if Pa.DynamicPcdList: for Pcd in Pa.DynamicPcdList: - PcdTokenNumber += os.linesep + PcdTokenNumber += TAB_LINE_BREAK PcdTokenNumber += str((Pcd.TokenCName, Pcd.TokenSpaceGuidCName)) PcdTokenNumber += ' : ' PcdTokenNumber += str(Pa.PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName]) @@ -661,11 +720,11 @@ class WorkspaceAutoGen(AutoGen): for files in AllWorkSpaceMetaFiles: if files.endswith('.dec'): continue - f = open(files, 'r') + f = open(files, 'rb') Content = f.read() f.close() m.update(Content) - SaveFileOnChange(os.path.join(self.BuildDir, 'AutoGen.hash'), m.hexdigest(), True) + SaveFileOnChange(os.path.join(self.BuildDir, 'AutoGen.hash'), m.hexdigest(), False) GlobalData.gPlatformHash = m.hexdigest() # @@ -682,7 +741,7 @@ class WorkspaceAutoGen(AutoGen): return True def _GenPkgLevelHash(self, Pkg): - if Pkg.PackageName in GlobalData.gPackageHash[Pkg.Arch]: + if Pkg.PackageName in GlobalData.gPackageHash: return PkgDir = os.path.join(self.BuildDir, Pkg.Arch, Pkg.PackageName) @@ -690,7 +749,7 @@ class WorkspaceAutoGen(AutoGen): HashFile = os.path.join(PkgDir, Pkg.PackageName + '.hash') m = hashlib.md5() # Get .dec file's hash value - f = open(Pkg.MetaFile.Path, 'r') + f = open(Pkg.MetaFile.Path, 'rb') Content = f.read() f.close() m.update(Content) @@ -700,12 +759,12 @@ class WorkspaceAutoGen(AutoGen): for Root, Dirs, Files in os.walk(str(inc)): for File in sorted(Files): File_Path = os.path.join(Root, File) - f = open(File_Path, 'r') + f = open(File_Path, 'rb') Content = f.read() f.close() m.update(Content) - SaveFileOnChange(HashFile, m.hexdigest(), True) - GlobalData.gPackageHash[Pkg.Arch][Pkg.PackageName] = m.hexdigest() + SaveFileOnChange(HashFile, m.hexdigest(), False) + GlobalData.gPackageHash[Pkg.PackageName] = m.hexdigest() def _GetMetaFiles(self, Target, Toolchain, Arch): AllWorkSpaceMetaFiles = set() @@ -864,7 +923,7 @@ class WorkspaceAutoGen(AutoGen): def _CheckAllPcdsTokenValueConflict(self): for Pa in self.AutoGenObjectList: for Package in Pa.PackageList: - PcdList = Package.Pcds.values() + PcdList = list(Package.Pcds.values()) PcdList.sort(key=lambda x: int(x.TokenValue, 0)) Count = 0 while (Count < len(PcdList) - 1) : @@ -910,7 +969,7 @@ class WorkspaceAutoGen(AutoGen): Count += SameTokenValuePcdListCount Count += 1 - PcdList = Package.Pcds.values() + PcdList = list(Package.Pcds.values()) PcdList.sort(key=lambda x: "%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName)) Count = 0 while (Count < len(PcdList) - 1) : @@ -935,7 +994,56 @@ class WorkspaceAutoGen(AutoGen): @property def GenFdsCommandDict(self): - return GenMake.TopLevelMakefile(self)._TemplateDict + FdsCommandDict = {} + LogLevel = EdkLogger.GetLevel() + if LogLevel == EdkLogger.VERBOSE: + FdsCommandDict["verbose"] = True + elif LogLevel <= EdkLogger.DEBUG_9: + FdsCommandDict["debug"] = LogLevel - 1 + elif LogLevel == EdkLogger.QUIET: + FdsCommandDict["quiet"] = True + + if GlobalData.gEnableGenfdsMultiThread: + FdsCommandDict["GenfdsMultiThread"] = True + if GlobalData.gIgnoreSource: + FdsCommandDict["IgnoreSources"] = True + + FdsCommandDict["OptionPcd"] = [] + for pcd in GlobalData.BuildOptionPcd: + if pcd[2]: + pcdname = '.'.join(pcd[0:3]) + else: + pcdname = '.'.join(pcd[0:2]) + if pcd[3].startswith('{'): + FdsCommandDict["OptionPcd"].append(pcdname + '=' + 'H' + '"' + pcd[3] + '"') + else: + FdsCommandDict["OptionPcd"].append(pcdname + '=' + pcd[3]) + + MacroList = [] + # macros passed to GenFds + MacroDict = {} + MacroDict.update(GlobalData.gGlobalDefines) + MacroDict.update(GlobalData.gCommandLineDefines) + for MacroName in MacroDict: + if MacroDict[MacroName] != "": + MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\'))) + else: + MacroList.append('"%s"' % MacroName) + FdsCommandDict["macro"] = MacroList + + FdsCommandDict["fdf_file"] = [self.FdfFile] + FdsCommandDict["build_target"] = self.BuildTarget + FdsCommandDict["toolchain_tag"] = self.ToolChain + FdsCommandDict["active_platform"] = str(self) + + FdsCommandDict["conf_directory"] = GlobalData.gConfDirectory + FdsCommandDict["build_architecture_list"] = ','.join(self.ArchList) + FdsCommandDict["platform_build_directory"] = self.BuildDir + + FdsCommandDict["fd"] = self.FdTargetList + FdsCommandDict["fv"] = self.FvTargetList + FdsCommandDict["cap"] = self.CapTargetList + return FdsCommandDict ## Create makefile for the platform and modules in it # @@ -977,7 +1085,6 @@ class PlatformAutoGen(AutoGen): # call super().__init__ then call the worker function with different parameter count def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs): if not hasattr(self, "_Init"): - super(PlatformAutoGen, self).__init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs) self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch) self._Init = True # @@ -1028,10 +1135,8 @@ class PlatformAutoGen(AutoGen): self.BuildTarget = Target self.Arch = Arch self.SourceDir = PlatformFile.SubDir - self.SourceOverrideDir = None self.FdTargetList = self.Workspace.FdTargetList self.FvTargetList = self.Workspace.FvTargetList - self.AllPcdList = [] # get the original module/package/platform objects self.BuildDatabase = Workspace.BuildDatabase self.DscBuildDataObj = Workspace.Platform @@ -1075,7 +1180,7 @@ class PlatformAutoGen(AutoGen): # @cached_class_function def CreateCodeFile(self, CreateModuleCodeFile=False): - # only module has code to be greated, so do nothing if CreateModuleCodeFile is False + # only module has code to be created, so do nothing if CreateModuleCodeFile is False if not CreateModuleCodeFile: return @@ -1112,6 +1217,9 @@ class PlatformAutoGen(AutoGen): self.IsMakeFileCreated = True + @property + def AllPcdList(self): + return self.DynamicPcdList + self.NonDynamicPcdList ## Deal with Shared FixedAtBuild Pcds # def CollectFixedAtBuildPcds(self): @@ -1185,7 +1293,7 @@ class PlatformAutoGen(AutoGen): if os.path.exists(VpdMapFilePath): OrgVpdFile.Read(VpdMapFilePath) PcdItems = OrgVpdFile.GetOffset(PcdNvStoreDfBuffer[0]) - NvStoreOffset = PcdItems.values()[0].strip() if PcdItems else '0' + NvStoreOffset = list(PcdItems.values())[0].strip() if PcdItems else '0' else: EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath) @@ -1384,7 +1492,7 @@ class PlatformAutoGen(AutoGen): if (self.Workspace.ArchList[-1] == self.Arch): for Pcd in self._DynamicPcdList: # just pick the a value to determine whether is unicode string type - Sku = Pcd.SkuInfoList.values()[0] + Sku = Pcd.SkuInfoList.get(TAB_DEFAULT) Sku.VpdOffset = Sku.VpdOffset.strip() if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]: @@ -1490,7 +1598,7 @@ class PlatformAutoGen(AutoGen): if not FoundFlag : # just pick the a value to determine whether is unicode string type SkuValueMap = {} - SkuObjList = DscPcdEntry.SkuInfoList.items() + SkuObjList = list(DscPcdEntry.SkuInfoList.items()) DefaultSku = DscPcdEntry.SkuInfoList.get(TAB_DEFAULT) if DefaultSku: defaultindex = SkuObjList.index((TAB_DEFAULT, DefaultSku)) @@ -1516,7 +1624,7 @@ class PlatformAutoGen(AutoGen): DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName] # Only fix the value while no value provided in DSC file. if not Sku.DefaultValue: - DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]].DefaultValue = DecPcdEntry.DefaultValue + DscPcdEntry.SkuInfoList[list(DscPcdEntry.SkuInfoList.keys())[0]].DefaultValue = DecPcdEntry.DefaultValue if DscPcdEntry not in self._DynamicPcdList: self._DynamicPcdList.append(DscPcdEntry) @@ -1573,7 +1681,7 @@ class PlatformAutoGen(AutoGen): PcdName,PcdGuid = PcdNvStoreDfBuffer[0].TokenCName, PcdNvStoreDfBuffer[0].TokenSpaceGuidCName if (PcdName,PcdGuid) in VpdSkuMap: DefaultSku = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT) - VpdSkuMap[(PcdName,PcdGuid)] = {DefaultSku.DefaultValue:[DefaultSku]} + VpdSkuMap[(PcdName,PcdGuid)] = {DefaultSku.DefaultValue:[SkuObj for SkuObj in PcdNvStoreDfBuffer[0].SkuInfoList.values() ]} # Process VPD map file generated by third party BPDG tool if NeedProcessVpdMapFile: @@ -1598,7 +1706,7 @@ class PlatformAutoGen(AutoGen): # Delete the DynamicPcdList At the last time enter into this function for Pcd in self._DynamicPcdList: # just pick the a value to determine whether is unicode string type - Sku = Pcd.SkuInfoList.values()[0] + Sku = Pcd.SkuInfoList.get(TAB_DEFAULT) Sku.VpdOffset = Sku.VpdOffset.strip() if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]: @@ -1621,12 +1729,11 @@ class PlatformAutoGen(AutoGen): for pcd in self._DynamicPcdList: if len(pcd.SkuInfoList) == 1: for (SkuName, SkuId) in allskuset: - if type(SkuId) in (str, unicode) and eval(SkuId) == 0 or SkuId == 0: + if isinstance(SkuId, str) and eval(SkuId) == 0 or SkuId == 0: continue pcd.SkuInfoList[SkuName] = copy.deepcopy(pcd.SkuInfoList[TAB_DEFAULT]) pcd.SkuInfoList[SkuName].SkuId = SkuId pcd.SkuInfoList[SkuName].SkuIdName = SkuName - self.AllPcdList = self._NonDynamicPcdList + self._DynamicPcdList def FixVpdOffset(self, VpdFile ): FvPath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY) @@ -1719,11 +1826,11 @@ class PlatformAutoGen(AutoGen): def BuildCommand(self): RetVal = [] if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]: - RetVal += SplitOption(self.ToolDefinition["MAKE"]["PATH"]) + RetVal += _SplitOption(self.ToolDefinition["MAKE"]["PATH"]) if "FLAGS" in self.ToolDefinition["MAKE"]: NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip() if NewOption != '': - RetVal += SplitOption(NewOption) + RetVal += _SplitOption(NewOption) if "MAKE" in self.EdkIIBuildOption: if "FLAGS" in self.EdkIIBuildOption["MAKE"]: Flags = self.EdkIIBuildOption["MAKE"]["FLAGS"] @@ -1735,7 +1842,7 @@ class PlatformAutoGen(AutoGen): ## Get tool chain definition # - # Get each tool defition for given tool chain from tools_def.txt and platform + # Get each tool definition for given tool chain from tools_def.txt and platform # @cached_property def ToolDefinition(self): @@ -1792,7 +1899,7 @@ class PlatformAutoGen(AutoGen): ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value) ToolsDef += "\n" - SaveFileOnChange(self.ToolDefinitionFile, ToolsDef) + SaveFileOnChange(self.ToolDefinitionFile, ToolsDef, False) for DllPath in DllPathList: os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"] os.environ["MAKE_FLAGS"] = MakeFlags @@ -2016,8 +2123,8 @@ class PlatformAutoGen(AutoGen): ## Override PCD setting (type, value, ...) # - # @param ToPcd The PCD to be overrided - # @param FromPcd The PCD overrideing from + # @param ToPcd The PCD to be overridden + # @param FromPcd The PCD overriding from # def _OverridePcd(self, ToPcd, FromPcd, Module="", Msg="", Library=""): # @@ -2104,7 +2211,7 @@ class PlatformAutoGen(AutoGen): ## Apply PCD setting defined platform to a module # - # @param Module The module from which the PCD setting will be overrided + # @param Module The module from which the PCD setting will be overridden # # @retval PCD_list The list PCDs with settings from platform # @@ -2172,7 +2279,7 @@ class PlatformAutoGen(AutoGen): Pcd.MaxDatumSize = str(len(Value.split(','))) else: Pcd.MaxDatumSize = str(len(Value) - 1) - return Pcds.values() + return list(Pcds.values()) @@ -2241,7 +2348,7 @@ class PlatformAutoGen(AutoGen): # Use the highest priority value. # if (len(OverrideList) >= 2): - KeyList = OverrideList.keys() + KeyList = list(OverrideList.keys()) for Index in range(len(KeyList)): NowKey = KeyList[Index] Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_") @@ -2336,7 +2443,7 @@ class PlatformAutoGen(AutoGen): ## Append build options in platform to a module # - # @param Module The module to which the build options will be appened + # @param Module The module to which the build options will be appended # # @retval options The options appended with build options in platform # @@ -2359,9 +2466,9 @@ class PlatformAutoGen(AutoGen): if Attr == TAB_TOD_DEFINES_BUILDRULEORDER: BuildRuleOrder = Options[Tool][Attr] - AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() + - PlatformModuleOptions.keys() + ModuleTypeOptions.keys() + - self.ToolDefinition.keys()) + AllTools = set(list(ModuleOptions.keys()) + list(PlatformOptions.keys()) + + list(PlatformModuleOptions.keys()) + list(ModuleTypeOptions.keys()) + + list(self.ToolDefinition.keys())) BuildOptions = defaultdict(lambda: defaultdict(str)) for Tool in AllTools: for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]: @@ -2409,7 +2516,6 @@ class ModuleAutoGen(AutoGen): # call super().__init__ then call the worker function with different parameter count def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs): if not hasattr(self, "_Init"): - super(ModuleAutoGen, self).__init__(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs) self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args) self._Init = True @@ -2446,11 +2552,6 @@ class ModuleAutoGen(AutoGen): self.SourceDir = self.MetaFile.SubDir self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir) - self.SourceOverrideDir = None - # use overrided path defined in DSC file - if self.MetaFile.Key in GlobalData.gOverrideDir: - self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key] - self.ToolChain = Toolchain self.BuildTarget = Target self.Arch = Arch @@ -2572,7 +2673,7 @@ class ModuleAutoGen(AutoGen): def Guid(self): # # To build same module more than once, the module path with FILE_GUID overridden has - # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path + # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the real path # in DSC. The overridden GUID can be retrieved from file name # if os.path.basename(self.MetaFile.File) != os.path.basename(self.MetaFile.Path): @@ -2632,7 +2733,7 @@ class ModuleAutoGen(AutoGen): self.MetaFile.BaseName )) - ## Return the directory to store the intermediate object files of the mdoule + ## Return the directory to store the intermediate object files of the module @cached_property def OutputDir(self): return _MakeDir((self.BuildDir, "OUTPUT")) @@ -2644,7 +2745,7 @@ class ModuleAutoGen(AutoGen): return path.join(self.PlatformInfo.BuildDir, TAB_FV_DIRECTORY, "Ffs", self.Guid + self.Name) return '' - ## Return the directory to store auto-gened source files of the mdoule + ## Return the directory to store auto-gened source files of the module @cached_property def DebugDir(self): return _MakeDir((self.BuildDir, "DEBUG")) @@ -2655,12 +2756,7 @@ class ModuleAutoGen(AutoGen): RetVal = {} for Type in self.Module.CustomMakefile: MakeType = gMakeTypeMap[Type] if Type in gMakeTypeMap else 'nmake' - if self.SourceOverrideDir is not None: - File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type]) - if not os.path.exists(File): - File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type]) - else: - File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type]) + File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type]) RetVal[MakeType] = File return RetVal @@ -2696,7 +2792,7 @@ class ModuleAutoGen(AutoGen): ## Get the depex string # - # @return : a string contain all depex expresion. + # @return : a string contain all depex expression. def _GetDepexExpresionString(self): DepexStr = '' DepexList = [] @@ -2706,11 +2802,11 @@ class ModuleAutoGen(AutoGen): for M in [self.Module] + self.DependentLibraryList: Filename = M.MetaFile.Path InfObj = InfSectionParser.InfSectionParser(Filename) - DepexExpresionList = InfObj.GetDepexExpresionList() - for DepexExpresion in DepexExpresionList: - for key in DepexExpresion: + DepexExpressionList = InfObj.GetDepexExpresionList() + for DepexExpression in DepexExpressionList: + for key in DepexExpression: Arch, ModuleType = key - DepexExpr = [x for x in DepexExpresion[key] if not str(x).startswith('#')] + DepexExpr = [x for x in DepexExpression[key] if not str(x).startswith('#')] # the type of build module is USER_DEFINED. # All different DEPEX section tags would be copied into the As Built INF file # and there would be separate DEPEX section tags @@ -2765,7 +2861,7 @@ class ModuleAutoGen(AutoGen): DepexList = [] # - # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion + # Append depex from dependent libraries, if not "BEFORE", "AFTER" expression # for M in [self.Module] + self.DependentLibraryList: Inherited = False @@ -2779,10 +2875,16 @@ class ModuleAutoGen(AutoGen): if '.' not in item: NewList.append(item) else: - if item not in self._FixedPcdVoidTypeDict: + FixedVoidTypePcds = {} + if item in self.FixedVoidTypePcds: + FixedVoidTypePcds = self.FixedVoidTypePcds + elif M in self.PlatformInfo.LibraryAutoGenList: + Index = self.PlatformInfo.LibraryAutoGenList.index(M) + FixedVoidTypePcds = self.PlatformInfo.LibraryAutoGenList[Index].FixedVoidTypePcds + if item not in FixedVoidTypePcds: EdkLogger.error("build", FORMAT_INVALID, "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type in the module.".format(item)) else: - Value = self._FixedPcdVoidTypeDict[item] + Value = FixedVoidTypePcds[item] if len(Value.split(',')) != 16: EdkLogger.error("build", FORMAT_INVALID, "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type and 16 bytes in the module.".format(item)) @@ -2918,13 +3020,14 @@ class ModuleAutoGen(AutoGen): # EDK II modules must not reference header files outside of the packages they depend on or # within the module's directory tree. Report error if violation. # - for Path in IncPathList: - if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir): - ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption) - EdkLogger.error("build", - PARAMETER_INVALID, - ExtraData=ErrMsg, - File=str(self.MetaFile)) + if GlobalData.gDisableIncludePathCheck == False: + for Path in IncPathList: + if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir): + ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption) + EdkLogger.error("build", + PARAMETER_INVALID, + ExtraData=ErrMsg, + File=str(self.MetaFile)) RetVal += IncPathList return RetVal @@ -2969,7 +3072,7 @@ class ModuleAutoGen(AutoGen): self.BuildOption for SingleFile in FileList: if self.BuildRuleOrder and SingleFile.Ext in self.BuildRuleOrder and SingleFile.Ext in self.BuildRules: - key = SingleFile.Path.split(SingleFile.Ext)[0] + key = SingleFile.Path.rsplit(SingleFile.Ext,1)[0] if key in Order_Dict: Order_Dict[key].append(SingleFile.Ext) else: @@ -3190,7 +3293,7 @@ class ModuleAutoGen(AutoGen): AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir) RetVal[AutoFile] = str(StringH) self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE) - if UniStringBinBuffer is not None and UniStringBinBuffer.getvalue() != "": + if UniStringBinBuffer is not None and UniStringBinBuffer.getvalue() != b"": AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir) RetVal[AutoFile] = UniStringBinBuffer.getvalue() AutoFile.IsBinary = True @@ -3201,7 +3304,7 @@ class ModuleAutoGen(AutoGen): AutoFile = PathClass(gAutoGenImageDefFileName % {"module_name":self.Name}, self.DebugDir) RetVal[AutoFile] = str(StringIdf) self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE) - if IdfGenBinBuffer is not None and IdfGenBinBuffer.getvalue() != "": + if IdfGenBinBuffer is not None and IdfGenBinBuffer.getvalue() != b"": AutoFile = PathClass(gAutoGenIdfFileName % {"module_name":self.Name}, self.OutputDir) RetVal[AutoFile] = IdfGenBinBuffer.getvalue() AutoFile.IsBinary = True @@ -3210,7 +3313,7 @@ class ModuleAutoGen(AutoGen): IdfGenBinBuffer.close() return RetVal - ## Return the list of library modules explicitly or implicityly used by this module + ## Return the list of library modules explicitly or implicitly used by this module @cached_property def DependentLibraryList(self): # only merge library classes and PCD for non-library module @@ -3313,7 +3416,7 @@ class ModuleAutoGen(AutoGen): RetVal.append(PackageDir) IncludesList = Package.Includes if Package._PrivateIncludes: - if not self.MetaFile.Path.startswith(PackageDir): + if not self.MetaFile.OriginalPath.Path.startswith(PackageDir): IncludesList = list(set(Package.Includes).difference(set(Package._PrivateIncludes))) for Inc in IncludesList: if Inc not in RetVal: @@ -3367,7 +3470,7 @@ class ModuleAutoGen(AutoGen): Guid = gEfiVarStoreGuidPattern.search(Content, Pos) if not Guid: break - NameArray = ConvertStringToByteArray('L"' + Name.group(1) + '"') + NameArray = _ConvertStringToByteArray('L"' + Name.group(1) + '"') NameGuids.add((NameArray, GuidStructureStringToGuidString(Guid.group(1)))) Pos = Content.find('efivarstore', Name.end()) if not NameGuids: @@ -3380,7 +3483,7 @@ class ModuleAutoGen(AutoGen): Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList, self.MetaFile.Path) if not Value: continue - Name = ConvertStringToByteArray(SkuInfo.VariableName) + Name = _ConvertStringToByteArray(SkuInfo.VariableName) Guid = GuidStructureStringToGuidString(Value) if (Name, Guid) in NameGuids and Pcd not in HiiExPcds: HiiExPcds.append(Pcd) @@ -3406,7 +3509,7 @@ class ModuleAutoGen(AutoGen): return None MapFileName = os.path.join(self.OutputDir, self.Name + ".map") EfiFileName = os.path.join(self.OutputDir, self.Name + ".efi") - VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, VfrUniBaseName.values()) + VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, list(VfrUniBaseName.values())) if not VfrUniOffsetList: return None @@ -3419,7 +3522,7 @@ class ModuleAutoGen(AutoGen): EdkLogger.error("build", FILE_OPEN_FAILURE, "File open failed for %s" % UniVfrOffsetFileName, None) # Use a instance of BytesIO to cache data - fStringIO = BytesIO('') + fStringIO = BytesIO() for Item in VfrUniOffsetList: if (Item[0].find("Strings") != -1): @@ -3428,9 +3531,8 @@ class ModuleAutoGen(AutoGen): # GUID + Offset # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } } # - UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66] - UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid] - fStringIO.write(''.join(UniGuid)) + UniGuid = b'\xe0\xc5\x13\x89\xf63\x86M\x9b\xf1C\xef\x89\xfc\x06f' + fStringIO.write(UniGuid) UniValue = pack ('Q', int (Item[1], 16)) fStringIO.write (UniValue) else: @@ -3439,9 +3541,8 @@ class ModuleAutoGen(AutoGen): # GUID + Offset # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } }; # - VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2] - VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid] - fStringIO.write(''.join(VfrGuid)) + VfrGuid = b'\xb4|\xbc\xd0Gj_I\xaa\x11q\x07F\xda\x06\xa2' + fStringIO.write(VfrGuid) VfrValue = pack ('Q', int (Item[1], 16)) fStringIO.write (VfrValue) # @@ -3701,7 +3802,7 @@ class ModuleAutoGen(AutoGen): Padding = '0x00, ' if Unicode: Padding = Padding * 2 - ArraySize = ArraySize / 2 + ArraySize = ArraySize // 2 if ArraySize < (len(PcdValue) + 1): if Pcd.MaxSizeUserSet: EdkLogger.error("build", AUTOGEN_ERROR, @@ -3783,8 +3884,8 @@ class ModuleAutoGen(AutoGen): AsBuiltInfDict['userextension_tianocore_item'] = UserExtStr # Generated depex expression section in comments. - DepexExpresion = self._GetDepexExpresionString() - AsBuiltInfDict['depexsection_item'] = DepexExpresion if DepexExpresion else '' + DepexExpression = self._GetDepexExpresionString() + AsBuiltInfDict['depexsection_item'] = DepexExpression if DepexExpression else '' AsBuiltInf = TemplateString() AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict)) @@ -3796,16 +3897,17 @@ class ModuleAutoGen(AutoGen): self.CopyModuleToCache() def CopyModuleToCache(self): - FileDir = path.join(GlobalData.gBinCacheDest, self.Arch, self.SourceDir, self.MetaFile.BaseName) + FileDir = path.join(GlobalData.gBinCacheDest, self.PlatformInfo.OutputDir, self.BuildTarget + "_" + self.ToolChain, self.Arch, self.SourceDir, self.MetaFile.BaseName) CreateDirectory (FileDir) HashFile = path.join(self.BuildDir, self.Name + '.hash') - ModuleFile = path.join(self.OutputDir, self.Name + '.inf') if os.path.exists(HashFile): shutil.copy2(HashFile, FileDir) - if os.path.exists(ModuleFile): - shutil.copy2(ModuleFile, FileDir) + if not self.IsLibrary: + ModuleFile = path.join(self.OutputDir, self.Name + '.inf') + if os.path.exists(ModuleFile): + shutil.copy2(ModuleFile, FileDir) if not self.OutputFile: - Ma = self.BuildDatabase[PathClass(ModuleFile), self.Arch, self.BuildTarget, self.ToolChain] + Ma = self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain] self.OutputFile = Ma.Binaries if self.OutputFile: for File in self.OutputFile: @@ -3813,17 +3915,27 @@ class ModuleAutoGen(AutoGen): if not os.path.isabs(File): File = os.path.join(self.OutputDir, File) if os.path.exists(File): - shutil.copy2(File, FileDir) + sub_dir = os.path.relpath(File, self.OutputDir) + destination_file = os.path.join(FileDir, sub_dir) + destination_dir = os.path.dirname(destination_file) + CreateDirectory(destination_dir) + shutil.copy2(File, destination_dir) def AttemptModuleCacheCopy(self): + # If library or Module is binary do not skip by hash if self.IsBinaryModule: return False - FileDir = path.join(GlobalData.gBinCacheSource, self.Arch, self.SourceDir, self.MetaFile.BaseName) + # .inc is contains binary information so do not skip by hash as well + for f_ext in self.SourceFileList: + if '.inc' in str(f_ext): + return False + FileDir = path.join(GlobalData.gBinCacheSource, self.PlatformInfo.OutputDir, self.BuildTarget + "_" + self.ToolChain, self.Arch, self.SourceDir, self.MetaFile.BaseName) HashFile = path.join(FileDir, self.Name + '.hash') if os.path.exists(HashFile): f = open(HashFile, 'r') CacheHash = f.read() f.close() + self.GenModuleHash() if GlobalData.gModuleHash[self.Arch][self.Name]: if CacheHash == GlobalData.gModuleHash[self.Arch][self.Name]: for root, dir, files in os.walk(FileDir): @@ -3832,7 +3944,11 @@ class ModuleAutoGen(AutoGen): shutil.copy2(HashFile, self.BuildDir) else: File = path.join(root, f) - shutil.copy2(File, self.OutputDir) + sub_dir = os.path.relpath(File, FileDir) + destination_file = os.path.join(self.OutputDir, sub_dir) + destination_dir = os.path.dirname(destination_file) + CreateDirectory(destination_dir) + shutil.copy2(File, destination_dir) if self.Name == "PcdPeim" or self.Name == "PcdDxe": CreatePcdDatabaseCode(self, TemplateString(), TemplateString()) return True @@ -3978,50 +4094,86 @@ class ModuleAutoGen(AutoGen): return RetVal def GenModuleHash(self): + # Initialize a dictionary for each arch type if self.Arch not in GlobalData.gModuleHash: GlobalData.gModuleHash[self.Arch] = {} + + # Early exit if module or library has been hashed and is in memory + if self.Name in GlobalData.gModuleHash[self.Arch]: + return GlobalData.gModuleHash[self.Arch][self.Name].encode('utf-8') + + # Initialze hash object m = hashlib.md5() + # Add Platform level hash - m.update(GlobalData.gPlatformHash) + m.update(GlobalData.gPlatformHash.encode('utf-8')) + # Add Package level hash if self.DependentPackageList: for Pkg in sorted(self.DependentPackageList, key=lambda x: x.PackageName): - if Pkg.PackageName in GlobalData.gPackageHash[self.Arch]: - m.update(GlobalData.gPackageHash[self.Arch][Pkg.PackageName]) + if Pkg.PackageName in GlobalData.gPackageHash: + m.update(GlobalData.gPackageHash[Pkg.PackageName].encode('utf-8')) # Add Library hash if self.LibraryAutoGenList: for Lib in sorted(self.LibraryAutoGenList, key=lambda x: x.Name): if Lib.Name not in GlobalData.gModuleHash[self.Arch]: Lib.GenModuleHash() - m.update(GlobalData.gModuleHash[self.Arch][Lib.Name]) + m.update(GlobalData.gModuleHash[self.Arch][Lib.Name].encode('utf-8')) # Add Module self - f = open(str(self.MetaFile), 'r') + f = open(str(self.MetaFile), 'rb') Content = f.read() f.close() m.update(Content) + # Add Module's source files if self.SourceFileList: for File in sorted(self.SourceFileList, key=lambda x: str(x)): - f = open(str(File), 'r') + f = open(str(File), 'rb') Content = f.read() f.close() m.update(Content) - ModuleHashFile = path.join(self.BuildDir, self.Name + ".hash") - if self.Name not in GlobalData.gModuleHash[self.Arch]: - GlobalData.gModuleHash[self.Arch][self.Name] = m.hexdigest() - if GlobalData.gBinCacheSource: - if self.AttemptModuleCacheCopy(): - return False - return SaveFileOnChange(ModuleHashFile, m.hexdigest(), True) + GlobalData.gModuleHash[self.Arch][self.Name] = m.hexdigest() + + return GlobalData.gModuleHash[self.Arch][self.Name].encode('utf-8') ## Decide whether we can skip the ModuleAutoGen process def CanSkipbyHash(self): - if GlobalData.gUseHashCache: - return not self.GenModuleHash() - return False + # Hashing feature is off + if not GlobalData.gUseHashCache: + return False + + # Initialize a dictionary for each arch type + if self.Arch not in GlobalData.gBuildHashSkipTracking: + GlobalData.gBuildHashSkipTracking[self.Arch] = dict() + + # If library or Module is binary do not skip by hash + if self.IsBinaryModule: + return False + + # .inc is contains binary information so do not skip by hash as well + for f_ext in self.SourceFileList: + if '.inc' in str(f_ext): + return False + + # Use Cache, if exists and if Module has a copy in cache + if GlobalData.gBinCacheSource and self.AttemptModuleCacheCopy(): + return True + + # Early exit for libraries that haven't yet finished building + HashFile = path.join(self.BuildDir, self.Name + ".hash") + if self.IsLibrary and not os.path.exists(HashFile): + return False + + # Return a Boolean based on if can skip by hash, either from memory or from IO. + if self.Name not in GlobalData.gBuildHashSkipTracking[self.Arch]: + # If hashes are the same, SaveFileOnChange() will return False. + GlobalData.gBuildHashSkipTracking[self.Arch][self.Name] = not SaveFileOnChange(HashFile, self.GenModuleHash(), True) + return GlobalData.gBuildHashSkipTracking[self.Arch][self.Name] + else: + return GlobalData.gBuildHashSkipTracking[self.Arch][self.Name] ## Decide whether we can skip the ModuleAutoGen process # If any source file is newer than the module than we cannot skip