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