Home | History | Annotate | Download | only in AutoGen
      1 ## @file

      2 # Create makefile for MS nmake and GNU make

      3 #

      4 # Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>

      5 # This program and the accompanying materials

      6 # are licensed and made available under the terms and conditions of the BSD License

      7 # which accompanies this distribution.  The full text of the license may be found at

      8 # http://opensource.org/licenses/bsd-license.php

      9 #

     10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

     11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

     12 #

     13 
     14 ## Import Modules

     15 #

     16 import Common.LongFilePathOs as os
     17 import sys
     18 import string
     19 import re
     20 import os.path as path
     21 from Common.LongFilePathSupport import OpenLongFilePath as open
     22 from Common.MultipleWorkspace import MultipleWorkspace as mws
     23 from Common.BuildToolError import *
     24 from Common.Misc import *
     25 from Common.String import *
     26 from BuildEngine import *
     27 import Common.GlobalData as GlobalData
     28 
     29 ## Regular expression for finding header file inclusions

     30 gIncludePattern = re.compile(r"^[ \t]*#?[ \t]*include(?:[ \t]*(?:\\(?:\r\n|\r|\n))*[ \t]*)*(?:\(?[\"<]?[ \t]*)([-\w.\\/() \t]+)(?:[ \t]*[\">]?\)?)", re.MULTILINE | re.UNICODE | re.IGNORECASE)
     31 
     32 ## Regular expression for matching macro used in header file inclusion

     33 gMacroPattern = re.compile("([_A-Z][_A-Z0-9]*)[ \t]*\((.+)\)", re.UNICODE)
     34 
     35 gIsFileMap = {}
     36 
     37 ## pattern for include style in Edk.x code

     38 gProtocolDefinition = "Protocol/%(HeaderKey)s/%(HeaderKey)s.h"
     39 gGuidDefinition = "Guid/%(HeaderKey)s/%(HeaderKey)s.h"
     40 gArchProtocolDefinition = "ArchProtocol/%(HeaderKey)s/%(HeaderKey)s.h"
     41 gPpiDefinition = "Ppi/%(HeaderKey)s/%(HeaderKey)s.h"
     42 gIncludeMacroConversion = {
     43   "EFI_PROTOCOL_DEFINITION"         :   gProtocolDefinition,
     44   "EFI_GUID_DEFINITION"             :   gGuidDefinition,
     45   "EFI_ARCH_PROTOCOL_DEFINITION"    :   gArchProtocolDefinition,
     46   "EFI_PROTOCOL_PRODUCER"           :   gProtocolDefinition,
     47   "EFI_PROTOCOL_CONSUMER"           :   gProtocolDefinition,
     48   "EFI_PROTOCOL_DEPENDENCY"         :   gProtocolDefinition,
     49   "EFI_ARCH_PROTOCOL_PRODUCER"      :   gArchProtocolDefinition,
     50   "EFI_ARCH_PROTOCOL_CONSUMER"      :   gArchProtocolDefinition,
     51   "EFI_ARCH_PROTOCOL_DEPENDENCY"    :   gArchProtocolDefinition,
     52   "EFI_PPI_DEFINITION"              :   gPpiDefinition,
     53   "EFI_PPI_PRODUCER"                :   gPpiDefinition,
     54   "EFI_PPI_CONSUMER"                :   gPpiDefinition,
     55   "EFI_PPI_DEPENDENCY"              :   gPpiDefinition,
     56 }
     57 
     58 ## default makefile type

     59 gMakeType = ""
     60 if sys.platform == "win32":
     61     gMakeType = "nmake"
     62 else:
     63     gMakeType = "gmake"
     64 
     65 
     66 ## BuildFile class

     67 #

     68 #  This base class encapsules build file and its generation. It uses template to generate

     69 #  the content of build file. The content of build file will be got from AutoGen objects.

     70 #

     71 class BuildFile(object):
     72     ## template used to generate the build file (i.e. makefile if using make)

     73     _TEMPLATE_ = TemplateString('')
     74 
     75     _DEFAULT_FILE_NAME_ = "Makefile"
     76 
     77     ## default file name for each type of build file

     78     _FILE_NAME_ = {
     79         "nmake" :   "Makefile",
     80         "gmake" :   "GNUmakefile"
     81     }
     82 
     83     ## Fixed header string for makefile

     84     _MAKEFILE_HEADER = '''#
     85 # DO NOT EDIT
     86 # This file is auto-generated by build utility
     87 #
     88 # Module Name:
     89 #
     90 #   %s
     91 #
     92 # Abstract:
     93 #
     94 #   Auto-generated makefile for building modules, libraries or platform
     95 #
     96     '''
     97 
     98     ## Header string for each type of build file

     99     _FILE_HEADER_ = {
    100         "nmake" :   _MAKEFILE_HEADER % _FILE_NAME_["nmake"],
    101         "gmake" :   _MAKEFILE_HEADER % _FILE_NAME_["gmake"]
    102     }
    103 
    104     ## shell commands which can be used in build file in the form of macro

    105     #   $(CP)     copy file command

    106     #   $(MV)     move file command

    107     #   $(RM)     remove file command

    108     #   $(MD)     create dir command

    109     #   $(RD)     remove dir command

    110     #

    111     _SHELL_CMD_ = {
    112         "nmake" : {
    113             "CP"    :   "copy /y",
    114             "MV"    :   "move /y",
    115             "RM"    :   "del /f /q",
    116             "MD"    :   "mkdir",
    117             "RD"    :   "rmdir /s /q",
    118         },
    119 
    120         "gmake" : {
    121             "CP"    :   "cp -f",
    122             "MV"    :   "mv -f",
    123             "RM"    :   "rm -f",
    124             "MD"    :   "mkdir -p",
    125             "RD"    :   "rm -r -f",
    126         }
    127     }
    128 
    129     ## directory separator

    130     _SEP_ = {
    131         "nmake" :   "\\",
    132         "gmake" :   "/"
    133     }
    134 
    135     ## directory creation template

    136     _MD_TEMPLATE_ = {
    137         "nmake" :   'if not exist %(dir)s $(MD) %(dir)s',
    138         "gmake" :   "$(MD) %(dir)s"
    139     }
    140 
    141     ## directory removal template

    142     _RD_TEMPLATE_ = {
    143         "nmake" :   'if exist %(dir)s $(RD) %(dir)s',
    144         "gmake" :   "$(RD) %(dir)s"
    145     }
    146 
    147     _CD_TEMPLATE_ = {
    148         "nmake" :   'if exist %(dir)s cd %(dir)s',
    149         "gmake" :   "test -e %(dir)s && cd %(dir)s"
    150     }
    151 
    152     _MAKE_TEMPLATE_ = {
    153         "nmake" :   'if exist %(file)s "$(MAKE)" $(MAKE_FLAGS) -f %(file)s',
    154         "gmake" :   'test -e %(file)s && "$(MAKE)" $(MAKE_FLAGS) -f %(file)s'
    155     }
    156 
    157     _INCLUDE_CMD_ = {
    158         "nmake" :   '!INCLUDE',
    159         "gmake" :   "include"
    160     }
    161 
    162     _INC_FLAG_ = {"MSFT" : "/I", "GCC" : "-I", "INTEL" : "-I", "RVCT" : "-I"}
    163 
    164     ## Constructor of BuildFile

    165     #

    166     #   @param  AutoGenObject   Object of AutoGen class

    167     #

    168     def __init__(self, AutoGenObject):
    169         self._AutoGenObject = AutoGenObject
    170         self._FileType = gMakeType
    171 
    172     ## Create build file

    173     #

    174     #   @param  FileType    Type of build file. Only nmake and gmake are supported now.

    175     #

    176     #   @retval TRUE        The build file is created or re-created successfully

    177     #   @retval FALSE       The build file exists and is the same as the one to be generated

    178     #

    179     def Generate(self, FileType=gMakeType):
    180         if FileType not in self._FILE_NAME_:
    181             EdkLogger.error("build", PARAMETER_INVALID, "Invalid build type [%s]" % FileType,
    182                             ExtraData="[%s]" % str(self._AutoGenObject))
    183         self._FileType = FileType
    184         FileContent = self._TEMPLATE_.Replace(self._TemplateDict)
    185         FileName = self._FILE_NAME_[FileType]
    186         return SaveFileOnChange(os.path.join(self._AutoGenObject.MakeFileDir, FileName), FileContent, False)
    187 
    188     ## Return a list of directory creation command string

    189     #

    190     #   @param      DirList     The list of directory to be created

    191     #

    192     #   @retval     list        The directory creation command list

    193     #

    194     def GetCreateDirectoryCommand(self, DirList):
    195         return [self._MD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
    196 
    197     ## Return a list of directory removal command string

    198     #

    199     #   @param      DirList     The list of directory to be removed

    200     #

    201     #   @retval     list        The directory removal command list

    202     #

    203     def GetRemoveDirectoryCommand(self, DirList):
    204         return [self._RD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
    205 
    206     def PlaceMacro(self, Path, MacroDefinitions={}):
    207         if Path.startswith("$("):
    208             return Path
    209         else:
    210             PathLength = len(Path)
    211             for MacroName in MacroDefinitions:
    212                 MacroValue = MacroDefinitions[MacroName]
    213                 MacroValueLength = len(MacroValue)
    214                 if MacroValueLength <= PathLength and Path.startswith(MacroValue):
    215                     Path = "$(%s)%s" % (MacroName, Path[MacroValueLength:])
    216                     break
    217             return Path
    218 
    219 ## ModuleMakefile class
    220 #
    221 #  This class encapsules makefie and its generation for module. It uses template to generate
    222 #  the content of makefile. The content of makefile will be got from ModuleAutoGen object.
    223 #
    224 class ModuleMakefile(BuildFile):
    225     ## template used to generate the makefile for module
    226     _TEMPLATE_ = TemplateString('''\
    227 ${makefile_header}
    228 
    229 #
    230 # Platform Macro Definition
    231 #
    232 PLATFORM_NAME = ${platform_name}
    233 PLATFORM_GUID = ${platform_guid}
    234 PLATFORM_VERSION = ${platform_version}
    235 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
    236 PLATFORM_DIR = ${platform_dir}
    237 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
    238 
    239 #
    240 # Module Macro Definition
    241 #
    242 MODULE_NAME = ${module_name}
    243 MODULE_GUID = ${module_guid}
    244 MODULE_NAME_GUID = ${module_name_guid}
    245 MODULE_VERSION = ${module_version}
    246 MODULE_TYPE = ${module_type}
    247 MODULE_FILE = ${module_file}
    248 MODULE_FILE_BASE_NAME = ${module_file_base_name}
    249 BASE_NAME = $(MODULE_NAME)
    250 MODULE_RELATIVE_DIR = ${module_relative_directory}
    251 PACKAGE_RELATIVE_DIR = ${package_relative_directory}
    252 MODULE_DIR = ${module_dir}
    253 
    254 MODULE_ENTRY_POINT = ${module_entry_point}
    255 ARCH_ENTRY_POINT = ${arch_entry_point}
    256 IMAGE_ENTRY_POINT = ${image_entry_point}
    257 
    258 ${BEGIN}${module_extra_defines}
    259 ${END}
    260 #
    261 # Build Configuration Macro Definition
    262 #
    263 ARCH = ${architecture}
    264 TOOLCHAIN = ${toolchain_tag}
    265 TOOLCHAIN_TAG = ${toolchain_tag}
    266 TARGET = ${build_target}
    267 
    268 #
    269 # Build Directory Macro Definition
    270 #
    271 # PLATFORM_BUILD_DIR = ${platform_build_directory}
    272 BUILD_DIR = ${platform_build_directory}
    273 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
    274 LIB_DIR = $(BIN_DIR)
    275 MODULE_BUILD_DIR = ${module_build_directory}
    276 OUTPUT_DIR = ${module_output_directory}
    277 DEBUG_DIR = ${module_debug_directory}
    278 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
    279 DEST_DIR_DEBUG = $(DEBUG_DIR)
    280 
    281 #
    282 # Shell Command Macro
    283 #
    284 ${BEGIN}${shell_command_code} = ${shell_command}
    285 ${END}
    286 
    287 #
    288 # Tools definitions specific to this module
    289 #
    290 ${BEGIN}${module_tool_definitions}
    291 ${END}
    292 MAKE_FILE = ${makefile_path}
    293 
    294 #
    295 # Build Macro
    296 #
    297 ${BEGIN}${file_macro}
    298 ${END}
    299 
    300 COMMON_DEPS = ${BEGIN}${common_dependency_file} \\
    301               ${END}
    302 
    303 #
    304 # Overridable Target Macro Definitions
    305 #
    306 FORCE_REBUILD = force_build
    307 INIT_TARGET = init
    308 PCH_TARGET =
    309 BC_TARGET = ${BEGIN}${backward_compatible_target} ${END}
    310 CODA_TARGET = ${BEGIN}${remaining_build_target} \\
    311               ${END}
    312 
    313 #
    314 # Default target, which will build dependent libraries in addition to source files
    315 #
    316 
    317 all: mbuild
    318 
    319 
    320 #
    321 # Target used when called from platform makefile, which will bypass the build of dependent libraries
    322 #
    323 
    324 pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
    325 
    326 #
    327 # ModuleTarget
    328 #
    329 
    330 mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET)
    331 
    332 #
    333 # Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets
    334 #
    335 
    336 tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
    337 
    338 #
    339 # Phony target which is used to force executing commands for a target
    340 #
    341 force_build:
    342 \t-@
    343 
    344 #
    345 # Target to update the FD
    346 #
    347 
    348 fds: mbuild gen_fds
    349 
    350 #
    351 # Initialization target: print build information and create necessary directories
    352 #
    353 init: info dirs
    354 
    355 info:
    356 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
    357 
    358 dirs:
    359 ${BEGIN}\t-@${create_directory_command}\n${END}
    360 
    361 strdefs:
    362 \t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h
    363 
    364 #
    365 # GenLibsTarget
    366 #
    367 gen_libs:
    368 \t${BEGIN}@"$(MAKE)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name}
    369 \t${END}@cd $(MODULE_BUILD_DIR)
    370 
    371 #
    372 # Build Flash Device Image
    373 #
    374 gen_fds:
    375 \t@"$(MAKE)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds
    376 \t@cd $(MODULE_BUILD_DIR)
    377 
    378 #
    379 # Individual Object Build Targets
    380 #
    381 ${BEGIN}${file_build_target}
    382 ${END}
    383 
    384 #
    385 # clean all intermediate files
    386 #
    387 clean:
    388 \t${BEGIN}${clean_command}
    389 \t${END}
    390 
    391 #
    392 # clean all generated files
    393 #
    394 cleanall:
    395 ${BEGIN}\t${cleanall_command}
    396 ${END}\t$(RM) *.pdb *.idb > NUL 2>&1
    397 \t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi
    398 
    399 #
    400 # clean all dependent libraries built
    401 #
    402 cleanlib:
    403 \t${BEGIN}-@${library_build_command} cleanall
    404 \t${END}@cd $(MODULE_BUILD_DIR)\n\n''')
    405 
    406     _FILE_MACRO_TEMPLATE = TemplateString("${macro_name} = ${BEGIN} \\\n    ${source_file}${END}\n")
    407     _BUILD_TARGET_TEMPLATE = TemplateString("${BEGIN}${target} : ${deps}\n${END}\t${cmd}\n")
    408 
    409     ## Constructor of ModuleMakefile
    410     #
    411     #   @param  ModuleAutoGen   Object of ModuleAutoGen class
    412     #
    413     def __init__(self, ModuleAutoGen):
    414         BuildFile.__init__(self, ModuleAutoGen)
    415         self.PlatformInfo = self._AutoGenObject.PlatformInfo
    416 
    417         self.ResultFileList = []
    418         self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
    419 
    420         self.SourceFileDatabase = {}        # {file type : file path}
    421         self.DestFileDatabase = {}          # {file type : file path}
    422         self.FileBuildTargetList = []       # [(src, target string)]
    423         self.BuildTargetList = []           # [target string]
    424         self.PendingBuildTargetList = []    # [FileBuildRule objects]
    425         self.CommonFileDependency = []
    426         self.FileListMacros = {}
    427         self.ListFileMacros = {}
    428 
    429         self.FileCache = {}
    430         self.FileDependency = []
    431         self.LibraryBuildCommandList = []
    432         self.LibraryFileList = []
    433         self.LibraryMakefileList = []
    434         self.LibraryBuildDirectoryList = []
    435         self.SystemLibraryList = []
    436         self.Macros = sdict()
    437         self.Macros["OUTPUT_DIR"      ] = self._AutoGenObject.Macros["OUTPUT_DIR"]
    438         self.Macros["DEBUG_DIR"       ] = self._AutoGenObject.Macros["DEBUG_DIR"]
    439         self.Macros["MODULE_BUILD_DIR"] = self._AutoGenObject.Macros["MODULE_BUILD_DIR"]
    440         self.Macros["BIN_DIR"         ] = self._AutoGenObject.Macros["BIN_DIR"]
    441         self.Macros["BUILD_DIR"       ] = self._AutoGenObject.Macros["BUILD_DIR"]
    442         self.Macros["WORKSPACE"       ] = self._AutoGenObject.Macros["WORKSPACE"]
    443 
    444     # Compose a dict object containing information used to do replacement in template
    445     def _CreateTemplateDict(self):
    446         if self._FileType not in self._SEP_:
    447             EdkLogger.error("build", PARAMETER_INVALID, "Invalid Makefile type [%s]" % self._FileType,
    448                             ExtraData="[%s]" % str(self._AutoGenObject))
    449         Separator = self._SEP_[self._FileType]
    450 
    451         # break build if no source files and binary files are found
    452         if len(self._AutoGenObject.SourceFileList) == 0 and len(self._AutoGenObject.BinaryFileList) == 0:
    453             EdkLogger.error("build", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]"
    454                             % (self._AutoGenObject.BuildTarget, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch),
    455                             ExtraData="[%s]" % str(self._AutoGenObject))
    456 
    457         # convert dependent libraries to build command
    458         self.ProcessDependentLibrary()
    459         if len(self._AutoGenObject.Module.ModuleEntryPointList) > 0:
    460             ModuleEntryPoint = self._AutoGenObject.Module.ModuleEntryPointList[0]
    461         else:
    462             ModuleEntryPoint = "_ModuleEntryPoint"
    463 
    464         # Intel EBC compiler enforces EfiMain
    465         if self._AutoGenObject.AutoGenVersion < 0x00010005 and self._AutoGenObject.Arch == "EBC":
    466             ArchEntryPoint = "EfiMain"
    467         else:
    468             ArchEntryPoint = ModuleEntryPoint
    469 
    470         if self._AutoGenObject.Arch == "EBC":
    471             # EBC compiler always use "EfiStart" as entry point. Only applies to EdkII modules
    472             ImageEntryPoint = "EfiStart"
    473         elif self._AutoGenObject.AutoGenVersion < 0x00010005:
    474             # Edk modules use entry point specified in INF file
    475             ImageEntryPoint = ModuleEntryPoint
    476         else:
    477             # EdkII modules always use "_ModuleEntryPoint" as entry point
    478             ImageEntryPoint = "_ModuleEntryPoint"
    479 
    480         for k, v in self._AutoGenObject.Module.Defines.iteritems():
    481             if k not in self._AutoGenObject.Macros.keys():
    482                 self._AutoGenObject.Macros[k] = v
    483 
    484         if 'MODULE_ENTRY_POINT' not in self._AutoGenObject.Macros.keys():
    485             self._AutoGenObject.Macros['MODULE_ENTRY_POINT'] = ModuleEntryPoint
    486         if 'ARCH_ENTRY_POINT' not in self._AutoGenObject.Macros.keys():
    487             self._AutoGenObject.Macros['ARCH_ENTRY_POINT'] = ArchEntryPoint
    488         if 'IMAGE_ENTRY_POINT' not in self._AutoGenObject.Macros.keys():
    489             self._AutoGenObject.Macros['IMAGE_ENTRY_POINT'] = ImageEntryPoint
    490 
    491         PCI_COMPRESS_Flag = False
    492         for k, v in self._AutoGenObject.Module.Defines.iteritems():
    493             if 'PCI_COMPRESS' == k and 'TRUE' == v:
    494                 PCI_COMPRESS_Flag = True
    495 
    496         # tools definitions
    497         ToolsDef = []
    498         IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
    499         for Tool in self._AutoGenObject.BuildOption:
    500             for Attr in self._AutoGenObject.BuildOption[Tool]:
    501                 Value = self._AutoGenObject.BuildOption[Tool][Attr]
    502                 if Attr == "FAMILY":
    503                     continue
    504                 elif Attr == "PATH":
    505                     ToolsDef.append("%s = %s" % (Tool, Value))
    506                 else:
    507                     # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
    508                     if Tool == "MAKE":
    509                         continue
    510                     # Remove duplicated include path, if any
    511                     if Attr == "FLAGS":
    512                         Value = RemoveDupOption(Value, IncPrefix, self._AutoGenObject.IncludePathList)
    513                         if Tool == "OPTROM" and PCI_COMPRESS_Flag:
    514                             ValueList = Value.split()
    515                             if ValueList:
    516                                 for i, v in enumerate(ValueList):
    517                                     if '-e' == v:
    518                                         ValueList[i] = '-ec'
    519                                 Value = ' '.join(ValueList)
    520 
    521                     ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
    522             ToolsDef.append("")
    523 
    524         # generate the Response file and Response flag
    525         RespDict = self.CommandExceedLimit()
    526         RespFileList = os.path.join(self._AutoGenObject.OutputDir, 'respfilelist.txt')
    527         if RespDict:
    528             RespFileListContent = ''
    529             for Resp in RespDict.keys():
    530                 RespFile = os.path.join(self._AutoGenObject.OutputDir, str(Resp).lower() + '.txt')
    531                 StrList = RespDict[Resp].split(' ')
    532                 UnexpandMacro = []
    533                 NewStr = []
    534                 for Str in StrList:
    535                     if '$' in Str:
    536                         UnexpandMacro.append(Str)
    537                     else:
    538                         NewStr.append(Str)
    539                 UnexpandMacroStr = ' '.join(UnexpandMacro)
    540                 NewRespStr = ' '.join(NewStr)
    541                 SaveFileOnChange(RespFile, NewRespStr, False)
    542                 ToolsDef.append("%s = %s" % (Resp, UnexpandMacroStr + ' @' + RespFile))
    543                 RespFileListContent += '@' + RespFile + os.linesep
    544                 RespFileListContent += NewRespStr + os.linesep
    545             SaveFileOnChange(RespFileList, RespFileListContent, False)
    546         else:
    547             if os.path.exists(RespFileList):
    548                 os.remove(RespFileList)
    549 
    550         # convert source files and binary files to build targets
    551         self.ResultFileList = [str(T.Target) for T in self._AutoGenObject.CodaTargetList]
    552         if len(self.ResultFileList) == 0 and len(self._AutoGenObject.SourceFileList) <> 0:
    553             EdkLogger.error("build", AUTOGEN_ERROR, "Nothing to build",
    554                             ExtraData="[%s]" % str(self._AutoGenObject))
    555 
    556         self.ProcessBuildTargetList()
    557 
    558         # Generate macros used to represent input files
    559         FileMacroList = [] # macro name = file list
    560         for FileListMacro in self.FileListMacros:
    561             FileMacro = self._FILE_MACRO_TEMPLATE.Replace(
    562                                                     {
    563                                                         "macro_name"  : FileListMacro,
    564                                                         "source_file" : self.FileListMacros[FileListMacro]
    565                                                     }
    566                                                     )
    567             FileMacroList.append(FileMacro)
    568 
    569         # INC_LIST is special
    570         FileMacro = ""
    571         IncludePathList = []
    572         for P in  self._AutoGenObject.IncludePathList:
    573             IncludePathList.append(IncPrefix + self.PlaceMacro(P, self.Macros))
    574             if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:
    575                 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix + P)
    576         FileMacro += self._FILE_MACRO_TEMPLATE.Replace(
    577                                                 {
    578                                                     "macro_name"   : "INC",
    579                                                     "source_file" : IncludePathList
    580                                                 }
    581                                                 )
    582         FileMacroList.append(FileMacro)
    583 
    584         # Generate macros used to represent files containing list of input files
    585         for ListFileMacro in self.ListFileMacros:
    586             ListFileName = os.path.join(self._AutoGenObject.OutputDir, "%s.lst" % ListFileMacro.lower()[:len(ListFileMacro) - 5])
    587             FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))
    588             SaveFileOnChange(
    589                 ListFileName,
    590                 "\n".join(self.ListFileMacros[ListFileMacro]),
    591                 False
    592                 )
    593 
    594         # Edk modules need <BaseName>StrDefs.h for string ID
    595         #if self._AutoGenObject.AutoGenVersion < 0x00010005 and len(self._AutoGenObject.UnicodeFileList) > 0:
    596         #    BcTargetList = ['strdefs']
    597         #else:
    598         #    BcTargetList = []
    599         BcTargetList = []
    600 
    601         MakefileName = self._FILE_NAME_[self._FileType]
    602         LibraryMakeCommandList = []
    603         for D in self.LibraryBuildDirectoryList:
    604             Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)}
    605             LibraryMakeCommandList.append(Command)
    606 
    607         package_rel_dir = self._AutoGenObject.SourceDir
    608         current_dir = self.Macros["WORKSPACE"]
    609         found = False
    610         while not found and os.sep in package_rel_dir:
    611             index = package_rel_dir.index(os.sep)
    612             current_dir = mws.join(current_dir, package_rel_dir[:index])
    613             if os.path.exists(current_dir):
    614                 for fl in os.listdir(current_dir):
    615                     if fl.endswith('.dec'):
    616                         found = True
    617                         break
    618             package_rel_dir = package_rel_dir[index + 1:]
    619 
    620         MakefileTemplateDict = {
    621             "makefile_header"           : self._FILE_HEADER_[self._FileType],
    622             "makefile_path"             : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
    623             "makefile_name"             : MakefileName,
    624             "platform_name"             : self.PlatformInfo.Name,
    625             "platform_guid"             : self.PlatformInfo.Guid,
    626             "platform_version"          : self.PlatformInfo.Version,
    627             "platform_relative_directory": self.PlatformInfo.SourceDir,
    628             "platform_output_directory" : self.PlatformInfo.OutputDir,
    629             "platform_dir"              : self._AutoGenObject.Macros["PLATFORM_DIR"],
    630 
    631             "module_name"               : self._AutoGenObject.Name,
    632             "module_guid"               : self._AutoGenObject.Guid,
    633             "module_name_guid"          : self._AutoGenObject._GetUniqueBaseName(),
    634             "module_version"            : self._AutoGenObject.Version,
    635             "module_type"               : self._AutoGenObject.ModuleType,
    636             "module_file"               : self._AutoGenObject.MetaFile.Name,
    637             "module_file_base_name"     : self._AutoGenObject.MetaFile.BaseName,
    638             "module_relative_directory" : self._AutoGenObject.SourceDir,
    639             "module_dir"                : mws.join (self.Macros["WORKSPACE"], self._AutoGenObject.SourceDir),
    640             "package_relative_directory": package_rel_dir,
    641             "module_extra_defines"      : ["%s = %s" % (k, v) for k, v in self._AutoGenObject.Module.Defines.iteritems()],
    642 
    643             "architecture"              : self._AutoGenObject.Arch,
    644             "toolchain_tag"             : self._AutoGenObject.ToolChain,
    645             "build_target"              : self._AutoGenObject.BuildTarget,
    646 
    647             "platform_build_directory"  : self.PlatformInfo.BuildDir,
    648             "module_build_directory"    : self._AutoGenObject.BuildDir,
    649             "module_output_directory"   : self._AutoGenObject.OutputDir,
    650             "module_debug_directory"    : self._AutoGenObject.DebugDir,
    651 
    652             "separator"                 : Separator,
    653             "module_tool_definitions"   : ToolsDef,
    654 
    655             "shell_command_code"        : self._SHELL_CMD_[self._FileType].keys(),
    656             "shell_command"             : self._SHELL_CMD_[self._FileType].values(),
    657 
    658             "module_entry_point"        : ModuleEntryPoint,
    659             "image_entry_point"         : ImageEntryPoint,
    660             "arch_entry_point"          : ArchEntryPoint,
    661             "remaining_build_target"    : self.ResultFileList,
    662             "common_dependency_file"    : self.CommonFileDependency,
    663             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
    664             "clean_command"             : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]),
    665             "cleanall_command"          : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]),
    666             "dependent_library_build_directory" : self.LibraryBuildDirectoryList,
    667             "library_build_command"     : LibraryMakeCommandList,
    668             "file_macro"                : FileMacroList,
    669             "file_build_target"         : self.BuildTargetList,
    670             "backward_compatible_target": BcTargetList,
    671         }
    672 
    673         return MakefileTemplateDict
    674 
    675     def CommandExceedLimit(self):
    676         FlagDict = {
    677                     'CC'    :  { 'Macro' : '$(CC_FLAGS)',    'Value' : False},
    678                     'PP'    :  { 'Macro' : '$(PP_FLAGS)',    'Value' : False},
    679                     'APP'   :  { 'Macro' : '$(APP_FLAGS)',   'Value' : False},
    680                     'ASLPP' :  { 'Macro' : '$(ASLPP_FLAGS)', 'Value' : False},
    681                     'VFRPP' :  { 'Macro' : '$(VFRPP_FLAGS)', 'Value' : False},
    682                     'ASM'   :  { 'Macro' : '$(ASM_FLAGS)',   'Value' : False},
    683                     'ASLCC' :  { 'Macro' : '$(ASLCC_FLAGS)', 'Value' : False},
    684                    }
    685 
    686         RespDict = {}
    687         FileTypeList = []
    688         IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
    689 
    690         # base on the source files to decide the file type
    691         for File in self._AutoGenObject.SourceFileList:
    692             for type in self._AutoGenObject.FileTypes:
    693                 if File in self._AutoGenObject.FileTypes[type]:
    694                     if type not in FileTypeList:
    695                         FileTypeList.append(type)
    696 
    697         # calculate the command-line length
    698         if FileTypeList:
    699             for type in FileTypeList:
    700                 BuildTargets = self._AutoGenObject.BuildRules[type].BuildTargets
    701                 for Target in BuildTargets:
    702                     CommandList = BuildTargets[Target].Commands
    703                     for SingleCommand in CommandList:
    704                         Tool = ''
    705                         SingleCommandLength = len(SingleCommand)
    706                         SingleCommandList = SingleCommand.split()
    707                         if len(SingleCommandList) > 0:
    708                             for Flag in FlagDict.keys():
    709                                 if '$('+ Flag +')' in SingleCommandList[0]:
    710                                     Tool = Flag
    711                                     break
    712                         if Tool:
    713                             SingleCommandLength += len(self._AutoGenObject._BuildOption[Tool]['PATH'])
    714                             for item in SingleCommandList[1:]:
    715                                 if FlagDict[Tool]['Macro'] in item:
    716                                     Str = self._AutoGenObject._BuildOption[Tool]['FLAGS']
    717                                     for Option in self._AutoGenObject.BuildOption.keys():
    718                                         for Attr in self._AutoGenObject.BuildOption[Option]:
    719                                             if Str.find(Option + '_' + Attr) != -1:
    720                                                 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
    721                                     while(Str.find('$(') != -1):
    722                                         for macro in self._AutoGenObject.Macros.keys():
    723                                             MacroName = '$('+ macro + ')'
    724                                             if (Str.find(MacroName) != -1):
    725                                                 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
    726                                                 break
    727                                         else:
    728                                             break
    729                                     SingleCommandLength += len(Str)
    730                                 elif '$(INC)' in item:
    731                                     SingleCommandLength += self._AutoGenObject.IncludePathLength + len(IncPrefix) * len(self._AutoGenObject._IncludePathList)
    732                                 elif item.find('$(') != -1:
    733                                     Str = item
    734                                     for Option in self._AutoGenObject.BuildOption.keys():
    735                                         for Attr in self._AutoGenObject.BuildOption[Option]:
    736                                             if Str.find(Option + '_' + Attr) != -1:
    737                                                 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
    738                                     while(Str.find('$(') != -1):
    739                                         for macro in self._AutoGenObject.Macros.keys():
    740                                             MacroName = '$('+ macro + ')'
    741                                             if (Str.find(MacroName) != -1):
    742                                                 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
    743                                                 break
    744                                         else:
    745                                             break
    746                                     SingleCommandLength += len(Str)
    747 
    748                             if SingleCommandLength > GlobalData.gCommandMaxLength:
    749                                 FlagDict[Tool]['Value'] = True
    750 
    751                 # generate the response file content by combine the FLAGS and INC
    752                 for Flag in FlagDict.keys():
    753                     if FlagDict[Flag]['Value']:
    754                         Key = Flag + '_RESP'
    755                         RespMacro = FlagDict[Flag]['Macro'].replace('FLAGS', 'RESP')
    756                         Value = self._AutoGenObject.BuildOption[Flag]['FLAGS']
    757                         for inc in self._AutoGenObject._IncludePathList:
    758                             Value += ' ' + IncPrefix + inc
    759                         for Option in self._AutoGenObject.BuildOption.keys():
    760                             for Attr in self._AutoGenObject.BuildOption[Option]:
    761                                 if Value.find(Option + '_' + Attr) != -1:
    762                                     Value = Value.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
    763                         while (Value.find('$(') != -1):
    764                             for macro in self._AutoGenObject.Macros.keys():
    765                                 MacroName = '$('+ macro + ')'
    766                                 if (Value.find(MacroName) != -1):
    767                                     Value = Value.replace(MacroName, self._AutoGenObject.Macros[macro])
    768                                     break
    769                             else:
    770                                 break
    771 
    772                         if self._AutoGenObject.ToolChainFamily == 'GCC':
    773                             RespDict[Key] = Value.replace('\\', '/')
    774                         else:
    775                             RespDict[Key] = Value
    776                         for Target in BuildTargets:
    777                             for i, SingleCommand in enumerate(BuildTargets[Target].Commands):
    778                                 if FlagDict[Flag]['Macro'] in SingleCommand:
    779                                     BuildTargets[Target].Commands[i] = SingleCommand.replace('$(INC)','').replace(FlagDict[Flag]['Macro'], RespMacro)
    780         return RespDict
    781 
    782     def ProcessBuildTargetList(self):
    783         #
    784         # Search dependency file list for each source file
    785         #
    786         ForceIncludedFile = []
    787         for File in self._AutoGenObject.AutoGenFileList:
    788             if File.Ext == '.h':
    789                 ForceIncludedFile.append(File)
    790         SourceFileList = []
    791         for Target in self._AutoGenObject.IntroTargetList:
    792             SourceFileList.extend(Target.Inputs)
    793 
    794         self.FileDependency = self.GetFileDependency(
    795                                     SourceFileList,
    796                                     ForceIncludedFile,
    797                                     self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList
    798                                     )
    799         DepSet = None
    800         for File in self.FileDependency:
    801             if not self.FileDependency[File]:
    802                 self.FileDependency[File] = ['$(FORCE_REBUILD)']
    803                 continue
    804             # skip non-C files
    805             if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
    806                 continue
    807             elif DepSet == None:
    808                 DepSet = set(self.FileDependency[File])
    809             else:
    810                 DepSet &= set(self.FileDependency[File])
    811         # in case nothing in SourceFileList
    812         if DepSet == None:
    813             DepSet = set()
    814         #
    815         # Extract common files list in the dependency files
    816         #
    817         for File in DepSet:
    818             self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros))
    819 
    820         for File in self.FileDependency:
    821             # skip non-C files
    822             if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
    823                 continue
    824             NewDepSet = set(self.FileDependency[File])
    825             NewDepSet -= DepSet
    826             self.FileDependency[File] = ["$(COMMON_DEPS)"] + list(NewDepSet)
    827 
    828         # Convert target description object to target string in makefile
    829         for Type in self._AutoGenObject.Targets:
    830             for T in self._AutoGenObject.Targets[Type]:
    831                 # Generate related macros if needed
    832                 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
    833                     self.FileListMacros[T.FileListMacro] = []
    834                 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:
    835                     self.ListFileMacros[T.ListFileMacro] = []
    836                 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:
    837                     self.ListFileMacros[T.IncListFileMacro] = []
    838 
    839                 Deps = []
    840                 # Add force-dependencies
    841                 for Dep in T.Dependencies:
    842                     Deps.append(self.PlaceMacro(str(Dep), self.Macros))
    843                 # Add inclusion-dependencies
    844                 if len(T.Inputs) == 1 and T.Inputs[0] in self.FileDependency:
    845                     for F in self.FileDependency[T.Inputs[0]]:
    846                         Deps.append(self.PlaceMacro(str(F), self.Macros))
    847                 # Add source-dependencies
    848                 for F in T.Inputs:
    849                     NewFile = self.PlaceMacro(str(F), self.Macros)
    850                     # In order to use file list macro as dependency
    851                     if T.GenListFile:
    852                         # gnu tools need forward slash path separater, even on Windows
    853                         self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/'))
    854                         self.FileListMacros[T.FileListMacro].append(NewFile)
    855                     elif T.GenFileListMacro:
    856                         self.FileListMacros[T.FileListMacro].append(NewFile)
    857                     else:
    858                         Deps.append(NewFile)
    859 
    860                 # Use file list macro as dependency
    861                 if T.GenFileListMacro:
    862                     Deps.append("$(%s)" % T.FileListMacro)
    863 
    864                 TargetDict = {
    865                     "target"    :   self.PlaceMacro(T.Target.Path, self.Macros),
    866                     "cmd"       :   "\n\t".join(T.Commands),
    867                     "deps"      :   Deps
    868                 }
    869                 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
    870 
    871     ## For creating makefile targets for dependent libraries
    872     def ProcessDependentLibrary(self):
    873         for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
    874             if not LibraryAutoGen.IsBinaryModule:
    875                 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
    876 
    877     ## Return a list containing source file's dependencies
    878     #

    879     #   @param      FileList        The list of source files

    880     #   @param      ForceInculeList The list of files which will be included forcely

    881     #   @param      SearchPathList  The list of search path

    882     #

    883     #   @retval     dict            The mapping between source file path and its dependencies

    884     #

    885     def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
    886         Dependency = {}
    887         for F in FileList:
    888             Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)
    889         return Dependency
    890 
    891     ## Find dependencies for one source file

    892     #

    893     #  By searching recursively "#include" directive in file, find out all the

    894     #  files needed by given source file. The dependecies will be only searched

    895     #  in given search path list.

    896     #

    897     #   @param      File            The source file

    898     #   @param      ForceInculeList The list of files which will be included forcely

    899     #   @param      SearchPathList  The list of search path

    900     #

    901     #   @retval     list            The list of files the given source file depends on

    902     #

    903     def GetDependencyList(self, File, ForceList, SearchPathList):
    904         EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File)
    905         FileStack = [File] + ForceList
    906         DependencySet = set()
    907 
    908         if self._AutoGenObject.Arch not in gDependencyDatabase:
    909             gDependencyDatabase[self._AutoGenObject.Arch] = {}
    910         DepDb = gDependencyDatabase[self._AutoGenObject.Arch]
    911 
    912         while len(FileStack) > 0:
    913             F = FileStack.pop()
    914 
    915             FullPathDependList = []
    916             if F in self.FileCache:
    917                 for CacheFile in self.FileCache[F]:
    918                     FullPathDependList.append(CacheFile)
    919                     if CacheFile not in DependencySet:
    920                         FileStack.append(CacheFile)
    921                 DependencySet.update(FullPathDependList)
    922                 continue
    923 
    924             CurrentFileDependencyList = []
    925             if F in DepDb:
    926                 CurrentFileDependencyList = DepDb[F]
    927             else:
    928                 try:
    929                     Fd = open(F.Path, 'r')
    930                 except BaseException, X:
    931                     EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path + "\n\t" + str(X))
    932 
    933                 FileContent = Fd.read()
    934                 Fd.close()
    935                 if len(FileContent) == 0:
    936                     continue
    937 
    938                 if FileContent[0] == 0xff or FileContent[0] == 0xfe:
    939                     FileContent = unicode(FileContent, "utf-16")
    940                 IncludedFileList = gIncludePattern.findall(FileContent)
    941 
    942                 for Inc in IncludedFileList:
    943                     Inc = Inc.strip()
    944                     # if there's macro used to reference header file, expand it

    945                     HeaderList = gMacroPattern.findall(Inc)
    946                     if len(HeaderList) == 1 and len(HeaderList[0]) == 2:
    947                         HeaderType = HeaderList[0][0]
    948                         HeaderKey = HeaderList[0][1]
    949                         if HeaderType in gIncludeMacroConversion:
    950                             Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey}
    951                         else:
    952                             # not known macro used in #include, always build the file by

    953                             # returning a empty dependency

    954                             self.FileCache[File] = []
    955                             return []
    956                     Inc = os.path.normpath(Inc)
    957                     CurrentFileDependencyList.append(Inc)
    958                 DepDb[F] = CurrentFileDependencyList
    959 
    960             CurrentFilePath = F.Dir
    961             PathList = [CurrentFilePath] + SearchPathList
    962             for Inc in CurrentFileDependencyList:
    963                 for SearchPath in PathList:
    964                     FilePath = os.path.join(SearchPath, Inc)
    965                     if FilePath in gIsFileMap:
    966                         if not gIsFileMap[FilePath]:
    967                             continue
    968                     # If isfile is called too many times, the performance is slow down.

    969                     elif not os.path.isfile(FilePath):
    970                         gIsFileMap[FilePath] = False
    971                         continue
    972                     else:
    973                         gIsFileMap[FilePath] = True
    974                     FilePath = PathClass(FilePath)
    975                     FullPathDependList.append(FilePath)
    976                     if FilePath not in DependencySet:
    977                         FileStack.append(FilePath)
    978                     break
    979                 else:
    980                     EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\
    981                                     "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList)))
    982 
    983             self.FileCache[F] = FullPathDependList
    984             DependencySet.update(FullPathDependList)
    985 
    986         DependencySet.update(ForceList)
    987         if File in DependencySet:
    988             DependencySet.remove(File)
    989         DependencyList = list(DependencySet)  # remove duplicate ones

    990 
    991         return DependencyList
    992 
    993     _TemplateDict = property(_CreateTemplateDict)
    994 
    995 ## CustomMakefile class

    996 #

    997 #  This class encapsules makefie and its generation for module. It uses template to generate

    998 #  the content of makefile. The content of makefile will be got from ModuleAutoGen object.

    999 #

   1000 class CustomMakefile(BuildFile):
   1001     ## template used to generate the makefile for module with custom makefile

   1002     _TEMPLATE_ = TemplateString('''\
   1003 ${makefile_header}
   1004 
   1005 #
   1006 # Platform Macro Definition
   1007 #
   1008 PLATFORM_NAME = ${platform_name}
   1009 PLATFORM_GUID = ${platform_guid}
   1010 PLATFORM_VERSION = ${platform_version}
   1011 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
   1012 PLATFORM_DIR = ${platform_dir}
   1013 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
   1014 
   1015 #
   1016 # Module Macro Definition
   1017 #
   1018 MODULE_NAME = ${module_name}
   1019 MODULE_GUID = ${module_guid}
   1020 MODULE_NAME_GUID = ${module_name_guid}
   1021 MODULE_VERSION = ${module_version}
   1022 MODULE_TYPE = ${module_type}
   1023 MODULE_FILE = ${module_file}
   1024 MODULE_FILE_BASE_NAME = ${module_file_base_name}
   1025 BASE_NAME = $(MODULE_NAME)
   1026 MODULE_RELATIVE_DIR = ${module_relative_directory}
   1027 MODULE_DIR = ${module_dir}
   1028 
   1029 #
   1030 # Build Configuration Macro Definition
   1031 #
   1032 ARCH = ${architecture}
   1033 TOOLCHAIN = ${toolchain_tag}
   1034 TOOLCHAIN_TAG = ${toolchain_tag}
   1035 TARGET = ${build_target}
   1036 
   1037 #
   1038 # Build Directory Macro Definition
   1039 #
   1040 # PLATFORM_BUILD_DIR = ${platform_build_directory}
   1041 BUILD_DIR = ${platform_build_directory}
   1042 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
   1043 LIB_DIR = $(BIN_DIR)
   1044 MODULE_BUILD_DIR = ${module_build_directory}
   1045 OUTPUT_DIR = ${module_output_directory}
   1046 DEBUG_DIR = ${module_debug_directory}
   1047 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
   1048 DEST_DIR_DEBUG = $(DEBUG_DIR)
   1049 
   1050 #
   1051 # Tools definitions specific to this module
   1052 #
   1053 ${BEGIN}${module_tool_definitions}
   1054 ${END}
   1055 MAKE_FILE = ${makefile_path}
   1056 
   1057 #
   1058 # Shell Command Macro
   1059 #
   1060 ${BEGIN}${shell_command_code} = ${shell_command}
   1061 ${END}
   1062 
   1063 ${custom_makefile_content}
   1064 
   1065 #
   1066 # Target used when called from platform makefile, which will bypass the build of dependent libraries
   1067 #
   1068 
   1069 pbuild: init all
   1070 
   1071 
   1072 #
   1073 # ModuleTarget
   1074 #
   1075 
   1076 mbuild: init all
   1077 
   1078 #
   1079 # Build Target used in multi-thread build mode, which no init target is needed
   1080 #
   1081 
   1082 tbuild: all
   1083 
   1084 #
   1085 # Initialization target: print build information and create necessary directories
   1086 #
   1087 init:
   1088 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
   1089 ${BEGIN}\t-@${create_directory_command}\n${END}\
   1090 
   1091 ''')
   1092 
   1093     ## Constructor of CustomMakefile

   1094     #

   1095     #   @param  ModuleAutoGen   Object of ModuleAutoGen class

   1096     #

   1097     def __init__(self, ModuleAutoGen):
   1098         BuildFile.__init__(self, ModuleAutoGen)
   1099         self.PlatformInfo = self._AutoGenObject.PlatformInfo
   1100         self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
   1101 
   1102     # Compose a dict object containing information used to do replacement in template

   1103     def _CreateTemplateDict(self):
   1104         Separator = self._SEP_[self._FileType]
   1105         if self._FileType not in self._AutoGenObject.CustomMakefile:
   1106             EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType,
   1107                             ExtraData="[%s]" % str(self._AutoGenObject))
   1108         MakefilePath = mws.join(
   1109                                 self._AutoGenObject.WorkspaceDir,
   1110                                 self._AutoGenObject.CustomMakefile[self._FileType]
   1111                                 )
   1112         try:
   1113             CustomMakefile = open(MakefilePath, 'r').read()
   1114         except:
   1115             EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(self._AutoGenObject),
   1116                             ExtraData=self._AutoGenObject.CustomMakefile[self._FileType])
   1117 
   1118         # tools definitions

   1119         ToolsDef = []
   1120         for Tool in self._AutoGenObject.BuildOption:
   1121             # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.

   1122             if Tool == "MAKE":
   1123                 continue
   1124             for Attr in self._AutoGenObject.BuildOption[Tool]:
   1125                 if Attr == "FAMILY":
   1126                     continue
   1127                 elif Attr == "PATH":
   1128                     ToolsDef.append("%s = %s" % (Tool, self._AutoGenObject.BuildOption[Tool][Attr]))
   1129                 else:
   1130                     ToolsDef.append("%s_%s = %s" % (Tool, Attr, self._AutoGenObject.BuildOption[Tool][Attr]))
   1131             ToolsDef.append("")
   1132 
   1133         MakefileName = self._FILE_NAME_[self._FileType]
   1134         MakefileTemplateDict = {
   1135             "makefile_header"           : self._FILE_HEADER_[self._FileType],
   1136             "makefile_path"             : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
   1137             "platform_name"             : self.PlatformInfo.Name,
   1138             "platform_guid"             : self.PlatformInfo.Guid,
   1139             "platform_version"          : self.PlatformInfo.Version,
   1140             "platform_relative_directory": self.PlatformInfo.SourceDir,
   1141             "platform_output_directory" : self.PlatformInfo.OutputDir,
   1142             "platform_dir"              : self._AutoGenObject.Macros["PLATFORM_DIR"],
   1143 
   1144             "module_name"               : self._AutoGenObject.Name,
   1145             "module_guid"               : self._AutoGenObject.Guid,
   1146             "module_name_guid"          : self._AutoGenObject._GetUniqueBaseName(),
   1147             "module_version"            : self._AutoGenObject.Version,
   1148             "module_type"               : self._AutoGenObject.ModuleType,
   1149             "module_file"               : self._AutoGenObject.MetaFile,
   1150             "module_file_base_name"     : self._AutoGenObject.MetaFile.BaseName,
   1151             "module_relative_directory" : self._AutoGenObject.SourceDir,
   1152             "module_dir"                : mws.join (self._AutoGenObject.WorkspaceDir, self._AutoGenObject.SourceDir),
   1153 
   1154             "architecture"              : self._AutoGenObject.Arch,
   1155             "toolchain_tag"             : self._AutoGenObject.ToolChain,
   1156             "build_target"              : self._AutoGenObject.BuildTarget,
   1157 
   1158             "platform_build_directory"  : self.PlatformInfo.BuildDir,
   1159             "module_build_directory"    : self._AutoGenObject.BuildDir,
   1160             "module_output_directory"   : self._AutoGenObject.OutputDir,
   1161             "module_debug_directory"    : self._AutoGenObject.DebugDir,
   1162 
   1163             "separator"                 : Separator,
   1164             "module_tool_definitions"   : ToolsDef,
   1165 
   1166             "shell_command_code"        : self._SHELL_CMD_[self._FileType].keys(),
   1167             "shell_command"             : self._SHELL_CMD_[self._FileType].values(),
   1168 
   1169             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
   1170             "custom_makefile_content"   : CustomMakefile
   1171         }
   1172 
   1173         return MakefileTemplateDict
   1174 
   1175     _TemplateDict = property(_CreateTemplateDict)
   1176 
   1177 ## PlatformMakefile class

   1178 #

   1179 #  This class encapsules makefie and its generation for platform. It uses

   1180 # template to generate the content of makefile. The content of makefile will be

   1181 # got from PlatformAutoGen object.

   1182 #

   1183 class PlatformMakefile(BuildFile):
   1184     ## template used to generate the makefile for platform

   1185     _TEMPLATE_ = TemplateString('''\
   1186 ${makefile_header}
   1187 
   1188 #
   1189 # Platform Macro Definition
   1190 #
   1191 PLATFORM_NAME = ${platform_name}
   1192 PLATFORM_GUID = ${platform_guid}
   1193 PLATFORM_VERSION = ${platform_version}
   1194 PLATFORM_FILE = ${platform_file}
   1195 PLATFORM_DIR = ${platform_dir}
   1196 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
   1197 
   1198 #
   1199 # Build Configuration Macro Definition
   1200 #
   1201 TOOLCHAIN = ${toolchain_tag}
   1202 TOOLCHAIN_TAG = ${toolchain_tag}
   1203 TARGET = ${build_target}
   1204 
   1205 #
   1206 # Build Directory Macro Definition
   1207 #
   1208 BUILD_DIR = ${platform_build_directory}
   1209 FV_DIR = ${platform_build_directory}${separator}FV
   1210 
   1211 #
   1212 # Shell Command Macro
   1213 #
   1214 ${BEGIN}${shell_command_code} = ${shell_command}
   1215 ${END}
   1216 
   1217 MAKE = ${make_path}
   1218 MAKE_FILE = ${makefile_path}
   1219 
   1220 #
   1221 # Default target
   1222 #
   1223 all: init build_libraries build_modules
   1224 
   1225 #
   1226 # Initialization target: print build information and create necessary directories
   1227 #
   1228 init:
   1229 \t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
   1230 \t${BEGIN}-@${create_directory_command}
   1231 \t${END}
   1232 #
   1233 # library build target
   1234 #
   1235 libraries: init build_libraries
   1236 
   1237 #
   1238 # module build target
   1239 #
   1240 modules: init build_libraries build_modules
   1241 
   1242 #
   1243 # Build all libraries:
   1244 #
   1245 build_libraries:
   1246 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
   1247 ${END}\t@cd $(BUILD_DIR)
   1248 
   1249 #
   1250 # Build all modules:
   1251 #
   1252 build_modules:
   1253 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
   1254 ${END}\t@cd $(BUILD_DIR)
   1255 
   1256 #
   1257 # Clean intermediate files
   1258 #
   1259 clean:
   1260 \t${BEGIN}-@${library_build_command} clean
   1261 \t${END}${BEGIN}-@${module_build_command} clean
   1262 \t${END}@cd $(BUILD_DIR)
   1263 
   1264 #
   1265 # Clean all generated files except to makefile
   1266 #
   1267 cleanall:
   1268 ${BEGIN}\t${cleanall_command}
   1269 ${END}
   1270 
   1271 #
   1272 # Clean all library files
   1273 #
   1274 cleanlib:
   1275 \t${BEGIN}-@${library_build_command} cleanall
   1276 \t${END}@cd $(BUILD_DIR)\n
   1277 ''')
   1278 
   1279     ## Constructor of PlatformMakefile

   1280     #

   1281     #   @param  ModuleAutoGen   Object of PlatformAutoGen class

   1282     #

   1283     def __init__(self, PlatformAutoGen):
   1284         BuildFile.__init__(self, PlatformAutoGen)
   1285         self.ModuleBuildCommandList = []
   1286         self.ModuleMakefileList = []
   1287         self.IntermediateDirectoryList = []
   1288         self.ModuleBuildDirectoryList = []
   1289         self.LibraryBuildDirectoryList = []
   1290         self.LibraryMakeCommandList = []
   1291 
   1292     # Compose a dict object containing information used to do replacement in template

   1293     def _CreateTemplateDict(self):
   1294         Separator = self._SEP_[self._FileType]
   1295 
   1296         PlatformInfo = self._AutoGenObject
   1297         if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:
   1298             EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
   1299                             ExtraData="[%s]" % str(self._AutoGenObject))
   1300 
   1301         self.IntermediateDirectoryList = ["$(BUILD_DIR)"]
   1302         self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()
   1303         self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()
   1304 
   1305         MakefileName = self._FILE_NAME_[self._FileType]
   1306         LibraryMakefileList = []
   1307         LibraryMakeCommandList = []
   1308         for D in self.LibraryBuildDirectoryList:
   1309             D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})
   1310             Makefile = os.path.join(D, MakefileName)
   1311             Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
   1312             LibraryMakefileList.append(Makefile)
   1313             LibraryMakeCommandList.append(Command)
   1314         self.LibraryMakeCommandList = LibraryMakeCommandList
   1315 
   1316         ModuleMakefileList = []
   1317         ModuleMakeCommandList = []
   1318         for D in self.ModuleBuildDirectoryList:
   1319             D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})
   1320             Makefile = os.path.join(D, MakefileName)
   1321             Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
   1322             ModuleMakefileList.append(Makefile)
   1323             ModuleMakeCommandList.append(Command)
   1324 
   1325         MakefileTemplateDict = {
   1326             "makefile_header"           : self._FILE_HEADER_[self._FileType],
   1327             "makefile_path"             : os.path.join("$(BUILD_DIR)", MakefileName),
   1328             "make_path"                 : PlatformInfo.ToolDefinition["MAKE"]["PATH"],
   1329             "makefile_name"             : MakefileName,
   1330             "platform_name"             : PlatformInfo.Name,
   1331             "platform_guid"             : PlatformInfo.Guid,
   1332             "platform_version"          : PlatformInfo.Version,
   1333             "platform_file"             : self._AutoGenObject.MetaFile,
   1334             "platform_relative_directory": PlatformInfo.SourceDir,
   1335             "platform_output_directory" : PlatformInfo.OutputDir,
   1336             "platform_build_directory"  : PlatformInfo.BuildDir,
   1337             "platform_dir"              : self._AutoGenObject.Macros["PLATFORM_DIR"],
   1338 
   1339             "toolchain_tag"             : PlatformInfo.ToolChain,
   1340             "build_target"              : PlatformInfo.BuildTarget,
   1341             "shell_command_code"        : self._SHELL_CMD_[self._FileType].keys(),
   1342             "shell_command"             : self._SHELL_CMD_[self._FileType].values(),
   1343             "build_architecture_list"   : self._AutoGenObject.Arch,
   1344             "architecture"              : self._AutoGenObject.Arch,
   1345             "separator"                 : Separator,
   1346             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
   1347             "cleanall_command"          : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
   1348             "library_makefile_list"     : LibraryMakefileList,
   1349             "module_makefile_list"      : ModuleMakefileList,
   1350             "library_build_command"     : LibraryMakeCommandList,
   1351             "module_build_command"      : ModuleMakeCommandList,
   1352         }
   1353 
   1354         return MakefileTemplateDict
   1355 
   1356     ## Get the root directory list for intermediate files of all modules build

   1357     #

   1358     #   @retval     list    The list of directory

   1359     #

   1360     def GetModuleBuildDirectoryList(self):
   1361         DirList = []
   1362         for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
   1363             if not ModuleAutoGen.IsBinaryModule:
   1364                 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
   1365         return DirList
   1366 
   1367     ## Get the root directory list for intermediate files of all libraries build

   1368     #

   1369     #   @retval     list    The list of directory

   1370     #

   1371     def GetLibraryBuildDirectoryList(self):
   1372         DirList = []
   1373         for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
   1374             if not LibraryAutoGen.IsBinaryModule:
   1375                 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
   1376         return DirList
   1377 
   1378     _TemplateDict = property(_CreateTemplateDict)
   1379 
   1380 ## TopLevelMakefile class

   1381 #

   1382 #  This class encapsules makefie and its generation for entrance makefile. It

   1383 # uses template to generate the content of makefile. The content of makefile

   1384 # will be got from WorkspaceAutoGen object.

   1385 #

   1386 class TopLevelMakefile(BuildFile):
   1387     ## template used to generate toplevel makefile

   1388     _TEMPLATE_ = TemplateString('''${BEGIN}\tGenFds -f ${fdf_file} --conf=${conf_directory} -o ${platform_build_directory} -t ${toolchain_tag} -b ${build_target} -p ${active_platform} -a ${build_architecture_list} ${extra_options}${END}${BEGIN} -r ${fd} ${END}${BEGIN} -i ${fv} ${END}${BEGIN} -C ${cap} ${END}${BEGIN} -D ${macro} ${END}''')
   1389 
   1390     ## Constructor of TopLevelMakefile

   1391     #

   1392     #   @param  Workspace   Object of WorkspaceAutoGen class

   1393     #

   1394     def __init__(self, Workspace):
   1395         BuildFile.__init__(self, Workspace)
   1396         self.IntermediateDirectoryList = []
   1397 
   1398     # Compose a dict object containing information used to do replacement in template

   1399     def _CreateTemplateDict(self):
   1400         Separator = self._SEP_[self._FileType]
   1401 
   1402         # any platform autogen object is ok because we just need common information

   1403         PlatformInfo = self._AutoGenObject
   1404 
   1405         if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:
   1406             EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
   1407                             ExtraData="[%s]" % str(self._AutoGenObject))
   1408 
   1409         for Arch in PlatformInfo.ArchList:
   1410             self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch]))
   1411         self.IntermediateDirectoryList.append("$(FV_DIR)")
   1412 
   1413         # TRICK: for not generating GenFds call in makefile if no FDF file

   1414         MacroList = []
   1415         if PlatformInfo.FdfFile != None and PlatformInfo.FdfFile != "":
   1416             FdfFileList = [PlatformInfo.FdfFile]
   1417             # macros passed to GenFds

   1418             MacroList.append('"%s=%s"' % ("EFI_SOURCE", GlobalData.gEfiSource.replace('\\', '\\\\')))
   1419             MacroList.append('"%s=%s"' % ("EDK_SOURCE", GlobalData.gEdkSource.replace('\\', '\\\\')))
   1420             MacroDict = {}
   1421             MacroDict.update(GlobalData.gGlobalDefines)
   1422             MacroDict.update(GlobalData.gCommandLineDefines)
   1423             MacroDict.pop("EFI_SOURCE", "dummy")
   1424             MacroDict.pop("EDK_SOURCE", "dummy")
   1425             for MacroName in MacroDict:
   1426                 if MacroDict[MacroName] != "":
   1427                     MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))
   1428                 else:
   1429                     MacroList.append('"%s"' % MacroName)
   1430         else:
   1431             FdfFileList = []
   1432 
   1433         # pass extra common options to external program called in makefile, currently GenFds.exe
   1434         ExtraOption = ''
   1435         LogLevel = EdkLogger.GetLevel()
   1436         if LogLevel == EdkLogger.VERBOSE:
   1437             ExtraOption += " -v"
   1438         elif LogLevel <= EdkLogger.DEBUG_9:
   1439             ExtraOption += " -d %d" % (LogLevel - 1)
   1440         elif LogLevel == EdkLogger.QUIET:
   1441             ExtraOption += " -q"
   1442 
   1443         if GlobalData.gCaseInsensitive:
   1444             ExtraOption += " -c"
   1445 
   1446         if GlobalData.gIgnoreSource:
   1447             ExtraOption += " --ignore-sources"
   1448 
   1449         if GlobalData.BuildOptionPcd:
   1450             for index, option in enumerate(GlobalData.gCommand):
   1451                 if "--pcd" == option and GlobalData.gCommand[index+1]:
   1452                     ExtraOption += " --pcd " + GlobalData.gCommand[index+1]
   1453 
   1454         MakefileName = self._FILE_NAME_[self._FileType]
   1455         SubBuildCommandList = []
   1456         for A in PlatformInfo.ArchList:
   1457             Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)}
   1458             SubBuildCommandList.append(Command)
   1459 
   1460         MakefileTemplateDict = {
   1461             "makefile_header"           : self._FILE_HEADER_[self._FileType],
   1462             "makefile_path"             : os.path.join("$(BUILD_DIR)", MakefileName),
   1463             "make_path"                 : PlatformInfo.ToolDefinition["MAKE"]["PATH"],
   1464             "platform_name"             : PlatformInfo.Name,
   1465             "platform_guid"             : PlatformInfo.Guid,
   1466             "platform_version"          : PlatformInfo.Version,
   1467             "platform_build_directory"  : PlatformInfo.BuildDir,
   1468             "conf_directory"            : GlobalData.gConfDirectory,
   1469 
   1470             "toolchain_tag"             : PlatformInfo.ToolChain,
   1471             "build_target"              : PlatformInfo.BuildTarget,
   1472             "shell_command_code"        : self._SHELL_CMD_[self._FileType].keys(),
   1473             "shell_command"             : self._SHELL_CMD_[self._FileType].values(),
   1474             'arch'                      : list(PlatformInfo.ArchList),
   1475             "build_architecture_list"   : ','.join(PlatformInfo.ArchList),
   1476             "separator"                 : Separator,
   1477             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
   1478             "cleanall_command"          : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
   1479             "sub_build_command"         : SubBuildCommandList,
   1480             "fdf_file"                  : FdfFileList,
   1481             "active_platform"           : str(PlatformInfo),
   1482             "fd"                        : PlatformInfo.FdTargetList,
   1483             "fv"                        : PlatformInfo.FvTargetList,
   1484             "cap"                       : PlatformInfo.CapTargetList,
   1485             "extra_options"             : ExtraOption,
   1486             "macro"                     : MacroList,
   1487         }
   1488 
   1489         return MakefileTemplateDict
   1490 
   1491     ## Get the root directory list for intermediate files of all modules build
   1492     #
   1493     #   @retval     list    The list of directory
   1494     #
   1495     def GetModuleBuildDirectoryList(self):
   1496         DirList = []
   1497         for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
   1498             if not ModuleAutoGen.IsBinaryModule:
   1499                 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
   1500         return DirList
   1501 
   1502     ## Get the root directory list for intermediate files of all libraries build
   1503     #
   1504     #   @retval     list    The list of directory
   1505     #
   1506     def GetLibraryBuildDirectoryList(self):
   1507         DirList = []
   1508         for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
   1509             if not LibraryAutoGen.IsBinaryModule:
   1510                 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
   1511         return DirList
   1512 
   1513     _TemplateDict = property(_CreateTemplateDict)
   1514 
   1515 # This acts like the main() function for the script, unless it is 'import'ed into another script.
   1516 if __name__ == '__main__':
   1517     pass
   1518 
   1519