2 # Create makefile for MS nmake and GNU make
4 # Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
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.
16 import Common
.LongFilePathOs
as os
20 import os
.path
as path
21 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
22 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
23 from Common
.BuildToolError
import *
24 from Common
.Misc
import *
25 from Common
.String
import *
26 from BuildEngine
import *
27 import Common
.GlobalData
as GlobalData
29 ## Regular expression for finding header file inclusions
30 gIncludePattern
= re
.compile(r
"^[ \t]*#?[ \t]*include(?:[ \t]*(?:\\(?:\r\n|\r|\n))*[ \t]*)*(?:\(?[\"<]?
[ \t]*)([-\w
.\\/() \t]+)(?
:[ \t]*[\">]?\
)?
)", re.MULTILINE | re.UNICODE | re.IGNORECASE)
32 ## Regular expression for matching macro used in header file inclusion
33 gMacroPattern = re.compile("([_A
-Z
][_A
-Z0
-9]*)[ \t]*\
((.+)\
)", re.UNICODE)
37 ## pattern for include style in Edk.x code
38 gProtocolDefinition = "Protocol
/%(HeaderKey)s/%(HeaderKey)s.h
"
39 gGuidDefinition = "Guid
/%(HeaderKey)s/%(HeaderKey)s.h
"
40 gArchProtocolDefinition = "ArchProtocol
/%(HeaderKey)s/%(HeaderKey)s.h
"
41 gPpiDefinition = "Ppi
/%(HeaderKey)s/%(HeaderKey)s.h
"
42 gIncludeMacroConversion = {
43 "EFI_PROTOCOL_DEFINITION
" : gProtocolDefinition,
44 "EFI_GUID_DEFINITION
" : gGuidDefinition,
45 "EFI_ARCH_PROTOCOL_DEFINITION
" : gArchProtocolDefinition,
46 "EFI_PROTOCOL_PRODUCER
" : gProtocolDefinition,
47 "EFI_PROTOCOL_CONSUMER
" : gProtocolDefinition,
48 "EFI_PROTOCOL_DEPENDENCY
" : gProtocolDefinition,
49 "EFI_ARCH_PROTOCOL_PRODUCER
" : gArchProtocolDefinition,
50 "EFI_ARCH_PROTOCOL_CONSUMER
" : gArchProtocolDefinition,
51 "EFI_ARCH_PROTOCOL_DEPENDENCY
" : gArchProtocolDefinition,
52 "EFI_PPI_DEFINITION
" : gPpiDefinition,
53 "EFI_PPI_PRODUCER
" : gPpiDefinition,
54 "EFI_PPI_CONSUMER
" : gPpiDefinition,
55 "EFI_PPI_DEPENDENCY
" : gPpiDefinition,
58 ## default makefile type
60 if sys.platform == "win32
":
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.
71 class BuildFile(object):
72 ## template used to generate the build file (i.e. makefile if using make)
73 _TEMPLATE_ = TemplateString('')
75 _DEFAULT_FILE_NAME_ = "Makefile
"
77 ## default file name for each type of build file
80 "gmake
" : "GNUmakefile
"
83 ## Fixed header string for makefile
84 _MAKEFILE_HEADER = '''#
86 # This file is auto-generated by build utility
94 # Auto-generated makefile for building modules, libraries or platform
98 ## Header string for each type of build file
100 "nmake
" : _MAKEFILE_HEADER % _FILE_NAME_["nmake
"],
101 "gmake
" : _MAKEFILE_HEADER % _FILE_NAME_["gmake
"]
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
117 "RD
" : "rmdir
/s
/q
",
129 ## directory separator
135 ## directory creation template
137 "nmake
" : 'if not exist %(dir)s $(MD) %(dir)s',
138 "gmake
" : "$
(MD
) %(dir)s"
141 ## directory removal template
143 "nmake
" : 'if exist %(dir)s $(RD) %(dir)s',
144 "gmake
" : "$
(RD
) %(dir)s"
148 "nmake
" : 'if exist %(dir)s cd %(dir)s',
149 "gmake
" : "test
-e
%(dir)s && cd
%(dir)s"
153 "nmake
" : 'if exist %(file)s "$
(MAKE
)" $(MAKE_FLAGS) -f %(file)s',
154 "gmake
" : 'test -e %(file)s && "$
(MAKE
)" $(MAKE_FLAGS) -f %(file)s'
158 "nmake
" : '!INCLUDE',
162 _INC_FLAG_ = {"MSFT
" : "/I
", "GCC
" : "-I
", "INTEL
" : "-I
", "RVCT
" : "-I
"}
164 ## Constructor of BuildFile
166 # @param AutoGenObject Object of AutoGen class
168 def __init__(self, AutoGenObject):
169 self._AutoGenObject = AutoGenObject
170 self._FileType = gMakeType
174 # @param FileType Type of build file. Only nmake and gmake are supported now.
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
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)
188 ## Return a list of directory creation command string
190 # @param DirList The list of directory to be created
192 # @retval list The directory creation command list
194 def GetCreateDirectoryCommand(self, DirList):
195 return [self._MD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
197 ## Return a list of directory removal command string
199 # @param DirList The list of directory to be removed
201 # @retval list The directory removal command list
203 def GetRemoveDirectoryCommand(self, DirList):
204 return [self._RD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
206 def PlaceMacro(self, Path, MacroDefinitions={}):
207 if Path.startswith("$
("):
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:])
219 ## ModuleMakefile class
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.
224 class ModuleMakefile(BuildFile):
225 ## template used to generate the makefile for module
226 _TEMPLATE_ = TemplateString('''\
230 # Platform Macro Definition
232 PLATFORM_NAME = ${platform_name}
233 PLATFORM_GUID = ${platform_guid}
234 PLATFORM_VERSION = ${platform_version}
235 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
236 PLATFORM_DIR = ${platform_dir}
237 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
240 # Module Macro Definition
242 MODULE_NAME = ${module_name}
243 MODULE_GUID = ${module_guid}
244 MODULE_NAME_GUID = ${module_name_guid}
245 MODULE_VERSION = ${module_version}
246 MODULE_TYPE = ${module_type}
247 MODULE_FILE = ${module_file}
248 MODULE_FILE_BASE_NAME = ${module_file_base_name}
249 BASE_NAME = $(MODULE_NAME)
250 MODULE_RELATIVE_DIR = ${module_relative_directory}
251 PACKAGE_RELATIVE_DIR = ${package_relative_directory}
252 MODULE_DIR = ${module_dir}
254 MODULE_ENTRY_POINT = ${module_entry_point}
255 ARCH_ENTRY_POINT = ${arch_entry_point}
256 IMAGE_ENTRY_POINT = ${image_entry_point}
258 ${BEGIN}${module_extra_defines}
261 # Build Configuration Macro Definition
263 ARCH = ${architecture}
264 TOOLCHAIN = ${toolchain_tag}
265 TOOLCHAIN_TAG = ${toolchain_tag}
266 TARGET = ${build_target}
269 # Build Directory Macro Definition
271 # PLATFORM_BUILD_DIR = ${platform_build_directory}
272 BUILD_DIR = ${platform_build_directory}
273 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
275 MODULE_BUILD_DIR = ${module_build_directory}
276 OUTPUT_DIR = ${module_output_directory}
277 DEBUG_DIR = ${module_debug_directory}
278 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
279 DEST_DIR_DEBUG = $(DEBUG_DIR)
282 # Shell Command Macro
284 ${BEGIN}${shell_command_code} = ${shell_command}
288 # Tools definitions specific to this module
290 ${BEGIN}${module_tool_definitions}
292 MAKE_FILE = ${makefile_path}
297 ${BEGIN}${file_macro}
300 COMMON_DEPS = ${BEGIN}${common_dependency_file} \\
304 # Overridable Target Macro Definitions
306 FORCE_REBUILD = force_build
309 BC_TARGET = ${BEGIN}${backward_compatible_target} ${END}
310 CODA_TARGET = ${BEGIN}${remaining_build_target} \\
314 # Default target, which will build dependent libraries in addition to source files
321 # Target used when called from platform makefile, which will bypass the build of dependent libraries
324 pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
330 mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET)
333 # Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets
336 tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
339 # Phony target which is used to force executing commands for a target
345 # Target to update the FD
351 # Initialization target: print build information and create necessary directories
356 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
359 ${BEGIN}\t-@${create_directory_command}\n${END}
362 \t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h
368 \t${BEGIN}@"$
(MAKE
)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name}
369 \t${END}@cd $(MODULE_BUILD_DIR)
372 # Build Flash Device Image
375 \t@"$
(MAKE
)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds
376 \t@cd $(MODULE_BUILD_DIR)
379 # Individual Object Build Targets
381 ${BEGIN}${file_build_target}
385 # clean all intermediate files
388 \t${BEGIN}${clean_command}
392 # clean all generated files
395 ${BEGIN}\t${cleanall_command}
396 ${END}\t$(RM) *.pdb *.idb > NUL 2>&1
397 \t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi
400 # clean all dependent libraries built
403 \t${BEGIN}-@${library_build_command} cleanall
404 \t${END}@cd $(MODULE_BUILD_DIR)\n\n''')
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")
409 ## Constructor of ModuleMakefile
411 # @param ModuleAutoGen Object of ModuleAutoGen class
413 def __init__(self, ModuleAutoGen):
414 BuildFile.__init__(self, ModuleAutoGen)
415 self.PlatformInfo = self._AutoGenObject.PlatformInfo
417 self.ResultFileList = []
418 self.IntermediateDirectoryList = ["$
(DEBUG_DIR
)", "$
(OUTPUT_DIR
)"]
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 = {}
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
"]
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]
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))
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]
462 ModuleEntryPoint = "_ModuleEntryPoint
"
464 # Intel EBC compiler enforces EfiMain
465 if self._AutoGenObject.AutoGenVersion < 0x00010005 and self._AutoGenObject.Arch == "EBC
":
466 ArchEntryPoint = "EfiMain
"
468 ArchEntryPoint = ModuleEntryPoint
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
477 # EdkII modules always use "_ModuleEntryPoint
" as entry point
478 ImageEntryPoint = "_ModuleEntryPoint
"
480 for k, v in self._AutoGenObject.Module.Defines.iteritems():
481 if k not in self._AutoGenObject.Macros.keys():
482 self._AutoGenObject.Macros[k] = v
484 if 'MODULE_ENTRY_POINT' not in self._AutoGenObject.Macros.keys():
485 self._AutoGenObject.Macros['MODULE_ENTRY_POINT'] = ModuleEntryPoint
486 if 'ARCH_ENTRY_POINT' not in self._AutoGenObject.Macros.keys():
487 self._AutoGenObject.Macros['ARCH_ENTRY_POINT'] = ArchEntryPoint
488 if 'IMAGE_ENTRY_POINT' not in self._AutoGenObject.Macros.keys():
489 self._AutoGenObject.Macros['IMAGE_ENTRY_POINT'] = ImageEntryPoint
491 PCI_COMPRESS_Flag = False
492 for k, v in self._AutoGenObject.Module.Defines.iteritems():
493 if 'PCI_COMPRESS' == k and 'TRUE' == v:
494 PCI_COMPRESS_Flag = True
498 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
499 for Tool in self._AutoGenObject.BuildOption:
500 for Attr in self._AutoGenObject.BuildOption[Tool]:
501 Value = self._AutoGenObject.BuildOption[Tool][Attr]
505 ToolsDef.append("%s = %s" % (Tool, Value))
507 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
510 # Remove duplicated include path, if any
512 Value = RemoveDupOption(Value, IncPrefix, self._AutoGenObject.IncludePathList)
513 if Tool == "OPTROM
" and PCI_COMPRESS_Flag:
514 ValueList = Value.split()
516 for i, v in enumerate(ValueList):
519 Value = ' '.join(ValueList)
521 ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
524 # generate the Response file and Response flag
525 RespDict = self.CommandExceedLimit()
526 RespFileList = os.path.join(self._AutoGenObject.OutputDir, 'respfilelist.txt')
528 RespFileListContent = ''
529 for Resp in RespDict.keys():
530 RespFile = os.path.join(self._AutoGenObject.OutputDir, str(Resp).lower() + '.txt')
531 StrList = RespDict[Resp].split(' ')
536 UnexpandMacro.append(Str)
539 UnexpandMacroStr = ' '.join(UnexpandMacro)
540 NewRespStr = ' '.join(NewStr)
541 SaveFileOnChange(RespFile, NewRespStr, False)
542 ToolsDef.append("%s = %s" % (Resp, UnexpandMacroStr + ' @' + RespFile))
543 RespFileListContent += '@' + RespFile + os.linesep
544 RespFileListContent += NewRespStr + os.linesep
545 SaveFileOnChange(RespFileList, RespFileListContent, False)
547 if os.path.exists(RespFileList):
548 os.remove(RespFileList)
550 # convert source files and binary files to build targets
551 self.ResultFileList = [str(T.Target) for T in self._AutoGenObject.CodaTargetList]
552 if len(self.ResultFileList) == 0 and len(self._AutoGenObject.SourceFileList) <> 0:
553 EdkLogger.error("build
", AUTOGEN_ERROR, "Nothing to build
",
554 ExtraData="[%s]" % str(self._AutoGenObject))
556 self.ProcessBuildTargetList()
558 # Generate macros used to represent input files
559 FileMacroList = [] # macro name = file list
560 for FileListMacro in self.FileListMacros:
561 FileMacro = self._FILE_MACRO_TEMPLATE.Replace(
563 "macro_name
" : FileListMacro,
564 "source_file
" : self.FileListMacros[FileListMacro]
567 FileMacroList.append(FileMacro)
569 # INC_LIST is special
572 for P in self._AutoGenObject.IncludePathList:
573 IncludePathList.append(IncPrefix + self.PlaceMacro(P, self.Macros))
574 if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:
575 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix + P)
576 FileMacro += self._FILE_MACRO_TEMPLATE.Replace(
578 "macro_name
" : "INC
",
579 "source_file
" : IncludePathList
582 FileMacroList.append(FileMacro)
584 # Generate macros used to represent files containing list of input files
585 for ListFileMacro in self.ListFileMacros:
586 ListFileName = os.path.join(self._AutoGenObject.OutputDir, "%s.lst
" % ListFileMacro.lower()[:len(ListFileMacro) - 5])
587 FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))
590 "\n".join(self.ListFileMacros[ListFileMacro]),
594 # Edk modules need <BaseName>StrDefs.h for string ID
595 #if self._AutoGenObject.AutoGenVersion < 0x00010005 and len(self._AutoGenObject.UnicodeFileList) > 0:
596 # BcTargetList = ['strdefs']
601 MakefileName = self._FILE_NAME_[self._FileType]
602 LibraryMakeCommandList = []
603 for D in self.LibraryBuildDirectoryList:
604 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)}
605 LibraryMakeCommandList.append(Command)
607 package_rel_dir = self._AutoGenObject.SourceDir
608 current_dir = self.Macros["WORKSPACE
"]
610 while not found and os.sep in package_rel_dir:
611 index = package_rel_dir.index(os.sep)
612 current_dir = mws.join(current_dir, package_rel_dir[:index])
613 if os.path.exists(current_dir):
614 for fl in os.listdir(current_dir):
615 if fl.endswith('.dec'):
618 package_rel_dir = package_rel_dir[index + 1:]
620 MakefileTemplateDict = {
621 "makefile_header
" : self._FILE_HEADER_[self._FileType],
622 "makefile_path
" : os.path.join("$
(MODULE_BUILD_DIR
)", MakefileName),
623 "makefile_name
" : MakefileName,
624 "platform_name
" : self.PlatformInfo.Name,
625 "platform_guid
" : self.PlatformInfo.Guid,
626 "platform_version
" : self.PlatformInfo.Version,
627 "platform_relative_directory
": self.PlatformInfo.SourceDir,
628 "platform_output_directory
" : self.PlatformInfo.OutputDir,
629 "platform_dir
" : self._AutoGenObject.Macros["PLATFORM_DIR
"],
631 "module_name
" : self._AutoGenObject.Name,
632 "module_guid
" : self._AutoGenObject.Guid,
633 "module_name_guid
" : self._AutoGenObject._GetUniqueBaseName(),
634 "module_version
" : self._AutoGenObject.Version,
635 "module_type
" : self._AutoGenObject.ModuleType,
636 "module_file
" : self._AutoGenObject.MetaFile.Name,
637 "module_file_base_name
" : self._AutoGenObject.MetaFile.BaseName,
638 "module_relative_directory
" : self._AutoGenObject.SourceDir,
639 "module_dir
" : mws.join (self.Macros["WORKSPACE
"], self._AutoGenObject.SourceDir),
640 "package_relative_directory
": package_rel_dir,
641 "module_extra_defines
" : ["%s = %s" % (k, v) for k, v in self._AutoGenObject.Module.Defines.iteritems()],
643 "architecture
" : self._AutoGenObject.Arch,
644 "toolchain_tag
" : self._AutoGenObject.ToolChain,
645 "build_target
" : self._AutoGenObject.BuildTarget,
647 "platform_build_directory
" : self.PlatformInfo.BuildDir,
648 "module_build_directory
" : self._AutoGenObject.BuildDir,
649 "module_output_directory
" : self._AutoGenObject.OutputDir,
650 "module_debug_directory
" : self._AutoGenObject.DebugDir,
652 "separator
" : Separator,
653 "module_tool_definitions
" : ToolsDef,
655 "shell_command_code
" : self._SHELL_CMD_[self._FileType].keys(),
656 "shell_command
" : self._SHELL_CMD_[self._FileType].values(),
658 "module_entry_point
" : ModuleEntryPoint,
659 "image_entry_point
" : ImageEntryPoint,
660 "arch_entry_point
" : ArchEntryPoint,
661 "remaining_build_target
" : self.ResultFileList,
662 "common_dependency_file
" : self.CommonFileDependency,
663 "create_directory_command
" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
664 "clean_command
" : self.GetRemoveDirectoryCommand(["$
(OUTPUT_DIR
)"]),
665 "cleanall_command
" : self.GetRemoveDirectoryCommand(["$
(DEBUG_DIR
)", "$
(OUTPUT_DIR
)"]),
666 "dependent_library_build_directory
" : self.LibraryBuildDirectoryList,
667 "library_build_command
" : LibraryMakeCommandList,
668 "file_macro
" : FileMacroList,
669 "file_build_target
" : self.BuildTargetList,
670 "backward_compatible_target
": BcTargetList,
673 return MakefileTemplateDict
675 def CommandExceedLimit(self):
677 'CC' : { 'Macro' : '$(CC_FLAGS)', 'Value' : False},
678 'PP' : { 'Macro' : '$(PP_FLAGS)', 'Value' : False},
679 'APP' : { 'Macro' : '$(APP_FLAGS)', 'Value' : False},
680 'ASLPP' : { 'Macro' : '$(ASLPP_FLAGS)', 'Value' : False},
681 'VFRPP' : { 'Macro' : '$(VFRPP_FLAGS)', 'Value' : False},
682 'ASM' : { 'Macro' : '$(ASM_FLAGS)', 'Value' : False},
683 'ASLCC' : { 'Macro' : '$(ASLCC_FLAGS)', 'Value' : False},
688 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
690 # base on the source files to decide the file type
691 for File in self._AutoGenObject.SourceFileList:
692 for type in self._AutoGenObject.FileTypes:
693 if File in self._AutoGenObject.FileTypes[type]:
694 if type not in FileTypeList:
695 FileTypeList.append(type)
697 # calculate the command-line length
699 for type in FileTypeList:
700 BuildTargets = self._AutoGenObject.BuildRules[type].BuildTargets
701 for Target in BuildTargets:
702 CommandList = BuildTargets[Target].Commands
703 for SingleCommand in CommandList:
705 SingleCommandLength = len(SingleCommand)
706 SingleCommandList = SingleCommand.split()
707 if len(SingleCommandList) > 0:
708 for Flag in FlagDict.keys():
709 if '$('+ Flag +')' in SingleCommandList[0]:
713 SingleCommandLength += len(self._AutoGenObject._BuildOption[Tool]['PATH'])
714 for item in SingleCommandList[1:]:
715 if FlagDict[Tool]['Macro'] in item:
716 Str = self._AutoGenObject._BuildOption[Tool]['FLAGS']
717 for Option in self._AutoGenObject.BuildOption.keys():
718 for Attr in self._AutoGenObject.BuildOption[Option]:
719 if Str.find(Option + '_' + Attr) != -1:
720 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
721 while(Str.find('$(') != -1):
722 for macro in self._AutoGenObject.Macros.keys():
723 MacroName = '$('+ macro + ')'
724 if (Str.find(MacroName) != -1):
725 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
729 SingleCommandLength += len(Str)
730 elif '$(INC)' in item:
731 SingleCommandLength += self._AutoGenObject.IncludePathLength + len(IncPrefix) * len(self._AutoGenObject._IncludePathList)
732 elif item.find('$(') != -1:
734 for Option in self._AutoGenObject.BuildOption.keys():
735 for Attr in self._AutoGenObject.BuildOption[Option]:
736 if Str.find(Option + '_' + Attr) != -1:
737 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
738 while(Str.find('$(') != -1):
739 for macro in self._AutoGenObject.Macros.keys():
740 MacroName = '$('+ macro + ')'
741 if (Str.find(MacroName) != -1):
742 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
746 SingleCommandLength += len(Str)
748 if SingleCommandLength > GlobalData.gCommandMaxLength:
749 FlagDict[Tool]['Value'] = True
751 # generate the response file content by combine the FLAGS and INC
752 for Flag in FlagDict.keys():
753 if FlagDict[Flag]['Value']:
755 RespMacro = FlagDict[Flag]['Macro'].replace('FLAGS', 'RESP')
756 Value = self._AutoGenObject.BuildOption[Flag]['FLAGS']
757 for inc in self._AutoGenObject._IncludePathList:
758 Value += ' ' + IncPrefix + inc
759 for Option in self._AutoGenObject.BuildOption.keys():
760 for Attr in self._AutoGenObject.BuildOption[Option]:
761 if Value.find(Option + '_' + Attr) != -1:
762 Value = Value.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
763 while (Value.find('$(') != -1):
764 for macro in self._AutoGenObject.Macros.keys():
765 MacroName = '$('+ macro + ')'
766 if (Value.find(MacroName) != -1):
767 Value = Value.replace(MacroName, self._AutoGenObject.Macros[macro])
771 RespDict[Key] = Value
772 for Target in BuildTargets:
773 for i, SingleCommand in enumerate(BuildTargets[Target].Commands):
774 if FlagDict[Flag]['Macro'] in SingleCommand:
775 BuildTargets[Target].Commands[i] = SingleCommand.replace('$(INC)','').replace(FlagDict[Flag]['Macro'], RespMacro)
778 def ProcessBuildTargetList(self):
780 # Search dependency file list for each source file
782 ForceIncludedFile = []
783 for File in self._AutoGenObject.AutoGenFileList:
785 ForceIncludedFile.append(File)
787 for Target in self._AutoGenObject.IntroTargetList:
788 SourceFileList.extend(Target.Inputs)
790 self.FileDependency = self.GetFileDependency(
793 self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList
796 for File in self.FileDependency:
797 if not self.FileDependency[File]:
798 self.FileDependency[File] = ['$(FORCE_REBUILD)']
801 if File.Ext not in [".c
", ".C
"] or File.Name == "AutoGen
.c
":
804 DepSet = set(self.FileDependency[File])
806 DepSet &= set(self.FileDependency[File])
807 # in case nothing in SourceFileList
811 # Extract common files list in the dependency files
814 self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros))
816 for File in self.FileDependency:
818 if File.Ext not in [".c
", ".C
"] or File.Name == "AutoGen
.c
":
820 NewDepSet = set(self.FileDependency[File])
822 self.FileDependency[File] = ["$
(COMMON_DEPS
)"] + list(NewDepSet)
824 # Convert target description object to target string in makefile
825 for Type in self._AutoGenObject.Targets:
826 for T in self._AutoGenObject.Targets[Type]:
827 # Generate related macros if needed
828 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
829 self.FileListMacros[T.FileListMacro] = []
830 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:
831 self.ListFileMacros[T.ListFileMacro] = []
832 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:
833 self.ListFileMacros[T.IncListFileMacro] = []
836 # Add force-dependencies
837 for Dep in T.Dependencies:
838 Deps.append(self.PlaceMacro(str(Dep), self.Macros))
839 # Add inclusion-dependencies
840 if len(T.Inputs) == 1 and T.Inputs[0] in self.FileDependency:
841 for F in self.FileDependency[T.Inputs[0]]:
842 Deps.append(self.PlaceMacro(str(F), self.Macros))
843 # Add source-dependencies
845 NewFile = self.PlaceMacro(str(F), self.Macros)
846 # In order to use file list macro as dependency
848 # gnu tools need forward slash path separater, even on Windows
849 self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/'))
850 self.FileListMacros[T.FileListMacro].append(NewFile)
851 elif T.GenFileListMacro:
852 self.FileListMacros[T.FileListMacro].append(NewFile)
856 # Use file list macro as dependency
857 if T.GenFileListMacro:
858 Deps.append("$
(%s)" % T.FileListMacro)
861 "target
" : self.PlaceMacro(T.Target.Path, self.Macros),
862 "cmd
" : "\n\t".join(T.Commands),
865 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
867 ## For creating makefile targets for dependent libraries
868 def ProcessDependentLibrary(self):
869 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
870 if not LibraryAutoGen.IsBinaryModule:
871 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
873 ## Return a list containing source file's dependencies
875 # @param FileList The list of source files
876 # @param ForceInculeList The list of files which will be included forcely
877 # @param SearchPathList The list of search path
879 # @retval dict The mapping between source file path and its dependencies
881 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
884 Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)
887 ## Find dependencies for one source file
889 # By searching recursively "#include" directive in file, find out all the
890 # files needed by given source file. The dependecies will be only searched
891 # in given search path list.
893 # @param File The source file
894 # @param ForceInculeList The list of files which will be included forcely
895 # @param SearchPathList The list of search path
897 # @retval list The list of files the given source file depends on
899 def GetDependencyList(self
, File
, ForceList
, SearchPathList
):
900 EdkLogger
.debug(EdkLogger
.DEBUG_1
, "Try to get dependency files for %s" % File
)
901 FileStack
= [File
] + ForceList
902 DependencySet
= set()
904 if self
._AutoGenObject
.Arch
not in gDependencyDatabase
:
905 gDependencyDatabase
[self
._AutoGenObject
.Arch
] = {}
906 DepDb
= gDependencyDatabase
[self
._AutoGenObject
.Arch
]
908 while len(FileStack
) > 0:
911 FullPathDependList
= []
912 if F
in self
.FileCache
:
913 for CacheFile
in self
.FileCache
[F
]:
914 FullPathDependList
.append(CacheFile
)
915 if CacheFile
not in DependencySet
:
916 FileStack
.append(CacheFile
)
917 DependencySet
.update(FullPathDependList
)
920 CurrentFileDependencyList
= []
922 CurrentFileDependencyList
= DepDb
[F
]
925 Fd
= open(F
.Path
, 'r')
926 except BaseException
, X
:
927 EdkLogger
.error("build", FILE_OPEN_FAILURE
, ExtraData
=F
.Path
+ "\n\t" + str(X
))
929 FileContent
= Fd
.read()
931 if len(FileContent
) == 0:
934 if FileContent
[0] == 0xff or FileContent
[0] == 0xfe:
935 FileContent
= unicode(FileContent
, "utf-16")
936 IncludedFileList
= gIncludePattern
.findall(FileContent
)
938 for Inc
in IncludedFileList
:
940 # if there's macro used to reference header file, expand it
941 HeaderList
= gMacroPattern
.findall(Inc
)
942 if len(HeaderList
) == 1 and len(HeaderList
[0]) == 2:
943 HeaderType
= HeaderList
[0][0]
944 HeaderKey
= HeaderList
[0][1]
945 if HeaderType
in gIncludeMacroConversion
:
946 Inc
= gIncludeMacroConversion
[HeaderType
] % {"HeaderKey" : HeaderKey
}
948 # not known macro used in #include, always build the file by
949 # returning a empty dependency
950 self
.FileCache
[File
] = []
952 Inc
= os
.path
.normpath(Inc
)
953 CurrentFileDependencyList
.append(Inc
)
954 DepDb
[F
] = CurrentFileDependencyList
956 CurrentFilePath
= F
.Dir
957 PathList
= [CurrentFilePath
] + SearchPathList
958 for Inc
in CurrentFileDependencyList
:
959 for SearchPath
in PathList
:
960 FilePath
= os
.path
.join(SearchPath
, Inc
)
961 if FilePath
in gIsFileMap
:
962 if not gIsFileMap
[FilePath
]:
964 # If isfile is called too many times, the performance is slow down.
965 elif not os
.path
.isfile(FilePath
):
966 gIsFileMap
[FilePath
] = False
969 gIsFileMap
[FilePath
] = True
970 FilePath
= PathClass(FilePath
)
971 FullPathDependList
.append(FilePath
)
972 if FilePath
not in DependencySet
:
973 FileStack
.append(FilePath
)
976 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "%s included by %s was not found "\
977 "in any given path:\n\t%s" % (Inc
, F
, "\n\t".join(SearchPathList
)))
979 self
.FileCache
[F
] = FullPathDependList
980 DependencySet
.update(FullPathDependList
)
982 DependencySet
.update(ForceList
)
983 if File
in DependencySet
:
984 DependencySet
.remove(File
)
985 DependencyList
= list(DependencySet
) # remove duplicate ones
987 return DependencyList
989 _TemplateDict
= property(_CreateTemplateDict
)
991 ## CustomMakefile class
993 # This class encapsules makefie and its generation for module. It uses template to generate
994 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
996 class CustomMakefile(BuildFile
):
997 ## template used to generate the makefile for module with custom makefile
998 _TEMPLATE_
= TemplateString('''\
1002 # Platform Macro Definition
1004 PLATFORM_NAME = ${platform_name}
1005 PLATFORM_GUID = ${platform_guid}
1006 PLATFORM_VERSION = ${platform_version}
1007 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
1008 PLATFORM_DIR = ${platform_dir}
1009 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1012 # Module Macro Definition
1014 MODULE_NAME = ${module_name}
1015 MODULE_GUID = ${module_guid}
1016 MODULE_NAME_GUID = ${module_name_guid}
1017 MODULE_VERSION = ${module_version}
1018 MODULE_TYPE = ${module_type}
1019 MODULE_FILE = ${module_file}
1020 MODULE_FILE_BASE_NAME = ${module_file_base_name}
1021 BASE_NAME = $(MODULE_NAME)
1022 MODULE_RELATIVE_DIR = ${module_relative_directory}
1023 MODULE_DIR = ${module_dir}
1026 # Build Configuration Macro Definition
1028 ARCH = ${architecture}
1029 TOOLCHAIN = ${toolchain_tag}
1030 TOOLCHAIN_TAG = ${toolchain_tag}
1031 TARGET = ${build_target}
1034 # Build Directory Macro Definition
1036 # PLATFORM_BUILD_DIR = ${platform_build_directory}
1037 BUILD_DIR = ${platform_build_directory}
1038 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
1039 LIB_DIR = $(BIN_DIR)
1040 MODULE_BUILD_DIR = ${module_build_directory}
1041 OUTPUT_DIR = ${module_output_directory}
1042 DEBUG_DIR = ${module_debug_directory}
1043 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
1044 DEST_DIR_DEBUG = $(DEBUG_DIR)
1047 # Tools definitions specific to this module
1049 ${BEGIN}${module_tool_definitions}
1051 MAKE_FILE = ${makefile_path}
1054 # Shell Command Macro
1056 ${BEGIN}${shell_command_code} = ${shell_command}
1059 ${custom_makefile_content}
1062 # Target used when called from platform makefile, which will bypass the build of dependent libraries
1075 # Build Target used in multi-thread build mode, which no init target is needed
1081 # Initialization target: print build information and create necessary directories
1084 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
1085 ${BEGIN}\t-@${create_directory_command}\n${END}\
1089 ## Constructor of CustomMakefile
1091 # @param ModuleAutoGen Object of ModuleAutoGen class
1093 def __init__(self
, ModuleAutoGen
):
1094 BuildFile
.__init
__(self
, ModuleAutoGen
)
1095 self
.PlatformInfo
= self
._AutoGenObject
.PlatformInfo
1096 self
.IntermediateDirectoryList
= ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
1098 # Compose a dict object containing information used to do replacement in template
1099 def _CreateTemplateDict(self
):
1100 Separator
= self
._SEP
_[self
._FileType
]
1101 if self
._FileType
not in self
._AutoGenObject
.CustomMakefile
:
1102 EdkLogger
.error('build', OPTION_NOT_SUPPORTED
, "No custom makefile for %s" % self
._FileType
,
1103 ExtraData
="[%s]" % str(self
._AutoGenObject
))
1104 MakefilePath
= mws
.join(
1105 self
._AutoGenObject
.WorkspaceDir
,
1106 self
._AutoGenObject
.CustomMakefile
[self
._FileType
]
1109 CustomMakefile
= open(MakefilePath
, 'r').read()
1111 EdkLogger
.error('build', FILE_OPEN_FAILURE
, File
=str(self
._AutoGenObject
),
1112 ExtraData
=self
._AutoGenObject
.CustomMakefile
[self
._FileType
])
1116 for Tool
in self
._AutoGenObject
.BuildOption
:
1117 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
1120 for Attr
in self
._AutoGenObject
.BuildOption
[Tool
]:
1121 if Attr
== "FAMILY":
1123 elif Attr
== "PATH":
1124 ToolsDef
.append("%s = %s" % (Tool
, self
._AutoGenObject
.BuildOption
[Tool
][Attr
]))
1126 ToolsDef
.append("%s_%s = %s" % (Tool
, Attr
, self
._AutoGenObject
.BuildOption
[Tool
][Attr
]))
1129 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1130 MakefileTemplateDict
= {
1131 "makefile_header" : self
._FILE
_HEADER
_[self
._FileType
],
1132 "makefile_path" : os
.path
.join("$(MODULE_BUILD_DIR)", MakefileName
),
1133 "platform_name" : self
.PlatformInfo
.Name
,
1134 "platform_guid" : self
.PlatformInfo
.Guid
,
1135 "platform_version" : self
.PlatformInfo
.Version
,
1136 "platform_relative_directory": self
.PlatformInfo
.SourceDir
,
1137 "platform_output_directory" : self
.PlatformInfo
.OutputDir
,
1138 "platform_dir" : self
._AutoGenObject
.Macros
["PLATFORM_DIR"],
1140 "module_name" : self
._AutoGenObject
.Name
,
1141 "module_guid" : self
._AutoGenObject
.Guid
,
1142 "module_name_guid" : self
._AutoGenObject
._GetUniqueBaseName
(),
1143 "module_version" : self
._AutoGenObject
.Version
,
1144 "module_type" : self
._AutoGenObject
.ModuleType
,
1145 "module_file" : self
._AutoGenObject
.MetaFile
,
1146 "module_file_base_name" : self
._AutoGenObject
.MetaFile
.BaseName
,
1147 "module_relative_directory" : self
._AutoGenObject
.SourceDir
,
1148 "module_dir" : mws
.join (self
._AutoGenObject
.WorkspaceDir
, self
._AutoGenObject
.SourceDir
),
1150 "architecture" : self
._AutoGenObject
.Arch
,
1151 "toolchain_tag" : self
._AutoGenObject
.ToolChain
,
1152 "build_target" : self
._AutoGenObject
.BuildTarget
,
1154 "platform_build_directory" : self
.PlatformInfo
.BuildDir
,
1155 "module_build_directory" : self
._AutoGenObject
.BuildDir
,
1156 "module_output_directory" : self
._AutoGenObject
.OutputDir
,
1157 "module_debug_directory" : self
._AutoGenObject
.DebugDir
,
1159 "separator" : Separator
,
1160 "module_tool_definitions" : ToolsDef
,
1162 "shell_command_code" : self
._SHELL
_CMD
_[self
._FileType
].keys(),
1163 "shell_command" : self
._SHELL
_CMD
_[self
._FileType
].values(),
1165 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1166 "custom_makefile_content" : CustomMakefile
1169 return MakefileTemplateDict
1171 _TemplateDict
= property(_CreateTemplateDict
)
1173 ## PlatformMakefile class
1175 # This class encapsules makefie and its generation for platform. It uses
1176 # template to generate the content of makefile. The content of makefile will be
1177 # got from PlatformAutoGen object.
1179 class PlatformMakefile(BuildFile
):
1180 ## template used to generate the makefile for platform
1181 _TEMPLATE_
= TemplateString('''\
1185 # Platform Macro Definition
1187 PLATFORM_NAME = ${platform_name}
1188 PLATFORM_GUID = ${platform_guid}
1189 PLATFORM_VERSION = ${platform_version}
1190 PLATFORM_FILE = ${platform_file}
1191 PLATFORM_DIR = ${platform_dir}
1192 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1195 # Build Configuration Macro Definition
1197 TOOLCHAIN = ${toolchain_tag}
1198 TOOLCHAIN_TAG = ${toolchain_tag}
1199 TARGET = ${build_target}
1202 # Build Directory Macro Definition
1204 BUILD_DIR = ${platform_build_directory}
1205 FV_DIR = ${platform_build_directory}${separator}FV
1208 # Shell Command Macro
1210 ${BEGIN}${shell_command_code} = ${shell_command}
1214 MAKE_FILE = ${makefile_path}
1219 all: init build_libraries build_modules
1222 # Initialization target: print build information and create necessary directories
1225 \t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
1226 \t${BEGIN}-@${create_directory_command}
1229 # library build target
1231 libraries: init build_libraries
1234 # module build target
1236 modules: init build_libraries build_modules
1239 # Build all libraries:
1242 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
1243 ${END}\t@cd $(BUILD_DIR)
1246 # Build all modules:
1249 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
1250 ${END}\t@cd $(BUILD_DIR)
1253 # Clean intermediate files
1256 \t${BEGIN}-@${library_build_command} clean
1257 \t${END}${BEGIN}-@${module_build_command} clean
1258 \t${END}@cd $(BUILD_DIR)
1261 # Clean all generated files except to makefile
1264 ${BEGIN}\t${cleanall_command}
1268 # Clean all library files
1271 \t${BEGIN}-@${library_build_command} cleanall
1272 \t${END}@cd $(BUILD_DIR)\n
1275 ## Constructor of PlatformMakefile
1277 # @param ModuleAutoGen Object of PlatformAutoGen class
1279 def __init__(self
, PlatformAutoGen
):
1280 BuildFile
.__init
__(self
, PlatformAutoGen
)
1281 self
.ModuleBuildCommandList
= []
1282 self
.ModuleMakefileList
= []
1283 self
.IntermediateDirectoryList
= []
1284 self
.ModuleBuildDirectoryList
= []
1285 self
.LibraryBuildDirectoryList
= []
1286 self
.LibraryMakeCommandList
= []
1288 # Compose a dict object containing information used to do replacement in template
1289 def _CreateTemplateDict(self
):
1290 Separator
= self
._SEP
_[self
._FileType
]
1292 PlatformInfo
= self
._AutoGenObject
1293 if "MAKE" not in PlatformInfo
.ToolDefinition
or "PATH" not in PlatformInfo
.ToolDefinition
["MAKE"]:
1294 EdkLogger
.error("build", OPTION_MISSING
, "No MAKE command defined. Please check your tools_def.txt!",
1295 ExtraData
="[%s]" % str(self
._AutoGenObject
))
1297 self
.IntermediateDirectoryList
= ["$(BUILD_DIR)"]
1298 self
.ModuleBuildDirectoryList
= self
.GetModuleBuildDirectoryList()
1299 self
.LibraryBuildDirectoryList
= self
.GetLibraryBuildDirectoryList()
1301 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1302 LibraryMakefileList
= []
1303 LibraryMakeCommandList
= []
1304 for D
in self
.LibraryBuildDirectoryList
:
1305 D
= self
.PlaceMacro(D
, {"BUILD_DIR":PlatformInfo
.BuildDir
})
1306 Makefile
= os
.path
.join(D
, MakefileName
)
1307 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":Makefile
}
1308 LibraryMakefileList
.append(Makefile
)
1309 LibraryMakeCommandList
.append(Command
)
1310 self
.LibraryMakeCommandList
= LibraryMakeCommandList
1312 ModuleMakefileList
= []
1313 ModuleMakeCommandList
= []
1314 for D
in self
.ModuleBuildDirectoryList
:
1315 D
= self
.PlaceMacro(D
, {"BUILD_DIR":PlatformInfo
.BuildDir
})
1316 Makefile
= os
.path
.join(D
, MakefileName
)
1317 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":Makefile
}
1318 ModuleMakefileList
.append(Makefile
)
1319 ModuleMakeCommandList
.append(Command
)
1321 MakefileTemplateDict
= {
1322 "makefile_header" : self
._FILE
_HEADER
_[self
._FileType
],
1323 "makefile_path" : os
.path
.join("$(BUILD_DIR)", MakefileName
),
1324 "make_path" : PlatformInfo
.ToolDefinition
["MAKE"]["PATH"],
1325 "makefile_name" : MakefileName
,
1326 "platform_name" : PlatformInfo
.Name
,
1327 "platform_guid" : PlatformInfo
.Guid
,
1328 "platform_version" : PlatformInfo
.Version
,
1329 "platform_file" : self
._AutoGenObject
.MetaFile
,
1330 "platform_relative_directory": PlatformInfo
.SourceDir
,
1331 "platform_output_directory" : PlatformInfo
.OutputDir
,
1332 "platform_build_directory" : PlatformInfo
.BuildDir
,
1333 "platform_dir" : self
._AutoGenObject
.Macros
["PLATFORM_DIR"],
1335 "toolchain_tag" : PlatformInfo
.ToolChain
,
1336 "build_target" : PlatformInfo
.BuildTarget
,
1337 "shell_command_code" : self
._SHELL
_CMD
_[self
._FileType
].keys(),
1338 "shell_command" : self
._SHELL
_CMD
_[self
._FileType
].values(),
1339 "build_architecture_list" : self
._AutoGenObject
.Arch
,
1340 "architecture" : self
._AutoGenObject
.Arch
,
1341 "separator" : Separator
,
1342 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1343 "cleanall_command" : self
.GetRemoveDirectoryCommand(self
.IntermediateDirectoryList
),
1344 "library_makefile_list" : LibraryMakefileList
,
1345 "module_makefile_list" : ModuleMakefileList
,
1346 "library_build_command" : LibraryMakeCommandList
,
1347 "module_build_command" : ModuleMakeCommandList
,
1350 return MakefileTemplateDict
1352 ## Get the root directory list for intermediate files of all modules build
1354 # @retval list The list of directory
1356 def GetModuleBuildDirectoryList(self
):
1358 for ModuleAutoGen
in self
._AutoGenObject
.ModuleAutoGenList
:
1359 if not ModuleAutoGen
.IsBinaryModule
:
1360 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, ModuleAutoGen
.BuildDir
))
1363 ## Get the root directory list for intermediate files of all libraries build
1365 # @retval list The list of directory
1367 def GetLibraryBuildDirectoryList(self
):
1369 for LibraryAutoGen
in self
._AutoGenObject
.LibraryAutoGenList
:
1370 if not LibraryAutoGen
.IsBinaryModule
:
1371 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, LibraryAutoGen
.BuildDir
))
1374 _TemplateDict
= property(_CreateTemplateDict
)
1376 ## TopLevelMakefile class
1378 # This class encapsules makefie and its generation for entrance makefile. It
1379 # uses template to generate the content of makefile. The content of makefile
1380 # will be got from WorkspaceAutoGen object.
1382 class TopLevelMakefile(BuildFile
):
1383 ## template used to generate toplevel makefile
1384 _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}''')
1386 ## Constructor of TopLevelMakefile
1388 # @param Workspace Object of WorkspaceAutoGen class
1390 def __init__(self
, Workspace
):
1391 BuildFile
.__init
__(self
, Workspace
)
1392 self
.IntermediateDirectoryList
= []
1394 # Compose a dict object containing information used to do replacement in template
1395 def _CreateTemplateDict(self
):
1396 Separator
= self
._SEP
_[self
._FileType
]
1398 # any platform autogen object is ok because we just need common information
1399 PlatformInfo
= self
._AutoGenObject
1401 if "MAKE" not in PlatformInfo
.ToolDefinition
or "PATH" not in PlatformInfo
.ToolDefinition
["MAKE"]:
1402 EdkLogger
.error("build", OPTION_MISSING
, "No MAKE command defined. Please check your tools_def.txt!",
1403 ExtraData
="[%s]" % str(self
._AutoGenObject
))
1405 for Arch
in PlatformInfo
.ArchList
:
1406 self
.IntermediateDirectoryList
.append(Separator
.join(["$(BUILD_DIR)", Arch
]))
1407 self
.IntermediateDirectoryList
.append("$(FV_DIR)")
1409 # TRICK: for not generating GenFds call in makefile if no FDF file
1411 if PlatformInfo
.FdfFile
!= None and PlatformInfo
.FdfFile
!= "":
1412 FdfFileList
= [PlatformInfo
.FdfFile
]
1413 # macros passed to GenFds
1414 MacroList
.append('"%s=%s"' % ("EFI_SOURCE", GlobalData
.gEfiSource
.replace('\\', '\\\\')))
1415 MacroList
.append('"%s=%s"' % ("EDK_SOURCE", GlobalData
.gEdkSource
.replace('\\', '\\\\')))
1417 MacroDict
.update(GlobalData
.gGlobalDefines
)
1418 MacroDict
.update(GlobalData
.gCommandLineDefines
)
1419 MacroDict
.pop("EFI_SOURCE", "dummy")
1420 MacroDict
.pop("EDK_SOURCE", "dummy")
1421 for MacroName
in MacroDict
:
1422 if MacroDict
[MacroName
] != "":
1423 MacroList
.append('"%s=%s"' % (MacroName
, MacroDict
[MacroName
].replace('\\', '\\\\')))
1425 MacroList
.append('"%s"' % MacroName
)
1429 # pass extra common options to external program called in makefile, currently GenFds.exe
1431 LogLevel
= EdkLogger
.GetLevel()
1432 if LogLevel
== EdkLogger
.VERBOSE
:
1433 ExtraOption
+= " -v"
1434 elif LogLevel
<= EdkLogger
.DEBUG_9
:
1435 ExtraOption
+= " -d %d" % (LogLevel
- 1)
1436 elif LogLevel
== EdkLogger
.QUIET
:
1437 ExtraOption
+= " -q"
1439 if GlobalData
.gCaseInsensitive
:
1440 ExtraOption
+= " -c"
1442 if GlobalData
.gIgnoreSource
:
1443 ExtraOption
+= " --ignore-sources"
1445 if GlobalData
.BuildOptionPcd
:
1446 for index
, option
in enumerate(GlobalData
.gCommand
):
1447 if "--pcd" == option
and GlobalData
.gCommand
[index
+1]:
1448 ExtraOption
+= " --pcd " + GlobalData
.gCommand
[index
+1]
1450 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1451 SubBuildCommandList
= []
1452 for A
in PlatformInfo
.ArchList
:
1453 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":os
.path
.join("$(BUILD_DIR)", A
, MakefileName
)}
1454 SubBuildCommandList
.append(Command
)
1456 MakefileTemplateDict
= {
1457 "makefile_header" : self
._FILE
_HEADER
_[self
._FileType
],
1458 "makefile_path" : os
.path
.join("$(BUILD_DIR)", MakefileName
),
1459 "make_path" : PlatformInfo
.ToolDefinition
["MAKE"]["PATH"],
1460 "platform_name" : PlatformInfo
.Name
,
1461 "platform_guid" : PlatformInfo
.Guid
,
1462 "platform_version" : PlatformInfo
.Version
,
1463 "platform_build_directory" : PlatformInfo
.BuildDir
,
1464 "conf_directory" : GlobalData
.gConfDirectory
,
1466 "toolchain_tag" : PlatformInfo
.ToolChain
,
1467 "build_target" : PlatformInfo
.BuildTarget
,
1468 "shell_command_code" : self
._SHELL
_CMD
_[self
._FileType
].keys(),
1469 "shell_command" : self
._SHELL
_CMD
_[self
._FileType
].values(),
1470 'arch' : list(PlatformInfo
.ArchList
),
1471 "build_architecture_list" : ','.join(PlatformInfo
.ArchList
),
1472 "separator" : Separator
,
1473 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1474 "cleanall_command" : self
.GetRemoveDirectoryCommand(self
.IntermediateDirectoryList
),
1475 "sub_build_command" : SubBuildCommandList
,
1476 "fdf_file" : FdfFileList
,
1477 "active_platform" : str(PlatformInfo
),
1478 "fd" : PlatformInfo
.FdTargetList
,
1479 "fv" : PlatformInfo
.FvTargetList
,
1480 "cap" : PlatformInfo
.CapTargetList
,
1481 "extra_options" : ExtraOption
,
1482 "macro" : MacroList
,
1485 return MakefileTemplateDict
1487 ## Get the root directory list for intermediate files of all modules build
1489 # @retval list The list of directory
1491 def GetModuleBuildDirectoryList(self
):
1493 for ModuleAutoGen
in self
._AutoGenObject
.ModuleAutoGenList
:
1494 if not ModuleAutoGen
.IsBinaryModule
:
1495 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, ModuleAutoGen
.BuildDir
))
1498 ## Get the root directory list for intermediate files of all libraries build
1500 # @retval list The list of directory
1502 def GetLibraryBuildDirectoryList(self
):
1504 for LibraryAutoGen
in self
._AutoGenObject
.LibraryAutoGenList
:
1505 if not LibraryAutoGen
.IsBinaryModule
:
1506 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, LibraryAutoGen
.BuildDir
))
1509 _TemplateDict
= property(_CreateTemplateDict
)
1511 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1512 if __name__
== '__main__':