2014-01-27 06:23:15 +01:00
## @file
# Create makefile for MS nmake and GNU make
#
2021-04-23 21:31:09 +02:00
# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
2021-09-23 10:59:00 +02:00
# Copyright (c) 2020 - 2021, Arm Limited. All rights reserved.<BR>
2019-04-04 01:03:11 +02:00
# SPDX-License-Identifier: BSD-2-Clause-Patent
2014-01-27 06:23:15 +01:00
#
## Import Modules
#
2018-10-15 02:27:53 +02:00
from __future__ import absolute_import
2014-08-15 05:06:48 +02:00
import Common . LongFilePathOs as os
2014-01-27 06:23:15 +01:00
import sys
import string
import re
import os . path as path
2014-08-15 05:06:48 +02:00
from Common . LongFilePathSupport import OpenLongFilePath as open
2015-10-08 11:27:14 +02:00
from Common . MultipleWorkspace import MultipleWorkspace as mws
2014-01-27 06:23:15 +01:00
from Common . BuildToolError import *
from Common . Misc import *
2018-05-19 12:50:25 +02:00
from Common . StringUtils import *
2018-07-13 12:18:37 +02:00
from . BuildEngine import *
2014-01-27 06:23:15 +01:00
import Common . GlobalData as GlobalData
2018-04-03 23:03:05 +02:00
from collections import OrderedDict
2018-08-24 18:33:17 +02:00
from Common . DataType import TAB_COMPILER_MSFT
2014-01-27 06:23:15 +01:00
## Regular expression for finding header file inclusions
2018-10-24 03:08:39 +02:00
gIncludePattern = re . compile ( r " ^[ \ t]*[# % ]?[ \ t]*include(?:[ \ t]*(?: \\ (?: \ r \ n| \ r| \ n))*[ \ t]*)*(?: \ (?[ \" <]?[ \ t]*)([- \ w. \\ /() \ t]+)(?:[ \ t]*[ \" >]? \ )?) " , re . MULTILINE | re . UNICODE | re . IGNORECASE )
2014-01-27 06:23:15 +01:00
## 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 ,
}
2020-02-10 11:49:07 +01:00
NMAKE_FILETYPE = " nmake "
GMAKE_FILETYPE = " gmake "
WIN32_PLATFORM = " win32 "
POSIX_PLATFORM = " posix "
2014-01-27 06:23:15 +01:00
## 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_ = {
2020-02-10 11:49:07 +01:00
NMAKE_FILETYPE : " Makefile " ,
GMAKE_FILETYPE : " GNUmakefile "
2014-01-27 06:23:15 +01:00
}
2020-02-10 11:49:07 +01:00
# Get Makefile name.
def getMakefileName ( self ) :
if not self . _FileType :
return self . _DEFAULT_FILE_NAME_
else :
return self . _FILE_NAME_ [ self . _FileType ]
2014-01-27 06:23:15 +01:00
## 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_ = {
2020-02-10 11:49:07 +01:00
NMAKE_FILETYPE : _MAKEFILE_HEADER % _FILE_NAME_ [ NMAKE_FILETYPE ] ,
GMAKE_FILETYPE : _MAKEFILE_HEADER % _FILE_NAME_ [ GMAKE_FILETYPE ]
2014-01-27 06:23:15 +01:00
}
## 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_ = {
2020-02-10 11:49:07 +01:00
WIN32_PLATFORM : {
2014-01-27 06:23:15 +01:00
" CP " : " copy /y " ,
" MV " : " move /y " ,
" RM " : " del /f /q " ,
" MD " : " mkdir " ,
" RD " : " rmdir /s /q " ,
} ,
2020-02-10 11:49:07 +01:00
POSIX_PLATFORM : {
2022-07-08 15:10:00 +02:00
" CP " : " cp -p -f " ,
2014-01-27 06:23:15 +01:00
" MV " : " mv -f " ,
" RM " : " rm -f " ,
" MD " : " mkdir -p " ,
" RD " : " rm -r -f " ,
}
}
## directory separator
_SEP_ = {
2020-02-10 11:49:07 +01:00
WIN32_PLATFORM : " \\ " ,
POSIX_PLATFORM : " / "
2014-01-27 06:23:15 +01:00
}
## directory creation template
_MD_TEMPLATE_ = {
2020-02-10 11:49:07 +01:00
WIN32_PLATFORM : ' if not exist %(dir)s $(MD) %(dir)s ' ,
POSIX_PLATFORM : " $(MD) %(dir)s "
2014-01-27 06:23:15 +01:00
}
## directory removal template
_RD_TEMPLATE_ = {
2020-02-10 11:49:07 +01:00
WIN32_PLATFORM : ' if exist %(dir)s $(RD) %(dir)s ' ,
POSIX_PLATFORM : " $(RD) %(dir)s "
2014-01-27 06:23:15 +01:00
}
2017-11-22 08:42:25 +01:00
## cp if exist
_CP_TEMPLATE_ = {
2020-02-10 11:49:07 +01:00
WIN32_PLATFORM : ' if exist %(Src)s $(CP) %(Src)s %(Dst)s ' ,
POSIX_PLATFORM : " test -f %(Src)s && $(CP) %(Src)s %(Dst)s "
2017-11-22 08:42:25 +01:00
}
2014-01-27 06:23:15 +01:00
_CD_TEMPLATE_ = {
2020-02-10 11:49:07 +01:00
WIN32_PLATFORM : ' if exist %(dir)s cd %(dir)s ' ,
POSIX_PLATFORM : " test -e %(dir)s && cd %(dir)s "
2014-01-27 06:23:15 +01:00
}
_MAKE_TEMPLATE_ = {
2020-02-10 11:49:07 +01:00
WIN32_PLATFORM : ' if exist %(file)s " $(MAKE) " $(MAKE_FLAGS) -f %(file)s ' ,
POSIX_PLATFORM : ' test -e %(file)s && " $(MAKE) " $(MAKE_FLAGS) -f %(file)s '
2014-01-27 06:23:15 +01:00
}
_INCLUDE_CMD_ = {
2020-02-10 11:49:07 +01:00
NMAKE_FILETYPE : ' !INCLUDE ' ,
GMAKE_FILETYPE : " include "
2014-01-27 06:23:15 +01:00
}
2022-05-03 20:48:20 +02:00
_INC_FLAG_ = { TAB_COMPILER_MSFT : " /I " , " GCC " : " -I " , " INTEL " : " -I " , " NASM " : " -I " }
2014-01-27 06:23:15 +01:00
## Constructor of BuildFile
#
# @param AutoGenObject Object of AutoGen class
#
def __init__ ( self , AutoGenObject ) :
self . _AutoGenObject = AutoGenObject
2020-02-10 11:49:07 +01:00
MakePath = AutoGenObject . BuildOption . get ( ' MAKE ' , { } ) . get ( ' PATH ' )
if not MakePath :
2021-09-23 10:59:00 +02:00
MakePath = AutoGenObject . ToolDefinition . get ( ' MAKE ' , { } ) . get ( ' PATH ' )
if " nmake " in MakePath :
2020-02-10 11:49:07 +01:00
self . _FileType = NMAKE_FILETYPE
else :
2021-09-23 10:59:00 +02:00
self . _FileType = GMAKE_FILETYPE
2020-02-10 11:49:07 +01:00
if sys . platform == " win32 " :
self . _Platform = WIN32_PLATFORM
else :
self . _Platform = POSIX_PLATFORM
## Create build file.
2014-01-27 06:23:15 +01:00
#
2020-02-10 11:49:07 +01:00
# Only nmake and gmake are supported.
2014-01-27 06:23:15 +01:00
#
2020-02-10 11:49:07 +01:00
# @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.
2014-01-27 06:23:15 +01:00
#
2020-02-10 11:49:07 +01:00
def Generate ( self ) :
2014-01-27 06:23:15 +01:00
FileContent = self . _TEMPLATE_ . Replace ( self . _TemplateDict )
2020-02-10 11:49:07 +01:00
FileName = self . getMakefileName ( )
2019-11-20 03:58:30 +01:00
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 ( " " )
2020-01-17 04:11:27 +01:00
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 ( " " )
2014-01-27 06:23:15 +01:00
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 ) :
2020-02-10 11:49:07 +01:00
return [ self . _MD_TEMPLATE_ [ self . _Platform ] % { ' dir ' : Dir } for Dir in DirList ]
2014-01-27 06:23:15 +01:00
## 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 ) :
2020-02-10 11:49:07 +01:00
return [ self . _RD_TEMPLATE_ [ self . _Platform ] % { ' dir ' : Dir } for Dir in DirList ]
2014-01-27 06:23:15 +01:00
2019-09-12 10:18:27 +02:00
def PlaceMacro ( self , Path , MacroDefinitions = None ) :
2014-01-27 06:23:15 +01:00
if Path . startswith ( " $( " ) :
return Path
else :
2019-09-12 10:18:27 +02:00
if MacroDefinitions is None :
MacroDefinitions = { }
2014-01-27 06:23:15 +01:00
PathLength = len ( Path )
for MacroName in MacroDefinitions :
MacroValue = MacroDefinitions [ MacroName ]
MacroValueLength = len ( MacroValue )
2017-11-22 08:42:25 +01:00
if MacroValueLength == 0 :
continue
2014-01-27 06:23:15 +01:00
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 }
2016-04-13 07:09:17 +02:00
PLATFORM_DIR = $ { platform_dir }
2014-01-27 06:23:15 +01:00
PLATFORM_OUTPUT_DIR = $ { platform_output_directory }
#
# Module Macro Definition
#
MODULE_NAME = $ { module_name }
MODULE_GUID = $ { module_guid }
2015-06-10 09:50:59 +02:00
MODULE_NAME_GUID = $ { module_name_guid }
2014-01-27 06:23:15 +01:00
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 }
2014-08-28 15:53:34 +02:00
PACKAGE_RELATIVE_DIR = $ { package_relative_directory }
2016-02-21 01:46:58 +01:00
MODULE_DIR = $ { module_dir }
2017-11-22 08:42:25 +01:00
FFS_OUTPUT_DIR = $ { ffs_output_directory }
2014-01-27 06:23:15 +01:00
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 )
2019-11-20 03:58:30 +01:00
$ { INCLUDETAG }
2014-01-27 06:23:15 +01:00
#
# Individual Object Build Targets
#
$ { BEGIN } $ { file_build_target }
$ { END }
#
# clean all intermediate files
#
clean :
\t $ { BEGIN } $ { clean_command }
2017-04-11 04:47:53 +02:00
\t $ { END } \t $ ( RM ) AutoGenTimeStamp
2014-01-27 06:23:15 +01:00
#
# 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
2017-04-11 04:47:53 +02:00
\t $ ( RM ) AutoGenTimeStamp
2014-01-27 06:23:15 +01:00
#
# 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 = { }
2019-04-18 13:20:46 +02:00
self . ObjTargetDict = OrderedDict ( )
2014-01-27 06:23:15 +01:00
self . FileCache = { }
self . LibraryBuildCommandList = [ ]
self . LibraryFileList = [ ]
self . LibraryMakefileList = [ ]
self . LibraryBuildDirectoryList = [ ]
self . SystemLibraryList = [ ]
2018-04-03 23:03:05 +02:00
self . Macros = OrderedDict ( )
2014-01-27 06:23:15 +01:00
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 " ]
2017-11-22 08:42:25 +01:00
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 = [ ]
2019-09-18 08:54:34 +02:00
self . DependencyHeaderFileSet = set ( )
2014-01-27 06:23:15 +01:00
# Compose a dict object containing information used to do replacement in template
2018-09-11 00:18:03 +02:00
@property
def _TemplateDict ( self ) :
2018-06-27 23:27:48 +02:00
MyAgo = self . _AutoGenObject
2020-02-10 11:49:07 +01:00
Separator = self . _SEP_ [ self . _Platform ]
2014-01-27 06:23:15 +01:00
# break build if no source files and binary files are found
2018-06-27 23:27:48 +02:00
if len ( MyAgo . SourceFileList ) == 0 and len ( MyAgo . BinaryFileList ) == 0 :
2014-01-27 06:23:15 +01:00
EdkLogger . error ( " build " , AUTOGEN_ERROR , " No files to be built in module [ %s , %s , %s ] "
2018-06-27 23:27:48 +02:00
% ( MyAgo . BuildTarget , MyAgo . ToolChain , MyAgo . Arch ) ,
ExtraData = " [ %s ] " % str ( MyAgo ) )
2014-01-27 06:23:15 +01:00
# convert dependent libraries to build command
self . ProcessDependentLibrary ( )
2018-06-27 23:27:48 +02:00
if len ( MyAgo . Module . ModuleEntryPointList ) > 0 :
ModuleEntryPoint = MyAgo . Module . ModuleEntryPointList [ 0 ]
2014-01-27 06:23:15 +01:00
else :
ModuleEntryPoint = " _ModuleEntryPoint "
2019-01-14 02:24:12 +01:00
ArchEntryPoint = ModuleEntryPoint
2014-01-27 06:23:15 +01:00
2018-06-27 23:27:48 +02:00
if MyAgo . Arch == " EBC " :
2014-01-27 06:23:15 +01:00
# 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 "
2018-11-28 02:58:55 +01:00
for k , v in MyAgo . Module . Defines . items ( ) :
2018-06-27 23:27:48 +02:00
if k not in MyAgo . Macros :
MyAgo . Macros [ k ] = v
2016-03-23 07:54:36 +01:00
2018-06-27 23:27:48 +02:00
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
2016-03-23 07:54:36 +01:00
2016-06-03 04:01:53 +02:00
PCI_COMPRESS_Flag = False
2018-11-28 02:58:55 +01:00
for k , v in MyAgo . Module . Defines . items ( ) :
2016-06-03 04:01:53 +02:00
if ' PCI_COMPRESS ' == k and ' TRUE ' == v :
PCI_COMPRESS_Flag = True
2014-01-27 06:23:15 +01:00
# tools definitions
ToolsDef = [ ]
2018-06-27 23:27:48 +02:00
IncPrefix = self . _INC_FLAG_ [ MyAgo . ToolChainFamily ]
2021-04-23 21:31:09 +02:00
for Tool in sorted ( list ( MyAgo . BuildOption ) ) :
Appended = False
for Attr in sorted ( list ( MyAgo . BuildOption [ Tool ] ) ) :
2018-06-27 23:27:48 +02:00
Value = MyAgo . BuildOption [ Tool ] [ Attr ]
2014-01-27 06:23:15 +01:00
if Attr == " FAMILY " :
continue
elif Attr == " PATH " :
ToolsDef . append ( " %s = %s " % ( Tool , Value ) )
2021-04-23 21:31:09 +02:00
Appended = True
2014-01-27 06:23:15 +01:00
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 " :
2018-06-27 23:27:48 +02:00
Value = RemoveDupOption ( Value , IncPrefix , MyAgo . IncludePathList )
2016-06-03 04:01:53 +02:00
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 )
2014-01-27 06:23:15 +01:00
ToolsDef . append ( " %s _ %s = %s " % ( Tool , Attr , Value ) )
2021-04-23 21:31:09 +02:00
Appended = True
if Appended :
ToolsDef . append ( " " )
2014-01-27 06:23:15 +01:00
2016-03-16 04:06:44 +01:00
# generate the Response file and Response flag
RespDict = self . CommandExceedLimit ( )
2018-06-27 23:27:48 +02:00
RespFileList = os . path . join ( MyAgo . OutputDir , ' respfilelist.txt ' )
2016-03-16 04:06:44 +01:00
if RespDict :
RespFileListContent = ' '
2018-04-17 16:40:15 +02:00
for Resp in RespDict :
2018-06-27 23:27:48 +02:00
RespFile = os . path . join ( MyAgo . OutputDir , str ( Resp ) . lower ( ) + ' .txt ' )
2016-03-23 07:54:36 +01:00
StrList = RespDict [ Resp ] . split ( ' ' )
UnexpandMacro = [ ]
NewStr = [ ]
for Str in StrList :
2019-11-20 03:58:30 +01:00
if ' $ ' in Str or ' -MMD ' in Str or ' -MF ' in Str :
2016-03-23 07:54:36 +01:00
UnexpandMacro . append ( Str )
else :
NewStr . append ( Str )
UnexpandMacroStr = ' ' . join ( UnexpandMacro )
NewRespStr = ' ' . join ( NewStr )
SaveFileOnChange ( RespFile , NewRespStr , False )
ToolsDef . append ( " %s = %s " % ( Resp , UnexpandMacroStr + ' @ ' + RespFile ) )
2018-12-18 03:45:04 +01:00
RespFileListContent + = ' @ ' + RespFile + TAB_LINE_BREAK
RespFileListContent + = NewRespStr + TAB_LINE_BREAK
2016-03-16 04:06:44 +01:00
SaveFileOnChange ( RespFileList , RespFileListContent , False )
else :
if os . path . exists ( RespFileList ) :
os . remove ( RespFileList )
2014-01-27 06:23:15 +01:00
# convert source files and binary files to build targets
2018-06-27 23:27:48 +02:00
self . ResultFileList = [ str ( T . Target ) for T in MyAgo . CodaTargetList ]
if len ( self . ResultFileList ) == 0 and len ( MyAgo . SourceFileList ) != 0 :
2014-01-27 06:23:15 +01:00
EdkLogger . error ( " build " , AUTOGEN_ERROR , " Nothing to build " ,
2018-06-27 23:27:48 +02:00
ExtraData = " [ %s ] " % str ( MyAgo ) )
2014-01-27 06:23:15 +01:00
2020-11-10 06:39:50 +01:00
self . ProcessBuildTargetList ( MyAgo . OutputDir , ToolsDef )
2017-11-22 08:42:25 +01:00
self . ParserGenerateFfsCmd ( )
2014-01-27 06:23:15 +01:00
# 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 = [ ]
2018-06-27 23:27:48 +02:00
for P in MyAgo . IncludePathList :
2015-12-01 05:22:16 +01:00
IncludePathList . append ( IncPrefix + self . PlaceMacro ( P , self . Macros ) )
2014-01-27 06:23:15 +01:00
if FileBuildRule . INC_LIST_MACRO in self . ListFileMacros :
2015-12-01 05:22:16 +01:00
self . ListFileMacros [ FileBuildRule . INC_LIST_MACRO ] . append ( IncPrefix + P )
2014-01-27 06:23:15 +01:00
FileMacro + = self . _FILE_MACRO_TEMPLATE . Replace (
{
" macro_name " : " INC " ,
" source_file " : IncludePathList
}
)
FileMacroList . append ( FileMacro )
2018-12-18 17:13:12 +01:00
# Add support when compiling .nasm source files
2019-11-20 03:58:30 +01:00
IncludePathList = [ ]
asmsource = [ item for item in MyAgo . SourceFileList if item . File . upper ( ) . endswith ( ( " .NASM " , " .ASM " , " .NASMB " , " S " ) ) ]
if asmsource :
2018-12-18 17:13:12 +01:00
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 )
2020-02-10 11:49:08 +01:00
# 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 :
2018-12-18 17:13:12 +01:00
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 } ) )
2014-01-27 06:23:15 +01:00
# Generate macros used to represent files containing list of input files
for ListFileMacro in self . ListFileMacros :
2018-06-27 23:27:48 +02:00
ListFileName = os . path . join ( MyAgo . OutputDir , " %s .lst " % ListFileMacro . lower ( ) [ : len ( ListFileMacro ) - 5 ] )
2014-01-27 06:23:15 +01:00
FileMacroList . append ( " %s = %s " % ( ListFileMacro , ListFileName ) )
SaveFileOnChange (
ListFileName ,
" \n " . join ( self . ListFileMacros [ ListFileMacro ] ) ,
False
)
2019-04-16 04:43:04 +02:00
# 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 ) )
2014-01-27 06:23:15 +01:00
BcTargetList = [ ]
2020-02-10 11:49:07 +01:00
MakefileName = self . getMakefileName ( )
2014-01-27 06:23:15 +01:00
LibraryMakeCommandList = [ ]
for D in self . LibraryBuildDirectoryList :
2020-02-10 11:49:07 +01:00
Command = self . _MAKE_TEMPLATE_ [ self . _Platform ] % { " file " : os . path . join ( D , MakefileName ) }
2014-01-27 06:23:15 +01:00
LibraryMakeCommandList . append ( Command )
2018-06-27 23:27:48 +02:00
package_rel_dir = MyAgo . SourceDir
2015-06-16 06:23:00 +02:00
current_dir = self . Macros [ " WORKSPACE " ]
found = False
while not found and os . sep in package_rel_dir :
index = package_rel_dir . index ( os . sep )
2015-10-08 11:27:14 +02:00
current_dir = mws . join ( current_dir , package_rel_dir [ : index ] )
2019-10-02 00:57:56 +02:00
if os . path . exists ( current_dir ) :
2016-06-03 03:29:06 +02:00
for fl in os . listdir ( current_dir ) :
if fl . endswith ( ' .dec ' ) :
found = True
break
2015-06-16 06:23:00 +02:00
package_rel_dir = package_rel_dir [ index + 1 : ]
2014-08-28 15:53:34 +02:00
2014-01-27 06:23:15 +01:00
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 ,
2018-06-27 23:27:48 +02:00
" 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 ) ,
2014-08-28 15:53:34 +02:00
" package_relative_directory " : package_rel_dir ,
2018-11-28 02:58:55 +01:00
" module_extra_defines " : [ " %s = %s " % ( k , v ) for k , v in MyAgo . Module . Defines . items ( ) ] ,
2014-01-27 06:23:15 +01:00
2018-06-27 23:27:48 +02:00
" architecture " : MyAgo . Arch ,
" toolchain_tag " : MyAgo . ToolChain ,
" build_target " : MyAgo . BuildTarget ,
2014-01-27 06:23:15 +01:00
" platform_build_directory " : self . PlatformInfo . BuildDir ,
2018-06-27 23:27:48 +02:00
" module_build_directory " : MyAgo . BuildDir ,
" module_output_directory " : MyAgo . OutputDir ,
" module_debug_directory " : MyAgo . DebugDir ,
2014-01-27 06:23:15 +01:00
" separator " : Separator ,
" module_tool_definitions " : ToolsDef ,
2020-02-10 11:49:07 +01:00
" shell_command_code " : list ( self . _SHELL_CMD_ [ self . _Platform ] . keys ( ) ) ,
" shell_command " : list ( self . _SHELL_CMD_ [ self . _Platform ] . values ( ) ) ,
2014-01-27 06:23:15 +01:00
" 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 ,
2020-01-17 04:11:27 +01:00
" 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 " )
] )
2014-01-27 06:23:15 +01:00
}
return MakefileTemplateDict
2017-11-22 08:42:25 +01:00
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 :
2018-05-18 02:06:52 +02:00
self . ResultFileList . append ( Dst )
2017-11-22 08:42:25 +01:00
if ' %s : ' % ( Dst ) not in self . BuildTargetList :
2020-02-07 09:45:18 +01:00
self . BuildTargetList . append ( " %s : %s " % ( Dst , Src ) )
2020-02-10 11:49:07 +01:00
self . BuildTargetList . append ( ' \t ' + self . _CP_TEMPLATE_ [ self . _Platform ] % { ' Src ' : Src , ' Dst ' : Dst } )
2017-11-22 08:42:25 +01:00
FfsCmdList = Cmd [ 0 ]
for index , Str in enumerate ( FfsCmdList ) :
if ' -o ' == Str :
OutputFile = FfsCmdList [ index + 1 ]
2019-04-03 04:17:02 +02:00
if ' -i ' == Str or " -oi " == Str :
2017-11-22 08:42:25 +01:00
if DepsFileList == [ ] :
DepsFileList = [ FfsCmdList [ index + 1 ] ]
else :
DepsFileList . append ( FfsCmdList [ index + 1 ] )
DepsFileString = ' ' . join ( DepsFileList ) . strip ( )
if DepsFileString == ' ' :
continue
OutputFile = self . ReplaceMacro ( OutputFile )
2018-05-18 02:06:52 +02:00
self . ResultFileList . append ( OutputFile )
2017-11-22 08:42:25 +01:00
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 ' ) :
2018-06-25 12:31:33 +02:00
SecDepsFileList . append ( os . path . join ( ' $(MODULE_DIR) ' , ' $(MODULE_FILE) ' ) )
2017-11-22 08:42:25 +01:00
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 :
2020-09-23 12:57:32 +02:00
if self . _AutoGenObject . Macros [ Macro ] and os . path . normcase ( self . _AutoGenObject . Macros [ Macro ] ) in os . path . normcase ( str ) :
replace_dir = str [ os . path . normcase ( str ) . index ( os . path . normcase ( self . _AutoGenObject . Macros [ Macro ] ) ) : os . path . normcase ( str ) . index (
os . path . normcase ( self . _AutoGenObject . Macros [ Macro ] ) ) + len ( self . _AutoGenObject . Macros [ Macro ] ) ]
str = str . replace ( replace_dir , ' $( ' + Macro + ' ) ' )
2017-11-22 08:42:25 +01:00
return str
2016-03-16 04:06:44 +01:00
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 :
2018-04-17 16:40:15 +02:00
for Flag in FlagDict :
2016-03-16 04:06:44 +01:00
if ' $( ' + Flag + ' ) ' in SingleCommandList [ 0 ] :
Tool = Flag
break
if Tool :
2018-08-03 17:11:06 +02:00
if ' PATH ' not in self . _AutoGenObject . BuildOption [ Tool ] :
2018-02-07 02:17:08 +01:00
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 ) )
2018-08-03 17:11:06 +02:00
SingleCommandLength + = len ( self . _AutoGenObject . BuildOption [ Tool ] [ ' PATH ' ] )
2016-03-16 04:06:44 +01:00
for item in SingleCommandList [ 1 : ] :
if FlagDict [ Tool ] [ ' Macro ' ] in item :
2018-08-03 17:11:06 +02:00
if ' FLAGS ' not in self . _AutoGenObject . BuildOption [ Tool ] :
2018-02-07 02:17:08 +01:00
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 ) )
2018-08-03 17:11:06 +02:00
Str = self . _AutoGenObject . BuildOption [ Tool ] [ ' FLAGS ' ]
2018-04-17 16:40:15 +02:00
for Option in self . _AutoGenObject . BuildOption :
2016-03-23 07:54:36 +01:00
for Attr in self . _AutoGenObject . BuildOption [ Option ] :
if Str . find ( Option + ' _ ' + Attr ) != - 1 :
Str = Str . replace ( ' $( ' + Option + ' _ ' + Attr + ' ) ' , self . _AutoGenObject . BuildOption [ Option ] [ Attr ] )
2016-03-16 04:06:44 +01:00
while ( Str . find ( ' $( ' ) != - 1 ) :
2018-04-17 16:40:15 +02:00
for macro in self . _AutoGenObject . Macros :
2016-03-16 04:06:44 +01:00
MacroName = ' $( ' + macro + ' ) '
if ( Str . find ( MacroName ) != - 1 ) :
Str = Str . replace ( MacroName , self . _AutoGenObject . Macros [ macro ] )
break
else :
2016-03-23 07:54:36 +01:00
break
2016-03-16 04:06:44 +01:00
SingleCommandLength + = len ( Str )
elif ' $(INC) ' in item :
2018-08-03 17:11:06 +02:00
SingleCommandLength + = self . _AutoGenObject . IncludePathLength + len ( IncPrefix ) * len ( self . _AutoGenObject . IncludePathList )
2016-03-16 04:06:44 +01:00
elif item . find ( ' $( ' ) != - 1 :
Str = item
2018-04-17 16:40:15 +02:00
for Option in self . _AutoGenObject . BuildOption :
2016-03-16 04:06:44 +01:00
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 ) :
2018-04-17 16:40:15 +02:00
for macro in self . _AutoGenObject . Macros :
2016-03-16 04:06:44 +01:00
MacroName = ' $( ' + macro + ' ) '
if ( Str . find ( MacroName ) != - 1 ) :
Str = Str . replace ( MacroName , self . _AutoGenObject . Macros [ macro ] )
break
else :
2016-03-23 07:54:36 +01:00
break
2016-03-16 04:06:44 +01:00
SingleCommandLength + = len ( Str )
if SingleCommandLength > GlobalData . gCommandMaxLength :
FlagDict [ Tool ] [ ' Value ' ] = True
# generate the response file content by combine the FLAGS and INC
2018-04-17 16:40:15 +02:00
for Flag in FlagDict :
2016-03-16 04:06:44 +01:00
if FlagDict [ Flag ] [ ' Value ' ] :
Key = Flag + ' _RESP '
RespMacro = FlagDict [ Flag ] [ ' Macro ' ] . replace ( ' FLAGS ' , ' RESP ' )
Value = self . _AutoGenObject . BuildOption [ Flag ] [ ' FLAGS ' ]
2018-08-03 17:11:06 +02:00
for inc in self . _AutoGenObject . IncludePathList :
2016-03-16 04:06:44 +01:00
Value + = ' ' + IncPrefix + inc
2018-04-17 16:40:15 +02:00
for Option in self . _AutoGenObject . BuildOption :
2016-03-23 07:54:36 +01:00
for Attr in self . _AutoGenObject . BuildOption [ Option ] :
if Value . find ( Option + ' _ ' + Attr ) != - 1 :
Value = Value . replace ( ' $( ' + Option + ' _ ' + Attr + ' ) ' , self . _AutoGenObject . BuildOption [ Option ] [ Attr ] )
2016-03-16 04:06:44 +01:00
while ( Value . find ( ' $( ' ) != - 1 ) :
2018-04-17 16:40:15 +02:00
for macro in self . _AutoGenObject . Macros :
2016-03-16 04:06:44 +01:00
MacroName = ' $( ' + macro + ' ) '
if ( Value . find ( MacroName ) != - 1 ) :
Value = Value . replace ( MacroName , self . _AutoGenObject . Macros [ macro ] )
break
else :
2016-03-23 07:54:36 +01:00
break
2016-11-03 08:44:17 +01:00
if self . _AutoGenObject . ToolChainFamily == ' GCC ' :
RespDict [ Key ] = Value . replace ( ' \\ ' , ' / ' )
else :
RespDict [ Key ] = Value
2016-03-16 04:06:44 +01:00
for Target in BuildTargets :
for i , SingleCommand in enumerate ( BuildTargets [ Target ] . Commands ) :
if FlagDict [ Flag ] [ ' Macro ' ] in SingleCommand :
2018-06-25 12:31:33 +02:00
BuildTargets [ Target ] . Commands [ i ] = SingleCommand . replace ( ' $(INC) ' , ' ' ) . replace ( FlagDict [ Flag ] [ ' Macro ' ] , RespMacro )
2016-03-16 04:06:44 +01:00
return RespDict
2020-11-10 06:39:50 +01:00
def ProcessBuildTargetList ( self , RespFile , ToolsDef ) :
2014-01-27 06:23:15 +01:00
#
# Search dependency file list for each source file
#
ForceIncludedFile = [ ]
for File in self . _AutoGenObject . AutoGenFileList :
if File . Ext == ' .h ' :
ForceIncludedFile . append ( File )
SourceFileList = [ ]
2017-09-15 10:14:17 +02:00
OutPutFileList = [ ]
2014-01-27 06:23:15 +01:00
for Target in self . _AutoGenObject . IntroTargetList :
SourceFileList . extend ( Target . Inputs )
2017-09-15 10:14:17 +02:00
OutPutFileList . extend ( Target . Outputs )
if OutPutFileList :
for Item in OutPutFileList :
if Item in SourceFileList :
SourceFileList . remove ( Item )
2014-01-27 06:23:15 +01:00
2019-11-20 03:58:30 +01:00
FileDependencyDict = { item : ForceIncludedFile for item in SourceFileList }
2019-09-18 08:54:34 +02:00
2019-11-20 03:58:30 +01:00
for Dependency in FileDependencyDict . values ( ) :
self . DependencyHeaderFileSet . update ( set ( Dependency ) )
2019-08-15 16:26:17 +02:00
2019-08-12 17:32:11 +02:00
# Get a set of unique package includes from MetaFile
parentMetaFileIncludes = set ( )
for aInclude in self . _AutoGenObject . PackageIncludePathList :
aIncludeName = str ( aInclude )
parentMetaFileIncludes . add ( aIncludeName . lower ( ) )
2019-05-29 18:26:48 +02:00
# Check if header files are listed in metafile
2019-08-12 17:32:11 +02:00
# Get a set of unique module header source files from MetaFile
2019-05-29 18:26:48 +02:00
headerFilesInMetaFileSet = set ( )
for aFile in self . _AutoGenObject . SourceFileList :
aFileName = str ( aFile )
if not aFileName . endswith ( ' .h ' ) :
continue
headerFilesInMetaFileSet . add ( aFileName . lower ( ) )
2019-08-12 17:32:11 +02:00
# Get a set of unique module autogen files
2019-05-29 18:26:48 +02:00
localAutoGenFileSet = set ( )
for aFile in self . _AutoGenObject . AutoGenFileList :
localAutoGenFileSet . add ( str ( aFile ) . lower ( ) )
2019-08-12 17:32:11 +02:00
# Get a set of unique module dependency header files
2019-05-29 18:26:48 +02:00
# Exclude autogen files and files not in the source directory
2019-08-12 17:32:11 +02:00
# and files that are under the package include list
2019-05-29 18:26:48 +02:00
headerFileDependencySet = set ( )
localSourceDir = str ( self . _AutoGenObject . SourceDir ) . lower ( )
for Dependency in FileDependencyDict . values ( ) :
for aFile in Dependency :
aFileName = str ( aFile ) . lower ( )
2019-08-12 17:32:11 +02:00
# Exclude non-header files
2019-05-29 18:26:48 +02:00
if not aFileName . endswith ( ' .h ' ) :
continue
2019-08-12 17:32:11 +02:00
# Exclude autogen files
2019-05-29 18:26:48 +02:00
if aFileName in localAutoGenFileSet :
continue
2019-08-12 17:32:11 +02:00
# Exclude include out of local scope
2019-05-29 18:26:48 +02:00
if localSourceDir not in aFileName :
continue
2019-08-12 17:32:11 +02:00
# 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
2019-05-29 18:26:48 +02:00
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
2019-05-29 18:26:49 +02:00
if GlobalData . gUseHashCache :
2019-08-15 16:26:19 +02:00
GlobalData . gModuleBuildTracking [ self . _AutoGenObject ] = ' FAIL_METAFILE '
2019-05-29 18:26:48 +02:00
EdkLogger . warn ( " build " , " Module MetaFile [Sources] is missing local header! " ,
ExtraData = " Local Header: " + aFile + " not found in " + self . _AutoGenObject . MetaFile . Path
)
2018-07-19 19:57:39 +02:00
for File , Dependency in FileDependencyDict . items ( ) :
if not Dependency :
2014-01-27 06:23:15 +01:00
continue
BaseTools: Skip module AutoGen by comparing timestamp.
[Introduction]
The BaseTool Build.py AutoGen parse INF meta-file and generate
AutoGen.c/AutoGen.h/makefile. When we only change .c .h code, the
AutoGen might be not necessary, but Build.py spend a lot of time on it.
There's a -u flag to skip all module's AutoGen. In my environment, it save
35%~50% of time in rebuild a ROM.
However, if user change one .INF meta-file, then -u flag is not available.
[Idea]
AutoGen can compare meta-file's timestamp and decide if the module's
AutoGen can be skipped. With this, when a module's INF is changed, we
only run this module's AutoGen, we don't need to run other module's.
[Implementation]
In the end of a module's AutoGen, we create a AutoGenTimeStamp.
The file save a file list that related to this module's AutoGen.
In other word, the file list in AutoGenTimeStamp is INPUT files of
module AutoGen, AutoGenTimeStamp file is OUTPUT.
During rebuild, we compare time stamp between INPUT and OUTPUT, and
decide if we can skip it.
Below is the Input/Output of a module's AutoGen.
[Input]
1. All the DSC/DEC/FDF used by the platform.
2. Macro and PCD defined by Build Options such as "build -D AAA=TRUE
--pcd BbbPcd=0".
3. INF file of a module.
4. Source files of a module, list in [Sources] section of INF.
5. All the library link by the module.
6. All the .h files included by the module's sources.
[Output]
AutoGen.c/AutoGen.h/makefile/AutoGenTimeStamp
[Testing]
This patch save my build time. When I make a change without touching
DSC/DEC/FDF, it is absolutely much faster than original rebuild,
35%~50% time saving in my environment
(compare to original tool rebuild time).
If I change any DSC/DEC/FDF, there's no performance improve, because it
can't skip any module's AutoGen.
Please note that if your environment will generate DSC/FDF during prebuild,
it will not skip any AutoGen because of DSC timestamp is changed. This will
require prebuild script not to update metafile when content is not changed.
2017-02-24 08:26:19 +01:00
2018-07-19 19:57:39 +02:00
self . _AutoGenObject . AutoGenDepSet | = set ( Dependency )
BaseTools: Skip module AutoGen by comparing timestamp.
[Introduction]
The BaseTool Build.py AutoGen parse INF meta-file and generate
AutoGen.c/AutoGen.h/makefile. When we only change .c .h code, the
AutoGen might be not necessary, but Build.py spend a lot of time on it.
There's a -u flag to skip all module's AutoGen. In my environment, it save
35%~50% of time in rebuild a ROM.
However, if user change one .INF meta-file, then -u flag is not available.
[Idea]
AutoGen can compare meta-file's timestamp and decide if the module's
AutoGen can be skipped. With this, when a module's INF is changed, we
only run this module's AutoGen, we don't need to run other module's.
[Implementation]
In the end of a module's AutoGen, we create a AutoGenTimeStamp.
The file save a file list that related to this module's AutoGen.
In other word, the file list in AutoGenTimeStamp is INPUT files of
module AutoGen, AutoGenTimeStamp file is OUTPUT.
During rebuild, we compare time stamp between INPUT and OUTPUT, and
decide if we can skip it.
Below is the Input/Output of a module's AutoGen.
[Input]
1. All the DSC/DEC/FDF used by the platform.
2. Macro and PCD defined by Build Options such as "build -D AAA=TRUE
--pcd BbbPcd=0".
3. INF file of a module.
4. Source files of a module, list in [Sources] section of INF.
5. All the library link by the module.
6. All the .h files included by the module's sources.
[Output]
AutoGen.c/AutoGen.h/makefile/AutoGenTimeStamp
[Testing]
This patch save my build time. When I make a change without touching
DSC/DEC/FDF, it is absolutely much faster than original rebuild,
35%~50% time saving in my environment
(compare to original tool rebuild time).
If I change any DSC/DEC/FDF, there's no performance improve, because it
can't skip any module's AutoGen.
Please note that if your environment will generate DSC/FDF during prebuild,
it will not skip any AutoGen because of DSC timestamp is changed. This will
require prebuild script not to update metafile when content is not changed.
2017-02-24 08:26:19 +01:00
2019-04-16 04:43:04 +02:00
CmdSumDict = { }
CmdTargetDict = { }
CmdCppDict = { }
DependencyDict = FileDependencyDict . copy ( )
2014-01-27 06:23:15 +01:00
# Convert target description object to target string in makefile
2019-04-18 13:20:46 +02:00
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 )
2014-01-27 06:23:15 +01:00
for Type in self . _AutoGenObject . Targets :
2020-11-10 06:39:50 +01:00
resp_file_number = 0
2018-10-15 02:27:53 +02:00
for T in self . _AutoGenObject . Targets [ Type ] :
2014-01-27 06:23:15 +01:00
# 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 = [ ]
2019-04-16 04:43:04 +02:00
CCodeDeps = [ ]
2014-01-27 06:23:15 +01:00
# Add force-dependencies
for Dep in T . Dependencies :
Deps . append ( self . PlaceMacro ( str ( Dep ) , self . Macros ) )
2019-04-16 04:43:04 +02:00
if Dep != ' $(MAKE_FILE) ' :
CCodeDeps . append ( self . PlaceMacro ( str ( Dep ) , self . Macros ) )
2014-01-27 06:23:15 +01:00
# Add inclusion-dependencies
2018-07-19 19:57:39 +02:00
if len ( T . Inputs ) == 1 and T . Inputs [ 0 ] in FileDependencyDict :
for F in FileDependencyDict [ T . Inputs [ 0 ] ] :
2014-01-27 06:23:15 +01:00
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 :
2019-02-06 08:44:39 +01:00
# gnu tools need forward slash path separator, even on Windows
2014-11-18 03:38:20 +01:00
self . ListFileMacros [ T . ListFileMacro ] . append ( str ( F ) . replace ( ' \\ ' , ' / ' ) )
2014-01-27 06:23:15 +01:00
self . FileListMacros [ T . FileListMacro ] . append ( NewFile )
elif T . GenFileListMacro :
self . FileListMacros [ T . FileListMacro ] . append ( NewFile )
else :
Deps . append ( NewFile )
2019-07-15 16:42:45 +02:00
for key in self . FileListMacros :
self . FileListMacros [ key ] . sort ( )
2014-01-27 06:23:15 +01:00
# Use file list macro as dependency
if T . GenFileListMacro :
Deps . append ( " $( %s ) " % T . FileListMacro )
2017-12-04 03:25:43 +01:00
if Type in [ TAB_OBJECT_FILE , TAB_STATIC_LIBRARY ] :
Deps . append ( " $( %s ) " % T . ListFileMacro )
2014-01-27 06:23:15 +01:00
2019-04-16 04:43:04 +02:00
if self . _AutoGenObject . BuildRuleFamily == TAB_COMPILER_MSFT and Type == TAB_C_CODE_FILE :
2020-11-10 06:39:50 +01:00
T , CmdTarget , CmdTargetDict , CmdCppDict = self . ParserCCodeFile ( T , Type , CmdSumDict , CmdTargetDict ,
CmdCppDict , DependencyDict , RespFile ,
ToolsDef , resp_file_number )
resp_file_number + = 1
2019-04-16 04:43:04 +02:00
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 ) )
2020-07-01 16:06:01 +02:00
# 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 ) )
2020-11-10 06:39:50 +01:00
def ParserCCodeFile ( self , T , Type , CmdSumDict , CmdTargetDict , CmdCppDict , DependencyDict , RespFile , ToolsDef ,
resp_file_number ) :
SaveFilePath = os . path . join ( RespFile , " cc_resp_ %s .txt " % resp_file_number )
2019-04-16 04:43:04 +02:00
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 :
2019-11-20 03:58:30 +01:00
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 )
2019-04-16 04:43:04 +02:00
if T . Commands :
CommandList = T . Commands [ : ]
for Item in CommandList [ : ] :
SingleCommandList = Item . split ( )
2019-04-23 05:21:22 +02:00
if len ( SingleCommandList ) > 0 and self . CheckCCCmd ( SingleCommandList ) :
2019-04-16 04:43:04 +02:00
for Temp in SingleCommandList :
if Temp . startswith ( ' /Fo ' ) :
CmdSign = ' %s %s ' % ( Temp . rsplit ( TAB_SLASH , 1 ) [ 0 ] , TAB_SLASH )
break
2020-11-10 06:39:50 +01:00
else :
continue
2019-04-16 04:43:04 +02:00
if CmdSign not in list ( CmdTargetDict . keys ( ) ) :
2020-11-10 06:39:50 +01:00
cmd = Item . replace ( Temp , CmdSign )
if SingleCommandList [ - 1 ] in cmd :
CmdTargetDict [ CmdSign ] = [ cmd . replace ( SingleCommandList [ - 1 ] , " " ) . rstrip ( ) , SingleCommandList [ - 1 ] ]
2019-04-16 04:43:04 +02:00
else :
2020-11-10 06:39:50 +01:00
# CmdTargetDict[CmdSign] = "%s %s" % (CmdTargetDict[CmdSign], SingleCommandList[-1])
CmdTargetDict [ CmdSign ] . append ( SingleCommandList [ - 1 ] )
2019-04-16 04:43:04 +02:00
Index = CommandList . index ( Item )
CommandList . pop ( Index )
2022-06-25 07:11:40 +02:00
BaseName = SingleCommandList [ - 1 ] . rsplit ( ' . ' , 1 ) [ 0 ]
if BaseName . endswith ( " %s %s " % ( TAB_SLASH , CmdSumDict [ CmdSign [ 3 : ] . rsplit ( TAB_SLASH , 1 ) [ 0 ] ] ) ) :
2019-04-16 04:43:04 +02:00
Cpplist = CmdCppDict [ T . Target . SubDir ]
2019-11-20 03:58:30 +01:00
Cpplist . insert ( 0 , ' $(OBJLIST_ %d ): ' % list ( self . ObjTargetDict . keys ( ) ) . index ( T . Target . SubDir ) )
2020-11-10 06:39:50 +01:00
source_files = CmdTargetDict [ CmdSign ] [ 1 : ]
source_files . insert ( 0 , " " )
if len ( source_files ) > 2 :
SaveFileOnChange ( SaveFilePath , " " . join ( source_files ) , False )
T . Commands [ Index ] = ' %s \n \t %s $(cc_resp_ %s ) ' % (
' \\ \n \t ' . join ( Cpplist ) , CmdTargetDict [ CmdSign ] [ 0 ] , resp_file_number )
ToolsDef . append ( " cc_resp_ %s = @ %s " % ( resp_file_number , SaveFilePath ) )
elif len ( source_files ) < = 2 and len ( " " . join ( CmdTargetDict [ CmdSign ] [ : 2 ] ) ) > GlobalData . gCommandMaxLength :
SaveFileOnChange ( SaveFilePath , " " . join ( source_files ) , False )
T . Commands [ Index ] = ' %s \n \t %s $(cc_resp_ %s ) ' % (
' \\ \n \t ' . join ( Cpplist ) , CmdTargetDict [ CmdSign ] [ 0 ] , resp_file_number )
ToolsDef . append ( " cc_resp_ %s = @ %s " % ( resp_file_number , SaveFilePath ) )
else :
T . Commands [ Index ] = ' %s \n \t %s ' % ( ' \\ \n \t ' . join ( Cpplist ) , " " . join ( CmdTargetDict [ CmdSign ] ) )
2019-04-16 04:43:04 +02:00
else :
T . Commands . pop ( Index )
return T , CmdSumDict , CmdTargetDict , CmdCppDict
2014-01-27 06:23:15 +01:00
2019-04-23 05:21:22 +02:00
def CheckCCCmd ( self , CommandList ) :
for cmd in CommandList :
if ' $(CC) ' in cmd :
return True
return False
2014-01-27 06:23:15 +01:00
## For creating makefile targets for dependent libraries
def ProcessDependentLibrary ( self ) :
for LibraryAutoGen in self . _AutoGenObject . LibraryAutoGenList :
2019-08-15 16:26:17 +02:00
if not LibraryAutoGen . IsBinaryModule :
2016-06-13 12:00:52 +02:00
self . LibraryBuildDirectoryList . append ( self . PlaceMacro ( LibraryAutoGen . BuildDir , self . Macros ) )
2014-01-27 06:23:15 +01:00
## 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 :
2019-08-15 16:26:17 +02:00
Dependency [ F ] = GetDependencyList ( self . _AutoGenObject , self . FileCache , F , ForceInculeList , SearchPathList )
2014-01-27 06:23:15 +01:00
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 }
2016-04-14 18:28:19 +02:00
PLATFORM_DIR = $ { platform_dir }
2014-01-27 06:23:15 +01:00
PLATFORM_OUTPUT_DIR = $ { platform_output_directory }
#
# Module Macro Definition
#
MODULE_NAME = $ { module_name }
MODULE_GUID = $ { module_guid }
2015-06-10 09:50:59 +02:00
MODULE_NAME_GUID = $ { module_name_guid }
2014-01-27 06:23:15 +01:00
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 }
2016-02-21 01:46:58 +01:00
MODULE_DIR = $ { module_dir }
2014-01-27 06:23:15 +01:00
#
# 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) " ]
2019-09-18 08:54:34 +02:00
self . DependencyHeaderFileSet = set ( )
2014-01-27 06:23:15 +01:00
# Compose a dict object containing information used to do replacement in template
2018-09-11 00:18:03 +02:00
@property
def _TemplateDict ( self ) :
2020-02-10 11:49:07 +01:00
Separator = self . _SEP_ [ self . _Platform ]
2018-06-27 23:27:48 +02:00
MyAgo = self . _AutoGenObject
if self . _FileType not in MyAgo . CustomMakefile :
2014-01-27 06:23:15 +01:00
EdkLogger . error ( ' build ' , OPTION_NOT_SUPPORTED , " No custom makefile for %s " % self . _FileType ,
2018-06-27 23:27:48 +02:00
ExtraData = " [ %s ] " % str ( MyAgo ) )
2016-02-21 01:46:58 +01:00
MakefilePath = mws . join (
2018-06-27 23:27:48 +02:00
MyAgo . WorkspaceDir ,
MyAgo . CustomMakefile [ self . _FileType ]
2014-01-27 06:23:15 +01:00
)
try :
CustomMakefile = open ( MakefilePath , ' r ' ) . read ( )
except :
2018-06-27 23:27:48 +02:00
EdkLogger . error ( ' build ' , FILE_OPEN_FAILURE , File = str ( MyAgo ) ,
ExtraData = MyAgo . CustomMakefile [ self . _FileType ] )
2014-01-27 06:23:15 +01:00
# tools definitions
ToolsDef = [ ]
2018-06-27 23:27:48 +02:00
for Tool in MyAgo . BuildOption :
2014-01-27 06:23:15 +01:00
# Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
if Tool == " MAKE " :
continue
2018-06-27 23:27:48 +02:00
for Attr in MyAgo . BuildOption [ Tool ] :
2014-01-27 06:23:15 +01:00
if Attr == " FAMILY " :
continue
elif Attr == " PATH " :
2018-06-27 23:27:48 +02:00
ToolsDef . append ( " %s = %s " % ( Tool , MyAgo . BuildOption [ Tool ] [ Attr ] ) )
2014-01-27 06:23:15 +01:00
else :
2018-06-27 23:27:48 +02:00
ToolsDef . append ( " %s _ %s = %s " % ( Tool , Attr , MyAgo . BuildOption [ Tool ] [ Attr ] ) )
2014-01-27 06:23:15 +01:00
ToolsDef . append ( " " )
2020-02-10 11:49:07 +01:00
MakefileName = self . getMakefileName ( )
2014-01-27 06:23:15 +01:00
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 ,
2018-06-27 23:27:48 +02:00
" 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 ,
2014-01-27 06:23:15 +01:00
" platform_build_directory " : self . PlatformInfo . BuildDir ,
2018-06-27 23:27:48 +02:00
" module_build_directory " : MyAgo . BuildDir ,
" module_output_directory " : MyAgo . OutputDir ,
" module_debug_directory " : MyAgo . DebugDir ,
2014-01-27 06:23:15 +01:00
" separator " : Separator ,
" module_tool_definitions " : ToolsDef ,
2020-02-10 11:49:07 +01:00
" shell_command_code " : list ( self . _SHELL_CMD_ [ self . _Platform ] . keys ( ) ) ,
" shell_command " : list ( self . _SHELL_CMD_ [ self . _Platform ] . values ( ) ) ,
2014-01-27 06:23:15 +01:00
" 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 }
2016-04-14 18:28:19 +02:00
PLATFORM_DIR = $ { platform_dir }
2014-01-27 06:23:15 +01:00
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 = [ ]
2014-08-18 06:59:01 +02:00
self . LibraryMakeCommandList = [ ]
2019-09-18 08:54:34 +02:00
self . DependencyHeaderFileSet = set ( )
2014-01-27 06:23:15 +01:00
# Compose a dict object containing information used to do replacement in template
2018-09-11 00:18:03 +02:00
@property
def _TemplateDict ( self ) :
2020-02-10 11:49:07 +01:00
Separator = self . _SEP_ [ self . _Platform ]
2014-01-27 06:23:15 +01:00
2018-06-27 23:27:48 +02:00
MyAgo = self . _AutoGenObject
if " MAKE " not in MyAgo . ToolDefinition or " PATH " not in MyAgo . ToolDefinition [ " MAKE " ] :
2014-01-27 06:23:15 +01:00
EdkLogger . error ( " build " , OPTION_MISSING , " No MAKE command defined. Please check your tools_def.txt! " ,
2018-06-27 23:27:48 +02:00
ExtraData = " [ %s ] " % str ( MyAgo ) )
2014-01-27 06:23:15 +01:00
self . IntermediateDirectoryList = [ " $(BUILD_DIR) " ]
self . ModuleBuildDirectoryList = self . GetModuleBuildDirectoryList ( )
self . LibraryBuildDirectoryList = self . GetLibraryBuildDirectoryList ( )
2020-02-10 11:49:07 +01:00
MakefileName = self . getMakefileName ( )
2014-01-27 06:23:15 +01:00
LibraryMakefileList = [ ]
LibraryMakeCommandList = [ ]
for D in self . LibraryBuildDirectoryList :
2018-06-27 23:27:48 +02:00
D = self . PlaceMacro ( D , { " BUILD_DIR " : MyAgo . BuildDir } )
2014-01-27 06:23:15 +01:00
Makefile = os . path . join ( D , MakefileName )
2020-02-10 11:49:07 +01:00
Command = self . _MAKE_TEMPLATE_ [ self . _Platform ] % { " file " : Makefile }
2014-01-27 06:23:15 +01:00
LibraryMakefileList . append ( Makefile )
LibraryMakeCommandList . append ( Command )
2014-08-18 06:59:01 +02:00
self . LibraryMakeCommandList = LibraryMakeCommandList
2014-01-27 06:23:15 +01:00
ModuleMakefileList = [ ]
ModuleMakeCommandList = [ ]
for D in self . ModuleBuildDirectoryList :
2018-06-27 23:27:48 +02:00
D = self . PlaceMacro ( D , { " BUILD_DIR " : MyAgo . BuildDir } )
2014-01-27 06:23:15 +01:00
Makefile = os . path . join ( D , MakefileName )
2020-02-10 11:49:07 +01:00
Command = self . _MAKE_TEMPLATE_ [ self . _Platform ] % { " file " : Makefile }
2014-01-27 06:23:15 +01:00
ModuleMakefileList . append ( Makefile )
ModuleMakeCommandList . append ( Command )
MakefileTemplateDict = {
" makefile_header " : self . _FILE_HEADER_ [ self . _FileType ] ,
" makefile_path " : os . path . join ( " $(BUILD_DIR) " , MakefileName ) ,
2018-06-27 23:27:48 +02:00
" make_path " : MyAgo . ToolDefinition [ " MAKE " ] [ " PATH " ] ,
2014-01-27 06:23:15 +01:00
" makefile_name " : MakefileName ,
2018-06-27 23:27:48 +02:00
" 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 ,
2020-02-10 11:49:07 +01:00
" shell_command_code " : list ( self . _SHELL_CMD_ [ self . _Platform ] . keys ( ) ) ,
" shell_command " : list ( self . _SHELL_CMD_ [ self . _Platform ] . values ( ) ) ,
2018-06-27 23:27:48 +02:00
" build_architecture_list " : MyAgo . Arch ,
" architecture " : MyAgo . Arch ,
2014-01-27 06:23:15 +01:00
" 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 :
2014-08-28 15:53:34 +02:00
if not ModuleAutoGen . IsBinaryModule :
DirList . append ( os . path . join ( self . _AutoGenObject . BuildDir , ModuleAutoGen . BuildDir ) )
2014-01-27 06:23:15 +01:00
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 :
2019-08-15 16:26:17 +02:00
if not LibraryAutoGen . IsBinaryModule :
2014-08-28 15:53:34 +02:00
DirList . append ( os . path . join ( self . _AutoGenObject . BuildDir , LibraryAutoGen . BuildDir ) )
2014-01-27 06:23:15 +01:00
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
2014-08-28 15:53:34 +02:00
_TEMPLATE_ = TemplateString ( ''' $ {BEGIN} \t GenFds -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} ''' )
2014-01-27 06:23:15 +01:00
## Constructor of TopLevelMakefile
#
# @param Workspace Object of WorkspaceAutoGen class
#
def __init__ ( self , Workspace ) :
BuildFile . __init__ ( self , Workspace )
self . IntermediateDirectoryList = [ ]
2019-09-18 08:54:34 +02:00
self . DependencyHeaderFileSet = set ( )
2014-01-27 06:23:15 +01:00
# Compose a dict object containing information used to do replacement in template
2018-09-11 00:18:03 +02:00
@property
def _TemplateDict ( self ) :
2020-02-10 11:49:07 +01:00
Separator = self . _SEP_ [ self . _Platform ]
2014-01-27 06:23:15 +01:00
# any platform autogen object is ok because we just need common information
2018-06-27 23:27:48 +02:00
MyAgo = self . _AutoGenObject
2014-01-27 06:23:15 +01:00
2018-06-27 23:27:48 +02:00
if " MAKE " not in MyAgo . ToolDefinition or " PATH " not in MyAgo . ToolDefinition [ " MAKE " ] :
2014-01-27 06:23:15 +01:00
EdkLogger . error ( " build " , OPTION_MISSING , " No MAKE command defined. Please check your tools_def.txt! " ,
2018-06-27 23:27:48 +02:00
ExtraData = " [ %s ] " % str ( MyAgo ) )
2014-01-27 06:23:15 +01:00
2018-06-27 23:27:48 +02:00
for Arch in MyAgo . ArchList :
2014-01-27 06:23:15 +01:00
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 = [ ]
2018-06-27 23:27:48 +02:00
if MyAgo . FdfFile is not None and MyAgo . FdfFile != " " :
FdfFileList = [ MyAgo . FdfFile ]
2014-01-27 06:23:15 +01:00
# 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 "
2019-09-06 15:22:58 +02:00
if not GlobalData . gEnableGenfdsMultiThread :
ExtraOption + = " --no-genfds-multi-thread "
2014-08-28 15:53:34 +02:00
if GlobalData . gIgnoreSource :
ExtraOption + = " --ignore-sources "
2018-03-08 06:56:21 +01:00
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 ]
2016-04-20 03:32:52 +02:00
2020-02-10 11:49:07 +01:00
MakefileName = self . getMakefileName ( )
2014-01-27 06:23:15 +01:00
SubBuildCommandList = [ ]
2018-06-27 23:27:48 +02:00
for A in MyAgo . ArchList :
2020-02-10 11:49:07 +01:00
Command = self . _MAKE_TEMPLATE_ [ self . _Platform ] % { " file " : os . path . join ( " $(BUILD_DIR) " , A , MakefileName ) }
2014-01-27 06:23:15 +01:00
SubBuildCommandList . append ( Command )
MakefileTemplateDict = {
" makefile_header " : self . _FILE_HEADER_ [ self . _FileType ] ,
" makefile_path " : os . path . join ( " $(BUILD_DIR) " , MakefileName ) ,
2018-06-27 23:27:48 +02:00
" make_path " : MyAgo . ToolDefinition [ " MAKE " ] [ " PATH " ] ,
" platform_name " : MyAgo . Name ,
" platform_guid " : MyAgo . Guid ,
" platform_version " : MyAgo . Version ,
" platform_build_directory " : MyAgo . BuildDir ,
2014-08-28 15:53:34 +02:00
" conf_directory " : GlobalData . gConfDirectory ,
2014-01-27 06:23:15 +01:00
2018-06-27 23:27:48 +02:00
" toolchain_tag " : MyAgo . ToolChain ,
" build_target " : MyAgo . BuildTarget ,
2020-02-10 11:49:07 +01:00
" shell_command_code " : list ( self . _SHELL_CMD_ [ self . _Platform ] . keys ( ) ) ,
" shell_command " : list ( self . _SHELL_CMD_ [ self . _Platform ] . values ( ) ) ,
2018-06-27 23:27:48 +02:00
' arch ' : list ( MyAgo . ArchList ) ,
" build_architecture_list " : ' , ' . join ( MyAgo . ArchList ) ,
2014-01-27 06:23:15 +01:00
" separator " : Separator ,
" create_directory_command " : self . GetCreateDirectoryCommand ( self . IntermediateDirectoryList ) ,
" cleanall_command " : self . GetRemoveDirectoryCommand ( self . IntermediateDirectoryList ) ,
" sub_build_command " : SubBuildCommandList ,
" fdf_file " : FdfFileList ,
2018-06-27 23:27:48 +02:00
" active_platform " : str ( MyAgo ) ,
" fd " : MyAgo . FdTargetList ,
" fv " : MyAgo . FvTargetList ,
" cap " : MyAgo . CapTargetList ,
2014-01-27 06:23:15 +01:00
" 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 :
2014-08-28 15:53:34 +02:00
if not ModuleAutoGen . IsBinaryModule :
DirList . append ( os . path . join ( self . _AutoGenObject . BuildDir , ModuleAutoGen . BuildDir ) )
2014-01-27 06:23:15 +01:00
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 :
2019-08-15 16:26:17 +02:00
if not LibraryAutoGen . IsBinaryModule :
2014-08-28 15:53:34 +02:00
DirList . append ( os . path . join ( self . _AutoGenObject . BuildDir , LibraryAutoGen . BuildDir ) )
2014-01-27 06:23:15 +01:00
return DirList
2019-08-15 16:26:17 +02:00
## 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 :
2019-09-20 08:00:12 +02:00
Fd = open ( F . Path , ' rb ' )
FileContent = Fd . read ( )
Fd . close ( )
2019-08-15 16:26:17 +02:00
except BaseException as X :
EdkLogger . error ( " build " , FILE_OPEN_FAILURE , ExtraData = F . Path + " \n \t " + str ( X ) )
2019-09-20 08:00:12 +02:00
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
2019-08-15 16:26:17 +02:00
continue
2019-09-20 08:00:12 +02:00
IncludedFileList = gIncludePattern . findall ( FileContent )
2019-08-15 16:26:17 +02:00
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
2014-01-27 06:23:15 +01:00
# This acts like the main() function for the script, unless it is 'import'ed into another script.
if __name__ == ' __main__ ' :
2019-09-12 10:18:27 +02:00
pass