1## @file 2# Create makefile for MS nmake and GNU make 3# 4# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR> 5# This program and the accompanying materials 6# are licensed and made available under the terms and conditions of the BSD License 7# which accompanies this distribution. The full text of the license may be found at 8# http://opensource.org/licenses/bsd-license.php 9# 10# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12# 13 14## Import Modules 15# 16import Common.LongFilePathOs as os 17import sys 18import string 19import re 20import os.path as path 21from Common.LongFilePathSupport import OpenLongFilePath as open 22from Common.MultipleWorkspace import MultipleWorkspace as mws 23from Common.BuildToolError import * 24from Common.Misc import * 25from Common.String import * 26from BuildEngine import * 27import Common.GlobalData as GlobalData 28 29## Regular expression for finding header file inclusions 30gIncludePattern = re.compile(r"^[ \t]*#?[ \t]*include(?:[ \t]*(?:\\(?:\r\n|\r|\n))*[ \t]*)*(?:\(?[\"<]?[ \t]*)([-\w.\\/() \t]+)(?:[ \t]*[\">]?\)?)", re.MULTILINE | re.UNICODE | re.IGNORECASE) 31 32## Regular expression for matching macro used in header file inclusion 33gMacroPattern = re.compile("([_A-Z][_A-Z0-9]*)[ \t]*\((.+)\)", re.UNICODE) 34 35gIsFileMap = {} 36 37## pattern for include style in Edk.x code 38gProtocolDefinition = "Protocol/%(HeaderKey)s/%(HeaderKey)s.h" 39gGuidDefinition = "Guid/%(HeaderKey)s/%(HeaderKey)s.h" 40gArchProtocolDefinition = "ArchProtocol/%(HeaderKey)s/%(HeaderKey)s.h" 41gPpiDefinition = "Ppi/%(HeaderKey)s/%(HeaderKey)s.h" 42gIncludeMacroConversion = { 43 "EFI_PROTOCOL_DEFINITION" : gProtocolDefinition, 44 "EFI_GUID_DEFINITION" : gGuidDefinition, 45 "EFI_ARCH_PROTOCOL_DEFINITION" : gArchProtocolDefinition, 46 "EFI_PROTOCOL_PRODUCER" : gProtocolDefinition, 47 "EFI_PROTOCOL_CONSUMER" : gProtocolDefinition, 48 "EFI_PROTOCOL_DEPENDENCY" : gProtocolDefinition, 49 "EFI_ARCH_PROTOCOL_PRODUCER" : gArchProtocolDefinition, 50 "EFI_ARCH_PROTOCOL_CONSUMER" : gArchProtocolDefinition, 51 "EFI_ARCH_PROTOCOL_DEPENDENCY" : gArchProtocolDefinition, 52 "EFI_PPI_DEFINITION" : gPpiDefinition, 53 "EFI_PPI_PRODUCER" : gPpiDefinition, 54 "EFI_PPI_CONSUMER" : gPpiDefinition, 55 "EFI_PPI_DEPENDENCY" : gPpiDefinition, 56} 57 58## default makefile type 59gMakeType = "" 60if sys.platform == "win32": 61 gMakeType = "nmake" 62else: 63 gMakeType = "gmake" 64 65 66## BuildFile class 67# 68# This base class encapsules build file and its generation. It uses template to generate 69# the content of build file. The content of build file will be got from AutoGen objects. 70# 71class BuildFile(object): 72 ## template used to generate the build file (i.e. makefile if using make) 73 _TEMPLATE_ = TemplateString('') 74 75 _DEFAULT_FILE_NAME_ = "Makefile" 76 77 ## default file name for each type of build file 78 _FILE_NAME_ = { 79 "nmake" : "Makefile", 80 "gmake" : "GNUmakefile" 81 } 82 83 ## Fixed header string for makefile 84 _MAKEFILE_HEADER = '''# 85# DO NOT EDIT 86# This file is auto-generated by build utility 87# 88# Module Name: 89# 90# %s 91# 92# Abstract: 93# 94# Auto-generated makefile for building modules, libraries or platform 95# 96 ''' 97 98 ## Header string for each type of build file 99 _FILE_HEADER_ = { 100 "nmake" : _MAKEFILE_HEADER % _FILE_NAME_["nmake"], 101 "gmake" : _MAKEFILE_HEADER % _FILE_NAME_["gmake"] 102 } 103 104 ## shell commands which can be used in build file in the form of macro 105 # $(CP) copy file command 106 # $(MV) move file command 107 # $(RM) remove file command 108 # $(MD) create dir command 109 # $(RD) remove dir command 110 # 111 _SHELL_CMD_ = { 112 "nmake" : { 113 "CP" : "copy /y", 114 "MV" : "move /y", 115 "RM" : "del /f /q", 116 "MD" : "mkdir", 117 "RD" : "rmdir /s /q", 118 }, 119 120 "gmake" : { 121 "CP" : "cp -f", 122 "MV" : "mv -f", 123 "RM" : "rm -f", 124 "MD" : "mkdir -p", 125 "RD" : "rm -r -f", 126 } 127 } 128 129 ## directory separator 130 _SEP_ = { 131 "nmake" : "\\", 132 "gmake" : "/" 133 } 134 135 ## directory creation template 136 _MD_TEMPLATE_ = { 137 "nmake" : 'if not exist %(dir)s $(MD) %(dir)s', 138 "gmake" : "$(MD) %(dir)s" 139 } 140 141 ## directory removal template 142 _RD_TEMPLATE_ = { 143 "nmake" : 'if exist %(dir)s $(RD) %(dir)s', 144 "gmake" : "$(RD) %(dir)s" 145 } 146 147 _CD_TEMPLATE_ = { 148 "nmake" : 'if exist %(dir)s cd %(dir)s', 149 "gmake" : "test -e %(dir)s && cd %(dir)s" 150 } 151 152 _MAKE_TEMPLATE_ = { 153 "nmake" : 'if exist %(file)s "$(MAKE)" $(MAKE_FLAGS) -f %(file)s', 154 "gmake" : 'test -e %(file)s && "$(MAKE)" $(MAKE_FLAGS) -f %(file)s' 155 } 156 157 _INCLUDE_CMD_ = { 158 "nmake" : '!INCLUDE', 159 "gmake" : "include" 160 } 161 162 _INC_FLAG_ = {"MSFT" : "/I", "GCC" : "-I", "INTEL" : "-I", "RVCT" : "-I"} 163 164 ## Constructor of BuildFile 165 # 166 # @param AutoGenObject Object of AutoGen class 167 # 168 def __init__(self, AutoGenObject): 169 self._AutoGenObject = AutoGenObject 170 self._FileType = gMakeType 171 172 ## Create build file 173 # 174 # @param FileType Type of build file. Only nmake and gmake are supported now. 175 # 176 # @retval TRUE The build file is created or re-created successfully 177 # @retval FALSE The build file exists and is the same as the one to be generated 178 # 179 def Generate(self, FileType=gMakeType): 180 if FileType not in self._FILE_NAME_: 181 EdkLogger.error("build", PARAMETER_INVALID, "Invalid build type [%s]" % FileType, 182 ExtraData="[%s]" % str(self._AutoGenObject)) 183 self._FileType = FileType 184 FileContent = self._TEMPLATE_.Replace(self._TemplateDict) 185 FileName = self._FILE_NAME_[FileType] 186 return SaveFileOnChange(os.path.join(self._AutoGenObject.MakeFileDir, FileName), FileContent, False) 187 188 ## Return a list of directory creation command string 189 # 190 # @param DirList The list of directory to be created 191 # 192 # @retval list The directory creation command list 193 # 194 def GetCreateDirectoryCommand(self, DirList): 195 return [self._MD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList] 196 197 ## Return a list of directory removal command string 198 # 199 # @param DirList The list of directory to be removed 200 # 201 # @retval list The directory removal command list 202 # 203 def GetRemoveDirectoryCommand(self, DirList): 204 return [self._RD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList] 205 206 def PlaceMacro(self, Path, MacroDefinitions={}): 207 if Path.startswith("$("): 208 return Path 209 else: 210 PathLength = len(Path) 211 for MacroName in MacroDefinitions: 212 MacroValue = MacroDefinitions[MacroName] 213 MacroValueLength = len(MacroValue) 214 if MacroValueLength <= PathLength and Path.startswith(MacroValue): 215 Path = "$(%s)%s" % (MacroName, Path[MacroValueLength:]) 216 break 217 return Path 218 219## ModuleMakefile class 220# 221# This class encapsules makefie and its generation for module. It uses template to generate 222# the content of makefile. The content of makefile will be got from ModuleAutoGen object. 223# 224class ModuleMakefile(BuildFile): 225 ## template used to generate the makefile for module 226 _TEMPLATE_ = TemplateString('''\ 227${makefile_header} 228 229# 230# Platform Macro Definition 231# 232PLATFORM_NAME = ${platform_name} 233PLATFORM_GUID = ${platform_guid} 234PLATFORM_VERSION = ${platform_version} 235PLATFORM_RELATIVE_DIR = ${platform_relative_directory} 236PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory} 237PLATFORM_OUTPUT_DIR = ${platform_output_directory} 238 239# 240# Module Macro Definition 241# 242MODULE_NAME = ${module_name} 243MODULE_GUID = ${module_guid} 244MODULE_NAME_GUID = ${module_name_guid} 245MODULE_VERSION = ${module_version} 246MODULE_TYPE = ${module_type} 247MODULE_FILE = ${module_file} 248MODULE_FILE_BASE_NAME = ${module_file_base_name} 249BASE_NAME = $(MODULE_NAME) 250MODULE_RELATIVE_DIR = ${module_relative_directory} 251PACKAGE_RELATIVE_DIR = ${package_relative_directory} 252MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory} 253 254MODULE_ENTRY_POINT = ${module_entry_point} 255ARCH_ENTRY_POINT = ${arch_entry_point} 256IMAGE_ENTRY_POINT = ${image_entry_point} 257 258${BEGIN}${module_extra_defines} 259${END} 260# 261# Build Configuration Macro Definition 262# 263ARCH = ${architecture} 264TOOLCHAIN = ${toolchain_tag} 265TOOLCHAIN_TAG = ${toolchain_tag} 266TARGET = ${build_target} 267 268# 269# Build Directory Macro Definition 270# 271# PLATFORM_BUILD_DIR = ${platform_build_directory} 272BUILD_DIR = ${platform_build_directory} 273BIN_DIR = $(BUILD_DIR)${separator}${architecture} 274LIB_DIR = $(BIN_DIR) 275MODULE_BUILD_DIR = ${module_build_directory} 276OUTPUT_DIR = ${module_output_directory} 277DEBUG_DIR = ${module_debug_directory} 278DEST_DIR_OUTPUT = $(OUTPUT_DIR) 279DEST_DIR_DEBUG = $(DEBUG_DIR) 280 281# 282# Shell Command Macro 283# 284${BEGIN}${shell_command_code} = ${shell_command} 285${END} 286 287# 288# Tools definitions specific to this module 289# 290${BEGIN}${module_tool_definitions} 291${END} 292MAKE_FILE = ${makefile_path} 293 294# 295# Build Macro 296# 297${BEGIN}${file_macro} 298${END} 299 300COMMON_DEPS = ${BEGIN}${common_dependency_file} \\ 301 ${END} 302 303# 304# Overridable Target Macro Definitions 305# 306FORCE_REBUILD = force_build 307INIT_TARGET = init 308PCH_TARGET = 309BC_TARGET = ${BEGIN}${backward_compatible_target} ${END} 310CODA_TARGET = ${BEGIN}${remaining_build_target} \\ 311 ${END} 312 313# 314# Default target, which will build dependent libraries in addition to source files 315# 316 317all: mbuild 318 319 320# 321# Target used when called from platform makefile, which will bypass the build of dependent libraries 322# 323 324pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET) 325 326# 327# ModuleTarget 328# 329 330mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET) 331 332# 333# Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets 334# 335 336tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET) 337 338# 339# Phony target which is used to force executing commands for a target 340# 341force_build: 342\t-@ 343 344# 345# Target to update the FD 346# 347 348fds: mbuild gen_fds 349 350# 351# Initialization target: print build information and create necessary directories 352# 353init: info dirs 354 355info: 356\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)] 357 358dirs: 359${BEGIN}\t-@${create_directory_command}\n${END} 360 361strdefs: 362\t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h 363 364# 365# GenLibsTarget 366# 367gen_libs: 368\t${BEGIN}@"$(MAKE)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name} 369\t${END}@cd $(MODULE_BUILD_DIR) 370 371# 372# Build Flash Device Image 373# 374gen_fds: 375\t@"$(MAKE)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds 376\t@cd $(MODULE_BUILD_DIR) 377 378# 379# Individual Object Build Targets 380# 381${BEGIN}${file_build_target} 382${END} 383 384# 385# clean all intermediate files 386# 387clean: 388\t${BEGIN}${clean_command} 389\t${END} 390 391# 392# clean all generated files 393# 394cleanall: 395${BEGIN}\t${cleanall_command} 396${END}\t$(RM) *.pdb *.idb > NUL 2>&1 397\t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi 398 399# 400# clean all dependent libraries built 401# 402cleanlib: 403\t${BEGIN}-@${library_build_command} cleanall 404\t${END}@cd $(MODULE_BUILD_DIR)\n\n''') 405 406 _FILE_MACRO_TEMPLATE = TemplateString("${macro_name} = ${BEGIN} \\\n ${source_file}${END}\n") 407 _BUILD_TARGET_TEMPLATE = TemplateString("${BEGIN}${target} : ${deps}\n${END}\t${cmd}\n") 408 409 ## Constructor of ModuleMakefile 410 # 411 # @param ModuleAutoGen Object of ModuleAutoGen class 412 # 413 def __init__(self, ModuleAutoGen): 414 BuildFile.__init__(self, ModuleAutoGen) 415 self.PlatformInfo = self._AutoGenObject.PlatformInfo 416 417 self.ResultFileList = [] 418 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"] 419 420 self.SourceFileDatabase = {} # {file type : file path} 421 self.DestFileDatabase = {} # {file type : file path} 422 self.FileBuildTargetList = [] # [(src, target string)] 423 self.BuildTargetList = [] # [target string] 424 self.PendingBuildTargetList = [] # [FileBuildRule objects] 425 self.CommonFileDependency = [] 426 self.FileListMacros = {} 427 self.ListFileMacros = {} 428 429 self.FileCache = {} 430 self.FileDependency = [] 431 self.LibraryBuildCommandList = [] 432 self.LibraryFileList = [] 433 self.LibraryMakefileList = [] 434 self.LibraryBuildDirectoryList = [] 435 self.SystemLibraryList = [] 436 self.Macros = sdict() 437 self.Macros["OUTPUT_DIR" ] = self._AutoGenObject.Macros["OUTPUT_DIR"] 438 self.Macros["DEBUG_DIR" ] = self._AutoGenObject.Macros["DEBUG_DIR"] 439 self.Macros["MODULE_BUILD_DIR"] = self._AutoGenObject.Macros["MODULE_BUILD_DIR"] 440 self.Macros["BIN_DIR" ] = self._AutoGenObject.Macros["BIN_DIR"] 441 self.Macros["BUILD_DIR" ] = self._AutoGenObject.Macros["BUILD_DIR"] 442 self.Macros["WORKSPACE" ] = self._AutoGenObject.Macros["WORKSPACE"] 443 444 # Compose a dict object containing information used to do replacement in template 445 def _CreateTemplateDict(self): 446 if self._FileType not in self._SEP_: 447 EdkLogger.error("build", PARAMETER_INVALID, "Invalid Makefile type [%s]" % self._FileType, 448 ExtraData="[%s]" % str(self._AutoGenObject)) 449 Separator = self._SEP_[self._FileType] 450 451 # break build if no source files and binary files are found 452 if len(self._AutoGenObject.SourceFileList) == 0 and len(self._AutoGenObject.BinaryFileList) == 0: 453 EdkLogger.error("build", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]" 454 % (self._AutoGenObject.BuildTarget, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch), 455 ExtraData="[%s]" % str(self._AutoGenObject)) 456 457 # convert dependent libraries to build command 458 self.ProcessDependentLibrary() 459 if len(self._AutoGenObject.Module.ModuleEntryPointList) > 0: 460 ModuleEntryPoint = self._AutoGenObject.Module.ModuleEntryPointList[0] 461 else: 462 ModuleEntryPoint = "_ModuleEntryPoint" 463 464 # Intel EBC compiler enforces EfiMain 465 if self._AutoGenObject.AutoGenVersion < 0x00010005 and self._AutoGenObject.Arch == "EBC": 466 ArchEntryPoint = "EfiMain" 467 else: 468 ArchEntryPoint = ModuleEntryPoint 469 470 if self._AutoGenObject.Arch == "EBC": 471 # EBC compiler always use "EfiStart" as entry point. Only applies to EdkII modules 472 ImageEntryPoint = "EfiStart" 473 elif self._AutoGenObject.AutoGenVersion < 0x00010005: 474 # Edk modules use entry point specified in INF file 475 ImageEntryPoint = ModuleEntryPoint 476 else: 477 # EdkII modules always use "_ModuleEntryPoint" as entry point 478 ImageEntryPoint = "_ModuleEntryPoint" 479 480 # tools definitions 481 ToolsDef = [] 482 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily] 483 for Tool in self._AutoGenObject.BuildOption: 484 for Attr in self._AutoGenObject.BuildOption[Tool]: 485 Value = self._AutoGenObject.BuildOption[Tool][Attr] 486 if Attr == "FAMILY": 487 continue 488 elif Attr == "PATH": 489 ToolsDef.append("%s = %s" % (Tool, Value)) 490 else: 491 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable. 492 if Tool == "MAKE": 493 continue 494 # Remove duplicated include path, if any 495 if Attr == "FLAGS": 496 Value = RemoveDupOption(Value, IncPrefix, self._AutoGenObject.IncludePathList) 497 ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value)) 498 ToolsDef.append("") 499 500 # convert source files and binary files to build targets 501 self.ResultFileList = [str(T.Target) for T in self._AutoGenObject.CodaTargetList] 502 if len(self.ResultFileList) == 0 and len(self._AutoGenObject.SourceFileList) <> 0: 503 EdkLogger.error("build", AUTOGEN_ERROR, "Nothing to build", 504 ExtraData="[%s]" % str(self._AutoGenObject)) 505 506 self.ProcessBuildTargetList() 507 508 # Generate macros used to represent input files 509 FileMacroList = [] # macro name = file list 510 for FileListMacro in self.FileListMacros: 511 FileMacro = self._FILE_MACRO_TEMPLATE.Replace( 512 { 513 "macro_name" : FileListMacro, 514 "source_file" : self.FileListMacros[FileListMacro] 515 } 516 ) 517 FileMacroList.append(FileMacro) 518 519 # INC_LIST is special 520 FileMacro = "" 521 IncludePathList = [] 522 for P in self._AutoGenObject.IncludePathList: 523 IncludePathList.append(IncPrefix + self.PlaceMacro(P, self.Macros)) 524 if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros: 525 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix + P) 526 FileMacro += self._FILE_MACRO_TEMPLATE.Replace( 527 { 528 "macro_name" : "INC", 529 "source_file" : IncludePathList 530 } 531 ) 532 FileMacroList.append(FileMacro) 533 534 # Generate macros used to represent files containing list of input files 535 for ListFileMacro in self.ListFileMacros: 536 ListFileName = os.path.join(self._AutoGenObject.OutputDir, "%s.lst" % ListFileMacro.lower()[:len(ListFileMacro) - 5]) 537 FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName)) 538 SaveFileOnChange( 539 ListFileName, 540 "\n".join(self.ListFileMacros[ListFileMacro]), 541 False 542 ) 543 544 # Edk modules need <BaseName>StrDefs.h for string ID 545 #if self._AutoGenObject.AutoGenVersion < 0x00010005 and len(self._AutoGenObject.UnicodeFileList) > 0: 546 # BcTargetList = ['strdefs'] 547 #else: 548 # BcTargetList = [] 549 BcTargetList = [] 550 551 MakefileName = self._FILE_NAME_[self._FileType] 552 LibraryMakeCommandList = [] 553 for D in self.LibraryBuildDirectoryList: 554 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)} 555 LibraryMakeCommandList.append(Command) 556 557 package_rel_dir = self._AutoGenObject.SourceDir 558 current_dir = self.Macros["WORKSPACE"] 559 found = False 560 while not found and os.sep in package_rel_dir: 561 index = package_rel_dir.index(os.sep) 562 current_dir = mws.join(current_dir, package_rel_dir[:index]) 563 for fl in os.listdir(current_dir): 564 if fl.endswith('.dec'): 565 found = True 566 break 567 package_rel_dir = package_rel_dir[index + 1:] 568 569 MakefileTemplateDict = { 570 "makefile_header" : self._FILE_HEADER_[self._FileType], 571 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName), 572 "makefile_name" : MakefileName, 573 "platform_name" : self.PlatformInfo.Name, 574 "platform_guid" : self.PlatformInfo.Guid, 575 "platform_version" : self.PlatformInfo.Version, 576 "platform_relative_directory": self.PlatformInfo.SourceDir, 577 "platform_output_directory" : self.PlatformInfo.OutputDir, 578 579 "module_name" : self._AutoGenObject.Name, 580 "module_guid" : self._AutoGenObject.Guid, 581 "module_name_guid" : self._AutoGenObject._GetUniqueBaseName(), 582 "module_version" : self._AutoGenObject.Version, 583 "module_type" : self._AutoGenObject.ModuleType, 584 "module_file" : self._AutoGenObject.MetaFile.Name, 585 "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName, 586 "module_relative_directory" : self._AutoGenObject.SourceDir, 587 "package_relative_directory": package_rel_dir, 588 "module_extra_defines" : ["%s = %s" % (k, v) for k, v in self._AutoGenObject.Module.Defines.iteritems()], 589 590 "architecture" : self._AutoGenObject.Arch, 591 "toolchain_tag" : self._AutoGenObject.ToolChain, 592 "build_target" : self._AutoGenObject.BuildTarget, 593 594 "platform_build_directory" : self.PlatformInfo.BuildDir, 595 "module_build_directory" : self._AutoGenObject.BuildDir, 596 "module_output_directory" : self._AutoGenObject.OutputDir, 597 "module_debug_directory" : self._AutoGenObject.DebugDir, 598 599 "separator" : Separator, 600 "module_tool_definitions" : ToolsDef, 601 602 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(), 603 "shell_command" : self._SHELL_CMD_[self._FileType].values(), 604 605 "module_entry_point" : ModuleEntryPoint, 606 "image_entry_point" : ImageEntryPoint, 607 "arch_entry_point" : ArchEntryPoint, 608 "remaining_build_target" : self.ResultFileList, 609 "common_dependency_file" : self.CommonFileDependency, 610 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), 611 "clean_command" : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]), 612 "cleanall_command" : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]), 613 "dependent_library_build_directory" : self.LibraryBuildDirectoryList, 614 "library_build_command" : LibraryMakeCommandList, 615 "file_macro" : FileMacroList, 616 "file_build_target" : self.BuildTargetList, 617 "backward_compatible_target": BcTargetList, 618 } 619 620 return MakefileTemplateDict 621 622 def ProcessBuildTargetList(self): 623 # 624 # Search dependency file list for each source file 625 # 626 ForceIncludedFile = [] 627 for File in self._AutoGenObject.AutoGenFileList: 628 if File.Ext == '.h': 629 ForceIncludedFile.append(File) 630 SourceFileList = [] 631 for Target in self._AutoGenObject.IntroTargetList: 632 SourceFileList.extend(Target.Inputs) 633 634 self.FileDependency = self.GetFileDependency( 635 SourceFileList, 636 ForceIncludedFile, 637 self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList 638 ) 639 DepSet = None 640 for File in self.FileDependency: 641 if not self.FileDependency[File]: 642 self.FileDependency[File] = ['$(FORCE_REBUILD)'] 643 continue 644 # skip non-C files 645 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c": 646 continue 647 elif DepSet == None: 648 DepSet = set(self.FileDependency[File]) 649 else: 650 DepSet &= set(self.FileDependency[File]) 651 # in case nothing in SourceFileList 652 if DepSet == None: 653 DepSet = set() 654 # 655 # Extract common files list in the dependency files 656 # 657 for File in DepSet: 658 self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros)) 659 660 for File in self.FileDependency: 661 # skip non-C files 662 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c": 663 continue 664 NewDepSet = set(self.FileDependency[File]) 665 NewDepSet -= DepSet 666 self.FileDependency[File] = ["$(COMMON_DEPS)"] + list(NewDepSet) 667 668 # Convert target description object to target string in makefile 669 for Type in self._AutoGenObject.Targets: 670 for T in self._AutoGenObject.Targets[Type]: 671 # Generate related macros if needed 672 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros: 673 self.FileListMacros[T.FileListMacro] = [] 674 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros: 675 self.ListFileMacros[T.ListFileMacro] = [] 676 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros: 677 self.ListFileMacros[T.IncListFileMacro] = [] 678 679 Deps = [] 680 # Add force-dependencies 681 for Dep in T.Dependencies: 682 Deps.append(self.PlaceMacro(str(Dep), self.Macros)) 683 # Add inclusion-dependencies 684 if len(T.Inputs) == 1 and T.Inputs[0] in self.FileDependency: 685 for F in self.FileDependency[T.Inputs[0]]: 686 Deps.append(self.PlaceMacro(str(F), self.Macros)) 687 # Add source-dependencies 688 for F in T.Inputs: 689 NewFile = self.PlaceMacro(str(F), self.Macros) 690 # In order to use file list macro as dependency 691 if T.GenListFile: 692 # gnu tools need forward slash path separater, even on Windows 693 self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/')) 694 self.FileListMacros[T.FileListMacro].append(NewFile) 695 elif T.GenFileListMacro: 696 self.FileListMacros[T.FileListMacro].append(NewFile) 697 else: 698 Deps.append(NewFile) 699 700 # Use file list macro as dependency 701 if T.GenFileListMacro: 702 Deps.append("$(%s)" % T.FileListMacro) 703 704 TargetDict = { 705 "target" : self.PlaceMacro(T.Target.Path, self.Macros), 706 "cmd" : "\n\t".join(T.Commands), 707 "deps" : Deps 708 } 709 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict)) 710 711 ## For creating makefile targets for dependent libraries 712 def ProcessDependentLibrary(self): 713 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList: 714 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros)) 715 716 ## Return a list containing source file's dependencies 717 # 718 # @param FileList The list of source files 719 # @param ForceInculeList The list of files which will be included forcely 720 # @param SearchPathList The list of search path 721 # 722 # @retval dict The mapping between source file path and its dependencies 723 # 724 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList): 725 Dependency = {} 726 for F in FileList: 727 Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList) 728 return Dependency 729 730 ## Find dependencies for one source file 731 # 732 # By searching recursively "#include" directive in file, find out all the 733 # files needed by given source file. The dependecies will be only searched 734 # in given search path list. 735 # 736 # @param File The source file 737 # @param ForceInculeList The list of files which will be included forcely 738 # @param SearchPathList The list of search path 739 # 740 # @retval list The list of files the given source file depends on 741 # 742 def GetDependencyList(self, File, ForceList, SearchPathList): 743 EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File) 744 FileStack = [File] + ForceList 745 DependencySet = set() 746 747 if self._AutoGenObject.Arch not in gDependencyDatabase: 748 gDependencyDatabase[self._AutoGenObject.Arch] = {} 749 DepDb = gDependencyDatabase[self._AutoGenObject.Arch] 750 751 while len(FileStack) > 0: 752 F = FileStack.pop() 753 754 FullPathDependList = [] 755 if F in self.FileCache: 756 for CacheFile in self.FileCache[F]: 757 FullPathDependList.append(CacheFile) 758 if CacheFile not in DependencySet: 759 FileStack.append(CacheFile) 760 DependencySet.update(FullPathDependList) 761 continue 762 763 CurrentFileDependencyList = [] 764 if F in DepDb: 765 CurrentFileDependencyList = DepDb[F] 766 else: 767 try: 768 Fd = open(F.Path, 'r') 769 except BaseException, X: 770 EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path + "\n\t" + str(X)) 771 772 FileContent = Fd.read() 773 Fd.close() 774 if len(FileContent) == 0: 775 continue 776 777 if FileContent[0] == 0xff or FileContent[0] == 0xfe: 778 FileContent = unicode(FileContent, "utf-16") 779 IncludedFileList = gIncludePattern.findall(FileContent) 780 781 for Inc in IncludedFileList: 782 Inc = Inc.strip() 783 # if there's macro used to reference header file, expand it 784 HeaderList = gMacroPattern.findall(Inc) 785 if len(HeaderList) == 1 and len(HeaderList[0]) == 2: 786 HeaderType = HeaderList[0][0] 787 HeaderKey = HeaderList[0][1] 788 if HeaderType in gIncludeMacroConversion: 789 Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey} 790 else: 791 # not known macro used in #include, always build the file by 792 # returning a empty dependency 793 self.FileCache[File] = [] 794 return [] 795 Inc = os.path.normpath(Inc) 796 CurrentFileDependencyList.append(Inc) 797 DepDb[F] = CurrentFileDependencyList 798 799 CurrentFilePath = F.Dir 800 PathList = [CurrentFilePath] + SearchPathList 801 for Inc in CurrentFileDependencyList: 802 for SearchPath in PathList: 803 FilePath = os.path.join(SearchPath, Inc) 804 if FilePath in gIsFileMap: 805 if not gIsFileMap[FilePath]: 806 continue 807 # If isfile is called too many times, the performance is slow down. 808 elif not os.path.isfile(FilePath): 809 gIsFileMap[FilePath] = False 810 continue 811 else: 812 gIsFileMap[FilePath] = True 813 FilePath = PathClass(FilePath) 814 FullPathDependList.append(FilePath) 815 if FilePath not in DependencySet: 816 FileStack.append(FilePath) 817 break 818 else: 819 EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\ 820 "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList))) 821 822 self.FileCache[F] = FullPathDependList 823 DependencySet.update(FullPathDependList) 824 825 DependencySet.update(ForceList) 826 if File in DependencySet: 827 DependencySet.remove(File) 828 DependencyList = list(DependencySet) # remove duplicate ones 829 830 return DependencyList 831 832 _TemplateDict = property(_CreateTemplateDict) 833 834## CustomMakefile class 835# 836# This class encapsules makefie and its generation for module. It uses template to generate 837# the content of makefile. The content of makefile will be got from ModuleAutoGen object. 838# 839class CustomMakefile(BuildFile): 840 ## template used to generate the makefile for module with custom makefile 841 _TEMPLATE_ = TemplateString('''\ 842${makefile_header} 843 844# 845# Platform Macro Definition 846# 847PLATFORM_NAME = ${platform_name} 848PLATFORM_GUID = ${platform_guid} 849PLATFORM_VERSION = ${platform_version} 850PLATFORM_RELATIVE_DIR = ${platform_relative_directory} 851PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory} 852PLATFORM_OUTPUT_DIR = ${platform_output_directory} 853 854# 855# Module Macro Definition 856# 857MODULE_NAME = ${module_name} 858MODULE_GUID = ${module_guid} 859MODULE_NAME_GUID = ${module_name_guid} 860MODULE_VERSION = ${module_version} 861MODULE_TYPE = ${module_type} 862MODULE_FILE = ${module_file} 863MODULE_FILE_BASE_NAME = ${module_file_base_name} 864BASE_NAME = $(MODULE_NAME) 865MODULE_RELATIVE_DIR = ${module_relative_directory} 866MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory} 867 868# 869# Build Configuration Macro Definition 870# 871ARCH = ${architecture} 872TOOLCHAIN = ${toolchain_tag} 873TOOLCHAIN_TAG = ${toolchain_tag} 874TARGET = ${build_target} 875 876# 877# Build Directory Macro Definition 878# 879# PLATFORM_BUILD_DIR = ${platform_build_directory} 880BUILD_DIR = ${platform_build_directory} 881BIN_DIR = $(BUILD_DIR)${separator}${architecture} 882LIB_DIR = $(BIN_DIR) 883MODULE_BUILD_DIR = ${module_build_directory} 884OUTPUT_DIR = ${module_output_directory} 885DEBUG_DIR = ${module_debug_directory} 886DEST_DIR_OUTPUT = $(OUTPUT_DIR) 887DEST_DIR_DEBUG = $(DEBUG_DIR) 888 889# 890# Tools definitions specific to this module 891# 892${BEGIN}${module_tool_definitions} 893${END} 894MAKE_FILE = ${makefile_path} 895 896# 897# Shell Command Macro 898# 899${BEGIN}${shell_command_code} = ${shell_command} 900${END} 901 902${custom_makefile_content} 903 904# 905# Target used when called from platform makefile, which will bypass the build of dependent libraries 906# 907 908pbuild: init all 909 910 911# 912# ModuleTarget 913# 914 915mbuild: init all 916 917# 918# Build Target used in multi-thread build mode, which no init target is needed 919# 920 921tbuild: all 922 923# 924# Initialization target: print build information and create necessary directories 925# 926init: 927\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)] 928${BEGIN}\t-@${create_directory_command}\n${END}\ 929 930''') 931 932 ## Constructor of CustomMakefile 933 # 934 # @param ModuleAutoGen Object of ModuleAutoGen class 935 # 936 def __init__(self, ModuleAutoGen): 937 BuildFile.__init__(self, ModuleAutoGen) 938 self.PlatformInfo = self._AutoGenObject.PlatformInfo 939 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"] 940 941 # Compose a dict object containing information used to do replacement in template 942 def _CreateTemplateDict(self): 943 Separator = self._SEP_[self._FileType] 944 if self._FileType not in self._AutoGenObject.CustomMakefile: 945 EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType, 946 ExtraData="[%s]" % str(self._AutoGenObject)) 947 MakefilePath = os.path.join( 948 self._AutoGenObject.WorkspaceDir, 949 self._AutoGenObject.CustomMakefile[self._FileType] 950 ) 951 try: 952 CustomMakefile = open(MakefilePath, 'r').read() 953 except: 954 EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(self._AutoGenObject), 955 ExtraData=self._AutoGenObject.CustomMakefile[self._FileType]) 956 957 # tools definitions 958 ToolsDef = [] 959 for Tool in self._AutoGenObject.BuildOption: 960 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable. 961 if Tool == "MAKE": 962 continue 963 for Attr in self._AutoGenObject.BuildOption[Tool]: 964 if Attr == "FAMILY": 965 continue 966 elif Attr == "PATH": 967 ToolsDef.append("%s = %s" % (Tool, self._AutoGenObject.BuildOption[Tool][Attr])) 968 else: 969 ToolsDef.append("%s_%s = %s" % (Tool, Attr, self._AutoGenObject.BuildOption[Tool][Attr])) 970 ToolsDef.append("") 971 972 MakefileName = self._FILE_NAME_[self._FileType] 973 MakefileTemplateDict = { 974 "makefile_header" : self._FILE_HEADER_[self._FileType], 975 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName), 976 "platform_name" : self.PlatformInfo.Name, 977 "platform_guid" : self.PlatformInfo.Guid, 978 "platform_version" : self.PlatformInfo.Version, 979 "platform_relative_directory": self.PlatformInfo.SourceDir, 980 "platform_output_directory" : self.PlatformInfo.OutputDir, 981 982 "module_name" : self._AutoGenObject.Name, 983 "module_guid" : self._AutoGenObject.Guid, 984 "module_name_guid" : self._AutoGenObject._GetUniqueBaseName(), 985 "module_version" : self._AutoGenObject.Version, 986 "module_type" : self._AutoGenObject.ModuleType, 987 "module_file" : self._AutoGenObject.MetaFile, 988 "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName, 989 "module_relative_directory" : self._AutoGenObject.SourceDir, 990 991 "architecture" : self._AutoGenObject.Arch, 992 "toolchain_tag" : self._AutoGenObject.ToolChain, 993 "build_target" : self._AutoGenObject.BuildTarget, 994 995 "platform_build_directory" : self.PlatformInfo.BuildDir, 996 "module_build_directory" : self._AutoGenObject.BuildDir, 997 "module_output_directory" : self._AutoGenObject.OutputDir, 998 "module_debug_directory" : self._AutoGenObject.DebugDir, 999 1000 "separator" : Separator, 1001 "module_tool_definitions" : ToolsDef, 1002 1003 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(), 1004 "shell_command" : self._SHELL_CMD_[self._FileType].values(), 1005 1006 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), 1007 "custom_makefile_content" : CustomMakefile 1008 } 1009 1010 return MakefileTemplateDict 1011 1012 _TemplateDict = property(_CreateTemplateDict) 1013 1014## PlatformMakefile class 1015# 1016# This class encapsules makefie and its generation for platform. It uses 1017# template to generate the content of makefile. The content of makefile will be 1018# got from PlatformAutoGen object. 1019# 1020class PlatformMakefile(BuildFile): 1021 ## template used to generate the makefile for platform 1022 _TEMPLATE_ = TemplateString('''\ 1023${makefile_header} 1024 1025# 1026# Platform Macro Definition 1027# 1028PLATFORM_NAME = ${platform_name} 1029PLATFORM_GUID = ${platform_guid} 1030PLATFORM_VERSION = ${platform_version} 1031PLATFORM_FILE = ${platform_file} 1032PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory} 1033PLATFORM_OUTPUT_DIR = ${platform_output_directory} 1034 1035# 1036# Build Configuration Macro Definition 1037# 1038TOOLCHAIN = ${toolchain_tag} 1039TOOLCHAIN_TAG = ${toolchain_tag} 1040TARGET = ${build_target} 1041 1042# 1043# Build Directory Macro Definition 1044# 1045BUILD_DIR = ${platform_build_directory} 1046FV_DIR = ${platform_build_directory}${separator}FV 1047 1048# 1049# Shell Command Macro 1050# 1051${BEGIN}${shell_command_code} = ${shell_command} 1052${END} 1053 1054MAKE = ${make_path} 1055MAKE_FILE = ${makefile_path} 1056 1057# 1058# Default target 1059# 1060all: init build_libraries build_modules 1061 1062# 1063# Initialization target: print build information and create necessary directories 1064# 1065init: 1066\t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}] 1067\t${BEGIN}-@${create_directory_command} 1068\t${END} 1069# 1070# library build target 1071# 1072libraries: init build_libraries 1073 1074# 1075# module build target 1076# 1077modules: init build_libraries build_modules 1078 1079# 1080# Build all libraries: 1081# 1082build_libraries: 1083${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild 1084${END}\t@cd $(BUILD_DIR) 1085 1086# 1087# Build all modules: 1088# 1089build_modules: 1090${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild 1091${END}\t@cd $(BUILD_DIR) 1092 1093# 1094# Clean intermediate files 1095# 1096clean: 1097\t${BEGIN}-@${library_build_command} clean 1098\t${END}${BEGIN}-@${module_build_command} clean 1099\t${END}@cd $(BUILD_DIR) 1100 1101# 1102# Clean all generated files except to makefile 1103# 1104cleanall: 1105${BEGIN}\t${cleanall_command} 1106${END} 1107 1108# 1109# Clean all library files 1110# 1111cleanlib: 1112\t${BEGIN}-@${library_build_command} cleanall 1113\t${END}@cd $(BUILD_DIR)\n 1114''') 1115 1116 ## Constructor of PlatformMakefile 1117 # 1118 # @param ModuleAutoGen Object of PlatformAutoGen class 1119 # 1120 def __init__(self, PlatformAutoGen): 1121 BuildFile.__init__(self, PlatformAutoGen) 1122 self.ModuleBuildCommandList = [] 1123 self.ModuleMakefileList = [] 1124 self.IntermediateDirectoryList = [] 1125 self.ModuleBuildDirectoryList = [] 1126 self.LibraryBuildDirectoryList = [] 1127 self.LibraryMakeCommandList = [] 1128 1129 # Compose a dict object containing information used to do replacement in template 1130 def _CreateTemplateDict(self): 1131 Separator = self._SEP_[self._FileType] 1132 1133 PlatformInfo = self._AutoGenObject 1134 if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]: 1135 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!", 1136 ExtraData="[%s]" % str(self._AutoGenObject)) 1137 1138 self.IntermediateDirectoryList = ["$(BUILD_DIR)"] 1139 self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList() 1140 self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList() 1141 1142 MakefileName = self._FILE_NAME_[self._FileType] 1143 LibraryMakefileList = [] 1144 LibraryMakeCommandList = [] 1145 for D in self.LibraryBuildDirectoryList: 1146 D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir}) 1147 Makefile = os.path.join(D, MakefileName) 1148 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile} 1149 LibraryMakefileList.append(Makefile) 1150 LibraryMakeCommandList.append(Command) 1151 self.LibraryMakeCommandList = LibraryMakeCommandList 1152 1153 ModuleMakefileList = [] 1154 ModuleMakeCommandList = [] 1155 for D in self.ModuleBuildDirectoryList: 1156 D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir}) 1157 Makefile = os.path.join(D, MakefileName) 1158 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile} 1159 ModuleMakefileList.append(Makefile) 1160 ModuleMakeCommandList.append(Command) 1161 1162 MakefileTemplateDict = { 1163 "makefile_header" : self._FILE_HEADER_[self._FileType], 1164 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName), 1165 "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"], 1166 "makefile_name" : MakefileName, 1167 "platform_name" : PlatformInfo.Name, 1168 "platform_guid" : PlatformInfo.Guid, 1169 "platform_version" : PlatformInfo.Version, 1170 "platform_file" : self._AutoGenObject.MetaFile, 1171 "platform_relative_directory": PlatformInfo.SourceDir, 1172 "platform_output_directory" : PlatformInfo.OutputDir, 1173 "platform_build_directory" : PlatformInfo.BuildDir, 1174 1175 "toolchain_tag" : PlatformInfo.ToolChain, 1176 "build_target" : PlatformInfo.BuildTarget, 1177 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(), 1178 "shell_command" : self._SHELL_CMD_[self._FileType].values(), 1179 "build_architecture_list" : self._AutoGenObject.Arch, 1180 "architecture" : self._AutoGenObject.Arch, 1181 "separator" : Separator, 1182 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), 1183 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList), 1184 "library_makefile_list" : LibraryMakefileList, 1185 "module_makefile_list" : ModuleMakefileList, 1186 "library_build_command" : LibraryMakeCommandList, 1187 "module_build_command" : ModuleMakeCommandList, 1188 } 1189 1190 return MakefileTemplateDict 1191 1192 ## Get the root directory list for intermediate files of all modules build 1193 # 1194 # @retval list The list of directory 1195 # 1196 def GetModuleBuildDirectoryList(self): 1197 DirList = [] 1198 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList: 1199 if not ModuleAutoGen.IsBinaryModule: 1200 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir)) 1201 return DirList 1202 1203 ## Get the root directory list for intermediate files of all libraries build 1204 # 1205 # @retval list The list of directory 1206 # 1207 def GetLibraryBuildDirectoryList(self): 1208 DirList = [] 1209 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList: 1210 if not LibraryAutoGen.IsBinaryModule: 1211 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir)) 1212 return DirList 1213 1214 _TemplateDict = property(_CreateTemplateDict) 1215 1216## TopLevelMakefile class 1217# 1218# This class encapsules makefie and its generation for entrance makefile. It 1219# uses template to generate the content of makefile. The content of makefile 1220# will be got from WorkspaceAutoGen object. 1221# 1222class TopLevelMakefile(BuildFile): 1223 ## template used to generate toplevel makefile 1224 _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}''') 1225 1226 ## Constructor of TopLevelMakefile 1227 # 1228 # @param Workspace Object of WorkspaceAutoGen class 1229 # 1230 def __init__(self, Workspace): 1231 BuildFile.__init__(self, Workspace) 1232 self.IntermediateDirectoryList = [] 1233 1234 # Compose a dict object containing information used to do replacement in template 1235 def _CreateTemplateDict(self): 1236 Separator = self._SEP_[self._FileType] 1237 1238 # any platform autogen object is ok because we just need common information 1239 PlatformInfo = self._AutoGenObject 1240 1241 if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]: 1242 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!", 1243 ExtraData="[%s]" % str(self._AutoGenObject)) 1244 1245 for Arch in PlatformInfo.ArchList: 1246 self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch])) 1247 self.IntermediateDirectoryList.append("$(FV_DIR)") 1248 1249 # TRICK: for not generating GenFds call in makefile if no FDF file 1250 MacroList = [] 1251 if PlatformInfo.FdfFile != None and PlatformInfo.FdfFile != "": 1252 FdfFileList = [PlatformInfo.FdfFile] 1253 # macros passed to GenFds 1254 MacroList.append('"%s=%s"' % ("EFI_SOURCE", GlobalData.gEfiSource.replace('\\', '\\\\'))) 1255 MacroList.append('"%s=%s"' % ("EDK_SOURCE", GlobalData.gEdkSource.replace('\\', '\\\\'))) 1256 MacroDict = {} 1257 MacroDict.update(GlobalData.gGlobalDefines) 1258 MacroDict.update(GlobalData.gCommandLineDefines) 1259 MacroDict.pop("EFI_SOURCE", "dummy") 1260 MacroDict.pop("EDK_SOURCE", "dummy") 1261 for MacroName in MacroDict: 1262 if MacroDict[MacroName] != "": 1263 MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\'))) 1264 else: 1265 MacroList.append('"%s"' % MacroName) 1266 else: 1267 FdfFileList = [] 1268 1269 # pass extra common options to external program called in makefile, currently GenFds.exe 1270 ExtraOption = '' 1271 LogLevel = EdkLogger.GetLevel() 1272 if LogLevel == EdkLogger.VERBOSE: 1273 ExtraOption += " -v" 1274 elif LogLevel <= EdkLogger.DEBUG_9: 1275 ExtraOption += " -d %d" % (LogLevel - 1) 1276 elif LogLevel == EdkLogger.QUIET: 1277 ExtraOption += " -q" 1278 1279 if GlobalData.gCaseInsensitive: 1280 ExtraOption += " -c" 1281 1282 if GlobalData.gIgnoreSource: 1283 ExtraOption += " --ignore-sources" 1284 1285 MakefileName = self._FILE_NAME_[self._FileType] 1286 SubBuildCommandList = [] 1287 for A in PlatformInfo.ArchList: 1288 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)} 1289 SubBuildCommandList.append(Command) 1290 1291 MakefileTemplateDict = { 1292 "makefile_header" : self._FILE_HEADER_[self._FileType], 1293 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName), 1294 "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"], 1295 "platform_name" : PlatformInfo.Name, 1296 "platform_guid" : PlatformInfo.Guid, 1297 "platform_version" : PlatformInfo.Version, 1298 "platform_build_directory" : PlatformInfo.BuildDir, 1299 "conf_directory" : GlobalData.gConfDirectory, 1300 1301 "toolchain_tag" : PlatformInfo.ToolChain, 1302 "build_target" : PlatformInfo.BuildTarget, 1303 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(), 1304 "shell_command" : self._SHELL_CMD_[self._FileType].values(), 1305 'arch' : list(PlatformInfo.ArchList), 1306 "build_architecture_list" : ','.join(PlatformInfo.ArchList), 1307 "separator" : Separator, 1308 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), 1309 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList), 1310 "sub_build_command" : SubBuildCommandList, 1311 "fdf_file" : FdfFileList, 1312 "active_platform" : str(PlatformInfo), 1313 "fd" : PlatformInfo.FdTargetList, 1314 "fv" : PlatformInfo.FvTargetList, 1315 "cap" : PlatformInfo.CapTargetList, 1316 "extra_options" : ExtraOption, 1317 "macro" : MacroList, 1318 } 1319 1320 return MakefileTemplateDict 1321 1322 ## Get the root directory list for intermediate files of all modules build 1323 # 1324 # @retval list The list of directory 1325 # 1326 def GetModuleBuildDirectoryList(self): 1327 DirList = [] 1328 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList: 1329 if not ModuleAutoGen.IsBinaryModule: 1330 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir)) 1331 return DirList 1332 1333 ## Get the root directory list for intermediate files of all libraries build 1334 # 1335 # @retval list The list of directory 1336 # 1337 def GetLibraryBuildDirectoryList(self): 1338 DirList = [] 1339 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList: 1340 if not LibraryAutoGen.IsBinaryModule: 1341 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir)) 1342 return DirList 1343 1344 _TemplateDict = property(_CreateTemplateDict) 1345 1346# This acts like the main() function for the script, unless it is 'import'ed into another script. 1347if __name__ == '__main__': 1348 pass 1349 1350