2 # Create makefile for MS nmake and GNU make
4 # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 # SPDX-License-Identifier: BSD-2-Clause-Patent
10 from __future__
import absolute_import
11 import Common
.LongFilePathOs
as os
15 import os
.path
as path
16 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
17 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
18 from Common
.BuildToolError
import *
19 from Common
.Misc
import *
20 from Common
.StringUtils
import *
21 from .BuildEngine
import *
22 import Common
.GlobalData
as GlobalData
23 from collections
import OrderedDict
24 from Common
.DataType
import TAB_COMPILER_MSFT
26 ## Regular expression for finding header file inclusions
27 gIncludePattern
= re
.compile(r
"^[ \t]*[#%]?[ \t]*include(?:[ \t]*(?:\\(?:\r\n|\r|\n))*[ \t]*)*(?:\(?[\"<]?
[ \t]*)([-\w
.\\/() \t]+)(?
:[ \t]*[\">]?\
)?
)", re.MULTILINE | re.UNICODE | re.IGNORECASE)
29 ## Regular expression for matching macro used in header file inclusion
30 gMacroPattern = re.compile("([_A
-Z
][_A
-Z0
-9]*)[ \t]*\
((.+)\
)", re.UNICODE)
34 ## pattern for include style in Edk.x code
35 gProtocolDefinition = "Protocol
/%(HeaderKey)s/%(HeaderKey)s.h
"
36 gGuidDefinition = "Guid
/%(HeaderKey)s/%(HeaderKey)s.h
"
37 gArchProtocolDefinition = "ArchProtocol
/%(HeaderKey)s/%(HeaderKey)s.h
"
38 gPpiDefinition = "Ppi
/%(HeaderKey)s/%(HeaderKey)s.h
"
39 gIncludeMacroConversion = {
40 "EFI_PROTOCOL_DEFINITION
" : gProtocolDefinition,
41 "EFI_GUID_DEFINITION
" : gGuidDefinition,
42 "EFI_ARCH_PROTOCOL_DEFINITION
" : gArchProtocolDefinition,
43 "EFI_PROTOCOL_PRODUCER
" : gProtocolDefinition,
44 "EFI_PROTOCOL_CONSUMER
" : gProtocolDefinition,
45 "EFI_PROTOCOL_DEPENDENCY
" : gProtocolDefinition,
46 "EFI_ARCH_PROTOCOL_PRODUCER
" : gArchProtocolDefinition,
47 "EFI_ARCH_PROTOCOL_CONSUMER
" : gArchProtocolDefinition,
48 "EFI_ARCH_PROTOCOL_DEPENDENCY
" : gArchProtocolDefinition,
49 "EFI_PPI_DEFINITION
" : gPpiDefinition,
50 "EFI_PPI_PRODUCER
" : gPpiDefinition,
51 "EFI_PPI_CONSUMER
" : gPpiDefinition,
52 "EFI_PPI_DEPENDENCY
" : gPpiDefinition,
55 ## default makefile type
57 if sys.platform == "win32
":
65 # This base class encapsules build file and its generation. It uses template to generate
66 # the content of build file. The content of build file will be got from AutoGen objects.
68 class BuildFile(object):
69 ## template used to generate the build file (i.e. makefile if using make)
70 _TEMPLATE_ = TemplateString('')
72 _DEFAULT_FILE_NAME_ = "Makefile
"
74 ## default file name for each type of build file
77 "gmake
" : "GNUmakefile
"
80 ## Fixed header string for makefile
81 _MAKEFILE_HEADER = '''#
83 # This file is auto-generated by build utility
91 # Auto-generated makefile for building modules, libraries or platform
95 ## Header string for each type of build file
97 "nmake
" : _MAKEFILE_HEADER % _FILE_NAME_["nmake
"],
98 "gmake
" : _MAKEFILE_HEADER % _FILE_NAME_["gmake
"]
101 ## shell commands which can be used in build file in the form of macro
102 # $(CP) copy file command
103 # $(MV) move file command
104 # $(RM) remove file command
105 # $(MD) create dir command
106 # $(RD) remove dir command
114 "RD
" : "rmdir
/s
/q
",
126 ## directory separator
132 ## directory creation template
134 "nmake
" : 'if not exist %(dir)s $(MD) %(dir)s',
135 "gmake
" : "$
(MD
) %(dir)s"
138 ## directory removal template
140 "nmake
" : 'if exist %(dir)s $(RD) %(dir)s',
141 "gmake
" : "$
(RD
) %(dir)s"
145 "nmake
" : 'if exist %(Src)s $(CP) %(Src)s %(Dst)s',
146 "gmake
" : "test
-f
%(Src)s && $
(CP
) %(Src)s %(Dst)s"
150 "nmake
" : 'if exist %(dir)s cd %(dir)s',
151 "gmake
" : "test
-e
%(dir)s && cd
%(dir)s"
155 "nmake
" : 'if exist %(file)s "$
(MAKE
)" $(MAKE_FLAGS) -f %(file)s',
156 "gmake
" : 'test -e %(file)s && "$
(MAKE
)" $(MAKE_FLAGS) -f %(file)s'
160 "nmake
" : '!INCLUDE',
164 _INC_FLAG_ = {TAB_COMPILER_MSFT : "/I
", "GCC
" : "-I
", "INTEL
" : "-I
", "RVCT
" : "-I
", "NASM
" : "-I
"}
166 ## Constructor of BuildFile
168 # @param AutoGenObject Object of AutoGen class
170 def __init__(self, AutoGenObject):
171 self._AutoGenObject = AutoGenObject
172 self._FileType = gMakeType
176 # @param FileType Type of build file. Only nmake and gmake are supported now.
178 # @retval TRUE The build file is created or re-created successfully
179 # @retval FALSE The build file exists and is the same as the one to be generated
181 def Generate(self, FileType=gMakeType):
182 if FileType not in self._FILE_NAME_:
183 EdkLogger.error("build
", PARAMETER_INVALID, "Invalid build
type [%s]" % FileType,
184 ExtraData="[%s]" % str(self._AutoGenObject))
185 self._FileType = FileType
186 FileContent = self._TEMPLATE_.Replace(self._TemplateDict)
187 FileName = self._FILE_NAME_[FileType]
188 return SaveFileOnChange(os.path.join(self._AutoGenObject.MakeFileDir, FileName), FileContent, False)
190 ## Return a list of directory creation command string
192 # @param DirList The list of directory to be created
194 # @retval list The directory creation command list
196 def GetCreateDirectoryCommand(self, DirList):
197 return [self._MD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
199 ## Return a list of directory removal command string
201 # @param DirList The list of directory to be removed
203 # @retval list The directory removal command list
205 def GetRemoveDirectoryCommand(self, DirList):
206 return [self._RD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
208 def PlaceMacro(self, Path, MacroDefinitions={}):
209 if Path.startswith("$
("):
212 PathLength = len(Path)
213 for MacroName in MacroDefinitions:
214 MacroValue = MacroDefinitions[MacroName]
215 MacroValueLength = len(MacroValue)
216 if MacroValueLength == 0:
218 if MacroValueLength <= PathLength and Path.startswith(MacroValue):
219 Path = "$
(%s)%s" % (MacroName, Path[MacroValueLength:])
223 ## ModuleMakefile class
225 # This class encapsules makefie and its generation for module. It uses template to generate
226 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
228 class ModuleMakefile(BuildFile):
229 ## template used to generate the makefile for module
230 _TEMPLATE_ = TemplateString('''\
234 # Platform Macro Definition
236 PLATFORM_NAME = ${platform_name}
237 PLATFORM_GUID = ${platform_guid}
238 PLATFORM_VERSION = ${platform_version}
239 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
240 PLATFORM_DIR = ${platform_dir}
241 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
244 # Module Macro Definition
246 MODULE_NAME = ${module_name}
247 MODULE_GUID = ${module_guid}
248 MODULE_NAME_GUID = ${module_name_guid}
249 MODULE_VERSION = ${module_version}
250 MODULE_TYPE = ${module_type}
251 MODULE_FILE = ${module_file}
252 MODULE_FILE_BASE_NAME = ${module_file_base_name}
253 BASE_NAME = $(MODULE_NAME)
254 MODULE_RELATIVE_DIR = ${module_relative_directory}
255 PACKAGE_RELATIVE_DIR = ${package_relative_directory}
256 MODULE_DIR = ${module_dir}
257 FFS_OUTPUT_DIR = ${ffs_output_directory}
259 MODULE_ENTRY_POINT = ${module_entry_point}
260 ARCH_ENTRY_POINT = ${arch_entry_point}
261 IMAGE_ENTRY_POINT = ${image_entry_point}
263 ${BEGIN}${module_extra_defines}
266 # Build Configuration Macro Definition
268 ARCH = ${architecture}
269 TOOLCHAIN = ${toolchain_tag}
270 TOOLCHAIN_TAG = ${toolchain_tag}
271 TARGET = ${build_target}
274 # Build Directory Macro Definition
276 # PLATFORM_BUILD_DIR = ${platform_build_directory}
277 BUILD_DIR = ${platform_build_directory}
278 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
280 MODULE_BUILD_DIR = ${module_build_directory}
281 OUTPUT_DIR = ${module_output_directory}
282 DEBUG_DIR = ${module_debug_directory}
283 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
284 DEST_DIR_DEBUG = $(DEBUG_DIR)
287 # Shell Command Macro
289 ${BEGIN}${shell_command_code} = ${shell_command}
293 # Tools definitions specific to this module
295 ${BEGIN}${module_tool_definitions}
297 MAKE_FILE = ${makefile_path}
302 ${BEGIN}${file_macro}
305 COMMON_DEPS = ${BEGIN}${common_dependency_file} \\
309 # Overridable Target Macro Definitions
311 FORCE_REBUILD = force_build
314 BC_TARGET = ${BEGIN}${backward_compatible_target} ${END}
315 CODA_TARGET = ${BEGIN}${remaining_build_target} \\
319 # Default target, which will build dependent libraries in addition to source files
326 # Target used when called from platform makefile, which will bypass the build of dependent libraries
329 pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
335 mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET)
338 # Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets
341 tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
344 # Phony target which is used to force executing commands for a target
350 # Target to update the FD
356 # Initialization target: print build information and create necessary directories
361 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
364 ${BEGIN}\t-@${create_directory_command}\n${END}
367 \t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h
373 \t${BEGIN}@"$
(MAKE
)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name}
374 \t${END}@cd $(MODULE_BUILD_DIR)
377 # Build Flash Device Image
380 \t@"$
(MAKE
)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds
381 \t@cd $(MODULE_BUILD_DIR)
384 # Individual Object Build Targets
386 ${BEGIN}${file_build_target}
390 # clean all intermediate files
393 \t${BEGIN}${clean_command}
394 \t${END}\t$(RM) AutoGenTimeStamp
397 # clean all generated files
400 ${BEGIN}\t${cleanall_command}
401 ${END}\t$(RM) *.pdb *.idb > NUL 2>&1
402 \t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi
403 \t$(RM) AutoGenTimeStamp
406 # clean all dependent libraries built
409 \t${BEGIN}-@${library_build_command} cleanall
410 \t${END}@cd $(MODULE_BUILD_DIR)\n\n''')
412 _FILE_MACRO_TEMPLATE = TemplateString("${macro_name}
= ${BEGIN}
\\\n ${source_file}${END}
\n")
413 _BUILD_TARGET_TEMPLATE = TemplateString("${BEGIN}${target}
: ${deps}
\n${END}
\t${cmd}
\n")
415 ## Constructor of ModuleMakefile
417 # @param ModuleAutoGen Object of ModuleAutoGen class
419 def __init__(self, ModuleAutoGen):
420 BuildFile.__init__(self, ModuleAutoGen)
421 self.PlatformInfo = self._AutoGenObject.PlatformInfo
423 self.ResultFileList = []
424 self.IntermediateDirectoryList = ["$
(DEBUG_DIR
)", "$
(OUTPUT_DIR
)"]
426 self.FileBuildTargetList = [] # [(src, target string)]
427 self.BuildTargetList = [] # [target string]
428 self.PendingBuildTargetList = [] # [FileBuildRule objects]
429 self.CommonFileDependency = []
430 self.FileListMacros = {}
431 self.ListFileMacros = {}
432 self.ObjTargetDict = OrderedDict()
434 self.LibraryBuildCommandList = []
435 self.LibraryFileList = []
436 self.LibraryMakefileList = []
437 self.LibraryBuildDirectoryList = []
438 self.SystemLibraryList = []
439 self.Macros = OrderedDict()
440 self.Macros["OUTPUT_DIR
" ] = self._AutoGenObject.Macros["OUTPUT_DIR
"]
441 self.Macros["DEBUG_DIR
" ] = self._AutoGenObject.Macros["DEBUG_DIR
"]
442 self.Macros["MODULE_BUILD_DIR
"] = self._AutoGenObject.Macros["MODULE_BUILD_DIR
"]
443 self.Macros["BIN_DIR
" ] = self._AutoGenObject.Macros["BIN_DIR
"]
444 self.Macros["BUILD_DIR
" ] = self._AutoGenObject.Macros["BUILD_DIR
"]
445 self.Macros["WORKSPACE
" ] = self._AutoGenObject.Macros["WORKSPACE
"]
446 self.Macros["FFS_OUTPUT_DIR
" ] = self._AutoGenObject.Macros["FFS_OUTPUT_DIR
"]
447 self.GenFfsList = ModuleAutoGen.GenFfsList
448 self.MacroList = ['FFS_OUTPUT_DIR', 'MODULE_GUID', 'OUTPUT_DIR']
449 self.FfsOutputFileList = []
451 # Compose a dict object containing information used to do replacement in template
453 def _TemplateDict(self):
454 if self._FileType not in self._SEP_:
455 EdkLogger.error("build
", PARAMETER_INVALID, "Invalid Makefile
type [%s]" % self._FileType,
456 ExtraData="[%s]" % str(self._AutoGenObject))
457 MyAgo = self._AutoGenObject
458 Separator = self._SEP_[self._FileType]
460 # break build if no source files and binary files are found
461 if len(MyAgo.SourceFileList) == 0 and len(MyAgo.BinaryFileList) == 0:
462 EdkLogger.error("build
", AUTOGEN_ERROR, "No files to be built
in module
[%s, %s, %s]"
463 % (MyAgo.BuildTarget, MyAgo.ToolChain, MyAgo.Arch),
464 ExtraData="[%s]" % str(MyAgo))
466 # convert dependent libraries to build command
467 self.ProcessDependentLibrary()
468 if len(MyAgo.Module.ModuleEntryPointList) > 0:
469 ModuleEntryPoint = MyAgo.Module.ModuleEntryPointList[0]
471 ModuleEntryPoint = "_ModuleEntryPoint
"
473 ArchEntryPoint = ModuleEntryPoint
475 if MyAgo.Arch == "EBC
":
476 # EBC compiler always use "EfiStart
" as entry point. Only applies to EdkII modules
477 ImageEntryPoint = "EfiStart
"
479 # EdkII modules always use "_ModuleEntryPoint
" as entry point
480 ImageEntryPoint = "_ModuleEntryPoint
"
482 for k, v in MyAgo.Module.Defines.items():
483 if k not in MyAgo.Macros:
486 if 'MODULE_ENTRY_POINT' not in MyAgo.Macros:
487 MyAgo.Macros['MODULE_ENTRY_POINT'] = ModuleEntryPoint
488 if 'ARCH_ENTRY_POINT' not in MyAgo.Macros:
489 MyAgo.Macros['ARCH_ENTRY_POINT'] = ArchEntryPoint
490 if 'IMAGE_ENTRY_POINT' not in MyAgo.Macros:
491 MyAgo.Macros['IMAGE_ENTRY_POINT'] = ImageEntryPoint
493 PCI_COMPRESS_Flag = False
494 for k, v in MyAgo.Module.Defines.items():
495 if 'PCI_COMPRESS' == k and 'TRUE' == v:
496 PCI_COMPRESS_Flag = True
500 IncPrefix = self._INC_FLAG_[MyAgo.ToolChainFamily]
501 for Tool in MyAgo.BuildOption:
502 for Attr in MyAgo.BuildOption[Tool]:
503 Value = MyAgo.BuildOption[Tool][Attr]
507 ToolsDef.append("%s = %s" % (Tool, Value))
509 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
512 # Remove duplicated include path, if any
514 Value = RemoveDupOption(Value, IncPrefix, MyAgo.IncludePathList)
515 if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and Tool == 'CC' and '/GM' in Value:
516 Value = Value.replace(' /MP', '')
517 MyAgo.BuildOption[Tool][Attr] = Value
518 if Tool == "OPTROM
" and PCI_COMPRESS_Flag:
519 ValueList = Value.split()
521 for i, v in enumerate(ValueList):
524 Value = ' '.join(ValueList)
526 ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
529 # generate the Response file and Response flag
530 RespDict = self.CommandExceedLimit()
531 RespFileList = os.path.join(MyAgo.OutputDir, 'respfilelist.txt')
533 RespFileListContent = ''
534 for Resp in RespDict:
535 RespFile = os.path.join(MyAgo.OutputDir, str(Resp).lower() + '.txt')
536 StrList = RespDict[Resp].split(' ')
541 UnexpandMacro.append(Str)
544 UnexpandMacroStr = ' '.join(UnexpandMacro)
545 NewRespStr = ' '.join(NewStr)
546 SaveFileOnChange(RespFile, NewRespStr, False)
547 ToolsDef.append("%s = %s" % (Resp, UnexpandMacroStr + ' @' + RespFile))
548 RespFileListContent += '@' + RespFile + TAB_LINE_BREAK
549 RespFileListContent += NewRespStr + TAB_LINE_BREAK
550 SaveFileOnChange(RespFileList, RespFileListContent, False)
552 if os.path.exists(RespFileList):
553 os.remove(RespFileList)
555 # convert source files and binary files to build targets
556 self.ResultFileList = [str(T.Target) for T in MyAgo.CodaTargetList]
557 if len(self.ResultFileList) == 0 and len(MyAgo.SourceFileList) != 0:
558 EdkLogger.error("build
", AUTOGEN_ERROR, "Nothing to build
",
559 ExtraData="[%s]" % str(MyAgo))
561 self.ProcessBuildTargetList()
562 self.ParserGenerateFfsCmd()
564 # Generate macros used to represent input files
565 FileMacroList = [] # macro name = file list
566 for FileListMacro in self.FileListMacros:
567 FileMacro = self._FILE_MACRO_TEMPLATE.Replace(
569 "macro_name
" : FileListMacro,
570 "source_file
" : self.FileListMacros[FileListMacro]
573 FileMacroList.append(FileMacro)
575 # INC_LIST is special
578 for P in MyAgo.IncludePathList:
579 IncludePathList.append(IncPrefix + self.PlaceMacro(P, self.Macros))
580 if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:
581 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix + P)
582 FileMacro += self._FILE_MACRO_TEMPLATE.Replace(
584 "macro_name
" : "INC
",
585 "source_file
" : IncludePathList
588 FileMacroList.append(FileMacro)
589 # Add support when compiling .nasm source files
590 for File in self.FileCache.keys():
591 if not str(File).endswith('.nasm'):
594 for P in MyAgo.IncludePathList:
595 IncludePath = self._INC_FLAG_['NASM'] + self.PlaceMacro(P, self.Macros)
596 if IncludePath.endswith(os.sep):
597 IncludePath = IncludePath.rstrip(os.sep)
598 # When compiling .nasm files, need to add a literal backslash at each path
599 # To specify a literal backslash at the end of the line, precede it with a caret (^)
600 if P == MyAgo.IncludePathList[-1] and os.sep == '\\':
601 IncludePath = ''.join([IncludePath, '^', os.sep])
603 IncludePath = os.path.join(IncludePath, '')
604 IncludePathList.append(IncludePath)
605 FileMacroList.append(self._FILE_MACRO_TEMPLATE.Replace({"macro_name
": "NASM_INC
", "source_file
": IncludePathList}))
608 # Generate macros used to represent files containing list of input files
609 for ListFileMacro in self.ListFileMacros:
610 ListFileName = os.path.join(MyAgo.OutputDir, "%s.lst
" % ListFileMacro.lower()[:len(ListFileMacro) - 5])
611 FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))
614 "\n".join(self.ListFileMacros[ListFileMacro]),
618 # Generate objlist used to create .obj file
619 for Type in self.ObjTargetDict:
620 NewLine = ' '.join(list(self.ObjTargetDict[Type]))
621 FileMacroList.append("OBJLIST_
%s = %s" % (list(self.ObjTargetDict.keys()).index(Type), NewLine))
625 MakefileName = self._FILE_NAME_[self._FileType]
626 LibraryMakeCommandList = []
627 for D in self.LibraryBuildDirectoryList:
628 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)}
629 LibraryMakeCommandList.append(Command)
631 package_rel_dir = MyAgo.SourceDir
632 current_dir = self.Macros["WORKSPACE
"]
634 while not found and os.sep in package_rel_dir:
635 index = package_rel_dir.index(os.sep)
636 current_dir = mws.join(current_dir, package_rel_dir[:index])
637 if os.path.exists(current_dir):
638 for fl in os.listdir(current_dir):
639 if fl.endswith('.dec'):
642 package_rel_dir = package_rel_dir[index + 1:]
644 MakefileTemplateDict = {
645 "makefile_header
" : self._FILE_HEADER_[self._FileType],
646 "makefile_path
" : os.path.join("$
(MODULE_BUILD_DIR
)", MakefileName),
647 "makefile_name
" : MakefileName,
648 "platform_name
" : self.PlatformInfo.Name,
649 "platform_guid
" : self.PlatformInfo.Guid,
650 "platform_version
" : self.PlatformInfo.Version,
651 "platform_relative_directory
": self.PlatformInfo.SourceDir,
652 "platform_output_directory
" : self.PlatformInfo.OutputDir,
653 "ffs_output_directory
" : MyAgo.Macros["FFS_OUTPUT_DIR
"],
654 "platform_dir
" : MyAgo.Macros["PLATFORM_DIR
"],
656 "module_name
" : MyAgo.Name,
657 "module_guid
" : MyAgo.Guid,
658 "module_name_guid
" : MyAgo.UniqueBaseName,
659 "module_version
" : MyAgo.Version,
660 "module_type
" : MyAgo.ModuleType,
661 "module_file
" : MyAgo.MetaFile.Name,
662 "module_file_base_name
" : MyAgo.MetaFile.BaseName,
663 "module_relative_directory
" : MyAgo.SourceDir,
664 "module_dir
" : mws.join (self.Macros["WORKSPACE
"], MyAgo.SourceDir),
665 "package_relative_directory
": package_rel_dir,
666 "module_extra_defines
" : ["%s = %s" % (k, v) for k, v in MyAgo.Module.Defines.items()],
668 "architecture
" : MyAgo.Arch,
669 "toolchain_tag
" : MyAgo.ToolChain,
670 "build_target
" : MyAgo.BuildTarget,
672 "platform_build_directory
" : self.PlatformInfo.BuildDir,
673 "module_build_directory
" : MyAgo.BuildDir,
674 "module_output_directory
" : MyAgo.OutputDir,
675 "module_debug_directory
" : MyAgo.DebugDir,
677 "separator
" : Separator,
678 "module_tool_definitions
" : ToolsDef,
680 "shell_command_code
" : list(self._SHELL_CMD_[self._FileType].keys()),
681 "shell_command
" : list(self._SHELL_CMD_[self._FileType].values()),
683 "module_entry_point
" : ModuleEntryPoint,
684 "image_entry_point
" : ImageEntryPoint,
685 "arch_entry_point
" : ArchEntryPoint,
686 "remaining_build_target
" : self.ResultFileList,
687 "common_dependency_file
" : self.CommonFileDependency,
688 "create_directory_command
" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
689 "clean_command
" : self.GetRemoveDirectoryCommand(["$
(OUTPUT_DIR
)"]),
690 "cleanall_command
" : self.GetRemoveDirectoryCommand(["$
(DEBUG_DIR
)", "$
(OUTPUT_DIR
)"]),
691 "dependent_library_build_directory
" : self.LibraryBuildDirectoryList,
692 "library_build_command
" : LibraryMakeCommandList,
693 "file_macro
" : FileMacroList,
694 "file_build_target
" : self.BuildTargetList,
695 "backward_compatible_target
": BcTargetList,
698 return MakefileTemplateDict
700 def ParserGenerateFfsCmd(self):
701 #Add Ffs cmd to self.BuildTargetList
705 for Cmd in self.GenFfsList:
707 for CopyCmd in Cmd[2]:
709 Src = self.ReplaceMacro(Src)
710 Dst = self.ReplaceMacro(Dst)
711 if Dst not in self.ResultFileList:
712 self.ResultFileList.append(Dst)
713 if '%s :' %(Dst) not in self.BuildTargetList:
714 self.BuildTargetList.append("%s :" %(Dst))
715 self.BuildTargetList.append('\t' + self._CP_TEMPLATE_[self._FileType] %{'Src': Src, 'Dst': Dst})
718 for index, Str in enumerate(FfsCmdList):
720 OutputFile = FfsCmdList[index + 1]
721 if '-i' == Str or "-oi
" == Str:
722 if DepsFileList == []:
723 DepsFileList = [FfsCmdList[index + 1]]
725 DepsFileList.append(FfsCmdList[index + 1])
726 DepsFileString = ' '.join(DepsFileList).strip()
727 if DepsFileString == '':
729 OutputFile = self.ReplaceMacro(OutputFile)
730 self.ResultFileList.append(OutputFile)
731 DepsFileString = self.ReplaceMacro(DepsFileString)
732 self.BuildTargetList.append('%s : %s' % (OutputFile, DepsFileString))
733 CmdString = ' '.join(FfsCmdList).strip()
734 CmdString = self.ReplaceMacro(CmdString)
735 self.BuildTargetList.append('\t%s' % CmdString)
737 self.ParseSecCmd(DepsFileList, Cmd[1])
738 for SecOutputFile, SecDepsFile, SecCmd in self.FfsOutputFileList :
739 self.BuildTargetList.append('%s : %s' % (self.ReplaceMacro(SecOutputFile), self.ReplaceMacro(SecDepsFile)))
740 self.BuildTargetList.append('\t%s' % self.ReplaceMacro(SecCmd))
741 self.FfsOutputFileList = []
743 def ParseSecCmd(self, OutputFileList, CmdTuple):
744 for OutputFile in OutputFileList:
745 for SecCmdStr in CmdTuple:
747 SecCmdList = SecCmdStr.split()
748 CmdName = SecCmdList[0]
749 for index, CmdItem in enumerate(SecCmdList):
750 if '-o' == CmdItem and OutputFile == SecCmdList[index + 1]:
752 while index + 1 < len(SecCmdList):
753 if not SecCmdList[index+1].startswith('-'):
754 SecDepsFileList.append(SecCmdList[index + 1])
756 if CmdName == 'Trim':
757 SecDepsFileList.append(os.path.join('$(DEBUG_DIR)', os.path.basename(OutputFile).replace('offset', 'efi')))
758 if OutputFile.endswith('.ui') or OutputFile.endswith('.ver'):
759 SecDepsFileList.append(os.path.join('$(MODULE_DIR)', '$(MODULE_FILE)'))
760 self.FfsOutputFileList.append((OutputFile, ' '.join(SecDepsFileList), SecCmdStr))
761 if len(SecDepsFileList) > 0:
762 self.ParseSecCmd(SecDepsFileList, CmdTuple)
767 def ReplaceMacro(self, str):
768 for Macro in self.MacroList:
769 if self._AutoGenObject.Macros[Macro] and self._AutoGenObject.Macros[Macro] in str:
770 str = str.replace(self._AutoGenObject.Macros[Macro], '$(' + Macro + ')')
773 def CommandExceedLimit(self):
775 'CC' : { 'Macro' : '$(CC_FLAGS)', 'Value' : False},
776 'PP' : { 'Macro' : '$(PP_FLAGS)', 'Value' : False},
777 'APP' : { 'Macro' : '$(APP_FLAGS)', 'Value' : False},
778 'ASLPP' : { 'Macro' : '$(ASLPP_FLAGS)', 'Value' : False},
779 'VFRPP' : { 'Macro' : '$(VFRPP_FLAGS)', 'Value' : False},
780 'ASM' : { 'Macro' : '$(ASM_FLAGS)', 'Value' : False},
781 'ASLCC' : { 'Macro' : '$(ASLCC_FLAGS)', 'Value' : False},
786 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
788 # base on the source files to decide the file type
789 for File in self._AutoGenObject.SourceFileList:
790 for type in self._AutoGenObject.FileTypes:
791 if File in self._AutoGenObject.FileTypes[type]:
792 if type not in FileTypeList:
793 FileTypeList.append(type)
795 # calculate the command-line length
797 for type in FileTypeList:
798 BuildTargets = self._AutoGenObject.BuildRules[type].BuildTargets
799 for Target in BuildTargets:
800 CommandList = BuildTargets[Target].Commands
801 for SingleCommand in CommandList:
803 SingleCommandLength = len(SingleCommand)
804 SingleCommandList = SingleCommand.split()
805 if len(SingleCommandList) > 0:
806 for Flag in FlagDict:
807 if '$('+ Flag +')' in SingleCommandList[0]:
811 if 'PATH' not in self._AutoGenObject.BuildOption[Tool]:
812 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))
813 SingleCommandLength += len(self._AutoGenObject.BuildOption[Tool]['PATH
'])
814 for item in SingleCommandList[1:]:
815 if FlagDict[Tool]['Macro
'] in item:
816 if 'FLAGS
' not in self._AutoGenObject.BuildOption[Tool]:
817 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))
818 Str = self._AutoGenObject.BuildOption[Tool]['FLAGS']
819 for Option in self._AutoGenObject.BuildOption:
820 for Attr in self._AutoGenObject.BuildOption[Option]:
821 if Str.find(Option + '_' + Attr) != -1:
822 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
823 while(Str.find('$(') != -1):
824 for macro in self._AutoGenObject.Macros:
825 MacroName = '$('+ macro + ')'
826 if (Str.find(MacroName) != -1):
827 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
831 SingleCommandLength += len(Str)
832 elif '$(INC)' in item:
833 SingleCommandLength += self._AutoGenObject.IncludePathLength + len(IncPrefix) * len(self._AutoGenObject.IncludePathList)
834 elif item.find('$(') != -1:
836 for Option in self._AutoGenObject.BuildOption:
837 for Attr in self._AutoGenObject.BuildOption[Option]:
838 if Str.find(Option + '_' + Attr) != -1:
839 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
840 while(Str.find('$(') != -1):
841 for macro in self._AutoGenObject.Macros:
842 MacroName = '$('+ macro + ')'
843 if (Str.find(MacroName) != -1):
844 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
848 SingleCommandLength += len(Str)
850 if SingleCommandLength > GlobalData.gCommandMaxLength:
851 FlagDict[Tool]['Value'] = True
853 # generate the response file content by combine the FLAGS and INC
854 for Flag in FlagDict:
855 if FlagDict[Flag]['Value']:
857 RespMacro = FlagDict[Flag]['Macro'].replace('FLAGS', 'RESP')
858 Value = self._AutoGenObject.BuildOption[Flag]['FLAGS']
859 for inc in self._AutoGenObject.IncludePathList:
860 Value += ' ' + IncPrefix + inc
861 for Option in self._AutoGenObject.BuildOption:
862 for Attr in self._AutoGenObject.BuildOption[Option]:
863 if Value.find(Option + '_' + Attr) != -1:
864 Value = Value.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
865 while (Value.find('$(') != -1):
866 for macro in self._AutoGenObject.Macros:
867 MacroName = '$('+ macro + ')'
868 if (Value.find(MacroName) != -1):
869 Value = Value.replace(MacroName, self._AutoGenObject.Macros[macro])
874 if self._AutoGenObject.ToolChainFamily == 'GCC':
875 RespDict[Key] = Value.replace('\\', '/')
877 RespDict[Key] = Value
878 for Target in BuildTargets:
879 for i, SingleCommand in enumerate(BuildTargets[Target].Commands):
880 if FlagDict[Flag]['Macro'] in SingleCommand:
881 BuildTargets[Target].Commands[i] = SingleCommand.replace('$(INC)', '').replace(FlagDict[Flag]['Macro'], RespMacro)
884 def ProcessBuildTargetList(self):
886 # Search dependency file list for each source file
888 ForceIncludedFile = []
889 for File in self._AutoGenObject.AutoGenFileList:
891 ForceIncludedFile.append(File)
894 for Target in self._AutoGenObject.IntroTargetList:
895 SourceFileList.extend(Target.Inputs)
896 OutPutFileList.extend(Target.Outputs)
899 for Item in OutPutFileList:
900 if Item in SourceFileList:
901 SourceFileList.remove(Item)
903 FileDependencyDict = self.GetFileDependency(
906 self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList
909 # Get a set of unique package includes from MetaFile
910 parentMetaFileIncludes = set()
911 for aInclude in self._AutoGenObject.PackageIncludePathList:
912 aIncludeName = str(aInclude)
913 parentMetaFileIncludes.add(aIncludeName.lower())
915 # Check if header files are listed in metafile
916 # Get a set of unique module header source files from MetaFile
917 headerFilesInMetaFileSet = set()
918 for aFile in self._AutoGenObject.SourceFileList:
919 aFileName = str(aFile)
920 if not aFileName.endswith('.h'):
922 headerFilesInMetaFileSet.add(aFileName.lower())
924 # Get a set of unique module autogen files
925 localAutoGenFileSet = set()
926 for aFile in self._AutoGenObject.AutoGenFileList:
927 localAutoGenFileSet.add(str(aFile).lower())
929 # Get a set of unique module dependency header files
930 # Exclude autogen files and files not in the source directory
931 # and files that are under the package include list
932 headerFileDependencySet = set()
933 localSourceDir = str(self._AutoGenObject.SourceDir).lower()
934 for Dependency in FileDependencyDict.values():
935 for aFile in Dependency:
936 aFileName = str(aFile).lower()
937 # Exclude non-header files
938 if not aFileName.endswith('.h'):
940 # Exclude autogen files
941 if aFileName in localAutoGenFileSet:
943 # Exclude include out of local scope
944 if localSourceDir not in aFileName:
946 # Exclude files covered by package includes
948 for aIncludePath in parentMetaFileIncludes:
949 if aIncludePath in aFileName:
954 # Keep the file to be checked
955 headerFileDependencySet.add(aFileName)
957 # Ensure that gModuleBuildTracking has been initialized per architecture
958 if self._AutoGenObject.Arch not in GlobalData.gModuleBuildTracking:
959 GlobalData.gModuleBuildTracking[self._AutoGenObject.Arch] = dict()
961 # Check if a module dependency header file is missing from the module's MetaFile
962 for aFile in headerFileDependencySet:
963 if aFile in headerFilesInMetaFileSet:
965 if GlobalData.gUseHashCache:
966 GlobalData.gModuleBuildTracking[self._AutoGenObject.Arch][self._AutoGenObject] = 'FAIL_METAFILE'
967 EdkLogger.warn("build
","Module MetaFile
[Sources
] is missing local header
!",
968 ExtraData = "Local Header
: " + aFile + " not found
in " + self._AutoGenObject.MetaFile.Path
972 for File,Dependency in FileDependencyDict.items():
974 FileDependencyDict[File] = ['$(FORCE_REBUILD)']
977 self._AutoGenObject.AutoGenDepSet |= set(Dependency)
980 if File.Ext not in [".c
", ".C
"] or File.Name == "AutoGen
.c
":
983 DepSet = set(Dependency)
985 DepSet &= set(Dependency)
986 # in case nothing in SourceFileList
990 # Extract common files list in the dependency files
993 self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros))
998 DependencyDict = FileDependencyDict.copy()
999 for File in FileDependencyDict:
1001 if File.Ext not in [".c
", ".C
"] or File.Name == "AutoGen
.c
":
1003 NewDepSet = set(FileDependencyDict[File])
1005 FileDependencyDict[File] = ["$
(COMMON_DEPS
)"] + list(NewDepSet)
1006 DependencyDict[File] = list(NewDepSet)
1008 # Convert target description object to target string in makefile
1009 if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and TAB_C_CODE_FILE in self._AutoGenObject.Targets:
1010 for T in self._AutoGenObject.Targets[TAB_C_CODE_FILE]:
1011 NewFile = self.PlaceMacro(str(T), self.Macros)
1012 if not self.ObjTargetDict.get(T.Target.SubDir):
1013 self.ObjTargetDict[T.Target.SubDir] = set()
1014 self.ObjTargetDict[T.Target.SubDir].add(NewFile)
1015 for Type in self._AutoGenObject.Targets:
1016 for T in self._AutoGenObject.Targets[Type]:
1017 # Generate related macros if needed
1018 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
1019 self.FileListMacros[T.FileListMacro] = []
1020 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:
1021 self.ListFileMacros[T.ListFileMacro] = []
1022 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:
1023 self.ListFileMacros[T.IncListFileMacro] = []
1027 # Add force-dependencies
1028 for Dep in T.Dependencies:
1029 Deps.append(self.PlaceMacro(str(Dep), self.Macros))
1030 if Dep != '$(MAKE_FILE)':
1031 CCodeDeps.append(self.PlaceMacro(str(Dep), self.Macros))
1032 # Add inclusion-dependencies
1033 if len(T.Inputs) == 1 and T.Inputs[0] in FileDependencyDict:
1034 for F in FileDependencyDict[T.Inputs[0]]:
1035 Deps.append(self.PlaceMacro(str(F), self.Macros))
1036 # Add source-dependencies
1038 NewFile = self.PlaceMacro(str(F), self.Macros)
1039 # In order to use file list macro as dependency
1041 # gnu tools need forward slash path separator, even on Windows
1042 self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/'))
1043 self.FileListMacros[T.FileListMacro].append(NewFile)
1044 elif T.GenFileListMacro:
1045 self.FileListMacros[T.FileListMacro].append(NewFile)
1047 Deps.append(NewFile)
1048 for key in self.FileListMacros:
1049 self.FileListMacros[key].sort()
1050 # Use file list macro as dependency
1051 if T.GenFileListMacro:
1052 Deps.append("$
(%s)" % T.FileListMacro)
1053 if Type in [TAB_OBJECT_FILE, TAB_STATIC_LIBRARY]:
1054 Deps.append("$
(%s)" % T.ListFileMacro)
1056 if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and Type == TAB_C_CODE_FILE:
1057 T, CmdTarget, CmdTargetDict, CmdCppDict = self.ParserCCodeFile(T, Type, CmdSumDict, CmdTargetDict, CmdCppDict, DependencyDict)
1058 TargetDict = {"target
": self.PlaceMacro(T.Target.Path, self.Macros), "cmd
": "\n\t".join(T.Commands),"deps
": CCodeDeps}
1059 CmdLine = self._BUILD_TARGET_TEMPLATE.Replace(TargetDict).rstrip().replace('\t$(OBJLIST', '$(OBJLIST')
1061 CmdLine = '%s%s' %(CmdLine, TAB_LINE_BREAK)
1062 if CCodeDeps or CmdLine:
1063 self.BuildTargetList.append(CmdLine)
1065 TargetDict = {"target
": self.PlaceMacro(T.Target.Path, self.Macros), "cmd
": "\n\t".join(T.Commands),"deps
": Deps}
1066 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
1068 def ParserCCodeFile(self, T, Type, CmdSumDict, CmdTargetDict, CmdCppDict, DependencyDict):
1070 for item in self._AutoGenObject.Targets[Type]:
1071 CmdSumDict[item.Target.SubDir] = item.Target.BaseName
1072 for CppPath in item.Inputs:
1073 Path = self.PlaceMacro(CppPath.Path, self.Macros)
1074 if CmdCppDict.get(item.Target.SubDir):
1075 CmdCppDict[item.Target.SubDir].append(Path)
1077 CmdCppDict[item.Target.SubDir] = ['$(MAKE_FILE)', Path]
1078 if CppPath.Path in DependencyDict:
1079 for Temp in DependencyDict[CppPath.Path]:
1081 Path = self.PlaceMacro(Temp.Path, self.Macros)
1084 if Path not in (self.CommonFileDependency + CmdCppDict[item.Target.SubDir]):
1085 CmdCppDict[item.Target.SubDir].append(Path)
1087 CommandList = T.Commands[:]
1088 for Item in CommandList[:]:
1089 SingleCommandList = Item.split()
1090 if len(SingleCommandList) > 0 and self.CheckCCCmd(SingleCommandList):
1091 for Temp in SingleCommandList:
1092 if Temp.startswith('/Fo'):
1093 CmdSign = '%s%s' % (Temp.rsplit(TAB_SLASH, 1)[0], TAB_SLASH)
1096 if CmdSign not in list(CmdTargetDict.keys()):
1097 CmdTargetDict[CmdSign] = Item.replace(Temp, CmdSign)
1099 CmdTargetDict[CmdSign] = "%s %s" % (CmdTargetDict[CmdSign], SingleCommandList[-1])
1100 Index = CommandList.index(Item)
1101 CommandList.pop(Index)
1102 if SingleCommandList[-1].endswith("%s%s.c
" % (TAB_SLASH, CmdSumDict[CmdSign[3:].rsplit(TAB_SLASH, 1)[0]])):
1103 Cpplist = CmdCppDict[T.Target.SubDir]
1104 Cpplist.insert(0, '$(OBJLIST_%d): $(COMMON_DEPS)' % list(self.ObjTargetDict.keys()).index(T.Target.SubDir))
1105 T.Commands[Index] = '%s\n\t%s' % (' \\\n\t'.join(Cpplist), CmdTargetDict[CmdSign])
1107 T.Commands.pop(Index)
1108 return T, CmdSumDict, CmdTargetDict, CmdCppDict
1110 def CheckCCCmd(self, CommandList):
1111 for cmd in CommandList:
1115 ## For creating makefile targets for dependent libraries
1116 def ProcessDependentLibrary(self):
1117 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1118 if not LibraryAutoGen.IsBinaryModule and not LibraryAutoGen.CanSkipbyHash():
1119 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
1121 ## Return a list containing source file's dependencies
1123 # @param FileList The list of source files
1124 # @param ForceInculeList The list of files which will be included forcely
1125 # @param SearchPathList The list of search path
1127 # @retval dict The mapping between source file path and its dependencies
1129 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
1132 Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)
1135 ## Find dependencies for one source file
1137 # By searching recursively "#include" directive in file, find out all the
1138 # files needed by given source file. The dependencies will be only searched
1139 # in given search path list.
1141 # @param File The source file
1142 # @param ForceInculeList The list of files which will be included forcely
1143 # @param SearchPathList The list of search path
1145 # @retval list The list of files the given source file depends on
1147 def GetDependencyList(self
, File
, ForceList
, SearchPathList
):
1148 EdkLogger
.debug(EdkLogger
.DEBUG_1
, "Try to get dependency files for %s" % File
)
1149 FileStack
= [File
] + ForceList
1150 DependencySet
= set()
1152 if self
._AutoGenObject
.Arch
not in gDependencyDatabase
:
1153 gDependencyDatabase
[self
._AutoGenObject
.Arch
] = {}
1154 DepDb
= gDependencyDatabase
[self
._AutoGenObject
.Arch
]
1156 while len(FileStack
) > 0:
1159 FullPathDependList
= []
1160 if F
in self
.FileCache
:
1161 for CacheFile
in self
.FileCache
[F
]:
1162 FullPathDependList
.append(CacheFile
)
1163 if CacheFile
not in DependencySet
:
1164 FileStack
.append(CacheFile
)
1165 DependencySet
.update(FullPathDependList
)
1168 CurrentFileDependencyList
= []
1170 CurrentFileDependencyList
= DepDb
[F
]
1173 Fd
= open(F
.Path
, 'rb')
1174 FileContent
= Fd
.read()
1176 except BaseException
as X
:
1177 EdkLogger
.error("build", FILE_OPEN_FAILURE
, ExtraData
=F
.Path
+ "\n\t" + str(X
))
1178 if len(FileContent
) == 0:
1181 if FileContent
[0] == 0xff or FileContent
[0] == 0xfe:
1182 FileContent
= FileContent
.decode('utf-16')
1184 FileContent
= FileContent
.decode()
1186 # The file is not txt file. for example .mcb file
1188 IncludedFileList
= gIncludePattern
.findall(FileContent
)
1190 for Inc
in IncludedFileList
:
1192 # if there's macro used to reference header file, expand it
1193 HeaderList
= gMacroPattern
.findall(Inc
)
1194 if len(HeaderList
) == 1 and len(HeaderList
[0]) == 2:
1195 HeaderType
= HeaderList
[0][0]
1196 HeaderKey
= HeaderList
[0][1]
1197 if HeaderType
in gIncludeMacroConversion
:
1198 Inc
= gIncludeMacroConversion
[HeaderType
] % {"HeaderKey" : HeaderKey
}
1200 # not known macro used in #include, always build the file by
1201 # returning a empty dependency
1202 self
.FileCache
[File
] = []
1204 Inc
= os
.path
.normpath(Inc
)
1205 CurrentFileDependencyList
.append(Inc
)
1206 DepDb
[F
] = CurrentFileDependencyList
1208 CurrentFilePath
= F
.Dir
1209 PathList
= [CurrentFilePath
] + SearchPathList
1210 for Inc
in CurrentFileDependencyList
:
1211 for SearchPath
in PathList
:
1212 FilePath
= os
.path
.join(SearchPath
, Inc
)
1213 if FilePath
in gIsFileMap
:
1214 if not gIsFileMap
[FilePath
]:
1216 # If isfile is called too many times, the performance is slow down.
1217 elif not os
.path
.isfile(FilePath
):
1218 gIsFileMap
[FilePath
] = False
1221 gIsFileMap
[FilePath
] = True
1222 FilePath
= PathClass(FilePath
)
1223 FullPathDependList
.append(FilePath
)
1224 if FilePath
not in DependencySet
:
1225 FileStack
.append(FilePath
)
1228 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "%s included by %s was not found "\
1229 "in any given path:\n\t%s" % (Inc
, F
, "\n\t".join(SearchPathList
)))
1231 self
.FileCache
[F
] = FullPathDependList
1232 DependencySet
.update(FullPathDependList
)
1234 DependencySet
.update(ForceList
)
1235 if File
in DependencySet
:
1236 DependencySet
.remove(File
)
1237 DependencyList
= list(DependencySet
) # remove duplicate ones
1239 return DependencyList
1241 ## CustomMakefile class
1243 # This class encapsules makefie and its generation for module. It uses template to generate
1244 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
1246 class CustomMakefile(BuildFile
):
1247 ## template used to generate the makefile for module with custom makefile
1248 _TEMPLATE_
= TemplateString('''\
1252 # Platform Macro Definition
1254 PLATFORM_NAME = ${platform_name}
1255 PLATFORM_GUID = ${platform_guid}
1256 PLATFORM_VERSION = ${platform_version}
1257 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
1258 PLATFORM_DIR = ${platform_dir}
1259 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1262 # Module Macro Definition
1264 MODULE_NAME = ${module_name}
1265 MODULE_GUID = ${module_guid}
1266 MODULE_NAME_GUID = ${module_name_guid}
1267 MODULE_VERSION = ${module_version}
1268 MODULE_TYPE = ${module_type}
1269 MODULE_FILE = ${module_file}
1270 MODULE_FILE_BASE_NAME = ${module_file_base_name}
1271 BASE_NAME = $(MODULE_NAME)
1272 MODULE_RELATIVE_DIR = ${module_relative_directory}
1273 MODULE_DIR = ${module_dir}
1276 # Build Configuration Macro Definition
1278 ARCH = ${architecture}
1279 TOOLCHAIN = ${toolchain_tag}
1280 TOOLCHAIN_TAG = ${toolchain_tag}
1281 TARGET = ${build_target}
1284 # Build Directory Macro Definition
1286 # PLATFORM_BUILD_DIR = ${platform_build_directory}
1287 BUILD_DIR = ${platform_build_directory}
1288 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
1289 LIB_DIR = $(BIN_DIR)
1290 MODULE_BUILD_DIR = ${module_build_directory}
1291 OUTPUT_DIR = ${module_output_directory}
1292 DEBUG_DIR = ${module_debug_directory}
1293 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
1294 DEST_DIR_DEBUG = $(DEBUG_DIR)
1297 # Tools definitions specific to this module
1299 ${BEGIN}${module_tool_definitions}
1301 MAKE_FILE = ${makefile_path}
1304 # Shell Command Macro
1306 ${BEGIN}${shell_command_code} = ${shell_command}
1309 ${custom_makefile_content}
1312 # Target used when called from platform makefile, which will bypass the build of dependent libraries
1325 # Build Target used in multi-thread build mode, which no init target is needed
1331 # Initialization target: print build information and create necessary directories
1334 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
1335 ${BEGIN}\t-@${create_directory_command}\n${END}\
1339 ## Constructor of CustomMakefile
1341 # @param ModuleAutoGen Object of ModuleAutoGen class
1343 def __init__(self
, ModuleAutoGen
):
1344 BuildFile
.__init
__(self
, ModuleAutoGen
)
1345 self
.PlatformInfo
= self
._AutoGenObject
.PlatformInfo
1346 self
.IntermediateDirectoryList
= ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
1348 # Compose a dict object containing information used to do replacement in template
1350 def _TemplateDict(self
):
1351 Separator
= self
._SEP
_[self
._FileType
]
1352 MyAgo
= self
._AutoGenObject
1353 if self
._FileType
not in MyAgo
.CustomMakefile
:
1354 EdkLogger
.error('build', OPTION_NOT_SUPPORTED
, "No custom makefile for %s" % self
._FileType
,
1355 ExtraData
="[%s]" % str(MyAgo
))
1356 MakefilePath
= mws
.join(
1358 MyAgo
.CustomMakefile
[self
._FileType
]
1361 CustomMakefile
= open(MakefilePath
, 'r').read()
1363 EdkLogger
.error('build', FILE_OPEN_FAILURE
, File
=str(MyAgo
),
1364 ExtraData
=MyAgo
.CustomMakefile
[self
._FileType
])
1368 for Tool
in MyAgo
.BuildOption
:
1369 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
1372 for Attr
in MyAgo
.BuildOption
[Tool
]:
1373 if Attr
== "FAMILY":
1375 elif Attr
== "PATH":
1376 ToolsDef
.append("%s = %s" % (Tool
, MyAgo
.BuildOption
[Tool
][Attr
]))
1378 ToolsDef
.append("%s_%s = %s" % (Tool
, Attr
, MyAgo
.BuildOption
[Tool
][Attr
]))
1381 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1382 MakefileTemplateDict
= {
1383 "makefile_header" : self
._FILE
_HEADER
_[self
._FileType
],
1384 "makefile_path" : os
.path
.join("$(MODULE_BUILD_DIR)", MakefileName
),
1385 "platform_name" : self
.PlatformInfo
.Name
,
1386 "platform_guid" : self
.PlatformInfo
.Guid
,
1387 "platform_version" : self
.PlatformInfo
.Version
,
1388 "platform_relative_directory": self
.PlatformInfo
.SourceDir
,
1389 "platform_output_directory" : self
.PlatformInfo
.OutputDir
,
1390 "platform_dir" : MyAgo
.Macros
["PLATFORM_DIR"],
1392 "module_name" : MyAgo
.Name
,
1393 "module_guid" : MyAgo
.Guid
,
1394 "module_name_guid" : MyAgo
.UniqueBaseName
,
1395 "module_version" : MyAgo
.Version
,
1396 "module_type" : MyAgo
.ModuleType
,
1397 "module_file" : MyAgo
.MetaFile
,
1398 "module_file_base_name" : MyAgo
.MetaFile
.BaseName
,
1399 "module_relative_directory" : MyAgo
.SourceDir
,
1400 "module_dir" : mws
.join (MyAgo
.WorkspaceDir
, MyAgo
.SourceDir
),
1402 "architecture" : MyAgo
.Arch
,
1403 "toolchain_tag" : MyAgo
.ToolChain
,
1404 "build_target" : MyAgo
.BuildTarget
,
1406 "platform_build_directory" : self
.PlatformInfo
.BuildDir
,
1407 "module_build_directory" : MyAgo
.BuildDir
,
1408 "module_output_directory" : MyAgo
.OutputDir
,
1409 "module_debug_directory" : MyAgo
.DebugDir
,
1411 "separator" : Separator
,
1412 "module_tool_definitions" : ToolsDef
,
1414 "shell_command_code" : list(self
._SHELL
_CMD
_[self
._FileType
].keys()),
1415 "shell_command" : list(self
._SHELL
_CMD
_[self
._FileType
].values()),
1417 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1418 "custom_makefile_content" : CustomMakefile
1421 return MakefileTemplateDict
1423 ## PlatformMakefile class
1425 # This class encapsules makefie and its generation for platform. It uses
1426 # template to generate the content of makefile. The content of makefile will be
1427 # got from PlatformAutoGen object.
1429 class PlatformMakefile(BuildFile
):
1430 ## template used to generate the makefile for platform
1431 _TEMPLATE_
= TemplateString('''\
1435 # Platform Macro Definition
1437 PLATFORM_NAME = ${platform_name}
1438 PLATFORM_GUID = ${platform_guid}
1439 PLATFORM_VERSION = ${platform_version}
1440 PLATFORM_FILE = ${platform_file}
1441 PLATFORM_DIR = ${platform_dir}
1442 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1445 # Build Configuration Macro Definition
1447 TOOLCHAIN = ${toolchain_tag}
1448 TOOLCHAIN_TAG = ${toolchain_tag}
1449 TARGET = ${build_target}
1452 # Build Directory Macro Definition
1454 BUILD_DIR = ${platform_build_directory}
1455 FV_DIR = ${platform_build_directory}${separator}FV
1458 # Shell Command Macro
1460 ${BEGIN}${shell_command_code} = ${shell_command}
1464 MAKE_FILE = ${makefile_path}
1469 all: init build_libraries build_modules
1472 # Initialization target: print build information and create necessary directories
1475 \t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
1476 \t${BEGIN}-@${create_directory_command}
1479 # library build target
1481 libraries: init build_libraries
1484 # module build target
1486 modules: init build_libraries build_modules
1489 # Build all libraries:
1492 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
1493 ${END}\t@cd $(BUILD_DIR)
1496 # Build all modules:
1499 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
1500 ${END}\t@cd $(BUILD_DIR)
1503 # Clean intermediate files
1506 \t${BEGIN}-@${library_build_command} clean
1507 \t${END}${BEGIN}-@${module_build_command} clean
1508 \t${END}@cd $(BUILD_DIR)
1511 # Clean all generated files except to makefile
1514 ${BEGIN}\t${cleanall_command}
1518 # Clean all library files
1521 \t${BEGIN}-@${library_build_command} cleanall
1522 \t${END}@cd $(BUILD_DIR)\n
1525 ## Constructor of PlatformMakefile
1527 # @param ModuleAutoGen Object of PlatformAutoGen class
1529 def __init__(self
, PlatformAutoGen
):
1530 BuildFile
.__init
__(self
, PlatformAutoGen
)
1531 self
.ModuleBuildCommandList
= []
1532 self
.ModuleMakefileList
= []
1533 self
.IntermediateDirectoryList
= []
1534 self
.ModuleBuildDirectoryList
= []
1535 self
.LibraryBuildDirectoryList
= []
1536 self
.LibraryMakeCommandList
= []
1538 # Compose a dict object containing information used to do replacement in template
1540 def _TemplateDict(self
):
1541 Separator
= self
._SEP
_[self
._FileType
]
1543 MyAgo
= self
._AutoGenObject
1544 if "MAKE" not in MyAgo
.ToolDefinition
or "PATH" not in MyAgo
.ToolDefinition
["MAKE"]:
1545 EdkLogger
.error("build", OPTION_MISSING
, "No MAKE command defined. Please check your tools_def.txt!",
1546 ExtraData
="[%s]" % str(MyAgo
))
1548 self
.IntermediateDirectoryList
= ["$(BUILD_DIR)"]
1549 self
.ModuleBuildDirectoryList
= self
.GetModuleBuildDirectoryList()
1550 self
.LibraryBuildDirectoryList
= self
.GetLibraryBuildDirectoryList()
1552 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1553 LibraryMakefileList
= []
1554 LibraryMakeCommandList
= []
1555 for D
in self
.LibraryBuildDirectoryList
:
1556 D
= self
.PlaceMacro(D
, {"BUILD_DIR":MyAgo
.BuildDir
})
1557 Makefile
= os
.path
.join(D
, MakefileName
)
1558 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":Makefile
}
1559 LibraryMakefileList
.append(Makefile
)
1560 LibraryMakeCommandList
.append(Command
)
1561 self
.LibraryMakeCommandList
= LibraryMakeCommandList
1563 ModuleMakefileList
= []
1564 ModuleMakeCommandList
= []
1565 for D
in self
.ModuleBuildDirectoryList
:
1566 D
= self
.PlaceMacro(D
, {"BUILD_DIR":MyAgo
.BuildDir
})
1567 Makefile
= os
.path
.join(D
, MakefileName
)
1568 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":Makefile
}
1569 ModuleMakefileList
.append(Makefile
)
1570 ModuleMakeCommandList
.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 "makefile_name" : MakefileName
,
1577 "platform_name" : MyAgo
.Name
,
1578 "platform_guid" : MyAgo
.Guid
,
1579 "platform_version" : MyAgo
.Version
,
1580 "platform_file" : MyAgo
.MetaFile
,
1581 "platform_relative_directory": MyAgo
.SourceDir
,
1582 "platform_output_directory" : MyAgo
.OutputDir
,
1583 "platform_build_directory" : MyAgo
.BuildDir
,
1584 "platform_dir" : MyAgo
.Macros
["PLATFORM_DIR"],
1586 "toolchain_tag" : MyAgo
.ToolChain
,
1587 "build_target" : MyAgo
.BuildTarget
,
1588 "shell_command_code" : list(self
._SHELL
_CMD
_[self
._FileType
].keys()),
1589 "shell_command" : list(self
._SHELL
_CMD
_[self
._FileType
].values()),
1590 "build_architecture_list" : MyAgo
.Arch
,
1591 "architecture" : MyAgo
.Arch
,
1592 "separator" : Separator
,
1593 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1594 "cleanall_command" : self
.GetRemoveDirectoryCommand(self
.IntermediateDirectoryList
),
1595 "library_makefile_list" : LibraryMakefileList
,
1596 "module_makefile_list" : ModuleMakefileList
,
1597 "library_build_command" : LibraryMakeCommandList
,
1598 "module_build_command" : ModuleMakeCommandList
,
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
and not LibraryAutoGen
.CanSkipbyHash():
1622 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, LibraryAutoGen
.BuildDir
))
1625 ## TopLevelMakefile class
1627 # This class encapsules makefie and its generation for entrance makefile. It
1628 # uses template to generate the content of makefile. The content of makefile
1629 # will be got from WorkspaceAutoGen object.
1631 class TopLevelMakefile(BuildFile
):
1632 ## template used to generate toplevel makefile
1633 _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}''')
1635 ## Constructor of TopLevelMakefile
1637 # @param Workspace Object of WorkspaceAutoGen class
1639 def __init__(self
, Workspace
):
1640 BuildFile
.__init
__(self
, Workspace
)
1641 self
.IntermediateDirectoryList
= []
1643 # Compose a dict object containing information used to do replacement in template
1645 def _TemplateDict(self
):
1646 Separator
= self
._SEP
_[self
._FileType
]
1648 # any platform autogen object is ok because we just need common information
1649 MyAgo
= self
._AutoGenObject
1651 if "MAKE" not in MyAgo
.ToolDefinition
or "PATH" not in MyAgo
.ToolDefinition
["MAKE"]:
1652 EdkLogger
.error("build", OPTION_MISSING
, "No MAKE command defined. Please check your tools_def.txt!",
1653 ExtraData
="[%s]" % str(MyAgo
))
1655 for Arch
in MyAgo
.ArchList
:
1656 self
.IntermediateDirectoryList
.append(Separator
.join(["$(BUILD_DIR)", Arch
]))
1657 self
.IntermediateDirectoryList
.append("$(FV_DIR)")
1659 # TRICK: for not generating GenFds call in makefile if no FDF file
1661 if MyAgo
.FdfFile
is not None and MyAgo
.FdfFile
!= "":
1662 FdfFileList
= [MyAgo
.FdfFile
]
1663 # macros passed to GenFds
1665 MacroDict
.update(GlobalData
.gGlobalDefines
)
1666 MacroDict
.update(GlobalData
.gCommandLineDefines
)
1667 for MacroName
in MacroDict
:
1668 if MacroDict
[MacroName
] != "":
1669 MacroList
.append('"%s=%s"' % (MacroName
, MacroDict
[MacroName
].replace('\\', '\\\\')))
1671 MacroList
.append('"%s"' % MacroName
)
1675 # pass extra common options to external program called in makefile, currently GenFds.exe
1677 LogLevel
= EdkLogger
.GetLevel()
1678 if LogLevel
== EdkLogger
.VERBOSE
:
1679 ExtraOption
+= " -v"
1680 elif LogLevel
<= EdkLogger
.DEBUG_9
:
1681 ExtraOption
+= " -d %d" % (LogLevel
- 1)
1682 elif LogLevel
== EdkLogger
.QUIET
:
1683 ExtraOption
+= " -q"
1685 if GlobalData
.gCaseInsensitive
:
1686 ExtraOption
+= " -c"
1687 if GlobalData
.gEnableGenfdsMultiThread
:
1688 ExtraOption
+= " --genfds-multi-thread"
1689 if GlobalData
.gIgnoreSource
:
1690 ExtraOption
+= " --ignore-sources"
1692 for pcd
in GlobalData
.BuildOptionPcd
:
1694 pcdname
= '.'.join(pcd
[0:3])
1696 pcdname
= '.'.join(pcd
[0:2])
1697 if pcd
[3].startswith('{'):
1698 ExtraOption
+= " --pcd " + pcdname
+ '=' + 'H' + '"' + pcd
[3] + '"'
1700 ExtraOption
+= " --pcd " + pcdname
+ '=' + pcd
[3]
1702 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1703 SubBuildCommandList
= []
1704 for A
in MyAgo
.ArchList
:
1705 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":os
.path
.join("$(BUILD_DIR)", A
, MakefileName
)}
1706 SubBuildCommandList
.append(Command
)
1708 MakefileTemplateDict
= {
1709 "makefile_header" : self
._FILE
_HEADER
_[self
._FileType
],
1710 "makefile_path" : os
.path
.join("$(BUILD_DIR)", MakefileName
),
1711 "make_path" : MyAgo
.ToolDefinition
["MAKE"]["PATH"],
1712 "platform_name" : MyAgo
.Name
,
1713 "platform_guid" : MyAgo
.Guid
,
1714 "platform_version" : MyAgo
.Version
,
1715 "platform_build_directory" : MyAgo
.BuildDir
,
1716 "conf_directory" : GlobalData
.gConfDirectory
,
1718 "toolchain_tag" : MyAgo
.ToolChain
,
1719 "build_target" : MyAgo
.BuildTarget
,
1720 "shell_command_code" : list(self
._SHELL
_CMD
_[self
._FileType
].keys()),
1721 "shell_command" : list(self
._SHELL
_CMD
_[self
._FileType
].values()),
1722 'arch' : list(MyAgo
.ArchList
),
1723 "build_architecture_list" : ','.join(MyAgo
.ArchList
),
1724 "separator" : Separator
,
1725 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1726 "cleanall_command" : self
.GetRemoveDirectoryCommand(self
.IntermediateDirectoryList
),
1727 "sub_build_command" : SubBuildCommandList
,
1728 "fdf_file" : FdfFileList
,
1729 "active_platform" : str(MyAgo
),
1730 "fd" : MyAgo
.FdTargetList
,
1731 "fv" : MyAgo
.FvTargetList
,
1732 "cap" : MyAgo
.CapTargetList
,
1733 "extra_options" : ExtraOption
,
1734 "macro" : MacroList
,
1737 return MakefileTemplateDict
1739 ## Get the root directory list for intermediate files of all modules build
1741 # @retval list The list of directory
1743 def GetModuleBuildDirectoryList(self
):
1745 for ModuleAutoGen
in self
._AutoGenObject
.ModuleAutoGenList
:
1746 if not ModuleAutoGen
.IsBinaryModule
:
1747 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, ModuleAutoGen
.BuildDir
))
1750 ## Get the root directory list for intermediate files of all libraries build
1752 # @retval list The list of directory
1754 def GetLibraryBuildDirectoryList(self
):
1756 for LibraryAutoGen
in self
._AutoGenObject
.LibraryAutoGenList
:
1757 if not LibraryAutoGen
.IsBinaryModule
and not LibraryAutoGen
.CanSkipbyHash():
1758 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, LibraryAutoGen
.BuildDir
))
1761 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1762 if __name__
== '__main__':