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
493 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
494 for Tool in self._AutoGenObject.BuildOption:
495 for Attr in self._AutoGenObject.BuildOption[Tool]:
496 Value = self._AutoGenObject.BuildOption[Tool][Attr]
500 ToolsDef.append("%s = %s" % (Tool, Value))
502 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
505 # Remove duplicated include path, if any
507 Value = RemoveDupOption(Value, IncPrefix, self._AutoGenObject.IncludePathList)
508 ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
511 # generate the Response file and Response flag
512 RespDict = self.CommandExceedLimit()
513 RespFileList = os.path.join(self._AutoGenObject.OutputDir, 'respfilelist.txt')
515 RespFileListContent = ''
516 for Resp in RespDict.keys():
517 RespFile = os.path.join(self._AutoGenObject.OutputDir, str(Resp).lower() + '.txt')
518 StrList = RespDict[Resp].split(' ')
523 UnexpandMacro.append(Str)
526 UnexpandMacroStr = ' '.join(UnexpandMacro)
527 NewRespStr = ' '.join(NewStr)
528 SaveFileOnChange(RespFile, NewRespStr, False)
529 ToolsDef.append("%s = %s" % (Resp, UnexpandMacroStr + ' @' + RespFile))
530 RespFileListContent += '@' + RespFile + os.linesep
531 RespFileListContent += NewRespStr + os.linesep
532 SaveFileOnChange(RespFileList, RespFileListContent, False)
534 if os.path.exists(RespFileList):
535 os.remove(RespFileList)
537 # convert source files and binary files to build targets
538 self.ResultFileList = [str(T.Target) for T in self._AutoGenObject.CodaTargetList]
539 if len(self.ResultFileList) == 0 and len(self._AutoGenObject.SourceFileList) <> 0:
540 EdkLogger.error("build
", AUTOGEN_ERROR, "Nothing to build
",
541 ExtraData="[%s]" % str(self._AutoGenObject))
543 self.ProcessBuildTargetList()
545 # Generate macros used to represent input files
546 FileMacroList = [] # macro name = file list
547 for FileListMacro in self.FileListMacros:
548 FileMacro = self._FILE_MACRO_TEMPLATE.Replace(
550 "macro_name
" : FileListMacro,
551 "source_file
" : self.FileListMacros[FileListMacro]
554 FileMacroList.append(FileMacro)
556 # INC_LIST is special
559 for P in self._AutoGenObject.IncludePathList:
560 IncludePathList.append(IncPrefix + self.PlaceMacro(P, self.Macros))
561 if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:
562 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix + P)
563 FileMacro += self._FILE_MACRO_TEMPLATE.Replace(
565 "macro_name
" : "INC
",
566 "source_file
" : IncludePathList
569 FileMacroList.append(FileMacro)
571 # Generate macros used to represent files containing list of input files
572 for ListFileMacro in self.ListFileMacros:
573 ListFileName = os.path.join(self._AutoGenObject.OutputDir, "%s.lst
" % ListFileMacro.lower()[:len(ListFileMacro) - 5])
574 FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))
577 "\n".join(self.ListFileMacros[ListFileMacro]),
581 # Edk modules need <BaseName>StrDefs.h for string ID
582 #if self._AutoGenObject.AutoGenVersion < 0x00010005 and len(self._AutoGenObject.UnicodeFileList) > 0:
583 # BcTargetList = ['strdefs']
588 MakefileName = self._FILE_NAME_[self._FileType]
589 LibraryMakeCommandList = []
590 for D in self.LibraryBuildDirectoryList:
591 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)}
592 LibraryMakeCommandList.append(Command)
594 package_rel_dir = self._AutoGenObject.SourceDir
595 current_dir = self.Macros["WORKSPACE
"]
597 while not found and os.sep in package_rel_dir:
598 index = package_rel_dir.index(os.sep)
599 current_dir = mws.join(current_dir, package_rel_dir[:index])
600 if os.path.exists(current_dir):
601 for fl in os.listdir(current_dir):
602 if fl.endswith('.dec'):
605 package_rel_dir = package_rel_dir[index + 1:]
607 MakefileTemplateDict = {
608 "makefile_header
" : self._FILE_HEADER_[self._FileType],
609 "makefile_path
" : os.path.join("$
(MODULE_BUILD_DIR
)", MakefileName),
610 "makefile_name
" : MakefileName,
611 "platform_name
" : self.PlatformInfo.Name,
612 "platform_guid
" : self.PlatformInfo.Guid,
613 "platform_version
" : self.PlatformInfo.Version,
614 "platform_relative_directory
": self.PlatformInfo.SourceDir,
615 "platform_output_directory
" : self.PlatformInfo.OutputDir,
616 "platform_dir
" : self._AutoGenObject.Macros["PLATFORM_DIR
"],
618 "module_name
" : self._AutoGenObject.Name,
619 "module_guid
" : self._AutoGenObject.Guid,
620 "module_name_guid
" : self._AutoGenObject._GetUniqueBaseName(),
621 "module_version
" : self._AutoGenObject.Version,
622 "module_type
" : self._AutoGenObject.ModuleType,
623 "module_file
" : self._AutoGenObject.MetaFile.Name,
624 "module_file_base_name
" : self._AutoGenObject.MetaFile.BaseName,
625 "module_relative_directory
" : self._AutoGenObject.SourceDir,
626 "module_dir
" : mws.join (self.Macros["WORKSPACE
"], self._AutoGenObject.SourceDir),
627 "package_relative_directory
": package_rel_dir,
628 "module_extra_defines
" : ["%s = %s" % (k, v) for k, v in self._AutoGenObject.Module.Defines.iteritems()],
630 "architecture
" : self._AutoGenObject.Arch,
631 "toolchain_tag
" : self._AutoGenObject.ToolChain,
632 "build_target
" : self._AutoGenObject.BuildTarget,
634 "platform_build_directory
" : self.PlatformInfo.BuildDir,
635 "module_build_directory
" : self._AutoGenObject.BuildDir,
636 "module_output_directory
" : self._AutoGenObject.OutputDir,
637 "module_debug_directory
" : self._AutoGenObject.DebugDir,
639 "separator
" : Separator,
640 "module_tool_definitions
" : ToolsDef,
642 "shell_command_code
" : self._SHELL_CMD_[self._FileType].keys(),
643 "shell_command
" : self._SHELL_CMD_[self._FileType].values(),
645 "module_entry_point
" : ModuleEntryPoint,
646 "image_entry_point
" : ImageEntryPoint,
647 "arch_entry_point
" : ArchEntryPoint,
648 "remaining_build_target
" : self.ResultFileList,
649 "common_dependency_file
" : self.CommonFileDependency,
650 "create_directory_command
" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
651 "clean_command
" : self.GetRemoveDirectoryCommand(["$
(OUTPUT_DIR
)"]),
652 "cleanall_command
" : self.GetRemoveDirectoryCommand(["$
(DEBUG_DIR
)", "$
(OUTPUT_DIR
)"]),
653 "dependent_library_build_directory
" : self.LibraryBuildDirectoryList,
654 "library_build_command
" : LibraryMakeCommandList,
655 "file_macro
" : FileMacroList,
656 "file_build_target
" : self.BuildTargetList,
657 "backward_compatible_target
": BcTargetList,
660 return MakefileTemplateDict
662 def CommandExceedLimit(self):
664 'CC' : { 'Macro' : '$(CC_FLAGS)', 'Value' : False},
665 'PP' : { 'Macro' : '$(PP_FLAGS)', 'Value' : False},
666 'APP' : { 'Macro' : '$(APP_FLAGS)', 'Value' : False},
667 'ASLPP' : { 'Macro' : '$(ASLPP_FLAGS)', 'Value' : False},
668 'VFRPP' : { 'Macro' : '$(VFRPP_FLAGS)', 'Value' : False},
669 'ASM' : { 'Macro' : '$(ASM_FLAGS)', 'Value' : False},
670 'ASLCC' : { 'Macro' : '$(ASLCC_FLAGS)', 'Value' : False},
675 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
677 # base on the source files to decide the file type
678 for File in self._AutoGenObject.SourceFileList:
679 for type in self._AutoGenObject.FileTypes:
680 if File in self._AutoGenObject.FileTypes[type]:
681 if type not in FileTypeList:
682 FileTypeList.append(type)
684 # calculate the command-line length
686 for type in FileTypeList:
687 BuildTargets = self._AutoGenObject.BuildRules[type].BuildTargets
688 for Target in BuildTargets:
689 CommandList = BuildTargets[Target].Commands
690 for SingleCommand in CommandList:
692 SingleCommandLength = len(SingleCommand)
693 SingleCommandList = SingleCommand.split()
694 if len(SingleCommandList) > 0:
695 for Flag in FlagDict.keys():
696 if '$('+ Flag +')' in SingleCommandList[0]:
700 SingleCommandLength += len(self._AutoGenObject._BuildOption[Tool]['PATH'])
701 for item in SingleCommandList[1:]:
702 if FlagDict[Tool]['Macro'] in item:
703 Str = self._AutoGenObject._BuildOption[Tool]['FLAGS']
704 for Option in self._AutoGenObject.BuildOption.keys():
705 for Attr in self._AutoGenObject.BuildOption[Option]:
706 if Str.find(Option + '_' + Attr) != -1:
707 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
708 while(Str.find('$(') != -1):
709 for macro in self._AutoGenObject.Macros.keys():
710 MacroName = '$('+ macro + ')'
711 if (Str.find(MacroName) != -1):
712 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
716 SingleCommandLength += len(Str)
717 elif '$(INC)' in item:
718 SingleCommandLength += self._AutoGenObject.IncludePathLength + len(IncPrefix) * len(self._AutoGenObject._IncludePathList)
719 elif item.find('$(') != -1:
721 for Option in self._AutoGenObject.BuildOption.keys():
722 for Attr in self._AutoGenObject.BuildOption[Option]:
723 if Str.find(Option + '_' + Attr) != -1:
724 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
725 while(Str.find('$(') != -1):
726 for macro in self._AutoGenObject.Macros.keys():
727 MacroName = '$('+ macro + ')'
728 if (Str.find(MacroName) != -1):
729 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
733 SingleCommandLength += len(Str)
735 if SingleCommandLength > GlobalData.gCommandMaxLength:
736 FlagDict[Tool]['Value'] = True
738 # generate the response file content by combine the FLAGS and INC
739 for Flag in FlagDict.keys():
740 if FlagDict[Flag]['Value']:
742 RespMacro = FlagDict[Flag]['Macro'].replace('FLAGS', 'RESP')
743 Value = self._AutoGenObject.BuildOption[Flag]['FLAGS']
744 for inc in self._AutoGenObject._IncludePathList:
745 Value += ' ' + IncPrefix + inc
746 for Option in self._AutoGenObject.BuildOption.keys():
747 for Attr in self._AutoGenObject.BuildOption[Option]:
748 if Value.find(Option + '_' + Attr) != -1:
749 Value = Value.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
750 while (Value.find('$(') != -1):
751 for macro in self._AutoGenObject.Macros.keys():
752 MacroName = '$('+ macro + ')'
753 if (Value.find(MacroName) != -1):
754 Value = Value.replace(MacroName, self._AutoGenObject.Macros[macro])
758 RespDict[Key] = Value
759 for Target in BuildTargets:
760 for i, SingleCommand in enumerate(BuildTargets[Target].Commands):
761 if FlagDict[Flag]['Macro'] in SingleCommand:
762 BuildTargets[Target].Commands[i] = SingleCommand.replace('$(INC)','').replace(FlagDict[Flag]['Macro'], RespMacro)
765 def ProcessBuildTargetList(self):
767 # Search dependency file list for each source file
769 ForceIncludedFile = []
770 for File in self._AutoGenObject.AutoGenFileList:
772 ForceIncludedFile.append(File)
774 for Target in self._AutoGenObject.IntroTargetList:
775 SourceFileList.extend(Target.Inputs)
777 self.FileDependency = self.GetFileDependency(
780 self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList
783 for File in self.FileDependency:
784 if not self.FileDependency[File]:
785 self.FileDependency[File] = ['$(FORCE_REBUILD)']
788 if File.Ext not in [".c
", ".C
"] or File.Name == "AutoGen
.c
":
791 DepSet = set(self.FileDependency[File])
793 DepSet &= set(self.FileDependency[File])
794 # in case nothing in SourceFileList
798 # Extract common files list in the dependency files
801 self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros))
803 for File in self.FileDependency:
805 if File.Ext not in [".c
", ".C
"] or File.Name == "AutoGen
.c
":
807 NewDepSet = set(self.FileDependency[File])
809 self.FileDependency[File] = ["$
(COMMON_DEPS
)"] + list(NewDepSet)
811 # Convert target description object to target string in makefile
812 for Type in self._AutoGenObject.Targets:
813 for T in self._AutoGenObject.Targets[Type]:
814 # Generate related macros if needed
815 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
816 self.FileListMacros[T.FileListMacro] = []
817 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:
818 self.ListFileMacros[T.ListFileMacro] = []
819 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:
820 self.ListFileMacros[T.IncListFileMacro] = []
823 # Add force-dependencies
824 for Dep in T.Dependencies:
825 Deps.append(self.PlaceMacro(str(Dep), self.Macros))
826 # Add inclusion-dependencies
827 if len(T.Inputs) == 1 and T.Inputs[0] in self.FileDependency:
828 for F in self.FileDependency[T.Inputs[0]]:
829 Deps.append(self.PlaceMacro(str(F), self.Macros))
830 # Add source-dependencies
832 NewFile = self.PlaceMacro(str(F), self.Macros)
833 # In order to use file list macro as dependency
835 # gnu tools need forward slash path separater, even on Windows
836 self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/'))
837 self.FileListMacros[T.FileListMacro].append(NewFile)
838 elif T.GenFileListMacro:
839 self.FileListMacros[T.FileListMacro].append(NewFile)
843 # Use file list macro as dependency
844 if T.GenFileListMacro:
845 Deps.append("$
(%s)" % T.FileListMacro)
848 "target
" : self.PlaceMacro(T.Target.Path, self.Macros),
849 "cmd
" : "\n\t".join(T.Commands),
852 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
854 ## For creating makefile targets for dependent libraries
855 def ProcessDependentLibrary(self):
856 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
857 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
859 ## Return a list containing source file's dependencies
861 # @param FileList The list of source files
862 # @param ForceInculeList The list of files which will be included forcely
863 # @param SearchPathList The list of search path
865 # @retval dict The mapping between source file path and its dependencies
867 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
870 Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)
873 ## Find dependencies for one source file
875 # By searching recursively "#include" directive in file, find out all the
876 # files needed by given source file. The dependecies will be only searched
877 # in given search path list.
879 # @param File The source file
880 # @param ForceInculeList The list of files which will be included forcely
881 # @param SearchPathList The list of search path
883 # @retval list The list of files the given source file depends on
885 def GetDependencyList(self
, File
, ForceList
, SearchPathList
):
886 EdkLogger
.debug(EdkLogger
.DEBUG_1
, "Try to get dependency files for %s" % File
)
887 FileStack
= [File
] + ForceList
888 DependencySet
= set()
890 if self
._AutoGenObject
.Arch
not in gDependencyDatabase
:
891 gDependencyDatabase
[self
._AutoGenObject
.Arch
] = {}
892 DepDb
= gDependencyDatabase
[self
._AutoGenObject
.Arch
]
894 while len(FileStack
) > 0:
897 FullPathDependList
= []
898 if F
in self
.FileCache
:
899 for CacheFile
in self
.FileCache
[F
]:
900 FullPathDependList
.append(CacheFile
)
901 if CacheFile
not in DependencySet
:
902 FileStack
.append(CacheFile
)
903 DependencySet
.update(FullPathDependList
)
906 CurrentFileDependencyList
= []
908 CurrentFileDependencyList
= DepDb
[F
]
911 Fd
= open(F
.Path
, 'r')
912 except BaseException
, X
:
913 EdkLogger
.error("build", FILE_OPEN_FAILURE
, ExtraData
=F
.Path
+ "\n\t" + str(X
))
915 FileContent
= Fd
.read()
917 if len(FileContent
) == 0:
920 if FileContent
[0] == 0xff or FileContent
[0] == 0xfe:
921 FileContent
= unicode(FileContent
, "utf-16")
922 IncludedFileList
= gIncludePattern
.findall(FileContent
)
924 for Inc
in IncludedFileList
:
926 # if there's macro used to reference header file, expand it
927 HeaderList
= gMacroPattern
.findall(Inc
)
928 if len(HeaderList
) == 1 and len(HeaderList
[0]) == 2:
929 HeaderType
= HeaderList
[0][0]
930 HeaderKey
= HeaderList
[0][1]
931 if HeaderType
in gIncludeMacroConversion
:
932 Inc
= gIncludeMacroConversion
[HeaderType
] % {"HeaderKey" : HeaderKey
}
934 # not known macro used in #include, always build the file by
935 # returning a empty dependency
936 self
.FileCache
[File
] = []
938 Inc
= os
.path
.normpath(Inc
)
939 CurrentFileDependencyList
.append(Inc
)
940 DepDb
[F
] = CurrentFileDependencyList
942 CurrentFilePath
= F
.Dir
943 PathList
= [CurrentFilePath
] + SearchPathList
944 for Inc
in CurrentFileDependencyList
:
945 for SearchPath
in PathList
:
946 FilePath
= os
.path
.join(SearchPath
, Inc
)
947 if FilePath
in gIsFileMap
:
948 if not gIsFileMap
[FilePath
]:
950 # If isfile is called too many times, the performance is slow down.
951 elif not os
.path
.isfile(FilePath
):
952 gIsFileMap
[FilePath
] = False
955 gIsFileMap
[FilePath
] = True
956 FilePath
= PathClass(FilePath
)
957 FullPathDependList
.append(FilePath
)
958 if FilePath
not in DependencySet
:
959 FileStack
.append(FilePath
)
962 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "%s included by %s was not found "\
963 "in any given path:\n\t%s" % (Inc
, F
, "\n\t".join(SearchPathList
)))
965 self
.FileCache
[F
] = FullPathDependList
966 DependencySet
.update(FullPathDependList
)
968 DependencySet
.update(ForceList
)
969 if File
in DependencySet
:
970 DependencySet
.remove(File
)
971 DependencyList
= list(DependencySet
) # remove duplicate ones
973 return DependencyList
975 _TemplateDict
= property(_CreateTemplateDict
)
977 ## CustomMakefile class
979 # This class encapsules makefie and its generation for module. It uses template to generate
980 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
982 class CustomMakefile(BuildFile
):
983 ## template used to generate the makefile for module with custom makefile
984 _TEMPLATE_
= TemplateString('''\
988 # Platform Macro Definition
990 PLATFORM_NAME = ${platform_name}
991 PLATFORM_GUID = ${platform_guid}
992 PLATFORM_VERSION = ${platform_version}
993 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
994 PLATFORM_DIR = ${platform_dir}
995 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
998 # Module Macro Definition
1000 MODULE_NAME = ${module_name}
1001 MODULE_GUID = ${module_guid}
1002 MODULE_NAME_GUID = ${module_name_guid}
1003 MODULE_VERSION = ${module_version}
1004 MODULE_TYPE = ${module_type}
1005 MODULE_FILE = ${module_file}
1006 MODULE_FILE_BASE_NAME = ${module_file_base_name}
1007 BASE_NAME = $(MODULE_NAME)
1008 MODULE_RELATIVE_DIR = ${module_relative_directory}
1009 MODULE_DIR = ${module_dir}
1012 # Build Configuration Macro Definition
1014 ARCH = ${architecture}
1015 TOOLCHAIN = ${toolchain_tag}
1016 TOOLCHAIN_TAG = ${toolchain_tag}
1017 TARGET = ${build_target}
1020 # Build Directory Macro Definition
1022 # PLATFORM_BUILD_DIR = ${platform_build_directory}
1023 BUILD_DIR = ${platform_build_directory}
1024 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
1025 LIB_DIR = $(BIN_DIR)
1026 MODULE_BUILD_DIR = ${module_build_directory}
1027 OUTPUT_DIR = ${module_output_directory}
1028 DEBUG_DIR = ${module_debug_directory}
1029 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
1030 DEST_DIR_DEBUG = $(DEBUG_DIR)
1033 # Tools definitions specific to this module
1035 ${BEGIN}${module_tool_definitions}
1037 MAKE_FILE = ${makefile_path}
1040 # Shell Command Macro
1042 ${BEGIN}${shell_command_code} = ${shell_command}
1045 ${custom_makefile_content}
1048 # Target used when called from platform makefile, which will bypass the build of dependent libraries
1061 # Build Target used in multi-thread build mode, which no init target is needed
1067 # Initialization target: print build information and create necessary directories
1070 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
1071 ${BEGIN}\t-@${create_directory_command}\n${END}\
1075 ## Constructor of CustomMakefile
1077 # @param ModuleAutoGen Object of ModuleAutoGen class
1079 def __init__(self
, ModuleAutoGen
):
1080 BuildFile
.__init
__(self
, ModuleAutoGen
)
1081 self
.PlatformInfo
= self
._AutoGenObject
.PlatformInfo
1082 self
.IntermediateDirectoryList
= ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
1084 # Compose a dict object containing information used to do replacement in template
1085 def _CreateTemplateDict(self
):
1086 Separator
= self
._SEP
_[self
._FileType
]
1087 if self
._FileType
not in self
._AutoGenObject
.CustomMakefile
:
1088 EdkLogger
.error('build', OPTION_NOT_SUPPORTED
, "No custom makefile for %s" % self
._FileType
,
1089 ExtraData
="[%s]" % str(self
._AutoGenObject
))
1090 MakefilePath
= mws
.join(
1091 self
._AutoGenObject
.WorkspaceDir
,
1092 self
._AutoGenObject
.CustomMakefile
[self
._FileType
]
1095 CustomMakefile
= open(MakefilePath
, 'r').read()
1097 EdkLogger
.error('build', FILE_OPEN_FAILURE
, File
=str(self
._AutoGenObject
),
1098 ExtraData
=self
._AutoGenObject
.CustomMakefile
[self
._FileType
])
1102 for Tool
in self
._AutoGenObject
.BuildOption
:
1103 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
1106 for Attr
in self
._AutoGenObject
.BuildOption
[Tool
]:
1107 if Attr
== "FAMILY":
1109 elif Attr
== "PATH":
1110 ToolsDef
.append("%s = %s" % (Tool
, self
._AutoGenObject
.BuildOption
[Tool
][Attr
]))
1112 ToolsDef
.append("%s_%s = %s" % (Tool
, Attr
, self
._AutoGenObject
.BuildOption
[Tool
][Attr
]))
1115 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1116 MakefileTemplateDict
= {
1117 "makefile_header" : self
._FILE
_HEADER
_[self
._FileType
],
1118 "makefile_path" : os
.path
.join("$(MODULE_BUILD_DIR)", MakefileName
),
1119 "platform_name" : self
.PlatformInfo
.Name
,
1120 "platform_guid" : self
.PlatformInfo
.Guid
,
1121 "platform_version" : self
.PlatformInfo
.Version
,
1122 "platform_relative_directory": self
.PlatformInfo
.SourceDir
,
1123 "platform_output_directory" : self
.PlatformInfo
.OutputDir
,
1124 "platform_dir" : self
._AutoGenObject
.Macros
["PLATFORM_DIR"],
1126 "module_name" : self
._AutoGenObject
.Name
,
1127 "module_guid" : self
._AutoGenObject
.Guid
,
1128 "module_name_guid" : self
._AutoGenObject
._GetUniqueBaseName
(),
1129 "module_version" : self
._AutoGenObject
.Version
,
1130 "module_type" : self
._AutoGenObject
.ModuleType
,
1131 "module_file" : self
._AutoGenObject
.MetaFile
,
1132 "module_file_base_name" : self
._AutoGenObject
.MetaFile
.BaseName
,
1133 "module_relative_directory" : self
._AutoGenObject
.SourceDir
,
1134 "module_dir" : mws
.join (self
._AutoGenObject
.WorkspaceDir
, self
._AutoGenObject
.SourceDir
),
1136 "architecture" : self
._AutoGenObject
.Arch
,
1137 "toolchain_tag" : self
._AutoGenObject
.ToolChain
,
1138 "build_target" : self
._AutoGenObject
.BuildTarget
,
1140 "platform_build_directory" : self
.PlatformInfo
.BuildDir
,
1141 "module_build_directory" : self
._AutoGenObject
.BuildDir
,
1142 "module_output_directory" : self
._AutoGenObject
.OutputDir
,
1143 "module_debug_directory" : self
._AutoGenObject
.DebugDir
,
1145 "separator" : Separator
,
1146 "module_tool_definitions" : ToolsDef
,
1148 "shell_command_code" : self
._SHELL
_CMD
_[self
._FileType
].keys(),
1149 "shell_command" : self
._SHELL
_CMD
_[self
._FileType
].values(),
1151 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1152 "custom_makefile_content" : CustomMakefile
1155 return MakefileTemplateDict
1157 _TemplateDict
= property(_CreateTemplateDict
)
1159 ## PlatformMakefile class
1161 # This class encapsules makefie and its generation for platform. It uses
1162 # template to generate the content of makefile. The content of makefile will be
1163 # got from PlatformAutoGen object.
1165 class PlatformMakefile(BuildFile
):
1166 ## template used to generate the makefile for platform
1167 _TEMPLATE_
= TemplateString('''\
1171 # Platform Macro Definition
1173 PLATFORM_NAME = ${platform_name}
1174 PLATFORM_GUID = ${platform_guid}
1175 PLATFORM_VERSION = ${platform_version}
1176 PLATFORM_FILE = ${platform_file}
1177 PLATFORM_DIR = ${platform_dir}
1178 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1181 # Build Configuration Macro Definition
1183 TOOLCHAIN = ${toolchain_tag}
1184 TOOLCHAIN_TAG = ${toolchain_tag}
1185 TARGET = ${build_target}
1188 # Build Directory Macro Definition
1190 BUILD_DIR = ${platform_build_directory}
1191 FV_DIR = ${platform_build_directory}${separator}FV
1194 # Shell Command Macro
1196 ${BEGIN}${shell_command_code} = ${shell_command}
1200 MAKE_FILE = ${makefile_path}
1205 all: init build_libraries build_modules
1208 # Initialization target: print build information and create necessary directories
1211 \t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
1212 \t${BEGIN}-@${create_directory_command}
1215 # library build target
1217 libraries: init build_libraries
1220 # module build target
1222 modules: init build_libraries build_modules
1225 # Build all libraries:
1228 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
1229 ${END}\t@cd $(BUILD_DIR)
1232 # Build all modules:
1235 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
1236 ${END}\t@cd $(BUILD_DIR)
1239 # Clean intermediate files
1242 \t${BEGIN}-@${library_build_command} clean
1243 \t${END}${BEGIN}-@${module_build_command} clean
1244 \t${END}@cd $(BUILD_DIR)
1247 # Clean all generated files except to makefile
1250 ${BEGIN}\t${cleanall_command}
1254 # Clean all library files
1257 \t${BEGIN}-@${library_build_command} cleanall
1258 \t${END}@cd $(BUILD_DIR)\n
1261 ## Constructor of PlatformMakefile
1263 # @param ModuleAutoGen Object of PlatformAutoGen class
1265 def __init__(self
, PlatformAutoGen
):
1266 BuildFile
.__init
__(self
, PlatformAutoGen
)
1267 self
.ModuleBuildCommandList
= []
1268 self
.ModuleMakefileList
= []
1269 self
.IntermediateDirectoryList
= []
1270 self
.ModuleBuildDirectoryList
= []
1271 self
.LibraryBuildDirectoryList
= []
1272 self
.LibraryMakeCommandList
= []
1274 # Compose a dict object containing information used to do replacement in template
1275 def _CreateTemplateDict(self
):
1276 Separator
= self
._SEP
_[self
._FileType
]
1278 PlatformInfo
= self
._AutoGenObject
1279 if "MAKE" not in PlatformInfo
.ToolDefinition
or "PATH" not in PlatformInfo
.ToolDefinition
["MAKE"]:
1280 EdkLogger
.error("build", OPTION_MISSING
, "No MAKE command defined. Please check your tools_def.txt!",
1281 ExtraData
="[%s]" % str(self
._AutoGenObject
))
1283 self
.IntermediateDirectoryList
= ["$(BUILD_DIR)"]
1284 self
.ModuleBuildDirectoryList
= self
.GetModuleBuildDirectoryList()
1285 self
.LibraryBuildDirectoryList
= self
.GetLibraryBuildDirectoryList()
1287 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1288 LibraryMakefileList
= []
1289 LibraryMakeCommandList
= []
1290 for D
in self
.LibraryBuildDirectoryList
:
1291 D
= self
.PlaceMacro(D
, {"BUILD_DIR":PlatformInfo
.BuildDir
})
1292 Makefile
= os
.path
.join(D
, MakefileName
)
1293 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":Makefile
}
1294 LibraryMakefileList
.append(Makefile
)
1295 LibraryMakeCommandList
.append(Command
)
1296 self
.LibraryMakeCommandList
= LibraryMakeCommandList
1298 ModuleMakefileList
= []
1299 ModuleMakeCommandList
= []
1300 for D
in self
.ModuleBuildDirectoryList
:
1301 D
= self
.PlaceMacro(D
, {"BUILD_DIR":PlatformInfo
.BuildDir
})
1302 Makefile
= os
.path
.join(D
, MakefileName
)
1303 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":Makefile
}
1304 ModuleMakefileList
.append(Makefile
)
1305 ModuleMakeCommandList
.append(Command
)
1307 MakefileTemplateDict
= {
1308 "makefile_header" : self
._FILE
_HEADER
_[self
._FileType
],
1309 "makefile_path" : os
.path
.join("$(BUILD_DIR)", MakefileName
),
1310 "make_path" : PlatformInfo
.ToolDefinition
["MAKE"]["PATH"],
1311 "makefile_name" : MakefileName
,
1312 "platform_name" : PlatformInfo
.Name
,
1313 "platform_guid" : PlatformInfo
.Guid
,
1314 "platform_version" : PlatformInfo
.Version
,
1315 "platform_file" : self
._AutoGenObject
.MetaFile
,
1316 "platform_relative_directory": PlatformInfo
.SourceDir
,
1317 "platform_output_directory" : PlatformInfo
.OutputDir
,
1318 "platform_build_directory" : PlatformInfo
.BuildDir
,
1319 "platform_dir" : self
._AutoGenObject
.Macros
["PLATFORM_DIR"],
1321 "toolchain_tag" : PlatformInfo
.ToolChain
,
1322 "build_target" : PlatformInfo
.BuildTarget
,
1323 "shell_command_code" : self
._SHELL
_CMD
_[self
._FileType
].keys(),
1324 "shell_command" : self
._SHELL
_CMD
_[self
._FileType
].values(),
1325 "build_architecture_list" : self
._AutoGenObject
.Arch
,
1326 "architecture" : self
._AutoGenObject
.Arch
,
1327 "separator" : Separator
,
1328 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1329 "cleanall_command" : self
.GetRemoveDirectoryCommand(self
.IntermediateDirectoryList
),
1330 "library_makefile_list" : LibraryMakefileList
,
1331 "module_makefile_list" : ModuleMakefileList
,
1332 "library_build_command" : LibraryMakeCommandList
,
1333 "module_build_command" : ModuleMakeCommandList
,
1336 return MakefileTemplateDict
1338 ## Get the root directory list for intermediate files of all modules build
1340 # @retval list The list of directory
1342 def GetModuleBuildDirectoryList(self
):
1344 for ModuleAutoGen
in self
._AutoGenObject
.ModuleAutoGenList
:
1345 if not ModuleAutoGen
.IsBinaryModule
:
1346 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, ModuleAutoGen
.BuildDir
))
1349 ## Get the root directory list for intermediate files of all libraries build
1351 # @retval list The list of directory
1353 def GetLibraryBuildDirectoryList(self
):
1355 for LibraryAutoGen
in self
._AutoGenObject
.LibraryAutoGenList
:
1356 if not LibraryAutoGen
.IsBinaryModule
:
1357 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, LibraryAutoGen
.BuildDir
))
1360 _TemplateDict
= property(_CreateTemplateDict
)
1362 ## TopLevelMakefile class
1364 # This class encapsules makefie and its generation for entrance makefile. It
1365 # uses template to generate the content of makefile. The content of makefile
1366 # will be got from WorkspaceAutoGen object.
1368 class TopLevelMakefile(BuildFile
):
1369 ## template used to generate toplevel makefile
1370 _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}''')
1372 ## Constructor of TopLevelMakefile
1374 # @param Workspace Object of WorkspaceAutoGen class
1376 def __init__(self
, Workspace
):
1377 BuildFile
.__init
__(self
, Workspace
)
1378 self
.IntermediateDirectoryList
= []
1380 # Compose a dict object containing information used to do replacement in template
1381 def _CreateTemplateDict(self
):
1382 Separator
= self
._SEP
_[self
._FileType
]
1384 # any platform autogen object is ok because we just need common information
1385 PlatformInfo
= self
._AutoGenObject
1387 if "MAKE" not in PlatformInfo
.ToolDefinition
or "PATH" not in PlatformInfo
.ToolDefinition
["MAKE"]:
1388 EdkLogger
.error("build", OPTION_MISSING
, "No MAKE command defined. Please check your tools_def.txt!",
1389 ExtraData
="[%s]" % str(self
._AutoGenObject
))
1391 for Arch
in PlatformInfo
.ArchList
:
1392 self
.IntermediateDirectoryList
.append(Separator
.join(["$(BUILD_DIR)", Arch
]))
1393 self
.IntermediateDirectoryList
.append("$(FV_DIR)")
1395 # TRICK: for not generating GenFds call in makefile if no FDF file
1397 if PlatformInfo
.FdfFile
!= None and PlatformInfo
.FdfFile
!= "":
1398 FdfFileList
= [PlatformInfo
.FdfFile
]
1399 # macros passed to GenFds
1400 MacroList
.append('"%s=%s"' % ("EFI_SOURCE", GlobalData
.gEfiSource
.replace('\\', '\\\\')))
1401 MacroList
.append('"%s=%s"' % ("EDK_SOURCE", GlobalData
.gEdkSource
.replace('\\', '\\\\')))
1403 MacroDict
.update(GlobalData
.gGlobalDefines
)
1404 MacroDict
.update(GlobalData
.gCommandLineDefines
)
1405 MacroDict
.pop("EFI_SOURCE", "dummy")
1406 MacroDict
.pop("EDK_SOURCE", "dummy")
1407 for MacroName
in MacroDict
:
1408 if MacroDict
[MacroName
] != "":
1409 MacroList
.append('"%s=%s"' % (MacroName
, MacroDict
[MacroName
].replace('\\', '\\\\')))
1411 MacroList
.append('"%s"' % MacroName
)
1415 # pass extra common options to external program called in makefile, currently GenFds.exe
1417 LogLevel
= EdkLogger
.GetLevel()
1418 if LogLevel
== EdkLogger
.VERBOSE
:
1419 ExtraOption
+= " -v"
1420 elif LogLevel
<= EdkLogger
.DEBUG_9
:
1421 ExtraOption
+= " -d %d" % (LogLevel
- 1)
1422 elif LogLevel
== EdkLogger
.QUIET
:
1423 ExtraOption
+= " -q"
1425 if GlobalData
.gCaseInsensitive
:
1426 ExtraOption
+= " -c"
1428 if GlobalData
.gIgnoreSource
:
1429 ExtraOption
+= " --ignore-sources"
1431 if GlobalData
.BuildOptionPcd
:
1432 for index
, option
in enumerate(GlobalData
.gCommand
):
1433 if "--pcd" == option
and GlobalData
.gCommand
[index
+1]:
1434 ExtraOption
+= " --pcd " + GlobalData
.gCommand
[index
+1]
1436 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1437 SubBuildCommandList
= []
1438 for A
in PlatformInfo
.ArchList
:
1439 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":os
.path
.join("$(BUILD_DIR)", A
, MakefileName
)}
1440 SubBuildCommandList
.append(Command
)
1442 MakefileTemplateDict
= {
1443 "makefile_header" : self
._FILE
_HEADER
_[self
._FileType
],
1444 "makefile_path" : os
.path
.join("$(BUILD_DIR)", MakefileName
),
1445 "make_path" : PlatformInfo
.ToolDefinition
["MAKE"]["PATH"],
1446 "platform_name" : PlatformInfo
.Name
,
1447 "platform_guid" : PlatformInfo
.Guid
,
1448 "platform_version" : PlatformInfo
.Version
,
1449 "platform_build_directory" : PlatformInfo
.BuildDir
,
1450 "conf_directory" : GlobalData
.gConfDirectory
,
1452 "toolchain_tag" : PlatformInfo
.ToolChain
,
1453 "build_target" : PlatformInfo
.BuildTarget
,
1454 "shell_command_code" : self
._SHELL
_CMD
_[self
._FileType
].keys(),
1455 "shell_command" : self
._SHELL
_CMD
_[self
._FileType
].values(),
1456 'arch' : list(PlatformInfo
.ArchList
),
1457 "build_architecture_list" : ','.join(PlatformInfo
.ArchList
),
1458 "separator" : Separator
,
1459 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1460 "cleanall_command" : self
.GetRemoveDirectoryCommand(self
.IntermediateDirectoryList
),
1461 "sub_build_command" : SubBuildCommandList
,
1462 "fdf_file" : FdfFileList
,
1463 "active_platform" : str(PlatformInfo
),
1464 "fd" : PlatformInfo
.FdTargetList
,
1465 "fv" : PlatformInfo
.FvTargetList
,
1466 "cap" : PlatformInfo
.CapTargetList
,
1467 "extra_options" : ExtraOption
,
1468 "macro" : MacroList
,
1471 return MakefileTemplateDict
1473 ## Get the root directory list for intermediate files of all modules build
1475 # @retval list The list of directory
1477 def GetModuleBuildDirectoryList(self
):
1479 for ModuleAutoGen
in self
._AutoGenObject
.ModuleAutoGenList
:
1480 if not ModuleAutoGen
.IsBinaryModule
:
1481 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, ModuleAutoGen
.BuildDir
))
1484 ## Get the root directory list for intermediate files of all libraries build
1486 # @retval list The list of directory
1488 def GetLibraryBuildDirectoryList(self
):
1490 for LibraryAutoGen
in self
._AutoGenObject
.LibraryAutoGenList
:
1491 if not LibraryAutoGen
.IsBinaryModule
:
1492 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, LibraryAutoGen
.BuildDir
))
1495 _TemplateDict
= property(_CreateTemplateDict
)
1497 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1498 if __name__
== '__main__':