2 # Create makefile for MS nmake and GNU make
4 # Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>
5 # Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
11 from __future__
import absolute_import
12 import Common
.LongFilePathOs
as os
16 import os
.path
as path
17 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
18 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
19 from Common
.BuildToolError
import *
20 from Common
.Misc
import *
21 from Common
.StringUtils
import *
22 from .BuildEngine
import *
23 import Common
.GlobalData
as GlobalData
24 from collections
import OrderedDict
25 from Common
.DataType
import TAB_COMPILER_MSFT
27 ## Regular expression for finding header file inclusions
28 gIncludePattern
= re
.compile(r
"^[ \t]*[#%]?[ \t]*include(?:[ \t]*(?:\\(?:\r\n|\r|\n))*[ \t]*)*(?:\(?[\"<]?
[ \t]*)([-\w
.\\/() \t]+)(?
:[ \t]*[\">]?\
)?
)", re.MULTILINE | re.UNICODE | re.IGNORECASE)
30 ## Regular expression for matching macro used in header file inclusion
31 gMacroPattern = re.compile("([_A
-Z
][_A
-Z0
-9]*)[ \t]*\
((.+)\
)", re.UNICODE)
35 ## pattern for include style in Edk.x code
36 gProtocolDefinition = "Protocol
/%(HeaderKey)s/%(HeaderKey)s.h
"
37 gGuidDefinition = "Guid
/%(HeaderKey)s/%(HeaderKey)s.h
"
38 gArchProtocolDefinition = "ArchProtocol
/%(HeaderKey)s/%(HeaderKey)s.h
"
39 gPpiDefinition = "Ppi
/%(HeaderKey)s/%(HeaderKey)s.h
"
40 gIncludeMacroConversion = {
41 "EFI_PROTOCOL_DEFINITION
" : gProtocolDefinition,
42 "EFI_GUID_DEFINITION
" : gGuidDefinition,
43 "EFI_ARCH_PROTOCOL_DEFINITION
" : gArchProtocolDefinition,
44 "EFI_PROTOCOL_PRODUCER
" : gProtocolDefinition,
45 "EFI_PROTOCOL_CONSUMER
" : gProtocolDefinition,
46 "EFI_PROTOCOL_DEPENDENCY
" : gProtocolDefinition,
47 "EFI_ARCH_PROTOCOL_PRODUCER
" : gArchProtocolDefinition,
48 "EFI_ARCH_PROTOCOL_CONSUMER
" : gArchProtocolDefinition,
49 "EFI_ARCH_PROTOCOL_DEPENDENCY
" : gArchProtocolDefinition,
50 "EFI_PPI_DEFINITION
" : gPpiDefinition,
51 "EFI_PPI_PRODUCER
" : gPpiDefinition,
52 "EFI_PPI_CONSUMER
" : gPpiDefinition,
53 "EFI_PPI_DEPENDENCY
" : gPpiDefinition,
56 NMAKE_FILETYPE = "nmake
"
57 GMAKE_FILETYPE = "gmake
"
58 WIN32_PLATFORM = "win32
"
59 POSIX_PLATFORM = "posix
"
63 # This base class encapsules build file and its generation. It uses template to generate
64 # the content of build file. The content of build file will be got from AutoGen objects.
66 class BuildFile(object):
67 ## template used to generate the build file (i.e. makefile if using make)
68 _TEMPLATE_ = TemplateString('')
70 _DEFAULT_FILE_NAME_ = "Makefile
"
72 ## default file name for each type of build file
74 NMAKE_FILETYPE : "Makefile
",
75 GMAKE_FILETYPE : "GNUmakefile
"
79 def getMakefileName(self):
80 if not self._FileType:
81 return self._DEFAULT_FILE_NAME_
83 return self._FILE_NAME_[self._FileType]
85 ## Fixed header string for makefile
86 _MAKEFILE_HEADER = '''#
88 # This file is auto-generated by build utility
96 # Auto-generated makefile for building modules, libraries or platform
100 ## Header string for each type of build file
102 NMAKE_FILETYPE : _MAKEFILE_HEADER % _FILE_NAME_[NMAKE_FILETYPE],
103 GMAKE_FILETYPE : _MAKEFILE_HEADER % _FILE_NAME_[GMAKE_FILETYPE]
106 ## shell commands which can be used in build file in the form of macro
107 # $(CP) copy file command
108 # $(MV) move file command
109 # $(RM) remove file command
110 # $(MD) create dir command
111 # $(RD) remove dir command
119 "RD
" : "rmdir
/s
/q
",
131 ## directory separator
133 WIN32_PLATFORM : "\\",
137 ## directory creation template
139 WIN32_PLATFORM : 'if not exist %(dir)s $(MD) %(dir)s',
140 POSIX_PLATFORM : "$
(MD
) %(dir)s"
143 ## directory removal template
145 WIN32_PLATFORM : 'if exist %(dir)s $(RD) %(dir)s',
146 POSIX_PLATFORM : "$
(RD
) %(dir)s"
150 WIN32_PLATFORM : 'if exist %(Src)s $(CP) %(Src)s %(Dst)s',
151 POSIX_PLATFORM : "test
-f
%(Src)s && $
(CP
) %(Src)s %(Dst)s"
155 WIN32_PLATFORM : 'if exist %(dir)s cd %(dir)s',
156 POSIX_PLATFORM : "test
-e
%(dir)s && cd
%(dir)s"
160 WIN32_PLATFORM : 'if exist %(file)s "$
(MAKE
)" $(MAKE_FLAGS) -f %(file)s',
161 POSIX_PLATFORM : 'test -e %(file)s && "$
(MAKE
)" $(MAKE_FLAGS) -f %(file)s'
165 NMAKE_FILETYPE : '!INCLUDE',
166 GMAKE_FILETYPE : "include
"
169 _INC_FLAG_ = {TAB_COMPILER_MSFT : "/I
", "GCC
" : "-I
", "INTEL
" : "-I
", "RVCT
" : "-I
", "NASM
" : "-I
"}
171 ## Constructor of BuildFile
173 # @param AutoGenObject Object of AutoGen class
175 def __init__(self, AutoGenObject):
176 self._AutoGenObject = AutoGenObject
178 MakePath = AutoGenObject.BuildOption.get('MAKE', {}).get('PATH')
181 elif "nmake
" in MakePath:
182 self._FileType = NMAKE_FILETYPE
184 self._FileType = "gmake
"
186 if sys.platform == "win32
":
187 self._Platform = WIN32_PLATFORM
189 self._Platform = POSIX_PLATFORM
191 ## Create build file.
193 # Only nmake and gmake are supported.
195 # @retval TRUE The build file is created or re-created successfully.
196 # @retval FALSE The build file exists and is the same as the one to be generated.
199 FileContent = self._TEMPLATE_.Replace(self._TemplateDict)
200 FileName = self.getMakefileName()
201 if not os.path.exists(os.path.join(self._AutoGenObject.MakeFileDir, "deps
.txt
")):
202 with open(os.path.join(self._AutoGenObject.MakeFileDir, "deps
.txt
"),"w
+") as fd:
204 if not os.path.exists(os.path.join(self._AutoGenObject.MakeFileDir, "dependency
")):
205 with open(os.path.join(self._AutoGenObject.MakeFileDir, "dependency
"),"w
+") as fd:
207 if not os.path.exists(os.path.join(self._AutoGenObject.MakeFileDir, "deps_target
")):
208 with open(os.path.join(self._AutoGenObject.MakeFileDir, "deps_target
"),"w
+") as fd:
210 return SaveFileOnChange(os.path.join(self._AutoGenObject.MakeFileDir, FileName), FileContent, False)
212 ## Return a list of directory creation command string
214 # @param DirList The list of directory to be created
216 # @retval list The directory creation command list
218 def GetCreateDirectoryCommand(self, DirList):
219 return [self._MD_TEMPLATE_[self._Platform] % {'dir':Dir} for Dir in DirList]
221 ## Return a list of directory removal command string
223 # @param DirList The list of directory to be removed
225 # @retval list The directory removal command list
227 def GetRemoveDirectoryCommand(self, DirList):
228 return [self._RD_TEMPLATE_[self._Platform] % {'dir':Dir} for Dir in DirList]
230 def PlaceMacro(self, Path, MacroDefinitions=None):
231 if Path.startswith("$
("):
234 if MacroDefinitions is None:
235 MacroDefinitions = {}
236 PathLength = len(Path)
237 for MacroName in MacroDefinitions:
238 MacroValue = MacroDefinitions[MacroName]
239 MacroValueLength = len(MacroValue)
240 if MacroValueLength == 0:
242 if MacroValueLength <= PathLength and Path.startswith(MacroValue):
243 Path = "$
(%s)%s" % (MacroName, Path[MacroValueLength:])
247 ## ModuleMakefile class
249 # This class encapsules makefie and its generation for module. It uses template to generate
250 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
252 class ModuleMakefile(BuildFile):
253 ## template used to generate the makefile for module
254 _TEMPLATE_ = TemplateString('''\
258 # Platform Macro Definition
260 PLATFORM_NAME = ${platform_name}
261 PLATFORM_GUID = ${platform_guid}
262 PLATFORM_VERSION = ${platform_version}
263 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
264 PLATFORM_DIR = ${platform_dir}
265 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
268 # Module Macro Definition
270 MODULE_NAME = ${module_name}
271 MODULE_GUID = ${module_guid}
272 MODULE_NAME_GUID = ${module_name_guid}
273 MODULE_VERSION = ${module_version}
274 MODULE_TYPE = ${module_type}
275 MODULE_FILE = ${module_file}
276 MODULE_FILE_BASE_NAME = ${module_file_base_name}
277 BASE_NAME = $(MODULE_NAME)
278 MODULE_RELATIVE_DIR = ${module_relative_directory}
279 PACKAGE_RELATIVE_DIR = ${package_relative_directory}
280 MODULE_DIR = ${module_dir}
281 FFS_OUTPUT_DIR = ${ffs_output_directory}
283 MODULE_ENTRY_POINT = ${module_entry_point}
284 ARCH_ENTRY_POINT = ${arch_entry_point}
285 IMAGE_ENTRY_POINT = ${image_entry_point}
287 ${BEGIN}${module_extra_defines}
290 # Build Configuration Macro Definition
292 ARCH = ${architecture}
293 TOOLCHAIN = ${toolchain_tag}
294 TOOLCHAIN_TAG = ${toolchain_tag}
295 TARGET = ${build_target}
298 # Build Directory Macro Definition
300 # PLATFORM_BUILD_DIR = ${platform_build_directory}
301 BUILD_DIR = ${platform_build_directory}
302 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
304 MODULE_BUILD_DIR = ${module_build_directory}
305 OUTPUT_DIR = ${module_output_directory}
306 DEBUG_DIR = ${module_debug_directory}
307 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
308 DEST_DIR_DEBUG = $(DEBUG_DIR)
311 # Shell Command Macro
313 ${BEGIN}${shell_command_code} = ${shell_command}
317 # Tools definitions specific to this module
319 ${BEGIN}${module_tool_definitions}
321 MAKE_FILE = ${makefile_path}
326 ${BEGIN}${file_macro}
330 # Overridable Target Macro Definitions
332 FORCE_REBUILD = force_build
335 BC_TARGET = ${BEGIN}${backward_compatible_target} ${END}
336 CODA_TARGET = ${BEGIN}${remaining_build_target} \\
340 # Default target, which will build dependent libraries in addition to source files
347 # Target used when called from platform makefile, which will bypass the build of dependent libraries
350 pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
356 mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET)
359 # Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets
362 tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
365 # Phony target which is used to force executing commands for a target
371 # Target to update the FD
377 # Initialization target: print build information and create necessary directories
382 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
385 ${BEGIN}\t-@${create_directory_command}\n${END}
388 \t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h
394 \t${BEGIN}@"$
(MAKE
)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name}
395 \t${END}@cd $(MODULE_BUILD_DIR)
398 # Build Flash Device Image
401 \t@"$
(MAKE
)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds
402 \t@cd $(MODULE_BUILD_DIR)
407 # Individual Object Build Targets
409 ${BEGIN}${file_build_target}
413 # clean all intermediate files
416 \t${BEGIN}${clean_command}
417 \t${END}\t$(RM) AutoGenTimeStamp
420 # clean all generated files
423 ${BEGIN}\t${cleanall_command}
424 ${END}\t$(RM) *.pdb *.idb > NUL 2>&1
425 \t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi
426 \t$(RM) AutoGenTimeStamp
429 # clean all dependent libraries built
432 \t${BEGIN}-@${library_build_command} cleanall
433 \t${END}@cd $(MODULE_BUILD_DIR)\n\n''')
435 _FILE_MACRO_TEMPLATE = TemplateString("${macro_name}
= ${BEGIN}
\\\n ${source_file}${END}
\n")
436 _BUILD_TARGET_TEMPLATE = TemplateString("${BEGIN}${target}
: ${deps}
\n${END}
\t${cmd}
\n")
438 ## Constructor of ModuleMakefile
440 # @param ModuleAutoGen Object of ModuleAutoGen class
442 def __init__(self, ModuleAutoGen):
443 BuildFile.__init__(self, ModuleAutoGen)
444 self.PlatformInfo = self._AutoGenObject.PlatformInfo
446 self.ResultFileList = []
447 self.IntermediateDirectoryList = ["$
(DEBUG_DIR
)", "$
(OUTPUT_DIR
)"]
449 self.FileBuildTargetList = [] # [(src, target string)]
450 self.BuildTargetList = [] # [target string]
451 self.PendingBuildTargetList = [] # [FileBuildRule objects]
452 self.CommonFileDependency = []
453 self.FileListMacros = {}
454 self.ListFileMacros = {}
455 self.ObjTargetDict = OrderedDict()
457 self.LibraryBuildCommandList = []
458 self.LibraryFileList = []
459 self.LibraryMakefileList = []
460 self.LibraryBuildDirectoryList = []
461 self.SystemLibraryList = []
462 self.Macros = OrderedDict()
463 self.Macros["OUTPUT_DIR
" ] = self._AutoGenObject.Macros["OUTPUT_DIR
"]
464 self.Macros["DEBUG_DIR
" ] = self._AutoGenObject.Macros["DEBUG_DIR
"]
465 self.Macros["MODULE_BUILD_DIR
"] = self._AutoGenObject.Macros["MODULE_BUILD_DIR
"]
466 self.Macros["BIN_DIR
" ] = self._AutoGenObject.Macros["BIN_DIR
"]
467 self.Macros["BUILD_DIR
" ] = self._AutoGenObject.Macros["BUILD_DIR
"]
468 self.Macros["WORKSPACE
" ] = self._AutoGenObject.Macros["WORKSPACE
"]
469 self.Macros["FFS_OUTPUT_DIR
" ] = self._AutoGenObject.Macros["FFS_OUTPUT_DIR
"]
470 self.GenFfsList = ModuleAutoGen.GenFfsList
471 self.MacroList = ['FFS_OUTPUT_DIR', 'MODULE_GUID', 'OUTPUT_DIR']
472 self.FfsOutputFileList = []
473 self.DependencyHeaderFileSet = set()
475 # Compose a dict object containing information used to do replacement in template
477 def _TemplateDict(self):
478 MyAgo = self._AutoGenObject
479 Separator = self._SEP_[self._Platform]
481 # break build if no source files and binary files are found
482 if len(MyAgo.SourceFileList) == 0 and len(MyAgo.BinaryFileList) == 0:
483 EdkLogger.error("build
", AUTOGEN_ERROR, "No files to be built
in module
[%s, %s, %s]"
484 % (MyAgo.BuildTarget, MyAgo.ToolChain, MyAgo.Arch),
485 ExtraData="[%s]" % str(MyAgo))
487 # convert dependent libraries to build command
488 self.ProcessDependentLibrary()
489 if len(MyAgo.Module.ModuleEntryPointList) > 0:
490 ModuleEntryPoint = MyAgo.Module.ModuleEntryPointList[0]
492 ModuleEntryPoint = "_ModuleEntryPoint
"
494 ArchEntryPoint = ModuleEntryPoint
496 if MyAgo.Arch == "EBC
":
497 # EBC compiler always use "EfiStart
" as entry point. Only applies to EdkII modules
498 ImageEntryPoint = "EfiStart
"
500 # EdkII modules always use "_ModuleEntryPoint
" as entry point
501 ImageEntryPoint = "_ModuleEntryPoint
"
503 for k, v in MyAgo.Module.Defines.items():
504 if k not in MyAgo.Macros:
507 if 'MODULE_ENTRY_POINT' not in MyAgo.Macros:
508 MyAgo.Macros['MODULE_ENTRY_POINT'] = ModuleEntryPoint
509 if 'ARCH_ENTRY_POINT' not in MyAgo.Macros:
510 MyAgo.Macros['ARCH_ENTRY_POINT'] = ArchEntryPoint
511 if 'IMAGE_ENTRY_POINT' not in MyAgo.Macros:
512 MyAgo.Macros['IMAGE_ENTRY_POINT'] = ImageEntryPoint
514 PCI_COMPRESS_Flag = False
515 for k, v in MyAgo.Module.Defines.items():
516 if 'PCI_COMPRESS' == k and 'TRUE' == v:
517 PCI_COMPRESS_Flag = True
521 IncPrefix = self._INC_FLAG_[MyAgo.ToolChainFamily]
522 for Tool in MyAgo.BuildOption:
523 for Attr in MyAgo.BuildOption[Tool]:
524 Value = MyAgo.BuildOption[Tool][Attr]
528 ToolsDef.append("%s = %s" % (Tool, Value))
530 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
533 # Remove duplicated include path, if any
535 Value = RemoveDupOption(Value, IncPrefix, MyAgo.IncludePathList)
536 if Tool == "OPTROM
" and PCI_COMPRESS_Flag:
537 ValueList = Value.split()
539 for i, v in enumerate(ValueList):
542 Value = ' '.join(ValueList)
544 ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
547 # generate the Response file and Response flag
548 RespDict = self.CommandExceedLimit()
549 RespFileList = os.path.join(MyAgo.OutputDir, 'respfilelist.txt')
551 RespFileListContent = ''
552 for Resp in RespDict:
553 RespFile = os.path.join(MyAgo.OutputDir, str(Resp).lower() + '.txt')
554 StrList = RespDict[Resp].split(' ')
558 if '$' in Str or '-MMD' in Str or '-MF' in Str:
559 UnexpandMacro.append(Str)
562 UnexpandMacroStr = ' '.join(UnexpandMacro)
563 NewRespStr = ' '.join(NewStr)
564 SaveFileOnChange(RespFile, NewRespStr, False)
565 ToolsDef.append("%s = %s" % (Resp, UnexpandMacroStr + ' @' + RespFile))
566 RespFileListContent += '@' + RespFile + TAB_LINE_BREAK
567 RespFileListContent += NewRespStr + TAB_LINE_BREAK
568 SaveFileOnChange(RespFileList, RespFileListContent, False)
570 if os.path.exists(RespFileList):
571 os.remove(RespFileList)
573 # convert source files and binary files to build targets
574 self.ResultFileList = [str(T.Target) for T in MyAgo.CodaTargetList]
575 if len(self.ResultFileList) == 0 and len(MyAgo.SourceFileList) != 0:
576 EdkLogger.error("build
", AUTOGEN_ERROR, "Nothing to build
",
577 ExtraData="[%s]" % str(MyAgo))
579 self.ProcessBuildTargetList(MyAgo.OutputDir, ToolsDef)
580 self.ParserGenerateFfsCmd()
582 # Generate macros used to represent input files
583 FileMacroList = [] # macro name = file list
584 for FileListMacro in self.FileListMacros:
585 FileMacro = self._FILE_MACRO_TEMPLATE.Replace(
587 "macro_name
" : FileListMacro,
588 "source_file
" : self.FileListMacros[FileListMacro]
591 FileMacroList.append(FileMacro)
593 # INC_LIST is special
596 for P in MyAgo.IncludePathList:
597 IncludePathList.append(IncPrefix + self.PlaceMacro(P, self.Macros))
598 if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:
599 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix + P)
600 FileMacro += self._FILE_MACRO_TEMPLATE.Replace(
602 "macro_name
" : "INC
",
603 "source_file
" : IncludePathList
606 FileMacroList.append(FileMacro)
607 # Add support when compiling .nasm source files
609 asmsource = [item for item in MyAgo.SourceFileList if item.File.upper().endswith((".NASM
",".ASM
",".NASMB
","S
"))]
611 for P in MyAgo.IncludePathList:
612 IncludePath = self._INC_FLAG_['NASM'] + self.PlaceMacro(P, self.Macros)
613 if IncludePath.endswith(os.sep):
614 IncludePath = IncludePath.rstrip(os.sep)
615 # When compiling .nasm files, need to add a literal backslash at each path.
616 # In nmake makfiles, a trailing literal backslash must be escaped with a caret ('^').
617 # It is otherwise replaced with a space (' '). This is not necessary for GNU makfefiles.
618 if P == MyAgo.IncludePathList[-1] and self._Platform == WIN32_PLATFORM and self._FileType == NMAKE_FILETYPE:
619 IncludePath = ''.join([IncludePath, '^', os.sep])
621 IncludePath = os.path.join(IncludePath, '')
622 IncludePathList.append(IncludePath)
623 FileMacroList.append(self._FILE_MACRO_TEMPLATE.Replace({"macro_name
": "NASM_INC
", "source_file
": IncludePathList}))
625 # Generate macros used to represent files containing list of input files
626 for ListFileMacro in self.ListFileMacros:
627 ListFileName = os.path.join(MyAgo.OutputDir, "%s.lst
" % ListFileMacro.lower()[:len(ListFileMacro) - 5])
628 FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))
631 "\n".join(self.ListFileMacros[ListFileMacro]),
635 # Generate objlist used to create .obj file
636 for Type in self.ObjTargetDict:
637 NewLine = ' '.join(list(self.ObjTargetDict[Type]))
638 FileMacroList.append("OBJLIST_
%s = %s" % (list(self.ObjTargetDict.keys()).index(Type), NewLine))
642 MakefileName = self.getMakefileName()
643 LibraryMakeCommandList = []
644 for D in self.LibraryBuildDirectoryList:
645 Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":os.path.join(D, MakefileName)}
646 LibraryMakeCommandList.append(Command)
648 package_rel_dir = MyAgo.SourceDir
649 current_dir = self.Macros["WORKSPACE
"]
651 while not found and os.sep in package_rel_dir:
652 index = package_rel_dir.index(os.sep)
653 current_dir = mws.join(current_dir, package_rel_dir[:index])
654 if os.path.exists(current_dir):
655 for fl in os.listdir(current_dir):
656 if fl.endswith('.dec'):
659 package_rel_dir = package_rel_dir[index + 1:]
661 MakefileTemplateDict = {
662 "makefile_header
" : self._FILE_HEADER_[self._FileType],
663 "makefile_path
" : os.path.join("$
(MODULE_BUILD_DIR
)", MakefileName),
664 "makefile_name
" : MakefileName,
665 "platform_name
" : self.PlatformInfo.Name,
666 "platform_guid
" : self.PlatformInfo.Guid,
667 "platform_version
" : self.PlatformInfo.Version,
668 "platform_relative_directory
": self.PlatformInfo.SourceDir,
669 "platform_output_directory
" : self.PlatformInfo.OutputDir,
670 "ffs_output_directory
" : MyAgo.Macros["FFS_OUTPUT_DIR
"],
671 "platform_dir
" : MyAgo.Macros["PLATFORM_DIR
"],
673 "module_name
" : MyAgo.Name,
674 "module_guid
" : MyAgo.Guid,
675 "module_name_guid
" : MyAgo.UniqueBaseName,
676 "module_version
" : MyAgo.Version,
677 "module_type
" : MyAgo.ModuleType,
678 "module_file
" : MyAgo.MetaFile.Name,
679 "module_file_base_name
" : MyAgo.MetaFile.BaseName,
680 "module_relative_directory
" : MyAgo.SourceDir,
681 "module_dir
" : mws.join (self.Macros["WORKSPACE
"], MyAgo.SourceDir),
682 "package_relative_directory
": package_rel_dir,
683 "module_extra_defines
" : ["%s = %s" % (k, v) for k, v in MyAgo.Module.Defines.items()],
685 "architecture
" : MyAgo.Arch,
686 "toolchain_tag
" : MyAgo.ToolChain,
687 "build_target
" : MyAgo.BuildTarget,
689 "platform_build_directory
" : self.PlatformInfo.BuildDir,
690 "module_build_directory
" : MyAgo.BuildDir,
691 "module_output_directory
" : MyAgo.OutputDir,
692 "module_debug_directory
" : MyAgo.DebugDir,
694 "separator
" : Separator,
695 "module_tool_definitions
" : ToolsDef,
697 "shell_command_code
" : list(self._SHELL_CMD_[self._Platform].keys()),
698 "shell_command
" : list(self._SHELL_CMD_[self._Platform].values()),
700 "module_entry_point
" : ModuleEntryPoint,
701 "image_entry_point
" : ImageEntryPoint,
702 "arch_entry_point
" : ArchEntryPoint,
703 "remaining_build_target
" : self.ResultFileList,
704 "common_dependency_file
" : self.CommonFileDependency,
705 "create_directory_command
" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
706 "clean_command
" : self.GetRemoveDirectoryCommand(["$
(OUTPUT_DIR
)"]),
707 "cleanall_command
" : self.GetRemoveDirectoryCommand(["$
(DEBUG_DIR
)", "$
(OUTPUT_DIR
)"]),
708 "dependent_library_build_directory
" : self.LibraryBuildDirectoryList,
709 "library_build_command
" : LibraryMakeCommandList,
710 "file_macro
" : FileMacroList,
711 "file_build_target
" : self.BuildTargetList,
712 "backward_compatible_target
": BcTargetList,
713 "INCLUDETAG
" : "\n".join([self._INCLUDE_CMD_[self._FileType] + " " + os.path.join("$
(MODULE_BUILD_DIR
)","dependency
"),
714 self._INCLUDE_CMD_[self._FileType] + " " + os.path.join("$
(MODULE_BUILD_DIR
)","deps_target
")
718 return MakefileTemplateDict
720 def ParserGenerateFfsCmd(self):
721 #Add Ffs cmd to self.BuildTargetList
725 for Cmd in self.GenFfsList:
727 for CopyCmd in Cmd[2]:
729 Src = self.ReplaceMacro(Src)
730 Dst = self.ReplaceMacro(Dst)
731 if Dst not in self.ResultFileList:
732 self.ResultFileList.append(Dst)
733 if '%s :' %(Dst) not in self.BuildTargetList:
734 self.BuildTargetList.append("%s : %s" %(Dst,Src))
735 self.BuildTargetList.append('\t' + self._CP_TEMPLATE_[self._Platform] %{'Src': Src, 'Dst': Dst})
738 for index, Str in enumerate(FfsCmdList):
740 OutputFile = FfsCmdList[index + 1]
741 if '-i' == Str or "-oi
" == Str:
742 if DepsFileList == []:
743 DepsFileList = [FfsCmdList[index + 1]]
745 DepsFileList.append(FfsCmdList[index + 1])
746 DepsFileString = ' '.join(DepsFileList).strip()
747 if DepsFileString == '':
749 OutputFile = self.ReplaceMacro(OutputFile)
750 self.ResultFileList.append(OutputFile)
751 DepsFileString = self.ReplaceMacro(DepsFileString)
752 self.BuildTargetList.append('%s : %s' % (OutputFile, DepsFileString))
753 CmdString = ' '.join(FfsCmdList).strip()
754 CmdString = self.ReplaceMacro(CmdString)
755 self.BuildTargetList.append('\t%s' % CmdString)
757 self.ParseSecCmd(DepsFileList, Cmd[1])
758 for SecOutputFile, SecDepsFile, SecCmd in self.FfsOutputFileList :
759 self.BuildTargetList.append('%s : %s' % (self.ReplaceMacro(SecOutputFile), self.ReplaceMacro(SecDepsFile)))
760 self.BuildTargetList.append('\t%s' % self.ReplaceMacro(SecCmd))
761 self.FfsOutputFileList = []
763 def ParseSecCmd(self, OutputFileList, CmdTuple):
764 for OutputFile in OutputFileList:
765 for SecCmdStr in CmdTuple:
767 SecCmdList = SecCmdStr.split()
768 CmdName = SecCmdList[0]
769 for index, CmdItem in enumerate(SecCmdList):
770 if '-o' == CmdItem and OutputFile == SecCmdList[index + 1]:
772 while index + 1 < len(SecCmdList):
773 if not SecCmdList[index+1].startswith('-'):
774 SecDepsFileList.append(SecCmdList[index + 1])
776 if CmdName == 'Trim':
777 SecDepsFileList.append(os.path.join('$(DEBUG_DIR)', os.path.basename(OutputFile).replace('offset', 'efi')))
778 if OutputFile.endswith('.ui') or OutputFile.endswith('.ver'):
779 SecDepsFileList.append(os.path.join('$(MODULE_DIR)', '$(MODULE_FILE)'))
780 self.FfsOutputFileList.append((OutputFile, ' '.join(SecDepsFileList), SecCmdStr))
781 if len(SecDepsFileList) > 0:
782 self.ParseSecCmd(SecDepsFileList, CmdTuple)
787 def ReplaceMacro(self, str):
788 for Macro in self.MacroList:
789 if self._AutoGenObject.Macros[Macro] and os.path.normcase(self._AutoGenObject.Macros[Macro]) in os.path.normcase(str):
790 replace_dir = str[os.path.normcase(str).index(os.path.normcase(self._AutoGenObject.Macros[Macro])): os.path.normcase(str).index(
791 os.path.normcase(self._AutoGenObject.Macros[Macro])) + len(self._AutoGenObject.Macros[Macro])]
792 str = str.replace(replace_dir, '$(' + Macro + ')')
795 def CommandExceedLimit(self):
797 'CC' : { 'Macro' : '$(CC_FLAGS)', 'Value' : False},
798 'PP' : { 'Macro' : '$(PP_FLAGS)', 'Value' : False},
799 'APP' : { 'Macro' : '$(APP_FLAGS)', 'Value' : False},
800 'ASLPP' : { 'Macro' : '$(ASLPP_FLAGS)', 'Value' : False},
801 'VFRPP' : { 'Macro' : '$(VFRPP_FLAGS)', 'Value' : False},
802 'ASM' : { 'Macro' : '$(ASM_FLAGS)', 'Value' : False},
803 'ASLCC' : { 'Macro' : '$(ASLCC_FLAGS)', 'Value' : False},
808 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
810 # base on the source files to decide the file type
811 for File in self._AutoGenObject.SourceFileList:
812 for type in self._AutoGenObject.FileTypes:
813 if File in self._AutoGenObject.FileTypes[type]:
814 if type not in FileTypeList:
815 FileTypeList.append(type)
817 # calculate the command-line length
819 for type in FileTypeList:
820 BuildTargets = self._AutoGenObject.BuildRules[type].BuildTargets
821 for Target in BuildTargets:
822 CommandList = BuildTargets[Target].Commands
823 for SingleCommand in CommandList:
825 SingleCommandLength = len(SingleCommand)
826 SingleCommandList = SingleCommand.split()
827 if len(SingleCommandList) > 0:
828 for Flag in FlagDict:
829 if '$('+ Flag +')' in SingleCommandList[0]:
833 if 'PATH' not in self._AutoGenObject.BuildOption[Tool]:
834 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))
835 SingleCommandLength += len(self._AutoGenObject.BuildOption[Tool]['PATH
'])
836 for item in SingleCommandList[1:]:
837 if FlagDict[Tool]['Macro
'] in item:
838 if 'FLAGS
' not in self._AutoGenObject.BuildOption[Tool]:
839 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))
840 Str = self._AutoGenObject.BuildOption[Tool]['FLAGS']
841 for Option in self._AutoGenObject.BuildOption:
842 for Attr in self._AutoGenObject.BuildOption[Option]:
843 if Str.find(Option + '_' + Attr) != -1:
844 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
845 while(Str.find('$(') != -1):
846 for macro in self._AutoGenObject.Macros:
847 MacroName = '$('+ macro + ')'
848 if (Str.find(MacroName) != -1):
849 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
853 SingleCommandLength += len(Str)
854 elif '$(INC)' in item:
855 SingleCommandLength += self._AutoGenObject.IncludePathLength + len(IncPrefix) * len(self._AutoGenObject.IncludePathList)
856 elif item.find('$(') != -1:
858 for Option in self._AutoGenObject.BuildOption:
859 for Attr in self._AutoGenObject.BuildOption[Option]:
860 if Str.find(Option + '_' + Attr) != -1:
861 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
862 while(Str.find('$(') != -1):
863 for macro in self._AutoGenObject.Macros:
864 MacroName = '$('+ macro + ')'
865 if (Str.find(MacroName) != -1):
866 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
870 SingleCommandLength += len(Str)
872 if SingleCommandLength > GlobalData.gCommandMaxLength:
873 FlagDict[Tool]['Value'] = True
875 # generate the response file content by combine the FLAGS and INC
876 for Flag in FlagDict:
877 if FlagDict[Flag]['Value']:
879 RespMacro = FlagDict[Flag]['Macro'].replace('FLAGS', 'RESP')
880 Value = self._AutoGenObject.BuildOption[Flag]['FLAGS']
881 for inc in self._AutoGenObject.IncludePathList:
882 Value += ' ' + IncPrefix + inc
883 for Option in self._AutoGenObject.BuildOption:
884 for Attr in self._AutoGenObject.BuildOption[Option]:
885 if Value.find(Option + '_' + Attr) != -1:
886 Value = Value.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
887 while (Value.find('$(') != -1):
888 for macro in self._AutoGenObject.Macros:
889 MacroName = '$('+ macro + ')'
890 if (Value.find(MacroName) != -1):
891 Value = Value.replace(MacroName, self._AutoGenObject.Macros[macro])
896 if self._AutoGenObject.ToolChainFamily == 'GCC':
897 RespDict[Key] = Value.replace('\\', '/')
899 RespDict[Key] = Value
900 for Target in BuildTargets:
901 for i, SingleCommand in enumerate(BuildTargets[Target].Commands):
902 if FlagDict[Flag]['Macro'] in SingleCommand:
903 BuildTargets[Target].Commands[i] = SingleCommand.replace('$(INC)', '').replace(FlagDict[Flag]['Macro'], RespMacro)
906 def ProcessBuildTargetList(self, RespFile, ToolsDef):
908 # Search dependency file list for each source file
910 ForceIncludedFile = []
911 for File in self._AutoGenObject.AutoGenFileList:
913 ForceIncludedFile.append(File)
916 for Target in self._AutoGenObject.IntroTargetList:
917 SourceFileList.extend(Target.Inputs)
918 OutPutFileList.extend(Target.Outputs)
921 for Item in OutPutFileList:
922 if Item in SourceFileList:
923 SourceFileList.remove(Item)
925 FileDependencyDict = {item:ForceIncludedFile for item in SourceFileList}
927 for Dependency in FileDependencyDict.values():
928 self.DependencyHeaderFileSet.update(set(Dependency))
930 # Get a set of unique package includes from MetaFile
931 parentMetaFileIncludes = set()
932 for aInclude in self._AutoGenObject.PackageIncludePathList:
933 aIncludeName = str(aInclude)
934 parentMetaFileIncludes.add(aIncludeName.lower())
936 # Check if header files are listed in metafile
937 # Get a set of unique module header source files from MetaFile
938 headerFilesInMetaFileSet = set()
939 for aFile in self._AutoGenObject.SourceFileList:
940 aFileName = str(aFile)
941 if not aFileName.endswith('.h'):
943 headerFilesInMetaFileSet.add(aFileName.lower())
945 # Get a set of unique module autogen files
946 localAutoGenFileSet = set()
947 for aFile in self._AutoGenObject.AutoGenFileList:
948 localAutoGenFileSet.add(str(aFile).lower())
950 # Get a set of unique module dependency header files
951 # Exclude autogen files and files not in the source directory
952 # and files that are under the package include list
953 headerFileDependencySet = set()
954 localSourceDir = str(self._AutoGenObject.SourceDir).lower()
955 for Dependency in FileDependencyDict.values():
956 for aFile in Dependency:
957 aFileName = str(aFile).lower()
958 # Exclude non-header files
959 if not aFileName.endswith('.h'):
961 # Exclude autogen files
962 if aFileName in localAutoGenFileSet:
964 # Exclude include out of local scope
965 if localSourceDir not in aFileName:
967 # Exclude files covered by package includes
969 for aIncludePath in parentMetaFileIncludes:
970 if aIncludePath in aFileName:
975 # Keep the file to be checked
976 headerFileDependencySet.add(aFileName)
978 # Check if a module dependency header file is missing from the module's MetaFile
979 for aFile in headerFileDependencySet:
980 if aFile in headerFilesInMetaFileSet:
982 if GlobalData.gUseHashCache:
983 GlobalData.gModuleBuildTracking[self._AutoGenObject] = 'FAIL_METAFILE'
984 EdkLogger.warn("build
","Module MetaFile
[Sources
] is missing local header
!",
985 ExtraData = "Local Header
: " + aFile + " not found
in " + self._AutoGenObject.MetaFile.Path
988 for File,Dependency in FileDependencyDict.items():
992 self._AutoGenObject.AutoGenDepSet |= set(Dependency)
997 DependencyDict = FileDependencyDict.copy()
999 # Convert target description object to target string in makefile
1000 if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and TAB_C_CODE_FILE in self._AutoGenObject.Targets:
1001 for T in self._AutoGenObject.Targets[TAB_C_CODE_FILE]:
1002 NewFile = self.PlaceMacro(str(T), self.Macros)
1003 if not self.ObjTargetDict.get(T.Target.SubDir):
1004 self.ObjTargetDict[T.Target.SubDir] = set()
1005 self.ObjTargetDict[T.Target.SubDir].add(NewFile)
1006 for Type in self._AutoGenObject.Targets:
1007 resp_file_number = 0
1008 for T in self._AutoGenObject.Targets[Type]:
1009 # Generate related macros if needed
1010 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
1011 self.FileListMacros[T.FileListMacro] = []
1012 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:
1013 self.ListFileMacros[T.ListFileMacro] = []
1014 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:
1015 self.ListFileMacros[T.IncListFileMacro] = []
1019 # Add force-dependencies
1020 for Dep in T.Dependencies:
1021 Deps.append(self.PlaceMacro(str(Dep), self.Macros))
1022 if Dep != '$(MAKE_FILE)':
1023 CCodeDeps.append(self.PlaceMacro(str(Dep), self.Macros))
1024 # Add inclusion-dependencies
1025 if len(T.Inputs) == 1 and T.Inputs[0] in FileDependencyDict:
1026 for F in FileDependencyDict[T.Inputs[0]]:
1027 Deps.append(self.PlaceMacro(str(F), self.Macros))
1028 # Add source-dependencies
1030 NewFile = self.PlaceMacro(str(F), self.Macros)
1031 # In order to use file list macro as dependency
1033 # gnu tools need forward slash path separator, even on Windows
1034 self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/'))
1035 self.FileListMacros[T.FileListMacro].append(NewFile)
1036 elif T.GenFileListMacro:
1037 self.FileListMacros[T.FileListMacro].append(NewFile)
1039 Deps.append(NewFile)
1040 for key in self.FileListMacros:
1041 self.FileListMacros[key].sort()
1042 # Use file list macro as dependency
1043 if T.GenFileListMacro:
1044 Deps.append("$
(%s)" % T.FileListMacro)
1045 if Type in [TAB_OBJECT_FILE, TAB_STATIC_LIBRARY]:
1046 Deps.append("$
(%s)" % T.ListFileMacro)
1048 if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and Type == TAB_C_CODE_FILE:
1049 T, CmdTarget, CmdTargetDict, CmdCppDict = self.ParserCCodeFile(T, Type, CmdSumDict, CmdTargetDict,
1050 CmdCppDict, DependencyDict, RespFile,
1051 ToolsDef, resp_file_number)
1052 resp_file_number += 1
1053 TargetDict = {"target
": self.PlaceMacro(T.Target.Path, self.Macros), "cmd
": "\n\t".join(T.Commands),"deps
": CCodeDeps}
1054 CmdLine = self._BUILD_TARGET_TEMPLATE.Replace(TargetDict).rstrip().replace('\t$(OBJLIST', '$(OBJLIST')
1056 CmdLine = '%s%s' %(CmdLine, TAB_LINE_BREAK)
1057 if CCodeDeps or CmdLine:
1058 self.BuildTargetList.append(CmdLine)
1060 TargetDict = {"target
": self.PlaceMacro(T.Target.Path, self.Macros), "cmd
": "\n\t".join(T.Commands),"deps
": Deps}
1061 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
1063 # Add a Makefile rule for targets generating multiple files.
1064 # The main output is a prerequisite for the other output files.
1065 for i in T.Outputs[1:]:
1066 AnnexeTargetDict = {"target
": self.PlaceMacro(i.Path, self.Macros), "cmd
": "", "deps
": self.PlaceMacro(T.Target.Path, self.Macros)}
1067 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(AnnexeTargetDict))
1069 def ParserCCodeFile(self, T, Type, CmdSumDict, CmdTargetDict, CmdCppDict, DependencyDict, RespFile, ToolsDef,
1071 SaveFilePath = os.path.join(RespFile, "cc_resp_
%s.txt
" % resp_file_number)
1073 for item in self._AutoGenObject.Targets[Type]:
1074 CmdSumDict[item.Target.SubDir] = item.Target.BaseName
1075 for CppPath in item.Inputs:
1076 Path = self.PlaceMacro(CppPath.Path, self.Macros)
1077 if CmdCppDict.get(item.Target.SubDir):
1078 CmdCppDict[item.Target.SubDir].append(Path)
1080 CmdCppDict[item.Target.SubDir] = ['$(MAKE_FILE)', Path]
1081 if CppPath.Path in DependencyDict:
1082 for Temp in DependencyDict[CppPath.Path]:
1084 Path = self.PlaceMacro(Temp.Path, self.Macros)
1087 if Path not in (self.CommonFileDependency + CmdCppDict[item.Target.SubDir]):
1088 CmdCppDict[item.Target.SubDir].append(Path)
1090 CommandList = T.Commands[:]
1091 for Item in CommandList[:]:
1092 SingleCommandList = Item.split()
1093 if len(SingleCommandList) > 0 and self.CheckCCCmd(SingleCommandList):
1094 for Temp in SingleCommandList:
1095 if Temp.startswith('/Fo'):
1096 CmdSign = '%s%s' % (Temp.rsplit(TAB_SLASH, 1)[0], TAB_SLASH)
1100 if CmdSign not in list(CmdTargetDict.keys()):
1101 cmd = Item.replace(Temp, CmdSign)
1102 if SingleCommandList[-1] in cmd:
1103 CmdTargetDict[CmdSign] = [cmd.replace(SingleCommandList[-1], "").rstrip(), SingleCommandList[-1]]
1105 # CmdTargetDict[CmdSign] = "%s %s" % (CmdTargetDict[CmdSign], SingleCommandList[-1])
1106 CmdTargetDict[CmdSign].append(SingleCommandList[-1])
1107 Index = CommandList.index(Item)
1108 CommandList.pop(Index)
1109 if SingleCommandList[-1].endswith("%s%s.c
" % (TAB_SLASH, CmdSumDict[CmdSign[3:].rsplit(TAB_SLASH, 1)[0]])):
1110 Cpplist = CmdCppDict[T.Target.SubDir]
1111 Cpplist.insert(0, '$(OBJLIST_%d): ' % list(self.ObjTargetDict.keys()).index(T.Target.SubDir))
1112 source_files = CmdTargetDict[CmdSign][1:]
1113 source_files.insert(0, " ")
1114 if len(source_files)>2:
1115 SaveFileOnChange(SaveFilePath, " ".join(source_files), False)
1116 T.Commands[Index] = '%s\n\t%s $(cc_resp_%s)' % (
1117 ' \\\n\t'.join(Cpplist), CmdTargetDict[CmdSign][0], resp_file_number)
1118 ToolsDef.append("cc_resp_
%s = @%s" % (resp_file_number, SaveFilePath))
1120 elif len(source_files)<=2 and len(" ".join(CmdTargetDict[CmdSign][:2]))>GlobalData.gCommandMaxLength:
1121 SaveFileOnChange(SaveFilePath, " ".join(source_files), False)
1122 T.Commands[Index] = '%s\n\t%s $(cc_resp_%s)' % (
1123 ' \\\n\t'.join(Cpplist), CmdTargetDict[CmdSign][0], resp_file_number)
1124 ToolsDef.append("cc_resp_
%s = @%s" % (resp_file_number, SaveFilePath))
1127 T.Commands[Index] = '%s\n\t%s' % (' \\\n\t'.join(Cpplist), " ".join(CmdTargetDict[CmdSign]))
1129 T.Commands.pop(Index)
1130 return T, CmdSumDict, CmdTargetDict, CmdCppDict
1132 def CheckCCCmd(self, CommandList):
1133 for cmd in CommandList:
1137 ## For creating makefile targets for dependent libraries
1138 def ProcessDependentLibrary(self):
1139 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1140 if not LibraryAutoGen.IsBinaryModule:
1141 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
1143 ## Return a list containing source file's dependencies
1145 # @param FileList The list of source files
1146 # @param ForceInculeList The list of files which will be included forcely
1147 # @param SearchPathList The list of search path
1149 # @retval dict The mapping between source file path and its dependencies
1151 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
1154 Dependency[F] = GetDependencyList(self._AutoGenObject, self.FileCache, F, ForceInculeList, SearchPathList)
1158 ## CustomMakefile class
1160 # This class encapsules makefie and its generation for module. It uses template to generate
1161 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
1163 class CustomMakefile(BuildFile):
1164 ## template used to generate the makefile for module with custom makefile
1165 _TEMPLATE_ = TemplateString('''\
1169 # Platform Macro Definition
1171 PLATFORM_NAME = ${platform_name}
1172 PLATFORM_GUID = ${platform_guid}
1173 PLATFORM_VERSION = ${platform_version}
1174 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
1175 PLATFORM_DIR = ${platform_dir}
1176 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1179 # Module Macro Definition
1181 MODULE_NAME = ${module_name}
1182 MODULE_GUID = ${module_guid}
1183 MODULE_NAME_GUID = ${module_name_guid}
1184 MODULE_VERSION = ${module_version}
1185 MODULE_TYPE = ${module_type}
1186 MODULE_FILE = ${module_file}
1187 MODULE_FILE_BASE_NAME = ${module_file_base_name}
1188 BASE_NAME = $(MODULE_NAME)
1189 MODULE_RELATIVE_DIR = ${module_relative_directory}
1190 MODULE_DIR = ${module_dir}
1193 # Build Configuration Macro Definition
1195 ARCH = ${architecture}
1196 TOOLCHAIN = ${toolchain_tag}
1197 TOOLCHAIN_TAG = ${toolchain_tag}
1198 TARGET = ${build_target}
1201 # Build Directory Macro Definition
1203 # PLATFORM_BUILD_DIR = ${platform_build_directory}
1204 BUILD_DIR = ${platform_build_directory}
1205 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
1206 LIB_DIR = $(BIN_DIR)
1207 MODULE_BUILD_DIR = ${module_build_directory}
1208 OUTPUT_DIR = ${module_output_directory}
1209 DEBUG_DIR = ${module_debug_directory}
1210 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
1211 DEST_DIR_DEBUG = $(DEBUG_DIR)
1214 # Tools definitions specific to this module
1216 ${BEGIN}${module_tool_definitions}
1218 MAKE_FILE = ${makefile_path}
1221 # Shell Command Macro
1223 ${BEGIN}${shell_command_code} = ${shell_command}
1226 ${custom_makefile_content}
1229 # Target used when called from platform makefile, which will bypass the build of dependent libraries
1242 # Build Target used in multi-thread build mode, which no init target is needed
1248 # Initialization target: print build information and create necessary directories
1251 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
1252 ${BEGIN}\t-@${create_directory_command}\n${END}\
1256 ## Constructor of CustomMakefile
1258 # @param ModuleAutoGen Object of ModuleAutoGen class
1260 def __init__(self, ModuleAutoGen):
1261 BuildFile.__init__(self, ModuleAutoGen)
1262 self.PlatformInfo = self._AutoGenObject.PlatformInfo
1263 self.IntermediateDirectoryList = ["$
(DEBUG_DIR
)", "$
(OUTPUT_DIR
)"]
1264 self.DependencyHeaderFileSet = set()
1266 # Compose a dict object containing information used to do replacement in template
1268 def _TemplateDict(self):
1269 Separator = self._SEP_[self._Platform]
1270 MyAgo = self._AutoGenObject
1271 if self._FileType not in MyAgo.CustomMakefile:
1272 EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile
for %s" % self._FileType,
1273 ExtraData="[%s]" % str(MyAgo))
1274 MakefilePath = mws.join(
1276 MyAgo.CustomMakefile[self._FileType]
1279 CustomMakefile = open(MakefilePath, 'r').read()
1281 EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(MyAgo),
1282 ExtraData=MyAgo.CustomMakefile[self._FileType])
1286 for Tool in MyAgo.BuildOption:
1287 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
1290 for Attr in MyAgo.BuildOption[Tool]:
1291 if Attr == "FAMILY
":
1293 elif Attr == "PATH
":
1294 ToolsDef.append("%s = %s" % (Tool, MyAgo.BuildOption[Tool][Attr]))
1296 ToolsDef.append("%s_%s = %s" % (Tool, Attr, MyAgo.BuildOption[Tool][Attr]))
1299 MakefileName = self.getMakefileName()
1300 MakefileTemplateDict = {
1301 "makefile_header
" : self._FILE_HEADER_[self._FileType],
1302 "makefile_path
" : os.path.join("$
(MODULE_BUILD_DIR
)", MakefileName),
1303 "platform_name
" : self.PlatformInfo.Name,
1304 "platform_guid
" : self.PlatformInfo.Guid,
1305 "platform_version
" : self.PlatformInfo.Version,
1306 "platform_relative_directory
": self.PlatformInfo.SourceDir,
1307 "platform_output_directory
" : self.PlatformInfo.OutputDir,
1308 "platform_dir
" : MyAgo.Macros["PLATFORM_DIR
"],
1310 "module_name
" : MyAgo.Name,
1311 "module_guid
" : MyAgo.Guid,
1312 "module_name_guid
" : MyAgo.UniqueBaseName,
1313 "module_version
" : MyAgo.Version,
1314 "module_type
" : MyAgo.ModuleType,
1315 "module_file
" : MyAgo.MetaFile,
1316 "module_file_base_name
" : MyAgo.MetaFile.BaseName,
1317 "module_relative_directory
" : MyAgo.SourceDir,
1318 "module_dir
" : mws.join (MyAgo.WorkspaceDir, MyAgo.SourceDir),
1320 "architecture
" : MyAgo.Arch,
1321 "toolchain_tag
" : MyAgo.ToolChain,
1322 "build_target
" : MyAgo.BuildTarget,
1324 "platform_build_directory
" : self.PlatformInfo.BuildDir,
1325 "module_build_directory
" : MyAgo.BuildDir,
1326 "module_output_directory
" : MyAgo.OutputDir,
1327 "module_debug_directory
" : MyAgo.DebugDir,
1329 "separator
" : Separator,
1330 "module_tool_definitions
" : ToolsDef,
1332 "shell_command_code
" : list(self._SHELL_CMD_[self._Platform].keys()),
1333 "shell_command
" : list(self._SHELL_CMD_[self._Platform].values()),
1335 "create_directory_command
" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1336 "custom_makefile_content
" : CustomMakefile
1339 return MakefileTemplateDict
1341 ## PlatformMakefile class
1343 # This class encapsules makefie and its generation for platform. It uses
1344 # template to generate the content of makefile. The content of makefile will be
1345 # got from PlatformAutoGen object.
1347 class PlatformMakefile(BuildFile):
1348 ## template used to generate the makefile for platform
1349 _TEMPLATE_ = TemplateString('''\
1353 # Platform Macro Definition
1355 PLATFORM_NAME = ${platform_name}
1356 PLATFORM_GUID = ${platform_guid}
1357 PLATFORM_VERSION = ${platform_version}
1358 PLATFORM_FILE = ${platform_file}
1359 PLATFORM_DIR = ${platform_dir}
1360 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1363 # Build Configuration Macro Definition
1365 TOOLCHAIN = ${toolchain_tag}
1366 TOOLCHAIN_TAG = ${toolchain_tag}
1367 TARGET = ${build_target}
1370 # Build Directory Macro Definition
1372 BUILD_DIR = ${platform_build_directory}
1373 FV_DIR = ${platform_build_directory}${separator}FV
1376 # Shell Command Macro
1378 ${BEGIN}${shell_command_code} = ${shell_command}
1382 MAKE_FILE = ${makefile_path}
1387 all: init build_libraries build_modules
1390 # Initialization target: print build information and create necessary directories
1393 \t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
1394 \t${BEGIN}-@${create_directory_command}
1397 # library build target
1399 libraries: init build_libraries
1402 # module build target
1404 modules: init build_libraries build_modules
1407 # Build all libraries:
1410 ${BEGIN}\t@"$
(MAKE
)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
1411 ${END}\t@cd $(BUILD_DIR)
1414 # Build all modules:
1417 ${BEGIN}\t@"$
(MAKE
)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
1418 ${END}\t@cd $(BUILD_DIR)
1421 # Clean intermediate files
1424 \t${BEGIN}-@${library_build_command} clean
1425 \t${END}${BEGIN}-@${module_build_command} clean
1426 \t${END}@cd $(BUILD_DIR)
1429 # Clean all generated files except to makefile
1432 ${BEGIN}\t${cleanall_command}
1436 # Clean all library files
1439 \t${BEGIN}-@${library_build_command} cleanall
1440 \t${END}@cd $(BUILD_DIR)\n
1443 ## Constructor of PlatformMakefile
1445 # @param ModuleAutoGen Object of PlatformAutoGen class
1447 def __init__(self, PlatformAutoGen):
1448 BuildFile.__init__(self, PlatformAutoGen)
1449 self.ModuleBuildCommandList = []
1450 self.ModuleMakefileList = []
1451 self.IntermediateDirectoryList = []
1452 self.ModuleBuildDirectoryList = []
1453 self.LibraryBuildDirectoryList = []
1454 self.LibraryMakeCommandList = []
1455 self.DependencyHeaderFileSet = set()
1457 # Compose a dict object containing information used to do replacement in template
1459 def _TemplateDict(self):
1460 Separator = self._SEP_[self._Platform]
1462 MyAgo = self._AutoGenObject
1463 if "MAKE
" not in MyAgo.ToolDefinition or "PATH
" not in MyAgo.ToolDefinition["MAKE
"]:
1464 EdkLogger.error("build
", OPTION_MISSING, "No MAKE command defined
. Please check your tools_def
.txt
!",
1465 ExtraData="[%s]" % str(MyAgo))
1467 self.IntermediateDirectoryList = ["$
(BUILD_DIR
)"]
1468 self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()
1469 self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()
1471 MakefileName = self.getMakefileName()
1472 LibraryMakefileList = []
1473 LibraryMakeCommandList = []
1474 for D in self.LibraryBuildDirectoryList:
1475 D = self.PlaceMacro(D, {"BUILD_DIR
":MyAgo.BuildDir})
1476 Makefile = os.path.join(D, MakefileName)
1477 Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":Makefile}
1478 LibraryMakefileList.append(Makefile)
1479 LibraryMakeCommandList.append(Command)
1480 self.LibraryMakeCommandList = LibraryMakeCommandList
1482 ModuleMakefileList = []
1483 ModuleMakeCommandList = []
1484 for D in self.ModuleBuildDirectoryList:
1485 D = self.PlaceMacro(D, {"BUILD_DIR
":MyAgo.BuildDir})
1486 Makefile = os.path.join(D, MakefileName)
1487 Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":Makefile}
1488 ModuleMakefileList.append(Makefile)
1489 ModuleMakeCommandList.append(Command)
1491 MakefileTemplateDict = {
1492 "makefile_header
" : self._FILE_HEADER_[self._FileType],
1493 "makefile_path
" : os.path.join("$
(BUILD_DIR
)", MakefileName),
1494 "make_path
" : MyAgo.ToolDefinition["MAKE
"]["PATH
"],
1495 "makefile_name
" : MakefileName,
1496 "platform_name
" : MyAgo.Name,
1497 "platform_guid
" : MyAgo.Guid,
1498 "platform_version
" : MyAgo.Version,
1499 "platform_file
" : MyAgo.MetaFile,
1500 "platform_relative_directory
": MyAgo.SourceDir,
1501 "platform_output_directory
" : MyAgo.OutputDir,
1502 "platform_build_directory
" : MyAgo.BuildDir,
1503 "platform_dir
" : MyAgo.Macros["PLATFORM_DIR
"],
1505 "toolchain_tag
" : MyAgo.ToolChain,
1506 "build_target
" : MyAgo.BuildTarget,
1507 "shell_command_code
" : list(self._SHELL_CMD_[self._Platform].keys()),
1508 "shell_command
" : list(self._SHELL_CMD_[self._Platform].values()),
1509 "build_architecture_list
" : MyAgo.Arch,
1510 "architecture
" : MyAgo.Arch,
1511 "separator
" : Separator,
1512 "create_directory_command
" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1513 "cleanall_command
" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1514 "library_makefile_list
" : LibraryMakefileList,
1515 "module_makefile_list
" : ModuleMakefileList,
1516 "library_build_command
" : LibraryMakeCommandList,
1517 "module_build_command
" : ModuleMakeCommandList,
1520 return MakefileTemplateDict
1522 ## Get the root directory list for intermediate files of all modules build
1524 # @retval list The list of directory
1526 def GetModuleBuildDirectoryList(self):
1528 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1529 if not ModuleAutoGen.IsBinaryModule:
1530 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1533 ## Get the root directory list for intermediate files of all libraries build
1535 # @retval list The list of directory
1537 def GetLibraryBuildDirectoryList(self):
1539 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1540 if not LibraryAutoGen.IsBinaryModule:
1541 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1544 ## TopLevelMakefile class
1546 # This class encapsules makefie and its generation for entrance makefile. It
1547 # uses template to generate the content of makefile. The content of makefile
1548 # will be got from WorkspaceAutoGen object.
1550 class TopLevelMakefile(BuildFile):
1551 ## template used to generate toplevel makefile
1552 _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}''')
1554 ## Constructor of TopLevelMakefile
1556 # @param Workspace Object of WorkspaceAutoGen class
1558 def __init__(self, Workspace):
1559 BuildFile.__init__(self, Workspace)
1560 self.IntermediateDirectoryList = []
1561 self.DependencyHeaderFileSet = set()
1563 # Compose a dict object containing information used to do replacement in template
1565 def _TemplateDict(self):
1566 Separator = self._SEP_[self._Platform]
1568 # any platform autogen object is ok because we just need common information
1569 MyAgo = self._AutoGenObject
1571 if "MAKE
" not in MyAgo.ToolDefinition or "PATH
" not in MyAgo.ToolDefinition["MAKE
"]:
1572 EdkLogger.error("build
", OPTION_MISSING, "No MAKE command defined
. Please check your tools_def
.txt
!",
1573 ExtraData="[%s]" % str(MyAgo))
1575 for Arch in MyAgo.ArchList:
1576 self.IntermediateDirectoryList.append(Separator.join(["$
(BUILD_DIR
)", Arch]))
1577 self.IntermediateDirectoryList.append("$
(FV_DIR
)")
1579 # TRICK: for not generating GenFds call in makefile if no FDF file
1581 if MyAgo.FdfFile is not None and MyAgo.FdfFile != "":
1582 FdfFileList = [MyAgo.FdfFile]
1583 # macros passed to GenFds
1585 MacroDict.update(GlobalData.gGlobalDefines)
1586 MacroDict.update(GlobalData.gCommandLineDefines)
1587 for MacroName in MacroDict:
1588 if MacroDict[MacroName] != "":
1589 MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))
1591 MacroList.append('"%s"' % MacroName)
1595 # pass extra common options to external program called in makefile, currently GenFds.exe
1597 LogLevel = EdkLogger.GetLevel()
1598 if LogLevel == EdkLogger.VERBOSE:
1599 ExtraOption += " -v
"
1600 elif LogLevel <= EdkLogger.DEBUG_9:
1601 ExtraOption += " -d
%d" % (LogLevel - 1)
1602 elif LogLevel == EdkLogger.QUIET:
1603 ExtraOption += " -q
"
1605 if GlobalData.gCaseInsensitive:
1606 ExtraOption += " -c
"
1607 if not GlobalData.gEnableGenfdsMultiThread:
1608 ExtraOption += " --no
-genfds
-multi
-thread
"
1609 if GlobalData.gIgnoreSource:
1610 ExtraOption += " --ignore
-sources
"
1612 for pcd in GlobalData.BuildOptionPcd:
1614 pcdname = '.'.join(pcd[0:3])
1616 pcdname = '.'.join(pcd[0:2])
1617 if pcd[3].startswith('{'):
1618 ExtraOption += " --pcd
" + pcdname + '=' + 'H' + '"' + pcd[3] + '"'
1620 ExtraOption += " --pcd
" + pcdname + '=' + pcd[3]
1622 MakefileName = self.getMakefileName()
1623 SubBuildCommandList = []
1624 for A in MyAgo.ArchList:
1625 Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":os.path.join("$
(BUILD_DIR
)", A, MakefileName)}
1626 SubBuildCommandList.append(Command)
1628 MakefileTemplateDict = {
1629 "makefile_header
" : self._FILE_HEADER_[self._FileType],
1630 "makefile_path
" : os.path.join("$
(BUILD_DIR
)", MakefileName),
1631 "make_path
" : MyAgo.ToolDefinition["MAKE
"]["PATH
"],
1632 "platform_name
" : MyAgo.Name,
1633 "platform_guid
" : MyAgo.Guid,
1634 "platform_version
" : MyAgo.Version,
1635 "platform_build_directory
" : MyAgo.BuildDir,
1636 "conf_directory
" : GlobalData.gConfDirectory,
1638 "toolchain_tag
" : MyAgo.ToolChain,
1639 "build_target
" : MyAgo.BuildTarget,
1640 "shell_command_code
" : list(self._SHELL_CMD_[self._Platform].keys()),
1641 "shell_command
" : list(self._SHELL_CMD_[self._Platform].values()),
1642 'arch' : list(MyAgo.ArchList),
1643 "build_architecture_list
" : ','.join(MyAgo.ArchList),
1644 "separator
" : Separator,
1645 "create_directory_command
" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1646 "cleanall_command
" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1647 "sub_build_command
" : SubBuildCommandList,
1648 "fdf_file
" : FdfFileList,
1649 "active_platform
" : str(MyAgo),
1650 "fd
" : MyAgo.FdTargetList,
1651 "fv
" : MyAgo.FvTargetList,
1652 "cap
" : MyAgo.CapTargetList,
1653 "extra_options
" : ExtraOption,
1654 "macro
" : MacroList,
1657 return MakefileTemplateDict
1659 ## Get the root directory list for intermediate files of all modules build
1661 # @retval list The list of directory
1663 def GetModuleBuildDirectoryList(self):
1665 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1666 if not ModuleAutoGen.IsBinaryModule:
1667 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1670 ## Get the root directory list for intermediate files of all libraries build
1672 # @retval list The list of directory
1674 def GetLibraryBuildDirectoryList(self):
1676 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1677 if not LibraryAutoGen.IsBinaryModule:
1678 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1681 ## Find dependencies for one source file
1683 # By searching recursively "#include" directive in file, find out all the
1684 # files needed by given source file. The dependencies will be only searched
1685 # in given search path list.
1687 # @param File The source file
1688 # @param ForceInculeList The list of files which will be included forcely
1689 # @param SearchPathList The list of search path
1691 # @retval list The list of files the given source file depends on
1693 def GetDependencyList(AutoGenObject
, FileCache
, File
, ForceList
, SearchPathList
):
1694 EdkLogger
.debug(EdkLogger
.DEBUG_1
, "Try to get dependency files for %s" % File
)
1695 FileStack
= [File
] + ForceList
1696 DependencySet
= set()
1698 if AutoGenObject
.Arch
not in gDependencyDatabase
:
1699 gDependencyDatabase
[AutoGenObject
.Arch
] = {}
1700 DepDb
= gDependencyDatabase
[AutoGenObject
.Arch
]
1702 while len(FileStack
) > 0:
1705 FullPathDependList
= []
1707 for CacheFile
in FileCache
[F
]:
1708 FullPathDependList
.append(CacheFile
)
1709 if CacheFile
not in DependencySet
:
1710 FileStack
.append(CacheFile
)
1711 DependencySet
.update(FullPathDependList
)
1714 CurrentFileDependencyList
= []
1716 CurrentFileDependencyList
= DepDb
[F
]
1719 Fd
= open(F
.Path
, 'rb')
1720 FileContent
= Fd
.read()
1722 except BaseException
as X
:
1723 EdkLogger
.error("build", FILE_OPEN_FAILURE
, ExtraData
=F
.Path
+ "\n\t" + str(X
))
1724 if len(FileContent
) == 0:
1727 if FileContent
[0] == 0xff or FileContent
[0] == 0xfe:
1728 FileContent
= FileContent
.decode('utf-16')
1730 FileContent
= FileContent
.decode()
1732 # The file is not txt file. for example .mcb file
1734 IncludedFileList
= gIncludePattern
.findall(FileContent
)
1736 for Inc
in IncludedFileList
:
1738 # if there's macro used to reference header file, expand it
1739 HeaderList
= gMacroPattern
.findall(Inc
)
1740 if len(HeaderList
) == 1 and len(HeaderList
[0]) == 2:
1741 HeaderType
= HeaderList
[0][0]
1742 HeaderKey
= HeaderList
[0][1]
1743 if HeaderType
in gIncludeMacroConversion
:
1744 Inc
= gIncludeMacroConversion
[HeaderType
] % {"HeaderKey" : HeaderKey
}
1746 # not known macro used in #include, always build the file by
1747 # returning a empty dependency
1748 FileCache
[File
] = []
1750 Inc
= os
.path
.normpath(Inc
)
1751 CurrentFileDependencyList
.append(Inc
)
1752 DepDb
[F
] = CurrentFileDependencyList
1754 CurrentFilePath
= F
.Dir
1755 PathList
= [CurrentFilePath
] + SearchPathList
1756 for Inc
in CurrentFileDependencyList
:
1757 for SearchPath
in PathList
:
1758 FilePath
= os
.path
.join(SearchPath
, Inc
)
1759 if FilePath
in gIsFileMap
:
1760 if not gIsFileMap
[FilePath
]:
1762 # If isfile is called too many times, the performance is slow down.
1763 elif not os
.path
.isfile(FilePath
):
1764 gIsFileMap
[FilePath
] = False
1767 gIsFileMap
[FilePath
] = True
1768 FilePath
= PathClass(FilePath
)
1769 FullPathDependList
.append(FilePath
)
1770 if FilePath
not in DependencySet
:
1771 FileStack
.append(FilePath
)
1774 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "%s included by %s was not found "\
1775 "in any given path:\n\t%s" % (Inc
, F
, "\n\t".join(SearchPathList
)))
1777 FileCache
[F
] = FullPathDependList
1778 DependencySet
.update(FullPathDependList
)
1780 DependencySet
.update(ForceList
)
1781 if File
in DependencySet
:
1782 DependencySet
.remove(File
)
1783 DependencyList
= list(DependencySet
) # remove duplicate ones
1785 return DependencyList
1787 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1788 if __name__
== '__main__':