1## @file
2# Create makefile for MS nmake and GNU make
3#
4# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5# SPDX-License-Identifier: BSD-2-Clause-Patent
6#
7
8## Import Modules
9#
10from __future__ import absolute_import
11import Common.LongFilePathOs as os
12import sys
13import string
14import re
15import os.path as path
16from Common.LongFilePathSupport import OpenLongFilePath as open
17from Common.MultipleWorkspace import MultipleWorkspace as mws
18from Common.BuildToolError import *
19from Common.Misc import *
20from Common.StringUtils import *
21from .BuildEngine import *
22import Common.GlobalData as GlobalData
23from collections import OrderedDict
24from Common.DataType import TAB_COMPILER_MSFT
25
26## Regular expression for finding header file inclusions
27gIncludePattern = re.compile(r"^[ \t]*[#%]?[ \t]*include(?:[ \t]*(?:\\(?:\r\n|\r|\n))*[ \t]*)*(?:\(?[\"<]?[ \t]*)([-\w.\\/() \t]+)(?:[ \t]*[\">]?\)?)", re.MULTILINE | re.UNICODE | re.IGNORECASE)
28
29## Regular expression for matching macro used in header file inclusion
30gMacroPattern = re.compile("([_A-Z][_A-Z0-9]*)[ \t]*\((.+)\)", re.UNICODE)
31
32gIsFileMap = {}
33
34## pattern for include style in Edk.x code
35gProtocolDefinition = "Protocol/%(HeaderKey)s/%(HeaderKey)s.h"
36gGuidDefinition = "Guid/%(HeaderKey)s/%(HeaderKey)s.h"
37gArchProtocolDefinition = "ArchProtocol/%(HeaderKey)s/%(HeaderKey)s.h"
38gPpiDefinition = "Ppi/%(HeaderKey)s/%(HeaderKey)s.h"
39gIncludeMacroConversion = {
40  "EFI_PROTOCOL_DEFINITION"         :   gProtocolDefinition,
41  "EFI_GUID_DEFINITION"             :   gGuidDefinition,
42  "EFI_ARCH_PROTOCOL_DEFINITION"    :   gArchProtocolDefinition,
43  "EFI_PROTOCOL_PRODUCER"           :   gProtocolDefinition,
44  "EFI_PROTOCOL_CONSUMER"           :   gProtocolDefinition,
45  "EFI_PROTOCOL_DEPENDENCY"         :   gProtocolDefinition,
46  "EFI_ARCH_PROTOCOL_PRODUCER"      :   gArchProtocolDefinition,
47  "EFI_ARCH_PROTOCOL_CONSUMER"      :   gArchProtocolDefinition,
48  "EFI_ARCH_PROTOCOL_DEPENDENCY"    :   gArchProtocolDefinition,
49  "EFI_PPI_DEFINITION"              :   gPpiDefinition,
50  "EFI_PPI_PRODUCER"                :   gPpiDefinition,
51  "EFI_PPI_CONSUMER"                :   gPpiDefinition,
52  "EFI_PPI_DEPENDENCY"              :   gPpiDefinition,
53}
54
55## default makefile type
56gMakeType = ""
57if sys.platform == "win32":
58    gMakeType = "nmake"
59else:
60    gMakeType = "gmake"
61
62
63## BuildFile class
64#
65#  This base class encapsules build file and its generation. It uses template to generate
66#  the content of build file. The content of build file will be got from AutoGen objects.
67#
68class BuildFile(object):
69    ## template used to generate the build file (i.e. makefile if using make)
70    _TEMPLATE_ = TemplateString('')
71
72    _DEFAULT_FILE_NAME_ = "Makefile"
73
74    ## default file name for each type of build file
75    _FILE_NAME_ = {
76        "nmake" :   "Makefile",
77        "gmake" :   "GNUmakefile"
78    }
79
80    ## Fixed header string for makefile
81    _MAKEFILE_HEADER = '''#
82# DO NOT EDIT
83# This file is auto-generated by build utility
84#
85# Module Name:
86#
87#   %s
88#
89# Abstract:
90#
91#   Auto-generated makefile for building modules, libraries or platform
92#
93    '''
94
95    ## Header string for each type of build file
96    _FILE_HEADER_ = {
97        "nmake" :   _MAKEFILE_HEADER % _FILE_NAME_["nmake"],
98        "gmake" :   _MAKEFILE_HEADER % _FILE_NAME_["gmake"]
99    }
100
101    ## shell commands which can be used in build file in the form of macro
102    #   $(CP)     copy file command
103    #   $(MV)     move file command
104    #   $(RM)     remove file command
105    #   $(MD)     create dir command
106    #   $(RD)     remove dir command
107    #
108    _SHELL_CMD_ = {
109        "nmake" : {
110            "CP"    :   "copy /y",
111            "MV"    :   "move /y",
112            "RM"    :   "del /f /q",
113            "MD"    :   "mkdir",
114            "RD"    :   "rmdir /s /q",
115        },
116
117        "gmake" : {
118            "CP"    :   "cp -f",
119            "MV"    :   "mv -f",
120            "RM"    :   "rm -f",
121            "MD"    :   "mkdir -p",
122            "RD"    :   "rm -r -f",
123        }
124    }
125
126    ## directory separator
127    _SEP_ = {
128        "nmake" :   "\\",
129        "gmake" :   "/"
130    }
131
132    ## directory creation template
133    _MD_TEMPLATE_ = {
134        "nmake" :   'if not exist %(dir)s $(MD) %(dir)s',
135        "gmake" :   "$(MD) %(dir)s"
136    }
137
138    ## directory removal template
139    _RD_TEMPLATE_ = {
140        "nmake" :   'if exist %(dir)s $(RD) %(dir)s',
141        "gmake" :   "$(RD) %(dir)s"
142    }
143    ## cp if exist
144    _CP_TEMPLATE_ = {
145        "nmake" :   'if exist %(Src)s $(CP) %(Src)s %(Dst)s',
146        "gmake" :   "test -f %(Src)s && $(CP) %(Src)s %(Dst)s"
147    }
148
149    _CD_TEMPLATE_ = {
150        "nmake" :   'if exist %(dir)s cd %(dir)s',
151        "gmake" :   "test -e %(dir)s && cd %(dir)s"
152    }
153
154    _MAKE_TEMPLATE_ = {
155        "nmake" :   'if exist %(file)s "$(MAKE)" $(MAKE_FLAGS) -f %(file)s',
156        "gmake" :   'test -e %(file)s && "$(MAKE)" $(MAKE_FLAGS) -f %(file)s'
157    }
158
159    _INCLUDE_CMD_ = {
160        "nmake" :   '!INCLUDE',
161        "gmake" :   "include"
162    }
163
164    _INC_FLAG_ = {TAB_COMPILER_MSFT : "/I", "GCC" : "-I", "INTEL" : "-I", "RVCT" : "-I", "NASM" : "-I"}
165
166    ## Constructor of BuildFile
167    #
168    #   @param  AutoGenObject   Object of AutoGen class
169    #
170    def __init__(self, AutoGenObject):
171        self._AutoGenObject = AutoGenObject
172        self._FileType = gMakeType
173
174    ## Create build file
175    #
176    #   @param  FileType    Type of build file. Only nmake and gmake are supported now.
177    #
178    #   @retval TRUE        The build file is created or re-created successfully
179    #   @retval FALSE       The build file exists and is the same as the one to be generated
180    #
181    def Generate(self, FileType=gMakeType):
182        if FileType not in self._FILE_NAME_:
183            EdkLogger.error("build", PARAMETER_INVALID, "Invalid build type [%s]" % FileType,
184                            ExtraData="[%s]" % str(self._AutoGenObject))
185        self._FileType = FileType
186        FileContent = self._TEMPLATE_.Replace(self._TemplateDict)
187        FileName = self._FILE_NAME_[FileType]
188        return SaveFileOnChange(os.path.join(self._AutoGenObject.MakeFileDir, FileName), FileContent, False)
189
190    ## Return a list of directory creation command string
191    #
192    #   @param      DirList     The list of directory to be created
193    #
194    #   @retval     list        The directory creation command list
195    #
196    def GetCreateDirectoryCommand(self, DirList):
197        return [self._MD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
198
199    ## Return a list of directory removal command string
200    #
201    #   @param      DirList     The list of directory to be removed
202    #
203    #   @retval     list        The directory removal command list
204    #
205    def GetRemoveDirectoryCommand(self, DirList):
206        return [self._RD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
207
208    def PlaceMacro(self, Path, MacroDefinitions={}):
209        if Path.startswith("$("):
210            return Path
211        else:
212            PathLength = len(Path)
213            for MacroName in MacroDefinitions:
214                MacroValue = MacroDefinitions[MacroName]
215                MacroValueLength = len(MacroValue)
216                if MacroValueLength == 0:
217                    continue
218                if MacroValueLength <= PathLength and Path.startswith(MacroValue):
219                    Path = "$(%s)%s" % (MacroName, Path[MacroValueLength:])
220                    break
221            return Path
222
223## ModuleMakefile class
224#
225#  This class encapsules makefie and its generation for module. It uses template to generate
226#  the content of makefile. The content of makefile will be got from ModuleAutoGen object.
227#
228class ModuleMakefile(BuildFile):
229    ## template used to generate the makefile for module
230    _TEMPLATE_ = TemplateString('''\
231${makefile_header}
232
233#
234# Platform Macro Definition
235#
236PLATFORM_NAME = ${platform_name}
237PLATFORM_GUID = ${platform_guid}
238PLATFORM_VERSION = ${platform_version}
239PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
240PLATFORM_DIR = ${platform_dir}
241PLATFORM_OUTPUT_DIR = ${platform_output_directory}
242
243#
244# Module Macro Definition
245#
246MODULE_NAME = ${module_name}
247MODULE_GUID = ${module_guid}
248MODULE_NAME_GUID = ${module_name_guid}
249MODULE_VERSION = ${module_version}
250MODULE_TYPE = ${module_type}
251MODULE_FILE = ${module_file}
252MODULE_FILE_BASE_NAME = ${module_file_base_name}
253BASE_NAME = $(MODULE_NAME)
254MODULE_RELATIVE_DIR = ${module_relative_directory}
255PACKAGE_RELATIVE_DIR = ${package_relative_directory}
256MODULE_DIR = ${module_dir}
257FFS_OUTPUT_DIR = ${ffs_output_directory}
258
259MODULE_ENTRY_POINT = ${module_entry_point}
260ARCH_ENTRY_POINT = ${arch_entry_point}
261IMAGE_ENTRY_POINT = ${image_entry_point}
262
263${BEGIN}${module_extra_defines}
264${END}
265#
266# Build Configuration Macro Definition
267#
268ARCH = ${architecture}
269TOOLCHAIN = ${toolchain_tag}
270TOOLCHAIN_TAG = ${toolchain_tag}
271TARGET = ${build_target}
272
273#
274# Build Directory Macro Definition
275#
276# PLATFORM_BUILD_DIR = ${platform_build_directory}
277BUILD_DIR = ${platform_build_directory}
278BIN_DIR = $(BUILD_DIR)${separator}${architecture}
279LIB_DIR = $(BIN_DIR)
280MODULE_BUILD_DIR = ${module_build_directory}
281OUTPUT_DIR = ${module_output_directory}
282DEBUG_DIR = ${module_debug_directory}
283DEST_DIR_OUTPUT = $(OUTPUT_DIR)
284DEST_DIR_DEBUG = $(DEBUG_DIR)
285
286#
287# Shell Command Macro
288#
289${BEGIN}${shell_command_code} = ${shell_command}
290${END}
291
292#
293# Tools definitions specific to this module
294#
295${BEGIN}${module_tool_definitions}
296${END}
297MAKE_FILE = ${makefile_path}
298
299#
300# Build Macro
301#
302${BEGIN}${file_macro}
303${END}
304
305COMMON_DEPS = ${BEGIN}${common_dependency_file} \\
306              ${END}
307
308#
309# Overridable Target Macro Definitions
310#
311FORCE_REBUILD = force_build
312INIT_TARGET = init
313PCH_TARGET =
314BC_TARGET = ${BEGIN}${backward_compatible_target} ${END}
315CODA_TARGET = ${BEGIN}${remaining_build_target} \\
316              ${END}
317
318#
319# Default target, which will build dependent libraries in addition to source files
320#
321
322all: mbuild
323
324
325#
326# Target used when called from platform makefile, which will bypass the build of dependent libraries
327#
328
329pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
330
331#
332# ModuleTarget
333#
334
335mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET)
336
337#
338# Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets
339#
340
341tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
342
343#
344# Phony target which is used to force executing commands for a target
345#
346force_build:
347\t-@
348
349#
350# Target to update the FD
351#
352
353fds: mbuild gen_fds
354
355#
356# Initialization target: print build information and create necessary directories
357#
358init: info dirs
359
360info:
361\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
362
363dirs:
364${BEGIN}\t-@${create_directory_command}\n${END}
365
366strdefs:
367\t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h
368
369#
370# GenLibsTarget
371#
372gen_libs:
373\t${BEGIN}@"$(MAKE)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name}
374\t${END}@cd $(MODULE_BUILD_DIR)
375
376#
377# Build Flash Device Image
378#
379gen_fds:
380\t@"$(MAKE)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds
381\t@cd $(MODULE_BUILD_DIR)
382
383#
384# Individual Object Build Targets
385#
386${BEGIN}${file_build_target}
387${END}
388
389#
390# clean all intermediate files
391#
392clean:
393\t${BEGIN}${clean_command}
394\t${END}\t$(RM) AutoGenTimeStamp
395
396#
397# clean all generated files
398#
399cleanall:
400${BEGIN}\t${cleanall_command}
401${END}\t$(RM) *.pdb *.idb > NUL 2>&1
402\t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi
403\t$(RM) AutoGenTimeStamp
404
405#
406# clean all dependent libraries built
407#
408cleanlib:
409\t${BEGIN}-@${library_build_command} cleanall
410\t${END}@cd $(MODULE_BUILD_DIR)\n\n''')
411
412    _FILE_MACRO_TEMPLATE = TemplateString("${macro_name} = ${BEGIN} \\\n    ${source_file}${END}\n")
413    _BUILD_TARGET_TEMPLATE = TemplateString("${BEGIN}${target} : ${deps}\n${END}\t${cmd}\n")
414
415    ## Constructor of ModuleMakefile
416    #
417    #   @param  ModuleAutoGen   Object of ModuleAutoGen class
418    #
419    def __init__(self, ModuleAutoGen):
420        BuildFile.__init__(self, ModuleAutoGen)
421        self.PlatformInfo = self._AutoGenObject.PlatformInfo
422
423        self.ResultFileList = []
424        self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
425
426        self.FileBuildTargetList = []       # [(src, target string)]
427        self.BuildTargetList = []           # [target string]
428        self.PendingBuildTargetList = []    # [FileBuildRule objects]
429        self.CommonFileDependency = []
430        self.FileListMacros = {}
431        self.ListFileMacros = {}
432        self.ObjTargetDict = OrderedDict()
433        self.FileCache = {}
434        self.LibraryBuildCommandList = []
435        self.LibraryFileList = []
436        self.LibraryMakefileList = []
437        self.LibraryBuildDirectoryList = []
438        self.SystemLibraryList = []
439        self.Macros = OrderedDict()
440        self.Macros["OUTPUT_DIR"      ] = self._AutoGenObject.Macros["OUTPUT_DIR"]
441        self.Macros["DEBUG_DIR"       ] = self._AutoGenObject.Macros["DEBUG_DIR"]
442        self.Macros["MODULE_BUILD_DIR"] = self._AutoGenObject.Macros["MODULE_BUILD_DIR"]
443        self.Macros["BIN_DIR"         ] = self._AutoGenObject.Macros["BIN_DIR"]
444        self.Macros["BUILD_DIR"       ] = self._AutoGenObject.Macros["BUILD_DIR"]
445        self.Macros["WORKSPACE"       ] = self._AutoGenObject.Macros["WORKSPACE"]
446        self.Macros["FFS_OUTPUT_DIR"  ] = self._AutoGenObject.Macros["FFS_OUTPUT_DIR"]
447        self.GenFfsList                 = ModuleAutoGen.GenFfsList
448        self.MacroList = ['FFS_OUTPUT_DIR', 'MODULE_GUID', 'OUTPUT_DIR']
449        self.FfsOutputFileList = []
450
451    # Compose a dict object containing information used to do replacement in template
452    @property
453    def _TemplateDict(self):
454        if self._FileType not in self._SEP_:
455            EdkLogger.error("build", PARAMETER_INVALID, "Invalid Makefile type [%s]" % self._FileType,
456                            ExtraData="[%s]" % str(self._AutoGenObject))
457        MyAgo = self._AutoGenObject
458        Separator = self._SEP_[self._FileType]
459
460        # break build if no source files and binary files are found
461        if len(MyAgo.SourceFileList) == 0 and len(MyAgo.BinaryFileList) == 0:
462            EdkLogger.error("build", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]"
463                            % (MyAgo.BuildTarget, MyAgo.ToolChain, MyAgo.Arch),
464                            ExtraData="[%s]" % str(MyAgo))
465
466        # convert dependent libraries to build command
467        self.ProcessDependentLibrary()
468        if len(MyAgo.Module.ModuleEntryPointList) > 0:
469            ModuleEntryPoint = MyAgo.Module.ModuleEntryPointList[0]
470        else:
471            ModuleEntryPoint = "_ModuleEntryPoint"
472
473        ArchEntryPoint = ModuleEntryPoint
474
475        if MyAgo.Arch == "EBC":
476            # EBC compiler always use "EfiStart" as entry point. Only applies to EdkII modules
477            ImageEntryPoint = "EfiStart"
478        else:
479            # EdkII modules always use "_ModuleEntryPoint" as entry point
480            ImageEntryPoint = "_ModuleEntryPoint"
481
482        for k, v in MyAgo.Module.Defines.items():
483            if k not in MyAgo.Macros:
484                MyAgo.Macros[k] = v
485
486        if 'MODULE_ENTRY_POINT' not in MyAgo.Macros:
487            MyAgo.Macros['MODULE_ENTRY_POINT'] = ModuleEntryPoint
488        if 'ARCH_ENTRY_POINT' not in MyAgo.Macros:
489            MyAgo.Macros['ARCH_ENTRY_POINT'] = ArchEntryPoint
490        if 'IMAGE_ENTRY_POINT' not in MyAgo.Macros:
491            MyAgo.Macros['IMAGE_ENTRY_POINT'] = ImageEntryPoint
492
493        PCI_COMPRESS_Flag = False
494        for k, v in MyAgo.Module.Defines.items():
495            if 'PCI_COMPRESS' == k and 'TRUE' == v:
496                PCI_COMPRESS_Flag = True
497
498        # tools definitions
499        ToolsDef = []
500        IncPrefix = self._INC_FLAG_[MyAgo.ToolChainFamily]
501        for Tool in MyAgo.BuildOption:
502            for Attr in MyAgo.BuildOption[Tool]:
503                Value = MyAgo.BuildOption[Tool][Attr]
504                if Attr == "FAMILY":
505                    continue
506                elif Attr == "PATH":
507                    ToolsDef.append("%s = %s" % (Tool, Value))
508                else:
509                    # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
510                    if Tool == "MAKE":
511                        continue
512                    # Remove duplicated include path, if any
513                    if Attr == "FLAGS":
514                        Value = RemoveDupOption(Value, IncPrefix, MyAgo.IncludePathList)
515                        if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and Tool == 'CC' and '/GM' in Value:
516                            Value = Value.replace(' /MP', '')
517                            MyAgo.BuildOption[Tool][Attr] = Value
518                        if Tool == "OPTROM" and PCI_COMPRESS_Flag:
519                            ValueList = Value.split()
520                            if ValueList:
521                                for i, v in enumerate(ValueList):
522                                    if '-e' == v:
523                                        ValueList[i] = '-ec'
524                                Value = ' '.join(ValueList)
525
526                    ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
527            ToolsDef.append("")
528
529        # generate the Response file and Response flag
530        RespDict = self.CommandExceedLimit()
531        RespFileList = os.path.join(MyAgo.OutputDir, 'respfilelist.txt')
532        if RespDict:
533            RespFileListContent = ''
534            for Resp in RespDict:
535                RespFile = os.path.join(MyAgo.OutputDir, str(Resp).lower() + '.txt')
536                StrList = RespDict[Resp].split(' ')
537                UnexpandMacro = []
538                NewStr = []
539                for Str in StrList:
540                    if '$' in Str:
541                        UnexpandMacro.append(Str)
542                    else:
543                        NewStr.append(Str)
544                UnexpandMacroStr = ' '.join(UnexpandMacro)
545                NewRespStr = ' '.join(NewStr)
546                SaveFileOnChange(RespFile, NewRespStr, False)
547                ToolsDef.append("%s = %s" % (Resp, UnexpandMacroStr + ' @' + RespFile))
548                RespFileListContent += '@' + RespFile + TAB_LINE_BREAK
549                RespFileListContent += NewRespStr + TAB_LINE_BREAK
550            SaveFileOnChange(RespFileList, RespFileListContent, False)
551        else:
552            if os.path.exists(RespFileList):
553                os.remove(RespFileList)
554
555        # convert source files and binary files to build targets
556        self.ResultFileList = [str(T.Target) for T in MyAgo.CodaTargetList]
557        if len(self.ResultFileList) == 0 and len(MyAgo.SourceFileList) != 0:
558            EdkLogger.error("build", AUTOGEN_ERROR, "Nothing to build",
559                            ExtraData="[%s]" % str(MyAgo))
560
561        self.ProcessBuildTargetList()
562        self.ParserGenerateFfsCmd()
563
564        # Generate macros used to represent input files
565        FileMacroList = [] # macro name = file list
566        for FileListMacro in self.FileListMacros:
567            FileMacro = self._FILE_MACRO_TEMPLATE.Replace(
568                                                    {
569                                                        "macro_name"  : FileListMacro,
570                                                        "source_file" : self.FileListMacros[FileListMacro]
571                                                    }
572                                                    )
573            FileMacroList.append(FileMacro)
574
575        # INC_LIST is special
576        FileMacro = ""
577        IncludePathList = []
578        for P in  MyAgo.IncludePathList:
579            IncludePathList.append(IncPrefix + self.PlaceMacro(P, self.Macros))
580            if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:
581                self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix + P)
582        FileMacro += self._FILE_MACRO_TEMPLATE.Replace(
583                                                {
584                                                    "macro_name"   : "INC",
585                                                    "source_file" : IncludePathList
586                                                }
587                                                )
588        FileMacroList.append(FileMacro)
589        # Add support when compiling .nasm source files
590        for File in self.FileCache.keys():
591            if not str(File).endswith('.nasm'):
592                continue
593            IncludePathList = []
594            for P in  MyAgo.IncludePathList:
595                IncludePath = self._INC_FLAG_['NASM'] + self.PlaceMacro(P, self.Macros)
596                if IncludePath.endswith(os.sep):
597                    IncludePath = IncludePath.rstrip(os.sep)
598                # When compiling .nasm files, need to add a literal backslash at each path
599                # To specify a literal backslash at the end of the line, precede it with a caret (^)
600                if P == MyAgo.IncludePathList[-1] and os.sep == '\\':
601                    IncludePath = ''.join([IncludePath, '^', os.sep])
602                else:
603                    IncludePath = os.path.join(IncludePath, '')
604                IncludePathList.append(IncludePath)
605            FileMacroList.append(self._FILE_MACRO_TEMPLATE.Replace({"macro_name": "NASM_INC", "source_file": IncludePathList}))
606            break
607
608        # Generate macros used to represent files containing list of input files
609        for ListFileMacro in self.ListFileMacros:
610            ListFileName = os.path.join(MyAgo.OutputDir, "%s.lst" % ListFileMacro.lower()[:len(ListFileMacro) - 5])
611            FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))
612            SaveFileOnChange(
613                ListFileName,
614                "\n".join(self.ListFileMacros[ListFileMacro]),
615                False
616                )
617
618        # Generate objlist used to create .obj file
619        for Type in self.ObjTargetDict:
620            NewLine = ' '.join(list(self.ObjTargetDict[Type]))
621            FileMacroList.append("OBJLIST_%s = %s" % (list(self.ObjTargetDict.keys()).index(Type), NewLine))
622
623        BcTargetList = []
624
625        MakefileName = self._FILE_NAME_[self._FileType]
626        LibraryMakeCommandList = []
627        for D in self.LibraryBuildDirectoryList:
628            Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)}
629            LibraryMakeCommandList.append(Command)
630
631        package_rel_dir = MyAgo.SourceDir
632        current_dir = self.Macros["WORKSPACE"]
633        found = False
634        while not found and os.sep in package_rel_dir:
635            index = package_rel_dir.index(os.sep)
636            current_dir = mws.join(current_dir, package_rel_dir[:index])
637            if os.path.exists(current_dir):
638                for fl in os.listdir(current_dir):
639                    if fl.endswith('.dec'):
640                        found = True
641                        break
642            package_rel_dir = package_rel_dir[index + 1:]
643
644        MakefileTemplateDict = {
645            "makefile_header"           : self._FILE_HEADER_[self._FileType],
646            "makefile_path"             : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
647            "makefile_name"             : MakefileName,
648            "platform_name"             : self.PlatformInfo.Name,
649            "platform_guid"             : self.PlatformInfo.Guid,
650            "platform_version"          : self.PlatformInfo.Version,
651            "platform_relative_directory": self.PlatformInfo.SourceDir,
652            "platform_output_directory" : self.PlatformInfo.OutputDir,
653            "ffs_output_directory"      : MyAgo.Macros["FFS_OUTPUT_DIR"],
654            "platform_dir"              : MyAgo.Macros["PLATFORM_DIR"],
655
656            "module_name"               : MyAgo.Name,
657            "module_guid"               : MyAgo.Guid,
658            "module_name_guid"          : MyAgo.UniqueBaseName,
659            "module_version"            : MyAgo.Version,
660            "module_type"               : MyAgo.ModuleType,
661            "module_file"               : MyAgo.MetaFile.Name,
662            "module_file_base_name"     : MyAgo.MetaFile.BaseName,
663            "module_relative_directory" : MyAgo.SourceDir,
664            "module_dir"                : mws.join (self.Macros["WORKSPACE"], MyAgo.SourceDir),
665            "package_relative_directory": package_rel_dir,
666            "module_extra_defines"      : ["%s = %s" % (k, v) for k, v in MyAgo.Module.Defines.items()],
667
668            "architecture"              : MyAgo.Arch,
669            "toolchain_tag"             : MyAgo.ToolChain,
670            "build_target"              : MyAgo.BuildTarget,
671
672            "platform_build_directory"  : self.PlatformInfo.BuildDir,
673            "module_build_directory"    : MyAgo.BuildDir,
674            "module_output_directory"   : MyAgo.OutputDir,
675            "module_debug_directory"    : MyAgo.DebugDir,
676
677            "separator"                 : Separator,
678            "module_tool_definitions"   : ToolsDef,
679
680            "shell_command_code"        : list(self._SHELL_CMD_[self._FileType].keys()),
681            "shell_command"             : list(self._SHELL_CMD_[self._FileType].values()),
682
683            "module_entry_point"        : ModuleEntryPoint,
684            "image_entry_point"         : ImageEntryPoint,
685            "arch_entry_point"          : ArchEntryPoint,
686            "remaining_build_target"    : self.ResultFileList,
687            "common_dependency_file"    : self.CommonFileDependency,
688            "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
689            "clean_command"             : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]),
690            "cleanall_command"          : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]),
691            "dependent_library_build_directory" : self.LibraryBuildDirectoryList,
692            "library_build_command"     : LibraryMakeCommandList,
693            "file_macro"                : FileMacroList,
694            "file_build_target"         : self.BuildTargetList,
695            "backward_compatible_target": BcTargetList,
696        }
697
698        return MakefileTemplateDict
699
700    def ParserGenerateFfsCmd(self):
701        #Add Ffs cmd to self.BuildTargetList
702        OutputFile = ''
703        DepsFileList = []
704
705        for Cmd in self.GenFfsList:
706            if Cmd[2]:
707                for CopyCmd in Cmd[2]:
708                    Src, Dst = CopyCmd
709                    Src = self.ReplaceMacro(Src)
710                    Dst = self.ReplaceMacro(Dst)
711                    if Dst not in self.ResultFileList:
712                        self.ResultFileList.append(Dst)
713                    if '%s :' %(Dst) not in self.BuildTargetList:
714                        self.BuildTargetList.append("%s :" %(Dst))
715                        self.BuildTargetList.append('\t' + self._CP_TEMPLATE_[self._FileType] %{'Src': Src, 'Dst': Dst})
716
717            FfsCmdList = Cmd[0]
718            for index, Str in enumerate(FfsCmdList):
719                if '-o' == Str:
720                    OutputFile = FfsCmdList[index + 1]
721                if '-i' == Str or "-oi" == Str:
722                    if DepsFileList == []:
723                        DepsFileList = [FfsCmdList[index + 1]]
724                    else:
725                        DepsFileList.append(FfsCmdList[index + 1])
726            DepsFileString = ' '.join(DepsFileList).strip()
727            if DepsFileString == '':
728                continue
729            OutputFile = self.ReplaceMacro(OutputFile)
730            self.ResultFileList.append(OutputFile)
731            DepsFileString = self.ReplaceMacro(DepsFileString)
732            self.BuildTargetList.append('%s : %s' % (OutputFile, DepsFileString))
733            CmdString = ' '.join(FfsCmdList).strip()
734            CmdString = self.ReplaceMacro(CmdString)
735            self.BuildTargetList.append('\t%s' % CmdString)
736
737            self.ParseSecCmd(DepsFileList, Cmd[1])
738            for SecOutputFile, SecDepsFile, SecCmd in self.FfsOutputFileList :
739                self.BuildTargetList.append('%s : %s' % (self.ReplaceMacro(SecOutputFile), self.ReplaceMacro(SecDepsFile)))
740                self.BuildTargetList.append('\t%s' % self.ReplaceMacro(SecCmd))
741            self.FfsOutputFileList = []
742
743    def ParseSecCmd(self, OutputFileList, CmdTuple):
744        for OutputFile in OutputFileList:
745            for SecCmdStr in CmdTuple:
746                SecDepsFileList = []
747                SecCmdList = SecCmdStr.split()
748                CmdName = SecCmdList[0]
749                for index, CmdItem in enumerate(SecCmdList):
750                    if '-o' == CmdItem and OutputFile == SecCmdList[index + 1]:
751                        index = index + 1
752                        while index + 1 < len(SecCmdList):
753                            if not SecCmdList[index+1].startswith('-'):
754                                SecDepsFileList.append(SecCmdList[index + 1])
755                            index = index + 1
756                        if CmdName == 'Trim':
757                            SecDepsFileList.append(os.path.join('$(DEBUG_DIR)', os.path.basename(OutputFile).replace('offset', 'efi')))
758                        if OutputFile.endswith('.ui') or OutputFile.endswith('.ver'):
759                            SecDepsFileList.append(os.path.join('$(MODULE_DIR)', '$(MODULE_FILE)'))
760                        self.FfsOutputFileList.append((OutputFile, ' '.join(SecDepsFileList), SecCmdStr))
761                        if len(SecDepsFileList) > 0:
762                            self.ParseSecCmd(SecDepsFileList, CmdTuple)
763                        break
764                    else:
765                        continue
766
767    def ReplaceMacro(self, str):
768        for Macro in self.MacroList:
769            if self._AutoGenObject.Macros[Macro] and self._AutoGenObject.Macros[Macro] in str:
770                str = str.replace(self._AutoGenObject.Macros[Macro], '$(' + Macro + ')')
771        return str
772
773    def CommandExceedLimit(self):
774        FlagDict = {
775                    'CC'    :  { 'Macro' : '$(CC_FLAGS)',    'Value' : False},
776                    'PP'    :  { 'Macro' : '$(PP_FLAGS)',    'Value' : False},
777                    'APP'   :  { 'Macro' : '$(APP_FLAGS)',   'Value' : False},
778                    'ASLPP' :  { 'Macro' : '$(ASLPP_FLAGS)', 'Value' : False},
779                    'VFRPP' :  { 'Macro' : '$(VFRPP_FLAGS)', 'Value' : False},
780                    'ASM'   :  { 'Macro' : '$(ASM_FLAGS)',   'Value' : False},
781                    'ASLCC' :  { 'Macro' : '$(ASLCC_FLAGS)', 'Value' : False},
782                   }
783
784        RespDict = {}
785        FileTypeList = []
786        IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
787
788        # base on the source files to decide the file type
789        for File in self._AutoGenObject.SourceFileList:
790            for type in self._AutoGenObject.FileTypes:
791                if File in self._AutoGenObject.FileTypes[type]:
792                    if type not in FileTypeList:
793                        FileTypeList.append(type)
794
795        # calculate the command-line length
796        if FileTypeList:
797            for type in FileTypeList:
798                BuildTargets = self._AutoGenObject.BuildRules[type].BuildTargets
799                for Target in BuildTargets:
800                    CommandList = BuildTargets[Target].Commands
801                    for SingleCommand in CommandList:
802                        Tool = ''
803                        SingleCommandLength = len(SingleCommand)
804                        SingleCommandList = SingleCommand.split()
805                        if len(SingleCommandList) > 0:
806                            for Flag in FlagDict:
807                                if '$('+ Flag +')' in SingleCommandList[0]:
808                                    Tool = Flag
809                                    break
810                        if Tool:
811                            if 'PATH' not in self._AutoGenObject.BuildOption[Tool]:
812                                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))
813                            SingleCommandLength += len(self._AutoGenObject.BuildOption[Tool]['PATH'])
814                            for item in SingleCommandList[1:]:
815                                if FlagDict[Tool]['Macro'] in item:
816                                    if 'FLAGS' not in self._AutoGenObject.BuildOption[Tool]:
817                                        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))
818                                    Str = self._AutoGenObject.BuildOption[Tool]['FLAGS']
819                                    for Option in self._AutoGenObject.BuildOption:
820                                        for Attr in self._AutoGenObject.BuildOption[Option]:
821                                            if Str.find(Option + '_' + Attr) != -1:
822                                                Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
823                                    while(Str.find('$(') != -1):
824                                        for macro in self._AutoGenObject.Macros:
825                                            MacroName = '$('+ macro + ')'
826                                            if (Str.find(MacroName) != -1):
827                                                Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
828                                                break
829                                        else:
830                                            break
831                                    SingleCommandLength += len(Str)
832                                elif '$(INC)' in item:
833                                    SingleCommandLength += self._AutoGenObject.IncludePathLength + len(IncPrefix) * len(self._AutoGenObject.IncludePathList)
834                                elif item.find('$(') != -1:
835                                    Str = item
836                                    for Option in self._AutoGenObject.BuildOption:
837                                        for Attr in self._AutoGenObject.BuildOption[Option]:
838                                            if Str.find(Option + '_' + Attr) != -1:
839                                                Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
840                                    while(Str.find('$(') != -1):
841                                        for macro in self._AutoGenObject.Macros:
842                                            MacroName = '$('+ macro + ')'
843                                            if (Str.find(MacroName) != -1):
844                                                Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
845                                                break
846                                        else:
847                                            break
848                                    SingleCommandLength += len(Str)
849
850                            if SingleCommandLength > GlobalData.gCommandMaxLength:
851                                FlagDict[Tool]['Value'] = True
852
853                # generate the response file content by combine the FLAGS and INC
854                for Flag in FlagDict:
855                    if FlagDict[Flag]['Value']:
856                        Key = Flag + '_RESP'
857                        RespMacro = FlagDict[Flag]['Macro'].replace('FLAGS', 'RESP')
858                        Value = self._AutoGenObject.BuildOption[Flag]['FLAGS']
859                        for inc in self._AutoGenObject.IncludePathList:
860                            Value += ' ' + IncPrefix + inc
861                        for Option in self._AutoGenObject.BuildOption:
862                            for Attr in self._AutoGenObject.BuildOption[Option]:
863                                if Value.find(Option + '_' + Attr) != -1:
864                                    Value = Value.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
865                        while (Value.find('$(') != -1):
866                            for macro in self._AutoGenObject.Macros:
867                                MacroName = '$('+ macro + ')'
868                                if (Value.find(MacroName) != -1):
869                                    Value = Value.replace(MacroName, self._AutoGenObject.Macros[macro])
870                                    break
871                            else:
872                                break
873
874                        if self._AutoGenObject.ToolChainFamily == 'GCC':
875                            RespDict[Key] = Value.replace('\\', '/')
876                        else:
877                            RespDict[Key] = Value
878                        for Target in BuildTargets:
879                            for i, SingleCommand in enumerate(BuildTargets[Target].Commands):
880                                if FlagDict[Flag]['Macro'] in SingleCommand:
881                                    BuildTargets[Target].Commands[i] = SingleCommand.replace('$(INC)', '').replace(FlagDict[Flag]['Macro'], RespMacro)
882        return RespDict
883
884    def ProcessBuildTargetList(self):
885        #
886        # Search dependency file list for each source file
887        #
888        ForceIncludedFile = []
889        for File in self._AutoGenObject.AutoGenFileList:
890            if File.Ext == '.h':
891                ForceIncludedFile.append(File)
892        SourceFileList = []
893        OutPutFileList = []
894        for Target in self._AutoGenObject.IntroTargetList:
895            SourceFileList.extend(Target.Inputs)
896            OutPutFileList.extend(Target.Outputs)
897
898        if OutPutFileList:
899            for Item in OutPutFileList:
900                if Item in SourceFileList:
901                    SourceFileList.remove(Item)
902
903        FileDependencyDict = self.GetFileDependency(
904                                    SourceFileList,
905                                    ForceIncludedFile,
906                                    self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList
907                                    )
908        DepSet = None
909        for File,Dependency in FileDependencyDict.items():
910            if not Dependency:
911                FileDependencyDict[File] = ['$(FORCE_REBUILD)']
912                continue
913
914            self._AutoGenObject.AutoGenDepSet |= set(Dependency)
915
916            # skip non-C files
917            if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
918                continue
919            elif DepSet is None:
920                DepSet = set(Dependency)
921            else:
922                DepSet &= set(Dependency)
923        # in case nothing in SourceFileList
924        if DepSet is None:
925            DepSet = set()
926        #
927        # Extract common files list in the dependency files
928        #
929        for File in DepSet:
930            self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros))
931
932        CmdSumDict = {}
933        CmdTargetDict = {}
934        CmdCppDict = {}
935        DependencyDict = FileDependencyDict.copy()
936        for File in FileDependencyDict:
937            # skip non-C files
938            if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
939                continue
940            NewDepSet = set(FileDependencyDict[File])
941            NewDepSet -= DepSet
942            FileDependencyDict[File] = ["$(COMMON_DEPS)"] + list(NewDepSet)
943            DependencyDict[File] = list(NewDepSet)
944
945        # Convert target description object to target string in makefile
946        if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and TAB_C_CODE_FILE in self._AutoGenObject.Targets:
947            for T in self._AutoGenObject.Targets[TAB_C_CODE_FILE]:
948                NewFile = self.PlaceMacro(str(T), self.Macros)
949                if not self.ObjTargetDict.get(T.Target.SubDir):
950                    self.ObjTargetDict[T.Target.SubDir] = set()
951                self.ObjTargetDict[T.Target.SubDir].add(NewFile)
952        for Type in self._AutoGenObject.Targets:
953            for T in self._AutoGenObject.Targets[Type]:
954                # Generate related macros if needed
955                if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
956                    self.FileListMacros[T.FileListMacro] = []
957                if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:
958                    self.ListFileMacros[T.ListFileMacro] = []
959                if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:
960                    self.ListFileMacros[T.IncListFileMacro] = []
961
962                Deps = []
963                CCodeDeps = []
964                # Add force-dependencies
965                for Dep in T.Dependencies:
966                    Deps.append(self.PlaceMacro(str(Dep), self.Macros))
967                    if Dep != '$(MAKE_FILE)':
968                        CCodeDeps.append(self.PlaceMacro(str(Dep), self.Macros))
969                # Add inclusion-dependencies
970                if len(T.Inputs) == 1 and T.Inputs[0] in FileDependencyDict:
971                    for F in FileDependencyDict[T.Inputs[0]]:
972                        Deps.append(self.PlaceMacro(str(F), self.Macros))
973                # Add source-dependencies
974                for F in T.Inputs:
975                    NewFile = self.PlaceMacro(str(F), self.Macros)
976                    # In order to use file list macro as dependency
977                    if T.GenListFile:
978                        # gnu tools need forward slash path separator, even on Windows
979                        self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/'))
980                        self.FileListMacros[T.FileListMacro].append(NewFile)
981                    elif T.GenFileListMacro:
982                        self.FileListMacros[T.FileListMacro].append(NewFile)
983                    else:
984                        Deps.append(NewFile)
985
986                # Use file list macro as dependency
987                if T.GenFileListMacro:
988                    Deps.append("$(%s)" % T.FileListMacro)
989                    if Type in [TAB_OBJECT_FILE, TAB_STATIC_LIBRARY]:
990                        Deps.append("$(%s)" % T.ListFileMacro)
991
992                if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and Type == TAB_C_CODE_FILE:
993                    T, CmdTarget, CmdTargetDict, CmdCppDict = self.ParserCCodeFile(T, Type, CmdSumDict, CmdTargetDict, CmdCppDict, DependencyDict)
994                    TargetDict = {"target": self.PlaceMacro(T.Target.Path, self.Macros), "cmd": "\n\t".join(T.Commands),"deps": CCodeDeps}
995                    CmdLine = self._BUILD_TARGET_TEMPLATE.Replace(TargetDict).rstrip().replace('\t$(OBJLIST', '$(OBJLIST')
996                    if T.Commands:
997                        CmdLine = '%s%s' %(CmdLine, TAB_LINE_BREAK)
998                    if CCodeDeps or CmdLine:
999                        self.BuildTargetList.append(CmdLine)
1000                else:
1001                    TargetDict = {"target": self.PlaceMacro(T.Target.Path, self.Macros), "cmd": "\n\t".join(T.Commands),"deps": Deps}
1002                    self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
1003
1004    def ParserCCodeFile(self, T, Type, CmdSumDict, CmdTargetDict, CmdCppDict, DependencyDict):
1005        if not CmdSumDict:
1006            for item in self._AutoGenObject.Targets[Type]:
1007                CmdSumDict[item.Target.SubDir] = item.Target.BaseName
1008                for CppPath in item.Inputs:
1009                    Path = self.PlaceMacro(CppPath.Path, self.Macros)
1010                    if CmdCppDict.get(item.Target.SubDir):
1011                        CmdCppDict[item.Target.SubDir].append(Path)
1012                    else:
1013                        CmdCppDict[item.Target.SubDir] = ['$(MAKE_FILE)', Path]
1014                    if CppPath.Path in DependencyDict:
1015                        for Temp in DependencyDict[CppPath.Path]:
1016                            try:
1017                                Path = self.PlaceMacro(Temp.Path, self.Macros)
1018                            except:
1019                                continue
1020                            if Path not in (self.CommonFileDependency + CmdCppDict[item.Target.SubDir]):
1021                                CmdCppDict[item.Target.SubDir].append(Path)
1022        if T.Commands:
1023            CommandList = T.Commands[:]
1024            for Item in CommandList[:]:
1025                SingleCommandList = Item.split()
1026                if len(SingleCommandList) > 0 and self.CheckCCCmd(SingleCommandList):
1027                    for Temp in SingleCommandList:
1028                        if Temp.startswith('/Fo'):
1029                            CmdSign = '%s%s' % (Temp.rsplit(TAB_SLASH, 1)[0], TAB_SLASH)
1030                            break
1031                    else: continue
1032                    if CmdSign not in list(CmdTargetDict.keys()):
1033                        CmdTargetDict[CmdSign] = Item.replace(Temp, CmdSign)
1034                    else:
1035                        CmdTargetDict[CmdSign] = "%s %s" % (CmdTargetDict[CmdSign], SingleCommandList[-1])
1036                    Index = CommandList.index(Item)
1037                    CommandList.pop(Index)
1038                    if SingleCommandList[-1].endswith("%s%s.c" % (TAB_SLASH, CmdSumDict[CmdSign.lstrip('/Fo').rsplit(TAB_SLASH, 1)[0]])):
1039                        Cpplist = CmdCppDict[T.Target.SubDir]
1040                        Cpplist.insert(0, '$(OBJLIST_%d): $(COMMON_DEPS)' % list(self.ObjTargetDict.keys()).index(T.Target.SubDir))
1041                        T.Commands[Index] = '%s\n\t%s' % (' \\\n\t'.join(Cpplist), CmdTargetDict[CmdSign])
1042                    else:
1043                        T.Commands.pop(Index)
1044        return T, CmdSumDict, CmdTargetDict, CmdCppDict
1045
1046    def CheckCCCmd(self, CommandList):
1047        for cmd in CommandList:
1048            if '$(CC)' in cmd:
1049                return True
1050        return False
1051    ## For creating makefile targets for dependent libraries
1052    def ProcessDependentLibrary(self):
1053        for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1054            if not LibraryAutoGen.IsBinaryModule and not LibraryAutoGen.CanSkipbyHash():
1055                self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
1056
1057    ## Return a list containing source file's dependencies
1058    #
1059    #   @param      FileList        The list of source files
1060    #   @param      ForceInculeList The list of files which will be included forcely
1061    #   @param      SearchPathList  The list of search path
1062    #
1063    #   @retval     dict            The mapping between source file path and its dependencies
1064    #
1065    def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
1066        Dependency = {}
1067        for F in FileList:
1068            Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)
1069        return Dependency
1070
1071    ## Find dependencies for one source file
1072    #
1073    #  By searching recursively "#include" directive in file, find out all the
1074    #  files needed by given source file. The dependencies will be only searched
1075    #  in given search path list.
1076    #
1077    #   @param      File            The source file
1078    #   @param      ForceInculeList The list of files which will be included forcely
1079    #   @param      SearchPathList  The list of search path
1080    #
1081    #   @retval     list            The list of files the given source file depends on
1082    #
1083    def GetDependencyList(self, File, ForceList, SearchPathList):
1084        EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File)
1085        FileStack = [File] + ForceList
1086        DependencySet = set()
1087
1088        if self._AutoGenObject.Arch not in gDependencyDatabase:
1089            gDependencyDatabase[self._AutoGenObject.Arch] = {}
1090        DepDb = gDependencyDatabase[self._AutoGenObject.Arch]
1091
1092        while len(FileStack) > 0:
1093            F = FileStack.pop()
1094
1095            FullPathDependList = []
1096            if F in self.FileCache:
1097                for CacheFile in self.FileCache[F]:
1098                    FullPathDependList.append(CacheFile)
1099                    if CacheFile not in DependencySet:
1100                        FileStack.append(CacheFile)
1101                DependencySet.update(FullPathDependList)
1102                continue
1103
1104            CurrentFileDependencyList = []
1105            if F in DepDb:
1106                CurrentFileDependencyList = DepDb[F]
1107            else:
1108                try:
1109                    Fd = open(F.Path, 'rb')
1110                    FileContent = Fd.read()
1111                    Fd.close()
1112                except BaseException as X:
1113                    EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path + "\n\t" + str(X))
1114                if len(FileContent) == 0:
1115                    continue
1116                try:
1117                    if FileContent[0] == 0xff or FileContent[0] == 0xfe:
1118                        FileContent = FileContent.decode('utf-16')
1119                    else:
1120                        FileContent = FileContent.decode()
1121                except:
1122                    # The file is not txt file. for example .mcb file
1123                    continue
1124                IncludedFileList = gIncludePattern.findall(FileContent)
1125
1126                for Inc in IncludedFileList:
1127                    Inc = Inc.strip()
1128                    # if there's macro used to reference header file, expand it
1129                    HeaderList = gMacroPattern.findall(Inc)
1130                    if len(HeaderList) == 1 and len(HeaderList[0]) == 2:
1131                        HeaderType = HeaderList[0][0]
1132                        HeaderKey = HeaderList[0][1]
1133                        if HeaderType in gIncludeMacroConversion:
1134                            Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey}
1135                        else:
1136                            # not known macro used in #include, always build the file by
1137                            # returning a empty dependency
1138                            self.FileCache[File] = []
1139                            return []
1140                    Inc = os.path.normpath(Inc)
1141                    CurrentFileDependencyList.append(Inc)
1142                DepDb[F] = CurrentFileDependencyList
1143
1144            CurrentFilePath = F.Dir
1145            PathList = [CurrentFilePath] + SearchPathList
1146            for Inc in CurrentFileDependencyList:
1147                for SearchPath in PathList:
1148                    FilePath = os.path.join(SearchPath, Inc)
1149                    if FilePath in gIsFileMap:
1150                        if not gIsFileMap[FilePath]:
1151                            continue
1152                    # If isfile is called too many times, the performance is slow down.
1153                    elif not os.path.isfile(FilePath):
1154                        gIsFileMap[FilePath] = False
1155                        continue
1156                    else:
1157                        gIsFileMap[FilePath] = True
1158                    FilePath = PathClass(FilePath)
1159                    FullPathDependList.append(FilePath)
1160                    if FilePath not in DependencySet:
1161                        FileStack.append(FilePath)
1162                    break
1163                else:
1164                    EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\
1165                                    "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList)))
1166
1167            self.FileCache[F] = FullPathDependList
1168            DependencySet.update(FullPathDependList)
1169
1170        DependencySet.update(ForceList)
1171        if File in DependencySet:
1172            DependencySet.remove(File)
1173        DependencyList = list(DependencySet)  # remove duplicate ones
1174
1175        return DependencyList
1176
1177## CustomMakefile class
1178#
1179#  This class encapsules makefie and its generation for module. It uses template to generate
1180#  the content of makefile. The content of makefile will be got from ModuleAutoGen object.
1181#
1182class CustomMakefile(BuildFile):
1183    ## template used to generate the makefile for module with custom makefile
1184    _TEMPLATE_ = TemplateString('''\
1185${makefile_header}
1186
1187#
1188# Platform Macro Definition
1189#
1190PLATFORM_NAME = ${platform_name}
1191PLATFORM_GUID = ${platform_guid}
1192PLATFORM_VERSION = ${platform_version}
1193PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
1194PLATFORM_DIR = ${platform_dir}
1195PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1196
1197#
1198# Module Macro Definition
1199#
1200MODULE_NAME = ${module_name}
1201MODULE_GUID = ${module_guid}
1202MODULE_NAME_GUID = ${module_name_guid}
1203MODULE_VERSION = ${module_version}
1204MODULE_TYPE = ${module_type}
1205MODULE_FILE = ${module_file}
1206MODULE_FILE_BASE_NAME = ${module_file_base_name}
1207BASE_NAME = $(MODULE_NAME)
1208MODULE_RELATIVE_DIR = ${module_relative_directory}
1209MODULE_DIR = ${module_dir}
1210
1211#
1212# Build Configuration Macro Definition
1213#
1214ARCH = ${architecture}
1215TOOLCHAIN = ${toolchain_tag}
1216TOOLCHAIN_TAG = ${toolchain_tag}
1217TARGET = ${build_target}
1218
1219#
1220# Build Directory Macro Definition
1221#
1222# PLATFORM_BUILD_DIR = ${platform_build_directory}
1223BUILD_DIR = ${platform_build_directory}
1224BIN_DIR = $(BUILD_DIR)${separator}${architecture}
1225LIB_DIR = $(BIN_DIR)
1226MODULE_BUILD_DIR = ${module_build_directory}
1227OUTPUT_DIR = ${module_output_directory}
1228DEBUG_DIR = ${module_debug_directory}
1229DEST_DIR_OUTPUT = $(OUTPUT_DIR)
1230DEST_DIR_DEBUG = $(DEBUG_DIR)
1231
1232#
1233# Tools definitions specific to this module
1234#
1235${BEGIN}${module_tool_definitions}
1236${END}
1237MAKE_FILE = ${makefile_path}
1238
1239#
1240# Shell Command Macro
1241#
1242${BEGIN}${shell_command_code} = ${shell_command}
1243${END}
1244
1245${custom_makefile_content}
1246
1247#
1248# Target used when called from platform makefile, which will bypass the build of dependent libraries
1249#
1250
1251pbuild: init all
1252
1253
1254#
1255# ModuleTarget
1256#
1257
1258mbuild: init all
1259
1260#
1261# Build Target used in multi-thread build mode, which no init target is needed
1262#
1263
1264tbuild: all
1265
1266#
1267# Initialization target: print build information and create necessary directories
1268#
1269init:
1270\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
1271${BEGIN}\t-@${create_directory_command}\n${END}\
1272
1273''')
1274
1275    ## Constructor of CustomMakefile
1276    #
1277    #   @param  ModuleAutoGen   Object of ModuleAutoGen class
1278    #
1279    def __init__(self, ModuleAutoGen):
1280        BuildFile.__init__(self, ModuleAutoGen)
1281        self.PlatformInfo = self._AutoGenObject.PlatformInfo
1282        self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
1283
1284    # Compose a dict object containing information used to do replacement in template
1285    @property
1286    def _TemplateDict(self):
1287        Separator = self._SEP_[self._FileType]
1288        MyAgo = self._AutoGenObject
1289        if self._FileType not in MyAgo.CustomMakefile:
1290            EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType,
1291                            ExtraData="[%s]" % str(MyAgo))
1292        MakefilePath = mws.join(
1293                                MyAgo.WorkspaceDir,
1294                                MyAgo.CustomMakefile[self._FileType]
1295                                )
1296        try:
1297            CustomMakefile = open(MakefilePath, 'r').read()
1298        except:
1299            EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(MyAgo),
1300                            ExtraData=MyAgo.CustomMakefile[self._FileType])
1301
1302        # tools definitions
1303        ToolsDef = []
1304        for Tool in MyAgo.BuildOption:
1305            # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
1306            if Tool == "MAKE":
1307                continue
1308            for Attr in MyAgo.BuildOption[Tool]:
1309                if Attr == "FAMILY":
1310                    continue
1311                elif Attr == "PATH":
1312                    ToolsDef.append("%s = %s" % (Tool, MyAgo.BuildOption[Tool][Attr]))
1313                else:
1314                    ToolsDef.append("%s_%s = %s" % (Tool, Attr, MyAgo.BuildOption[Tool][Attr]))
1315            ToolsDef.append("")
1316
1317        MakefileName = self._FILE_NAME_[self._FileType]
1318        MakefileTemplateDict = {
1319            "makefile_header"           : self._FILE_HEADER_[self._FileType],
1320            "makefile_path"             : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
1321            "platform_name"             : self.PlatformInfo.Name,
1322            "platform_guid"             : self.PlatformInfo.Guid,
1323            "platform_version"          : self.PlatformInfo.Version,
1324            "platform_relative_directory": self.PlatformInfo.SourceDir,
1325            "platform_output_directory" : self.PlatformInfo.OutputDir,
1326            "platform_dir"              : MyAgo.Macros["PLATFORM_DIR"],
1327
1328            "module_name"               : MyAgo.Name,
1329            "module_guid"               : MyAgo.Guid,
1330            "module_name_guid"          : MyAgo.UniqueBaseName,
1331            "module_version"            : MyAgo.Version,
1332            "module_type"               : MyAgo.ModuleType,
1333            "module_file"               : MyAgo.MetaFile,
1334            "module_file_base_name"     : MyAgo.MetaFile.BaseName,
1335            "module_relative_directory" : MyAgo.SourceDir,
1336            "module_dir"                : mws.join (MyAgo.WorkspaceDir, MyAgo.SourceDir),
1337
1338            "architecture"              : MyAgo.Arch,
1339            "toolchain_tag"             : MyAgo.ToolChain,
1340            "build_target"              : MyAgo.BuildTarget,
1341
1342            "platform_build_directory"  : self.PlatformInfo.BuildDir,
1343            "module_build_directory"    : MyAgo.BuildDir,
1344            "module_output_directory"   : MyAgo.OutputDir,
1345            "module_debug_directory"    : MyAgo.DebugDir,
1346
1347            "separator"                 : Separator,
1348            "module_tool_definitions"   : ToolsDef,
1349
1350            "shell_command_code"        : list(self._SHELL_CMD_[self._FileType].keys()),
1351            "shell_command"             : list(self._SHELL_CMD_[self._FileType].values()),
1352
1353            "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1354            "custom_makefile_content"   : CustomMakefile
1355        }
1356
1357        return MakefileTemplateDict
1358
1359## PlatformMakefile class
1360#
1361#  This class encapsules makefie and its generation for platform. It uses
1362# template to generate the content of makefile. The content of makefile will be
1363# got from PlatformAutoGen object.
1364#
1365class PlatformMakefile(BuildFile):
1366    ## template used to generate the makefile for platform
1367    _TEMPLATE_ = TemplateString('''\
1368${makefile_header}
1369
1370#
1371# Platform Macro Definition
1372#
1373PLATFORM_NAME = ${platform_name}
1374PLATFORM_GUID = ${platform_guid}
1375PLATFORM_VERSION = ${platform_version}
1376PLATFORM_FILE = ${platform_file}
1377PLATFORM_DIR = ${platform_dir}
1378PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1379
1380#
1381# Build Configuration Macro Definition
1382#
1383TOOLCHAIN = ${toolchain_tag}
1384TOOLCHAIN_TAG = ${toolchain_tag}
1385TARGET = ${build_target}
1386
1387#
1388# Build Directory Macro Definition
1389#
1390BUILD_DIR = ${platform_build_directory}
1391FV_DIR = ${platform_build_directory}${separator}FV
1392
1393#
1394# Shell Command Macro
1395#
1396${BEGIN}${shell_command_code} = ${shell_command}
1397${END}
1398
1399MAKE = ${make_path}
1400MAKE_FILE = ${makefile_path}
1401
1402#
1403# Default target
1404#
1405all: init build_libraries build_modules
1406
1407#
1408# Initialization target: print build information and create necessary directories
1409#
1410init:
1411\t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
1412\t${BEGIN}-@${create_directory_command}
1413\t${END}
1414#
1415# library build target
1416#
1417libraries: init build_libraries
1418
1419#
1420# module build target
1421#
1422modules: init build_libraries build_modules
1423
1424#
1425# Build all libraries:
1426#
1427build_libraries:
1428${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
1429${END}\t@cd $(BUILD_DIR)
1430
1431#
1432# Build all modules:
1433#
1434build_modules:
1435${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
1436${END}\t@cd $(BUILD_DIR)
1437
1438#
1439# Clean intermediate files
1440#
1441clean:
1442\t${BEGIN}-@${library_build_command} clean
1443\t${END}${BEGIN}-@${module_build_command} clean
1444\t${END}@cd $(BUILD_DIR)
1445
1446#
1447# Clean all generated files except to makefile
1448#
1449cleanall:
1450${BEGIN}\t${cleanall_command}
1451${END}
1452
1453#
1454# Clean all library files
1455#
1456cleanlib:
1457\t${BEGIN}-@${library_build_command} cleanall
1458\t${END}@cd $(BUILD_DIR)\n
1459''')
1460
1461    ## Constructor of PlatformMakefile
1462    #
1463    #   @param  ModuleAutoGen   Object of PlatformAutoGen class
1464    #
1465    def __init__(self, PlatformAutoGen):
1466        BuildFile.__init__(self, PlatformAutoGen)
1467        self.ModuleBuildCommandList = []
1468        self.ModuleMakefileList = []
1469        self.IntermediateDirectoryList = []
1470        self.ModuleBuildDirectoryList = []
1471        self.LibraryBuildDirectoryList = []
1472        self.LibraryMakeCommandList = []
1473
1474    # Compose a dict object containing information used to do replacement in template
1475    @property
1476    def _TemplateDict(self):
1477        Separator = self._SEP_[self._FileType]
1478
1479        MyAgo = self._AutoGenObject
1480        if "MAKE" not in MyAgo.ToolDefinition or "PATH" not in MyAgo.ToolDefinition["MAKE"]:
1481            EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
1482                            ExtraData="[%s]" % str(MyAgo))
1483
1484        self.IntermediateDirectoryList = ["$(BUILD_DIR)"]
1485        self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()
1486        self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()
1487
1488        MakefileName = self._FILE_NAME_[self._FileType]
1489        LibraryMakefileList = []
1490        LibraryMakeCommandList = []
1491        for D in self.LibraryBuildDirectoryList:
1492            D = self.PlaceMacro(D, {"BUILD_DIR":MyAgo.BuildDir})
1493            Makefile = os.path.join(D, MakefileName)
1494            Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
1495            LibraryMakefileList.append(Makefile)
1496            LibraryMakeCommandList.append(Command)
1497        self.LibraryMakeCommandList = LibraryMakeCommandList
1498
1499        ModuleMakefileList = []
1500        ModuleMakeCommandList = []
1501        for D in self.ModuleBuildDirectoryList:
1502            D = self.PlaceMacro(D, {"BUILD_DIR":MyAgo.BuildDir})
1503            Makefile = os.path.join(D, MakefileName)
1504            Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
1505            ModuleMakefileList.append(Makefile)
1506            ModuleMakeCommandList.append(Command)
1507
1508        MakefileTemplateDict = {
1509            "makefile_header"           : self._FILE_HEADER_[self._FileType],
1510            "makefile_path"             : os.path.join("$(BUILD_DIR)", MakefileName),
1511            "make_path"                 : MyAgo.ToolDefinition["MAKE"]["PATH"],
1512            "makefile_name"             : MakefileName,
1513            "platform_name"             : MyAgo.Name,
1514            "platform_guid"             : MyAgo.Guid,
1515            "platform_version"          : MyAgo.Version,
1516            "platform_file"             : MyAgo.MetaFile,
1517            "platform_relative_directory": MyAgo.SourceDir,
1518            "platform_output_directory" : MyAgo.OutputDir,
1519            "platform_build_directory"  : MyAgo.BuildDir,
1520            "platform_dir"              : MyAgo.Macros["PLATFORM_DIR"],
1521
1522            "toolchain_tag"             : MyAgo.ToolChain,
1523            "build_target"              : MyAgo.BuildTarget,
1524            "shell_command_code"        : list(self._SHELL_CMD_[self._FileType].keys()),
1525            "shell_command"             : list(self._SHELL_CMD_[self._FileType].values()),
1526            "build_architecture_list"   : MyAgo.Arch,
1527            "architecture"              : MyAgo.Arch,
1528            "separator"                 : Separator,
1529            "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1530            "cleanall_command"          : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1531            "library_makefile_list"     : LibraryMakefileList,
1532            "module_makefile_list"      : ModuleMakefileList,
1533            "library_build_command"     : LibraryMakeCommandList,
1534            "module_build_command"      : ModuleMakeCommandList,
1535        }
1536
1537        return MakefileTemplateDict
1538
1539    ## Get the root directory list for intermediate files of all modules build
1540    #
1541    #   @retval     list    The list of directory
1542    #
1543    def GetModuleBuildDirectoryList(self):
1544        DirList = []
1545        for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1546            if not ModuleAutoGen.IsBinaryModule:
1547                DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1548        return DirList
1549
1550    ## Get the root directory list for intermediate files of all libraries build
1551    #
1552    #   @retval     list    The list of directory
1553    #
1554    def GetLibraryBuildDirectoryList(self):
1555        DirList = []
1556        for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1557            if not LibraryAutoGen.IsBinaryModule and not LibraryAutoGen.CanSkipbyHash():
1558                DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1559        return DirList
1560
1561## TopLevelMakefile class
1562#
1563#  This class encapsules makefie and its generation for entrance makefile. It
1564# uses template to generate the content of makefile. The content of makefile
1565# will be got from WorkspaceAutoGen object.
1566#
1567class TopLevelMakefile(BuildFile):
1568    ## template used to generate toplevel makefile
1569    _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}''')
1570
1571    ## Constructor of TopLevelMakefile
1572    #
1573    #   @param  Workspace   Object of WorkspaceAutoGen class
1574    #
1575    def __init__(self, Workspace):
1576        BuildFile.__init__(self, Workspace)
1577        self.IntermediateDirectoryList = []
1578
1579    # Compose a dict object containing information used to do replacement in template
1580    @property
1581    def _TemplateDict(self):
1582        Separator = self._SEP_[self._FileType]
1583
1584        # any platform autogen object is ok because we just need common information
1585        MyAgo = self._AutoGenObject
1586
1587        if "MAKE" not in MyAgo.ToolDefinition or "PATH" not in MyAgo.ToolDefinition["MAKE"]:
1588            EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
1589                            ExtraData="[%s]" % str(MyAgo))
1590
1591        for Arch in MyAgo.ArchList:
1592            self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch]))
1593        self.IntermediateDirectoryList.append("$(FV_DIR)")
1594
1595        # TRICK: for not generating GenFds call in makefile if no FDF file
1596        MacroList = []
1597        if MyAgo.FdfFile is not None and MyAgo.FdfFile != "":
1598            FdfFileList = [MyAgo.FdfFile]
1599            # macros passed to GenFds
1600            MacroDict = {}
1601            MacroDict.update(GlobalData.gGlobalDefines)
1602            MacroDict.update(GlobalData.gCommandLineDefines)
1603            for MacroName in MacroDict:
1604                if MacroDict[MacroName] != "":
1605                    MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))
1606                else:
1607                    MacroList.append('"%s"' % MacroName)
1608        else:
1609            FdfFileList = []
1610
1611        # pass extra common options to external program called in makefile, currently GenFds.exe
1612        ExtraOption = ''
1613        LogLevel = EdkLogger.GetLevel()
1614        if LogLevel == EdkLogger.VERBOSE:
1615            ExtraOption += " -v"
1616        elif LogLevel <= EdkLogger.DEBUG_9:
1617            ExtraOption += " -d %d" % (LogLevel - 1)
1618        elif LogLevel == EdkLogger.QUIET:
1619            ExtraOption += " -q"
1620
1621        if GlobalData.gCaseInsensitive:
1622            ExtraOption += " -c"
1623        if GlobalData.gEnableGenfdsMultiThread:
1624            ExtraOption += " --genfds-multi-thread"
1625        if GlobalData.gIgnoreSource:
1626            ExtraOption += " --ignore-sources"
1627
1628        for pcd in GlobalData.BuildOptionPcd:
1629            if pcd[2]:
1630                pcdname = '.'.join(pcd[0:3])
1631            else:
1632                pcdname = '.'.join(pcd[0:2])
1633            if pcd[3].startswith('{'):
1634                ExtraOption += " --pcd " + pcdname + '=' + 'H' + '"' + pcd[3] + '"'
1635            else:
1636                ExtraOption += " --pcd " + pcdname + '=' + pcd[3]
1637
1638        MakefileName = self._FILE_NAME_[self._FileType]
1639        SubBuildCommandList = []
1640        for A in MyAgo.ArchList:
1641            Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)}
1642            SubBuildCommandList.append(Command)
1643
1644        MakefileTemplateDict = {
1645            "makefile_header"           : self._FILE_HEADER_[self._FileType],
1646            "makefile_path"             : os.path.join("$(BUILD_DIR)", MakefileName),
1647            "make_path"                 : MyAgo.ToolDefinition["MAKE"]["PATH"],
1648            "platform_name"             : MyAgo.Name,
1649            "platform_guid"             : MyAgo.Guid,
1650            "platform_version"          : MyAgo.Version,
1651            "platform_build_directory"  : MyAgo.BuildDir,
1652            "conf_directory"            : GlobalData.gConfDirectory,
1653
1654            "toolchain_tag"             : MyAgo.ToolChain,
1655            "build_target"              : MyAgo.BuildTarget,
1656            "shell_command_code"        : list(self._SHELL_CMD_[self._FileType].keys()),
1657            "shell_command"             : list(self._SHELL_CMD_[self._FileType].values()),
1658            'arch'                      : list(MyAgo.ArchList),
1659            "build_architecture_list"   : ','.join(MyAgo.ArchList),
1660            "separator"                 : Separator,
1661            "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1662            "cleanall_command"          : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1663            "sub_build_command"         : SubBuildCommandList,
1664            "fdf_file"                  : FdfFileList,
1665            "active_platform"           : str(MyAgo),
1666            "fd"                        : MyAgo.FdTargetList,
1667            "fv"                        : MyAgo.FvTargetList,
1668            "cap"                       : MyAgo.CapTargetList,
1669            "extra_options"             : ExtraOption,
1670            "macro"                     : MacroList,
1671        }
1672
1673        return MakefileTemplateDict
1674
1675    ## Get the root directory list for intermediate files of all modules build
1676    #
1677    #   @retval     list    The list of directory
1678    #
1679    def GetModuleBuildDirectoryList(self):
1680        DirList = []
1681        for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1682            if not ModuleAutoGen.IsBinaryModule:
1683                DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1684        return DirList
1685
1686    ## Get the root directory list for intermediate files of all libraries build
1687    #
1688    #   @retval     list    The list of directory
1689    #
1690    def GetLibraryBuildDirectoryList(self):
1691        DirList = []
1692        for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1693            if not LibraryAutoGen.IsBinaryModule and not LibraryAutoGen.CanSkipbyHash():
1694                DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1695        return DirList
1696
1697# This acts like the main() function for the script, unless it is 'import'ed into another script.
1698if __name__ == '__main__':
1699    pass
1700
1701