This patch clean some coding style issues, majorly for space character. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Yonghong Zhu <yonghong.zhu@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19080 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1350 lines
		
	
	
		
			53 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1350 lines
		
	
	
		
			53 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| ## @file
 | |
| # Create makefile for MS nmake and GNU make
 | |
| #
 | |
| # Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
 | |
| # This program and the accompanying materials
 | |
| # are licensed and made available under the terms and conditions of the BSD License
 | |
| # which accompanies this distribution.  The full text of the license may be found at
 | |
| # http://opensource.org/licenses/bsd-license.php
 | |
| #
 | |
| # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| #
 | |
| 
 | |
| ## Import Modules
 | |
| #
 | |
| 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.String import *
 | |
| from BuildEngine import *
 | |
| import Common.GlobalData as GlobalData
 | |
| 
 | |
| ## 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,
 | |
| }
 | |
| 
 | |
| ## default makefile type
 | |
| gMakeType = ""
 | |
| if sys.platform == "win32":
 | |
|     gMakeType = "nmake"
 | |
| else:
 | |
|     gMakeType = "gmake"
 | |
| 
 | |
| 
 | |
| ## 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" :   "Makefile",
 | |
|         "gmake" :   "GNUmakefile"
 | |
|     }
 | |
| 
 | |
|     ## 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" :   _MAKEFILE_HEADER % _FILE_NAME_["nmake"],
 | |
|         "gmake" :   _MAKEFILE_HEADER % _FILE_NAME_["gmake"]
 | |
|     }
 | |
| 
 | |
|     ## 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_ = {
 | |
|         "nmake" : {
 | |
|             "CP"    :   "copy /y",
 | |
|             "MV"    :   "move /y",
 | |
|             "RM"    :   "del /f /q",
 | |
|             "MD"    :   "mkdir",
 | |
|             "RD"    :   "rmdir /s /q",
 | |
|         },
 | |
| 
 | |
|         "gmake" : {
 | |
|             "CP"    :   "cp -f",
 | |
|             "MV"    :   "mv -f",
 | |
|             "RM"    :   "rm -f",
 | |
|             "MD"    :   "mkdir -p",
 | |
|             "RD"    :   "rm -r -f",
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     ## directory separator
 | |
|     _SEP_ = {
 | |
|         "nmake" :   "\\",
 | |
|         "gmake" :   "/"
 | |
|     }
 | |
| 
 | |
|     ## directory creation template
 | |
|     _MD_TEMPLATE_ = {
 | |
|         "nmake" :   'if not exist %(dir)s $(MD) %(dir)s',
 | |
|         "gmake" :   "$(MD) %(dir)s"
 | |
|     }
 | |
| 
 | |
|     ## directory removal template
 | |
|     _RD_TEMPLATE_ = {
 | |
|         "nmake" :   'if exist %(dir)s $(RD) %(dir)s',
 | |
|         "gmake" :   "$(RD) %(dir)s"
 | |
|     }
 | |
| 
 | |
|     _CD_TEMPLATE_ = {
 | |
|         "nmake" :   'if exist %(dir)s cd %(dir)s',
 | |
|         "gmake" :   "test -e %(dir)s && cd %(dir)s"
 | |
|     }
 | |
| 
 | |
|     _MAKE_TEMPLATE_ = {
 | |
|         "nmake" :   'if exist %(file)s "$(MAKE)" $(MAKE_FLAGS) -f %(file)s',
 | |
|         "gmake" :   'test -e %(file)s && "$(MAKE)" $(MAKE_FLAGS) -f %(file)s'
 | |
|     }
 | |
| 
 | |
|     _INCLUDE_CMD_ = {
 | |
|         "nmake" :   '!INCLUDE',
 | |
|         "gmake" :   "include"
 | |
|     }
 | |
| 
 | |
|     _INC_FLAG_ = {"MSFT" : "/I", "GCC" : "-I", "INTEL" : "-I", "RVCT" : "-I"}
 | |
| 
 | |
|     ## Constructor of BuildFile
 | |
|     #
 | |
|     #   @param  AutoGenObject   Object of AutoGen class
 | |
|     #
 | |
|     def __init__(self, AutoGenObject):
 | |
|         self._AutoGenObject = AutoGenObject
 | |
|         self._FileType = gMakeType
 | |
| 
 | |
|     ## Create build file
 | |
|     #
 | |
|     #   @param  FileType    Type of build file. Only nmake and gmake are supported now.
 | |
|     #
 | |
|     #   @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, FileType=gMakeType):
 | |
|         if FileType not in self._FILE_NAME_:
 | |
|             EdkLogger.error("build", PARAMETER_INVALID, "Invalid build type [%s]" % FileType,
 | |
|                             ExtraData="[%s]" % str(self._AutoGenObject))
 | |
|         self._FileType = FileType
 | |
|         FileContent = self._TEMPLATE_.Replace(self._TemplateDict)
 | |
|         FileName = self._FILE_NAME_[FileType]
 | |
|         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._FileType] % {'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._FileType] % {'dir':Dir} for Dir in DirList]
 | |
| 
 | |
|     def PlaceMacro(self, Path, MacroDefinitions={}):
 | |
|         if Path.startswith("$("):
 | |
|             return Path
 | |
|         else:
 | |
|             PathLength = len(Path)
 | |
|             for MacroName in MacroDefinitions:
 | |
|                 MacroValue = MacroDefinitions[MacroName]
 | |
|                 MacroValueLength = len(MacroValue)
 | |
|                 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 = $(WORKSPACE)${separator}${platform_relative_directory}
 | |
| 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 = $(WORKSPACE)${separator}${module_relative_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}
 | |
| 
 | |
| COMMON_DEPS = ${BEGIN}${common_dependency_file} \\
 | |
|               ${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)
 | |
| 
 | |
| #
 | |
| # Individual Object Build Targets
 | |
| #
 | |
| ${BEGIN}${file_build_target}
 | |
| ${END}
 | |
| 
 | |
| #
 | |
| # clean all intermediate files
 | |
| #
 | |
| clean:
 | |
| \t${BEGIN}${clean_command}
 | |
| \t${END}
 | |
| 
 | |
| #
 | |
| # 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
 | |
| 
 | |
| #
 | |
| # 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.SourceFileDatabase = {}        # {file type : file path}
 | |
|         self.DestFileDatabase = {}          # {file type : file path}
 | |
|         self.FileBuildTargetList = []       # [(src, target string)]
 | |
|         self.BuildTargetList = []           # [target string]
 | |
|         self.PendingBuildTargetList = []    # [FileBuildRule objects]
 | |
|         self.CommonFileDependency = []
 | |
|         self.FileListMacros = {}
 | |
|         self.ListFileMacros = {}
 | |
| 
 | |
|         self.FileCache = {}
 | |
|         self.FileDependency = []
 | |
|         self.LibraryBuildCommandList = []
 | |
|         self.LibraryFileList = []
 | |
|         self.LibraryMakefileList = []
 | |
|         self.LibraryBuildDirectoryList = []
 | |
|         self.SystemLibraryList = []
 | |
|         self.Macros = sdict()
 | |
|         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"]
 | |
| 
 | |
|     # Compose a dict object containing information used to do replacement in template
 | |
|     def _CreateTemplateDict(self):
 | |
|         if self._FileType not in self._SEP_:
 | |
|             EdkLogger.error("build", PARAMETER_INVALID, "Invalid Makefile type [%s]" % self._FileType,
 | |
|                             ExtraData="[%s]" % str(self._AutoGenObject))
 | |
|         Separator = self._SEP_[self._FileType]
 | |
| 
 | |
|         # break build if no source files and binary files are found
 | |
|         if len(self._AutoGenObject.SourceFileList) == 0 and len(self._AutoGenObject.BinaryFileList) == 0:
 | |
|             EdkLogger.error("build", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]"
 | |
|                             % (self._AutoGenObject.BuildTarget, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch),
 | |
|                             ExtraData="[%s]" % str(self._AutoGenObject))
 | |
| 
 | |
|         # convert dependent libraries to build command
 | |
|         self.ProcessDependentLibrary()
 | |
|         if len(self._AutoGenObject.Module.ModuleEntryPointList) > 0:
 | |
|             ModuleEntryPoint = self._AutoGenObject.Module.ModuleEntryPointList[0]
 | |
|         else:
 | |
|             ModuleEntryPoint = "_ModuleEntryPoint"
 | |
| 
 | |
|         # Intel EBC compiler enforces EfiMain
 | |
|         if self._AutoGenObject.AutoGenVersion < 0x00010005 and self._AutoGenObject.Arch == "EBC":
 | |
|             ArchEntryPoint = "EfiMain"
 | |
|         else:
 | |
|             ArchEntryPoint = ModuleEntryPoint
 | |
| 
 | |
|         if self._AutoGenObject.Arch == "EBC":
 | |
|             # EBC compiler always use "EfiStart" as entry point. Only applies to EdkII modules
 | |
|             ImageEntryPoint = "EfiStart"
 | |
|         elif self._AutoGenObject.AutoGenVersion < 0x00010005:
 | |
|             # Edk modules use entry point specified in INF file
 | |
|             ImageEntryPoint = ModuleEntryPoint
 | |
|         else:
 | |
|             # EdkII modules always use "_ModuleEntryPoint" as entry point
 | |
|             ImageEntryPoint = "_ModuleEntryPoint"
 | |
| 
 | |
|         # tools definitions
 | |
|         ToolsDef = []
 | |
|         IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
 | |
|         for Tool in self._AutoGenObject.BuildOption:
 | |
|             for Attr in self._AutoGenObject.BuildOption[Tool]:
 | |
|                 Value = self._AutoGenObject.BuildOption[Tool][Attr]
 | |
|                 if Attr == "FAMILY":
 | |
|                     continue
 | |
|                 elif Attr == "PATH":
 | |
|                     ToolsDef.append("%s = %s" % (Tool, Value))
 | |
|                 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, self._AutoGenObject.IncludePathList)
 | |
|                     ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
 | |
|             ToolsDef.append("")
 | |
| 
 | |
|         # convert source files and binary files to build targets
 | |
|         self.ResultFileList = [str(T.Target) for T in self._AutoGenObject.CodaTargetList]
 | |
|         if len(self.ResultFileList) == 0 and len(self._AutoGenObject.SourceFileList) <> 0:
 | |
|             EdkLogger.error("build", AUTOGEN_ERROR, "Nothing to build",
 | |
|                             ExtraData="[%s]" % str(self._AutoGenObject))
 | |
| 
 | |
|         self.ProcessBuildTargetList()
 | |
| 
 | |
|         # 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  self._AutoGenObject.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)
 | |
| 
 | |
|         # Generate macros used to represent files containing list of input files
 | |
|         for ListFileMacro in self.ListFileMacros:
 | |
|             ListFileName = os.path.join(self._AutoGenObject.OutputDir, "%s.lst" % ListFileMacro.lower()[:len(ListFileMacro) - 5])
 | |
|             FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))
 | |
|             SaveFileOnChange(
 | |
|                 ListFileName,
 | |
|                 "\n".join(self.ListFileMacros[ListFileMacro]),
 | |
|                 False
 | |
|                 )
 | |
| 
 | |
|         # Edk modules need <BaseName>StrDefs.h for string ID
 | |
|         #if self._AutoGenObject.AutoGenVersion < 0x00010005 and len(self._AutoGenObject.UnicodeFileList) > 0:
 | |
|         #    BcTargetList = ['strdefs']
 | |
|         #else:
 | |
|         #    BcTargetList = []
 | |
|         BcTargetList = []
 | |
| 
 | |
|         MakefileName = self._FILE_NAME_[self._FileType]
 | |
|         LibraryMakeCommandList = []
 | |
|         for D in self.LibraryBuildDirectoryList:
 | |
|             Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)}
 | |
|             LibraryMakeCommandList.append(Command)
 | |
| 
 | |
|         package_rel_dir = self._AutoGenObject.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])
 | |
|             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,
 | |
| 
 | |
|             "module_name"               : self._AutoGenObject.Name,
 | |
|             "module_guid"               : self._AutoGenObject.Guid,
 | |
|             "module_name_guid"          : self._AutoGenObject._GetUniqueBaseName(),
 | |
|             "module_version"            : self._AutoGenObject.Version,
 | |
|             "module_type"               : self._AutoGenObject.ModuleType,
 | |
|             "module_file"               : self._AutoGenObject.MetaFile.Name,
 | |
|             "module_file_base_name"     : self._AutoGenObject.MetaFile.BaseName,
 | |
|             "module_relative_directory" : self._AutoGenObject.SourceDir,
 | |
|             "package_relative_directory": package_rel_dir,
 | |
|             "module_extra_defines"      : ["%s = %s" % (k, v) for k, v in self._AutoGenObject.Module.Defines.iteritems()],
 | |
| 
 | |
|             "architecture"              : self._AutoGenObject.Arch,
 | |
|             "toolchain_tag"             : self._AutoGenObject.ToolChain,
 | |
|             "build_target"              : self._AutoGenObject.BuildTarget,
 | |
| 
 | |
|             "platform_build_directory"  : self.PlatformInfo.BuildDir,
 | |
|             "module_build_directory"    : self._AutoGenObject.BuildDir,
 | |
|             "module_output_directory"   : self._AutoGenObject.OutputDir,
 | |
|             "module_debug_directory"    : self._AutoGenObject.DebugDir,
 | |
| 
 | |
|             "separator"                 : Separator,
 | |
|             "module_tool_definitions"   : ToolsDef,
 | |
| 
 | |
|             "shell_command_code"        : self._SHELL_CMD_[self._FileType].keys(),
 | |
|             "shell_command"             : self._SHELL_CMD_[self._FileType].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,
 | |
|         }
 | |
| 
 | |
|         return MakefileTemplateDict
 | |
| 
 | |
|     def ProcessBuildTargetList(self):
 | |
|         #
 | |
|         # Search dependency file list for each source file
 | |
|         #
 | |
|         ForceIncludedFile = []
 | |
|         for File in self._AutoGenObject.AutoGenFileList:
 | |
|             if File.Ext == '.h':
 | |
|                 ForceIncludedFile.append(File)
 | |
|         SourceFileList = []
 | |
|         for Target in self._AutoGenObject.IntroTargetList:
 | |
|             SourceFileList.extend(Target.Inputs)
 | |
| 
 | |
|         self.FileDependency = self.GetFileDependency(
 | |
|                                     SourceFileList,
 | |
|                                     ForceIncludedFile,
 | |
|                                     self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList
 | |
|                                     )
 | |
|         DepSet = None
 | |
|         for File in self.FileDependency:
 | |
|             if not self.FileDependency[File]:
 | |
|                 self.FileDependency[File] = ['$(FORCE_REBUILD)']
 | |
|                 continue
 | |
|             # skip non-C files
 | |
|             if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
 | |
|                 continue
 | |
|             elif DepSet == None:
 | |
|                 DepSet = set(self.FileDependency[File])
 | |
|             else:
 | |
|                 DepSet &= set(self.FileDependency[File])
 | |
|         # in case nothing in SourceFileList
 | |
|         if DepSet == None:
 | |
|             DepSet = set()
 | |
|         #
 | |
|         # Extract common files list in the dependency files
 | |
|         #
 | |
|         for File in DepSet:
 | |
|             self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros))
 | |
| 
 | |
|         for File in self.FileDependency:
 | |
|             # skip non-C files
 | |
|             if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
 | |
|                 continue
 | |
|             NewDepSet = set(self.FileDependency[File])
 | |
|             NewDepSet -= DepSet
 | |
|             self.FileDependency[File] = ["$(COMMON_DEPS)"] + list(NewDepSet)
 | |
| 
 | |
|         # Convert target description object to target string in makefile
 | |
|         for Type in self._AutoGenObject.Targets:
 | |
|             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 = []
 | |
|                 # Add force-dependencies
 | |
|                 for Dep in T.Dependencies:
 | |
|                     Deps.append(self.PlaceMacro(str(Dep), self.Macros))
 | |
|                 # Add inclusion-dependencies
 | |
|                 if len(T.Inputs) == 1 and T.Inputs[0] in self.FileDependency:
 | |
|                     for F in self.FileDependency[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 separater, 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)
 | |
| 
 | |
|                 # Use file list macro as dependency
 | |
|                 if T.GenFileListMacro:
 | |
|                     Deps.append("$(%s)" % T.FileListMacro)
 | |
| 
 | |
|                 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))
 | |
| 
 | |
|     ## For creating makefile targets for dependent libraries
 | |
|     def ProcessDependentLibrary(self):
 | |
|         for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
 | |
|             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] = self.GetDependencyList(F, ForceInculeList, SearchPathList)
 | |
|         return Dependency
 | |
| 
 | |
|     ## Find dependencies for one source file
 | |
|     #
 | |
|     #  By searching recursively "#include" directive in file, find out all the
 | |
|     #  files needed by given source file. The dependecies 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(self, File, ForceList, SearchPathList):
 | |
|         EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File)
 | |
|         FileStack = [File] + ForceList
 | |
|         DependencySet = set()
 | |
| 
 | |
|         if self._AutoGenObject.Arch not in gDependencyDatabase:
 | |
|             gDependencyDatabase[self._AutoGenObject.Arch] = {}
 | |
|         DepDb = gDependencyDatabase[self._AutoGenObject.Arch]
 | |
| 
 | |
|         while len(FileStack) > 0:
 | |
|             F = FileStack.pop()
 | |
| 
 | |
|             FullPathDependList = []
 | |
|             if F in self.FileCache:
 | |
|                 for CacheFile in self.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, 'r')
 | |
|                 except BaseException, X:
 | |
|                     EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path + "\n\t" + str(X))
 | |
| 
 | |
|                 FileContent = Fd.read()
 | |
|                 Fd.close()
 | |
|                 if len(FileContent) == 0:
 | |
|                     continue
 | |
| 
 | |
|                 if FileContent[0] == 0xff or FileContent[0] == 0xfe:
 | |
|                     FileContent = unicode(FileContent, "utf-16")
 | |
|                 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
 | |
|                             self.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)))
 | |
| 
 | |
|             self.FileCache[F] = FullPathDependList
 | |
|             DependencySet.update(FullPathDependList)
 | |
| 
 | |
|         DependencySet.update(ForceList)
 | |
|         if File in DependencySet:
 | |
|             DependencySet.remove(File)
 | |
|         DependencyList = list(DependencySet)  # remove duplicate ones
 | |
| 
 | |
|         return DependencyList
 | |
| 
 | |
|     _TemplateDict = property(_CreateTemplateDict)
 | |
| 
 | |
| ## 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 = $(WORKSPACE)${separator}${platform_relative_directory}
 | |
| 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 = $(WORKSPACE)${separator}${module_relative_directory}
 | |
| 
 | |
| #
 | |
| # 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)"]
 | |
| 
 | |
|     # Compose a dict object containing information used to do replacement in template
 | |
|     def _CreateTemplateDict(self):
 | |
|         Separator = self._SEP_[self._FileType]
 | |
|         if self._FileType not in self._AutoGenObject.CustomMakefile:
 | |
|             EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType,
 | |
|                             ExtraData="[%s]" % str(self._AutoGenObject))
 | |
|         MakefilePath = os.path.join(
 | |
|                                 self._AutoGenObject.WorkspaceDir,
 | |
|                                 self._AutoGenObject.CustomMakefile[self._FileType]
 | |
|                                 )
 | |
|         try:
 | |
|             CustomMakefile = open(MakefilePath, 'r').read()
 | |
|         except:
 | |
|             EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(self._AutoGenObject),
 | |
|                             ExtraData=self._AutoGenObject.CustomMakefile[self._FileType])
 | |
| 
 | |
|         # tools definitions
 | |
|         ToolsDef = []
 | |
|         for Tool in self._AutoGenObject.BuildOption:
 | |
|             # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
 | |
|             if Tool == "MAKE":
 | |
|                 continue
 | |
|             for Attr in self._AutoGenObject.BuildOption[Tool]:
 | |
|                 if Attr == "FAMILY":
 | |
|                     continue
 | |
|                 elif Attr == "PATH":
 | |
|                     ToolsDef.append("%s = %s" % (Tool, self._AutoGenObject.BuildOption[Tool][Attr]))
 | |
|                 else:
 | |
|                     ToolsDef.append("%s_%s = %s" % (Tool, Attr, self._AutoGenObject.BuildOption[Tool][Attr]))
 | |
|             ToolsDef.append("")
 | |
| 
 | |
|         MakefileName = self._FILE_NAME_[self._FileType]
 | |
|         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,
 | |
| 
 | |
|             "module_name"               : self._AutoGenObject.Name,
 | |
|             "module_guid"               : self._AutoGenObject.Guid,
 | |
|             "module_name_guid"          : self._AutoGenObject._GetUniqueBaseName(),
 | |
|             "module_version"            : self._AutoGenObject.Version,
 | |
|             "module_type"               : self._AutoGenObject.ModuleType,
 | |
|             "module_file"               : self._AutoGenObject.MetaFile,
 | |
|             "module_file_base_name"     : self._AutoGenObject.MetaFile.BaseName,
 | |
|             "module_relative_directory" : self._AutoGenObject.SourceDir,
 | |
| 
 | |
|             "architecture"              : self._AutoGenObject.Arch,
 | |
|             "toolchain_tag"             : self._AutoGenObject.ToolChain,
 | |
|             "build_target"              : self._AutoGenObject.BuildTarget,
 | |
| 
 | |
|             "platform_build_directory"  : self.PlatformInfo.BuildDir,
 | |
|             "module_build_directory"    : self._AutoGenObject.BuildDir,
 | |
|             "module_output_directory"   : self._AutoGenObject.OutputDir,
 | |
|             "module_debug_directory"    : self._AutoGenObject.DebugDir,
 | |
| 
 | |
|             "separator"                 : Separator,
 | |
|             "module_tool_definitions"   : ToolsDef,
 | |
| 
 | |
|             "shell_command_code"        : self._SHELL_CMD_[self._FileType].keys(),
 | |
|             "shell_command"             : self._SHELL_CMD_[self._FileType].values(),
 | |
| 
 | |
|             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
 | |
|             "custom_makefile_content"   : CustomMakefile
 | |
|         }
 | |
| 
 | |
|         return MakefileTemplateDict
 | |
| 
 | |
|     _TemplateDict = property(_CreateTemplateDict)
 | |
| 
 | |
| ## 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 = $(WORKSPACE)${separator}${platform_relative_directory}
 | |
| 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 = []
 | |
| 
 | |
|     # Compose a dict object containing information used to do replacement in template
 | |
|     def _CreateTemplateDict(self):
 | |
|         Separator = self._SEP_[self._FileType]
 | |
| 
 | |
|         PlatformInfo = self._AutoGenObject
 | |
|         if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:
 | |
|             EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
 | |
|                             ExtraData="[%s]" % str(self._AutoGenObject))
 | |
| 
 | |
|         self.IntermediateDirectoryList = ["$(BUILD_DIR)"]
 | |
|         self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()
 | |
|         self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()
 | |
| 
 | |
|         MakefileName = self._FILE_NAME_[self._FileType]
 | |
|         LibraryMakefileList = []
 | |
|         LibraryMakeCommandList = []
 | |
|         for D in self.LibraryBuildDirectoryList:
 | |
|             D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})
 | |
|             Makefile = os.path.join(D, MakefileName)
 | |
|             Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
 | |
|             LibraryMakefileList.append(Makefile)
 | |
|             LibraryMakeCommandList.append(Command)
 | |
|         self.LibraryMakeCommandList = LibraryMakeCommandList
 | |
| 
 | |
|         ModuleMakefileList = []
 | |
|         ModuleMakeCommandList = []
 | |
|         for D in self.ModuleBuildDirectoryList:
 | |
|             D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})
 | |
|             Makefile = os.path.join(D, MakefileName)
 | |
|             Command = self._MAKE_TEMPLATE_[self._FileType] % {"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"                 : PlatformInfo.ToolDefinition["MAKE"]["PATH"],
 | |
|             "makefile_name"             : MakefileName,
 | |
|             "platform_name"             : PlatformInfo.Name,
 | |
|             "platform_guid"             : PlatformInfo.Guid,
 | |
|             "platform_version"          : PlatformInfo.Version,
 | |
|             "platform_file"             : self._AutoGenObject.MetaFile,
 | |
|             "platform_relative_directory": PlatformInfo.SourceDir,
 | |
|             "platform_output_directory" : PlatformInfo.OutputDir,
 | |
|             "platform_build_directory"  : PlatformInfo.BuildDir,
 | |
| 
 | |
|             "toolchain_tag"             : PlatformInfo.ToolChain,
 | |
|             "build_target"              : PlatformInfo.BuildTarget,
 | |
|             "shell_command_code"        : self._SHELL_CMD_[self._FileType].keys(),
 | |
|             "shell_command"             : self._SHELL_CMD_[self._FileType].values(),
 | |
|             "build_architecture_list"   : self._AutoGenObject.Arch,
 | |
|             "architecture"              : self._AutoGenObject.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
 | |
| 
 | |
|     _TemplateDict = property(_CreateTemplateDict)
 | |
| 
 | |
| ## 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 = []
 | |
| 
 | |
|     # Compose a dict object containing information used to do replacement in template
 | |
|     def _CreateTemplateDict(self):
 | |
|         Separator = self._SEP_[self._FileType]
 | |
| 
 | |
|         # any platform autogen object is ok because we just need common information
 | |
|         PlatformInfo = self._AutoGenObject
 | |
| 
 | |
|         if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:
 | |
|             EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
 | |
|                             ExtraData="[%s]" % str(self._AutoGenObject))
 | |
| 
 | |
|         for Arch in PlatformInfo.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 PlatformInfo.FdfFile != None and PlatformInfo.FdfFile != "":
 | |
|             FdfFileList = [PlatformInfo.FdfFile]
 | |
|             # macros passed to GenFds
 | |
|             MacroList.append('"%s=%s"' % ("EFI_SOURCE", GlobalData.gEfiSource.replace('\\', '\\\\')))
 | |
|             MacroList.append('"%s=%s"' % ("EDK_SOURCE", GlobalData.gEdkSource.replace('\\', '\\\\')))
 | |
|             MacroDict = {}
 | |
|             MacroDict.update(GlobalData.gGlobalDefines)
 | |
|             MacroDict.update(GlobalData.gCommandLineDefines)
 | |
|             MacroDict.pop("EFI_SOURCE", "dummy")
 | |
|             MacroDict.pop("EDK_SOURCE", "dummy")
 | |
|             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 GlobalData.gIgnoreSource:
 | |
|             ExtraOption += " --ignore-sources"
 | |
| 
 | |
|         MakefileName = self._FILE_NAME_[self._FileType]
 | |
|         SubBuildCommandList = []
 | |
|         for A in PlatformInfo.ArchList:
 | |
|             Command = self._MAKE_TEMPLATE_[self._FileType] % {"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"                 : PlatformInfo.ToolDefinition["MAKE"]["PATH"],
 | |
|             "platform_name"             : PlatformInfo.Name,
 | |
|             "platform_guid"             : PlatformInfo.Guid,
 | |
|             "platform_version"          : PlatformInfo.Version,
 | |
|             "platform_build_directory"  : PlatformInfo.BuildDir,
 | |
|             "conf_directory"            : GlobalData.gConfDirectory,
 | |
| 
 | |
|             "toolchain_tag"             : PlatformInfo.ToolChain,
 | |
|             "build_target"              : PlatformInfo.BuildTarget,
 | |
|             "shell_command_code"        : self._SHELL_CMD_[self._FileType].keys(),
 | |
|             "shell_command"             : self._SHELL_CMD_[self._FileType].values(),
 | |
|             'arch'                      : list(PlatformInfo.ArchList),
 | |
|             "build_architecture_list"   : ','.join(PlatformInfo.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(PlatformInfo),
 | |
|             "fd"                        : PlatformInfo.FdTargetList,
 | |
|             "fv"                        : PlatformInfo.FvTargetList,
 | |
|             "cap"                       : PlatformInfo.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
 | |
| 
 | |
|     _TemplateDict = property(_CreateTemplateDict)
 | |
| 
 | |
| # This acts like the main() function for the script, unless it is 'import'ed into another script.
 | |
| if __name__ == '__main__':
 | |
|     pass
 | |
| 
 |