EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

BaseTools/Source/Python/AutoGen/GenMake.py

Go to the documentation of this file.
00001 ## @file
00002 # Create makefile for MS nmake and GNU make
00003 #
00004 # Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
00005 # This program and the accompanying materials
00006 # are licensed and made available under the terms and conditions of the BSD License
00007 # which accompanies this distribution.  The full text of the license may be found at
00008 # http://opensource.org/licenses/bsd-license.php
00009 #
00010 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
00011 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
00012 #
00013 
00014 ## Import Modules
00015 #
00016 import os
00017 import sys
00018 import string
00019 import re
00020 import os.path as path
00021 
00022 from Common.BuildToolError import *
00023 from Common.Misc import *
00024 from Common.String import *
00025 from BuildEngine import *
00026 import Common.GlobalData as GlobalData
00027 
00028 ## Regular expression for finding header file inclusions
00029 gIncludePattern = re.compile(r"^[ \t]*#?[ \t]*include(?:[ \t]*(?:\\(?:\r\n|\r|\n))*[ \t]*)*(?:\(?[\"<]?[ \t]*)([-\w.\\/() \t]+)(?:[ \t]*[\">]?\)?)", re.MULTILINE|re.UNICODE|re.IGNORECASE)
00030 
00031 ## Regular expression for matching macro used in header file inclusion
00032 gMacroPattern = re.compile("([_A-Z][_A-Z0-9]*)[ \t]*\((.+)\)", re.UNICODE)
00033 
00034 ## pattern for include style in Edk.x code
00035 gProtocolDefinition = "Protocol/%(HeaderKey)s/%(HeaderKey)s.h"
00036 gGuidDefinition = "Guid/%(HeaderKey)s/%(HeaderKey)s.h"
00037 gArchProtocolDefinition = "ArchProtocol/%(HeaderKey)s/%(HeaderKey)s.h"
00038 gPpiDefinition = "Ppi/%(HeaderKey)s/%(HeaderKey)s.h"
00039 gIncludeMacroConversion = {
00040   "EFI_PROTOCOL_DEFINITION"         :   gProtocolDefinition,
00041   "EFI_GUID_DEFINITION"             :   gGuidDefinition,
00042   "EFI_ARCH_PROTOCOL_DEFINITION"    :   gArchProtocolDefinition,
00043   "EFI_PROTOCOL_PRODUCER"           :   gProtocolDefinition,
00044   "EFI_PROTOCOL_CONSUMER"           :   gProtocolDefinition,
00045   "EFI_PROTOCOL_DEPENDENCY"         :   gProtocolDefinition,
00046   "EFI_ARCH_PROTOCOL_PRODUCER"      :   gArchProtocolDefinition,
00047   "EFI_ARCH_PROTOCOL_CONSUMER"      :   gArchProtocolDefinition,
00048   "EFI_ARCH_PROTOCOL_DEPENDENCY"    :   gArchProtocolDefinition,
00049   "EFI_PPI_DEFINITION"              :   gPpiDefinition,
00050   "EFI_PPI_PRODUCER"                :   gPpiDefinition,
00051   "EFI_PPI_CONSUMER"                :   gPpiDefinition,
00052   "EFI_PPI_DEPENDENCY"              :   gPpiDefinition,
00053 }
00054 
00055 ## default makefile type
00056 gMakeType = ""
00057 if sys.platform == "win32":
00058     gMakeType = "nmake"
00059 else:
00060     gMakeType = "gmake"
00061 
00062 
00063 ## BuildFile class
00064 #
00065 #  This base class encapsules build file and its generation. It uses template to generate
00066 #  the content of build file. The content of build file will be got from AutoGen objects.
00067 #
00068 class BuildFile(object):
00069     ## template used to generate the build file (i.e. makefile if using make)
00070     _TEMPLATE_ = TemplateString('')
00071 
00072     _DEFAULT_FILE_NAME_ = "Makefile"
00073 
00074     ## default file name for each type of build file
00075     _FILE_NAME_ = {
00076         "nmake" :   "Makefile",
00077         "gmake" :   "GNUmakefile"
00078     }
00079 
00080     ## Fixed header string for makefile
00081     _MAKEFILE_HEADER = '''#
00082 # DO NOT EDIT
00083 # This file is auto-generated by build utility
00084 #
00085 # Module Name:
00086 #
00087 #   %s
00088 #
00089 # Abstract:
00090 #
00091 #   Auto-generated makefile for building modules, libraries or platform
00092 #
00093     '''
00094 
00095     ## Header string for each type of build file
00096     _FILE_HEADER_ = {
00097         "nmake" :   _MAKEFILE_HEADER % _FILE_NAME_["nmake"],
00098         "gmake" :   _MAKEFILE_HEADER % _FILE_NAME_["gmake"]
00099     }
00100 
00101     ## shell commands which can be used in build file in the form of macro
00102     #   $(CP)     copy file command
00103     #   $(MV)     move file command
00104     #   $(RM)     remove file command
00105     #   $(MD)     create dir command
00106     #   $(RD)     remove dir command
00107     #
00108     _SHELL_CMD_ = {
00109         "nmake" : {
00110             "CP"    :   "copy /y",
00111             "MV"    :   "move /y",
00112             "RM"    :   "del /f /q",
00113             "MD"    :   "mkdir",
00114             "RD"    :   "rmdir /s /q",
00115         },
00116 
00117         "gmake" : {
00118             "CP"    :   "cp -f",
00119             "MV"    :   "mv -f",
00120             "RM"    :   "rm -f",
00121             "MD"    :   "mkdir -p",
00122             "RD"    :   "rm -r -f",
00123         }
00124     }
00125 
00126     ## directory separator
00127     _SEP_ = {
00128         "nmake" :   "\\",
00129         "gmake" :   "/"
00130     }
00131 
00132     ## directory creation template
00133     _MD_TEMPLATE_ = {
00134         "nmake" :   'if not exist %(dir)s $(MD) %(dir)s',
00135         "gmake" :   "$(MD) %(dir)s"
00136     }
00137 
00138     ## directory removal template
00139     _RD_TEMPLATE_ = {
00140         "nmake" :   'if exist %(dir)s $(RD) %(dir)s',
00141         "gmake" :   "$(RD) %(dir)s"
00142     }
00143 
00144     _CD_TEMPLATE_ = {
00145         "nmake" :   'if exist %(dir)s cd %(dir)s',
00146         "gmake" :   "test -e %(dir)s && cd %(dir)s"
00147     }
00148 
00149     _MAKE_TEMPLATE_ = {
00150         "nmake" :   'if exist %(file)s "$(MAKE)" $(MAKE_FLAGS) -f %(file)s',
00151         "gmake" :   'test -e %(file)s && "$(MAKE)" $(MAKE_FLAGS) -f %(file)s'
00152     }
00153 
00154     _INCLUDE_CMD_ = {
00155         "nmake" :   '!INCLUDE',
00156         "gmake" :   "include"
00157     }
00158 
00159     _INC_FLAG_ = {"MSFT" : "/I", "GCC" : "-I", "INTEL" : "-I", "RVCT" : "-I"}
00160 
00161     ## Constructor of BuildFile
00162     #
00163     #   @param  AutoGenObject   Object of AutoGen class
00164     #
00165     def __init__(self, AutoGenObject):
00166         self._AutoGenObject = AutoGenObject
00167         self._FileType = gMakeType
00168 
00169     ## Create build file
00170     #
00171     #   @param  FileType    Type of build file. Only nmake and gmake are supported now.
00172     #
00173     #   @retval TRUE        The build file is created or re-created successfully
00174     #   @retval FALSE       The build file exists and is the same as the one to be generated
00175     #
00176     def Generate(self, FileType=gMakeType):
00177         if FileType not in self._FILE_NAME_:
00178             EdkLogger.error("build", PARAMETER_INVALID, "Invalid build type [%s]" % FileType,
00179                             ExtraData="[%s]" % str(self._AutoGenObject))
00180         self._FileType = FileType
00181         FileContent = self._TEMPLATE_.Replace(self._TemplateDict)
00182         FileName = self._FILE_NAME_[FileType]
00183         return SaveFileOnChange(os.path.join(self._AutoGenObject.MakeFileDir, FileName), FileContent, False)
00184 
00185     ## Return a list of directory creation command string
00186     #
00187     #   @param      DirList     The list of directory to be created
00188     #
00189     #   @retval     list        The directory creation command list
00190     #
00191     def GetCreateDirectoryCommand(self, DirList):
00192         return [self._MD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
00193 
00194     ## Return a list of directory removal command string
00195     #
00196     #   @param      DirList     The list of directory to be removed
00197     #
00198     #   @retval     list        The directory removal command list
00199     #
00200     def GetRemoveDirectoryCommand(self, DirList):
00201         return [self._RD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
00202 
00203     def PlaceMacro(self, Path, MacroDefinitions={}):
00204         if Path.startswith("$("):
00205             return Path
00206         else:
00207             PathLength = len(Path)
00208             for MacroName in MacroDefinitions:
00209                 MacroValue = MacroDefinitions[MacroName]
00210                 MacroValueLength = len(MacroValue)
00211                 if MacroValueLength <= PathLength and Path.startswith(MacroValue):
00212                     Path = "$(%s)%s" % (MacroName, Path[MacroValueLength:])
00213                     break
00214             return Path
00215 
00216 ## ModuleMakefile class
00217 #
00218 #  This class encapsules makefie and its generation for module. It uses template to generate
00219 #  the content of makefile. The content of makefile will be got from ModuleAutoGen object.
00220 #
00221 class ModuleMakefile(BuildFile):
00222     ## template used to generate the makefile for module
00223     _TEMPLATE_ = TemplateString('''\
00224 ${makefile_header}
00225 
00226 #
00227 # Platform Macro Definition
00228 #
00229 PLATFORM_NAME = ${platform_name}
00230 PLATFORM_GUID = ${platform_guid}
00231 PLATFORM_VERSION = ${platform_version}
00232 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
00233 PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}
00234 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
00235 
00236 #
00237 # Module Macro Definition
00238 #
00239 MODULE_NAME = ${module_name}
00240 MODULE_GUID = ${module_guid}
00241 MODULE_VERSION = ${module_version}
00242 MODULE_TYPE = ${module_type}
00243 MODULE_FILE = ${module_file}
00244 MODULE_FILE_BASE_NAME = ${module_file_base_name}
00245 BASE_NAME = $(MODULE_NAME)
00246 MODULE_RELATIVE_DIR = ${module_relative_directory}
00247 MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory}
00248 
00249 MODULE_ENTRY_POINT = ${module_entry_point}
00250 ARCH_ENTRY_POINT = ${arch_entry_point}
00251 IMAGE_ENTRY_POINT = ${image_entry_point}
00252 
00253 ${BEGIN}${module_extra_defines}
00254 ${END}
00255 #
00256 # Build Configuration Macro Definition
00257 #
00258 ARCH = ${architecture}
00259 TOOLCHAIN = ${toolchain_tag}
00260 TOOLCHAIN_TAG = ${toolchain_tag}
00261 TARGET = ${build_target}
00262 
00263 #
00264 # Build Directory Macro Definition
00265 #
00266 # PLATFORM_BUILD_DIR = ${platform_build_directory}
00267 BUILD_DIR = ${platform_build_directory}
00268 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
00269 LIB_DIR = $(BIN_DIR)
00270 MODULE_BUILD_DIR = ${module_build_directory}
00271 OUTPUT_DIR = ${module_output_directory}
00272 DEBUG_DIR = ${module_debug_directory}
00273 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
00274 DEST_DIR_DEBUG = $(DEBUG_DIR)
00275 
00276 #
00277 # Shell Command Macro
00278 #
00279 ${BEGIN}${shell_command_code} = ${shell_command}
00280 ${END}
00281 
00282 #
00283 # Tools definitions specific to this module
00284 #
00285 ${BEGIN}${module_tool_definitions}
00286 ${END}
00287 MAKE_FILE = ${makefile_path}
00288 
00289 #
00290 # Build Macro
00291 #
00292 ${BEGIN}${file_macro}
00293 ${END}
00294 
00295 COMMON_DEPS = ${BEGIN}${common_dependency_file} \\
00296               ${END}
00297 
00298 #
00299 # Overridable Target Macro Definitions
00300 #
00301 FORCE_REBUILD = force_build
00302 INIT_TARGET = init
00303 PCH_TARGET =
00304 BC_TARGET = ${BEGIN}${backward_compatible_target} ${END}
00305 CODA_TARGET = ${BEGIN}${remaining_build_target} \\
00306               ${END}
00307 
00308 #
00309 # Default target, which will build dependent libraries in addition to source files
00310 #
00311 
00312 all: mbuild
00313 
00314 
00315 #
00316 # Target used when called from platform makefile, which will bypass the build of dependent libraries
00317 #
00318 
00319 pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
00320 
00321 #
00322 # ModuleTarget
00323 #
00324 
00325 mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET)
00326 
00327 #
00328 # Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets
00329 #
00330 
00331 tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
00332 
00333 #
00334 # Phony target which is used to force executing commands for a target
00335 #
00336 force_build:
00337 \t-@
00338 
00339 #
00340 # Target to update the FD
00341 #
00342 
00343 fds: mbuild gen_fds
00344 
00345 #
00346 # Initialization target: print build information and create necessary directories
00347 #
00348 init: info dirs
00349 
00350 info:
00351 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
00352 
00353 dirs:
00354 ${BEGIN}\t-@${create_directory_command}\n${END}
00355 
00356 strdefs:
00357 \t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h
00358 
00359 #
00360 # GenLibsTarget
00361 #
00362 gen_libs:
00363 \t${BEGIN}@"$(MAKE)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name}
00364 \t${END}@cd $(MODULE_BUILD_DIR)
00365 
00366 #
00367 # Build Flash Device Image
00368 #
00369 gen_fds:
00370 \t@"$(MAKE)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds
00371 \t@cd $(MODULE_BUILD_DIR)
00372 
00373 #
00374 # Individual Object Build Targets
00375 #
00376 ${BEGIN}${file_build_target}
00377 ${END}
00378 
00379 #
00380 # clean all intermediate files
00381 #
00382 clean:
00383 \t${BEGIN}${clean_command}
00384 \t${END}
00385 
00386 #
00387 # clean all generated files
00388 #
00389 cleanall:
00390 ${BEGIN}\t${cleanall_command}
00391 ${END}\t$(RM) *.pdb *.idb > NUL 2>&1
00392 \t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi
00393 
00394 #
00395 # clean all dependent libraries built
00396 #
00397 cleanlib:
00398 \t${BEGIN}-@${library_build_command} cleanall
00399 \t${END}@cd $(MODULE_BUILD_DIR)\n\n''')
00400 
00401     _FILE_MACRO_TEMPLATE = TemplateString("${macro_name} = ${BEGIN} \\\n    ${source_file}${END}\n")
00402     _BUILD_TARGET_TEMPLATE = TemplateString("${BEGIN}${target} : ${deps}\n${END}\t${cmd}\n")
00403 
00404     ## Constructor of ModuleMakefile
00405     #
00406     #   @param  ModuleAutoGen   Object of ModuleAutoGen class
00407     #
00408     def __init__(self, ModuleAutoGen):
00409         BuildFile.__init__(self, ModuleAutoGen)
00410         self.PlatformInfo = self._AutoGenObject.PlatformInfo
00411 
00412         self.ResultFileList = []
00413         self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
00414 
00415         self.SourceFileDatabase = {}        # {file type : file path}
00416         self.DestFileDatabase = {}          # {file type : file path}
00417         self.FileBuildTargetList = []       # [(src, target string)]
00418         self.BuildTargetList = []           # [target string]
00419         self.PendingBuildTargetList = []    # [FileBuildRule objects]
00420         self.CommonFileDependency = []
00421         self.FileListMacros = {}
00422         self.ListFileMacros = {}
00423 
00424         self.FileDependency = []
00425         self.LibraryBuildCommandList = []
00426         self.LibraryFileList = []
00427         self.LibraryMakefileList = []
00428         self.LibraryBuildDirectoryList = []
00429         self.SystemLibraryList = []
00430         self.Macros = sdict()
00431         self.Macros["OUTPUT_DIR"      ] = self._AutoGenObject.Macros["OUTPUT_DIR"]
00432         self.Macros["DEBUG_DIR"       ] = self._AutoGenObject.Macros["DEBUG_DIR"]
00433         self.Macros["MODULE_BUILD_DIR"] = self._AutoGenObject.Macros["MODULE_BUILD_DIR"]
00434         self.Macros["BIN_DIR"         ] = self._AutoGenObject.Macros["BIN_DIR"]
00435         self.Macros["BUILD_DIR"       ] = self._AutoGenObject.Macros["BUILD_DIR"]
00436         self.Macros["WORKSPACE"       ] = self._AutoGenObject.Macros["WORKSPACE"]
00437 
00438     # Compose a dict object containing information used to do replacement in template
00439     def _CreateTemplateDict(self):
00440         if self._FileType not in self._SEP_:
00441             EdkLogger.error("build", PARAMETER_INVALID, "Invalid Makefile type [%s]" % self._FileType,
00442                             ExtraData="[%s]" % str(self._AutoGenObject))
00443         Separator = self._SEP_[self._FileType]
00444 
00445         # break build if no source files and binary files are found
00446         if len(self._AutoGenObject.SourceFileList) == 0 and len(self._AutoGenObject.BinaryFileList) == 0:
00447             EdkLogger.error("build", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]"
00448                             % (self._AutoGenObject.BuildTarget, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch),
00449                             ExtraData="[%s]" % str(self._AutoGenObject))
00450 
00451         # convert dependent libraries to build command
00452         self.ProcessDependentLibrary()
00453         if len(self._AutoGenObject.Module.ModuleEntryPointList) > 0:
00454             ModuleEntryPoint = self._AutoGenObject.Module.ModuleEntryPointList[0]
00455         else:
00456             ModuleEntryPoint = "_ModuleEntryPoint"
00457 
00458         # Intel EBC compiler enforces EfiMain
00459         if self._AutoGenObject.AutoGenVersion < 0x00010005 and self._AutoGenObject.Arch == "EBC":
00460             ArchEntryPoint = "EfiMain"
00461         else:
00462             ArchEntryPoint = ModuleEntryPoint
00463 
00464         if self._AutoGenObject.Arch == "EBC":
00465             # EBC compiler always use "EfiStart" as entry point. Only applies to EdkII modules
00466             ImageEntryPoint = "EfiStart"
00467         elif self._AutoGenObject.AutoGenVersion < 0x00010005:
00468             # Edk modules use entry point specified in INF file
00469             ImageEntryPoint = ModuleEntryPoint
00470         else:
00471             # EdkII modules always use "_ModuleEntryPoint" as entry point
00472             ImageEntryPoint = "_ModuleEntryPoint"
00473 
00474         # tools definitions
00475         ToolsDef = []
00476         IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
00477         for Tool in self._AutoGenObject.BuildOption:
00478             for Attr in self._AutoGenObject.BuildOption[Tool]:
00479                 Value = self._AutoGenObject.BuildOption[Tool][Attr]
00480                 if Attr == "FAMILY":
00481                     continue
00482                 elif Attr == "PATH":
00483                     ToolsDef.append("%s = %s" % (Tool, Value))
00484                 else:
00485                     # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
00486                     if Tool == "MAKE":
00487                         continue
00488                     # Remove duplicated include path, if any
00489                     if Attr == "FLAGS":
00490                         Value = RemoveDupOption(Value, IncPrefix, self._AutoGenObject.IncludePathList)
00491                     ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
00492             ToolsDef.append("")
00493 
00494         # convert source files and binary files to build targets
00495         self.ResultFileList = [str(T.Target) for T in self._AutoGenObject.CodaTargetList]
00496         if len(self.ResultFileList) == 0 and len(self._AutoGenObject.SourceFileList) <> 0:        
00497             EdkLogger.error("build", AUTOGEN_ERROR, "Nothing to build",
00498                             ExtraData="[%s]" % str(self._AutoGenObject))
00499 
00500         self.ProcessBuildTargetList()
00501 
00502         # Generate macros used to represent input files
00503         FileMacroList = [] # macro name = file list
00504         for FileListMacro in self.FileListMacros:
00505             FileMacro = self._FILE_MACRO_TEMPLATE.Replace(
00506                                                     {
00507                                                         "macro_name"  : FileListMacro,
00508                                                         "source_file" : self.FileListMacros[FileListMacro]
00509                                                     }
00510                                                     )
00511             FileMacroList.append(FileMacro)
00512 
00513         # INC_LIST is special
00514         FileMacro = ""
00515         IncludePathList = []
00516         for P in  self._AutoGenObject.IncludePathList:
00517             IncludePathList.append(IncPrefix+self.PlaceMacro(P, self.Macros))
00518             if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:
00519                 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix+P)
00520         FileMacro += self._FILE_MACRO_TEMPLATE.Replace(
00521                                                 {
00522                                                     "macro_name"   : "INC",
00523                                                     "source_file" : IncludePathList
00524                                                 }
00525                                                 )
00526         FileMacroList.append(FileMacro)
00527 
00528         # Generate macros used to represent files containing list of input files
00529         for ListFileMacro in self.ListFileMacros:
00530             ListFileName = os.path.join(self._AutoGenObject.OutputDir, "%s.lst" % ListFileMacro.lower()[:len(ListFileMacro)-5])
00531             FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))
00532             SaveFileOnChange(
00533                 ListFileName,
00534                 "\n".join(self.ListFileMacros[ListFileMacro]),
00535                 False
00536                 )
00537 
00538         # Edk modules need <BaseName>StrDefs.h for string ID
00539         #if self._AutoGenObject.AutoGenVersion < 0x00010005 and len(self._AutoGenObject.UnicodeFileList) > 0:
00540         #    BcTargetList = ['strdefs']
00541         #else:
00542         #    BcTargetList = []
00543         BcTargetList = []
00544 
00545         MakefileName = self._FILE_NAME_[self._FileType]
00546         LibraryMakeCommandList = []
00547         for D in self.LibraryBuildDirectoryList:
00548             Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)}
00549             LibraryMakeCommandList.append(Command)
00550 
00551         MakefileTemplateDict = {
00552             "makefile_header"           : self._FILE_HEADER_[self._FileType],
00553             "makefile_path"             : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
00554             "makefile_name"             : MakefileName,
00555             "platform_name"             : self.PlatformInfo.Name,
00556             "platform_guid"             : self.PlatformInfo.Guid,
00557             "platform_version"          : self.PlatformInfo.Version,
00558             "platform_relative_directory": self.PlatformInfo.SourceDir,
00559             "platform_output_directory" : self.PlatformInfo.OutputDir,
00560 
00561             "module_name"               : self._AutoGenObject.Name,
00562             "module_guid"               : self._AutoGenObject.Guid,
00563             "module_version"            : self._AutoGenObject.Version,
00564             "module_type"               : self._AutoGenObject.ModuleType,
00565             "module_file"               : self._AutoGenObject.MetaFile.Name,
00566             "module_file_base_name"     : self._AutoGenObject.MetaFile.BaseName,
00567             "module_relative_directory" : self._AutoGenObject.SourceDir,
00568             "module_extra_defines"      : ["%s = %s" % (k, v) for k,v in self._AutoGenObject.Module.Defines.iteritems()],
00569 
00570             "architecture"              : self._AutoGenObject.Arch,
00571             "toolchain_tag"             : self._AutoGenObject.ToolChain,
00572             "build_target"              : self._AutoGenObject.BuildTarget,
00573 
00574             "platform_build_directory"  : self.PlatformInfo.BuildDir,
00575             "module_build_directory"    : self._AutoGenObject.BuildDir,
00576             "module_output_directory"   : self._AutoGenObject.OutputDir,
00577             "module_debug_directory"    : self._AutoGenObject.DebugDir,
00578 
00579             "separator"                 : Separator,
00580             "module_tool_definitions"   : ToolsDef,
00581 
00582             "shell_command_code"        : self._SHELL_CMD_[self._FileType].keys(),
00583             "shell_command"             : self._SHELL_CMD_[self._FileType].values(),
00584 
00585             "module_entry_point"        : ModuleEntryPoint,
00586             "image_entry_point"         : ImageEntryPoint,
00587             "arch_entry_point"          : ArchEntryPoint,
00588             "remaining_build_target"    : self.ResultFileList,
00589             "common_dependency_file"    : self.CommonFileDependency,
00590             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
00591             "clean_command"             : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]),
00592             "cleanall_command"          : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]),
00593             "dependent_library_build_directory" : self.LibraryBuildDirectoryList,
00594             "library_build_command"     : LibraryMakeCommandList,
00595             "file_macro"                : FileMacroList,
00596             "file_build_target"         : self.BuildTargetList,
00597             "backward_compatible_target": BcTargetList,
00598         }
00599 
00600         return MakefileTemplateDict
00601 
00602     def ProcessBuildTargetList(self):
00603         #
00604         # Search dependency file list for each source file
00605         #
00606         ForceIncludedFile = []
00607         for File in self._AutoGenObject.AutoGenFileList:
00608             if File.Ext == '.h':
00609                 ForceIncludedFile.append(File)
00610         SourceFileList = []
00611         for Target in self._AutoGenObject.IntroTargetList:
00612             SourceFileList.extend(Target.Inputs)
00613 
00614         self.FileDependency = self.GetFileDependency(
00615                                     SourceFileList,
00616                                     ForceIncludedFile,
00617                                     self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList
00618                                     )
00619         DepSet = None
00620         for File in self.FileDependency:
00621             if not self.FileDependency[File]:
00622                 self.FileDependency[File] = ['$(FORCE_REBUILD)']
00623                 continue
00624             # skip non-C files
00625             if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
00626                 continue
00627             elif DepSet == None:
00628                 DepSet = set(self.FileDependency[File])
00629             else:
00630                 DepSet &= set(self.FileDependency[File])
00631         # in case nothing in SourceFileList
00632         if DepSet == None:
00633             DepSet = set()
00634         #
00635         # Extract common files list in the dependency files
00636         #
00637         for File in DepSet:
00638             self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros))
00639 
00640         for File in self.FileDependency:
00641             # skip non-C files
00642             if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
00643                 continue
00644             NewDepSet = set(self.FileDependency[File])
00645             NewDepSet -= DepSet
00646             self.FileDependency[File] = ["$(COMMON_DEPS)"] + list(NewDepSet)
00647 
00648         # Convert target description object to target string in makefile
00649         for Type in self._AutoGenObject.Targets:
00650             for T in self._AutoGenObject.Targets[Type]:
00651                 # Generate related macros if needed
00652                 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
00653                     self.FileListMacros[T.FileListMacro] = []
00654                 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:
00655                     self.ListFileMacros[T.ListFileMacro] = []
00656                 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:
00657                     self.ListFileMacros[T.IncListFileMacro] = []
00658 
00659                 Deps = []
00660                 # Add force-dependencies
00661                 for Dep in T.Dependencies:
00662                     Deps.append(self.PlaceMacro(str(Dep), self.Macros))
00663                 # Add inclusion-dependencies
00664                 if len(T.Inputs) == 1 and T.Inputs[0] in self.FileDependency:
00665                     for F in self.FileDependency[T.Inputs[0]]:
00666                         Deps.append(self.PlaceMacro(str(F), self.Macros))
00667                 # Add source-dependencies
00668                 for F in T.Inputs:
00669                     NewFile = self.PlaceMacro(str(F), self.Macros)
00670                     # In order to use file list macro as dependency
00671                     if T.GenListFile:
00672                         self.ListFileMacros[T.ListFileMacro].append(str(F))
00673                         self.FileListMacros[T.FileListMacro].append(NewFile)
00674                     elif T.GenFileListMacro:
00675                         self.FileListMacros[T.FileListMacro].append(NewFile)
00676                     else:
00677                         Deps.append(NewFile)
00678 
00679                 # Use file list macro as dependency
00680                 if T.GenFileListMacro:
00681                     Deps.append("$(%s)" % T.FileListMacro)
00682 
00683                 TargetDict = {
00684                     "target"    :   self.PlaceMacro(T.Target.Path, self.Macros),
00685                     "cmd"       :   "\n\t".join(T.Commands),
00686                     "deps"      :   Deps
00687                 }
00688                 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
00689 
00690     ## For creating makefile targets for dependent libraries
00691     def ProcessDependentLibrary(self):
00692         for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
00693             self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
00694 
00695     ## Return a list containing source file's dependencies
00696     #
00697     #   @param      FileList        The list of source files
00698     #   @param      ForceInculeList The list of files which will be included forcely
00699     #   @param      SearchPathList  The list of search path
00700     #
00701     #   @retval     dict            The mapping between source file path and its dependencies
00702     #
00703     def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
00704         Dependency = {}
00705         for F in FileList:
00706             Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)
00707         return Dependency
00708 
00709     ## Find dependencies for one source file
00710     #
00711     #  By searching recursively "#include" directive in file, find out all the
00712     #  files needed by given source file. The dependecies will be only searched
00713     #  in given search path list.
00714     #
00715     #   @param      File            The source file
00716     #   @param      ForceInculeList The list of files which will be included forcely
00717     #   @param      SearchPathList  The list of search path
00718     #
00719     #   @retval     list            The list of files the given source file depends on
00720     #
00721     def GetDependencyList(self, File, ForceList, SearchPathList):
00722         EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File)
00723         FileStack = [File] + ForceList
00724         DependencySet = set()
00725         MacroUsedByIncludedFile = False
00726 
00727         if self._AutoGenObject.Arch not in gDependencyDatabase:
00728             gDependencyDatabase[self._AutoGenObject.Arch] = {}
00729         DepDb = gDependencyDatabase[self._AutoGenObject.Arch]
00730 
00731         # add path of given source file into search path list.
00732         if File.Dir not in SearchPathList:
00733             SearchPathList.append(File.Dir)
00734         while len(FileStack) > 0:
00735             F = FileStack.pop()
00736 
00737             CurrentFileDependencyList = []
00738             if F in DepDb:
00739                 CurrentFileDependencyList = DepDb[F]
00740                 for Dep in CurrentFileDependencyList:
00741                     if Dep not in FileStack and Dep not in DependencySet:
00742                         FileStack.append(Dep)
00743             else:
00744                 try:
00745                     Fd = open(F.Path, 'r')
00746                 except BaseException, X:
00747                     EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path+"\n\t"+str(X))
00748 
00749                 FileContent = Fd.read()
00750                 Fd.close()
00751                 if len(FileContent) == 0:
00752                     continue
00753 
00754                 if FileContent[0] == 0xff or FileContent[0] == 0xfe:
00755                     FileContent = unicode(FileContent, "utf-16")
00756                 IncludedFileList = gIncludePattern.findall(FileContent)
00757 
00758                 CurrentFilePath = F.Dir
00759                 for Inc in IncludedFileList:
00760                     Inc = Inc.strip()
00761                     # if there's macro used to reference header file, expand it
00762                     HeaderList = gMacroPattern.findall(Inc)
00763                     if len(HeaderList) == 1 and len(HeaderList[0]) == 2:
00764                         HeaderType = HeaderList[0][0]
00765                         HeaderKey = HeaderList[0][1]
00766                         if HeaderType in gIncludeMacroConversion:
00767                             Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey}
00768                         else:
00769                             # not known macro used in #include
00770                             MacroUsedByIncludedFile = True
00771                             continue
00772                     Inc = os.path.normpath(Inc)
00773                     for SearchPath in [CurrentFilePath] + SearchPathList:
00774                         FilePath = os.path.join(SearchPath, Inc)
00775                         if not os.path.isfile(FilePath) or FilePath in CurrentFileDependencyList:
00776                             continue
00777                         FilePath = PathClass(FilePath)
00778                         CurrentFileDependencyList.append(FilePath)
00779                         if FilePath not in FileStack and FilePath not in DependencySet:
00780                             FileStack.append(FilePath)
00781                         break
00782                     else:
00783                         EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\
00784                                         "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList)))
00785 
00786                 if not MacroUsedByIncludedFile:
00787                     if F == File:
00788                         CurrentFileDependencyList += ForceList
00789                     #
00790                     # Don't keep the file in cache if it uses macro in included file.
00791                     # So it will be scanned again if another file includes this file.
00792                     #
00793                     DepDb[F] = CurrentFileDependencyList
00794             DependencySet.update(CurrentFileDependencyList)
00795 
00796         #
00797         # If there's macro used in included file, always build the file by
00798         # returning a empty dependency
00799         #
00800         if MacroUsedByIncludedFile:
00801             DependencyList = []
00802         else:
00803             DependencyList = list(DependencySet)  # remove duplicate ones
00804 
00805         return DependencyList
00806 
00807     _TemplateDict = property(_CreateTemplateDict)
00808 
00809 ## CustomMakefile class
00810 #
00811 #  This class encapsules makefie and its generation for module. It uses template to generate
00812 #  the content of makefile. The content of makefile will be got from ModuleAutoGen object.
00813 #
00814 class CustomMakefile(BuildFile):
00815     ## template used to generate the makefile for module with custom makefile
00816     _TEMPLATE_ = TemplateString('''\
00817 ${makefile_header}
00818 
00819 #
00820 # Platform Macro Definition
00821 #
00822 PLATFORM_NAME = ${platform_name}
00823 PLATFORM_GUID = ${platform_guid}
00824 PLATFORM_VERSION = ${platform_version}
00825 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
00826 PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}
00827 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
00828 
00829 #
00830 # Module Macro Definition
00831 #
00832 MODULE_NAME = ${module_name}
00833 MODULE_GUID = ${module_guid}
00834 MODULE_VERSION = ${module_version}
00835 MODULE_TYPE = ${module_type}
00836 MODULE_FILE = ${module_file}
00837 MODULE_FILE_BASE_NAME = ${module_file_base_name}
00838 BASE_NAME = $(MODULE_NAME)
00839 MODULE_RELATIVE_DIR = ${module_relative_directory}
00840 MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory}
00841 
00842 #
00843 # Build Configuration Macro Definition
00844 #
00845 ARCH = ${architecture}
00846 TOOLCHAIN = ${toolchain_tag}
00847 TOOLCHAIN_TAG = ${toolchain_tag}
00848 TARGET = ${build_target}
00849 
00850 #
00851 # Build Directory Macro Definition
00852 #
00853 # PLATFORM_BUILD_DIR = ${platform_build_directory}
00854 BUILD_DIR = ${platform_build_directory}
00855 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
00856 LIB_DIR = $(BIN_DIR)
00857 MODULE_BUILD_DIR = ${module_build_directory}
00858 OUTPUT_DIR = ${module_output_directory}
00859 DEBUG_DIR = ${module_debug_directory}
00860 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
00861 DEST_DIR_DEBUG = $(DEBUG_DIR)
00862 
00863 #
00864 # Tools definitions specific to this module
00865 #
00866 ${BEGIN}${module_tool_definitions}
00867 ${END}
00868 MAKE_FILE = ${makefile_path}
00869 
00870 #
00871 # Shell Command Macro
00872 #
00873 ${BEGIN}${shell_command_code} = ${shell_command}
00874 ${END}
00875 
00876 ${custom_makefile_content}
00877 
00878 #
00879 # Target used when called from platform makefile, which will bypass the build of dependent libraries
00880 #
00881 
00882 pbuild: init all
00883 
00884 
00885 #
00886 # ModuleTarget
00887 #
00888 
00889 mbuild: init all
00890 
00891 #
00892 # Build Target used in multi-thread build mode, which no init target is needed
00893 #
00894 
00895 tbuild: all
00896 
00897 #
00898 # Initialization target: print build information and create necessary directories
00899 #
00900 init:
00901 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
00902 ${BEGIN}\t-@${create_directory_command}\n${END}\
00903 
00904 ''')
00905 
00906     ## Constructor of CustomMakefile
00907     #
00908     #   @param  ModuleAutoGen   Object of ModuleAutoGen class
00909     #
00910     def __init__(self, ModuleAutoGen):
00911         BuildFile.__init__(self, ModuleAutoGen)
00912         self.PlatformInfo = self._AutoGenObject.PlatformInfo
00913         self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
00914 
00915     # Compose a dict object containing information used to do replacement in template
00916     def _CreateTemplateDict(self):
00917         Separator = self._SEP_[self._FileType]
00918         if self._FileType not in self._AutoGenObject.CustomMakefile:
00919             EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType,
00920                             ExtraData="[%s]" % str(self._AutoGenObject))
00921         MakefilePath = os.path.join(
00922                                 self._AutoGenObject.WorkspaceDir,
00923                                 self._AutoGenObject.CustomMakefile[self._FileType]
00924                                 )
00925         try:
00926             CustomMakefile = open(MakefilePath, 'r').read()
00927         except:
00928             EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(self._AutoGenObject),
00929                             ExtraData=self._AutoGenObject.CustomMakefile[self._FileType])
00930 
00931         # tools definitions
00932         ToolsDef = []
00933         for Tool in self._AutoGenObject.BuildOption:
00934             # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
00935             if Tool == "MAKE":
00936                 continue
00937             for Attr in self._AutoGenObject.BuildOption[Tool]:
00938                 if Attr == "FAMILY":
00939                     continue
00940                 elif Attr == "PATH":
00941                     ToolsDef.append("%s = %s" % (Tool, self._AutoGenObject.BuildOption[Tool][Attr]))
00942                 else:
00943                     ToolsDef.append("%s_%s = %s" % (Tool, Attr, self._AutoGenObject.BuildOption[Tool][Attr]))
00944             ToolsDef.append("")
00945 
00946         MakefileName = self._FILE_NAME_[self._FileType]
00947         MakefileTemplateDict = {
00948             "makefile_header"           : self._FILE_HEADER_[self._FileType],
00949             "makefile_path"             : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
00950             "platform_name"             : self.PlatformInfo.Name,
00951             "platform_guid"             : self.PlatformInfo.Guid,
00952             "platform_version"          : self.PlatformInfo.Version,
00953             "platform_relative_directory": self.PlatformInfo.SourceDir,
00954             "platform_output_directory" : self.PlatformInfo.OutputDir,
00955 
00956             "module_name"               : self._AutoGenObject.Name,
00957             "module_guid"               : self._AutoGenObject.Guid,
00958             "module_version"            : self._AutoGenObject.Version,
00959             "module_type"               : self._AutoGenObject.ModuleType,
00960             "module_file"               : self._AutoGenObject.MetaFile,
00961             "module_file_base_name"     : self._AutoGenObject.MetaFile.BaseName,
00962             "module_relative_directory" : self._AutoGenObject.SourceDir,
00963 
00964             "architecture"              : self._AutoGenObject.Arch,
00965             "toolchain_tag"             : self._AutoGenObject.ToolChain,
00966             "build_target"              : self._AutoGenObject.BuildTarget,
00967 
00968             "platform_build_directory"  : self.PlatformInfo.BuildDir,
00969             "module_build_directory"    : self._AutoGenObject.BuildDir,
00970             "module_output_directory"   : self._AutoGenObject.OutputDir,
00971             "module_debug_directory"    : self._AutoGenObject.DebugDir,
00972 
00973             "separator"                 : Separator,
00974             "module_tool_definitions"   : ToolsDef,
00975 
00976             "shell_command_code"        : self._SHELL_CMD_[self._FileType].keys(),
00977             "shell_command"             : self._SHELL_CMD_[self._FileType].values(),
00978 
00979             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
00980             "custom_makefile_content"   : CustomMakefile
00981         }
00982 
00983         return MakefileTemplateDict
00984 
00985     _TemplateDict = property(_CreateTemplateDict)
00986 
00987 ## PlatformMakefile class
00988 #
00989 #  This class encapsules makefie and its generation for platform. It uses
00990 # template to generate the content of makefile. The content of makefile will be
00991 # got from PlatformAutoGen object.
00992 #
00993 class PlatformMakefile(BuildFile):
00994     ## template used to generate the makefile for platform
00995     _TEMPLATE_ = TemplateString('''\
00996 ${makefile_header}
00997 
00998 #
00999 # Platform Macro Definition
01000 #
01001 PLATFORM_NAME = ${platform_name}
01002 PLATFORM_GUID = ${platform_guid}
01003 PLATFORM_VERSION = ${platform_version}
01004 PLATFORM_FILE = ${platform_file}
01005 PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}
01006 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
01007 
01008 #
01009 # Build Configuration Macro Definition
01010 #
01011 TOOLCHAIN = ${toolchain_tag}
01012 TOOLCHAIN_TAG = ${toolchain_tag}
01013 TARGET = ${build_target}
01014 
01015 #
01016 # Build Directory Macro Definition
01017 #
01018 BUILD_DIR = ${platform_build_directory}
01019 FV_DIR = ${platform_build_directory}${separator}FV
01020 
01021 #
01022 # Shell Command Macro
01023 #
01024 ${BEGIN}${shell_command_code} = ${shell_command}
01025 ${END}
01026 
01027 MAKE = ${make_path}
01028 MAKE_FILE = ${makefile_path}
01029 
01030 #
01031 # Default target
01032 #
01033 all: init build_libraries build_modules
01034 
01035 #
01036 # Initialization target: print build information and create necessary directories
01037 #
01038 init:
01039 \t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
01040 \t${BEGIN}-@${create_directory_command}
01041 \t${END}
01042 #
01043 # library build target
01044 #
01045 libraries: init build_libraries
01046 
01047 #
01048 # module build target
01049 #
01050 modules: init build_libraries build_modules
01051 
01052 #
01053 # Build all libraries:
01054 #
01055 build_libraries:
01056 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
01057 ${END}\t@cd $(BUILD_DIR)
01058 
01059 #
01060 # Build all modules:
01061 #
01062 build_modules:
01063 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
01064 ${END}\t@cd $(BUILD_DIR)
01065 
01066 #
01067 # Clean intermediate files
01068 #
01069 clean:
01070 \t${BEGIN}-@${library_build_command} clean
01071 \t${END}${BEGIN}-@${module_build_command} clean
01072 \t${END}@cd $(BUILD_DIR)
01073 
01074 #
01075 # Clean all generated files except to makefile
01076 #
01077 cleanall:
01078 ${BEGIN}\t${cleanall_command}
01079 ${END}
01080 
01081 #
01082 # Clean all library files
01083 #
01084 cleanlib:
01085 \t${BEGIN}-@${library_build_command} cleanall
01086 \t${END}@cd $(BUILD_DIR)\n
01087 ''')
01088 
01089     ## Constructor of PlatformMakefile
01090     #
01091     #   @param  ModuleAutoGen   Object of PlatformAutoGen class
01092     #
01093     def __init__(self, PlatformAutoGen):
01094         BuildFile.__init__(self, PlatformAutoGen)
01095         self.ModuleBuildCommandList = []
01096         self.ModuleMakefileList = []
01097         self.IntermediateDirectoryList = []
01098         self.ModuleBuildDirectoryList = []
01099         self.LibraryBuildDirectoryList = []
01100 
01101     # Compose a dict object containing information used to do replacement in template
01102     def _CreateTemplateDict(self):
01103         Separator = self._SEP_[self._FileType]
01104 
01105         PlatformInfo = self._AutoGenObject
01106         if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:
01107             EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
01108                             ExtraData="[%s]" % str(self._AutoGenObject))
01109 
01110         self.IntermediateDirectoryList = ["$(BUILD_DIR)"]
01111         self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()
01112         self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()
01113 
01114         MakefileName = self._FILE_NAME_[self._FileType]
01115         LibraryMakefileList = []
01116         LibraryMakeCommandList = []
01117         for D in self.LibraryBuildDirectoryList:
01118             D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})
01119             Makefile = os.path.join(D, MakefileName)
01120             Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
01121             LibraryMakefileList.append(Makefile)
01122             LibraryMakeCommandList.append(Command)
01123 
01124         ModuleMakefileList = []
01125         ModuleMakeCommandList = []
01126         for D in self.ModuleBuildDirectoryList:
01127             D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})
01128             Makefile = os.path.join(D, MakefileName)
01129             Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
01130             ModuleMakefileList.append(Makefile)
01131             ModuleMakeCommandList.append(Command)
01132 
01133         MakefileTemplateDict = {
01134             "makefile_header"           : self._FILE_HEADER_[self._FileType],
01135             "makefile_path"             : os.path.join("$(BUILD_DIR)", MakefileName),
01136             "make_path"                 : PlatformInfo.ToolDefinition["MAKE"]["PATH"],
01137             "makefile_name"             : MakefileName,
01138             "platform_name"             : PlatformInfo.Name,
01139             "platform_guid"             : PlatformInfo.Guid,
01140             "platform_version"          : PlatformInfo.Version,
01141             "platform_file"             : self._AutoGenObject.MetaFile,
01142             "platform_relative_directory": PlatformInfo.SourceDir,
01143             "platform_output_directory" : PlatformInfo.OutputDir,
01144             "platform_build_directory"  : PlatformInfo.BuildDir,
01145 
01146             "toolchain_tag"             : PlatformInfo.ToolChain,
01147             "build_target"              : PlatformInfo.BuildTarget,
01148             "shell_command_code"        : self._SHELL_CMD_[self._FileType].keys(),
01149             "shell_command"             : self._SHELL_CMD_[self._FileType].values(),
01150             "build_architecture_list"   : self._AutoGenObject.Arch,
01151             "architecture"              : self._AutoGenObject.Arch,
01152             "separator"                 : Separator,
01153             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
01154             "cleanall_command"          : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
01155             "library_makefile_list"     : LibraryMakefileList,
01156             "module_makefile_list"      : ModuleMakefileList,
01157             "library_build_command"     : LibraryMakeCommandList,
01158             "module_build_command"      : ModuleMakeCommandList,
01159         }
01160 
01161         return MakefileTemplateDict
01162 
01163     ## Get the root directory list for intermediate files of all modules build
01164     #
01165     #   @retval     list    The list of directory
01166     #
01167     def GetModuleBuildDirectoryList(self):
01168         DirList = []
01169         for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
01170             DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
01171         return DirList
01172 
01173     ## Get the root directory list for intermediate files of all libraries build
01174     #
01175     #   @retval     list    The list of directory
01176     #
01177     def GetLibraryBuildDirectoryList(self):
01178         DirList = []
01179         for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
01180             DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
01181         return DirList
01182 
01183     _TemplateDict = property(_CreateTemplateDict)
01184 
01185 ## TopLevelMakefile class
01186 #
01187 #  This class encapsules makefie and its generation for entrance makefile. It
01188 # uses template to generate the content of makefile. The content of makefile
01189 # will be got from WorkspaceAutoGen object.
01190 #
01191 class TopLevelMakefile(BuildFile):
01192     ## template used to generate toplevel makefile
01193     _TEMPLATE_ = TemplateString('''\
01194 ${makefile_header}
01195 
01196 #
01197 # Platform Macro Definition
01198 #
01199 PLATFORM_NAME = ${platform_name}
01200 PLATFORM_GUID = ${platform_guid}
01201 PLATFORM_VERSION = ${platform_version}
01202 
01203 #
01204 # Build Configuration Macro Definition
01205 #
01206 TOOLCHAIN = ${toolchain_tag}
01207 TOOLCHAIN_TAG = ${toolchain_tag}
01208 TARGET = ${build_target}
01209 
01210 #
01211 # Build Directory Macro Definition
01212 #
01213 BUILD_DIR = ${platform_build_directory}
01214 FV_DIR = ${platform_build_directory}${separator}FV
01215 
01216 #
01217 # Shell Command Macro
01218 #
01219 ${BEGIN}${shell_command_code} = ${shell_command}
01220 ${END}
01221 
01222 MAKE = ${make_path}
01223 MAKE_FILE = ${makefile_path}
01224 
01225 #
01226 # Default target
01227 #
01228 all: modules fds
01229 
01230 #
01231 # Initialization target: print build information and create necessary directories
01232 #
01233 init:
01234 \t-@
01235 \t${BEGIN}-@${create_directory_command}
01236 \t${END}
01237 #
01238 # library build target
01239 #
01240 libraries: init
01241 ${BEGIN}\t@cd $(BUILD_DIR)${separator}${arch} && "$(MAKE)" $(MAKE_FLAGS) libraries
01242 ${END}\t@cd $(BUILD_DIR)
01243 
01244 #
01245 # module build target
01246 #
01247 modules: init
01248 ${BEGIN}\t@cd $(BUILD_DIR)${separator}${arch} && "$(MAKE)" $(MAKE_FLAGS) modules
01249 ${END}\t@cd $(BUILD_DIR)
01250 
01251 #
01252 # Flash Device Image Target
01253 #
01254 fds: init
01255 \t-@cd $(FV_DIR)
01256 ${BEGIN}\tGenFds -f ${fdf_file} -o $(BUILD_DIR) -t $(TOOLCHAIN) -b $(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}
01257 
01258 #
01259 # run command for emulator platform only
01260 #
01261 run:
01262 \tcd $(BUILD_DIR)${separator}IA32 && ".${separator}SecMain"
01263 \tcd $(BUILD_DIR)
01264 
01265 #
01266 # Clean intermediate files
01267 #
01268 clean:
01269 ${BEGIN}\t-@${sub_build_command} clean
01270 ${END}\t@cd $(BUILD_DIR)
01271 
01272 #
01273 # Clean all generated files except to makefile
01274 #
01275 cleanall:
01276 ${BEGIN}\t${cleanall_command}
01277 ${END}
01278 
01279 #
01280 # Clean all library files
01281 #
01282 cleanlib:
01283 ${BEGIN}\t-@${sub_build_command} cleanlib
01284 ${END}\t@cd $(BUILD_DIR)\n
01285 ''')
01286 
01287     ## Constructor of TopLevelMakefile
01288     #
01289     #   @param  Workspace   Object of WorkspaceAutoGen class
01290     #
01291     def __init__(self, Workspace):
01292         BuildFile.__init__(self, Workspace)
01293         self.IntermediateDirectoryList = []
01294 
01295     # Compose a dict object containing information used to do replacement in template
01296     def _CreateTemplateDict(self):
01297         Separator = self._SEP_[self._FileType]
01298 
01299         # any platform autogen object is ok because we just need common information
01300         PlatformInfo = self._AutoGenObject
01301 
01302         if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:
01303             EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
01304                             ExtraData="[%s]" % str(self._AutoGenObject))
01305 
01306         for Arch in PlatformInfo.ArchList:
01307             self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch]))
01308         self.IntermediateDirectoryList.append("$(FV_DIR)")
01309 
01310         # TRICK: for not generating GenFds call in makefile if no FDF file
01311         MacroList = []
01312         if PlatformInfo.FdfFile != None and PlatformInfo.FdfFile != "":
01313             FdfFileList = [PlatformInfo.FdfFile]
01314             # macros passed to GenFds
01315             MacroList.append('"%s=%s"' % ("EFI_SOURCE", GlobalData.gEfiSource.replace('\\', '\\\\')))
01316             MacroList.append('"%s=%s"' % ("EDK_SOURCE", GlobalData.gEdkSource.replace('\\', '\\\\')))
01317             for MacroName in GlobalData.gGlobalDefines:
01318                 if GlobalData.gGlobalDefines[MacroName] != "":
01319                     MacroList.append('"%s=%s"' % (MacroName, GlobalData.gGlobalDefines[MacroName].replace('\\', '\\\\')))
01320                 else:
01321                     MacroList.append('"%s"' % MacroName)
01322             for MacroName in GlobalData.gCommandLineDefines:
01323                 if GlobalData.gCommandLineDefines[MacroName] != "":
01324                     MacroList.append('"%s=%s"' % (MacroName, GlobalData.gCommandLineDefines[MacroName].replace('\\', '\\\\')))
01325                 else:
01326                     MacroList.append('"%s"' % MacroName)                
01327         else:
01328             FdfFileList = []
01329 
01330         # pass extra common options to external program called in makefile, currently GenFds.exe
01331         ExtraOption = ''
01332         LogLevel = EdkLogger.GetLevel()
01333         if LogLevel == EdkLogger.VERBOSE:
01334             ExtraOption += " -v"
01335         elif LogLevel <= EdkLogger.DEBUG_9:
01336             ExtraOption += " -d %d" % (LogLevel - 1)
01337         elif LogLevel == EdkLogger.QUIET:
01338             ExtraOption += " -q"
01339 
01340         if GlobalData.gCaseInsensitive:
01341             ExtraOption += " -c"
01342 
01343         MakefileName = self._FILE_NAME_[self._FileType]
01344         SubBuildCommandList = []
01345         for A in PlatformInfo.ArchList:
01346             Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)}
01347             SubBuildCommandList.append(Command)
01348 
01349         MakefileTemplateDict = {
01350             "makefile_header"           : self._FILE_HEADER_[self._FileType],
01351             "makefile_path"             : os.path.join("$(BUILD_DIR)", MakefileName),
01352             "make_path"                 : PlatformInfo.ToolDefinition["MAKE"]["PATH"],
01353             "platform_name"             : PlatformInfo.Name,
01354             "platform_guid"             : PlatformInfo.Guid,
01355             "platform_version"          : PlatformInfo.Version,
01356             "platform_build_directory"  : PlatformInfo.BuildDir,
01357 
01358             "toolchain_tag"             : PlatformInfo.ToolChain,
01359             "build_target"              : PlatformInfo.BuildTarget,
01360             "shell_command_code"        : self._SHELL_CMD_[self._FileType].keys(),
01361             "shell_command"             : self._SHELL_CMD_[self._FileType].values(),
01362             'arch'                      : list(PlatformInfo.ArchList),
01363             "build_architecture_list"   : ','.join(PlatformInfo.ArchList),
01364             "separator"                 : Separator,
01365             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
01366             "cleanall_command"          : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
01367             "sub_build_command"         : SubBuildCommandList,
01368             "fdf_file"                  : FdfFileList,
01369             "active_platform"           : str(PlatformInfo),
01370             "fd"                        : PlatformInfo.FdTargetList,
01371             "fv"                        : PlatformInfo.FvTargetList,
01372             "cap"                       : PlatformInfo.CapTargetList,
01373             "extra_options"             : ExtraOption,
01374             "macro"                     : MacroList,
01375         }
01376 
01377         return MakefileTemplateDict
01378 
01379     ## Get the root directory list for intermediate files of all modules build
01380     #
01381     #   @retval     list    The list of directory
01382     #
01383     def GetModuleBuildDirectoryList(self):
01384         DirList = []
01385         for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
01386             DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
01387         return DirList
01388 
01389     ## Get the root directory list for intermediate files of all libraries build
01390     #
01391     #   @retval     list    The list of directory
01392     #
01393     def GetLibraryBuildDirectoryList(self):
01394         DirList = []
01395         for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
01396             DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
01397         return DirList
01398 
01399     _TemplateDict = property(_CreateTemplateDict)
01400 
01401 # This acts like the main() function for the script, unless it is 'import'ed into another script.
01402 if __name__ == '__main__':
01403     pass
01404 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines