2 # Create makefile for MS nmake and GNU make
4 # Copyright (c) 2007 - 2018, 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 from __future__
import absolute_import
17 import Common
.LongFilePathOs
as os
21 import os
.path
as path
22 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
23 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
24 from Common
.BuildToolError
import *
25 from Common
.Misc
import *
26 from Common
.StringUtils
import *
27 from .BuildEngine
import *
28 import Common
.GlobalData
as GlobalData
29 from collections
import OrderedDict
30 from Common
.DataType
import TAB_COMPILER_MSFT
32 ## Regular expression for finding header file inclusions
33 gIncludePattern
= re
.compile(r
"^[ \t]*[#%]?[ \t]*include(?:[ \t]*(?:\\(?:\r\n|\r|\n))*[ \t]*)*(?:\(?[\"<]?
[ \t]*)([-\w
.\\/() \t]+)(?
:[ \t]*[\">]?\
)?
)", re.MULTILINE | re.UNICODE | re.IGNORECASE)
35 ## Regular expression for matching macro used in header file inclusion
36 gMacroPattern = re.compile("([_A
-Z
][_A
-Z0
-9]*)[ \t]*\
((.+)\
)", re.UNICODE)
40 ## pattern for include style in Edk.x code
41 gProtocolDefinition = "Protocol
/%(HeaderKey)s/%(HeaderKey)s.h
"
42 gGuidDefinition = "Guid
/%(HeaderKey)s/%(HeaderKey)s.h
"
43 gArchProtocolDefinition = "ArchProtocol
/%(HeaderKey)s/%(HeaderKey)s.h
"
44 gPpiDefinition = "Ppi
/%(HeaderKey)s/%(HeaderKey)s.h
"
45 gIncludeMacroConversion = {
46 "EFI_PROTOCOL_DEFINITION
" : gProtocolDefinition,
47 "EFI_GUID_DEFINITION
" : gGuidDefinition,
48 "EFI_ARCH_PROTOCOL_DEFINITION
" : gArchProtocolDefinition,
49 "EFI_PROTOCOL_PRODUCER
" : gProtocolDefinition,
50 "EFI_PROTOCOL_CONSUMER
" : gProtocolDefinition,
51 "EFI_PROTOCOL_DEPENDENCY
" : gProtocolDefinition,
52 "EFI_ARCH_PROTOCOL_PRODUCER
" : gArchProtocolDefinition,
53 "EFI_ARCH_PROTOCOL_CONSUMER
" : gArchProtocolDefinition,
54 "EFI_ARCH_PROTOCOL_DEPENDENCY
" : gArchProtocolDefinition,
55 "EFI_PPI_DEFINITION
" : gPpiDefinition,
56 "EFI_PPI_PRODUCER
" : gPpiDefinition,
57 "EFI_PPI_CONSUMER
" : gPpiDefinition,
58 "EFI_PPI_DEPENDENCY
" : gPpiDefinition,
61 ## default makefile type
63 if sys.platform == "win32
":
71 # This base class encapsules build file and its generation. It uses template to generate
72 # the content of build file. The content of build file will be got from AutoGen objects.
74 class BuildFile(object):
75 ## template used to generate the build file (i.e. makefile if using make)
76 _TEMPLATE_ = TemplateString('')
78 _DEFAULT_FILE_NAME_ = "Makefile
"
80 ## default file name for each type of build file
83 "gmake
" : "GNUmakefile
"
86 ## Fixed header string for makefile
87 _MAKEFILE_HEADER = '''#
89 # This file is auto-generated by build utility
97 # Auto-generated makefile for building modules, libraries or platform
101 ## Header string for each type of build file
103 "nmake
" : _MAKEFILE_HEADER % _FILE_NAME_["nmake
"],
104 "gmake
" : _MAKEFILE_HEADER % _FILE_NAME_["gmake
"]
107 ## shell commands which can be used in build file in the form of macro
108 # $(CP) copy file command
109 # $(MV) move file command
110 # $(RM) remove file command
111 # $(MD) create dir command
112 # $(RD) remove dir command
120 "RD
" : "rmdir
/s
/q
",
132 ## directory separator
138 ## directory creation template
140 "nmake
" : 'if not exist %(dir)s $(MD) %(dir)s',
141 "gmake
" : "$
(MD
) %(dir)s"
144 ## directory removal template
146 "nmake
" : 'if exist %(dir)s $(RD) %(dir)s',
147 "gmake
" : "$
(RD
) %(dir)s"
151 "nmake
" : 'if exist %(Src)s $(CP) %(Src)s %(Dst)s',
152 "gmake
" : "test
-f
%(Src)s && $
(CP
) %(Src)s %(Dst)s"
156 "nmake
" : 'if exist %(dir)s cd %(dir)s',
157 "gmake
" : "test
-e
%(dir)s && cd
%(dir)s"
161 "nmake
" : 'if exist %(file)s "$
(MAKE
)" $(MAKE_FLAGS) -f %(file)s',
162 "gmake
" : 'test -e %(file)s && "$
(MAKE
)" $(MAKE_FLAGS) -f %(file)s'
166 "nmake
" : '!INCLUDE',
170 _INC_FLAG_ = {TAB_COMPILER_MSFT : "/I
", "GCC
" : "-I
", "INTEL
" : "-I
", "RVCT
" : "-I
", "NASM
" : "-I
"}
172 ## Constructor of BuildFile
174 # @param AutoGenObject Object of AutoGen class
176 def __init__(self, AutoGenObject):
177 self._AutoGenObject = AutoGenObject
178 self._FileType = gMakeType
182 # @param FileType Type of build file. Only nmake and gmake are supported now.
184 # @retval TRUE The build file is created or re-created successfully
185 # @retval FALSE The build file exists and is the same as the one to be generated
187 def Generate(self, FileType=gMakeType):
188 if FileType not in self._FILE_NAME_:
189 EdkLogger.error("build
", PARAMETER_INVALID, "Invalid build
type [%s]" % FileType,
190 ExtraData="[%s]" % str(self._AutoGenObject))
191 self._FileType = FileType
192 FileContent = self._TEMPLATE_.Replace(self._TemplateDict)
193 FileName = self._FILE_NAME_[FileType]
194 return SaveFileOnChange(os.path.join(self._AutoGenObject.MakeFileDir, FileName), FileContent, False)
196 ## Return a list of directory creation command string
198 # @param DirList The list of directory to be created
200 # @retval list The directory creation command list
202 def GetCreateDirectoryCommand(self, DirList):
203 return [self._MD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
205 ## Return a list of directory removal command string
207 # @param DirList The list of directory to be removed
209 # @retval list The directory removal command list
211 def GetRemoveDirectoryCommand(self, DirList):
212 return [self._RD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
214 def PlaceMacro(self, Path, MacroDefinitions={}):
215 if Path.startswith("$
("):
218 PathLength = len(Path)
219 for MacroName in MacroDefinitions:
220 MacroValue = MacroDefinitions[MacroName]
221 MacroValueLength = len(MacroValue)
222 if MacroValueLength == 0:
224 if MacroValueLength <= PathLength and Path.startswith(MacroValue):
225 Path = "$
(%s)%s" % (MacroName, Path[MacroValueLength:])
229 ## ModuleMakefile class
231 # This class encapsules makefie and its generation for module. It uses template to generate
232 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
234 class ModuleMakefile(BuildFile):
235 ## template used to generate the makefile for module
236 _TEMPLATE_ = TemplateString('''\
240 # Platform Macro Definition
242 PLATFORM_NAME = ${platform_name}
243 PLATFORM_GUID = ${platform_guid}
244 PLATFORM_VERSION = ${platform_version}
245 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
246 PLATFORM_DIR = ${platform_dir}
247 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
250 # Module Macro Definition
252 MODULE_NAME = ${module_name}
253 MODULE_GUID = ${module_guid}
254 MODULE_NAME_GUID = ${module_name_guid}
255 MODULE_VERSION = ${module_version}
256 MODULE_TYPE = ${module_type}
257 MODULE_FILE = ${module_file}
258 MODULE_FILE_BASE_NAME = ${module_file_base_name}
259 BASE_NAME = $(MODULE_NAME)
260 MODULE_RELATIVE_DIR = ${module_relative_directory}
261 PACKAGE_RELATIVE_DIR = ${package_relative_directory}
262 MODULE_DIR = ${module_dir}
263 FFS_OUTPUT_DIR = ${ffs_output_directory}
265 MODULE_ENTRY_POINT = ${module_entry_point}
266 ARCH_ENTRY_POINT = ${arch_entry_point}
267 IMAGE_ENTRY_POINT = ${image_entry_point}
269 ${BEGIN}${module_extra_defines}
272 # Build Configuration Macro Definition
274 ARCH = ${architecture}
275 TOOLCHAIN = ${toolchain_tag}
276 TOOLCHAIN_TAG = ${toolchain_tag}
277 TARGET = ${build_target}
280 # Build Directory Macro Definition
282 # PLATFORM_BUILD_DIR = ${platform_build_directory}
283 BUILD_DIR = ${platform_build_directory}
284 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
286 MODULE_BUILD_DIR = ${module_build_directory}
287 OUTPUT_DIR = ${module_output_directory}
288 DEBUG_DIR = ${module_debug_directory}
289 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
290 DEST_DIR_DEBUG = $(DEBUG_DIR)
293 # Shell Command Macro
295 ${BEGIN}${shell_command_code} = ${shell_command}
299 # Tools definitions specific to this module
301 ${BEGIN}${module_tool_definitions}
303 MAKE_FILE = ${makefile_path}
308 ${BEGIN}${file_macro}
311 COMMON_DEPS = ${BEGIN}${common_dependency_file} \\
315 # Overridable Target Macro Definitions
317 FORCE_REBUILD = force_build
320 BC_TARGET = ${BEGIN}${backward_compatible_target} ${END}
321 CODA_TARGET = ${BEGIN}${remaining_build_target} \\
325 # Default target, which will build dependent libraries in addition to source files
332 # Target used when called from platform makefile, which will bypass the build of dependent libraries
335 pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
341 mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET)
344 # Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets
347 tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
350 # Phony target which is used to force executing commands for a target
356 # Target to update the FD
362 # Initialization target: print build information and create necessary directories
367 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
370 ${BEGIN}\t-@${create_directory_command}\n${END}
373 \t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h
379 \t${BEGIN}@"$
(MAKE
)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name}
380 \t${END}@cd $(MODULE_BUILD_DIR)
383 # Build Flash Device Image
386 \t@"$
(MAKE
)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds
387 \t@cd $(MODULE_BUILD_DIR)
390 # Individual Object Build Targets
392 ${BEGIN}${file_build_target}
396 # clean all intermediate files
399 \t${BEGIN}${clean_command}
400 \t${END}\t$(RM) AutoGenTimeStamp
403 # clean all generated files
406 ${BEGIN}\t${cleanall_command}
407 ${END}\t$(RM) *.pdb *.idb > NUL 2>&1
408 \t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi
409 \t$(RM) AutoGenTimeStamp
412 # clean all dependent libraries built
415 \t${BEGIN}-@${library_build_command} cleanall
416 \t${END}@cd $(MODULE_BUILD_DIR)\n\n''')
418 _FILE_MACRO_TEMPLATE = TemplateString("${macro_name}
= ${BEGIN}
\\\n ${source_file}${END}
\n")
419 _BUILD_TARGET_TEMPLATE = TemplateString("${BEGIN}${target}
: ${deps}
\n${END}
\t${cmd}
\n")
421 ## Constructor of ModuleMakefile
423 # @param ModuleAutoGen Object of ModuleAutoGen class
425 def __init__(self, ModuleAutoGen):
426 BuildFile.__init__(self, ModuleAutoGen)
427 self.PlatformInfo = self._AutoGenObject.PlatformInfo
429 self.ResultFileList = []
430 self.IntermediateDirectoryList = ["$
(DEBUG_DIR
)", "$
(OUTPUT_DIR
)"]
432 self.FileBuildTargetList = [] # [(src, target string)]
433 self.BuildTargetList = [] # [target string]
434 self.PendingBuildTargetList = [] # [FileBuildRule objects]
435 self.CommonFileDependency = []
436 self.FileListMacros = {}
437 self.ListFileMacros = {}
440 self.LibraryBuildCommandList = []
441 self.LibraryFileList = []
442 self.LibraryMakefileList = []
443 self.LibraryBuildDirectoryList = []
444 self.SystemLibraryList = []
445 self.Macros = OrderedDict()
446 self.Macros["OUTPUT_DIR
" ] = self._AutoGenObject.Macros["OUTPUT_DIR
"]
447 self.Macros["DEBUG_DIR
" ] = self._AutoGenObject.Macros["DEBUG_DIR
"]
448 self.Macros["MODULE_BUILD_DIR
"] = self._AutoGenObject.Macros["MODULE_BUILD_DIR
"]
449 self.Macros["BIN_DIR
" ] = self._AutoGenObject.Macros["BIN_DIR
"]
450 self.Macros["BUILD_DIR
" ] = self._AutoGenObject.Macros["BUILD_DIR
"]
451 self.Macros["WORKSPACE
" ] = self._AutoGenObject.Macros["WORKSPACE
"]
452 self.Macros["FFS_OUTPUT_DIR
" ] = self._AutoGenObject.Macros["FFS_OUTPUT_DIR
"]
453 self.GenFfsList = ModuleAutoGen.GenFfsList
454 self.MacroList = ['FFS_OUTPUT_DIR', 'MODULE_GUID', 'OUTPUT_DIR']
455 self.FfsOutputFileList = []
457 # Compose a dict object containing information used to do replacement in template
459 def _TemplateDict(self):
460 if self._FileType not in self._SEP_:
461 EdkLogger.error("build
", PARAMETER_INVALID, "Invalid Makefile
type [%s]" % self._FileType,
462 ExtraData="[%s]" % str(self._AutoGenObject))
463 MyAgo = self._AutoGenObject
464 Separator = self._SEP_[self._FileType]
466 # break build if no source files and binary files are found
467 if len(MyAgo.SourceFileList) == 0 and len(MyAgo.BinaryFileList) == 0:
468 EdkLogger.error("build
", AUTOGEN_ERROR, "No files to be built
in module
[%s, %s, %s]"
469 % (MyAgo.BuildTarget, MyAgo.ToolChain, MyAgo.Arch),
470 ExtraData="[%s]" % str(MyAgo))
472 # convert dependent libraries to build command
473 self.ProcessDependentLibrary()
474 if len(MyAgo.Module.ModuleEntryPointList) > 0:
475 ModuleEntryPoint = MyAgo.Module.ModuleEntryPointList[0]
477 ModuleEntryPoint = "_ModuleEntryPoint
"
479 ArchEntryPoint = ModuleEntryPoint
481 if MyAgo.Arch == "EBC
":
482 # EBC compiler always use "EfiStart
" as entry point. Only applies to EdkII modules
483 ImageEntryPoint = "EfiStart
"
485 # EdkII modules always use "_ModuleEntryPoint
" as entry point
486 ImageEntryPoint = "_ModuleEntryPoint
"
488 for k, v in MyAgo.Module.Defines.items():
489 if k not in MyAgo.Macros:
492 if 'MODULE_ENTRY_POINT' not in MyAgo.Macros:
493 MyAgo.Macros['MODULE_ENTRY_POINT'] = ModuleEntryPoint
494 if 'ARCH_ENTRY_POINT' not in MyAgo.Macros:
495 MyAgo.Macros['ARCH_ENTRY_POINT'] = ArchEntryPoint
496 if 'IMAGE_ENTRY_POINT' not in MyAgo.Macros:
497 MyAgo.Macros['IMAGE_ENTRY_POINT'] = ImageEntryPoint
499 PCI_COMPRESS_Flag = False
500 for k, v in MyAgo.Module.Defines.items():
501 if 'PCI_COMPRESS' == k and 'TRUE' == v:
502 PCI_COMPRESS_Flag = True
506 IncPrefix = self._INC_FLAG_[MyAgo.ToolChainFamily]
507 for Tool in MyAgo.BuildOption:
508 for Attr in MyAgo.BuildOption[Tool]:
509 Value = MyAgo.BuildOption[Tool][Attr]
513 ToolsDef.append("%s = %s" % (Tool, Value))
515 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
518 # Remove duplicated include path, if any
520 Value = RemoveDupOption(Value, IncPrefix, MyAgo.IncludePathList)
521 if Tool == "OPTROM
" and PCI_COMPRESS_Flag:
522 ValueList = Value.split()
524 for i, v in enumerate(ValueList):
527 Value = ' '.join(ValueList)
529 ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
532 # generate the Response file and Response flag
533 RespDict = self.CommandExceedLimit()
534 RespFileList = os.path.join(MyAgo.OutputDir, 'respfilelist.txt')
536 RespFileListContent = ''
537 for Resp in RespDict:
538 RespFile = os.path.join(MyAgo.OutputDir, str(Resp).lower() + '.txt')
539 StrList = RespDict[Resp].split(' ')
544 UnexpandMacro.append(Str)
547 UnexpandMacroStr = ' '.join(UnexpandMacro)
548 NewRespStr = ' '.join(NewStr)
549 SaveFileOnChange(RespFile, NewRespStr, False)
550 ToolsDef.append("%s = %s" % (Resp, UnexpandMacroStr + ' @' + RespFile))
551 RespFileListContent += '@' + RespFile + TAB_LINE_BREAK
552 RespFileListContent += NewRespStr + TAB_LINE_BREAK
553 SaveFileOnChange(RespFileList, RespFileListContent, False)
555 if os.path.exists(RespFileList):
556 os.remove(RespFileList)
558 # convert source files and binary files to build targets
559 self.ResultFileList = [str(T.Target) for T in MyAgo.CodaTargetList]
560 if len(self.ResultFileList) == 0 and len(MyAgo.SourceFileList) != 0:
561 EdkLogger.error("build
", AUTOGEN_ERROR, "Nothing to build
",
562 ExtraData="[%s]" % str(MyAgo))
564 self.ProcessBuildTargetList()
565 self.ParserGenerateFfsCmd()
567 # Generate macros used to represent input files
568 FileMacroList = [] # macro name = file list
569 for FileListMacro in self.FileListMacros:
570 FileMacro = self._FILE_MACRO_TEMPLATE.Replace(
572 "macro_name
" : FileListMacro,
573 "source_file
" : self.FileListMacros[FileListMacro]
576 FileMacroList.append(FileMacro)
578 # INC_LIST is special
581 for P in MyAgo.IncludePathList:
582 IncludePathList.append(IncPrefix + self.PlaceMacro(P, self.Macros))
583 if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:
584 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix + P)
585 FileMacro += self._FILE_MACRO_TEMPLATE.Replace(
587 "macro_name
" : "INC
",
588 "source_file
" : IncludePathList
591 FileMacroList.append(FileMacro)
592 # Add support when compiling .nasm source files
593 for File in self.FileCache.keys():
594 if not str(File).endswith('.nasm'):
597 for P in MyAgo.IncludePathList:
598 IncludePath = self._INC_FLAG_['NASM'] + self.PlaceMacro(P, self.Macros)
599 if IncludePath.endswith(os.sep):
600 IncludePath = IncludePath.rstrip(os.sep)
601 # When compiling .nasm files, need to add a literal backslash at each path
602 # To specify a literal backslash at the end of the line, precede it with a caret (^)
603 if P == MyAgo.IncludePathList[-1] and os.sep == '\\':
604 IncludePath = ''.join([IncludePath, '^', os.sep])
606 IncludePath = os.path.join(IncludePath, '')
607 IncludePathList.append(IncludePath)
608 FileMacroList.append(self._FILE_MACRO_TEMPLATE.Replace({"macro_name
": "NASM_INC
", "source_file
": IncludePathList}))
611 # Generate macros used to represent files containing list of input files
612 for ListFileMacro in self.ListFileMacros:
613 ListFileName = os.path.join(MyAgo.OutputDir, "%s.lst
" % ListFileMacro.lower()[:len(ListFileMacro) - 5])
614 FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))
617 "\n".join(self.ListFileMacros[ListFileMacro]),
623 MakefileName = self._FILE_NAME_[self._FileType]
624 LibraryMakeCommandList = []
625 for D in self.LibraryBuildDirectoryList:
626 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)}
627 LibraryMakeCommandList.append(Command)
629 package_rel_dir = MyAgo.SourceDir
630 current_dir = self.Macros["WORKSPACE
"]
632 while not found and os.sep in package_rel_dir:
633 index = package_rel_dir.index(os.sep)
634 current_dir = mws.join(current_dir, package_rel_dir[:index])
635 if os.path.exists(current_dir):
636 for fl in os.listdir(current_dir):
637 if fl.endswith('.dec'):
640 package_rel_dir = package_rel_dir[index + 1:]
642 MakefileTemplateDict = {
643 "makefile_header
" : self._FILE_HEADER_[self._FileType],
644 "makefile_path
" : os.path.join("$
(MODULE_BUILD_DIR
)", MakefileName),
645 "makefile_name
" : MakefileName,
646 "platform_name
" : self.PlatformInfo.Name,
647 "platform_guid
" : self.PlatformInfo.Guid,
648 "platform_version
" : self.PlatformInfo.Version,
649 "platform_relative_directory
": self.PlatformInfo.SourceDir,
650 "platform_output_directory
" : self.PlatformInfo.OutputDir,
651 "ffs_output_directory
" : MyAgo.Macros["FFS_OUTPUT_DIR
"],
652 "platform_dir
" : MyAgo.Macros["PLATFORM_DIR
"],
654 "module_name
" : MyAgo.Name,
655 "module_guid
" : MyAgo.Guid,
656 "module_name_guid
" : MyAgo.UniqueBaseName,
657 "module_version
" : MyAgo.Version,
658 "module_type
" : MyAgo.ModuleType,
659 "module_file
" : MyAgo.MetaFile.Name,
660 "module_file_base_name
" : MyAgo.MetaFile.BaseName,
661 "module_relative_directory
" : MyAgo.SourceDir,
662 "module_dir
" : mws.join (self.Macros["WORKSPACE
"], MyAgo.SourceDir),
663 "package_relative_directory
": package_rel_dir,
664 "module_extra_defines
" : ["%s = %s" % (k, v) for k, v in MyAgo.Module.Defines.items()],
666 "architecture
" : MyAgo.Arch,
667 "toolchain_tag
" : MyAgo.ToolChain,
668 "build_target
" : MyAgo.BuildTarget,
670 "platform_build_directory
" : self.PlatformInfo.BuildDir,
671 "module_build_directory
" : MyAgo.BuildDir,
672 "module_output_directory
" : MyAgo.OutputDir,
673 "module_debug_directory
" : MyAgo.DebugDir,
675 "separator
" : Separator,
676 "module_tool_definitions
" : ToolsDef,
678 "shell_command_code
" : self._SHELL_CMD_[self._FileType].keys(),
679 "shell_command
" : self._SHELL_CMD_[self._FileType].values(),
681 "module_entry_point
" : ModuleEntryPoint,
682 "image_entry_point
" : ImageEntryPoint,
683 "arch_entry_point
" : ArchEntryPoint,
684 "remaining_build_target
" : self.ResultFileList,
685 "common_dependency_file
" : self.CommonFileDependency,
686 "create_directory_command
" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
687 "clean_command
" : self.GetRemoveDirectoryCommand(["$
(OUTPUT_DIR
)"]),
688 "cleanall_command
" : self.GetRemoveDirectoryCommand(["$
(DEBUG_DIR
)", "$
(OUTPUT_DIR
)"]),
689 "dependent_library_build_directory
" : self.LibraryBuildDirectoryList,
690 "library_build_command
" : LibraryMakeCommandList,
691 "file_macro
" : FileMacroList,
692 "file_build_target
" : self.BuildTargetList,
693 "backward_compatible_target
": BcTargetList,
696 return MakefileTemplateDict
698 def ParserGenerateFfsCmd(self):
699 #Add Ffs cmd to self.BuildTargetList
703 for Cmd in self.GenFfsList:
705 for CopyCmd in Cmd[2]:
707 Src = self.ReplaceMacro(Src)
708 Dst = self.ReplaceMacro(Dst)
709 if Dst not in self.ResultFileList:
710 self.ResultFileList.append(Dst)
711 if '%s :' %(Dst) not in self.BuildTargetList:
712 self.BuildTargetList.append("%s :" %(Dst))
713 self.BuildTargetList.append('\t' + self._CP_TEMPLATE_[self._FileType] %{'Src': Src, 'Dst': Dst})
716 for index, Str in enumerate(FfsCmdList):
718 OutputFile = FfsCmdList[index + 1]
720 if DepsFileList == []:
721 DepsFileList = [FfsCmdList[index + 1]]
723 DepsFileList.append(FfsCmdList[index + 1])
724 DepsFileString = ' '.join(DepsFileList).strip()
725 if DepsFileString == '':
727 OutputFile = self.ReplaceMacro(OutputFile)
728 self.ResultFileList.append(OutputFile)
729 DepsFileString = self.ReplaceMacro(DepsFileString)
730 self.BuildTargetList.append('%s : %s' % (OutputFile, DepsFileString))
731 CmdString = ' '.join(FfsCmdList).strip()
732 CmdString = self.ReplaceMacro(CmdString)
733 self.BuildTargetList.append('\t%s' % CmdString)
735 self.ParseSecCmd(DepsFileList, Cmd[1])
736 for SecOutputFile, SecDepsFile, SecCmd in self.FfsOutputFileList :
737 self.BuildTargetList.append('%s : %s' % (self.ReplaceMacro(SecOutputFile), self.ReplaceMacro(SecDepsFile)))
738 self.BuildTargetList.append('\t%s' % self.ReplaceMacro(SecCmd))
739 self.FfsOutputFileList = []
741 def ParseSecCmd(self, OutputFileList, CmdTuple):
742 for OutputFile in OutputFileList:
743 for SecCmdStr in CmdTuple:
745 SecCmdList = SecCmdStr.split()
746 CmdName = SecCmdList[0]
747 for index, CmdItem in enumerate(SecCmdList):
748 if '-o' == CmdItem and OutputFile == SecCmdList[index + 1]:
750 while index + 1 < len(SecCmdList):
751 if not SecCmdList[index+1].startswith('-'):
752 SecDepsFileList.append(SecCmdList[index + 1])
754 if CmdName == 'Trim':
755 SecDepsFileList.append(os.path.join('$(DEBUG_DIR)', os.path.basename(OutputFile).replace('offset', 'efi')))
756 if OutputFile.endswith('.ui') or OutputFile.endswith('.ver'):
757 SecDepsFileList.append(os.path.join('$(MODULE_DIR)', '$(MODULE_FILE)'))
758 self.FfsOutputFileList.append((OutputFile, ' '.join(SecDepsFileList), SecCmdStr))
759 if len(SecDepsFileList) > 0:
760 self.ParseSecCmd(SecDepsFileList, CmdTuple)
765 def ReplaceMacro(self, str):
766 for Macro in self.MacroList:
767 if self._AutoGenObject.Macros[Macro] and self._AutoGenObject.Macros[Macro] in str:
768 str = str.replace(self._AutoGenObject.Macros[Macro], '$(' + Macro + ')')
771 def CommandExceedLimit(self):
773 'CC' : { 'Macro' : '$(CC_FLAGS)', 'Value' : False},
774 'PP' : { 'Macro' : '$(PP_FLAGS)', 'Value' : False},
775 'APP' : { 'Macro' : '$(APP_FLAGS)', 'Value' : False},
776 'ASLPP' : { 'Macro' : '$(ASLPP_FLAGS)', 'Value' : False},
777 'VFRPP' : { 'Macro' : '$(VFRPP_FLAGS)', 'Value' : False},
778 'ASM' : { 'Macro' : '$(ASM_FLAGS)', 'Value' : False},
779 'ASLCC' : { 'Macro' : '$(ASLCC_FLAGS)', 'Value' : False},
784 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
786 # base on the source files to decide the file type
787 for File in self._AutoGenObject.SourceFileList:
788 for type in self._AutoGenObject.FileTypes:
789 if File in self._AutoGenObject.FileTypes[type]:
790 if type not in FileTypeList:
791 FileTypeList.append(type)
793 # calculate the command-line length
795 for type in FileTypeList:
796 BuildTargets = self._AutoGenObject.BuildRules[type].BuildTargets
797 for Target in BuildTargets:
798 CommandList = BuildTargets[Target].Commands
799 for SingleCommand in CommandList:
801 SingleCommandLength = len(SingleCommand)
802 SingleCommandList = SingleCommand.split()
803 if len(SingleCommandList) > 0:
804 for Flag in FlagDict:
805 if '$('+ Flag +')' in SingleCommandList[0]:
809 if 'PATH' not in self._AutoGenObject.BuildOption[Tool]:
810 EdkLogger.error("build
", AUTOGEN_ERROR, "%s_PATH doesn
't exist in %s ToolChain and %s Arch." %(Tool, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch), ExtraData="[%s]" % str(self._AutoGenObject))
811 SingleCommandLength += len(self._AutoGenObject.BuildOption[Tool]['PATH
'])
812 for item in SingleCommandList[1:]:
813 if FlagDict[Tool]['Macro
'] in item:
814 if 'FLAGS
' not in self._AutoGenObject.BuildOption[Tool]:
815 EdkLogger.error("build", AUTOGEN_ERROR, "%s_FLAGS doesn't exist
in %s ToolChain
and %s Arch
." %(Tool, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch), ExtraData="[%s]" % str(self._AutoGenObject))
816 Str = self._AutoGenObject.BuildOption[Tool]['FLAGS']
817 for Option in self._AutoGenObject.BuildOption:
818 for Attr in self._AutoGenObject.BuildOption[Option]:
819 if Str.find(Option + '_' + Attr) != -1:
820 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
821 while(Str.find('$(') != -1):
822 for macro in self._AutoGenObject.Macros:
823 MacroName = '$('+ macro + ')'
824 if (Str.find(MacroName) != -1):
825 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
829 SingleCommandLength += len(Str)
830 elif '$(INC)' in item:
831 SingleCommandLength += self._AutoGenObject.IncludePathLength + len(IncPrefix) * len(self._AutoGenObject.IncludePathList)
832 elif item.find('$(') != -1:
834 for Option in self._AutoGenObject.BuildOption:
835 for Attr in self._AutoGenObject.BuildOption[Option]:
836 if Str.find(Option + '_' + Attr) != -1:
837 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
838 while(Str.find('$(') != -1):
839 for macro in self._AutoGenObject.Macros:
840 MacroName = '$('+ macro + ')'
841 if (Str.find(MacroName) != -1):
842 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
846 SingleCommandLength += len(Str)
848 if SingleCommandLength > GlobalData.gCommandMaxLength:
849 FlagDict[Tool]['Value'] = True
851 # generate the response file content by combine the FLAGS and INC
852 for Flag in FlagDict:
853 if FlagDict[Flag]['Value']:
855 RespMacro = FlagDict[Flag]['Macro'].replace('FLAGS', 'RESP')
856 Value = self._AutoGenObject.BuildOption[Flag]['FLAGS']
857 for inc in self._AutoGenObject.IncludePathList:
858 Value += ' ' + IncPrefix + inc
859 for Option in self._AutoGenObject.BuildOption:
860 for Attr in self._AutoGenObject.BuildOption[Option]:
861 if Value.find(Option + '_' + Attr) != -1:
862 Value = Value.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
863 while (Value.find('$(') != -1):
864 for macro in self._AutoGenObject.Macros:
865 MacroName = '$('+ macro + ')'
866 if (Value.find(MacroName) != -1):
867 Value = Value.replace(MacroName, self._AutoGenObject.Macros[macro])
872 if self._AutoGenObject.ToolChainFamily == 'GCC':
873 RespDict[Key] = Value.replace('\\', '/')
875 RespDict[Key] = Value
876 for Target in BuildTargets:
877 for i, SingleCommand in enumerate(BuildTargets[Target].Commands):
878 if FlagDict[Flag]['Macro'] in SingleCommand:
879 BuildTargets[Target].Commands[i] = SingleCommand.replace('$(INC)', '').replace(FlagDict[Flag]['Macro'], RespMacro)
882 def ProcessBuildTargetList(self):
884 # Search dependency file list for each source file
886 ForceIncludedFile = []
887 for File in self._AutoGenObject.AutoGenFileList:
889 ForceIncludedFile.append(File)
892 for Target in self._AutoGenObject.IntroTargetList:
893 SourceFileList.extend(Target.Inputs)
894 OutPutFileList.extend(Target.Outputs)
897 for Item in OutPutFileList:
898 if Item in SourceFileList:
899 SourceFileList.remove(Item)
901 FileDependencyDict = self.GetFileDependency(
904 self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList
907 for File,Dependency in FileDependencyDict.items():
909 FileDependencyDict[File] = ['$(FORCE_REBUILD)']
912 self._AutoGenObject.AutoGenDepSet |= set(Dependency)
915 if File.Ext not in [".c
", ".C
"] or File.Name == "AutoGen
.c
":
918 DepSet = set(Dependency)
920 DepSet &= set(Dependency)
921 # in case nothing in SourceFileList
925 # Extract common files list in the dependency files
928 self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros))
930 for File in FileDependencyDict:
932 if File.Ext not in [".c
", ".C
"] or File.Name == "AutoGen
.c
":
934 NewDepSet = set(FileDependencyDict[File])
936 FileDependencyDict[File] = ["$
(COMMON_DEPS
)"] + list(NewDepSet)
938 # Convert target description object to target string in makefile
939 for Type in self._AutoGenObject.Targets:
940 for T in self._AutoGenObject.Targets[Type]:
941 # Generate related macros if needed
942 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
943 self.FileListMacros[T.FileListMacro] = []
944 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:
945 self.ListFileMacros[T.ListFileMacro] = []
946 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:
947 self.ListFileMacros[T.IncListFileMacro] = []
950 # Add force-dependencies
951 for Dep in T.Dependencies:
952 Deps.append(self.PlaceMacro(str(Dep), self.Macros))
953 # Add inclusion-dependencies
954 if len(T.Inputs) == 1 and T.Inputs[0] in FileDependencyDict:
955 for F in FileDependencyDict[T.Inputs[0]]:
956 Deps.append(self.PlaceMacro(str(F), self.Macros))
957 # Add source-dependencies
959 NewFile = self.PlaceMacro(str(F), self.Macros)
960 # In order to use file list macro as dependency
962 # gnu tools need forward slash path separater, even on Windows
963 self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/'))
964 self.FileListMacros[T.FileListMacro].append(NewFile)
965 elif T.GenFileListMacro:
966 self.FileListMacros[T.FileListMacro].append(NewFile)
970 # Use file list macro as dependency
971 if T.GenFileListMacro:
972 Deps.append("$
(%s)" % T.FileListMacro)
973 if Type in [TAB_OBJECT_FILE, TAB_STATIC_LIBRARY]:
974 Deps.append("$
(%s)" % T.ListFileMacro)
977 "target
" : self.PlaceMacro(T.Target.Path, self.Macros),
978 "cmd
" : "\n\t".join(T.Commands),
981 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
983 ## For creating makefile targets for dependent libraries
984 def ProcessDependentLibrary(self):
985 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
986 if not LibraryAutoGen.IsBinaryModule:
987 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
989 ## Return a list containing source file's dependencies
991 # @param FileList The list of source files
992 # @param ForceInculeList The list of files which will be included forcely
993 # @param SearchPathList The list of search path
995 # @retval dict The mapping between source file path and its dependencies
997 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
1000 Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)
1003 ## Find dependencies for one source file
1005 # By searching recursively "#include" directive in file, find out all the
1006 # files needed by given source file. The dependecies will be only searched
1007 # in given search path list.
1009 # @param File The source file
1010 # @param ForceInculeList The list of files which will be included forcely
1011 # @param SearchPathList The list of search path
1013 # @retval list The list of files the given source file depends on
1015 def GetDependencyList(self
, File
, ForceList
, SearchPathList
):
1016 EdkLogger
.debug(EdkLogger
.DEBUG_1
, "Try to get dependency files for %s" % File
)
1017 FileStack
= [File
] + ForceList
1018 DependencySet
= set()
1020 if self
._AutoGenObject
.Arch
not in gDependencyDatabase
:
1021 gDependencyDatabase
[self
._AutoGenObject
.Arch
] = {}
1022 DepDb
= gDependencyDatabase
[self
._AutoGenObject
.Arch
]
1024 while len(FileStack
) > 0:
1027 FullPathDependList
= []
1028 if F
in self
.FileCache
:
1029 for CacheFile
in self
.FileCache
[F
]:
1030 FullPathDependList
.append(CacheFile
)
1031 if CacheFile
not in DependencySet
:
1032 FileStack
.append(CacheFile
)
1033 DependencySet
.update(FullPathDependList
)
1036 CurrentFileDependencyList
= []
1038 CurrentFileDependencyList
= DepDb
[F
]
1041 Fd
= open(F
.Path
, 'r')
1042 except BaseException
as X
:
1043 EdkLogger
.error("build", FILE_OPEN_FAILURE
, ExtraData
=F
.Path
+ "\n\t" + str(X
))
1045 FileContent
= Fd
.read()
1047 if len(FileContent
) == 0:
1050 if FileContent
[0] == 0xff or FileContent
[0] == 0xfe:
1051 FileContent
= unicode(FileContent
, "utf-16")
1052 IncludedFileList
= gIncludePattern
.findall(FileContent
)
1054 for Inc
in IncludedFileList
:
1056 # if there's macro used to reference header file, expand it
1057 HeaderList
= gMacroPattern
.findall(Inc
)
1058 if len(HeaderList
) == 1 and len(HeaderList
[0]) == 2:
1059 HeaderType
= HeaderList
[0][0]
1060 HeaderKey
= HeaderList
[0][1]
1061 if HeaderType
in gIncludeMacroConversion
:
1062 Inc
= gIncludeMacroConversion
[HeaderType
] % {"HeaderKey" : HeaderKey
}
1064 # not known macro used in #include, always build the file by
1065 # returning a empty dependency
1066 self
.FileCache
[File
] = []
1068 Inc
= os
.path
.normpath(Inc
)
1069 CurrentFileDependencyList
.append(Inc
)
1070 DepDb
[F
] = CurrentFileDependencyList
1072 CurrentFilePath
= F
.Dir
1073 PathList
= [CurrentFilePath
] + SearchPathList
1074 for Inc
in CurrentFileDependencyList
:
1075 for SearchPath
in PathList
:
1076 FilePath
= os
.path
.join(SearchPath
, Inc
)
1077 if FilePath
in gIsFileMap
:
1078 if not gIsFileMap
[FilePath
]:
1080 # If isfile is called too many times, the performance is slow down.
1081 elif not os
.path
.isfile(FilePath
):
1082 gIsFileMap
[FilePath
] = False
1085 gIsFileMap
[FilePath
] = True
1086 FilePath
= PathClass(FilePath
)
1087 FullPathDependList
.append(FilePath
)
1088 if FilePath
not in DependencySet
:
1089 FileStack
.append(FilePath
)
1092 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "%s included by %s was not found "\
1093 "in any given path:\n\t%s" % (Inc
, F
, "\n\t".join(SearchPathList
)))
1095 self
.FileCache
[F
] = FullPathDependList
1096 DependencySet
.update(FullPathDependList
)
1098 DependencySet
.update(ForceList
)
1099 if File
in DependencySet
:
1100 DependencySet
.remove(File
)
1101 DependencyList
= list(DependencySet
) # remove duplicate ones
1103 return DependencyList
1105 ## CustomMakefile class
1107 # This class encapsules makefie and its generation for module. It uses template to generate
1108 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
1110 class CustomMakefile(BuildFile
):
1111 ## template used to generate the makefile for module with custom makefile
1112 _TEMPLATE_
= TemplateString('''\
1116 # Platform Macro Definition
1118 PLATFORM_NAME = ${platform_name}
1119 PLATFORM_GUID = ${platform_guid}
1120 PLATFORM_VERSION = ${platform_version}
1121 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
1122 PLATFORM_DIR = ${platform_dir}
1123 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1126 # Module Macro Definition
1128 MODULE_NAME = ${module_name}
1129 MODULE_GUID = ${module_guid}
1130 MODULE_NAME_GUID = ${module_name_guid}
1131 MODULE_VERSION = ${module_version}
1132 MODULE_TYPE = ${module_type}
1133 MODULE_FILE = ${module_file}
1134 MODULE_FILE_BASE_NAME = ${module_file_base_name}
1135 BASE_NAME = $(MODULE_NAME)
1136 MODULE_RELATIVE_DIR = ${module_relative_directory}
1137 MODULE_DIR = ${module_dir}
1140 # Build Configuration Macro Definition
1142 ARCH = ${architecture}
1143 TOOLCHAIN = ${toolchain_tag}
1144 TOOLCHAIN_TAG = ${toolchain_tag}
1145 TARGET = ${build_target}
1148 # Build Directory Macro Definition
1150 # PLATFORM_BUILD_DIR = ${platform_build_directory}
1151 BUILD_DIR = ${platform_build_directory}
1152 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
1153 LIB_DIR = $(BIN_DIR)
1154 MODULE_BUILD_DIR = ${module_build_directory}
1155 OUTPUT_DIR = ${module_output_directory}
1156 DEBUG_DIR = ${module_debug_directory}
1157 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
1158 DEST_DIR_DEBUG = $(DEBUG_DIR)
1161 # Tools definitions specific to this module
1163 ${BEGIN}${module_tool_definitions}
1165 MAKE_FILE = ${makefile_path}
1168 # Shell Command Macro
1170 ${BEGIN}${shell_command_code} = ${shell_command}
1173 ${custom_makefile_content}
1176 # Target used when called from platform makefile, which will bypass the build of dependent libraries
1189 # Build Target used in multi-thread build mode, which no init target is needed
1195 # Initialization target: print build information and create necessary directories
1198 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
1199 ${BEGIN}\t-@${create_directory_command}\n${END}\
1203 ## Constructor of CustomMakefile
1205 # @param ModuleAutoGen Object of ModuleAutoGen class
1207 def __init__(self
, ModuleAutoGen
):
1208 BuildFile
.__init
__(self
, ModuleAutoGen
)
1209 self
.PlatformInfo
= self
._AutoGenObject
.PlatformInfo
1210 self
.IntermediateDirectoryList
= ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
1212 # Compose a dict object containing information used to do replacement in template
1214 def _TemplateDict(self
):
1215 Separator
= self
._SEP
_[self
._FileType
]
1216 MyAgo
= self
._AutoGenObject
1217 if self
._FileType
not in MyAgo
.CustomMakefile
:
1218 EdkLogger
.error('build', OPTION_NOT_SUPPORTED
, "No custom makefile for %s" % self
._FileType
,
1219 ExtraData
="[%s]" % str(MyAgo
))
1220 MakefilePath
= mws
.join(
1222 MyAgo
.CustomMakefile
[self
._FileType
]
1225 CustomMakefile
= open(MakefilePath
, 'r').read()
1227 EdkLogger
.error('build', FILE_OPEN_FAILURE
, File
=str(MyAgo
),
1228 ExtraData
=MyAgo
.CustomMakefile
[self
._FileType
])
1232 for Tool
in MyAgo
.BuildOption
:
1233 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
1236 for Attr
in MyAgo
.BuildOption
[Tool
]:
1237 if Attr
== "FAMILY":
1239 elif Attr
== "PATH":
1240 ToolsDef
.append("%s = %s" % (Tool
, MyAgo
.BuildOption
[Tool
][Attr
]))
1242 ToolsDef
.append("%s_%s = %s" % (Tool
, Attr
, MyAgo
.BuildOption
[Tool
][Attr
]))
1245 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1246 MakefileTemplateDict
= {
1247 "makefile_header" : self
._FILE
_HEADER
_[self
._FileType
],
1248 "makefile_path" : os
.path
.join("$(MODULE_BUILD_DIR)", MakefileName
),
1249 "platform_name" : self
.PlatformInfo
.Name
,
1250 "platform_guid" : self
.PlatformInfo
.Guid
,
1251 "platform_version" : self
.PlatformInfo
.Version
,
1252 "platform_relative_directory": self
.PlatformInfo
.SourceDir
,
1253 "platform_output_directory" : self
.PlatformInfo
.OutputDir
,
1254 "platform_dir" : MyAgo
.Macros
["PLATFORM_DIR"],
1256 "module_name" : MyAgo
.Name
,
1257 "module_guid" : MyAgo
.Guid
,
1258 "module_name_guid" : MyAgo
.UniqueBaseName
,
1259 "module_version" : MyAgo
.Version
,
1260 "module_type" : MyAgo
.ModuleType
,
1261 "module_file" : MyAgo
.MetaFile
,
1262 "module_file_base_name" : MyAgo
.MetaFile
.BaseName
,
1263 "module_relative_directory" : MyAgo
.SourceDir
,
1264 "module_dir" : mws
.join (MyAgo
.WorkspaceDir
, MyAgo
.SourceDir
),
1266 "architecture" : MyAgo
.Arch
,
1267 "toolchain_tag" : MyAgo
.ToolChain
,
1268 "build_target" : MyAgo
.BuildTarget
,
1270 "platform_build_directory" : self
.PlatformInfo
.BuildDir
,
1271 "module_build_directory" : MyAgo
.BuildDir
,
1272 "module_output_directory" : MyAgo
.OutputDir
,
1273 "module_debug_directory" : MyAgo
.DebugDir
,
1275 "separator" : Separator
,
1276 "module_tool_definitions" : ToolsDef
,
1278 "shell_command_code" : self
._SHELL
_CMD
_[self
._FileType
].keys(),
1279 "shell_command" : self
._SHELL
_CMD
_[self
._FileType
].values(),
1281 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1282 "custom_makefile_content" : CustomMakefile
1285 return MakefileTemplateDict
1287 ## PlatformMakefile class
1289 # This class encapsules makefie and its generation for platform. It uses
1290 # template to generate the content of makefile. The content of makefile will be
1291 # got from PlatformAutoGen object.
1293 class PlatformMakefile(BuildFile
):
1294 ## template used to generate the makefile for platform
1295 _TEMPLATE_
= TemplateString('''\
1299 # Platform Macro Definition
1301 PLATFORM_NAME = ${platform_name}
1302 PLATFORM_GUID = ${platform_guid}
1303 PLATFORM_VERSION = ${platform_version}
1304 PLATFORM_FILE = ${platform_file}
1305 PLATFORM_DIR = ${platform_dir}
1306 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1309 # Build Configuration Macro Definition
1311 TOOLCHAIN = ${toolchain_tag}
1312 TOOLCHAIN_TAG = ${toolchain_tag}
1313 TARGET = ${build_target}
1316 # Build Directory Macro Definition
1318 BUILD_DIR = ${platform_build_directory}
1319 FV_DIR = ${platform_build_directory}${separator}FV
1322 # Shell Command Macro
1324 ${BEGIN}${shell_command_code} = ${shell_command}
1328 MAKE_FILE = ${makefile_path}
1333 all: init build_libraries build_modules
1336 # Initialization target: print build information and create necessary directories
1339 \t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
1340 \t${BEGIN}-@${create_directory_command}
1343 # library build target
1345 libraries: init build_libraries
1348 # module build target
1350 modules: init build_libraries build_modules
1353 # Build all libraries:
1356 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
1357 ${END}\t@cd $(BUILD_DIR)
1360 # Build all modules:
1363 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
1364 ${END}\t@cd $(BUILD_DIR)
1367 # Clean intermediate files
1370 \t${BEGIN}-@${library_build_command} clean
1371 \t${END}${BEGIN}-@${module_build_command} clean
1372 \t${END}@cd $(BUILD_DIR)
1375 # Clean all generated files except to makefile
1378 ${BEGIN}\t${cleanall_command}
1382 # Clean all library files
1385 \t${BEGIN}-@${library_build_command} cleanall
1386 \t${END}@cd $(BUILD_DIR)\n
1389 ## Constructor of PlatformMakefile
1391 # @param ModuleAutoGen Object of PlatformAutoGen class
1393 def __init__(self
, PlatformAutoGen
):
1394 BuildFile
.__init
__(self
, PlatformAutoGen
)
1395 self
.ModuleBuildCommandList
= []
1396 self
.ModuleMakefileList
= []
1397 self
.IntermediateDirectoryList
= []
1398 self
.ModuleBuildDirectoryList
= []
1399 self
.LibraryBuildDirectoryList
= []
1400 self
.LibraryMakeCommandList
= []
1402 # Compose a dict object containing information used to do replacement in template
1404 def _TemplateDict(self
):
1405 Separator
= self
._SEP
_[self
._FileType
]
1407 MyAgo
= self
._AutoGenObject
1408 if "MAKE" not in MyAgo
.ToolDefinition
or "PATH" not in MyAgo
.ToolDefinition
["MAKE"]:
1409 EdkLogger
.error("build", OPTION_MISSING
, "No MAKE command defined. Please check your tools_def.txt!",
1410 ExtraData
="[%s]" % str(MyAgo
))
1412 self
.IntermediateDirectoryList
= ["$(BUILD_DIR)"]
1413 self
.ModuleBuildDirectoryList
= self
.GetModuleBuildDirectoryList()
1414 self
.LibraryBuildDirectoryList
= self
.GetLibraryBuildDirectoryList()
1416 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1417 LibraryMakefileList
= []
1418 LibraryMakeCommandList
= []
1419 for D
in self
.LibraryBuildDirectoryList
:
1420 D
= self
.PlaceMacro(D
, {"BUILD_DIR":MyAgo
.BuildDir
})
1421 Makefile
= os
.path
.join(D
, MakefileName
)
1422 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":Makefile
}
1423 LibraryMakefileList
.append(Makefile
)
1424 LibraryMakeCommandList
.append(Command
)
1425 self
.LibraryMakeCommandList
= LibraryMakeCommandList
1427 ModuleMakefileList
= []
1428 ModuleMakeCommandList
= []
1429 for D
in self
.ModuleBuildDirectoryList
:
1430 D
= self
.PlaceMacro(D
, {"BUILD_DIR":MyAgo
.BuildDir
})
1431 Makefile
= os
.path
.join(D
, MakefileName
)
1432 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":Makefile
}
1433 ModuleMakefileList
.append(Makefile
)
1434 ModuleMakeCommandList
.append(Command
)
1436 MakefileTemplateDict
= {
1437 "makefile_header" : self
._FILE
_HEADER
_[self
._FileType
],
1438 "makefile_path" : os
.path
.join("$(BUILD_DIR)", MakefileName
),
1439 "make_path" : MyAgo
.ToolDefinition
["MAKE"]["PATH"],
1440 "makefile_name" : MakefileName
,
1441 "platform_name" : MyAgo
.Name
,
1442 "platform_guid" : MyAgo
.Guid
,
1443 "platform_version" : MyAgo
.Version
,
1444 "platform_file" : MyAgo
.MetaFile
,
1445 "platform_relative_directory": MyAgo
.SourceDir
,
1446 "platform_output_directory" : MyAgo
.OutputDir
,
1447 "platform_build_directory" : MyAgo
.BuildDir
,
1448 "platform_dir" : MyAgo
.Macros
["PLATFORM_DIR"],
1450 "toolchain_tag" : MyAgo
.ToolChain
,
1451 "build_target" : MyAgo
.BuildTarget
,
1452 "shell_command_code" : self
._SHELL
_CMD
_[self
._FileType
].keys(),
1453 "shell_command" : self
._SHELL
_CMD
_[self
._FileType
].values(),
1454 "build_architecture_list" : MyAgo
.Arch
,
1455 "architecture" : MyAgo
.Arch
,
1456 "separator" : Separator
,
1457 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1458 "cleanall_command" : self
.GetRemoveDirectoryCommand(self
.IntermediateDirectoryList
),
1459 "library_makefile_list" : LibraryMakefileList
,
1460 "module_makefile_list" : ModuleMakefileList
,
1461 "library_build_command" : LibraryMakeCommandList
,
1462 "module_build_command" : ModuleMakeCommandList
,
1465 return MakefileTemplateDict
1467 ## Get the root directory list for intermediate files of all modules build
1469 # @retval list The list of directory
1471 def GetModuleBuildDirectoryList(self
):
1473 for ModuleAutoGen
in self
._AutoGenObject
.ModuleAutoGenList
:
1474 if not ModuleAutoGen
.IsBinaryModule
:
1475 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, ModuleAutoGen
.BuildDir
))
1478 ## Get the root directory list for intermediate files of all libraries build
1480 # @retval list The list of directory
1482 def GetLibraryBuildDirectoryList(self
):
1484 for LibraryAutoGen
in self
._AutoGenObject
.LibraryAutoGenList
:
1485 if not LibraryAutoGen
.IsBinaryModule
:
1486 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, LibraryAutoGen
.BuildDir
))
1489 ## TopLevelMakefile class
1491 # This class encapsules makefie and its generation for entrance makefile. It
1492 # uses template to generate the content of makefile. The content of makefile
1493 # will be got from WorkspaceAutoGen object.
1495 class TopLevelMakefile(BuildFile
):
1496 ## template used to generate toplevel makefile
1497 _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}''')
1499 ## Constructor of TopLevelMakefile
1501 # @param Workspace Object of WorkspaceAutoGen class
1503 def __init__(self
, Workspace
):
1504 BuildFile
.__init
__(self
, Workspace
)
1505 self
.IntermediateDirectoryList
= []
1507 # Compose a dict object containing information used to do replacement in template
1509 def _TemplateDict(self
):
1510 Separator
= self
._SEP
_[self
._FileType
]
1512 # any platform autogen object is ok because we just need common information
1513 MyAgo
= self
._AutoGenObject
1515 if "MAKE" not in MyAgo
.ToolDefinition
or "PATH" not in MyAgo
.ToolDefinition
["MAKE"]:
1516 EdkLogger
.error("build", OPTION_MISSING
, "No MAKE command defined. Please check your tools_def.txt!",
1517 ExtraData
="[%s]" % str(MyAgo
))
1519 for Arch
in MyAgo
.ArchList
:
1520 self
.IntermediateDirectoryList
.append(Separator
.join(["$(BUILD_DIR)", Arch
]))
1521 self
.IntermediateDirectoryList
.append("$(FV_DIR)")
1523 # TRICK: for not generating GenFds call in makefile if no FDF file
1525 if MyAgo
.FdfFile
is not None and MyAgo
.FdfFile
!= "":
1526 FdfFileList
= [MyAgo
.FdfFile
]
1527 # macros passed to GenFds
1529 MacroDict
.update(GlobalData
.gGlobalDefines
)
1530 MacroDict
.update(GlobalData
.gCommandLineDefines
)
1531 for MacroName
in MacroDict
:
1532 if MacroDict
[MacroName
] != "":
1533 MacroList
.append('"%s=%s"' % (MacroName
, MacroDict
[MacroName
].replace('\\', '\\\\')))
1535 MacroList
.append('"%s"' % MacroName
)
1539 # pass extra common options to external program called in makefile, currently GenFds.exe
1541 LogLevel
= EdkLogger
.GetLevel()
1542 if LogLevel
== EdkLogger
.VERBOSE
:
1543 ExtraOption
+= " -v"
1544 elif LogLevel
<= EdkLogger
.DEBUG_9
:
1545 ExtraOption
+= " -d %d" % (LogLevel
- 1)
1546 elif LogLevel
== EdkLogger
.QUIET
:
1547 ExtraOption
+= " -q"
1549 if GlobalData
.gCaseInsensitive
:
1550 ExtraOption
+= " -c"
1551 if GlobalData
.gEnableGenfdsMultiThread
:
1552 ExtraOption
+= " --genfds-multi-thread"
1553 if GlobalData
.gIgnoreSource
:
1554 ExtraOption
+= " --ignore-sources"
1556 for pcd
in GlobalData
.BuildOptionPcd
:
1558 pcdname
= '.'.join(pcd
[0:3])
1560 pcdname
= '.'.join(pcd
[0:2])
1561 if pcd
[3].startswith('{'):
1562 ExtraOption
+= " --pcd " + pcdname
+ '=' + 'H' + '"' + pcd
[3] + '"'
1564 ExtraOption
+= " --pcd " + pcdname
+ '=' + pcd
[3]
1566 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1567 SubBuildCommandList
= []
1568 for A
in MyAgo
.ArchList
:
1569 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":os
.path
.join("$(BUILD_DIR)", A
, MakefileName
)}
1570 SubBuildCommandList
.append(Command
)
1572 MakefileTemplateDict
= {
1573 "makefile_header" : self
._FILE
_HEADER
_[self
._FileType
],
1574 "makefile_path" : os
.path
.join("$(BUILD_DIR)", MakefileName
),
1575 "make_path" : MyAgo
.ToolDefinition
["MAKE"]["PATH"],
1576 "platform_name" : MyAgo
.Name
,
1577 "platform_guid" : MyAgo
.Guid
,
1578 "platform_version" : MyAgo
.Version
,
1579 "platform_build_directory" : MyAgo
.BuildDir
,
1580 "conf_directory" : GlobalData
.gConfDirectory
,
1582 "toolchain_tag" : MyAgo
.ToolChain
,
1583 "build_target" : MyAgo
.BuildTarget
,
1584 "shell_command_code" : self
._SHELL
_CMD
_[self
._FileType
].keys(),
1585 "shell_command" : self
._SHELL
_CMD
_[self
._FileType
].values(),
1586 'arch' : list(MyAgo
.ArchList
),
1587 "build_architecture_list" : ','.join(MyAgo
.ArchList
),
1588 "separator" : Separator
,
1589 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1590 "cleanall_command" : self
.GetRemoveDirectoryCommand(self
.IntermediateDirectoryList
),
1591 "sub_build_command" : SubBuildCommandList
,
1592 "fdf_file" : FdfFileList
,
1593 "active_platform" : str(MyAgo
),
1594 "fd" : MyAgo
.FdTargetList
,
1595 "fv" : MyAgo
.FvTargetList
,
1596 "cap" : MyAgo
.CapTargetList
,
1597 "extra_options" : ExtraOption
,
1598 "macro" : MacroList
,
1601 return MakefileTemplateDict
1603 ## Get the root directory list for intermediate files of all modules build
1605 # @retval list The list of directory
1607 def GetModuleBuildDirectoryList(self
):
1609 for ModuleAutoGen
in self
._AutoGenObject
.ModuleAutoGenList
:
1610 if not ModuleAutoGen
.IsBinaryModule
:
1611 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, ModuleAutoGen
.BuildDir
))
1614 ## Get the root directory list for intermediate files of all libraries build
1616 # @retval list The list of directory
1618 def GetLibraryBuildDirectoryList(self
):
1620 for LibraryAutoGen
in self
._AutoGenObject
.LibraryAutoGenList
:
1621 if not LibraryAutoGen
.IsBinaryModule
:
1622 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, LibraryAutoGen
.BuildDir
))
1625 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1626 if __name__
== '__main__':