2019-09-03 11:58:42 +02:00
## @file
# Create makefile for MS nmake and GNU make
#
2022-02-05 19:53:39 +01:00
# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2020 - 2021, Arm Limited. All rights reserved.<BR>
2019-09-03 11:58:42 +02:00
# 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 ,
}
2022-02-05 19:53:39 +01:00
NMAKE_FILETYPE = " nmake "
GMAKE_FILETYPE = " gmake "
WIN32_PLATFORM = " win32 "
POSIX_PLATFORM = " posix "
2019-09-03 11:58:42 +02: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_ = {
2022-02-05 19:53:39 +01:00
NMAKE_FILETYPE : " Makefile " ,
GMAKE_FILETYPE : " GNUmakefile "
2019-09-03 11:58:42 +02:00
}
2022-02-05 19:53:39 +01:00
# Get Makefile name.
def getMakefileName ( self ) :
if not self . _FileType :
return self . _DEFAULT_FILE_NAME_
else :
return self . _FILE_NAME_ [ self . _FileType ]
2019-09-03 11:58:42 +02: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_ = {
2022-02-05 19:53:39 +01:00
NMAKE_FILETYPE : _MAKEFILE_HEADER % _FILE_NAME_ [ NMAKE_FILETYPE ] ,
GMAKE_FILETYPE : _MAKEFILE_HEADER % _FILE_NAME_ [ GMAKE_FILETYPE ]
2019-09-03 11:58:42 +02: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_ = {
2022-02-05 19:53:39 +01:00
WIN32_PLATFORM : {
2019-09-03 11:58:42 +02:00
" CP " : " copy /y " ,
" MV " : " move /y " ,
" RM " : " del /f /q " ,
" MD " : " mkdir " ,
" RD " : " rmdir /s /q " ,
} ,
2022-02-05 19:53:39 +01:00
POSIX_PLATFORM : {
2019-09-03 11:58:42 +02:00
" CP " : " cp -f " ,
" MV " : " mv -f " ,
" RM " : " rm -f " ,
" MD " : " mkdir -p " ,
" RD " : " rm -r -f " ,
}
}
## directory separator
_SEP_ = {
2022-02-05 19:53:39 +01:00
WIN32_PLATFORM : " \\ " ,
POSIX_PLATFORM : " / "
2019-09-03 11:58:42 +02:00
}
## directory creation template
_MD_TEMPLATE_ = {
2022-02-05 19:53:39 +01:00
WIN32_PLATFORM : ' if not exist %(dir)s $(MD) %(dir)s ' ,
POSIX_PLATFORM : " $(MD) %(dir)s "
2019-09-03 11:58:42 +02:00
}
## directory removal template
_RD_TEMPLATE_ = {
2022-02-05 19:53:39 +01:00
WIN32_PLATFORM : ' if exist %(dir)s $(RD) %(dir)s ' ,
POSIX_PLATFORM : " $(RD) %(dir)s "
2019-09-03 11:58:42 +02:00
}
## cp if exist
_CP_TEMPLATE_ = {
2022-02-05 19:53:39 +01:00
WIN32_PLATFORM : ' if exist %(Src)s $(CP) %(Src)s %(Dst)s ' ,
2022-02-06 08:42:19 +01:00
POSIX_PLATFORM : " @test -f %(Src)s && $(CP) %(Src)s %(Dst)s "
2019-09-03 11:58:42 +02:00
}
_CD_TEMPLATE_ = {
2022-02-05 19:53:39 +01:00
WIN32_PLATFORM : ' if exist %(dir)s cd %(dir)s ' ,
2022-02-06 08:42:19 +01:00
POSIX_PLATFORM : " @test -e %(dir)s && cd %(dir)s "
2019-09-03 11:58:42 +02:00
}
_MAKE_TEMPLATE_ = {
2022-02-05 19:53:39 +01:00
WIN32_PLATFORM : ' if exist %(file)s " $(MAKE) " $(MAKE_FLAGS) -f %(file)s ' ,
2022-02-06 08:42:19 +01:00
POSIX_PLATFORM : ' @test -e %(file)s && @ " $(MAKE) " $(MAKE_FLAGS) -f %(file)s '
2019-09-03 11:58:42 +02:00
}
_INCLUDE_CMD_ = {
2022-02-05 19:53:39 +01:00
NMAKE_FILETYPE : ' !INCLUDE ' ,
GMAKE_FILETYPE : " include "
2019-09-03 11:58:42 +02:00
}
_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
2022-02-05 19:53:39 +01:00
MakePath = AutoGenObject . BuildOption . get ( ' MAKE ' , { } ) . get ( ' PATH ' )
if not MakePath :
MakePath = AutoGenObject . ToolDefinition . get ( ' MAKE ' , { } ) . get ( ' PATH ' )
if " nmake " in MakePath :
self . _FileType = NMAKE_FILETYPE
else :
self . _FileType = GMAKE_FILETYPE
if sys . platform == " win32 " :
self . _Platform = WIN32_PLATFORM
else :
self . _Platform = POSIX_PLATFORM
## Create build file.
2019-09-03 11:58:42 +02:00
#
2022-02-05 19:53:39 +01:00
# Only nmake and gmake are supported.
2019-09-03 11:58:42 +02:00
#
2022-02-05 19:53:39 +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.
2019-09-03 11:58:42 +02:00
#
2022-02-05 19:53:39 +01:00
def Generate ( self ) :
2019-09-03 11:58:42 +02:00
FileContent = self . _TEMPLATE_ . Replace ( self . _TemplateDict )
2022-02-05 19:53:39 +01:00
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 ( " " )
2019-09-03 11:58:42 +02: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 ) :
2022-02-05 19:53:39 +01:00
return [ self . _MD_TEMPLATE_ [ self . _Platform ] % { ' dir ' : Dir } for Dir in DirList ]
2019-09-03 11:58:42 +02: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 ) :
2022-02-05 19:53:39 +01:00
return [ self . _RD_TEMPLATE_ [ self . _Platform ] % { ' dir ' : Dir } for Dir in DirList ]
2019-09-03 11:58:42 +02:00
2019-09-20 06:56:20 +02:00
def PlaceMacro ( self , Path , MacroDefinitions = None ) :
2019-09-03 11:58:42 +02:00
if Path . startswith ( " $( " ) :
return Path
else :
2019-09-20 06:56:20 +02:00
if MacroDefinitions is None :
MacroDefinitions = { }
2019-09-03 11:58:42 +02:00
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
2020-11-02 12:14:54 +01:00
TemplStr = ''' \
2019-09-03 11:58:42 +02:00
$ { 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 )
2022-02-05 19:53:39 +01:00
$ { INCLUDETAG }
2019-09-03 11:58:42 +02:00
#
# 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
2020-11-02 12:14:54 +01:00
\t $ { END } @cd $ ( MODULE_BUILD_DIR ) \n \n '''
if sys . platform == " win32 " :
_TEMPLATE_ = TemplateString ( '''
AT = @
! IF defined ( V ) & & " $(V) " != " 0 "
AT =
! ENDIF
''' + TemplStr)
else :
_TEMPLATE_ = TemplateString ( '''
#Verbose
AT_ = @
AT_0 = @
AT_1 =
AT = $ ( AT_ $ ( V ) )
''' + TemplStr)
2019-09-03 11:58:42 +02:00
_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 = [ ]
2019-09-25 15:48:59 +02:00
self . DependencyHeaderFileSet = set ( )
2019-09-03 11:58:42 +02:00
# Compose a dict object containing information used to do replacement in template
@property
def _TemplateDict ( self ) :
MyAgo = self . _AutoGenObject
2022-02-05 19:53:39 +01:00
Separator = self . _SEP_ [ self . _Platform ]
2019-09-03 11:58:42 +02:00
# 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 ]
2022-02-05 19:53:39 +01:00
for Tool in sorted ( list ( MyAgo . BuildOption ) ) :
Appended = False
for Attr in sorted ( list ( MyAgo . BuildOption [ Tool ] ) ) :
2019-09-03 11:58:42 +02:00
Value = MyAgo . BuildOption [ Tool ] [ Attr ]
if Attr == " FAMILY " :
continue
elif Attr == " PATH " :
ToolsDef . append ( " %s = %s " % ( Tool , Value ) )
2022-02-05 19:53:39 +01:00
Appended = True
2019-09-03 11:58:42 +02: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 " :
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 ) )
2022-02-05 19:53:39 +01:00
Appended = True
if Appended :
ToolsDef . append ( " " )
2019-09-03 11:58:42 +02:00
# 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 :
2022-02-05 19:53:39 +01:00
if ' $ ' in Str or ' -MMD ' in Str or ' -MF ' in Str :
2019-09-03 11:58:42 +02: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 ) )
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 ) )
2022-02-05 19:53:39 +01:00
self . ProcessBuildTargetList ( MyAgo . OutputDir , ToolsDef )
2019-09-03 11:58:42 +02:00
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
2022-02-05 19:53:39 +01:00
IncludePathList = [ ]
asmsource = [ item for item in MyAgo . SourceFileList if item . File . upper ( ) . endswith ( ( " .NASM " , " .ASM " , " .NASMB " , " S " ) ) ]
if asmsource :
2019-09-03 11:58:42 +02: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 )
2022-02-05 19:53:39 +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 :
2019-09-03 11:58:42 +02: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 } ) )
# 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 = [ ]
2022-02-05 19:53:39 +01:00
MakefileName = self . getMakefileName ( )
2019-09-03 11:58:42 +02:00
LibraryMakeCommandList = [ ]
for D in self . LibraryBuildDirectoryList :
2022-02-05 19:53:39 +01:00
Command = self . _MAKE_TEMPLATE_ [ self . _Platform ] % { " file " : os . path . join ( D , MakefileName ) }
2019-09-03 11:58:42 +02:00
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 ] )
2022-02-05 19:53:39 +01:00
if os . path . exists ( current_dir ) :
2019-09-03 11:58:42 +02:00
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 ,
2022-02-05 19:53:39 +01:00
" shell_command_code " : list ( self . _SHELL_CMD_ [ self . _Platform ] . keys ( ) ) ,
" shell_command " : list ( self . _SHELL_CMD_ [ self . _Platform ] . values ( ) ) ,
2019-09-03 11:58:42 +02: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 ,
2022-02-05 19:53:39 +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 " )
] )
2019-09-03 11:58:42 +02:00
}
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 :
2022-02-05 19:53:39 +01:00
self . BuildTargetList . append ( " %s : %s " % ( Dst , Src ) )
self . BuildTargetList . append ( ' \t ' + self . _CP_TEMPLATE_ [ self . _Platform ] % { ' Src ' : Src , ' Dst ' : Dst } )
2019-09-03 11:58:42 +02:00
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 )
2022-02-06 08:42:19 +01:00
self . BuildTargetList . append ( ' \t @ %s ' % CmdString )
2019-09-03 11:58:42 +02:00
self . ParseSecCmd ( DepsFileList , Cmd [ 1 ] )
for SecOutputFile , SecDepsFile , SecCmd in self . FfsOutputFileList :
self . BuildTargetList . append ( ' %s : %s ' % ( self . ReplaceMacro ( SecOutputFile ) , self . ReplaceMacro ( SecDepsFile ) ) )
2022-02-06 08:42:19 +01:00
self . BuildTargetList . append ( ' \t @ %s ' % self . ReplaceMacro ( SecCmd ) )
2019-09-03 11:58:42 +02:00
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 :
2022-02-05 19:53:39 +01: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 + ' ) ' )
2019-09-03 11:58:42 +02:00
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
2022-02-05 19:53:39 +01:00
def ProcessBuildTargetList ( self , RespFile , ToolsDef ) :
2019-09-03 11:58:42 +02:00
#
# 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 )
2022-02-05 19:53:39 +01:00
FileDependencyDict = { item : ForceIncludedFile for item in SourceFileList }
2019-09-03 11:58:42 +02:00
2022-02-05 19:53:39 +01:00
for Dependency in FileDependencyDict . values ( ) :
self . DependencyHeaderFileSet . update ( set ( Dependency ) )
2019-09-03 11:58:42 +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 ( ) )
# 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 :
2022-02-05 19:53:39 +01:00
resp_file_number = 0
2019-09-03 11:58:42 +02:00
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 :
2022-02-05 19:53:39 +01:00
T , CmdTarget , CmdTargetDict , CmdCppDict = self . ParserCCodeFile ( T , Type , CmdSumDict , CmdTargetDict ,
CmdCppDict , DependencyDict , RespFile ,
ToolsDef , resp_file_number )
resp_file_number + = 1
2019-09-03 11:58:42 +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 ) )
2022-02-05 19:53:39 +01: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 ) )
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-09-03 11:58:42 +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 :
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
2022-02-05 19:53:39 +01:00
else :
continue
2019-09-03 11:58:42 +02:00
if CmdSign not in list ( CmdTargetDict . keys ( ) ) :
2022-02-05 19:53:39 +01:00
cmd = Item . replace ( Temp , CmdSign )
if SingleCommandList [ - 1 ] in cmd :
CmdTargetDict [ CmdSign ] = [ cmd . replace ( SingleCommandList [ - 1 ] , " " ) . rstrip ( ) , SingleCommandList [ - 1 ] ]
2019-09-03 11:58:42 +02:00
else :
2022-02-05 19:53:39 +01:00
# CmdTargetDict[CmdSign] = "%s %s" % (CmdTargetDict[CmdSign], SingleCommandList[-1])
CmdTargetDict [ CmdSign ] . append ( SingleCommandList [ - 1 ] )
2019-09-03 11:58:42 +02:00
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 ]
2022-02-05 19:53:39 +01:00
Cpplist . insert ( 0 , ' $(OBJLIST_ %d ): ' % list ( self . ObjTargetDict . keys ( ) ) . index ( T . Target . SubDir ) )
source_files = CmdTargetDict [ CmdSign ] [ 1 : ]
source_files . insert ( 0 , " " )
if len ( source_files ) > 2 :
SaveFileOnChange ( SaveFilePath , " " . join ( source_files ) , False )
T . Commands [ Index ] = ' %s \n \t %s $(cc_resp_ %s ) ' % (
' \\ \n \t ' . join ( Cpplist ) , CmdTargetDict [ CmdSign ] [ 0 ] , resp_file_number )
ToolsDef . append ( " cc_resp_ %s = @ %s " % ( resp_file_number , SaveFilePath ) )
elif len ( source_files ) < = 2 and len ( " " . join ( CmdTargetDict [ CmdSign ] [ : 2 ] ) ) > GlobalData . gCommandMaxLength :
SaveFileOnChange ( SaveFilePath , " " . join ( source_files ) , False )
T . Commands [ Index ] = ' %s \n \t %s $(cc_resp_ %s ) ' % (
' \\ \n \t ' . join ( Cpplist ) , CmdTargetDict [ CmdSign ] [ 0 ] , resp_file_number )
ToolsDef . append ( " cc_resp_ %s = @ %s " % ( resp_file_number , SaveFilePath ) )
else :
T . Commands [ Index ] = ' %s \n \t %s ' % ( ' \\ \n \t ' . join ( Cpplist ) , " " . join ( CmdTargetDict [ CmdSign ] ) )
2019-09-03 11:58:42 +02:00
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) " ]
2019-09-25 19:52:02 +02:00
self . DependencyHeaderFileSet = set ( )
2019-09-03 11:58:42 +02:00
# Compose a dict object containing information used to do replacement in template
@property
def _TemplateDict ( self ) :
2022-02-05 19:53:39 +01:00
Separator = self . _SEP_ [ self . _Platform ]
2019-09-03 11:58:42 +02:00
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 ( " " )
2022-02-05 19:53:39 +01:00
MakefileName = self . getMakefileName ( )
2019-09-03 11:58:42 +02: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 ,
" 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 ,
2022-02-05 19:53:39 +01:00
" shell_command_code " : list ( self . _SHELL_CMD_ [ self . _Platform ] . keys ( ) ) ,
" shell_command " : list ( self . _SHELL_CMD_ [ self . _Platform ] . values ( ) ) ,
2019-09-03 11:58:42 +02: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 }
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 = [ ]
2019-09-25 19:52:02 +02:00
self . DependencyHeaderFileSet = set ( )
2019-09-03 11:58:42 +02:00
# Compose a dict object containing information used to do replacement in template
@property
def _TemplateDict ( self ) :
2022-02-05 19:53:39 +01:00
Separator = self . _SEP_ [ self . _Platform ]
2019-09-03 11:58:42 +02:00
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 ( )
2022-02-05 19:53:39 +01:00
MakefileName = self . getMakefileName ( )
2019-09-03 11:58:42 +02:00
LibraryMakefileList = [ ]
LibraryMakeCommandList = [ ]
for D in self . LibraryBuildDirectoryList :
D = self . PlaceMacro ( D , { " BUILD_DIR " : MyAgo . BuildDir } )
Makefile = os . path . join ( D , MakefileName )
2022-02-05 19:53:39 +01:00
Command = self . _MAKE_TEMPLATE_ [ self . _Platform ] % { " file " : Makefile }
2019-09-03 11:58:42 +02:00
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 )
2022-02-05 19:53:39 +01:00
Command = self . _MAKE_TEMPLATE_ [ self . _Platform ] % { " file " : Makefile }
2019-09-03 11:58:42 +02:00
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 ,
2022-02-05 19:53:39 +01:00
" shell_command_code " : list ( self . _SHELL_CMD_ [ self . _Platform ] . keys ( ) ) ,
" shell_command " : list ( self . _SHELL_CMD_ [ self . _Platform ] . values ( ) ) ,
2019-09-03 11:58:42 +02:00
" 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} \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} ''' )
## Constructor of TopLevelMakefile
#
# @param Workspace Object of WorkspaceAutoGen class
#
def __init__ ( self , Workspace ) :
BuildFile . __init__ ( self , Workspace )
self . IntermediateDirectoryList = [ ]
2019-09-25 19:52:02 +02:00
self . DependencyHeaderFileSet = set ( )
2019-09-03 11:58:42 +02:00
# Compose a dict object containing information used to do replacement in template
@property
def _TemplateDict ( self ) :
2022-02-05 19:53:39 +01:00
Separator = self . _SEP_ [ self . _Platform ]
2019-09-03 11:58:42 +02:00
# 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 "
2019-09-20 06:56:20 +02:00
if not GlobalData . gEnableGenfdsMultiThread :
ExtraOption + = " --no-genfds-multi-thread "
2019-09-03 11:58:42 +02:00
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 ]
2022-02-05 19:53:39 +01:00
MakefileName = self . getMakefileName ( )
2019-09-03 11:58:42 +02:00
SubBuildCommandList = [ ]
for A in MyAgo . ArchList :
2022-02-05 19:53:39 +01:00
Command = self . _MAKE_TEMPLATE_ [ self . _Platform ] % { " file " : os . path . join ( " $(BUILD_DIR) " , A , MakefileName ) }
2019-09-03 11:58:42 +02:00
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 ,
2022-02-05 19:53:39 +01:00
" shell_command_code " : list ( self . _SHELL_CMD_ [ self . _Platform ] . keys ( ) ) ,
" shell_command " : list ( self . _SHELL_CMD_ [ self . _Platform ] . values ( ) ) ,
2019-09-03 11:58:42 +02:00
' 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 :
2022-02-05 19:53:39 +01:00
Fd = open ( F . Path , ' rb ' )
FileContent = Fd . read ( )
Fd . close ( )
2019-09-03 11:58:42 +02:00
except BaseException as X :
EdkLogger . error ( " build " , FILE_OPEN_FAILURE , ExtraData = F . Path + " \n \t " + str ( X ) )
2022-02-05 19:53:39 +01: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-09-03 11:58:42 +02:00
continue
2022-02-05 19:53:39 +01:00
IncludedFileList = gIncludePattern . findall ( FileContent )
2019-09-03 11:58:42 +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
# This acts like the main() function for the script, unless it is 'import'ed into another script.
if __name__ == ' __main__ ' :
2019-09-20 06:56:20 +02:00
pass