2 # Create makefile for MS nmake and GNU make
4 # Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 import Common
.LongFilePathOs
as os
20 import os
.path
as path
21 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
22 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
23 from Common
.BuildToolError
import *
24 from Common
.Misc
import *
25 from Common
.String
import *
26 from BuildEngine
import *
27 import Common
.GlobalData
as GlobalData
29 ## Regular expression for finding header file inclusions
30 gIncludePattern
= re
.compile(r
"^[ \t]*#?[ \t]*include(?:[ \t]*(?:\\(?:\r\n|\r|\n))*[ \t]*)*(?:\(?[\"<]?
[ \t]*)([-\w
.\\/() \t]+)(?
:[ \t]*[\">]?\
)?
)", re.MULTILINE | re.UNICODE | re.IGNORECASE)
32 ## Regular expression for matching macro used in header file inclusion
33 gMacroPattern = re.compile("([_A
-Z
][_A
-Z0
-9]*)[ \t]*\
((.+)\
)", re.UNICODE)
37 ## pattern for include style in Edk.x code
38 gProtocolDefinition = "Protocol
/%(HeaderKey)s/%(HeaderKey)s.h
"
39 gGuidDefinition = "Guid
/%(HeaderKey)s/%(HeaderKey)s.h
"
40 gArchProtocolDefinition = "ArchProtocol
/%(HeaderKey)s/%(HeaderKey)s.h
"
41 gPpiDefinition = "Ppi
/%(HeaderKey)s/%(HeaderKey)s.h
"
42 gIncludeMacroConversion = {
43 "EFI_PROTOCOL_DEFINITION
" : gProtocolDefinition,
44 "EFI_GUID_DEFINITION
" : gGuidDefinition,
45 "EFI_ARCH_PROTOCOL_DEFINITION
" : gArchProtocolDefinition,
46 "EFI_PROTOCOL_PRODUCER
" : gProtocolDefinition,
47 "EFI_PROTOCOL_CONSUMER
" : gProtocolDefinition,
48 "EFI_PROTOCOL_DEPENDENCY
" : gProtocolDefinition,
49 "EFI_ARCH_PROTOCOL_PRODUCER
" : gArchProtocolDefinition,
50 "EFI_ARCH_PROTOCOL_CONSUMER
" : gArchProtocolDefinition,
51 "EFI_ARCH_PROTOCOL_DEPENDENCY
" : gArchProtocolDefinition,
52 "EFI_PPI_DEFINITION
" : gPpiDefinition,
53 "EFI_PPI_PRODUCER
" : gPpiDefinition,
54 "EFI_PPI_CONSUMER
" : gPpiDefinition,
55 "EFI_PPI_DEPENDENCY
" : gPpiDefinition,
58 ## default makefile type
60 if sys.platform == "win32
":
68 # This base class encapsules build file and its generation. It uses template to generate
69 # the content of build file. The content of build file will be got from AutoGen objects.
71 class BuildFile(object):
72 ## template used to generate the build file (i.e. makefile if using make)
73 _TEMPLATE_ = TemplateString('')
75 _DEFAULT_FILE_NAME_ = "Makefile
"
77 ## default file name for each type of build file
80 "gmake
" : "GNUmakefile
"
83 ## Fixed header string for makefile
84 _MAKEFILE_HEADER = '''#
86 # This file is auto-generated by build utility
94 # Auto-generated makefile for building modules, libraries or platform
98 ## Header string for each type of build file
100 "nmake
" : _MAKEFILE_HEADER % _FILE_NAME_["nmake
"],
101 "gmake
" : _MAKEFILE_HEADER % _FILE_NAME_["gmake
"]
104 ## shell commands which can be used in build file in the form of macro
105 # $(CP) copy file command
106 # $(MV) move file command
107 # $(RM) remove file command
108 # $(MD) create dir command
109 # $(RD) remove dir command
117 "RD
" : "rmdir
/s
/q
",
129 ## directory separator
135 ## directory creation template
137 "nmake
" : 'if not exist %(dir)s $(MD) %(dir)s',
138 "gmake
" : "$
(MD
) %(dir)s"
141 ## directory removal template
143 "nmake
" : 'if exist %(dir)s $(RD) %(dir)s',
144 "gmake
" : "$
(RD
) %(dir)s"
148 "nmake
" : 'if exist %(dir)s cd %(dir)s',
149 "gmake
" : "test
-e
%(dir)s && cd
%(dir)s"
153 "nmake
" : 'if exist %(file)s "$
(MAKE
)" $(MAKE_FLAGS) -f %(file)s',
154 "gmake
" : 'test -e %(file)s && "$
(MAKE
)" $(MAKE_FLAGS) -f %(file)s'
158 "nmake
" : '!INCLUDE',
162 _INC_FLAG_ = {"MSFT
" : "/I
", "GCC
" : "-I
", "INTEL
" : "-I
", "RVCT
" : "-I
"}
164 ## Constructor of BuildFile
166 # @param AutoGenObject Object of AutoGen class
168 def __init__(self, AutoGenObject):
169 self._AutoGenObject = AutoGenObject
170 self._FileType = gMakeType
174 # @param FileType Type of build file. Only nmake and gmake are supported now.
176 # @retval TRUE The build file is created or re-created successfully
177 # @retval FALSE The build file exists and is the same as the one to be generated
179 def Generate(self, FileType=gMakeType):
180 if FileType not in self._FILE_NAME_:
181 EdkLogger.error("build
", PARAMETER_INVALID, "Invalid build
type [%s]" % FileType,
182 ExtraData="[%s]" % str(self._AutoGenObject))
183 self._FileType = FileType
184 FileContent = self._TEMPLATE_.Replace(self._TemplateDict)
185 FileName = self._FILE_NAME_[FileType]
186 return SaveFileOnChange(os.path.join(self._AutoGenObject.MakeFileDir, FileName), FileContent, False)
188 ## Return a list of directory creation command string
190 # @param DirList The list of directory to be created
192 # @retval list The directory creation command list
194 def GetCreateDirectoryCommand(self, DirList):
195 return [self._MD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
197 ## Return a list of directory removal command string
199 # @param DirList The list of directory to be removed
201 # @retval list The directory removal command list
203 def GetRemoveDirectoryCommand(self, DirList):
204 return [self._RD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
206 def PlaceMacro(self, Path, MacroDefinitions={}):
207 if Path.startswith("$
("):
210 PathLength = len(Path)
211 for MacroName in MacroDefinitions:
212 MacroValue = MacroDefinitions[MacroName]
213 MacroValueLength = len(MacroValue)
214 if MacroValueLength <= PathLength and Path.startswith(MacroValue):
215 Path = "$
(%s)%s" % (MacroName, Path[MacroValueLength:])
219 ## ModuleMakefile class
221 # This class encapsules makefie and its generation for module. It uses template to generate
222 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
224 class ModuleMakefile(BuildFile):
225 ## template used to generate the makefile for module
226 _TEMPLATE_ = TemplateString('''\
230 # Platform Macro Definition
232 PLATFORM_NAME = ${platform_name}
233 PLATFORM_GUID = ${platform_guid}
234 PLATFORM_VERSION = ${platform_version}
235 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
236 PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}
237 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
240 # Module Macro Definition
242 MODULE_NAME = ${module_name}
243 MODULE_GUID = ${module_guid}
244 MODULE_NAME_GUID = ${module_name_guid}
245 MODULE_VERSION = ${module_version}
246 MODULE_TYPE = ${module_type}
247 MODULE_FILE = ${module_file}
248 MODULE_FILE_BASE_NAME = ${module_file_base_name}
249 BASE_NAME = $(MODULE_NAME)
250 MODULE_RELATIVE_DIR = ${module_relative_directory}
251 PACKAGE_RELATIVE_DIR = ${package_relative_directory}
252 MODULE_DIR = ${module_dir}
254 MODULE_ENTRY_POINT = ${module_entry_point}
255 ARCH_ENTRY_POINT = ${arch_entry_point}
256 IMAGE_ENTRY_POINT = ${image_entry_point}
258 ${BEGIN}${module_extra_defines}
261 # Build Configuration Macro Definition
263 ARCH = ${architecture}
264 TOOLCHAIN = ${toolchain_tag}
265 TOOLCHAIN_TAG = ${toolchain_tag}
266 TARGET = ${build_target}
269 # Build Directory Macro Definition
271 # PLATFORM_BUILD_DIR = ${platform_build_directory}
272 BUILD_DIR = ${platform_build_directory}
273 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
275 MODULE_BUILD_DIR = ${module_build_directory}
276 OUTPUT_DIR = ${module_output_directory}
277 DEBUG_DIR = ${module_debug_directory}
278 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
279 DEST_DIR_DEBUG = $(DEBUG_DIR)
282 # Shell Command Macro
284 ${BEGIN}${shell_command_code} = ${shell_command}
288 # Tools definitions specific to this module
290 ${BEGIN}${module_tool_definitions}
292 MAKE_FILE = ${makefile_path}
297 ${BEGIN}${file_macro}
300 COMMON_DEPS = ${BEGIN}${common_dependency_file} \\
304 # Overridable Target Macro Definitions
306 FORCE_REBUILD = force_build
309 BC_TARGET = ${BEGIN}${backward_compatible_target} ${END}
310 CODA_TARGET = ${BEGIN}${remaining_build_target} \\
314 # Default target, which will build dependent libraries in addition to source files
321 # Target used when called from platform makefile, which will bypass the build of dependent libraries
324 pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
330 mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET)
333 # Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets
336 tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
339 # Phony target which is used to force executing commands for a target
345 # Target to update the FD
351 # Initialization target: print build information and create necessary directories
356 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
359 ${BEGIN}\t-@${create_directory_command}\n${END}
362 \t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h
368 \t${BEGIN}@"$
(MAKE
)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name}
369 \t${END}@cd $(MODULE_BUILD_DIR)
372 # Build Flash Device Image
375 \t@"$
(MAKE
)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds
376 \t@cd $(MODULE_BUILD_DIR)
379 # Individual Object Build Targets
381 ${BEGIN}${file_build_target}
385 # clean all intermediate files
388 \t${BEGIN}${clean_command}
392 # clean all generated files
395 ${BEGIN}\t${cleanall_command}
396 ${END}\t$(RM) *.pdb *.idb > NUL 2>&1
397 \t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi
400 # clean all dependent libraries built
403 \t${BEGIN}-@${library_build_command} cleanall
404 \t${END}@cd $(MODULE_BUILD_DIR)\n\n''')
406 _FILE_MACRO_TEMPLATE = TemplateString("${macro_name}
= ${BEGIN}
\\\n ${source_file}${END}
\n")
407 _BUILD_TARGET_TEMPLATE = TemplateString("${BEGIN}${target}
: ${deps}
\n${END}
\t${cmd}
\n")
409 ## Constructor of ModuleMakefile
411 # @param ModuleAutoGen Object of ModuleAutoGen class
413 def __init__(self, ModuleAutoGen):
414 BuildFile.__init__(self, ModuleAutoGen)
415 self.PlatformInfo = self._AutoGenObject.PlatformInfo
417 self.ResultFileList = []
418 self.IntermediateDirectoryList = ["$
(DEBUG_DIR
)", "$
(OUTPUT_DIR
)"]
420 self.SourceFileDatabase = {} # {file type : file path}
421 self.DestFileDatabase = {} # {file type : file path}
422 self.FileBuildTargetList = [] # [(src, target string)]
423 self.BuildTargetList = [] # [target string]
424 self.PendingBuildTargetList = [] # [FileBuildRule objects]
425 self.CommonFileDependency = []
426 self.FileListMacros = {}
427 self.ListFileMacros = {}
430 self.FileDependency = []
431 self.LibraryBuildCommandList = []
432 self.LibraryFileList = []
433 self.LibraryMakefileList = []
434 self.LibraryBuildDirectoryList = []
435 self.SystemLibraryList = []
436 self.Macros = sdict()
437 self.Macros["OUTPUT_DIR
" ] = self._AutoGenObject.Macros["OUTPUT_DIR
"]
438 self.Macros["DEBUG_DIR
" ] = self._AutoGenObject.Macros["DEBUG_DIR
"]
439 self.Macros["MODULE_BUILD_DIR
"] = self._AutoGenObject.Macros["MODULE_BUILD_DIR
"]
440 self.Macros["BIN_DIR
" ] = self._AutoGenObject.Macros["BIN_DIR
"]
441 self.Macros["BUILD_DIR
" ] = self._AutoGenObject.Macros["BUILD_DIR
"]
442 self.Macros["WORKSPACE
" ] = self._AutoGenObject.Macros["WORKSPACE
"]
444 # Compose a dict object containing information used to do replacement in template
445 def _CreateTemplateDict(self):
446 if self._FileType not in self._SEP_:
447 EdkLogger.error("build
", PARAMETER_INVALID, "Invalid Makefile
type [%s]" % self._FileType,
448 ExtraData="[%s]" % str(self._AutoGenObject))
449 Separator = self._SEP_[self._FileType]
451 # break build if no source files and binary files are found
452 if len(self._AutoGenObject.SourceFileList) == 0 and len(self._AutoGenObject.BinaryFileList) == 0:
453 EdkLogger.error("build
", AUTOGEN_ERROR, "No files to be built
in module
[%s, %s, %s]"
454 % (self._AutoGenObject.BuildTarget, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch),
455 ExtraData="[%s]" % str(self._AutoGenObject))
457 # convert dependent libraries to build command
458 self.ProcessDependentLibrary()
459 if len(self._AutoGenObject.Module.ModuleEntryPointList) > 0:
460 ModuleEntryPoint = self._AutoGenObject.Module.ModuleEntryPointList[0]
462 ModuleEntryPoint = "_ModuleEntryPoint
"
464 # Intel EBC compiler enforces EfiMain
465 if self._AutoGenObject.AutoGenVersion < 0x00010005 and self._AutoGenObject.Arch == "EBC
":
466 ArchEntryPoint = "EfiMain
"
468 ArchEntryPoint = ModuleEntryPoint
470 if self._AutoGenObject.Arch == "EBC
":
471 # EBC compiler always use "EfiStart
" as entry point. Only applies to EdkII modules
472 ImageEntryPoint = "EfiStart
"
473 elif self._AutoGenObject.AutoGenVersion < 0x00010005:
474 # Edk modules use entry point specified in INF file
475 ImageEntryPoint = ModuleEntryPoint
477 # EdkII modules always use "_ModuleEntryPoint
" as entry point
478 ImageEntryPoint = "_ModuleEntryPoint
"
482 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
483 for Tool in self._AutoGenObject.BuildOption:
484 for Attr in self._AutoGenObject.BuildOption[Tool]:
485 Value = self._AutoGenObject.BuildOption[Tool][Attr]
489 ToolsDef.append("%s = %s" % (Tool, Value))
491 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
494 # Remove duplicated include path, if any
496 Value = RemoveDupOption(Value, IncPrefix, self._AutoGenObject.IncludePathList)
497 ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
500 # generate the Response file and Response flag
501 RespDict = self.CommandExceedLimit()
502 RespFileList = os.path.join(self._AutoGenObject.OutputDir, 'respfilelist.txt')
504 RespFileListContent = ''
505 for Resp in RespDict.keys():
506 RespFile = os.path.join(self._AutoGenObject.OutputDir, str(Resp).lower() + '.txt')
507 SaveFileOnChange(RespFile, RespDict[Resp], False)
508 ToolsDef.append("%s = %s" % (Resp, '@' + RespFile))
509 RespFileListContent += '@' + RespFile + os.linesep
510 RespFileListContent += RespDict[Resp] + os.linesep
511 SaveFileOnChange(RespFileList, RespFileListContent, False)
513 if os.path.exists(RespFileList):
514 os.remove(RespFileList)
516 # convert source files and binary files to build targets
517 self.ResultFileList = [str(T.Target) for T in self._AutoGenObject.CodaTargetList]
518 if len(self.ResultFileList) == 0 and len(self._AutoGenObject.SourceFileList) <> 0:
519 EdkLogger.error("build
", AUTOGEN_ERROR, "Nothing to build
",
520 ExtraData="[%s]" % str(self._AutoGenObject))
522 self.ProcessBuildTargetList()
524 # Generate macros used to represent input files
525 FileMacroList = [] # macro name = file list
526 for FileListMacro in self.FileListMacros:
527 FileMacro = self._FILE_MACRO_TEMPLATE.Replace(
529 "macro_name
" : FileListMacro,
530 "source_file
" : self.FileListMacros[FileListMacro]
533 FileMacroList.append(FileMacro)
535 # INC_LIST is special
538 for P in self._AutoGenObject.IncludePathList:
539 IncludePathList.append(IncPrefix + self.PlaceMacro(P, self.Macros))
540 if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:
541 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix + P)
542 FileMacro += self._FILE_MACRO_TEMPLATE.Replace(
544 "macro_name
" : "INC
",
545 "source_file
" : IncludePathList
548 FileMacroList.append(FileMacro)
550 # Generate macros used to represent files containing list of input files
551 for ListFileMacro in self.ListFileMacros:
552 ListFileName = os.path.join(self._AutoGenObject.OutputDir, "%s.lst
" % ListFileMacro.lower()[:len(ListFileMacro) - 5])
553 FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))
556 "\n".join(self.ListFileMacros[ListFileMacro]),
560 # Edk modules need <BaseName>StrDefs.h for string ID
561 #if self._AutoGenObject.AutoGenVersion < 0x00010005 and len(self._AutoGenObject.UnicodeFileList) > 0:
562 # BcTargetList = ['strdefs']
567 MakefileName = self._FILE_NAME_[self._FileType]
568 LibraryMakeCommandList = []
569 for D in self.LibraryBuildDirectoryList:
570 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)}
571 LibraryMakeCommandList.append(Command)
573 package_rel_dir = self._AutoGenObject.SourceDir
574 current_dir = self.Macros["WORKSPACE
"]
576 while not found and os.sep in package_rel_dir:
577 index = package_rel_dir.index(os.sep)
578 current_dir = mws.join(current_dir, package_rel_dir[:index])
579 for fl in os.listdir(current_dir):
580 if fl.endswith('.dec'):
583 package_rel_dir = package_rel_dir[index + 1:]
585 MakefileTemplateDict = {
586 "makefile_header
" : self._FILE_HEADER_[self._FileType],
587 "makefile_path
" : os.path.join("$
(MODULE_BUILD_DIR
)", MakefileName),
588 "makefile_name
" : MakefileName,
589 "platform_name
" : self.PlatformInfo.Name,
590 "platform_guid
" : self.PlatformInfo.Guid,
591 "platform_version
" : self.PlatformInfo.Version,
592 "platform_relative_directory
": self.PlatformInfo.SourceDir,
593 "platform_output_directory
" : self.PlatformInfo.OutputDir,
595 "module_name
" : self._AutoGenObject.Name,
596 "module_guid
" : self._AutoGenObject.Guid,
597 "module_name_guid
" : self._AutoGenObject._GetUniqueBaseName(),
598 "module_version
" : self._AutoGenObject.Version,
599 "module_type
" : self._AutoGenObject.ModuleType,
600 "module_file
" : self._AutoGenObject.MetaFile.Name,
601 "module_file_base_name
" : self._AutoGenObject.MetaFile.BaseName,
602 "module_relative_directory
" : self._AutoGenObject.SourceDir,
603 "module_dir
" : mws.join (self.Macros["WORKSPACE
"], self._AutoGenObject.SourceDir),
604 "package_relative_directory
": package_rel_dir,
605 "module_extra_defines
" : ["%s = %s" % (k, v) for k, v in self._AutoGenObject.Module.Defines.iteritems()],
607 "architecture
" : self._AutoGenObject.Arch,
608 "toolchain_tag
" : self._AutoGenObject.ToolChain,
609 "build_target
" : self._AutoGenObject.BuildTarget,
611 "platform_build_directory
" : self.PlatformInfo.BuildDir,
612 "module_build_directory
" : self._AutoGenObject.BuildDir,
613 "module_output_directory
" : self._AutoGenObject.OutputDir,
614 "module_debug_directory
" : self._AutoGenObject.DebugDir,
616 "separator
" : Separator,
617 "module_tool_definitions
" : ToolsDef,
619 "shell_command_code
" : self._SHELL_CMD_[self._FileType].keys(),
620 "shell_command
" : self._SHELL_CMD_[self._FileType].values(),
622 "module_entry_point
" : ModuleEntryPoint,
623 "image_entry_point
" : ImageEntryPoint,
624 "arch_entry_point
" : ArchEntryPoint,
625 "remaining_build_target
" : self.ResultFileList,
626 "common_dependency_file
" : self.CommonFileDependency,
627 "create_directory_command
" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
628 "clean_command
" : self.GetRemoveDirectoryCommand(["$
(OUTPUT_DIR
)"]),
629 "cleanall_command
" : self.GetRemoveDirectoryCommand(["$
(DEBUG_DIR
)", "$
(OUTPUT_DIR
)"]),
630 "dependent_library_build_directory
" : self.LibraryBuildDirectoryList,
631 "library_build_command
" : LibraryMakeCommandList,
632 "file_macro
" : FileMacroList,
633 "file_build_target
" : self.BuildTargetList,
634 "backward_compatible_target
": BcTargetList,
637 return MakefileTemplateDict
639 def CommandExceedLimit(self):
641 'CC' : { 'Macro' : '$(CC_FLAGS)', 'Value' : False},
642 'PP' : { 'Macro' : '$(PP_FLAGS)', 'Value' : False},
643 'APP' : { 'Macro' : '$(APP_FLAGS)', 'Value' : False},
644 'ASLPP' : { 'Macro' : '$(ASLPP_FLAGS)', 'Value' : False},
645 'VFRPP' : { 'Macro' : '$(VFRPP_FLAGS)', 'Value' : False},
646 'ASM' : { 'Macro' : '$(ASM_FLAGS)', 'Value' : False},
647 'ASLCC' : { 'Macro' : '$(ASLCC_FLAGS)', 'Value' : False},
652 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
654 # base on the source files to decide the file type
655 for File in self._AutoGenObject.SourceFileList:
656 for type in self._AutoGenObject.FileTypes:
657 if File in self._AutoGenObject.FileTypes[type]:
658 if type not in FileTypeList:
659 FileTypeList.append(type)
661 # calculate the command-line length
663 for type in FileTypeList:
664 BuildTargets = self._AutoGenObject.BuildRules[type].BuildTargets
665 for Target in BuildTargets:
666 CommandList = BuildTargets[Target].Commands
667 for SingleCommand in CommandList:
669 SingleCommandLength = len(SingleCommand)
670 SingleCommandList = SingleCommand.split()
671 if len(SingleCommandList) > 0:
672 for Flag in FlagDict.keys():
673 if '$('+ Flag +')' in SingleCommandList[0]:
677 SingleCommandLength += len(self._AutoGenObject._BuildOption[Tool]['PATH'])
678 for item in SingleCommandList[1:]:
679 if FlagDict[Tool]['Macro'] in item:
680 Str = self._AutoGenObject._BuildOption[Tool]['FLAGS']
681 while(Str.find('$(') != -1):
682 for macro in self._AutoGenObject.Macros.keys():
683 MacroName = '$('+ macro + ')'
684 if (Str.find(MacroName) != -1):
685 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
688 EdkLogger.error("build
", AUTOGEN_ERROR, "Not supported macro
is found
in make command
: %s" % Str, ExtraData="[%s]" % str(self._AutoGenObject))
689 SingleCommandLength += len(Str)
690 elif '$(INC)' in item:
691 SingleCommandLength += self._AutoGenObject.IncludePathLength + len(IncPrefix) * len(self._AutoGenObject._IncludePathList)
692 elif item.find('$(') != -1:
694 for Option in self._AutoGenObject.BuildOption.keys():
695 for Attr in self._AutoGenObject.BuildOption[Option]:
696 if Str.find(Option + '_' + Attr) != -1:
697 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
698 while(Str.find('$(') != -1):
699 for macro in self._AutoGenObject.Macros.keys():
700 MacroName = '$('+ macro + ')'
701 if (Str.find(MacroName) != -1):
702 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
705 EdkLogger.error("build
", AUTOGEN_ERROR, "Not supported macro
is found
in make command
: %s" % Str, ExtraData="[%s]" % str(self._AutoGenObject))
707 SingleCommandLength += len(Str)
709 if SingleCommandLength > GlobalData.gCommandMaxLength:
710 FlagDict[Tool]['Value'] = True
712 # generate the response file content by combine the FLAGS and INC
713 for Flag in FlagDict.keys():
714 if FlagDict[Flag]['Value']:
716 RespMacro = FlagDict[Flag]['Macro'].replace('FLAGS', 'RESP')
717 Value = self._AutoGenObject.BuildOption[Flag]['FLAGS']
718 for inc in self._AutoGenObject._IncludePathList:
719 Value += ' ' + IncPrefix + inc
720 while (Value.find('$(') != -1):
721 for macro in self._AutoGenObject.Macros.keys():
722 MacroName = '$('+ macro + ')'
723 if (Value.find(MacroName) != -1):
724 Value = Value.replace(MacroName, self._AutoGenObject.Macros[macro])
727 EdkLogger.error("build
", AUTOGEN_ERROR, "Not supported macro
is found
in make command
: %s" % Str, ExtraData="[%s]" % str(self._AutoGenObject))
728 RespDict[Key] = Value
729 for Target in BuildTargets:
730 for i, SingleCommand in enumerate(BuildTargets[Target].Commands):
731 if FlagDict[Flag]['Macro'] in SingleCommand:
732 BuildTargets[Target].Commands[i] = SingleCommand.replace('$(INC)','').replace(FlagDict[Flag]['Macro'], RespMacro)
735 def ProcessBuildTargetList(self):
737 # Search dependency file list for each source file
739 ForceIncludedFile = []
740 for File in self._AutoGenObject.AutoGenFileList:
742 ForceIncludedFile.append(File)
744 for Target in self._AutoGenObject.IntroTargetList:
745 SourceFileList.extend(Target.Inputs)
747 self.FileDependency = self.GetFileDependency(
750 self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList
753 for File in self.FileDependency:
754 if not self.FileDependency[File]:
755 self.FileDependency[File] = ['$(FORCE_REBUILD)']
758 if File.Ext not in [".c
", ".C
"] or File.Name == "AutoGen
.c
":
761 DepSet = set(self.FileDependency[File])
763 DepSet &= set(self.FileDependency[File])
764 # in case nothing in SourceFileList
768 # Extract common files list in the dependency files
771 self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros))
773 for File in self.FileDependency:
775 if File.Ext not in [".c
", ".C
"] or File.Name == "AutoGen
.c
":
777 NewDepSet = set(self.FileDependency[File])
779 self.FileDependency[File] = ["$
(COMMON_DEPS
)"] + list(NewDepSet)
781 # Convert target description object to target string in makefile
782 for Type in self._AutoGenObject.Targets:
783 for T in self._AutoGenObject.Targets[Type]:
784 # Generate related macros if needed
785 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
786 self.FileListMacros[T.FileListMacro] = []
787 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:
788 self.ListFileMacros[T.ListFileMacro] = []
789 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:
790 self.ListFileMacros[T.IncListFileMacro] = []
793 # Add force-dependencies
794 for Dep in T.Dependencies:
795 Deps.append(self.PlaceMacro(str(Dep), self.Macros))
796 # Add inclusion-dependencies
797 if len(T.Inputs) == 1 and T.Inputs[0] in self.FileDependency:
798 for F in self.FileDependency[T.Inputs[0]]:
799 Deps.append(self.PlaceMacro(str(F), self.Macros))
800 # Add source-dependencies
802 NewFile = self.PlaceMacro(str(F), self.Macros)
803 # In order to use file list macro as dependency
805 # gnu tools need forward slash path separater, even on Windows
806 self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/'))
807 self.FileListMacros[T.FileListMacro].append(NewFile)
808 elif T.GenFileListMacro:
809 self.FileListMacros[T.FileListMacro].append(NewFile)
813 # Use file list macro as dependency
814 if T.GenFileListMacro:
815 Deps.append("$
(%s)" % T.FileListMacro)
818 "target
" : self.PlaceMacro(T.Target.Path, self.Macros),
819 "cmd
" : "\n\t".join(T.Commands),
822 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
824 ## For creating makefile targets for dependent libraries
825 def ProcessDependentLibrary(self):
826 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
827 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
829 ## Return a list containing source file's dependencies
831 # @param FileList The list of source files
832 # @param ForceInculeList The list of files which will be included forcely
833 # @param SearchPathList The list of search path
835 # @retval dict The mapping between source file path and its dependencies
837 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
840 Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)
843 ## Find dependencies for one source file
845 # By searching recursively "#include" directive in file, find out all the
846 # files needed by given source file. The dependecies will be only searched
847 # in given search path list.
849 # @param File The source file
850 # @param ForceInculeList The list of files which will be included forcely
851 # @param SearchPathList The list of search path
853 # @retval list The list of files the given source file depends on
855 def GetDependencyList(self
, File
, ForceList
, SearchPathList
):
856 EdkLogger
.debug(EdkLogger
.DEBUG_1
, "Try to get dependency files for %s" % File
)
857 FileStack
= [File
] + ForceList
858 DependencySet
= set()
860 if self
._AutoGenObject
.Arch
not in gDependencyDatabase
:
861 gDependencyDatabase
[self
._AutoGenObject
.Arch
] = {}
862 DepDb
= gDependencyDatabase
[self
._AutoGenObject
.Arch
]
864 while len(FileStack
) > 0:
867 FullPathDependList
= []
868 if F
in self
.FileCache
:
869 for CacheFile
in self
.FileCache
[F
]:
870 FullPathDependList
.append(CacheFile
)
871 if CacheFile
not in DependencySet
:
872 FileStack
.append(CacheFile
)
873 DependencySet
.update(FullPathDependList
)
876 CurrentFileDependencyList
= []
878 CurrentFileDependencyList
= DepDb
[F
]
881 Fd
= open(F
.Path
, 'r')
882 except BaseException
, X
:
883 EdkLogger
.error("build", FILE_OPEN_FAILURE
, ExtraData
=F
.Path
+ "\n\t" + str(X
))
885 FileContent
= Fd
.read()
887 if len(FileContent
) == 0:
890 if FileContent
[0] == 0xff or FileContent
[0] == 0xfe:
891 FileContent
= unicode(FileContent
, "utf-16")
892 IncludedFileList
= gIncludePattern
.findall(FileContent
)
894 for Inc
in IncludedFileList
:
896 # if there's macro used to reference header file, expand it
897 HeaderList
= gMacroPattern
.findall(Inc
)
898 if len(HeaderList
) == 1 and len(HeaderList
[0]) == 2:
899 HeaderType
= HeaderList
[0][0]
900 HeaderKey
= HeaderList
[0][1]
901 if HeaderType
in gIncludeMacroConversion
:
902 Inc
= gIncludeMacroConversion
[HeaderType
] % {"HeaderKey" : HeaderKey
}
904 # not known macro used in #include, always build the file by
905 # returning a empty dependency
906 self
.FileCache
[File
] = []
908 Inc
= os
.path
.normpath(Inc
)
909 CurrentFileDependencyList
.append(Inc
)
910 DepDb
[F
] = CurrentFileDependencyList
912 CurrentFilePath
= F
.Dir
913 PathList
= [CurrentFilePath
] + SearchPathList
914 for Inc
in CurrentFileDependencyList
:
915 for SearchPath
in PathList
:
916 FilePath
= os
.path
.join(SearchPath
, Inc
)
917 if FilePath
in gIsFileMap
:
918 if not gIsFileMap
[FilePath
]:
920 # If isfile is called too many times, the performance is slow down.
921 elif not os
.path
.isfile(FilePath
):
922 gIsFileMap
[FilePath
] = False
925 gIsFileMap
[FilePath
] = True
926 FilePath
= PathClass(FilePath
)
927 FullPathDependList
.append(FilePath
)
928 if FilePath
not in DependencySet
:
929 FileStack
.append(FilePath
)
932 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "%s included by %s was not found "\
933 "in any given path:\n\t%s" % (Inc
, F
, "\n\t".join(SearchPathList
)))
935 self
.FileCache
[F
] = FullPathDependList
936 DependencySet
.update(FullPathDependList
)
938 DependencySet
.update(ForceList
)
939 if File
in DependencySet
:
940 DependencySet
.remove(File
)
941 DependencyList
= list(DependencySet
) # remove duplicate ones
943 return DependencyList
945 _TemplateDict
= property(_CreateTemplateDict
)
947 ## CustomMakefile class
949 # This class encapsules makefie and its generation for module. It uses template to generate
950 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
952 class CustomMakefile(BuildFile
):
953 ## template used to generate the makefile for module with custom makefile
954 _TEMPLATE_
= TemplateString('''\
958 # Platform Macro Definition
960 PLATFORM_NAME = ${platform_name}
961 PLATFORM_GUID = ${platform_guid}
962 PLATFORM_VERSION = ${platform_version}
963 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
964 PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}
965 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
968 # Module Macro Definition
970 MODULE_NAME = ${module_name}
971 MODULE_GUID = ${module_guid}
972 MODULE_NAME_GUID = ${module_name_guid}
973 MODULE_VERSION = ${module_version}
974 MODULE_TYPE = ${module_type}
975 MODULE_FILE = ${module_file}
976 MODULE_FILE_BASE_NAME = ${module_file_base_name}
977 BASE_NAME = $(MODULE_NAME)
978 MODULE_RELATIVE_DIR = ${module_relative_directory}
979 MODULE_DIR = ${module_dir}
982 # Build Configuration Macro Definition
984 ARCH = ${architecture}
985 TOOLCHAIN = ${toolchain_tag}
986 TOOLCHAIN_TAG = ${toolchain_tag}
987 TARGET = ${build_target}
990 # Build Directory Macro Definition
992 # PLATFORM_BUILD_DIR = ${platform_build_directory}
993 BUILD_DIR = ${platform_build_directory}
994 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
996 MODULE_BUILD_DIR = ${module_build_directory}
997 OUTPUT_DIR = ${module_output_directory}
998 DEBUG_DIR = ${module_debug_directory}
999 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
1000 DEST_DIR_DEBUG = $(DEBUG_DIR)
1003 # Tools definitions specific to this module
1005 ${BEGIN}${module_tool_definitions}
1007 MAKE_FILE = ${makefile_path}
1010 # Shell Command Macro
1012 ${BEGIN}${shell_command_code} = ${shell_command}
1015 ${custom_makefile_content}
1018 # Target used when called from platform makefile, which will bypass the build of dependent libraries
1031 # Build Target used in multi-thread build mode, which no init target is needed
1037 # Initialization target: print build information and create necessary directories
1040 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
1041 ${BEGIN}\t-@${create_directory_command}\n${END}\
1045 ## Constructor of CustomMakefile
1047 # @param ModuleAutoGen Object of ModuleAutoGen class
1049 def __init__(self
, ModuleAutoGen
):
1050 BuildFile
.__init
__(self
, ModuleAutoGen
)
1051 self
.PlatformInfo
= self
._AutoGenObject
.PlatformInfo
1052 self
.IntermediateDirectoryList
= ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
1054 # Compose a dict object containing information used to do replacement in template
1055 def _CreateTemplateDict(self
):
1056 Separator
= self
._SEP
_[self
._FileType
]
1057 if self
._FileType
not in self
._AutoGenObject
.CustomMakefile
:
1058 EdkLogger
.error('build', OPTION_NOT_SUPPORTED
, "No custom makefile for %s" % self
._FileType
,
1059 ExtraData
="[%s]" % str(self
._AutoGenObject
))
1060 MakefilePath
= mws
.join(
1061 self
._AutoGenObject
.WorkspaceDir
,
1062 self
._AutoGenObject
.CustomMakefile
[self
._FileType
]
1065 CustomMakefile
= open(MakefilePath
, 'r').read()
1067 EdkLogger
.error('build', FILE_OPEN_FAILURE
, File
=str(self
._AutoGenObject
),
1068 ExtraData
=self
._AutoGenObject
.CustomMakefile
[self
._FileType
])
1072 for Tool
in self
._AutoGenObject
.BuildOption
:
1073 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
1076 for Attr
in self
._AutoGenObject
.BuildOption
[Tool
]:
1077 if Attr
== "FAMILY":
1079 elif Attr
== "PATH":
1080 ToolsDef
.append("%s = %s" % (Tool
, self
._AutoGenObject
.BuildOption
[Tool
][Attr
]))
1082 ToolsDef
.append("%s_%s = %s" % (Tool
, Attr
, self
._AutoGenObject
.BuildOption
[Tool
][Attr
]))
1085 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1086 MakefileTemplateDict
= {
1087 "makefile_header" : self
._FILE
_HEADER
_[self
._FileType
],
1088 "makefile_path" : os
.path
.join("$(MODULE_BUILD_DIR)", MakefileName
),
1089 "platform_name" : self
.PlatformInfo
.Name
,
1090 "platform_guid" : self
.PlatformInfo
.Guid
,
1091 "platform_version" : self
.PlatformInfo
.Version
,
1092 "platform_relative_directory": self
.PlatformInfo
.SourceDir
,
1093 "platform_output_directory" : self
.PlatformInfo
.OutputDir
,
1095 "module_name" : self
._AutoGenObject
.Name
,
1096 "module_guid" : self
._AutoGenObject
.Guid
,
1097 "module_name_guid" : self
._AutoGenObject
._GetUniqueBaseName
(),
1098 "module_version" : self
._AutoGenObject
.Version
,
1099 "module_type" : self
._AutoGenObject
.ModuleType
,
1100 "module_file" : self
._AutoGenObject
.MetaFile
,
1101 "module_file_base_name" : self
._AutoGenObject
.MetaFile
.BaseName
,
1102 "module_relative_directory" : self
._AutoGenObject
.SourceDir
,
1103 "module_dir" : mws
.join (self
._AutoGenObject
.WorkspaceDir
, self
._AutoGenObject
.SourceDir
),
1105 "architecture" : self
._AutoGenObject
.Arch
,
1106 "toolchain_tag" : self
._AutoGenObject
.ToolChain
,
1107 "build_target" : self
._AutoGenObject
.BuildTarget
,
1109 "platform_build_directory" : self
.PlatformInfo
.BuildDir
,
1110 "module_build_directory" : self
._AutoGenObject
.BuildDir
,
1111 "module_output_directory" : self
._AutoGenObject
.OutputDir
,
1112 "module_debug_directory" : self
._AutoGenObject
.DebugDir
,
1114 "separator" : Separator
,
1115 "module_tool_definitions" : ToolsDef
,
1117 "shell_command_code" : self
._SHELL
_CMD
_[self
._FileType
].keys(),
1118 "shell_command" : self
._SHELL
_CMD
_[self
._FileType
].values(),
1120 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1121 "custom_makefile_content" : CustomMakefile
1124 return MakefileTemplateDict
1126 _TemplateDict
= property(_CreateTemplateDict
)
1128 ## PlatformMakefile class
1130 # This class encapsules makefie and its generation for platform. It uses
1131 # template to generate the content of makefile. The content of makefile will be
1132 # got from PlatformAutoGen object.
1134 class PlatformMakefile(BuildFile
):
1135 ## template used to generate the makefile for platform
1136 _TEMPLATE_
= TemplateString('''\
1140 # Platform Macro Definition
1142 PLATFORM_NAME = ${platform_name}
1143 PLATFORM_GUID = ${platform_guid}
1144 PLATFORM_VERSION = ${platform_version}
1145 PLATFORM_FILE = ${platform_file}
1146 PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}
1147 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1150 # Build Configuration Macro Definition
1152 TOOLCHAIN = ${toolchain_tag}
1153 TOOLCHAIN_TAG = ${toolchain_tag}
1154 TARGET = ${build_target}
1157 # Build Directory Macro Definition
1159 BUILD_DIR = ${platform_build_directory}
1160 FV_DIR = ${platform_build_directory}${separator}FV
1163 # Shell Command Macro
1165 ${BEGIN}${shell_command_code} = ${shell_command}
1169 MAKE_FILE = ${makefile_path}
1174 all: init build_libraries build_modules
1177 # Initialization target: print build information and create necessary directories
1180 \t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
1181 \t${BEGIN}-@${create_directory_command}
1184 # library build target
1186 libraries: init build_libraries
1189 # module build target
1191 modules: init build_libraries build_modules
1194 # Build all libraries:
1197 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
1198 ${END}\t@cd $(BUILD_DIR)
1201 # Build all modules:
1204 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
1205 ${END}\t@cd $(BUILD_DIR)
1208 # Clean intermediate files
1211 \t${BEGIN}-@${library_build_command} clean
1212 \t${END}${BEGIN}-@${module_build_command} clean
1213 \t${END}@cd $(BUILD_DIR)
1216 # Clean all generated files except to makefile
1219 ${BEGIN}\t${cleanall_command}
1223 # Clean all library files
1226 \t${BEGIN}-@${library_build_command} cleanall
1227 \t${END}@cd $(BUILD_DIR)\n
1230 ## Constructor of PlatformMakefile
1232 # @param ModuleAutoGen Object of PlatformAutoGen class
1234 def __init__(self
, PlatformAutoGen
):
1235 BuildFile
.__init
__(self
, PlatformAutoGen
)
1236 self
.ModuleBuildCommandList
= []
1237 self
.ModuleMakefileList
= []
1238 self
.IntermediateDirectoryList
= []
1239 self
.ModuleBuildDirectoryList
= []
1240 self
.LibraryBuildDirectoryList
= []
1241 self
.LibraryMakeCommandList
= []
1243 # Compose a dict object containing information used to do replacement in template
1244 def _CreateTemplateDict(self
):
1245 Separator
= self
._SEP
_[self
._FileType
]
1247 PlatformInfo
= self
._AutoGenObject
1248 if "MAKE" not in PlatformInfo
.ToolDefinition
or "PATH" not in PlatformInfo
.ToolDefinition
["MAKE"]:
1249 EdkLogger
.error("build", OPTION_MISSING
, "No MAKE command defined. Please check your tools_def.txt!",
1250 ExtraData
="[%s]" % str(self
._AutoGenObject
))
1252 self
.IntermediateDirectoryList
= ["$(BUILD_DIR)"]
1253 self
.ModuleBuildDirectoryList
= self
.GetModuleBuildDirectoryList()
1254 self
.LibraryBuildDirectoryList
= self
.GetLibraryBuildDirectoryList()
1256 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1257 LibraryMakefileList
= []
1258 LibraryMakeCommandList
= []
1259 for D
in self
.LibraryBuildDirectoryList
:
1260 D
= self
.PlaceMacro(D
, {"BUILD_DIR":PlatformInfo
.BuildDir
})
1261 Makefile
= os
.path
.join(D
, MakefileName
)
1262 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":Makefile
}
1263 LibraryMakefileList
.append(Makefile
)
1264 LibraryMakeCommandList
.append(Command
)
1265 self
.LibraryMakeCommandList
= LibraryMakeCommandList
1267 ModuleMakefileList
= []
1268 ModuleMakeCommandList
= []
1269 for D
in self
.ModuleBuildDirectoryList
:
1270 D
= self
.PlaceMacro(D
, {"BUILD_DIR":PlatformInfo
.BuildDir
})
1271 Makefile
= os
.path
.join(D
, MakefileName
)
1272 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":Makefile
}
1273 ModuleMakefileList
.append(Makefile
)
1274 ModuleMakeCommandList
.append(Command
)
1276 MakefileTemplateDict
= {
1277 "makefile_header" : self
._FILE
_HEADER
_[self
._FileType
],
1278 "makefile_path" : os
.path
.join("$(BUILD_DIR)", MakefileName
),
1279 "make_path" : PlatformInfo
.ToolDefinition
["MAKE"]["PATH"],
1280 "makefile_name" : MakefileName
,
1281 "platform_name" : PlatformInfo
.Name
,
1282 "platform_guid" : PlatformInfo
.Guid
,
1283 "platform_version" : PlatformInfo
.Version
,
1284 "platform_file" : self
._AutoGenObject
.MetaFile
,
1285 "platform_relative_directory": PlatformInfo
.SourceDir
,
1286 "platform_output_directory" : PlatformInfo
.OutputDir
,
1287 "platform_build_directory" : PlatformInfo
.BuildDir
,
1289 "toolchain_tag" : PlatformInfo
.ToolChain
,
1290 "build_target" : PlatformInfo
.BuildTarget
,
1291 "shell_command_code" : self
._SHELL
_CMD
_[self
._FileType
].keys(),
1292 "shell_command" : self
._SHELL
_CMD
_[self
._FileType
].values(),
1293 "build_architecture_list" : self
._AutoGenObject
.Arch
,
1294 "architecture" : self
._AutoGenObject
.Arch
,
1295 "separator" : Separator
,
1296 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1297 "cleanall_command" : self
.GetRemoveDirectoryCommand(self
.IntermediateDirectoryList
),
1298 "library_makefile_list" : LibraryMakefileList
,
1299 "module_makefile_list" : ModuleMakefileList
,
1300 "library_build_command" : LibraryMakeCommandList
,
1301 "module_build_command" : ModuleMakeCommandList
,
1304 return MakefileTemplateDict
1306 ## Get the root directory list for intermediate files of all modules build
1308 # @retval list The list of directory
1310 def GetModuleBuildDirectoryList(self
):
1312 for ModuleAutoGen
in self
._AutoGenObject
.ModuleAutoGenList
:
1313 if not ModuleAutoGen
.IsBinaryModule
:
1314 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, ModuleAutoGen
.BuildDir
))
1317 ## Get the root directory list for intermediate files of all libraries build
1319 # @retval list The list of directory
1321 def GetLibraryBuildDirectoryList(self
):
1323 for LibraryAutoGen
in self
._AutoGenObject
.LibraryAutoGenList
:
1324 if not LibraryAutoGen
.IsBinaryModule
:
1325 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, LibraryAutoGen
.BuildDir
))
1328 _TemplateDict
= property(_CreateTemplateDict
)
1330 ## TopLevelMakefile class
1332 # This class encapsules makefie and its generation for entrance makefile. It
1333 # uses template to generate the content of makefile. The content of makefile
1334 # will be got from WorkspaceAutoGen object.
1336 class TopLevelMakefile(BuildFile
):
1337 ## template used to generate toplevel makefile
1338 _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}''')
1340 ## Constructor of TopLevelMakefile
1342 # @param Workspace Object of WorkspaceAutoGen class
1344 def __init__(self
, Workspace
):
1345 BuildFile
.__init
__(self
, Workspace
)
1346 self
.IntermediateDirectoryList
= []
1348 # Compose a dict object containing information used to do replacement in template
1349 def _CreateTemplateDict(self
):
1350 Separator
= self
._SEP
_[self
._FileType
]
1352 # any platform autogen object is ok because we just need common information
1353 PlatformInfo
= self
._AutoGenObject
1355 if "MAKE" not in PlatformInfo
.ToolDefinition
or "PATH" not in PlatformInfo
.ToolDefinition
["MAKE"]:
1356 EdkLogger
.error("build", OPTION_MISSING
, "No MAKE command defined. Please check your tools_def.txt!",
1357 ExtraData
="[%s]" % str(self
._AutoGenObject
))
1359 for Arch
in PlatformInfo
.ArchList
:
1360 self
.IntermediateDirectoryList
.append(Separator
.join(["$(BUILD_DIR)", Arch
]))
1361 self
.IntermediateDirectoryList
.append("$(FV_DIR)")
1363 # TRICK: for not generating GenFds call in makefile if no FDF file
1365 if PlatformInfo
.FdfFile
!= None and PlatformInfo
.FdfFile
!= "":
1366 FdfFileList
= [PlatformInfo
.FdfFile
]
1367 # macros passed to GenFds
1368 MacroList
.append('"%s=%s"' % ("EFI_SOURCE", GlobalData
.gEfiSource
.replace('\\', '\\\\')))
1369 MacroList
.append('"%s=%s"' % ("EDK_SOURCE", GlobalData
.gEdkSource
.replace('\\', '\\\\')))
1371 MacroDict
.update(GlobalData
.gGlobalDefines
)
1372 MacroDict
.update(GlobalData
.gCommandLineDefines
)
1373 MacroDict
.pop("EFI_SOURCE", "dummy")
1374 MacroDict
.pop("EDK_SOURCE", "dummy")
1375 for MacroName
in MacroDict
:
1376 if MacroDict
[MacroName
] != "":
1377 MacroList
.append('"%s=%s"' % (MacroName
, MacroDict
[MacroName
].replace('\\', '\\\\')))
1379 MacroList
.append('"%s"' % MacroName
)
1383 # pass extra common options to external program called in makefile, currently GenFds.exe
1385 LogLevel
= EdkLogger
.GetLevel()
1386 if LogLevel
== EdkLogger
.VERBOSE
:
1387 ExtraOption
+= " -v"
1388 elif LogLevel
<= EdkLogger
.DEBUG_9
:
1389 ExtraOption
+= " -d %d" % (LogLevel
- 1)
1390 elif LogLevel
== EdkLogger
.QUIET
:
1391 ExtraOption
+= " -q"
1393 if GlobalData
.gCaseInsensitive
:
1394 ExtraOption
+= " -c"
1396 if GlobalData
.gIgnoreSource
:
1397 ExtraOption
+= " --ignore-sources"
1399 MakefileName
= self
._FILE
_NAME
_[self
._FileType
]
1400 SubBuildCommandList
= []
1401 for A
in PlatformInfo
.ArchList
:
1402 Command
= self
._MAKE
_TEMPLATE
_[self
._FileType
] % {"file":os
.path
.join("$(BUILD_DIR)", A
, MakefileName
)}
1403 SubBuildCommandList
.append(Command
)
1405 MakefileTemplateDict
= {
1406 "makefile_header" : self
._FILE
_HEADER
_[self
._FileType
],
1407 "makefile_path" : os
.path
.join("$(BUILD_DIR)", MakefileName
),
1408 "make_path" : PlatformInfo
.ToolDefinition
["MAKE"]["PATH"],
1409 "platform_name" : PlatformInfo
.Name
,
1410 "platform_guid" : PlatformInfo
.Guid
,
1411 "platform_version" : PlatformInfo
.Version
,
1412 "platform_build_directory" : PlatformInfo
.BuildDir
,
1413 "conf_directory" : GlobalData
.gConfDirectory
,
1415 "toolchain_tag" : PlatformInfo
.ToolChain
,
1416 "build_target" : PlatformInfo
.BuildTarget
,
1417 "shell_command_code" : self
._SHELL
_CMD
_[self
._FileType
].keys(),
1418 "shell_command" : self
._SHELL
_CMD
_[self
._FileType
].values(),
1419 'arch' : list(PlatformInfo
.ArchList
),
1420 "build_architecture_list" : ','.join(PlatformInfo
.ArchList
),
1421 "separator" : Separator
,
1422 "create_directory_command" : self
.GetCreateDirectoryCommand(self
.IntermediateDirectoryList
),
1423 "cleanall_command" : self
.GetRemoveDirectoryCommand(self
.IntermediateDirectoryList
),
1424 "sub_build_command" : SubBuildCommandList
,
1425 "fdf_file" : FdfFileList
,
1426 "active_platform" : str(PlatformInfo
),
1427 "fd" : PlatformInfo
.FdTargetList
,
1428 "fv" : PlatformInfo
.FvTargetList
,
1429 "cap" : PlatformInfo
.CapTargetList
,
1430 "extra_options" : ExtraOption
,
1431 "macro" : MacroList
,
1434 return MakefileTemplateDict
1436 ## Get the root directory list for intermediate files of all modules build
1438 # @retval list The list of directory
1440 def GetModuleBuildDirectoryList(self
):
1442 for ModuleAutoGen
in self
._AutoGenObject
.ModuleAutoGenList
:
1443 if not ModuleAutoGen
.IsBinaryModule
:
1444 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, ModuleAutoGen
.BuildDir
))
1447 ## Get the root directory list for intermediate files of all libraries build
1449 # @retval list The list of directory
1451 def GetLibraryBuildDirectoryList(self
):
1453 for LibraryAutoGen
in self
._AutoGenObject
.LibraryAutoGenList
:
1454 if not LibraryAutoGen
.IsBinaryModule
:
1455 DirList
.append(os
.path
.join(self
._AutoGenObject
.BuildDir
, LibraryAutoGen
.BuildDir
))
1458 _TemplateDict
= property(_CreateTemplateDict
)
1460 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1461 if __name__
== '__main__':