This patch modifies the Makefile generation not to stop
adding Makfile rules when the first final target is found.
E.g.:
If the following rules are described in build_rule.txt:
 -[Rule1]: .X files generate .Y and .Z files;
 -[Rule2]: .Z files generate .Z1 files.
Currently, if a File1.X file was part of the sources of a
module, only [Rule1] would be generated in the Makefile.
Indeed, there are no rules to apply to .Y files: .Y files
are a final target. However, there is still [Rule2] to
apply to .Z files.
This patch also adds a dependency between the first
ouput file of a rule and the other output files.
For instance, with the same example as above, File1.Y
and File1.Z are generated by the following rule:
File1.Y: File1.X
    <Generate File1.Y>
    <Generate File1.Z>
and the new dependency is:
File1.Z: File1.Y
This is necessary to keep a dependency order during the
execution of the Makefile. Indeed, .Y and .Z files are
generated by the execution of a common set of commands,
and without this rule, there is no explicit dependency
relation between them.
Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
Suggested-by: Tomas Pilar <Tomas.Pilar@arm.com>
Reviewed-by: Bob Feng <bob.c.feng@intel.com>
		
	
		
			
				
	
	
		
			1763 lines
		
	
	
		
			74 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1763 lines
		
	
	
		
			74 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
## @file
 | 
						|
# Create makefile for MS nmake and GNU make
 | 
						|
#
 | 
						|
# Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>
 | 
						|
# Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
 | 
						|
# SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
#
 | 
						|
 | 
						|
## Import Modules
 | 
						|
#
 | 
						|
from __future__ import absolute_import
 | 
						|
import Common.LongFilePathOs as os
 | 
						|
import sys
 | 
						|
import string
 | 
						|
import re
 | 
						|
import os.path as path
 | 
						|
from Common.LongFilePathSupport import OpenLongFilePath as open
 | 
						|
from Common.MultipleWorkspace import MultipleWorkspace as mws
 | 
						|
from Common.BuildToolError import *
 | 
						|
from Common.Misc import *
 | 
						|
from Common.StringUtils import *
 | 
						|
from .BuildEngine import *
 | 
						|
import Common.GlobalData as GlobalData
 | 
						|
from collections import OrderedDict
 | 
						|
from Common.DataType import TAB_COMPILER_MSFT
 | 
						|
 | 
						|
## Regular expression for finding header file inclusions
 | 
						|
gIncludePattern = re.compile(r"^[ \t]*[#%]?[ \t]*include(?:[ \t]*(?:\\(?:\r\n|\r|\n))*[ \t]*)*(?:\(?[\"<]?[ \t]*)([-\w.\\/() \t]+)(?:[ \t]*[\">]?\)?)", re.MULTILINE | re.UNICODE | re.IGNORECASE)
 | 
						|
 | 
						|
## Regular expression for matching macro used in header file inclusion
 | 
						|
gMacroPattern = re.compile("([_A-Z][_A-Z0-9]*)[ \t]*\((.+)\)", re.UNICODE)
 | 
						|
 | 
						|
gIsFileMap = {}
 | 
						|
 | 
						|
## pattern for include style in Edk.x code
 | 
						|
gProtocolDefinition = "Protocol/%(HeaderKey)s/%(HeaderKey)s.h"
 | 
						|
gGuidDefinition = "Guid/%(HeaderKey)s/%(HeaderKey)s.h"
 | 
						|
gArchProtocolDefinition = "ArchProtocol/%(HeaderKey)s/%(HeaderKey)s.h"
 | 
						|
gPpiDefinition = "Ppi/%(HeaderKey)s/%(HeaderKey)s.h"
 | 
						|
gIncludeMacroConversion = {
 | 
						|
  "EFI_PROTOCOL_DEFINITION"         :   gProtocolDefinition,
 | 
						|
  "EFI_GUID_DEFINITION"             :   gGuidDefinition,
 | 
						|
  "EFI_ARCH_PROTOCOL_DEFINITION"    :   gArchProtocolDefinition,
 | 
						|
  "EFI_PROTOCOL_PRODUCER"           :   gProtocolDefinition,
 | 
						|
  "EFI_PROTOCOL_CONSUMER"           :   gProtocolDefinition,
 | 
						|
  "EFI_PROTOCOL_DEPENDENCY"         :   gProtocolDefinition,
 | 
						|
  "EFI_ARCH_PROTOCOL_PRODUCER"      :   gArchProtocolDefinition,
 | 
						|
  "EFI_ARCH_PROTOCOL_CONSUMER"      :   gArchProtocolDefinition,
 | 
						|
  "EFI_ARCH_PROTOCOL_DEPENDENCY"    :   gArchProtocolDefinition,
 | 
						|
  "EFI_PPI_DEFINITION"              :   gPpiDefinition,
 | 
						|
  "EFI_PPI_PRODUCER"                :   gPpiDefinition,
 | 
						|
  "EFI_PPI_CONSUMER"                :   gPpiDefinition,
 | 
						|
  "EFI_PPI_DEPENDENCY"              :   gPpiDefinition,
 | 
						|
}
 | 
						|
 | 
						|
NMAKE_FILETYPE = "nmake"
 | 
						|
GMAKE_FILETYPE = "gmake"
 | 
						|
WIN32_PLATFORM = "win32"
 | 
						|
POSIX_PLATFORM = "posix"
 | 
						|
 | 
						|
## BuildFile class
 | 
						|
#
 | 
						|
#  This base class encapsules build file and its generation. It uses template to generate
 | 
						|
#  the content of build file. The content of build file will be got from AutoGen objects.
 | 
						|
#
 | 
						|
class BuildFile(object):
 | 
						|
    ## template used to generate the build file (i.e. makefile if using make)
 | 
						|
    _TEMPLATE_ = TemplateString('')
 | 
						|
 | 
						|
    _DEFAULT_FILE_NAME_ = "Makefile"
 | 
						|
 | 
						|
    ## default file name for each type of build file
 | 
						|
    _FILE_NAME_ = {
 | 
						|
        NMAKE_FILETYPE :   "Makefile",
 | 
						|
        GMAKE_FILETYPE :   "GNUmakefile"
 | 
						|
    }
 | 
						|
 | 
						|
    # Get Makefile name.
 | 
						|
    def getMakefileName(self):
 | 
						|
        if not self._FileType:
 | 
						|
            return self._DEFAULT_FILE_NAME_
 | 
						|
        else:
 | 
						|
            return self._FILE_NAME_[self._FileType]
 | 
						|
 | 
						|
    ## Fixed header string for makefile
 | 
						|
    _MAKEFILE_HEADER = '''#
 | 
						|
# DO NOT EDIT
 | 
						|
# This file is auto-generated by build utility
 | 
						|
#
 | 
						|
# Module Name:
 | 
						|
#
 | 
						|
#   %s
 | 
						|
#
 | 
						|
# Abstract:
 | 
						|
#
 | 
						|
#   Auto-generated makefile for building modules, libraries or platform
 | 
						|
#
 | 
						|
    '''
 | 
						|
 | 
						|
    ## Header string for each type of build file
 | 
						|
    _FILE_HEADER_ = {
 | 
						|
        NMAKE_FILETYPE :   _MAKEFILE_HEADER % _FILE_NAME_[NMAKE_FILETYPE],
 | 
						|
        GMAKE_FILETYPE :   _MAKEFILE_HEADER % _FILE_NAME_[GMAKE_FILETYPE]
 | 
						|
    }
 | 
						|
 | 
						|
    ## shell commands which can be used in build file in the form of macro
 | 
						|
    #   $(CP)     copy file command
 | 
						|
    #   $(MV)     move file command
 | 
						|
    #   $(RM)     remove file command
 | 
						|
    #   $(MD)     create dir command
 | 
						|
    #   $(RD)     remove dir command
 | 
						|
    #
 | 
						|
    _SHELL_CMD_ = {
 | 
						|
        WIN32_PLATFORM : {
 | 
						|
            "CP"    :   "copy /y",
 | 
						|
            "MV"    :   "move /y",
 | 
						|
            "RM"    :   "del /f /q",
 | 
						|
            "MD"    :   "mkdir",
 | 
						|
            "RD"    :   "rmdir /s /q",
 | 
						|
        },
 | 
						|
 | 
						|
        POSIX_PLATFORM : {
 | 
						|
            "CP"    :   "cp -f",
 | 
						|
            "MV"    :   "mv -f",
 | 
						|
            "RM"    :   "rm -f",
 | 
						|
            "MD"    :   "mkdir -p",
 | 
						|
            "RD"    :   "rm -r -f",
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    ## directory separator
 | 
						|
    _SEP_ = {
 | 
						|
        WIN32_PLATFORM :   "\\",
 | 
						|
        POSIX_PLATFORM :   "/"
 | 
						|
    }
 | 
						|
 | 
						|
    ## directory creation template
 | 
						|
    _MD_TEMPLATE_ = {
 | 
						|
        WIN32_PLATFORM :   'if not exist %(dir)s $(MD) %(dir)s',
 | 
						|
        POSIX_PLATFORM :   "$(MD) %(dir)s"
 | 
						|
    }
 | 
						|
 | 
						|
    ## directory removal template
 | 
						|
    _RD_TEMPLATE_ = {
 | 
						|
        WIN32_PLATFORM :   'if exist %(dir)s $(RD) %(dir)s',
 | 
						|
        POSIX_PLATFORM :   "$(RD) %(dir)s"
 | 
						|
    }
 | 
						|
    ## cp if exist
 | 
						|
    _CP_TEMPLATE_ = {
 | 
						|
        WIN32_PLATFORM :   'if exist %(Src)s $(CP) %(Src)s %(Dst)s',
 | 
						|
        POSIX_PLATFORM :   "test -f %(Src)s && $(CP) %(Src)s %(Dst)s"
 | 
						|
    }
 | 
						|
 | 
						|
    _CD_TEMPLATE_ = {
 | 
						|
        WIN32_PLATFORM :   'if exist %(dir)s cd %(dir)s',
 | 
						|
        POSIX_PLATFORM :   "test -e %(dir)s && cd %(dir)s"
 | 
						|
    }
 | 
						|
 | 
						|
    _MAKE_TEMPLATE_ = {
 | 
						|
        WIN32_PLATFORM :   'if exist %(file)s "$(MAKE)" $(MAKE_FLAGS) -f %(file)s',
 | 
						|
        POSIX_PLATFORM :   'test -e %(file)s && "$(MAKE)" $(MAKE_FLAGS) -f %(file)s'
 | 
						|
    }
 | 
						|
 | 
						|
    _INCLUDE_CMD_ = {
 | 
						|
        NMAKE_FILETYPE :   '!INCLUDE',
 | 
						|
        GMAKE_FILETYPE :   "include"
 | 
						|
    }
 | 
						|
 | 
						|
    _INC_FLAG_ = {TAB_COMPILER_MSFT : "/I", "GCC" : "-I", "INTEL" : "-I", "RVCT" : "-I", "NASM" : "-I"}
 | 
						|
 | 
						|
    ## Constructor of BuildFile
 | 
						|
    #
 | 
						|
    #   @param  AutoGenObject   Object of AutoGen class
 | 
						|
    #
 | 
						|
    def __init__(self, AutoGenObject):
 | 
						|
        self._AutoGenObject = AutoGenObject
 | 
						|
 | 
						|
        MakePath = AutoGenObject.BuildOption.get('MAKE', {}).get('PATH')
 | 
						|
        if not MakePath:
 | 
						|
            self._FileType = ""
 | 
						|
        elif "nmake" in MakePath:
 | 
						|
            self._FileType = NMAKE_FILETYPE
 | 
						|
        else:
 | 
						|
            self._FileType = "gmake"
 | 
						|
 | 
						|
        if sys.platform == "win32":
 | 
						|
            self._Platform = WIN32_PLATFORM
 | 
						|
        else:
 | 
						|
            self._Platform = POSIX_PLATFORM
 | 
						|
 | 
						|
    ## Create build file.
 | 
						|
    #
 | 
						|
    #  Only nmake and gmake are supported.
 | 
						|
    #
 | 
						|
    #  @retval TRUE     The build file is created or re-created successfully.
 | 
						|
    #  @retval FALSE    The build file exists and is the same as the one to be generated.
 | 
						|
    #
 | 
						|
    def Generate(self):
 | 
						|
        FileContent = self._TEMPLATE_.Replace(self._TemplateDict)
 | 
						|
        FileName = self.getMakefileName()
 | 
						|
        if not os.path.exists(os.path.join(self._AutoGenObject.MakeFileDir, "deps.txt")):
 | 
						|
            with open(os.path.join(self._AutoGenObject.MakeFileDir, "deps.txt"),"w+") as fd:
 | 
						|
                fd.write("")
 | 
						|
        if not os.path.exists(os.path.join(self._AutoGenObject.MakeFileDir, "dependency")):
 | 
						|
            with open(os.path.join(self._AutoGenObject.MakeFileDir, "dependency"),"w+") as fd:
 | 
						|
                fd.write("")
 | 
						|
        if not os.path.exists(os.path.join(self._AutoGenObject.MakeFileDir, "deps_target")):
 | 
						|
            with open(os.path.join(self._AutoGenObject.MakeFileDir, "deps_target"),"w+") as fd:
 | 
						|
                fd.write("")
 | 
						|
        return SaveFileOnChange(os.path.join(self._AutoGenObject.MakeFileDir, FileName), FileContent, False)
 | 
						|
 | 
						|
    ## Return a list of directory creation command string
 | 
						|
    #
 | 
						|
    #   @param      DirList     The list of directory to be created
 | 
						|
    #
 | 
						|
    #   @retval     list        The directory creation command list
 | 
						|
    #
 | 
						|
    def GetCreateDirectoryCommand(self, DirList):
 | 
						|
        return [self._MD_TEMPLATE_[self._Platform] % {'dir':Dir} for Dir in DirList]
 | 
						|
 | 
						|
    ## Return a list of directory removal command string
 | 
						|
    #
 | 
						|
    #   @param      DirList     The list of directory to be removed
 | 
						|
    #
 | 
						|
    #   @retval     list        The directory removal command list
 | 
						|
    #
 | 
						|
    def GetRemoveDirectoryCommand(self, DirList):
 | 
						|
        return [self._RD_TEMPLATE_[self._Platform] % {'dir':Dir} for Dir in DirList]
 | 
						|
 | 
						|
    def PlaceMacro(self, Path, MacroDefinitions=None):
 | 
						|
        if Path.startswith("$("):
 | 
						|
            return Path
 | 
						|
        else:
 | 
						|
            if MacroDefinitions is None:
 | 
						|
                MacroDefinitions = {}
 | 
						|
            PathLength = len(Path)
 | 
						|
            for MacroName in MacroDefinitions:
 | 
						|
                MacroValue = MacroDefinitions[MacroName]
 | 
						|
                MacroValueLength = len(MacroValue)
 | 
						|
                if MacroValueLength == 0:
 | 
						|
                    continue
 | 
						|
                if MacroValueLength <= PathLength and Path.startswith(MacroValue):
 | 
						|
                    Path = "$(%s)%s" % (MacroName, Path[MacroValueLength:])
 | 
						|
                    break
 | 
						|
            return Path
 | 
						|
 | 
						|
## ModuleMakefile class
 | 
						|
#
 | 
						|
#  This class encapsules makefie and its generation for module. It uses template to generate
 | 
						|
#  the content of makefile. The content of makefile will be got from ModuleAutoGen object.
 | 
						|
#
 | 
						|
class ModuleMakefile(BuildFile):
 | 
						|
    ## template used to generate the makefile for module
 | 
						|
    _TEMPLATE_ = TemplateString('''\
 | 
						|
${makefile_header}
 | 
						|
 | 
						|
#
 | 
						|
# Platform Macro Definition
 | 
						|
#
 | 
						|
PLATFORM_NAME = ${platform_name}
 | 
						|
PLATFORM_GUID = ${platform_guid}
 | 
						|
PLATFORM_VERSION = ${platform_version}
 | 
						|
PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
 | 
						|
PLATFORM_DIR = ${platform_dir}
 | 
						|
PLATFORM_OUTPUT_DIR = ${platform_output_directory}
 | 
						|
 | 
						|
#
 | 
						|
# Module Macro Definition
 | 
						|
#
 | 
						|
MODULE_NAME = ${module_name}
 | 
						|
MODULE_GUID = ${module_guid}
 | 
						|
MODULE_NAME_GUID = ${module_name_guid}
 | 
						|
MODULE_VERSION = ${module_version}
 | 
						|
MODULE_TYPE = ${module_type}
 | 
						|
MODULE_FILE = ${module_file}
 | 
						|
MODULE_FILE_BASE_NAME = ${module_file_base_name}
 | 
						|
BASE_NAME = $(MODULE_NAME)
 | 
						|
MODULE_RELATIVE_DIR = ${module_relative_directory}
 | 
						|
PACKAGE_RELATIVE_DIR = ${package_relative_directory}
 | 
						|
MODULE_DIR = ${module_dir}
 | 
						|
FFS_OUTPUT_DIR = ${ffs_output_directory}
 | 
						|
 | 
						|
MODULE_ENTRY_POINT = ${module_entry_point}
 | 
						|
ARCH_ENTRY_POINT = ${arch_entry_point}
 | 
						|
IMAGE_ENTRY_POINT = ${image_entry_point}
 | 
						|
 | 
						|
${BEGIN}${module_extra_defines}
 | 
						|
${END}
 | 
						|
#
 | 
						|
# Build Configuration Macro Definition
 | 
						|
#
 | 
						|
ARCH = ${architecture}
 | 
						|
TOOLCHAIN = ${toolchain_tag}
 | 
						|
TOOLCHAIN_TAG = ${toolchain_tag}
 | 
						|
TARGET = ${build_target}
 | 
						|
 | 
						|
#
 | 
						|
# Build Directory Macro Definition
 | 
						|
#
 | 
						|
# PLATFORM_BUILD_DIR = ${platform_build_directory}
 | 
						|
BUILD_DIR = ${platform_build_directory}
 | 
						|
BIN_DIR = $(BUILD_DIR)${separator}${architecture}
 | 
						|
LIB_DIR = $(BIN_DIR)
 | 
						|
MODULE_BUILD_DIR = ${module_build_directory}
 | 
						|
OUTPUT_DIR = ${module_output_directory}
 | 
						|
DEBUG_DIR = ${module_debug_directory}
 | 
						|
DEST_DIR_OUTPUT = $(OUTPUT_DIR)
 | 
						|
DEST_DIR_DEBUG = $(DEBUG_DIR)
 | 
						|
 | 
						|
#
 | 
						|
# Shell Command Macro
 | 
						|
#
 | 
						|
${BEGIN}${shell_command_code} = ${shell_command}
 | 
						|
${END}
 | 
						|
 | 
						|
#
 | 
						|
# Tools definitions specific to this module
 | 
						|
#
 | 
						|
${BEGIN}${module_tool_definitions}
 | 
						|
${END}
 | 
						|
MAKE_FILE = ${makefile_path}
 | 
						|
 | 
						|
#
 | 
						|
# Build Macro
 | 
						|
#
 | 
						|
${BEGIN}${file_macro}
 | 
						|
${END}
 | 
						|
 | 
						|
#
 | 
						|
# Overridable Target Macro Definitions
 | 
						|
#
 | 
						|
FORCE_REBUILD = force_build
 | 
						|
INIT_TARGET = init
 | 
						|
PCH_TARGET =
 | 
						|
BC_TARGET = ${BEGIN}${backward_compatible_target} ${END}
 | 
						|
CODA_TARGET = ${BEGIN}${remaining_build_target} \\
 | 
						|
              ${END}
 | 
						|
 | 
						|
#
 | 
						|
# Default target, which will build dependent libraries in addition to source files
 | 
						|
#
 | 
						|
 | 
						|
all: mbuild
 | 
						|
 | 
						|
 | 
						|
#
 | 
						|
# Target used when called from platform makefile, which will bypass the build of dependent libraries
 | 
						|
#
 | 
						|
 | 
						|
pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
 | 
						|
 | 
						|
#
 | 
						|
# ModuleTarget
 | 
						|
#
 | 
						|
 | 
						|
mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET)
 | 
						|
 | 
						|
#
 | 
						|
# Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets
 | 
						|
#
 | 
						|
 | 
						|
tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
 | 
						|
 | 
						|
#
 | 
						|
# Phony target which is used to force executing commands for a target
 | 
						|
#
 | 
						|
force_build:
 | 
						|
\t-@
 | 
						|
 | 
						|
#
 | 
						|
# Target to update the FD
 | 
						|
#
 | 
						|
 | 
						|
fds: mbuild gen_fds
 | 
						|
 | 
						|
#
 | 
						|
# Initialization target: print build information and create necessary directories
 | 
						|
#
 | 
						|
init: info dirs
 | 
						|
 | 
						|
info:
 | 
						|
\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
 | 
						|
 | 
						|
dirs:
 | 
						|
${BEGIN}\t-@${create_directory_command}\n${END}
 | 
						|
 | 
						|
strdefs:
 | 
						|
\t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h
 | 
						|
 | 
						|
#
 | 
						|
# GenLibsTarget
 | 
						|
#
 | 
						|
gen_libs:
 | 
						|
\t${BEGIN}@"$(MAKE)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name}
 | 
						|
\t${END}@cd $(MODULE_BUILD_DIR)
 | 
						|
 | 
						|
#
 | 
						|
# Build Flash Device Image
 | 
						|
#
 | 
						|
gen_fds:
 | 
						|
\t@"$(MAKE)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds
 | 
						|
\t@cd $(MODULE_BUILD_DIR)
 | 
						|
 | 
						|
${INCLUDETAG}
 | 
						|
 | 
						|
#
 | 
						|
# Individual Object Build Targets
 | 
						|
#
 | 
						|
${BEGIN}${file_build_target}
 | 
						|
${END}
 | 
						|
 | 
						|
#
 | 
						|
# clean all intermediate files
 | 
						|
#
 | 
						|
clean:
 | 
						|
\t${BEGIN}${clean_command}
 | 
						|
\t${END}\t$(RM) AutoGenTimeStamp
 | 
						|
 | 
						|
#
 | 
						|
# clean all generated files
 | 
						|
#
 | 
						|
cleanall:
 | 
						|
${BEGIN}\t${cleanall_command}
 | 
						|
${END}\t$(RM) *.pdb *.idb > NUL 2>&1
 | 
						|
\t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi
 | 
						|
\t$(RM) AutoGenTimeStamp
 | 
						|
 | 
						|
#
 | 
						|
# clean all dependent libraries built
 | 
						|
#
 | 
						|
cleanlib:
 | 
						|
\t${BEGIN}-@${library_build_command} cleanall
 | 
						|
\t${END}@cd $(MODULE_BUILD_DIR)\n\n''')
 | 
						|
 | 
						|
    _FILE_MACRO_TEMPLATE = TemplateString("${macro_name} = ${BEGIN} \\\n    ${source_file}${END}\n")
 | 
						|
    _BUILD_TARGET_TEMPLATE = TemplateString("${BEGIN}${target} : ${deps}\n${END}\t${cmd}\n")
 | 
						|
 | 
						|
    ## Constructor of ModuleMakefile
 | 
						|
    #
 | 
						|
    #   @param  ModuleAutoGen   Object of ModuleAutoGen class
 | 
						|
    #
 | 
						|
    def __init__(self, ModuleAutoGen):
 | 
						|
        BuildFile.__init__(self, ModuleAutoGen)
 | 
						|
        self.PlatformInfo = self._AutoGenObject.PlatformInfo
 | 
						|
 | 
						|
        self.ResultFileList = []
 | 
						|
        self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
 | 
						|
 | 
						|
        self.FileBuildTargetList = []       # [(src, target string)]
 | 
						|
        self.BuildTargetList = []           # [target string]
 | 
						|
        self.PendingBuildTargetList = []    # [FileBuildRule objects]
 | 
						|
        self.CommonFileDependency = []
 | 
						|
        self.FileListMacros = {}
 | 
						|
        self.ListFileMacros = {}
 | 
						|
        self.ObjTargetDict = OrderedDict()
 | 
						|
        self.FileCache = {}
 | 
						|
        self.LibraryBuildCommandList = []
 | 
						|
        self.LibraryFileList = []
 | 
						|
        self.LibraryMakefileList = []
 | 
						|
        self.LibraryBuildDirectoryList = []
 | 
						|
        self.SystemLibraryList = []
 | 
						|
        self.Macros = OrderedDict()
 | 
						|
        self.Macros["OUTPUT_DIR"      ] = self._AutoGenObject.Macros["OUTPUT_DIR"]
 | 
						|
        self.Macros["DEBUG_DIR"       ] = self._AutoGenObject.Macros["DEBUG_DIR"]
 | 
						|
        self.Macros["MODULE_BUILD_DIR"] = self._AutoGenObject.Macros["MODULE_BUILD_DIR"]
 | 
						|
        self.Macros["BIN_DIR"         ] = self._AutoGenObject.Macros["BIN_DIR"]
 | 
						|
        self.Macros["BUILD_DIR"       ] = self._AutoGenObject.Macros["BUILD_DIR"]
 | 
						|
        self.Macros["WORKSPACE"       ] = self._AutoGenObject.Macros["WORKSPACE"]
 | 
						|
        self.Macros["FFS_OUTPUT_DIR"  ] = self._AutoGenObject.Macros["FFS_OUTPUT_DIR"]
 | 
						|
        self.GenFfsList                 = ModuleAutoGen.GenFfsList
 | 
						|
        self.MacroList = ['FFS_OUTPUT_DIR', 'MODULE_GUID', 'OUTPUT_DIR']
 | 
						|
        self.FfsOutputFileList = []
 | 
						|
        self.DependencyHeaderFileSet = set()
 | 
						|
 | 
						|
    # Compose a dict object containing information used to do replacement in template
 | 
						|
    @property
 | 
						|
    def _TemplateDict(self):
 | 
						|
        MyAgo = self._AutoGenObject
 | 
						|
        Separator = self._SEP_[self._Platform]
 | 
						|
 | 
						|
        # break build if no source files and binary files are found
 | 
						|
        if len(MyAgo.SourceFileList) == 0 and len(MyAgo.BinaryFileList) == 0:
 | 
						|
            EdkLogger.error("build", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]"
 | 
						|
                            % (MyAgo.BuildTarget, MyAgo.ToolChain, MyAgo.Arch),
 | 
						|
                            ExtraData="[%s]" % str(MyAgo))
 | 
						|
 | 
						|
        # convert dependent libraries to build command
 | 
						|
        self.ProcessDependentLibrary()
 | 
						|
        if len(MyAgo.Module.ModuleEntryPointList) > 0:
 | 
						|
            ModuleEntryPoint = MyAgo.Module.ModuleEntryPointList[0]
 | 
						|
        else:
 | 
						|
            ModuleEntryPoint = "_ModuleEntryPoint"
 | 
						|
 | 
						|
        ArchEntryPoint = ModuleEntryPoint
 | 
						|
 | 
						|
        if MyAgo.Arch == "EBC":
 | 
						|
            # EBC compiler always use "EfiStart" as entry point. Only applies to EdkII modules
 | 
						|
            ImageEntryPoint = "EfiStart"
 | 
						|
        else:
 | 
						|
            # EdkII modules always use "_ModuleEntryPoint" as entry point
 | 
						|
            ImageEntryPoint = "_ModuleEntryPoint"
 | 
						|
 | 
						|
        for k, v in MyAgo.Module.Defines.items():
 | 
						|
            if k not in MyAgo.Macros:
 | 
						|
                MyAgo.Macros[k] = v
 | 
						|
 | 
						|
        if 'MODULE_ENTRY_POINT' not in MyAgo.Macros:
 | 
						|
            MyAgo.Macros['MODULE_ENTRY_POINT'] = ModuleEntryPoint
 | 
						|
        if 'ARCH_ENTRY_POINT' not in MyAgo.Macros:
 | 
						|
            MyAgo.Macros['ARCH_ENTRY_POINT'] = ArchEntryPoint
 | 
						|
        if 'IMAGE_ENTRY_POINT' not in MyAgo.Macros:
 | 
						|
            MyAgo.Macros['IMAGE_ENTRY_POINT'] = ImageEntryPoint
 | 
						|
 | 
						|
        PCI_COMPRESS_Flag = False
 | 
						|
        for k, v in MyAgo.Module.Defines.items():
 | 
						|
            if 'PCI_COMPRESS' == k and 'TRUE' == v:
 | 
						|
                PCI_COMPRESS_Flag = True
 | 
						|
 | 
						|
        # tools definitions
 | 
						|
        ToolsDef = []
 | 
						|
        IncPrefix = self._INC_FLAG_[MyAgo.ToolChainFamily]
 | 
						|
        for Tool in MyAgo.BuildOption:
 | 
						|
            for Attr in MyAgo.BuildOption[Tool]:
 | 
						|
                Value = MyAgo.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, 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))
 | 
						|
            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()
 | 
						|
        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 self._AutoGenObject.Macros[Macro] in str:
 | 
						|
                str = str.replace(self._AutoGenObject.Macros[Macro], '$(' + 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):
 | 
						|
        #
 | 
						|
        # 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:
 | 
						|
            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)
 | 
						|
                    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):
 | 
						|
        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()):
 | 
						|
                        CmdTargetDict[CmdSign] = Item.replace(Temp, CmdSign)
 | 
						|
                    else:
 | 
						|
                        CmdTargetDict[CmdSign] = "%s %s" % (CmdTargetDict[CmdSign], SingleCommandList[-1])
 | 
						|
                    Index = CommandList.index(Item)
 | 
						|
                    CommandList.pop(Index)
 | 
						|
                    if SingleCommandList[-1].endswith("%s%s.c" % (TAB_SLASH, CmdSumDict[CmdSign[3:].rsplit(TAB_SLASH, 1)[0]])):
 | 
						|
                        Cpplist = CmdCppDict[T.Target.SubDir]
 | 
						|
                        Cpplist.insert(0, '$(OBJLIST_%d): ' % list(self.ObjTargetDict.keys()).index(T.Target.SubDir))
 | 
						|
                        T.Commands[Index] = '%s\n\t%s' % (' \\\n\t'.join(Cpplist), 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
 |