diff options
| author | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
|---|---|---|
| committer | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
| commit | 7e2ccccace24636f29ddc210b94606abd4c7e42b (patch) | |
| tree | 545d43ea12671048956cafeb12303e84d601e571 /BaseTools/Source/Python/AutoGen/GenMake.py | |
| parent | 27b044605cd5f6b33a3d231576003850b3fe305b (diff) | |
| download | edk2-trunk.tar.xz | |
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'BaseTools/Source/Python/AutoGen/GenMake.py')
| -rwxr-xr-x | BaseTools/Source/Python/AutoGen/GenMake.py | 3588 |
1 files changed, 1794 insertions, 1794 deletions
diff --git a/BaseTools/Source/Python/AutoGen/GenMake.py b/BaseTools/Source/Python/AutoGen/GenMake.py index fbd35d4989..f6dbbdf4a5 100755 --- a/BaseTools/Source/Python/AutoGen/GenMake.py +++ b/BaseTools/Source/Python/AutoGen/GenMake.py @@ -1,1794 +1,1794 @@ -## @file
-# Create makefile for MS nmake and GNU make
-#
-# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
-# Copyright (c) 2020 - 2021, 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 -p -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", "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:
- MakePath = AutoGenObject.ToolDefinition.get('MAKE', {}).get('PATH')
- if "nmake" in MakePath:
- self._FileType = NMAKE_FILETYPE
- else:
- self._FileType = GMAKE_FILETYPE
-
- 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)
-
- 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}
- 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}
- 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)
- BaseName = SingleCommandList[-1].rsplit('.',1)[0]
- if BaseName.endswith("%s%s" % (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
+## @file +# Create makefile for MS nmake and GNU make +# +# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR> +# Copyright (c) 2020 - 2021, 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 -p -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", "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: + MakePath = AutoGenObject.ToolDefinition.get('MAKE', {}).get('PATH') + if "nmake" in MakePath: + self._FileType = NMAKE_FILETYPE + else: + self._FileType = GMAKE_FILETYPE + + 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) + + 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} + 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} + 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) + BaseName = SingleCommandList[-1].rsplit('.',1)[0] + if BaseName.endswith("%s%s" % (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 |
