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
" : list(self._SHELL_CMD_[self._FileType].keys()),
679 "shell_command
" : list(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 separator, 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 dependencies 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
, 'rb')
1042 FileContent
= Fd
.read()
1044 except BaseException
as X
:
1045 EdkLogger
.error("build", FILE_OPEN_FAILURE
, ExtraData
=F
.Path
+ "\n\t" + str(X
))
1046 if len(FileContent
) == 0:
1049 if FileContent
[0] == 0xff or FileContent
[0] == 0xfe:
1050 FileContent
= FileContent
.decode('utf-16')
1052 FileContent
= FileContent
.decode()
1054 # The file is not txt file. for example .mcb file
1056 IncludedFileList
= gIncludePattern
.findall(FileContent
)
1058 for Inc
in IncludedFileList
:
1060 # if there's macro used to reference header file, expand it
1061 HeaderList
= gMacroPattern
.findall(Inc
)
1062 if len(HeaderList
) == 1 and len(HeaderList
[0]) == 2:
1063 HeaderType
= HeaderList
[0][0]
1064 HeaderKey
= HeaderList
[0][1]
1065 if HeaderType
in gIncludeMacroConversion
:
1066 Inc
= gIncludeMacroConversion
[HeaderType
] % {"HeaderKey" : HeaderKey
}
1068 # not known macro used in #include, always build the file by
1069 # returning a empty dependency
1070 self
.FileCache
[File
] = []
1072 Inc
= os
.path
.normpath(Inc
)
1073 CurrentFileDependencyList
.append(Inc
)
1074 DepDb
[F
] = CurrentFileDependencyList
1076 CurrentFilePath
= F
.Dir
1077 PathList
= [CurrentFilePath
] + SearchPathList
1078 for Inc
in CurrentFileDependencyList
:
1079 for SearchPath
in PathList
:
1080 FilePath
= os
.path
.join(SearchPath
, Inc
)
1081 if FilePath
in gIsFileMap
:
1082 if not gIsFileMap
[FilePath
]:
1084 # If isfile is called too many times, the performance is slow down.
1085 elif not os
.path
.isfile(FilePath
):
1086 gIsFileMap
[FilePath
] = False
1089 gIsFileMap
[FilePath
] = True
1090 FilePath
= PathClass(FilePath
)
1091 FullPathDependList
.append(FilePath
)
1092 if FilePath
not in DependencySet
:
1093 FileStack
.append(FilePath
)
1096 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "%s included by %s was not found "\
1097 "in any given path:\n\t%s" % (Inc
, F
, "\n\t".join(SearchPathList
)))
1099 self
.FileCache
[F
] = FullPathDependList
1100 DependencySet
.update(FullPathDependList
)
1102 DependencySet
.update(ForceList
)
1103 if File
in DependencySet
:
1104 DependencySet
.remove(File
)
1105 DependencyList
= list(DependencySet
) # remove duplicate ones
1107 return DependencyList
1109 ## CustomMakefile class
1111 # This class encapsules makefie and its generation for module. It uses template to generate
1112 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
1114 class CustomMakefile(BuildFile
):
1115 ## template used to generate the makefile for module with custom makefile
1116 _TEMPLATE_
= TemplateString('''\
1120 # Platform Macro Definition
1122 PLATFORM_NAME = ${platform_name}
1123 PLATFORM_GUID = ${platform_guid}
1124 PLATFORM_VERSION = ${platform_version}
1125 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
1126 PLATFORM_DIR = ${platform_dir}
1127 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1130 # Module Macro Definition
1132 MODULE_NAME = ${module_name}
1133 MODULE_GUID = ${module_guid}
1134 MODULE_NAME_GUID = ${module_name_guid}
1135 MODULE_VERSION = ${module_version}
1136 MODULE_TYPE = ${module_type}
1137 MODULE_FILE = ${module_file}
1138 MODULE_FILE_BASE_NAME = ${module_file_base_name}
1139 BASE_NAME = $(MODULE_NAME)
1140 MODULE_RELATIVE_DIR = ${module_relative_directory}
1141 MODULE_DIR = ${module_dir}
1144 # Build Configuration Macro Definition
1146 ARCH = ${architecture}
1147 TOOLCHAIN = ${toolchain_tag}
1148 TOOLCHAIN_TAG = ${toolchain_tag}
1149 TARGET = ${build_target}
1152 # Build Directory Macro Definition
1154 # PLATFORM_BUILD_DIR = ${platform_build_directory}
1155 BUILD_DIR = ${platform_build_directory}
1156 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
1157 LIB_DIR = $(BIN_DIR)
1158 MODULE_BUILD_DIR = ${module_build_directory}
1159 OUTPUT_DIR = ${module_output_directory}
1160 DEBUG_DIR = ${module_debug_directory}
1161 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
1162 DEST_DIR_DEBUG = $(DEBUG_DIR)
1165 # Tools definitions specific to this module
1167 ${BEGIN}${module_tool_definitions}
1169 MAKE_FILE = ${makefile_path}
1172 # Shell Command Macro
1174 ${BEGIN}${shell_command_code} = ${shell_command}
1177 ${custom_makefile_content}
1180 # Target used when called from platform makefile, which will bypass the build of dependent libraries
1193 # Build Target used in multi-thread build mode, which no init target is needed
1199 # Initialization target: print build information and create necessary directories
1202 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
1203 ${BEGIN}\t-@${create_directory_command}\n${END}\
1207 ## Constructor of CustomMakefile
1209 # @param ModuleAutoGen Object of ModuleAutoGen class
1211 def __init__(self
, ModuleAutoGen
):
1212 BuildFile
.__init
__(self
, ModuleAutoGen
)
1213 self
.PlatformInfo
= self
._AutoGenObject
.PlatformInfo
1214 self
.IntermediateDirectoryList
= ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
1216 # Compose a dict object containing information used to do replacement in template
1218 def _TemplateDict(self
):
1219 Separator
= self
._SEP
_[self
._FileType
]
1220 MyAgo
= self
._AutoGenObject
1221 if self
._FileType
not in MyAgo
.CustomMakefile
:
1222 EdkLogger
.error('build', OPTION_NOT_SUPPORTED
, "No custom makefile for %s" % self
._FileType
,
1223 ExtraData
="[%s]" % str(MyAgo
))
1224 MakefilePath
= mws
.join(
1226 MyAgo
.CustomMakefile
[self
._FileType
]
1229 CustomMakefile
= open(MakefilePath
, 'r').read()
1231 EdkLogger
.error('build', FILE_OPEN_FAILURE
, File
=str(MyAgo
),
1232 ExtraData
=MyAgo
.CustomMakefile
[self
._FileType
])
1236 for Tool
in MyAgo
.BuildOption
:
1237 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
1240 for Attr
in MyAgo
.BuildOption
[Tool
]:
1241 if Attr
== "FAMILY":
1243 elif Attr
== "PATH":
1244 ToolsDef
.append("%s = %s" % (Tool
, MyAgo
.BuildOption
[Tool
][Attr
]))
1246 ToolsDef
.append("%s_%s = %s" % (Tool
, Attr
, MyAgo
.BuildOption
[Tool
][Attr
]))
1249 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1250 MakefileTemplateDict
= {
1251 "makefile_header" : self
._FILE
_HEADER
_[self
._FileType
],
1252 "makefile_path" : os
.path
.join("$(MODULE_BUILD_DIR)", MakefileName
),
1253 "platform_name" : self
.PlatformInfo
.Name
,
1254 "platform_guid" : self
.PlatformInfo
.Guid
,
1255 "platform_version" : self
.PlatformInfo
.Version
,
1256 "platform_relative_directory": self
.PlatformInfo
.SourceDir
,
1257 "platform_output_directory" : self
.PlatformInfo
.OutputDir
,
1258 "platform_dir" : MyAgo
.Macros
["PLATFORM_DIR"],
1260 "module_name" : MyAgo
.Name
,
1261 "module_guid" : MyAgo
.Guid
,
1262 "module_name_guid" : MyAgo
.UniqueBaseName
,
1263 "module_version" : MyAgo
.Version
,
1264 "module_type" : MyAgo
.ModuleType
,
1265 "module_file" : MyAgo
.MetaFile
,
1266 "module_file_base_name" : MyAgo
.MetaFile
.BaseName
,
1267 "module_relative_directory" : MyAgo
.SourceDir
,
1268 "module_dir" : mws
.join (MyAgo
.WorkspaceDir
, MyAgo
.SourceDir
),
1270 "architecture" : MyAgo
.Arch
,
1271 "toolchain_tag" : MyAgo
.ToolChain
,
1272 "build_target" : MyAgo
.BuildTarget
,
1274 "platform_build_directory" : self
.PlatformInfo
.BuildDir
,
1275 "module_build_directory" : MyAgo
.BuildDir
,
1276 "module_output_directory" : MyAgo
.OutputDir
,
1277 "module_debug_directory" : MyAgo
.DebugDir
,
1279 "separator" : Separator
,
1280 "module_tool_definitions" : ToolsDef
,
1282 "shell_command_code" : list(self
._SHELL
_CMD
_[self
._FileType
].keys()),
1283 "shell_command" : list(self
._SHELL
_CMD
_[self
._FileType
].values()),
1285 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1286 "custom_makefile_content" : CustomMakefile
1289 return MakefileTemplateDict
1291 ## PlatformMakefile class
1293 # This class encapsules makefie and its generation for platform. It uses
1294 # template to generate the content of makefile. The content of makefile will be
1295 # got from PlatformAutoGen object.
1297 class PlatformMakefile(BuildFile
):
1298 ## template used to generate the makefile for platform
1299 _TEMPLATE_
= TemplateString('''\
1303 # Platform Macro Definition
1305 PLATFORM_NAME = ${platform_name}
1306 PLATFORM_GUID = ${platform_guid}
1307 PLATFORM_VERSION = ${platform_version}
1308 PLATFORM_FILE = ${platform_file}
1309 PLATFORM_DIR = ${platform_dir}
1310 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1313 # Build Configuration Macro Definition
1315 TOOLCHAIN = ${toolchain_tag}
1316 TOOLCHAIN_TAG = ${toolchain_tag}
1317 TARGET = ${build_target}
1320 # Build Directory Macro Definition
1322 BUILD_DIR = ${platform_build_directory}
1323 FV_DIR = ${platform_build_directory}${separator}FV
1326 # Shell Command Macro
1328 ${BEGIN}${shell_command_code} = ${shell_command}
1332 MAKE_FILE = ${makefile_path}
1337 all: init build_libraries build_modules
1340 # Initialization target: print build information and create necessary directories
1343 \t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
1344 \t${BEGIN}-@${create_directory_command}
1347 # library build target
1349 libraries: init build_libraries
1352 # module build target
1354 modules: init build_libraries build_modules
1357 # Build all libraries:
1360 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
1361 ${END}\t@cd $(BUILD_DIR)
1364 # Build all modules:
1367 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
1368 ${END}\t@cd $(BUILD_DIR)
1371 # Clean intermediate files
1374 \t${BEGIN}-@${library_build_command} clean
1375 \t${END}${BEGIN}-@${module_build_command} clean
1376 \t${END}@cd $(BUILD_DIR)
1379 # Clean all generated files except to makefile
1382 ${BEGIN}\t${cleanall_command}
1386 # Clean all library files
1389 \t${BEGIN}-@${library_build_command} cleanall
1390 \t${END}@cd $(BUILD_DIR)\n
1393 ## Constructor of PlatformMakefile
1395 # @param ModuleAutoGen Object of PlatformAutoGen class
1397 def __init__(self
, PlatformAutoGen
):
1398 BuildFile
.__init
__(self
, PlatformAutoGen
)
1399 self
.ModuleBuildCommandList
= []
1400 self
.ModuleMakefileList
= []
1401 self
.IntermediateDirectoryList
= []
1402 self
.ModuleBuildDirectoryList
= []
1403 self
.LibraryBuildDirectoryList
= []
1404 self
.LibraryMakeCommandList
= []
1406 # Compose a dict object containing information used to do replacement in template
1408 def _TemplateDict(self
):
1409 Separator
= self
._SEP
_[self
._FileType
]
1411 MyAgo
= self
._AutoGenObject
1412 if "MAKE" not in MyAgo
.ToolDefinition
or "PATH" not in MyAgo
.ToolDefinition
["MAKE"]:
1413 EdkLogger
.error("build", OPTION_MISSING
, "No MAKE command defined. Please check your tools_def.txt!",
1414 ExtraData
="[%s]" % str(MyAgo
))
1416 self
.IntermediateDirectoryList
= ["$(BUILD_DIR)"]
1417 self
.ModuleBuildDirectoryList
= self
.GetModuleBuildDirectoryList()
1418 self
.LibraryBuildDirectoryList
= self
.GetLibraryBuildDirectoryList()
1420 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1421 LibraryMakefileList
= []
1422 LibraryMakeCommandList
= []
1423 for D
in self
.LibraryBuildDirectoryList
:
1424 D
= self
.PlaceMacro(D
, {"BUILD_DIR":MyAgo
.BuildDir
})
1425 Makefile
= os
.path
.join(D
, MakefileName
)
1426 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":Makefile
}
1427 LibraryMakefileList
.append(Makefile
)
1428 LibraryMakeCommandList
.append(Command
)
1429 self
.LibraryMakeCommandList
= LibraryMakeCommandList
1431 ModuleMakefileList
= []
1432 ModuleMakeCommandList
= []
1433 for D
in self
.ModuleBuildDirectoryList
:
1434 D
= self
.PlaceMacro(D
, {"BUILD_DIR":MyAgo
.BuildDir
})
1435 Makefile
= os
.path
.join(D
, MakefileName
)
1436 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":Makefile
}
1437 ModuleMakefileList
.append(Makefile
)
1438 ModuleMakeCommandList
.append(Command
)
1440 MakefileTemplateDict
= {
1441 "makefile_header" : self
._FILE
_HEADER
_[self
._FileType
],
1442 "makefile_path" : os
.path
.join("$(BUILD_DIR)", MakefileName
),
1443 "make_path" : MyAgo
.ToolDefinition
["MAKE"]["PATH"],
1444 "makefile_name" : MakefileName
,
1445 "platform_name" : MyAgo
.Name
,
1446 "platform_guid" : MyAgo
.Guid
,
1447 "platform_version" : MyAgo
.Version
,
1448 "platform_file" : MyAgo
.MetaFile
,
1449 "platform_relative_directory": MyAgo
.SourceDir
,
1450 "platform_output_directory" : MyAgo
.OutputDir
,
1451 "platform_build_directory" : MyAgo
.BuildDir
,
1452 "platform_dir" : MyAgo
.Macros
["PLATFORM_DIR"],
1454 "toolchain_tag" : MyAgo
.ToolChain
,
1455 "build_target" : MyAgo
.BuildTarget
,
1456 "shell_command_code" : list(self
._SHELL
_CMD
_[self
._FileType
].keys()),
1457 "shell_command" : list(self
._SHELL
_CMD
_[self
._FileType
].values()),
1458 "build_architecture_list" : MyAgo
.Arch
,
1459 "architecture" : MyAgo
.Arch
,
1460 "separator" : Separator
,
1461 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1462 "cleanall_command" : self
.GetRemoveDirectoryCommand(self
.IntermediateDirectoryList
),
1463 "library_makefile_list" : LibraryMakefileList
,
1464 "module_makefile_list" : ModuleMakefileList
,
1465 "library_build_command" : LibraryMakeCommandList
,
1466 "module_build_command" : ModuleMakeCommandList
,
1469 return MakefileTemplateDict
1471 ## Get the root directory list for intermediate files of all modules build
1473 # @retval list The list of directory
1475 def GetModuleBuildDirectoryList(self
):
1477 for ModuleAutoGen
in self
._AutoGenObject
.ModuleAutoGenList
:
1478 if not ModuleAutoGen
.IsBinaryModule
:
1479 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, ModuleAutoGen
.BuildDir
))
1482 ## Get the root directory list for intermediate files of all libraries build
1484 # @retval list The list of directory
1486 def GetLibraryBuildDirectoryList(self
):
1488 for LibraryAutoGen
in self
._AutoGenObject
.LibraryAutoGenList
:
1489 if not LibraryAutoGen
.IsBinaryModule
:
1490 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, LibraryAutoGen
.BuildDir
))
1493 ## TopLevelMakefile class
1495 # This class encapsules makefie and its generation for entrance makefile. It
1496 # uses template to generate the content of makefile. The content of makefile
1497 # will be got from WorkspaceAutoGen object.
1499 class TopLevelMakefile(BuildFile
):
1500 ## template used to generate toplevel makefile
1501 _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}''')
1503 ## Constructor of TopLevelMakefile
1505 # @param Workspace Object of WorkspaceAutoGen class
1507 def __init__(self
, Workspace
):
1508 BuildFile
.__init
__(self
, Workspace
)
1509 self
.IntermediateDirectoryList
= []
1511 # Compose a dict object containing information used to do replacement in template
1513 def _TemplateDict(self
):
1514 Separator
= self
._SEP
_[self
._FileType
]
1516 # any platform autogen object is ok because we just need common information
1517 MyAgo
= self
._AutoGenObject
1519 if "MAKE" not in MyAgo
.ToolDefinition
or "PATH" not in MyAgo
.ToolDefinition
["MAKE"]:
1520 EdkLogger
.error("build", OPTION_MISSING
, "No MAKE command defined. Please check your tools_def.txt!",
1521 ExtraData
="[%s]" % str(MyAgo
))
1523 for Arch
in MyAgo
.ArchList
:
1524 self
.IntermediateDirectoryList
.append(Separator
.join(["$(BUILD_DIR)", Arch
]))
1525 self
.IntermediateDirectoryList
.append("$(FV_DIR)")
1527 # TRICK: for not generating GenFds call in makefile if no FDF file
1529 if MyAgo
.FdfFile
is not None and MyAgo
.FdfFile
!= "":
1530 FdfFileList
= [MyAgo
.FdfFile
]
1531 # macros passed to GenFds
1533 MacroDict
.update(GlobalData
.gGlobalDefines
)
1534 MacroDict
.update(GlobalData
.gCommandLineDefines
)
1535 for MacroName
in MacroDict
:
1536 if MacroDict
[MacroName
] != "":
1537 MacroList
.append('"%s=%s"' % (MacroName
, MacroDict
[MacroName
].replace('\\', '\\\\')))
1539 MacroList
.append('"%s"' % MacroName
)
1543 # pass extra common options to external program called in makefile, currently GenFds.exe
1545 LogLevel
= EdkLogger
.GetLevel()
1546 if LogLevel
== EdkLogger
.VERBOSE
:
1547 ExtraOption
+= " -v"
1548 elif LogLevel
<= EdkLogger
.DEBUG_9
:
1549 ExtraOption
+= " -d %d" % (LogLevel
- 1)
1550 elif LogLevel
== EdkLogger
.QUIET
:
1551 ExtraOption
+= " -q"
1553 if GlobalData
.gCaseInsensitive
:
1554 ExtraOption
+= " -c"
1555 if GlobalData
.gEnableGenfdsMultiThread
:
1556 ExtraOption
+= " --genfds-multi-thread"
1557 if GlobalData
.gIgnoreSource
:
1558 ExtraOption
+= " --ignore-sources"
1560 for pcd
in GlobalData
.BuildOptionPcd
:
1562 pcdname
= '.'.join(pcd
[0:3])
1564 pcdname
= '.'.join(pcd
[0:2])
1565 if pcd
[3].startswith('{'):
1566 ExtraOption
+= " --pcd " + pcdname
+ '=' + 'H' + '"' + pcd
[3] + '"'
1568 ExtraOption
+= " --pcd " + pcdname
+ '=' + pcd
[3]
1570 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1571 SubBuildCommandList
= []
1572 for A
in MyAgo
.ArchList
:
1573 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":os
.path
.join("$(BUILD_DIR)", A
, MakefileName
)}
1574 SubBuildCommandList
.append(Command
)
1576 MakefileTemplateDict
= {
1577 "makefile_header" : self
._FILE
_HEADER
_[self
._FileType
],
1578 "makefile_path" : os
.path
.join("$(BUILD_DIR)", MakefileName
),
1579 "make_path" : MyAgo
.ToolDefinition
["MAKE"]["PATH"],
1580 "platform_name" : MyAgo
.Name
,
1581 "platform_guid" : MyAgo
.Guid
,
1582 "platform_version" : MyAgo
.Version
,
1583 "platform_build_directory" : MyAgo
.BuildDir
,
1584 "conf_directory" : GlobalData
.gConfDirectory
,
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 'arch' : list(MyAgo
.ArchList
),
1591 "build_architecture_list" : ','.join(MyAgo
.ArchList
),
1592 "separator" : Separator
,
1593 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1594 "cleanall_command" : self
.GetRemoveDirectoryCommand(self
.IntermediateDirectoryList
),
1595 "sub_build_command" : SubBuildCommandList
,
1596 "fdf_file" : FdfFileList
,
1597 "active_platform" : str(MyAgo
),
1598 "fd" : MyAgo
.FdTargetList
,
1599 "fv" : MyAgo
.FvTargetList
,
1600 "cap" : MyAgo
.CapTargetList
,
1601 "extra_options" : ExtraOption
,
1602 "macro" : MacroList
,
1605 return MakefileTemplateDict
1607 ## Get the root directory list for intermediate files of all modules build
1609 # @retval list The list of directory
1611 def GetModuleBuildDirectoryList(self
):
1613 for ModuleAutoGen
in self
._AutoGenObject
.ModuleAutoGenList
:
1614 if not ModuleAutoGen
.IsBinaryModule
:
1615 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, ModuleAutoGen
.BuildDir
))
1618 ## Get the root directory list for intermediate files of all libraries build
1620 # @retval list The list of directory
1622 def GetLibraryBuildDirectoryList(self
):
1624 for LibraryAutoGen
in self
._AutoGenObject
.LibraryAutoGenList
:
1625 if not LibraryAutoGen
.IsBinaryModule
:
1626 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, LibraryAutoGen
.BuildDir
))
1629 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1630 if __name__
== '__main__':