diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
commit | f215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch) | |
tree | 6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenMake.py | |
parent | Initial commit. (diff) | |
download | virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip |
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenMake.py')
-rwxr-xr-x | src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenMake.py | 1810 |
1 files changed, 1810 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenMake.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenMake.py new file mode 100755 index 00000000..130557de --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenMake.py @@ -0,0 +1,1810 @@ +## @file +# Create makefile for MS nmake and GNU make +# +# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR> +# Copyright (c) 2020, ARM Limited. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +## Import Modules +# +from __future__ import absolute_import +import Common.LongFilePathOs as os +import sys +import string +import re +import os.path as path +from Common.LongFilePathSupport import OpenLongFilePath as open +from Common.MultipleWorkspace import MultipleWorkspace as mws +from Common.BuildToolError import * +from Common.Misc import * +from Common.StringUtils import * +from .BuildEngine import * +import Common.GlobalData as GlobalData +from collections import OrderedDict +from Common.DataType import TAB_COMPILER_MSFT + +## Regular expression for finding header file inclusions +gIncludePattern = re.compile(r"^[ \t]*[#%]?[ \t]*include(?:[ \t]*(?:\\(?:\r\n|\r|\n))*[ \t]*)*(?:\(?[\"<]?[ \t]*)([-\w.\\/() \t]+)(?:[ \t]*[\">]?\)?)", re.MULTILINE | re.UNICODE | re.IGNORECASE) + +## Regular expression for matching macro used in header file inclusion +gMacroPattern = re.compile("([_A-Z][_A-Z0-9]*)[ \t]*\((.+)\)", re.UNICODE) + +gIsFileMap = {} + +## pattern for include style in Edk.x code +gProtocolDefinition = "Protocol/%(HeaderKey)s/%(HeaderKey)s.h" +gGuidDefinition = "Guid/%(HeaderKey)s/%(HeaderKey)s.h" +gArchProtocolDefinition = "ArchProtocol/%(HeaderKey)s/%(HeaderKey)s.h" +gPpiDefinition = "Ppi/%(HeaderKey)s/%(HeaderKey)s.h" +gIncludeMacroConversion = { + "EFI_PROTOCOL_DEFINITION" : gProtocolDefinition, + "EFI_GUID_DEFINITION" : gGuidDefinition, + "EFI_ARCH_PROTOCOL_DEFINITION" : gArchProtocolDefinition, + "EFI_PROTOCOL_PRODUCER" : gProtocolDefinition, + "EFI_PROTOCOL_CONSUMER" : gProtocolDefinition, + "EFI_PROTOCOL_DEPENDENCY" : gProtocolDefinition, + "EFI_ARCH_PROTOCOL_PRODUCER" : gArchProtocolDefinition, + "EFI_ARCH_PROTOCOL_CONSUMER" : gArchProtocolDefinition, + "EFI_ARCH_PROTOCOL_DEPENDENCY" : gArchProtocolDefinition, + "EFI_PPI_DEFINITION" : gPpiDefinition, + "EFI_PPI_PRODUCER" : gPpiDefinition, + "EFI_PPI_CONSUMER" : gPpiDefinition, + "EFI_PPI_DEPENDENCY" : gPpiDefinition, +} + +NMAKE_FILETYPE = "nmake" +GMAKE_FILETYPE = "gmake" +WIN32_PLATFORM = "win32" +POSIX_PLATFORM = "posix" + +## BuildFile class +# +# This base class encapsules build file and its generation. It uses template to generate +# the content of build file. The content of build file will be got from AutoGen objects. +# +class BuildFile(object): + ## template used to generate the build file (i.e. makefile if using make) + _TEMPLATE_ = TemplateString('') + + _DEFAULT_FILE_NAME_ = "Makefile" + + ## default file name for each type of build file + _FILE_NAME_ = { + NMAKE_FILETYPE : "Makefile", + GMAKE_FILETYPE : "GNUmakefile" + } + + # Get Makefile name. + def getMakefileName(self): + if not self._FileType: + return self._DEFAULT_FILE_NAME_ + else: + return self._FILE_NAME_[self._FileType] + + ## Fixed header string for makefile + _MAKEFILE_HEADER = '''# +# DO NOT EDIT +# This file is auto-generated by build utility +# +# Module Name: +# +# %s +# +# Abstract: +# +# Auto-generated makefile for building modules, libraries or platform +# + ''' + + ## Header string for each type of build file + _FILE_HEADER_ = { + NMAKE_FILETYPE : _MAKEFILE_HEADER % _FILE_NAME_[NMAKE_FILETYPE], + GMAKE_FILETYPE : _MAKEFILE_HEADER % _FILE_NAME_[GMAKE_FILETYPE] + } + + ## shell commands which can be used in build file in the form of macro + # $(CP) copy file command + # $(MV) move file command + # $(RM) remove file command + # $(MD) create dir command + # $(RD) remove dir command + # + _SHELL_CMD_ = { + WIN32_PLATFORM : { + "CP" : "copy /y", + "MV" : "move /y", + "RM" : "del /f /q", + "MD" : "mkdir", + "RD" : "rmdir /s /q", + }, + + POSIX_PLATFORM : { + "CP" : "cp -f", + "MV" : "mv -f", + "RM" : "rm -f", + "MD" : "mkdir -p", + "RD" : "rm -r -f", + } + } + + ## directory separator + _SEP_ = { + WIN32_PLATFORM : "\\", + POSIX_PLATFORM : "/" + } + + ## directory creation template + _MD_TEMPLATE_ = { + WIN32_PLATFORM : 'if not exist %(dir)s $(MD) %(dir)s', + POSIX_PLATFORM : "$(MD) %(dir)s" + } + + ## directory removal template + _RD_TEMPLATE_ = { + WIN32_PLATFORM : 'if exist %(dir)s $(RD) %(dir)s', + POSIX_PLATFORM : "$(RD) %(dir)s" + } + ## cp if exist + _CP_TEMPLATE_ = { + WIN32_PLATFORM : 'if exist %(Src)s $(CP) %(Src)s %(Dst)s', + POSIX_PLATFORM : "test -f %(Src)s && $(CP) %(Src)s %(Dst)s" + } + + _CD_TEMPLATE_ = { + WIN32_PLATFORM : 'if exist %(dir)s cd %(dir)s', + POSIX_PLATFORM : "test -e %(dir)s && cd %(dir)s" + } + + _MAKE_TEMPLATE_ = { + WIN32_PLATFORM : 'if exist %(file)s "$(MAKE)" $(MAKE_FLAGS) -f %(file)s', + POSIX_PLATFORM : 'test -e %(file)s && "$(MAKE)" $(MAKE_FLAGS) -f %(file)s' + } + + _INCLUDE_CMD_ = { + NMAKE_FILETYPE : '!INCLUDE', + GMAKE_FILETYPE : "include" + } + + _INC_FLAG_ = {TAB_COMPILER_MSFT : "/I", "GCC" : "-I", "INTEL" : "-I", "RVCT" : "-I", "NASM" : "-I"} + + ## Constructor of BuildFile + # + # @param AutoGenObject Object of AutoGen class + # + def __init__(self, AutoGenObject): + self._AutoGenObject = AutoGenObject + + MakePath = AutoGenObject.BuildOption.get('MAKE', {}).get('PATH') + if not MakePath: + self._FileType = "" + elif "nmake" in MakePath: + self._FileType = NMAKE_FILETYPE + else: + self._FileType = "gmake" + + if sys.platform == "win32": + self._Platform = WIN32_PLATFORM + else: + self._Platform = POSIX_PLATFORM + + ## Create build file. + # + # Only nmake and gmake are supported. + # + # @retval TRUE The build file is created or re-created successfully. + # @retval FALSE The build file exists and is the same as the one to be generated. + # + def Generate(self): + FileContent = self._TEMPLATE_.Replace(self._TemplateDict) + FileName = self.getMakefileName() + if not os.path.exists(os.path.join(self._AutoGenObject.MakeFileDir, "deps.txt")): + with open(os.path.join(self._AutoGenObject.MakeFileDir, "deps.txt"),"w+") as fd: + fd.write("") + if not os.path.exists(os.path.join(self._AutoGenObject.MakeFileDir, "dependency")): + with open(os.path.join(self._AutoGenObject.MakeFileDir, "dependency"),"w+") as fd: + fd.write("") + if not os.path.exists(os.path.join(self._AutoGenObject.MakeFileDir, "deps_target")): + with open(os.path.join(self._AutoGenObject.MakeFileDir, "deps_target"),"w+") as fd: + fd.write("") + return SaveFileOnChange(os.path.join(self._AutoGenObject.MakeFileDir, FileName), FileContent, False) + + ## Return a list of directory creation command string + # + # @param DirList The list of directory to be created + # + # @retval list The directory creation command list + # + def GetCreateDirectoryCommand(self, DirList): + return [self._MD_TEMPLATE_[self._Platform] % {'dir':Dir} for Dir in DirList] + + ## Return a list of directory removal command string + # + # @param DirList The list of directory to be removed + # + # @retval list The directory removal command list + # + def GetRemoveDirectoryCommand(self, DirList): + return [self._RD_TEMPLATE_[self._Platform] % {'dir':Dir} for Dir in DirList] + + def PlaceMacro(self, Path, MacroDefinitions=None): + if Path.startswith("$("): + return Path + else: + if MacroDefinitions is None: + MacroDefinitions = {} + PathLength = len(Path) + for MacroName in MacroDefinitions: + MacroValue = MacroDefinitions[MacroName] + MacroValueLength = len(MacroValue) + if MacroValueLength == 0: + continue + if MacroValueLength <= PathLength and Path.startswith(MacroValue): + Path = "$(%s)%s" % (MacroName, Path[MacroValueLength:]) + break + return Path + +## ModuleMakefile class +# +# This class encapsules makefie and its generation for module. It uses template to generate +# the content of makefile. The content of makefile will be got from ModuleAutoGen object. +# +class ModuleMakefile(BuildFile): + ## template used to generate the makefile for module + _TEMPLATE_ = TemplateString('''\ +${makefile_header} + +# +# Platform Macro Definition +# +PLATFORM_NAME = ${platform_name} +PLATFORM_GUID = ${platform_guid} +PLATFORM_VERSION = ${platform_version} +PLATFORM_RELATIVE_DIR = ${platform_relative_directory} +PLATFORM_DIR = ${platform_dir} +PLATFORM_OUTPUT_DIR = ${platform_output_directory} + +# +# Module Macro Definition +# +MODULE_NAME = ${module_name} +MODULE_GUID = ${module_guid} +MODULE_NAME_GUID = ${module_name_guid} +MODULE_VERSION = ${module_version} +MODULE_TYPE = ${module_type} +MODULE_FILE = ${module_file} +MODULE_FILE_BASE_NAME = ${module_file_base_name} +BASE_NAME = $(MODULE_NAME) +MODULE_RELATIVE_DIR = ${module_relative_directory} +PACKAGE_RELATIVE_DIR = ${package_relative_directory} +MODULE_DIR = ${module_dir} +FFS_OUTPUT_DIR = ${ffs_output_directory} + +MODULE_ENTRY_POINT = ${module_entry_point} +ARCH_ENTRY_POINT = ${arch_entry_point} +IMAGE_ENTRY_POINT = ${image_entry_point} + +${BEGIN}${module_extra_defines} +${END} +# +# Build Configuration Macro Definition +# +ARCH = ${architecture} +TOOLCHAIN = ${toolchain_tag} +TOOLCHAIN_TAG = ${toolchain_tag} +TARGET = ${build_target} + +# +# Build Directory Macro Definition +# +# PLATFORM_BUILD_DIR = ${platform_build_directory} +BUILD_DIR = ${platform_build_directory} +BIN_DIR = $(BUILD_DIR)${separator}${architecture} +LIB_DIR = $(BIN_DIR) +MODULE_BUILD_DIR = ${module_build_directory} +OUTPUT_DIR = ${module_output_directory} +DEBUG_DIR = ${module_debug_directory} +DEST_DIR_OUTPUT = $(OUTPUT_DIR) +DEST_DIR_DEBUG = $(DEBUG_DIR) + +# +# Shell Command Macro +# +${BEGIN}${shell_command_code} = ${shell_command} +${END} + +# +# Tools definitions specific to this module +# +${BEGIN}${module_tool_definitions} +${END} +MAKE_FILE = ${makefile_path} + +# +# Build Macro +# +${BEGIN}${file_macro} +${END} + +# +# Overridable Target Macro Definitions +# +FORCE_REBUILD = force_build +INIT_TARGET = init +PCH_TARGET = +BC_TARGET = ${BEGIN}${backward_compatible_target} ${END} +CODA_TARGET = ${BEGIN}${remaining_build_target} \\ + ${END} + +# +# Default target, which will build dependent libraries in addition to source files +# + +all: mbuild + + +# +# Target used when called from platform makefile, which will bypass the build of dependent libraries +# + +pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET) + +# +# ModuleTarget +# + +mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET) + +# +# Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets +# + +tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET) + +# +# Phony target which is used to force executing commands for a target +# +force_build: +\t-@ + +# +# Target to update the FD +# + +fds: mbuild gen_fds + +# +# Initialization target: print build information and create necessary directories +# +init: info dirs + +info: +\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)] + +dirs: +${BEGIN}\t-@${create_directory_command}\n${END} + +strdefs: +\t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h + +# +# GenLibsTarget +# +gen_libs: +\t${BEGIN}@"$(MAKE)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name} +\t${END}@cd $(MODULE_BUILD_DIR) + +# +# Build Flash Device Image +# +gen_fds: +\t@"$(MAKE)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds +\t@cd $(MODULE_BUILD_DIR) + +${INCLUDETAG} + +# +# Individual Object Build Targets +# +${BEGIN}${file_build_target} +${END} + +# +# clean all intermediate files +# +clean: +\t${BEGIN}${clean_command} +\t${END}\t$(RM) AutoGenTimeStamp + +# +# clean all generated files +# +cleanall: +${BEGIN}\t${cleanall_command} +${END}\t$(RM) *.pdb *.idb > NUL 2>&1 +\t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi +\t$(RM) AutoGenTimeStamp + +# +# clean all dependent libraries built +# +cleanlib: +\t${BEGIN}-@${library_build_command} cleanall +\t${END}@cd $(MODULE_BUILD_DIR)\n\n''') + + _FILE_MACRO_TEMPLATE = TemplateString("${macro_name} = ${BEGIN} \\\n ${source_file}${END}\n") + _BUILD_TARGET_TEMPLATE = TemplateString("${BEGIN}${target} : ${deps}\n${END}\t${cmd}\n") + + ## Constructor of ModuleMakefile + # + # @param ModuleAutoGen Object of ModuleAutoGen class + # + def __init__(self, ModuleAutoGen): + BuildFile.__init__(self, ModuleAutoGen) + self.PlatformInfo = self._AutoGenObject.PlatformInfo + + self.ResultFileList = [] + self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"] + + self.FileBuildTargetList = [] # [(src, target string)] + self.BuildTargetList = [] # [target string] + self.PendingBuildTargetList = [] # [FileBuildRule objects] + self.CommonFileDependency = [] + self.FileListMacros = {} + self.ListFileMacros = {} + self.ObjTargetDict = OrderedDict() + self.FileCache = {} + self.LibraryBuildCommandList = [] + self.LibraryFileList = [] + self.LibraryMakefileList = [] + self.LibraryBuildDirectoryList = [] + self.SystemLibraryList = [] + self.Macros = OrderedDict() + self.Macros["OUTPUT_DIR" ] = self._AutoGenObject.Macros["OUTPUT_DIR"] + self.Macros["DEBUG_DIR" ] = self._AutoGenObject.Macros["DEBUG_DIR"] + self.Macros["MODULE_BUILD_DIR"] = self._AutoGenObject.Macros["MODULE_BUILD_DIR"] + self.Macros["BIN_DIR" ] = self._AutoGenObject.Macros["BIN_DIR"] + self.Macros["BUILD_DIR" ] = self._AutoGenObject.Macros["BUILD_DIR"] + self.Macros["WORKSPACE" ] = self._AutoGenObject.Macros["WORKSPACE"] + self.Macros["FFS_OUTPUT_DIR" ] = self._AutoGenObject.Macros["FFS_OUTPUT_DIR"] + self.GenFfsList = ModuleAutoGen.GenFfsList + self.MacroList = ['FFS_OUTPUT_DIR', 'MODULE_GUID', 'OUTPUT_DIR'] + self.FfsOutputFileList = [] + self.DependencyHeaderFileSet = set() + + # Compose a dict object containing information used to do replacement in template + @property + def _TemplateDict(self): + MyAgo = self._AutoGenObject + Separator = self._SEP_[self._Platform] + + # break build if no source files and binary files are found + if len(MyAgo.SourceFileList) == 0 and len(MyAgo.BinaryFileList) == 0: + EdkLogger.error("build", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]" + % (MyAgo.BuildTarget, MyAgo.ToolChain, MyAgo.Arch), + ExtraData="[%s]" % str(MyAgo)) + + # convert dependent libraries to build command + self.ProcessDependentLibrary() + if len(MyAgo.Module.ModuleEntryPointList) > 0: + ModuleEntryPoint = MyAgo.Module.ModuleEntryPointList[0] + else: + ModuleEntryPoint = "_ModuleEntryPoint" + + ArchEntryPoint = ModuleEntryPoint + + if MyAgo.Arch == "EBC": + # EBC compiler always use "EfiStart" as entry point. Only applies to EdkII modules + ImageEntryPoint = "EfiStart" + else: + # EdkII modules always use "_ModuleEntryPoint" as entry point + ImageEntryPoint = "_ModuleEntryPoint" + + for k, v in MyAgo.Module.Defines.items(): + if k not in MyAgo.Macros: + MyAgo.Macros[k] = v + + if 'MODULE_ENTRY_POINT' not in MyAgo.Macros: + MyAgo.Macros['MODULE_ENTRY_POINT'] = ModuleEntryPoint + if 'ARCH_ENTRY_POINT' not in MyAgo.Macros: + MyAgo.Macros['ARCH_ENTRY_POINT'] = ArchEntryPoint + if 'IMAGE_ENTRY_POINT' not in MyAgo.Macros: + MyAgo.Macros['IMAGE_ENTRY_POINT'] = ImageEntryPoint + + PCI_COMPRESS_Flag = False + for k, v in MyAgo.Module.Defines.items(): + if 'PCI_COMPRESS' == k and 'TRUE' == v: + PCI_COMPRESS_Flag = True + + # tools definitions + ToolsDef = [] + IncPrefix = self._INC_FLAG_[MyAgo.ToolChainFamily] + for Tool in sorted(list(MyAgo.BuildOption)): + Appended = False + for Attr in sorted(list(MyAgo.BuildOption[Tool])): + Value = MyAgo.BuildOption[Tool][Attr] + if Attr == "FAMILY": + continue + elif Attr == "PATH": + ToolsDef.append("%s = %s" % (Tool, Value)) + Appended = True + else: + # Don't generate MAKE_FLAGS in makefile. It's put in environment variable. + if Tool == "MAKE": + continue + # Remove duplicated include path, if any + if Attr == "FLAGS": + Value = RemoveDupOption(Value, IncPrefix, MyAgo.IncludePathList) + if Tool == "OPTROM" and PCI_COMPRESS_Flag: + ValueList = Value.split() + if ValueList: + for i, v in enumerate(ValueList): + if '-e' == v: + ValueList[i] = '-ec' + Value = ' '.join(ValueList) + + ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value)) + Appended = True + if Appended: + ToolsDef.append("") + + # generate the Response file and Response flag + RespDict = self.CommandExceedLimit() + RespFileList = os.path.join(MyAgo.OutputDir, 'respfilelist.txt') + if RespDict: + RespFileListContent = '' + for Resp in RespDict: + RespFile = os.path.join(MyAgo.OutputDir, str(Resp).lower() + '.txt') + StrList = RespDict[Resp].split(' ') + UnexpandMacro = [] + NewStr = [] + for Str in StrList: + if '$' in Str or '-MMD' in Str or '-MF' in Str: + UnexpandMacro.append(Str) + else: + NewStr.append(Str) + UnexpandMacroStr = ' '.join(UnexpandMacro) + NewRespStr = ' '.join(NewStr) + SaveFileOnChange(RespFile, NewRespStr, False) + ToolsDef.append("%s = %s" % (Resp, UnexpandMacroStr + ' @' + RespFile)) + RespFileListContent += '@' + RespFile + TAB_LINE_BREAK + RespFileListContent += NewRespStr + TAB_LINE_BREAK + SaveFileOnChange(RespFileList, RespFileListContent, False) + else: + if os.path.exists(RespFileList): + os.remove(RespFileList) + + # convert source files and binary files to build targets + self.ResultFileList = [str(T.Target) for T in MyAgo.CodaTargetList] + if len(self.ResultFileList) == 0 and len(MyAgo.SourceFileList) != 0: + EdkLogger.error("build", AUTOGEN_ERROR, "Nothing to build", + ExtraData="[%s]" % str(MyAgo)) + + self.ProcessBuildTargetList(MyAgo.OutputDir, ToolsDef) + self.ParserGenerateFfsCmd() + + # Generate macros used to represent input files + FileMacroList = [] # macro name = file list + for FileListMacro in self.FileListMacros: + FileMacro = self._FILE_MACRO_TEMPLATE.Replace( + { + "macro_name" : FileListMacro, + "source_file" : self.FileListMacros[FileListMacro] + } + ) + FileMacroList.append(FileMacro) + + # INC_LIST is special + FileMacro = "" + IncludePathList = [] + for P in MyAgo.IncludePathList: + IncludePathList.append(IncPrefix + self.PlaceMacro(P, self.Macros)) + if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros: + self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix + P) + FileMacro += self._FILE_MACRO_TEMPLATE.Replace( + { + "macro_name" : "INC", + "source_file" : IncludePathList + } + ) + FileMacroList.append(FileMacro) + # Add support when compiling .nasm source files + IncludePathList = [] + asmsource = [item for item in MyAgo.SourceFileList if item.File.upper().endswith((".NASM",".ASM",".NASMB","S"))] + if asmsource: + for P in MyAgo.IncludePathList: + IncludePath = self._INC_FLAG_['NASM'] + self.PlaceMacro(P, self.Macros) + if IncludePath.endswith(os.sep): + IncludePath = IncludePath.rstrip(os.sep) + # When compiling .nasm files, need to add a literal backslash at each path. + # In nmake makfiles, a trailing literal backslash must be escaped with a caret ('^'). + # It is otherwise replaced with a space (' '). This is not necessary for GNU makfefiles. + if P == MyAgo.IncludePathList[-1] and self._Platform == WIN32_PLATFORM and self._FileType == NMAKE_FILETYPE: + IncludePath = ''.join([IncludePath, '^', os.sep]) + else: + IncludePath = os.path.join(IncludePath, '') + IncludePathList.append(IncludePath) + FileMacroList.append(self._FILE_MACRO_TEMPLATE.Replace({"macro_name": "NASM_INC", "source_file": IncludePathList})) + + # Generate macros used to represent files containing list of input files + for ListFileMacro in self.ListFileMacros: + ListFileName = os.path.join(MyAgo.OutputDir, "%s.lst" % ListFileMacro.lower()[:len(ListFileMacro) - 5]) + FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName)) + SaveFileOnChange( + ListFileName, + "\n".join(self.ListFileMacros[ListFileMacro]), + False + ) + + # Generate objlist used to create .obj file + for Type in self.ObjTargetDict: + NewLine = ' '.join(list(self.ObjTargetDict[Type])) + FileMacroList.append("OBJLIST_%s = %s" % (list(self.ObjTargetDict.keys()).index(Type), NewLine)) + + BcTargetList = [] + + MakefileName = self.getMakefileName() + LibraryMakeCommandList = [] + for D in self.LibraryBuildDirectoryList: + Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":os.path.join(D, MakefileName)} + LibraryMakeCommandList.append(Command) + + package_rel_dir = MyAgo.SourceDir + current_dir = self.Macros["WORKSPACE"] + found = False + while not found and os.sep in package_rel_dir: + index = package_rel_dir.index(os.sep) + current_dir = mws.join(current_dir, package_rel_dir[:index]) + if os.path.exists(current_dir): + for fl in os.listdir(current_dir): + if fl.endswith('.dec'): + found = True + break + package_rel_dir = package_rel_dir[index + 1:] + + MakefileTemplateDict = { + "makefile_header" : self._FILE_HEADER_[self._FileType], + "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName), + "makefile_name" : MakefileName, + "platform_name" : self.PlatformInfo.Name, + "platform_guid" : self.PlatformInfo.Guid, + "platform_version" : self.PlatformInfo.Version, + "platform_relative_directory": self.PlatformInfo.SourceDir, + "platform_output_directory" : self.PlatformInfo.OutputDir, + "ffs_output_directory" : MyAgo.Macros["FFS_OUTPUT_DIR"], + "platform_dir" : MyAgo.Macros["PLATFORM_DIR"], + + "module_name" : MyAgo.Name, + "module_guid" : MyAgo.Guid, + "module_name_guid" : MyAgo.UniqueBaseName, + "module_version" : MyAgo.Version, + "module_type" : MyAgo.ModuleType, + "module_file" : MyAgo.MetaFile.Name, + "module_file_base_name" : MyAgo.MetaFile.BaseName, + "module_relative_directory" : MyAgo.SourceDir, + "module_dir" : mws.join (self.Macros["WORKSPACE"], MyAgo.SourceDir), + "package_relative_directory": package_rel_dir, + "module_extra_defines" : ["%s = %s" % (k, v) for k, v in MyAgo.Module.Defines.items()], + + "architecture" : MyAgo.Arch, + "toolchain_tag" : MyAgo.ToolChain, + "build_target" : MyAgo.BuildTarget, + + "platform_build_directory" : self.PlatformInfo.BuildDir, + "module_build_directory" : MyAgo.BuildDir, + "module_output_directory" : MyAgo.OutputDir, + "module_debug_directory" : MyAgo.DebugDir, + + "separator" : Separator, + "module_tool_definitions" : ToolsDef, + + "shell_command_code" : list(self._SHELL_CMD_[self._Platform].keys()), + "shell_command" : list(self._SHELL_CMD_[self._Platform].values()), + + "module_entry_point" : ModuleEntryPoint, + "image_entry_point" : ImageEntryPoint, + "arch_entry_point" : ArchEntryPoint, + "remaining_build_target" : self.ResultFileList, + "common_dependency_file" : self.CommonFileDependency, + "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), + "clean_command" : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]), + "cleanall_command" : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]), + "dependent_library_build_directory" : self.LibraryBuildDirectoryList, + "library_build_command" : LibraryMakeCommandList, + "file_macro" : FileMacroList, + "file_build_target" : self.BuildTargetList, + "backward_compatible_target": BcTargetList, + "INCLUDETAG" : "\n".join([self._INCLUDE_CMD_[self._FileType] + " " + os.path.join("$(MODULE_BUILD_DIR)","dependency"), + self._INCLUDE_CMD_[self._FileType] + " " + os.path.join("$(MODULE_BUILD_DIR)","deps_target") + ]) + } + + return MakefileTemplateDict + + def ParserGenerateFfsCmd(self): + #Add Ffs cmd to self.BuildTargetList + OutputFile = '' + DepsFileList = [] + + for Cmd in self.GenFfsList: + if Cmd[2]: + for CopyCmd in Cmd[2]: + Src, Dst = CopyCmd + Src = self.ReplaceMacro(Src) + Dst = self.ReplaceMacro(Dst) + if Dst not in self.ResultFileList: + self.ResultFileList.append(Dst) + if '%s :' %(Dst) not in self.BuildTargetList: + self.BuildTargetList.append("%s : %s" %(Dst,Src)) + self.BuildTargetList.append('\t' + self._CP_TEMPLATE_[self._Platform] %{'Src': Src, 'Dst': Dst}) + + FfsCmdList = Cmd[0] + for index, Str in enumerate(FfsCmdList): + if '-o' == Str: + OutputFile = FfsCmdList[index + 1] + if '-i' == Str or "-oi" == Str: + if DepsFileList == []: + DepsFileList = [FfsCmdList[index + 1]] + else: + DepsFileList.append(FfsCmdList[index + 1]) + DepsFileString = ' '.join(DepsFileList).strip() + if DepsFileString == '': + continue + OutputFile = self.ReplaceMacro(OutputFile) + self.ResultFileList.append(OutputFile) + DepsFileString = self.ReplaceMacro(DepsFileString) + self.BuildTargetList.append('%s : %s' % (OutputFile, DepsFileString)) + CmdString = ' '.join(FfsCmdList).strip() + CmdString = self.ReplaceMacro(CmdString) + self.BuildTargetList.append('\t%s' % CmdString) + + self.ParseSecCmd(DepsFileList, Cmd[1]) + for SecOutputFile, SecDepsFile, SecCmd in self.FfsOutputFileList : + self.BuildTargetList.append('%s : %s' % (self.ReplaceMacro(SecOutputFile), self.ReplaceMacro(SecDepsFile))) + self.BuildTargetList.append('\t%s' % self.ReplaceMacro(SecCmd)) + self.FfsOutputFileList = [] + + def ParseSecCmd(self, OutputFileList, CmdTuple): + for OutputFile in OutputFileList: + for SecCmdStr in CmdTuple: + SecDepsFileList = [] + SecCmdList = SecCmdStr.split() + CmdName = SecCmdList[0] + for index, CmdItem in enumerate(SecCmdList): + if '-o' == CmdItem and OutputFile == SecCmdList[index + 1]: + index = index + 1 + while index + 1 < len(SecCmdList): + if not SecCmdList[index+1].startswith('-'): + SecDepsFileList.append(SecCmdList[index + 1]) + index = index + 1 + if CmdName == 'Trim': + SecDepsFileList.append(os.path.join('$(DEBUG_DIR)', os.path.basename(OutputFile).replace('offset', 'efi'))) + if OutputFile.endswith('.ui') or OutputFile.endswith('.ver'): + SecDepsFileList.append(os.path.join('$(MODULE_DIR)', '$(MODULE_FILE)')) + self.FfsOutputFileList.append((OutputFile, ' '.join(SecDepsFileList), SecCmdStr)) + if len(SecDepsFileList) > 0: + self.ParseSecCmd(SecDepsFileList, CmdTuple) + break + else: + continue + + def ReplaceMacro(self, str): + for Macro in self.MacroList: + if self._AutoGenObject.Macros[Macro] and os.path.normcase(self._AutoGenObject.Macros[Macro]) in os.path.normcase(str): + replace_dir = str[os.path.normcase(str).index(os.path.normcase(self._AutoGenObject.Macros[Macro])): os.path.normcase(str).index( + os.path.normcase(self._AutoGenObject.Macros[Macro])) + len(self._AutoGenObject.Macros[Macro])] + str = str.replace(replace_dir, '$(' + Macro + ')') + return str + + def CommandExceedLimit(self): + FlagDict = { + 'CC' : { 'Macro' : '$(CC_FLAGS)', 'Value' : False}, + 'PP' : { 'Macro' : '$(PP_FLAGS)', 'Value' : False}, + 'APP' : { 'Macro' : '$(APP_FLAGS)', 'Value' : False}, + 'ASLPP' : { 'Macro' : '$(ASLPP_FLAGS)', 'Value' : False}, + 'VFRPP' : { 'Macro' : '$(VFRPP_FLAGS)', 'Value' : False}, + 'ASM' : { 'Macro' : '$(ASM_FLAGS)', 'Value' : False}, + 'ASLCC' : { 'Macro' : '$(ASLCC_FLAGS)', 'Value' : False}, + } + + RespDict = {} + FileTypeList = [] + IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily] + + # base on the source files to decide the file type + for File in self._AutoGenObject.SourceFileList: + for type in self._AutoGenObject.FileTypes: + if File in self._AutoGenObject.FileTypes[type]: + if type not in FileTypeList: + FileTypeList.append(type) + + # calculate the command-line length + if FileTypeList: + for type in FileTypeList: + BuildTargets = self._AutoGenObject.BuildRules[type].BuildTargets + for Target in BuildTargets: + CommandList = BuildTargets[Target].Commands + for SingleCommand in CommandList: + Tool = '' + SingleCommandLength = len(SingleCommand) + SingleCommandList = SingleCommand.split() + if len(SingleCommandList) > 0: + for Flag in FlagDict: + if '$('+ Flag +')' in SingleCommandList[0]: + Tool = Flag + break + if Tool: + if 'PATH' not in self._AutoGenObject.BuildOption[Tool]: + EdkLogger.error("build", AUTOGEN_ERROR, "%s_PATH doesn't exist in %s ToolChain and %s Arch." %(Tool, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch), ExtraData="[%s]" % str(self._AutoGenObject)) + SingleCommandLength += len(self._AutoGenObject.BuildOption[Tool]['PATH']) + for item in SingleCommandList[1:]: + if FlagDict[Tool]['Macro'] in item: + if 'FLAGS' not in self._AutoGenObject.BuildOption[Tool]: + EdkLogger.error("build", AUTOGEN_ERROR, "%s_FLAGS doesn't exist in %s ToolChain and %s Arch." %(Tool, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch), ExtraData="[%s]" % str(self._AutoGenObject)) + Str = self._AutoGenObject.BuildOption[Tool]['FLAGS'] + for Option in self._AutoGenObject.BuildOption: + for Attr in self._AutoGenObject.BuildOption[Option]: + if Str.find(Option + '_' + Attr) != -1: + Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr]) + while(Str.find('$(') != -1): + for macro in self._AutoGenObject.Macros: + MacroName = '$('+ macro + ')' + if (Str.find(MacroName) != -1): + Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro]) + break + else: + break + SingleCommandLength += len(Str) + elif '$(INC)' in item: + SingleCommandLength += self._AutoGenObject.IncludePathLength + len(IncPrefix) * len(self._AutoGenObject.IncludePathList) + elif item.find('$(') != -1: + Str = item + for Option in self._AutoGenObject.BuildOption: + for Attr in self._AutoGenObject.BuildOption[Option]: + if Str.find(Option + '_' + Attr) != -1: + Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr]) + while(Str.find('$(') != -1): + for macro in self._AutoGenObject.Macros: + MacroName = '$('+ macro + ')' + if (Str.find(MacroName) != -1): + Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro]) + break + else: + break + SingleCommandLength += len(Str) + + if SingleCommandLength > GlobalData.gCommandMaxLength: + FlagDict[Tool]['Value'] = True + + # generate the response file content by combine the FLAGS and INC + for Flag in FlagDict: + if FlagDict[Flag]['Value']: + Key = Flag + '_RESP' + RespMacro = FlagDict[Flag]['Macro'].replace('FLAGS', 'RESP') + Value = self._AutoGenObject.BuildOption[Flag]['FLAGS'] + for inc in self._AutoGenObject.IncludePathList: + Value += ' ' + IncPrefix + inc + for Option in self._AutoGenObject.BuildOption: + for Attr in self._AutoGenObject.BuildOption[Option]: + if Value.find(Option + '_' + Attr) != -1: + Value = Value.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr]) + while (Value.find('$(') != -1): + for macro in self._AutoGenObject.Macros: + MacroName = '$('+ macro + ')' + if (Value.find(MacroName) != -1): + Value = Value.replace(MacroName, self._AutoGenObject.Macros[macro]) + break + else: + break + + if self._AutoGenObject.ToolChainFamily == 'GCC': + RespDict[Key] = Value.replace('\\', '/') + else: + RespDict[Key] = Value + for Target in BuildTargets: + for i, SingleCommand in enumerate(BuildTargets[Target].Commands): + if FlagDict[Flag]['Macro'] in SingleCommand: + BuildTargets[Target].Commands[i] = SingleCommand.replace('$(INC)', '').replace(FlagDict[Flag]['Macro'], RespMacro) + return RespDict + + def ProcessBuildTargetList(self, RespFile, ToolsDef): + # + # Search dependency file list for each source file + # + ForceIncludedFile = [] + for File in self._AutoGenObject.AutoGenFileList: + if File.Ext == '.h': + ForceIncludedFile.append(File) + SourceFileList = [] + OutPutFileList = [] + for Target in self._AutoGenObject.IntroTargetList: + SourceFileList.extend(Target.Inputs) + OutPutFileList.extend(Target.Outputs) + + if OutPutFileList: + for Item in OutPutFileList: + if Item in SourceFileList: + SourceFileList.remove(Item) + + FileDependencyDict = {item:ForceIncludedFile for item in SourceFileList} + + for Dependency in FileDependencyDict.values(): + self.DependencyHeaderFileSet.update(set(Dependency)) + + # Get a set of unique package includes from MetaFile + parentMetaFileIncludes = set() + for aInclude in self._AutoGenObject.PackageIncludePathList: + aIncludeName = str(aInclude) + parentMetaFileIncludes.add(aIncludeName.lower()) + + # Check if header files are listed in metafile + # Get a set of unique module header source files from MetaFile + headerFilesInMetaFileSet = set() + for aFile in self._AutoGenObject.SourceFileList: + aFileName = str(aFile) + if not aFileName.endswith('.h'): + continue + headerFilesInMetaFileSet.add(aFileName.lower()) + + # Get a set of unique module autogen files + localAutoGenFileSet = set() + for aFile in self._AutoGenObject.AutoGenFileList: + localAutoGenFileSet.add(str(aFile).lower()) + + # Get a set of unique module dependency header files + # Exclude autogen files and files not in the source directory + # and files that are under the package include list + headerFileDependencySet = set() + localSourceDir = str(self._AutoGenObject.SourceDir).lower() + for Dependency in FileDependencyDict.values(): + for aFile in Dependency: + aFileName = str(aFile).lower() + # Exclude non-header files + if not aFileName.endswith('.h'): + continue + # Exclude autogen files + if aFileName in localAutoGenFileSet: + continue + # Exclude include out of local scope + if localSourceDir not in aFileName: + continue + # Exclude files covered by package includes + pathNeeded = True + for aIncludePath in parentMetaFileIncludes: + if aIncludePath in aFileName: + pathNeeded = False + break + if not pathNeeded: + continue + # Keep the file to be checked + headerFileDependencySet.add(aFileName) + + # Check if a module dependency header file is missing from the module's MetaFile + for aFile in headerFileDependencySet: + if aFile in headerFilesInMetaFileSet: + continue + if GlobalData.gUseHashCache: + GlobalData.gModuleBuildTracking[self._AutoGenObject] = 'FAIL_METAFILE' + EdkLogger.warn("build","Module MetaFile [Sources] is missing local header!", + ExtraData = "Local Header: " + aFile + " not found in " + self._AutoGenObject.MetaFile.Path + ) + + for File,Dependency in FileDependencyDict.items(): + if not Dependency: + continue + + self._AutoGenObject.AutoGenDepSet |= set(Dependency) + + CmdSumDict = {} + CmdTargetDict = {} + CmdCppDict = {} + DependencyDict = FileDependencyDict.copy() + + # Convert target description object to target string in makefile + if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and TAB_C_CODE_FILE in self._AutoGenObject.Targets: + for T in self._AutoGenObject.Targets[TAB_C_CODE_FILE]: + NewFile = self.PlaceMacro(str(T), self.Macros) + if not self.ObjTargetDict.get(T.Target.SubDir): + self.ObjTargetDict[T.Target.SubDir] = set() + self.ObjTargetDict[T.Target.SubDir].add(NewFile) + for Type in self._AutoGenObject.Targets: + resp_file_number = 0 + for T in self._AutoGenObject.Targets[Type]: + # Generate related macros if needed + if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros: + self.FileListMacros[T.FileListMacro] = [] + if T.GenListFile and T.ListFileMacro not in self.ListFileMacros: + self.ListFileMacros[T.ListFileMacro] = [] + if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros: + self.ListFileMacros[T.IncListFileMacro] = [] + + Deps = [] + CCodeDeps = [] + # Add force-dependencies + for Dep in T.Dependencies: + Deps.append(self.PlaceMacro(str(Dep), self.Macros)) + if Dep != '$(MAKE_FILE)': + CCodeDeps.append(self.PlaceMacro(str(Dep), self.Macros)) + # Add inclusion-dependencies + if len(T.Inputs) == 1 and T.Inputs[0] in FileDependencyDict: + for F in FileDependencyDict[T.Inputs[0]]: + Deps.append(self.PlaceMacro(str(F), self.Macros)) + # Add source-dependencies + for F in T.Inputs: + NewFile = self.PlaceMacro(str(F), self.Macros) + # In order to use file list macro as dependency + if T.GenListFile: + # gnu tools need forward slash path separator, even on Windows + self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/')) + self.FileListMacros[T.FileListMacro].append(NewFile) + elif T.GenFileListMacro: + self.FileListMacros[T.FileListMacro].append(NewFile) + else: + Deps.append(NewFile) + for key in self.FileListMacros: + self.FileListMacros[key].sort() + # Use file list macro as dependency + if T.GenFileListMacro: + Deps.append("$(%s)" % T.FileListMacro) + if Type in [TAB_OBJECT_FILE, TAB_STATIC_LIBRARY]: + Deps.append("$(%s)" % T.ListFileMacro) + + # VBox - begin: Add $(QUIET) + sAllCmds = None; + for sCmd in T.Commands: + sCmd = sCmd.strip(); + if len(sCmd) > 0: + if sCmd[0] == '-' and self._FileType == 'nmake': + sCmd = '-$(EFI_QUIET)' + sCmd[1:]; + else: + sCmd = '$(EFI_QUIET)' + sCmd; + if sAllCmds is None: + sAllCmds = sCmd; + else: + sAllCmds += '\n\t' + sCmd; + # VBox - end. + + if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and Type == TAB_C_CODE_FILE: + T, CmdTarget, CmdTargetDict, CmdCppDict = self.ParserCCodeFile(T, Type, CmdSumDict, CmdTargetDict, + CmdCppDict, DependencyDict, RespFile, + ToolsDef, resp_file_number) + resp_file_number += 1 + TargetDict = {"target": self.PlaceMacro(T.Target.Path, self.Macros), "cmd": "\n\t".join(T.Commands),"deps": CCodeDeps} + # VBox: Original: TargetDict = {"target": self.PlaceMacro(T.Target.Path, self.Macros), "cmd": sAllCmds,"deps": CCodeDeps} + CmdLine = self._BUILD_TARGET_TEMPLATE.Replace(TargetDict).rstrip().replace('\t$(OBJLIST', '$(OBJLIST') + if T.Commands: + CmdLine = '%s%s' %(CmdLine, TAB_LINE_BREAK) + if CCodeDeps or CmdLine: + self.BuildTargetList.append(CmdLine) + else: + TargetDict = {"target": self.PlaceMacro(T.Target.Path, self.Macros), "cmd": "\n\t".join(T.Commands),"deps": Deps} + # VBox: Original: TargetDict = {"target": self.PlaceMacro(T.Target.Path, self.Macros), "cmd": sAllCmds,"deps": Deps} + self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict)) + + # Add a Makefile rule for targets generating multiple files. + # The main output is a prerequisite for the other output files. + for i in T.Outputs[1:]: + AnnexeTargetDict = {"target": self.PlaceMacro(i.Path, self.Macros), "cmd": "", "deps": self.PlaceMacro(T.Target.Path, self.Macros)} + self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(AnnexeTargetDict)) + + def ParserCCodeFile(self, T, Type, CmdSumDict, CmdTargetDict, CmdCppDict, DependencyDict, RespFile, ToolsDef, + resp_file_number): + SaveFilePath = os.path.join(RespFile, "cc_resp_%s.txt" % resp_file_number) + if not CmdSumDict: + for item in self._AutoGenObject.Targets[Type]: + CmdSumDict[item.Target.SubDir] = item.Target.BaseName + for CppPath in item.Inputs: + Path = self.PlaceMacro(CppPath.Path, self.Macros) + if CmdCppDict.get(item.Target.SubDir): + CmdCppDict[item.Target.SubDir].append(Path) + else: + CmdCppDict[item.Target.SubDir] = ['$(MAKE_FILE)', Path] + if CppPath.Path in DependencyDict: + for Temp in DependencyDict[CppPath.Path]: + try: + Path = self.PlaceMacro(Temp.Path, self.Macros) + except: + continue + if Path not in (self.CommonFileDependency + CmdCppDict[item.Target.SubDir]): + CmdCppDict[item.Target.SubDir].append(Path) + if T.Commands: + CommandList = T.Commands[:] + for Item in CommandList[:]: + SingleCommandList = Item.split() + if len(SingleCommandList) > 0 and self.CheckCCCmd(SingleCommandList): + for Temp in SingleCommandList: + if Temp.startswith('/Fo'): + CmdSign = '%s%s' % (Temp.rsplit(TAB_SLASH, 1)[0], TAB_SLASH) + break + else: + continue + if CmdSign not in list(CmdTargetDict.keys()): + cmd = Item.replace(Temp, CmdSign) + if SingleCommandList[-1] in cmd: + CmdTargetDict[CmdSign] = [cmd.replace(SingleCommandList[-1], "").rstrip(), SingleCommandList[-1]] + else: + # CmdTargetDict[CmdSign] = "%s %s" % (CmdTargetDict[CmdSign], SingleCommandList[-1]) + CmdTargetDict[CmdSign].append(SingleCommandList[-1]) + Index = CommandList.index(Item) + CommandList.pop(Index) + if SingleCommandList[-1].endswith("%s%s.c" % (TAB_SLASH, CmdSumDict[CmdSign[3:].rsplit(TAB_SLASH, 1)[0]])): + Cpplist = CmdCppDict[T.Target.SubDir] + Cpplist.insert(0, '$(OBJLIST_%d): ' % list(self.ObjTargetDict.keys()).index(T.Target.SubDir)) + source_files = CmdTargetDict[CmdSign][1:] + source_files.insert(0, " ") + if len(source_files)>2: + SaveFileOnChange(SaveFilePath, " ".join(source_files), False) + T.Commands[Index] = '%s\n\t%s $(cc_resp_%s)' % ( + ' \\\n\t'.join(Cpplist), CmdTargetDict[CmdSign][0], resp_file_number) + ToolsDef.append("cc_resp_%s = @%s" % (resp_file_number, SaveFilePath)) + + elif len(source_files)<=2 and len(" ".join(CmdTargetDict[CmdSign][:2]))>GlobalData.gCommandMaxLength: + SaveFileOnChange(SaveFilePath, " ".join(source_files), False) + T.Commands[Index] = '%s\n\t%s $(cc_resp_%s)' % ( + ' \\\n\t'.join(Cpplist), CmdTargetDict[CmdSign][0], resp_file_number) + ToolsDef.append("cc_resp_%s = @%s" % (resp_file_number, SaveFilePath)) + + else: + T.Commands[Index] = '%s\n\t%s' % (' \\\n\t'.join(Cpplist), " ".join(CmdTargetDict[CmdSign])) + else: + T.Commands.pop(Index) + return T, CmdSumDict, CmdTargetDict, CmdCppDict + + def CheckCCCmd(self, CommandList): + for cmd in CommandList: + if '$(CC)' in cmd: + return True + return False + ## For creating makefile targets for dependent libraries + def ProcessDependentLibrary(self): + for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList: + if not LibraryAutoGen.IsBinaryModule: + self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros)) + + ## Return a list containing source file's dependencies + # + # @param FileList The list of source files + # @param ForceInculeList The list of files which will be included forcely + # @param SearchPathList The list of search path + # + # @retval dict The mapping between source file path and its dependencies + # + def GetFileDependency(self, FileList, ForceInculeList, SearchPathList): + Dependency = {} + for F in FileList: + Dependency[F] = GetDependencyList(self._AutoGenObject, self.FileCache, F, ForceInculeList, SearchPathList) + return Dependency + + +## CustomMakefile class +# +# This class encapsules makefie and its generation for module. It uses template to generate +# the content of makefile. The content of makefile will be got from ModuleAutoGen object. +# +class CustomMakefile(BuildFile): + ## template used to generate the makefile for module with custom makefile + _TEMPLATE_ = TemplateString('''\ +${makefile_header} + +# +# Platform Macro Definition +# +PLATFORM_NAME = ${platform_name} +PLATFORM_GUID = ${platform_guid} +PLATFORM_VERSION = ${platform_version} +PLATFORM_RELATIVE_DIR = ${platform_relative_directory} +PLATFORM_DIR = ${platform_dir} +PLATFORM_OUTPUT_DIR = ${platform_output_directory} + +# +# Module Macro Definition +# +MODULE_NAME = ${module_name} +MODULE_GUID = ${module_guid} +MODULE_NAME_GUID = ${module_name_guid} +MODULE_VERSION = ${module_version} +MODULE_TYPE = ${module_type} +MODULE_FILE = ${module_file} +MODULE_FILE_BASE_NAME = ${module_file_base_name} +BASE_NAME = $(MODULE_NAME) +MODULE_RELATIVE_DIR = ${module_relative_directory} +MODULE_DIR = ${module_dir} + +# +# Build Configuration Macro Definition +# +ARCH = ${architecture} +TOOLCHAIN = ${toolchain_tag} +TOOLCHAIN_TAG = ${toolchain_tag} +TARGET = ${build_target} + +# +# Build Directory Macro Definition +# +# PLATFORM_BUILD_DIR = ${platform_build_directory} +BUILD_DIR = ${platform_build_directory} +BIN_DIR = $(BUILD_DIR)${separator}${architecture} +LIB_DIR = $(BIN_DIR) +MODULE_BUILD_DIR = ${module_build_directory} +OUTPUT_DIR = ${module_output_directory} +DEBUG_DIR = ${module_debug_directory} +DEST_DIR_OUTPUT = $(OUTPUT_DIR) +DEST_DIR_DEBUG = $(DEBUG_DIR) + +# +# Tools definitions specific to this module +# +${BEGIN}${module_tool_definitions} +${END} +MAKE_FILE = ${makefile_path} + +# +# Shell Command Macro +# +${BEGIN}${shell_command_code} = ${shell_command} +${END} + +${custom_makefile_content} + +# +# Target used when called from platform makefile, which will bypass the build of dependent libraries +# + +pbuild: init all + + +# +# ModuleTarget +# + +mbuild: init all + +# +# Build Target used in multi-thread build mode, which no init target is needed +# + +tbuild: all + +# +# Initialization target: print build information and create necessary directories +# +init: +\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)] +${BEGIN}\t-@${create_directory_command}\n${END}\ + +''') + + ## Constructor of CustomMakefile + # + # @param ModuleAutoGen Object of ModuleAutoGen class + # + def __init__(self, ModuleAutoGen): + BuildFile.__init__(self, ModuleAutoGen) + self.PlatformInfo = self._AutoGenObject.PlatformInfo + self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"] + self.DependencyHeaderFileSet = set() + + # Compose a dict object containing information used to do replacement in template + @property + def _TemplateDict(self): + Separator = self._SEP_[self._Platform] + MyAgo = self._AutoGenObject + if self._FileType not in MyAgo.CustomMakefile: + EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType, + ExtraData="[%s]" % str(MyAgo)) + MakefilePath = mws.join( + MyAgo.WorkspaceDir, + MyAgo.CustomMakefile[self._FileType] + ) + try: + CustomMakefile = open(MakefilePath, 'r').read() + except: + EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(MyAgo), + ExtraData=MyAgo.CustomMakefile[self._FileType]) + + # tools definitions + ToolsDef = [] + for Tool in MyAgo.BuildOption: + # Don't generate MAKE_FLAGS in makefile. It's put in environment variable. + if Tool == "MAKE": + continue + for Attr in MyAgo.BuildOption[Tool]: + if Attr == "FAMILY": + continue + elif Attr == "PATH": + ToolsDef.append("%s = %s" % (Tool, MyAgo.BuildOption[Tool][Attr])) + else: + ToolsDef.append("%s_%s = %s" % (Tool, Attr, MyAgo.BuildOption[Tool][Attr])) + ToolsDef.append("") + + MakefileName = self.getMakefileName() + MakefileTemplateDict = { + "makefile_header" : self._FILE_HEADER_[self._FileType], + "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName), + "platform_name" : self.PlatformInfo.Name, + "platform_guid" : self.PlatformInfo.Guid, + "platform_version" : self.PlatformInfo.Version, + "platform_relative_directory": self.PlatformInfo.SourceDir, + "platform_output_directory" : self.PlatformInfo.OutputDir, + "platform_dir" : MyAgo.Macros["PLATFORM_DIR"], + + "module_name" : MyAgo.Name, + "module_guid" : MyAgo.Guid, + "module_name_guid" : MyAgo.UniqueBaseName, + "module_version" : MyAgo.Version, + "module_type" : MyAgo.ModuleType, + "module_file" : MyAgo.MetaFile, + "module_file_base_name" : MyAgo.MetaFile.BaseName, + "module_relative_directory" : MyAgo.SourceDir, + "module_dir" : mws.join (MyAgo.WorkspaceDir, MyAgo.SourceDir), + + "architecture" : MyAgo.Arch, + "toolchain_tag" : MyAgo.ToolChain, + "build_target" : MyAgo.BuildTarget, + + "platform_build_directory" : self.PlatformInfo.BuildDir, + "module_build_directory" : MyAgo.BuildDir, + "module_output_directory" : MyAgo.OutputDir, + "module_debug_directory" : MyAgo.DebugDir, + + "separator" : Separator, + "module_tool_definitions" : ToolsDef, + + "shell_command_code" : list(self._SHELL_CMD_[self._Platform].keys()), + "shell_command" : list(self._SHELL_CMD_[self._Platform].values()), + + "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), + "custom_makefile_content" : CustomMakefile + } + + return MakefileTemplateDict + +## PlatformMakefile class +# +# This class encapsules makefie and its generation for platform. It uses +# template to generate the content of makefile. The content of makefile will be +# got from PlatformAutoGen object. +# +class PlatformMakefile(BuildFile): + ## template used to generate the makefile for platform + _TEMPLATE_ = TemplateString('''\ +${makefile_header} + +# +# Platform Macro Definition +# +PLATFORM_NAME = ${platform_name} +PLATFORM_GUID = ${platform_guid} +PLATFORM_VERSION = ${platform_version} +PLATFORM_FILE = ${platform_file} +PLATFORM_DIR = ${platform_dir} +PLATFORM_OUTPUT_DIR = ${platform_output_directory} + +# +# Build Configuration Macro Definition +# +TOOLCHAIN = ${toolchain_tag} +TOOLCHAIN_TAG = ${toolchain_tag} +TARGET = ${build_target} + +# +# Build Directory Macro Definition +# +BUILD_DIR = ${platform_build_directory} +FV_DIR = ${platform_build_directory}${separator}FV + +# +# Shell Command Macro +# +${BEGIN}${shell_command_code} = ${shell_command} +${END} + +MAKE = ${make_path} +MAKE_FILE = ${makefile_path} + +# +# Default target +# +all: init build_libraries build_modules + +# +# Initialization target: print build information and create necessary directories +# +init: +\t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}] +\t${BEGIN}-@${create_directory_command} +\t${END} +# +# library build target +# +libraries: init build_libraries + +# +# module build target +# +modules: init build_libraries build_modules + +# +# Build all libraries: +# +build_libraries: +${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild +${END}\t@cd $(BUILD_DIR) + +# +# Build all modules: +# +build_modules: +${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild +${END}\t@cd $(BUILD_DIR) + +# +# Clean intermediate files +# +clean: +\t${BEGIN}-@${library_build_command} clean +\t${END}${BEGIN}-@${module_build_command} clean +\t${END}@cd $(BUILD_DIR) + +# +# Clean all generated files except to makefile +# +cleanall: +${BEGIN}\t${cleanall_command} +${END} + +# +# Clean all library files +# +cleanlib: +\t${BEGIN}-@${library_build_command} cleanall +\t${END}@cd $(BUILD_DIR)\n +''') + + ## Constructor of PlatformMakefile + # + # @param ModuleAutoGen Object of PlatformAutoGen class + # + def __init__(self, PlatformAutoGen): + BuildFile.__init__(self, PlatformAutoGen) + self.ModuleBuildCommandList = [] + self.ModuleMakefileList = [] + self.IntermediateDirectoryList = [] + self.ModuleBuildDirectoryList = [] + self.LibraryBuildDirectoryList = [] + self.LibraryMakeCommandList = [] + self.DependencyHeaderFileSet = set() + + # Compose a dict object containing information used to do replacement in template + @property + def _TemplateDict(self): + Separator = self._SEP_[self._Platform] + + MyAgo = self._AutoGenObject + if "MAKE" not in MyAgo.ToolDefinition or "PATH" not in MyAgo.ToolDefinition["MAKE"]: + EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!", + ExtraData="[%s]" % str(MyAgo)) + + self.IntermediateDirectoryList = ["$(BUILD_DIR)"] + self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList() + self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList() + + MakefileName = self.getMakefileName() + LibraryMakefileList = [] + LibraryMakeCommandList = [] + for D in self.LibraryBuildDirectoryList: + D = self.PlaceMacro(D, {"BUILD_DIR":MyAgo.BuildDir}) + Makefile = os.path.join(D, MakefileName) + Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":Makefile} + LibraryMakefileList.append(Makefile) + LibraryMakeCommandList.append(Command) + self.LibraryMakeCommandList = LibraryMakeCommandList + + ModuleMakefileList = [] + ModuleMakeCommandList = [] + for D in self.ModuleBuildDirectoryList: + D = self.PlaceMacro(D, {"BUILD_DIR":MyAgo.BuildDir}) + Makefile = os.path.join(D, MakefileName) + Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":Makefile} + ModuleMakefileList.append(Makefile) + ModuleMakeCommandList.append(Command) + + MakefileTemplateDict = { + "makefile_header" : self._FILE_HEADER_[self._FileType], + "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName), + "make_path" : MyAgo.ToolDefinition["MAKE"]["PATH"], + "makefile_name" : MakefileName, + "platform_name" : MyAgo.Name, + "platform_guid" : MyAgo.Guid, + "platform_version" : MyAgo.Version, + "platform_file" : MyAgo.MetaFile, + "platform_relative_directory": MyAgo.SourceDir, + "platform_output_directory" : MyAgo.OutputDir, + "platform_build_directory" : MyAgo.BuildDir, + "platform_dir" : MyAgo.Macros["PLATFORM_DIR"], + + "toolchain_tag" : MyAgo.ToolChain, + "build_target" : MyAgo.BuildTarget, + "shell_command_code" : list(self._SHELL_CMD_[self._Platform].keys()), + "shell_command" : list(self._SHELL_CMD_[self._Platform].values()), + "build_architecture_list" : MyAgo.Arch, + "architecture" : MyAgo.Arch, + "separator" : Separator, + "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), + "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList), + "library_makefile_list" : LibraryMakefileList, + "module_makefile_list" : ModuleMakefileList, + "library_build_command" : LibraryMakeCommandList, + "module_build_command" : ModuleMakeCommandList, + } + + return MakefileTemplateDict + + ## Get the root directory list for intermediate files of all modules build + # + # @retval list The list of directory + # + def GetModuleBuildDirectoryList(self): + DirList = [] + for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList: + if not ModuleAutoGen.IsBinaryModule: + DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir)) + return DirList + + ## Get the root directory list for intermediate files of all libraries build + # + # @retval list The list of directory + # + def GetLibraryBuildDirectoryList(self): + DirList = [] + for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList: + if not LibraryAutoGen.IsBinaryModule: + DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir)) + return DirList + +## TopLevelMakefile class +# +# This class encapsules makefie and its generation for entrance makefile. It +# uses template to generate the content of makefile. The content of makefile +# will be got from WorkspaceAutoGen object. +# +class TopLevelMakefile(BuildFile): + ## template used to generate toplevel makefile + _TEMPLATE_ = TemplateString('''${BEGIN}\tGenFds -f ${fdf_file} --conf=${conf_directory} -o ${platform_build_directory} -t ${toolchain_tag} -b ${build_target} -p ${active_platform} -a ${build_architecture_list} ${extra_options}${END}${BEGIN} -r ${fd} ${END}${BEGIN} -i ${fv} ${END}${BEGIN} -C ${cap} ${END}${BEGIN} -D ${macro} ${END}''') + + ## Constructor of TopLevelMakefile + # + # @param Workspace Object of WorkspaceAutoGen class + # + def __init__(self, Workspace): + BuildFile.__init__(self, Workspace) + self.IntermediateDirectoryList = [] + self.DependencyHeaderFileSet = set() + + # Compose a dict object containing information used to do replacement in template + @property + def _TemplateDict(self): + Separator = self._SEP_[self._Platform] + + # any platform autogen object is ok because we just need common information + MyAgo = self._AutoGenObject + + if "MAKE" not in MyAgo.ToolDefinition or "PATH" not in MyAgo.ToolDefinition["MAKE"]: + EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!", + ExtraData="[%s]" % str(MyAgo)) + + for Arch in MyAgo.ArchList: + self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch])) + self.IntermediateDirectoryList.append("$(FV_DIR)") + + # TRICK: for not generating GenFds call in makefile if no FDF file + MacroList = [] + if MyAgo.FdfFile is not None and MyAgo.FdfFile != "": + FdfFileList = [MyAgo.FdfFile] + # 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) + else: + FdfFileList = [] + + # pass extra common options to external program called in makefile, currently GenFds.exe + ExtraOption = '' + LogLevel = EdkLogger.GetLevel() + if LogLevel == EdkLogger.VERBOSE: + ExtraOption += " -v" + elif LogLevel <= EdkLogger.DEBUG_9: + ExtraOption += " -d %d" % (LogLevel - 1) + elif LogLevel == EdkLogger.QUIET: + ExtraOption += " -q" + + if GlobalData.gCaseInsensitive: + ExtraOption += " -c" + if not GlobalData.gEnableGenfdsMultiThread: + ExtraOption += " --no-genfds-multi-thread" + if GlobalData.gIgnoreSource: + ExtraOption += " --ignore-sources" + + for pcd in GlobalData.BuildOptionPcd: + if pcd[2]: + pcdname = '.'.join(pcd[0:3]) + else: + pcdname = '.'.join(pcd[0:2]) + if pcd[3].startswith('{'): + ExtraOption += " --pcd " + pcdname + '=' + 'H' + '"' + pcd[3] + '"' + else: + ExtraOption += " --pcd " + pcdname + '=' + pcd[3] + + MakefileName = self.getMakefileName() + SubBuildCommandList = [] + for A in MyAgo.ArchList: + Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)} + SubBuildCommandList.append(Command) + + MakefileTemplateDict = { + "makefile_header" : self._FILE_HEADER_[self._FileType], + "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName), + "make_path" : MyAgo.ToolDefinition["MAKE"]["PATH"], + "platform_name" : MyAgo.Name, + "platform_guid" : MyAgo.Guid, + "platform_version" : MyAgo.Version, + "platform_build_directory" : MyAgo.BuildDir, + "conf_directory" : GlobalData.gConfDirectory, + + "toolchain_tag" : MyAgo.ToolChain, + "build_target" : MyAgo.BuildTarget, + "shell_command_code" : list(self._SHELL_CMD_[self._Platform].keys()), + "shell_command" : list(self._SHELL_CMD_[self._Platform].values()), + 'arch' : list(MyAgo.ArchList), + "build_architecture_list" : ','.join(MyAgo.ArchList), + "separator" : Separator, + "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), + "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList), + "sub_build_command" : SubBuildCommandList, + "fdf_file" : FdfFileList, + "active_platform" : str(MyAgo), + "fd" : MyAgo.FdTargetList, + "fv" : MyAgo.FvTargetList, + "cap" : MyAgo.CapTargetList, + "extra_options" : ExtraOption, + "macro" : MacroList, + } + + return MakefileTemplateDict + + ## Get the root directory list for intermediate files of all modules build + # + # @retval list The list of directory + # + def GetModuleBuildDirectoryList(self): + DirList = [] + for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList: + if not ModuleAutoGen.IsBinaryModule: + DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir)) + return DirList + + ## Get the root directory list for intermediate files of all libraries build + # + # @retval list The list of directory + # + def GetLibraryBuildDirectoryList(self): + DirList = [] + for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList: + if not LibraryAutoGen.IsBinaryModule: + DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir)) + return DirList + +## Find dependencies for one source file +# +# By searching recursively "#include" directive in file, find out all the +# files needed by given source file. The dependencies will be only searched +# in given search path list. +# +# @param File The source file +# @param ForceInculeList The list of files which will be included forcely +# @param SearchPathList The list of search path +# +# @retval list The list of files the given source file depends on +# +def GetDependencyList(AutoGenObject, FileCache, File, ForceList, SearchPathList): + EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File) + FileStack = [File] + ForceList + DependencySet = set() + + if AutoGenObject.Arch not in gDependencyDatabase: + gDependencyDatabase[AutoGenObject.Arch] = {} + DepDb = gDependencyDatabase[AutoGenObject.Arch] + + while len(FileStack) > 0: + F = FileStack.pop() + + FullPathDependList = [] + if F in FileCache: + for CacheFile in FileCache[F]: + FullPathDependList.append(CacheFile) + if CacheFile not in DependencySet: + FileStack.append(CacheFile) + DependencySet.update(FullPathDependList) + continue + + CurrentFileDependencyList = [] + if F in DepDb: + CurrentFileDependencyList = DepDb[F] + else: + try: + Fd = open(F.Path, 'rb') + FileContent = Fd.read() + Fd.close() + except BaseException as X: + EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path + "\n\t" + str(X)) + if len(FileContent) == 0: + continue + try: + if FileContent[0] == 0xff or FileContent[0] == 0xfe: + FileContent = FileContent.decode('utf-16') + else: + FileContent = FileContent.decode() + except: + # The file is not txt file. for example .mcb file + continue + IncludedFileList = gIncludePattern.findall(FileContent) + + for Inc in IncludedFileList: + Inc = Inc.strip() + # if there's macro used to reference header file, expand it + HeaderList = gMacroPattern.findall(Inc) + if len(HeaderList) == 1 and len(HeaderList[0]) == 2: + HeaderType = HeaderList[0][0] + HeaderKey = HeaderList[0][1] + if HeaderType in gIncludeMacroConversion: + Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey} + else: + # not known macro used in #include, always build the file by + # returning a empty dependency + FileCache[File] = [] + return [] + Inc = os.path.normpath(Inc) + CurrentFileDependencyList.append(Inc) + DepDb[F] = CurrentFileDependencyList + + CurrentFilePath = F.Dir + PathList = [CurrentFilePath] + SearchPathList + for Inc in CurrentFileDependencyList: + for SearchPath in PathList: + FilePath = os.path.join(SearchPath, Inc) + if FilePath in gIsFileMap: + if not gIsFileMap[FilePath]: + continue + # If isfile is called too many times, the performance is slow down. + elif not os.path.isfile(FilePath): + gIsFileMap[FilePath] = False + continue + else: + gIsFileMap[FilePath] = True + FilePath = PathClass(FilePath) + FullPathDependList.append(FilePath) + if FilePath not in DependencySet: + FileStack.append(FilePath) + break + else: + EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\ + "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList))) + + FileCache[F] = FullPathDependList + DependencySet.update(FullPathDependList) + + DependencySet.update(ForceList) + if File in DependencySet: + DependencySet.remove(File) + DependencyList = list(DependencySet) # remove duplicate ones + + return DependencyList + +# This acts like the main() function for the script, unless it is 'import'ed into another script. +if __name__ == '__main__': + pass |