2 # Create makefile for MS nmake and GNU make
4 # Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
5 # Copyright (c) 2020 - 2021, 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
", "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')
180 MakePath = AutoGenObject.ToolDefinition.get('MAKE', {}).get('PATH')
181 if "nmake
" in MakePath:
182 self._FileType = NMAKE_FILETYPE
184 self._FileType = GMAKE_FILETYPE
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 sorted(list(MyAgo.BuildOption)):
524 for Attr in sorted(list(MyAgo.BuildOption[Tool])):
525 Value = MyAgo.BuildOption[Tool][Attr]
529 ToolsDef.append("%s = %s" % (Tool, Value))
532 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
535 # Remove duplicated include path, if any
537 Value = RemoveDupOption(Value, IncPrefix, MyAgo.IncludePathList)
538 if Tool == "OPTROM
" and PCI_COMPRESS_Flag:
539 ValueList = Value.split()
541 for i, v in enumerate(ValueList):
544 Value = ' '.join(ValueList)
546 ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
551 # generate the Response file and Response flag
552 RespDict = self.CommandExceedLimit()
553 RespFileList = os.path.join(MyAgo.OutputDir, 'respfilelist.txt')
555 RespFileListContent = ''
556 for Resp in RespDict:
557 RespFile = os.path.join(MyAgo.OutputDir, str(Resp).lower() + '.txt')
558 StrList = RespDict[Resp].split(' ')
562 if '$' in Str or '-MMD' in Str or '-MF' in Str:
563 UnexpandMacro.append(Str)
566 UnexpandMacroStr = ' '.join(UnexpandMacro)
567 NewRespStr = ' '.join(NewStr)
568 SaveFileOnChange(RespFile, NewRespStr, False)
569 ToolsDef.append("%s = %s" % (Resp, UnexpandMacroStr + ' @' + RespFile))
570 RespFileListContent += '@' + RespFile + TAB_LINE_BREAK
571 RespFileListContent += NewRespStr + TAB_LINE_BREAK
572 SaveFileOnChange(RespFileList, RespFileListContent, False)
574 if os.path.exists(RespFileList):
575 os.remove(RespFileList)
577 # convert source files and binary files to build targets
578 self.ResultFileList = [str(T.Target) for T in MyAgo.CodaTargetList]
579 if len(self.ResultFileList) == 0 and len(MyAgo.SourceFileList) != 0:
580 EdkLogger.error("build
", AUTOGEN_ERROR, "Nothing to build
",
581 ExtraData="[%s]" % str(MyAgo))
583 self.ProcessBuildTargetList(MyAgo.OutputDir, ToolsDef)
584 self.ParserGenerateFfsCmd()
586 # Generate macros used to represent input files
587 FileMacroList = [] # macro name = file list
588 for FileListMacro in self.FileListMacros:
589 FileMacro = self._FILE_MACRO_TEMPLATE.Replace(
591 "macro_name
" : FileListMacro,
592 "source_file
" : self.FileListMacros[FileListMacro]
595 FileMacroList.append(FileMacro)
597 # INC_LIST is special
600 for P in MyAgo.IncludePathList:
601 IncludePathList.append(IncPrefix + self.PlaceMacro(P, self.Macros))
602 if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:
603 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix + P)
604 FileMacro += self._FILE_MACRO_TEMPLATE.Replace(
606 "macro_name
" : "INC
",
607 "source_file
" : IncludePathList
610 FileMacroList.append(FileMacro)
611 # Add support when compiling .nasm source files
613 asmsource = [item for item in MyAgo.SourceFileList if item.File.upper().endswith((".NASM
",".ASM
",".NASMB
","S
"))]
615 for P in MyAgo.IncludePathList:
616 IncludePath = self._INC_FLAG_['NASM'] + self.PlaceMacro(P, self.Macros)
617 if IncludePath.endswith(os.sep):
618 IncludePath = IncludePath.rstrip(os.sep)
619 # When compiling .nasm files, need to add a literal backslash at each path.
620 # In nmake makfiles, a trailing literal backslash must be escaped with a caret ('^').
621 # It is otherwise replaced with a space (' '). This is not necessary for GNU makfefiles.
622 if P == MyAgo.IncludePathList[-1] and self._Platform == WIN32_PLATFORM and self._FileType == NMAKE_FILETYPE:
623 IncludePath = ''.join([IncludePath, '^', os.sep])
625 IncludePath = os.path.join(IncludePath, '')
626 IncludePathList.append(IncludePath)
627 FileMacroList.append(self._FILE_MACRO_TEMPLATE.Replace({"macro_name
": "NASM_INC
", "source_file
": IncludePathList}))
629 # Generate macros used to represent files containing list of input files
630 for ListFileMacro in self.ListFileMacros:
631 ListFileName = os.path.join(MyAgo.OutputDir, "%s.lst
" % ListFileMacro.lower()[:len(ListFileMacro) - 5])
632 FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))
635 "\n".join(self.ListFileMacros[ListFileMacro]),
639 # Generate objlist used to create .obj file
640 for Type in self.ObjTargetDict:
641 NewLine = ' '.join(list(self.ObjTargetDict[Type]))
642 FileMacroList.append("OBJLIST_
%s = %s" % (list(self.ObjTargetDict.keys()).index(Type), NewLine))
646 MakefileName = self.getMakefileName()
647 LibraryMakeCommandList = []
648 for D in self.LibraryBuildDirectoryList:
649 Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":os.path.join(D, MakefileName)}
650 LibraryMakeCommandList.append(Command)
652 package_rel_dir = MyAgo.SourceDir
653 current_dir = self.Macros["WORKSPACE
"]
655 while not found and os.sep in package_rel_dir:
656 index = package_rel_dir.index(os.sep)
657 current_dir = mws.join(current_dir, package_rel_dir[:index])
658 if os.path.exists(current_dir):
659 for fl in os.listdir(current_dir):
660 if fl.endswith('.dec'):
663 package_rel_dir = package_rel_dir[index + 1:]
665 MakefileTemplateDict = {
666 "makefile_header
" : self._FILE_HEADER_[self._FileType],
667 "makefile_path
" : os.path.join("$
(MODULE_BUILD_DIR
)", MakefileName),
668 "makefile_name
" : MakefileName,
669 "platform_name
" : self.PlatformInfo.Name,
670 "platform_guid
" : self.PlatformInfo.Guid,
671 "platform_version
" : self.PlatformInfo.Version,
672 "platform_relative_directory
": self.PlatformInfo.SourceDir,
673 "platform_output_directory
" : self.PlatformInfo.OutputDir,
674 "ffs_output_directory
" : MyAgo.Macros["FFS_OUTPUT_DIR
"],
675 "platform_dir
" : MyAgo.Macros["PLATFORM_DIR
"],
677 "module_name
" : MyAgo.Name,
678 "module_guid
" : MyAgo.Guid,
679 "module_name_guid
" : MyAgo.UniqueBaseName,
680 "module_version
" : MyAgo.Version,
681 "module_type
" : MyAgo.ModuleType,
682 "module_file
" : MyAgo.MetaFile.Name,
683 "module_file_base_name
" : MyAgo.MetaFile.BaseName,
684 "module_relative_directory
" : MyAgo.SourceDir,
685 "module_dir
" : mws.join (self.Macros["WORKSPACE
"], MyAgo.SourceDir),
686 "package_relative_directory
": package_rel_dir,
687 "module_extra_defines
" : ["%s = %s" % (k, v) for k, v in MyAgo.Module.Defines.items()],
689 "architecture
" : MyAgo.Arch,
690 "toolchain_tag
" : MyAgo.ToolChain,
691 "build_target
" : MyAgo.BuildTarget,
693 "platform_build_directory
" : self.PlatformInfo.BuildDir,
694 "module_build_directory
" : MyAgo.BuildDir,
695 "module_output_directory
" : MyAgo.OutputDir,
696 "module_debug_directory
" : MyAgo.DebugDir,
698 "separator
" : Separator,
699 "module_tool_definitions
" : ToolsDef,
701 "shell_command_code
" : list(self._SHELL_CMD_[self._Platform].keys()),
702 "shell_command
" : list(self._SHELL_CMD_[self._Platform].values()),
704 "module_entry_point
" : ModuleEntryPoint,
705 "image_entry_point
" : ImageEntryPoint,
706 "arch_entry_point
" : ArchEntryPoint,
707 "remaining_build_target
" : self.ResultFileList,
708 "common_dependency_file
" : self.CommonFileDependency,
709 "create_directory_command
" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
710 "clean_command
" : self.GetRemoveDirectoryCommand(["$
(OUTPUT_DIR
)"]),
711 "cleanall_command
" : self.GetRemoveDirectoryCommand(["$
(DEBUG_DIR
)", "$
(OUTPUT_DIR
)"]),
712 "dependent_library_build_directory
" : self.LibraryBuildDirectoryList,
713 "library_build_command
" : LibraryMakeCommandList,
714 "file_macro
" : FileMacroList,
715 "file_build_target
" : self.BuildTargetList,
716 "backward_compatible_target
": BcTargetList,
717 "INCLUDETAG
" : "\n".join([self._INCLUDE_CMD_[self._FileType] + " " + os.path.join("$
(MODULE_BUILD_DIR
)","dependency
"),
718 self._INCLUDE_CMD_[self._FileType] + " " + os.path.join("$
(MODULE_BUILD_DIR
)","deps_target
")
722 return MakefileTemplateDict
724 def ParserGenerateFfsCmd(self):
725 #Add Ffs cmd to self.BuildTargetList
729 for Cmd in self.GenFfsList:
731 for CopyCmd in Cmd[2]:
733 Src = self.ReplaceMacro(Src)
734 Dst = self.ReplaceMacro(Dst)
735 if Dst not in self.ResultFileList:
736 self.ResultFileList.append(Dst)
737 if '%s :' %(Dst) not in self.BuildTargetList:
738 self.BuildTargetList.append("%s : %s" %(Dst,Src))
739 self.BuildTargetList.append('\t' + self._CP_TEMPLATE_[self._Platform] %{'Src': Src, 'Dst': Dst})
742 for index, Str in enumerate(FfsCmdList):
744 OutputFile = FfsCmdList[index + 1]
745 if '-i' == Str or "-oi
" == Str:
746 if DepsFileList == []:
747 DepsFileList = [FfsCmdList[index + 1]]
749 DepsFileList.append(FfsCmdList[index + 1])
750 DepsFileString = ' '.join(DepsFileList).strip()
751 if DepsFileString == '':
753 OutputFile = self.ReplaceMacro(OutputFile)
754 self.ResultFileList.append(OutputFile)
755 DepsFileString = self.ReplaceMacro(DepsFileString)
756 self.BuildTargetList.append('%s : %s' % (OutputFile, DepsFileString))
757 CmdString = ' '.join(FfsCmdList).strip()
758 CmdString = self.ReplaceMacro(CmdString)
759 self.BuildTargetList.append('\t%s' % CmdString)
761 self.ParseSecCmd(DepsFileList, Cmd[1])
762 for SecOutputFile, SecDepsFile, SecCmd in self.FfsOutputFileList :
763 self.BuildTargetList.append('%s : %s' % (self.ReplaceMacro(SecOutputFile), self.ReplaceMacro(SecDepsFile)))
764 self.BuildTargetList.append('\t%s' % self.ReplaceMacro(SecCmd))
765 self.FfsOutputFileList = []
767 def ParseSecCmd(self, OutputFileList, CmdTuple):
768 for OutputFile in OutputFileList:
769 for SecCmdStr in CmdTuple:
771 SecCmdList = SecCmdStr.split()
772 CmdName = SecCmdList[0]
773 for index, CmdItem in enumerate(SecCmdList):
774 if '-o' == CmdItem and OutputFile == SecCmdList[index + 1]:
776 while index + 1 < len(SecCmdList):
777 if not SecCmdList[index+1].startswith('-'):
778 SecDepsFileList.append(SecCmdList[index + 1])
780 if CmdName == 'Trim':
781 SecDepsFileList.append(os.path.join('$(DEBUG_DIR)', os.path.basename(OutputFile).replace('offset', 'efi')))
782 if OutputFile.endswith('.ui') or OutputFile.endswith('.ver'):
783 SecDepsFileList.append(os.path.join('$(MODULE_DIR)', '$(MODULE_FILE)'))
784 self.FfsOutputFileList.append((OutputFile, ' '.join(SecDepsFileList), SecCmdStr))
785 if len(SecDepsFileList) > 0:
786 self.ParseSecCmd(SecDepsFileList, CmdTuple)
791 def ReplaceMacro(self, str):
792 for Macro in self.MacroList:
793 if self._AutoGenObject.Macros[Macro] and os.path.normcase(self._AutoGenObject.Macros[Macro]) in os.path.normcase(str):
794 replace_dir = str[os.path.normcase(str).index(os.path.normcase(self._AutoGenObject.Macros[Macro])): os.path.normcase(str).index(
795 os.path.normcase(self._AutoGenObject.Macros[Macro])) + len(self._AutoGenObject.Macros[Macro])]
796 str = str.replace(replace_dir, '$(' + Macro + ')')
799 def CommandExceedLimit(self):
801 'CC' : { 'Macro' : '$(CC_FLAGS)', 'Value' : False},
802 'PP' : { 'Macro' : '$(PP_FLAGS)', 'Value' : False},
803 'APP' : { 'Macro' : '$(APP_FLAGS)', 'Value' : False},
804 'ASLPP' : { 'Macro' : '$(ASLPP_FLAGS)', 'Value' : False},
805 'VFRPP' : { 'Macro' : '$(VFRPP_FLAGS)', 'Value' : False},
806 'ASM' : { 'Macro' : '$(ASM_FLAGS)', 'Value' : False},
807 'ASLCC' : { 'Macro' : '$(ASLCC_FLAGS)', 'Value' : False},
812 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
814 # base on the source files to decide the file type
815 for File in self._AutoGenObject.SourceFileList:
816 for type in self._AutoGenObject.FileTypes:
817 if File in self._AutoGenObject.FileTypes[type]:
818 if type not in FileTypeList:
819 FileTypeList.append(type)
821 # calculate the command-line length
823 for type in FileTypeList:
824 BuildTargets = self._AutoGenObject.BuildRules[type].BuildTargets
825 for Target in BuildTargets:
826 CommandList = BuildTargets[Target].Commands
827 for SingleCommand in CommandList:
829 SingleCommandLength = len(SingleCommand)
830 SingleCommandList = SingleCommand.split()
831 if len(SingleCommandList) > 0:
832 for Flag in FlagDict:
833 if '$('+ Flag +')' in SingleCommandList[0]:
837 if 'PATH' not in self._AutoGenObject.BuildOption[Tool]:
838 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))
839 SingleCommandLength += len(self._AutoGenObject.BuildOption[Tool]['PATH
'])
840 for item in SingleCommandList[1:]:
841 if FlagDict[Tool]['Macro
'] in item:
842 if 'FLAGS
' not in self._AutoGenObject.BuildOption[Tool]:
843 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))
844 Str = self._AutoGenObject.BuildOption[Tool]['FLAGS']
845 for Option in self._AutoGenObject.BuildOption:
846 for Attr in self._AutoGenObject.BuildOption[Option]:
847 if Str.find(Option + '_' + Attr) != -1:
848 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
849 while(Str.find('$(') != -1):
850 for macro in self._AutoGenObject.Macros:
851 MacroName = '$('+ macro + ')'
852 if (Str.find(MacroName) != -1):
853 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
857 SingleCommandLength += len(Str)
858 elif '$(INC)' in item:
859 SingleCommandLength += self._AutoGenObject.IncludePathLength + len(IncPrefix) * len(self._AutoGenObject.IncludePathList)
860 elif item.find('$(') != -1:
862 for Option in self._AutoGenObject.BuildOption:
863 for Attr in self._AutoGenObject.BuildOption[Option]:
864 if Str.find(Option + '_' + Attr) != -1:
865 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
866 while(Str.find('$(') != -1):
867 for macro in self._AutoGenObject.Macros:
868 MacroName = '$('+ macro + ')'
869 if (Str.find(MacroName) != -1):
870 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
874 SingleCommandLength += len(Str)
876 if SingleCommandLength > GlobalData.gCommandMaxLength:
877 FlagDict[Tool]['Value'] = True
879 # generate the response file content by combine the FLAGS and INC
880 for Flag in FlagDict:
881 if FlagDict[Flag]['Value']:
883 RespMacro = FlagDict[Flag]['Macro'].replace('FLAGS', 'RESP')
884 Value = self._AutoGenObject.BuildOption[Flag]['FLAGS']
885 for inc in self._AutoGenObject.IncludePathList:
886 Value += ' ' + IncPrefix + inc
887 for Option in self._AutoGenObject.BuildOption:
888 for Attr in self._AutoGenObject.BuildOption[Option]:
889 if Value.find(Option + '_' + Attr) != -1:
890 Value = Value.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
891 while (Value.find('$(') != -1):
892 for macro in self._AutoGenObject.Macros:
893 MacroName = '$('+ macro + ')'
894 if (Value.find(MacroName) != -1):
895 Value = Value.replace(MacroName, self._AutoGenObject.Macros[macro])
900 if self._AutoGenObject.ToolChainFamily == 'GCC':
901 RespDict[Key] = Value.replace('\\', '/')
903 RespDict[Key] = Value
904 for Target in BuildTargets:
905 for i, SingleCommand in enumerate(BuildTargets[Target].Commands):
906 if FlagDict[Flag]['Macro'] in SingleCommand:
907 BuildTargets[Target].Commands[i] = SingleCommand.replace('$(INC)', '').replace(FlagDict[Flag]['Macro'], RespMacro)
910 def ProcessBuildTargetList(self, RespFile, ToolsDef):
912 # Search dependency file list for each source file
914 ForceIncludedFile = []
915 for File in self._AutoGenObject.AutoGenFileList:
917 ForceIncludedFile.append(File)
920 for Target in self._AutoGenObject.IntroTargetList:
921 SourceFileList.extend(Target.Inputs)
922 OutPutFileList.extend(Target.Outputs)
925 for Item in OutPutFileList:
926 if Item in SourceFileList:
927 SourceFileList.remove(Item)
929 FileDependencyDict = {item:ForceIncludedFile for item in SourceFileList}
931 for Dependency in FileDependencyDict.values():
932 self.DependencyHeaderFileSet.update(set(Dependency))
934 # Get a set of unique package includes from MetaFile
935 parentMetaFileIncludes = set()
936 for aInclude in self._AutoGenObject.PackageIncludePathList:
937 aIncludeName = str(aInclude)
938 parentMetaFileIncludes.add(aIncludeName.lower())
940 # Check if header files are listed in metafile
941 # Get a set of unique module header source files from MetaFile
942 headerFilesInMetaFileSet = set()
943 for aFile in self._AutoGenObject.SourceFileList:
944 aFileName = str(aFile)
945 if not aFileName.endswith('.h'):
947 headerFilesInMetaFileSet.add(aFileName.lower())
949 # Get a set of unique module autogen files
950 localAutoGenFileSet = set()
951 for aFile in self._AutoGenObject.AutoGenFileList:
952 localAutoGenFileSet.add(str(aFile).lower())
954 # Get a set of unique module dependency header files
955 # Exclude autogen files and files not in the source directory
956 # and files that are under the package include list
957 headerFileDependencySet = set()
958 localSourceDir = str(self._AutoGenObject.SourceDir).lower()
959 for Dependency in FileDependencyDict.values():
960 for aFile in Dependency:
961 aFileName = str(aFile).lower()
962 # Exclude non-header files
963 if not aFileName.endswith('.h'):
965 # Exclude autogen files
966 if aFileName in localAutoGenFileSet:
968 # Exclude include out of local scope
969 if localSourceDir not in aFileName:
971 # Exclude files covered by package includes
973 for aIncludePath in parentMetaFileIncludes:
974 if aIncludePath in aFileName:
979 # Keep the file to be checked
980 headerFileDependencySet.add(aFileName)
982 # Check if a module dependency header file is missing from the module's MetaFile
983 for aFile in headerFileDependencySet:
984 if aFile in headerFilesInMetaFileSet:
986 if GlobalData.gUseHashCache:
987 GlobalData.gModuleBuildTracking[self._AutoGenObject] = 'FAIL_METAFILE'
988 EdkLogger.warn("build
","Module MetaFile
[Sources
] is missing local header
!",
989 ExtraData = "Local Header
: " + aFile + " not found
in " + self._AutoGenObject.MetaFile.Path
992 for File,Dependency in FileDependencyDict.items():
996 self._AutoGenObject.AutoGenDepSet |= set(Dependency)
1001 DependencyDict = FileDependencyDict.copy()
1003 # Convert target description object to target string in makefile
1004 if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and TAB_C_CODE_FILE in self._AutoGenObject.Targets:
1005 for T in self._AutoGenObject.Targets[TAB_C_CODE_FILE]:
1006 NewFile = self.PlaceMacro(str(T), self.Macros)
1007 if not self.ObjTargetDict.get(T.Target.SubDir):
1008 self.ObjTargetDict[T.Target.SubDir] = set()
1009 self.ObjTargetDict[T.Target.SubDir].add(NewFile)
1010 for Type in self._AutoGenObject.Targets:
1011 resp_file_number = 0
1012 for T in self._AutoGenObject.Targets[Type]:
1013 # Generate related macros if needed
1014 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
1015 self.FileListMacros[T.FileListMacro] = []
1016 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:
1017 self.ListFileMacros[T.ListFileMacro] = []
1018 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:
1019 self.ListFileMacros[T.IncListFileMacro] = []
1023 # Add force-dependencies
1024 for Dep in T.Dependencies:
1025 Deps.append(self.PlaceMacro(str(Dep), self.Macros))
1026 if Dep != '$(MAKE_FILE)':
1027 CCodeDeps.append(self.PlaceMacro(str(Dep), self.Macros))
1028 # Add inclusion-dependencies
1029 if len(T.Inputs) == 1 and T.Inputs[0] in FileDependencyDict:
1030 for F in FileDependencyDict[T.Inputs[0]]:
1031 Deps.append(self.PlaceMacro(str(F), self.Macros))
1032 # Add source-dependencies
1034 NewFile = self.PlaceMacro(str(F), self.Macros)
1035 # In order to use file list macro as dependency
1037 # gnu tools need forward slash path separator, even on Windows
1038 self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/'))
1039 self.FileListMacros[T.FileListMacro].append(NewFile)
1040 elif T.GenFileListMacro:
1041 self.FileListMacros[T.FileListMacro].append(NewFile)
1043 Deps.append(NewFile)
1044 for key in self.FileListMacros:
1045 self.FileListMacros[key].sort()
1046 # Use file list macro as dependency
1047 if T.GenFileListMacro:
1048 Deps.append("$
(%s)" % T.FileListMacro)
1049 if Type in [TAB_OBJECT_FILE, TAB_STATIC_LIBRARY]:
1050 Deps.append("$
(%s)" % T.ListFileMacro)
1052 if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and Type == TAB_C_CODE_FILE:
1053 T, CmdTarget, CmdTargetDict, CmdCppDict = self.ParserCCodeFile(T, Type, CmdSumDict, CmdTargetDict,
1054 CmdCppDict, DependencyDict, RespFile,
1055 ToolsDef, resp_file_number)
1056 resp_file_number += 1
1057 TargetDict = {"target
": self.PlaceMacro(T.Target.Path, self.Macros), "cmd
": "\n\t".join(T.Commands),"deps
": CCodeDeps}
1058 CmdLine = self._BUILD_TARGET_TEMPLATE.Replace(TargetDict).rstrip().replace('\t$(OBJLIST', '$(OBJLIST')
1060 CmdLine = '%s%s' %(CmdLine, TAB_LINE_BREAK)
1061 if CCodeDeps or CmdLine:
1062 self.BuildTargetList.append(CmdLine)
1064 TargetDict = {"target
": self.PlaceMacro(T.Target.Path, self.Macros), "cmd
": "\n\t".join(T.Commands),"deps
": Deps}
1065 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
1067 # Add a Makefile rule for targets generating multiple files.
1068 # The main output is a prerequisite for the other output files.
1069 for i in T.Outputs[1:]:
1070 AnnexeTargetDict = {"target
": self.PlaceMacro(i.Path, self.Macros), "cmd
": "", "deps
": self.PlaceMacro(T.Target.Path, self.Macros)}
1071 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(AnnexeTargetDict))
1073 def ParserCCodeFile(self, T, Type, CmdSumDict, CmdTargetDict, CmdCppDict, DependencyDict, RespFile, ToolsDef,
1075 SaveFilePath = os.path.join(RespFile, "cc_resp_
%s.txt
" % resp_file_number)
1077 for item in self._AutoGenObject.Targets[Type]:
1078 CmdSumDict[item.Target.SubDir] = item.Target.BaseName
1079 for CppPath in item.Inputs:
1080 Path = self.PlaceMacro(CppPath.Path, self.Macros)
1081 if CmdCppDict.get(item.Target.SubDir):
1082 CmdCppDict[item.Target.SubDir].append(Path)
1084 CmdCppDict[item.Target.SubDir] = ['$(MAKE_FILE)', Path]
1085 if CppPath.Path in DependencyDict:
1086 for Temp in DependencyDict[CppPath.Path]:
1088 Path = self.PlaceMacro(Temp.Path, self.Macros)
1091 if Path not in (self.CommonFileDependency + CmdCppDict[item.Target.SubDir]):
1092 CmdCppDict[item.Target.SubDir].append(Path)
1094 CommandList = T.Commands[:]
1095 for Item in CommandList[:]:
1096 SingleCommandList = Item.split()
1097 if len(SingleCommandList) > 0 and self.CheckCCCmd(SingleCommandList):
1098 for Temp in SingleCommandList:
1099 if Temp.startswith('/Fo'):
1100 CmdSign = '%s%s' % (Temp.rsplit(TAB_SLASH, 1)[0], TAB_SLASH)
1104 if CmdSign not in list(CmdTargetDict.keys()):
1105 cmd = Item.replace(Temp, CmdSign)
1106 if SingleCommandList[-1] in cmd:
1107 CmdTargetDict[CmdSign] = [cmd.replace(SingleCommandList[-1], "").rstrip(), SingleCommandList[-1]]
1109 # CmdTargetDict[CmdSign] = "%s %s" % (CmdTargetDict[CmdSign], SingleCommandList[-1])
1110 CmdTargetDict[CmdSign].append(SingleCommandList[-1])
1111 Index = CommandList.index(Item)
1112 CommandList.pop(Index)
1113 if SingleCommandList[-1].endswith("%s%s.c
" % (TAB_SLASH, CmdSumDict[CmdSign[3:].rsplit(TAB_SLASH, 1)[0]])):
1114 Cpplist = CmdCppDict[T.Target.SubDir]
1115 Cpplist.insert(0, '$(OBJLIST_%d): ' % list(self.ObjTargetDict.keys()).index(T.Target.SubDir))
1116 source_files = CmdTargetDict[CmdSign][1:]
1117 source_files.insert(0, " ")
1118 if len(source_files)>2:
1119 SaveFileOnChange(SaveFilePath, " ".join(source_files), False)
1120 T.Commands[Index] = '%s\n\t%s $(cc_resp_%s)' % (
1121 ' \\\n\t'.join(Cpplist), CmdTargetDict[CmdSign][0], resp_file_number)
1122 ToolsDef.append("cc_resp_
%s = @%s" % (resp_file_number, SaveFilePath))
1124 elif len(source_files)<=2 and len(" ".join(CmdTargetDict[CmdSign][:2]))>GlobalData.gCommandMaxLength:
1125 SaveFileOnChange(SaveFilePath, " ".join(source_files), False)
1126 T.Commands[Index] = '%s\n\t%s $(cc_resp_%s)' % (
1127 ' \\\n\t'.join(Cpplist), CmdTargetDict[CmdSign][0], resp_file_number)
1128 ToolsDef.append("cc_resp_
%s = @%s" % (resp_file_number, SaveFilePath))
1131 T.Commands[Index] = '%s\n\t%s' % (' \\\n\t'.join(Cpplist), " ".join(CmdTargetDict[CmdSign]))
1133 T.Commands.pop(Index)
1134 return T, CmdSumDict, CmdTargetDict, CmdCppDict
1136 def CheckCCCmd(self, CommandList):
1137 for cmd in CommandList:
1141 ## For creating makefile targets for dependent libraries
1142 def ProcessDependentLibrary(self):
1143 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1144 if not LibraryAutoGen.IsBinaryModule:
1145 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
1147 ## Return a list containing source file's dependencies
1149 # @param FileList The list of source files
1150 # @param ForceInculeList The list of files which will be included forcely
1151 # @param SearchPathList The list of search path
1153 # @retval dict The mapping between source file path and its dependencies
1155 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
1158 Dependency[F] = GetDependencyList(self._AutoGenObject, self.FileCache, F, ForceInculeList, SearchPathList)
1162 ## CustomMakefile class
1164 # This class encapsules makefie and its generation for module. It uses template to generate
1165 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
1167 class CustomMakefile(BuildFile):
1168 ## template used to generate the makefile for module with custom makefile
1169 _TEMPLATE_ = TemplateString('''\
1173 # Platform Macro Definition
1175 PLATFORM_NAME = ${platform_name}
1176 PLATFORM_GUID = ${platform_guid}
1177 PLATFORM_VERSION = ${platform_version}
1178 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
1179 PLATFORM_DIR = ${platform_dir}
1180 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1183 # Module Macro Definition
1185 MODULE_NAME = ${module_name}
1186 MODULE_GUID = ${module_guid}
1187 MODULE_NAME_GUID = ${module_name_guid}
1188 MODULE_VERSION = ${module_version}
1189 MODULE_TYPE = ${module_type}
1190 MODULE_FILE = ${module_file}
1191 MODULE_FILE_BASE_NAME = ${module_file_base_name}
1192 BASE_NAME = $(MODULE_NAME)
1193 MODULE_RELATIVE_DIR = ${module_relative_directory}
1194 MODULE_DIR = ${module_dir}
1197 # Build Configuration Macro Definition
1199 ARCH = ${architecture}
1200 TOOLCHAIN = ${toolchain_tag}
1201 TOOLCHAIN_TAG = ${toolchain_tag}
1202 TARGET = ${build_target}
1205 # Build Directory Macro Definition
1207 # PLATFORM_BUILD_DIR = ${platform_build_directory}
1208 BUILD_DIR = ${platform_build_directory}
1209 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
1210 LIB_DIR = $(BIN_DIR)
1211 MODULE_BUILD_DIR = ${module_build_directory}
1212 OUTPUT_DIR = ${module_output_directory}
1213 DEBUG_DIR = ${module_debug_directory}
1214 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
1215 DEST_DIR_DEBUG = $(DEBUG_DIR)
1218 # Tools definitions specific to this module
1220 ${BEGIN}${module_tool_definitions}
1222 MAKE_FILE = ${makefile_path}
1225 # Shell Command Macro
1227 ${BEGIN}${shell_command_code} = ${shell_command}
1230 ${custom_makefile_content}
1233 # Target used when called from platform makefile, which will bypass the build of dependent libraries
1246 # Build Target used in multi-thread build mode, which no init target is needed
1252 # Initialization target: print build information and create necessary directories
1255 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
1256 ${BEGIN}\t-@${create_directory_command}\n${END}\
1260 ## Constructor of CustomMakefile
1262 # @param ModuleAutoGen Object of ModuleAutoGen class
1264 def __init__(self, ModuleAutoGen):
1265 BuildFile.__init__(self, ModuleAutoGen)
1266 self.PlatformInfo = self._AutoGenObject.PlatformInfo
1267 self.IntermediateDirectoryList = ["$
(DEBUG_DIR
)", "$
(OUTPUT_DIR
)"]
1268 self.DependencyHeaderFileSet = set()
1270 # Compose a dict object containing information used to do replacement in template
1272 def _TemplateDict(self):
1273 Separator = self._SEP_[self._Platform]
1274 MyAgo = self._AutoGenObject
1275 if self._FileType not in MyAgo.CustomMakefile:
1276 EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile
for %s" % self._FileType,
1277 ExtraData="[%s]" % str(MyAgo))
1278 MakefilePath = mws.join(
1280 MyAgo.CustomMakefile[self._FileType]
1283 CustomMakefile = open(MakefilePath, 'r').read()
1285 EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(MyAgo),
1286 ExtraData=MyAgo.CustomMakefile[self._FileType])
1290 for Tool in MyAgo.BuildOption:
1291 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
1294 for Attr in MyAgo.BuildOption[Tool]:
1295 if Attr == "FAMILY
":
1297 elif Attr == "PATH
":
1298 ToolsDef.append("%s = %s" % (Tool, MyAgo.BuildOption[Tool][Attr]))
1300 ToolsDef.append("%s_%s = %s" % (Tool, Attr, MyAgo.BuildOption[Tool][Attr]))
1303 MakefileName = self.getMakefileName()
1304 MakefileTemplateDict = {
1305 "makefile_header
" : self._FILE_HEADER_[self._FileType],
1306 "makefile_path
" : os.path.join("$
(MODULE_BUILD_DIR
)", MakefileName),
1307 "platform_name
" : self.PlatformInfo.Name,
1308 "platform_guid
" : self.PlatformInfo.Guid,
1309 "platform_version
" : self.PlatformInfo.Version,
1310 "platform_relative_directory
": self.PlatformInfo.SourceDir,
1311 "platform_output_directory
" : self.PlatformInfo.OutputDir,
1312 "platform_dir
" : MyAgo.Macros["PLATFORM_DIR
"],
1314 "module_name
" : MyAgo.Name,
1315 "module_guid
" : MyAgo.Guid,
1316 "module_name_guid
" : MyAgo.UniqueBaseName,
1317 "module_version
" : MyAgo.Version,
1318 "module_type
" : MyAgo.ModuleType,
1319 "module_file
" : MyAgo.MetaFile,
1320 "module_file_base_name
" : MyAgo.MetaFile.BaseName,
1321 "module_relative_directory
" : MyAgo.SourceDir,
1322 "module_dir
" : mws.join (MyAgo.WorkspaceDir, MyAgo.SourceDir),
1324 "architecture
" : MyAgo.Arch,
1325 "toolchain_tag
" : MyAgo.ToolChain,
1326 "build_target
" : MyAgo.BuildTarget,
1328 "platform_build_directory
" : self.PlatformInfo.BuildDir,
1329 "module_build_directory
" : MyAgo.BuildDir,
1330 "module_output_directory
" : MyAgo.OutputDir,
1331 "module_debug_directory
" : MyAgo.DebugDir,
1333 "separator
" : Separator,
1334 "module_tool_definitions
" : ToolsDef,
1336 "shell_command_code
" : list(self._SHELL_CMD_[self._Platform].keys()),
1337 "shell_command
" : list(self._SHELL_CMD_[self._Platform].values()),
1339 "create_directory_command
" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1340 "custom_makefile_content
" : CustomMakefile
1343 return MakefileTemplateDict
1345 ## PlatformMakefile class
1347 # This class encapsules makefie and its generation for platform. It uses
1348 # template to generate the content of makefile. The content of makefile will be
1349 # got from PlatformAutoGen object.
1351 class PlatformMakefile(BuildFile):
1352 ## template used to generate the makefile for platform
1353 _TEMPLATE_ = TemplateString('''\
1357 # Platform Macro Definition
1359 PLATFORM_NAME = ${platform_name}
1360 PLATFORM_GUID = ${platform_guid}
1361 PLATFORM_VERSION = ${platform_version}
1362 PLATFORM_FILE = ${platform_file}
1363 PLATFORM_DIR = ${platform_dir}
1364 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1367 # Build Configuration Macro Definition
1369 TOOLCHAIN = ${toolchain_tag}
1370 TOOLCHAIN_TAG = ${toolchain_tag}
1371 TARGET = ${build_target}
1374 # Build Directory Macro Definition
1376 BUILD_DIR = ${platform_build_directory}
1377 FV_DIR = ${platform_build_directory}${separator}FV
1380 # Shell Command Macro
1382 ${BEGIN}${shell_command_code} = ${shell_command}
1386 MAKE_FILE = ${makefile_path}
1391 all: init build_libraries build_modules
1394 # Initialization target: print build information and create necessary directories
1397 \t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
1398 \t${BEGIN}-@${create_directory_command}
1401 # library build target
1403 libraries: init build_libraries
1406 # module build target
1408 modules: init build_libraries build_modules
1411 # Build all libraries:
1414 ${BEGIN}\t@"$
(MAKE
)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
1415 ${END}\t@cd $(BUILD_DIR)
1418 # Build all modules:
1421 ${BEGIN}\t@"$
(MAKE
)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
1422 ${END}\t@cd $(BUILD_DIR)
1425 # Clean intermediate files
1428 \t${BEGIN}-@${library_build_command} clean
1429 \t${END}${BEGIN}-@${module_build_command} clean
1430 \t${END}@cd $(BUILD_DIR)
1433 # Clean all generated files except to makefile
1436 ${BEGIN}\t${cleanall_command}
1440 # Clean all library files
1443 \t${BEGIN}-@${library_build_command} cleanall
1444 \t${END}@cd $(BUILD_DIR)\n
1447 ## Constructor of PlatformMakefile
1449 # @param ModuleAutoGen Object of PlatformAutoGen class
1451 def __init__(self, PlatformAutoGen):
1452 BuildFile.__init__(self, PlatformAutoGen)
1453 self.ModuleBuildCommandList = []
1454 self.ModuleMakefileList = []
1455 self.IntermediateDirectoryList = []
1456 self.ModuleBuildDirectoryList = []
1457 self.LibraryBuildDirectoryList = []
1458 self.LibraryMakeCommandList = []
1459 self.DependencyHeaderFileSet = set()
1461 # Compose a dict object containing information used to do replacement in template
1463 def _TemplateDict(self):
1464 Separator = self._SEP_[self._Platform]
1466 MyAgo = self._AutoGenObject
1467 if "MAKE
" not in MyAgo.ToolDefinition or "PATH
" not in MyAgo.ToolDefinition["MAKE
"]:
1468 EdkLogger.error("build
", OPTION_MISSING, "No MAKE command defined
. Please check your tools_def
.txt
!",
1469 ExtraData="[%s]" % str(MyAgo))
1471 self.IntermediateDirectoryList = ["$
(BUILD_DIR
)"]
1472 self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()
1473 self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()
1475 MakefileName = self.getMakefileName()
1476 LibraryMakefileList = []
1477 LibraryMakeCommandList = []
1478 for D in self.LibraryBuildDirectoryList:
1479 D = self.PlaceMacro(D, {"BUILD_DIR
":MyAgo.BuildDir})
1480 Makefile = os.path.join(D, MakefileName)
1481 Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":Makefile}
1482 LibraryMakefileList.append(Makefile)
1483 LibraryMakeCommandList.append(Command)
1484 self.LibraryMakeCommandList = LibraryMakeCommandList
1486 ModuleMakefileList = []
1487 ModuleMakeCommandList = []
1488 for D in self.ModuleBuildDirectoryList:
1489 D = self.PlaceMacro(D, {"BUILD_DIR
":MyAgo.BuildDir})
1490 Makefile = os.path.join(D, MakefileName)
1491 Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":Makefile}
1492 ModuleMakefileList.append(Makefile)
1493 ModuleMakeCommandList.append(Command)
1495 MakefileTemplateDict = {
1496 "makefile_header
" : self._FILE_HEADER_[self._FileType],
1497 "makefile_path
" : os.path.join("$
(BUILD_DIR
)", MakefileName),
1498 "make_path
" : MyAgo.ToolDefinition["MAKE
"]["PATH
"],
1499 "makefile_name
" : MakefileName,
1500 "platform_name
" : MyAgo.Name,
1501 "platform_guid
" : MyAgo.Guid,
1502 "platform_version
" : MyAgo.Version,
1503 "platform_file
" : MyAgo.MetaFile,
1504 "platform_relative_directory
": MyAgo.SourceDir,
1505 "platform_output_directory
" : MyAgo.OutputDir,
1506 "platform_build_directory
" : MyAgo.BuildDir,
1507 "platform_dir
" : MyAgo.Macros["PLATFORM_DIR
"],
1509 "toolchain_tag
" : MyAgo.ToolChain,
1510 "build_target
" : MyAgo.BuildTarget,
1511 "shell_command_code
" : list(self._SHELL_CMD_[self._Platform].keys()),
1512 "shell_command
" : list(self._SHELL_CMD_[self._Platform].values()),
1513 "build_architecture_list
" : MyAgo.Arch,
1514 "architecture
" : MyAgo.Arch,
1515 "separator
" : Separator,
1516 "create_directory_command
" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1517 "cleanall_command
" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1518 "library_makefile_list
" : LibraryMakefileList,
1519 "module_makefile_list
" : ModuleMakefileList,
1520 "library_build_command
" : LibraryMakeCommandList,
1521 "module_build_command
" : ModuleMakeCommandList,
1524 return MakefileTemplateDict
1526 ## Get the root directory list for intermediate files of all modules build
1528 # @retval list The list of directory
1530 def GetModuleBuildDirectoryList(self):
1532 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1533 if not ModuleAutoGen.IsBinaryModule:
1534 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1537 ## Get the root directory list for intermediate files of all libraries build
1539 # @retval list The list of directory
1541 def GetLibraryBuildDirectoryList(self):
1543 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1544 if not LibraryAutoGen.IsBinaryModule:
1545 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1548 ## TopLevelMakefile class
1550 # This class encapsules makefie and its generation for entrance makefile. It
1551 # uses template to generate the content of makefile. The content of makefile
1552 # will be got from WorkspaceAutoGen object.
1554 class TopLevelMakefile(BuildFile):
1555 ## template used to generate toplevel makefile
1556 _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}''')
1558 ## Constructor of TopLevelMakefile
1560 # @param Workspace Object of WorkspaceAutoGen class
1562 def __init__(self, Workspace):
1563 BuildFile.__init__(self, Workspace)
1564 self.IntermediateDirectoryList = []
1565 self.DependencyHeaderFileSet = set()
1567 # Compose a dict object containing information used to do replacement in template
1569 def _TemplateDict(self):
1570 Separator = self._SEP_[self._Platform]
1572 # any platform autogen object is ok because we just need common information
1573 MyAgo = self._AutoGenObject
1575 if "MAKE
" not in MyAgo.ToolDefinition or "PATH
" not in MyAgo.ToolDefinition["MAKE
"]:
1576 EdkLogger.error("build
", OPTION_MISSING, "No MAKE command defined
. Please check your tools_def
.txt
!",
1577 ExtraData="[%s]" % str(MyAgo))
1579 for Arch in MyAgo.ArchList:
1580 self.IntermediateDirectoryList.append(Separator.join(["$
(BUILD_DIR
)", Arch]))
1581 self.IntermediateDirectoryList.append("$
(FV_DIR
)")
1583 # TRICK: for not generating GenFds call in makefile if no FDF file
1585 if MyAgo.FdfFile is not None and MyAgo.FdfFile != "":
1586 FdfFileList = [MyAgo.FdfFile]
1587 # macros passed to GenFds
1589 MacroDict.update(GlobalData.gGlobalDefines)
1590 MacroDict.update(GlobalData.gCommandLineDefines)
1591 for MacroName in MacroDict:
1592 if MacroDict[MacroName] != "":
1593 MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))
1595 MacroList.append('"%s"' % MacroName)
1599 # pass extra common options to external program called in makefile, currently GenFds.exe
1601 LogLevel = EdkLogger.GetLevel()
1602 if LogLevel == EdkLogger.VERBOSE:
1603 ExtraOption += " -v
"
1604 elif LogLevel <= EdkLogger.DEBUG_9:
1605 ExtraOption += " -d
%d" % (LogLevel - 1)
1606 elif LogLevel == EdkLogger.QUIET:
1607 ExtraOption += " -q
"
1609 if GlobalData.gCaseInsensitive:
1610 ExtraOption += " -c
"
1611 if not GlobalData.gEnableGenfdsMultiThread:
1612 ExtraOption += " --no
-genfds
-multi
-thread
"
1613 if GlobalData.gIgnoreSource:
1614 ExtraOption += " --ignore
-sources
"
1616 for pcd in GlobalData.BuildOptionPcd:
1618 pcdname = '.'.join(pcd[0:3])
1620 pcdname = '.'.join(pcd[0:2])
1621 if pcd[3].startswith('{'):
1622 ExtraOption += " --pcd
" + pcdname + '=' + 'H' + '"' + pcd[3] + '"'
1624 ExtraOption += " --pcd
" + pcdname + '=' + pcd[3]
1626 MakefileName = self.getMakefileName()
1627 SubBuildCommandList = []
1628 for A in MyAgo.ArchList:
1629 Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":os.path.join("$
(BUILD_DIR
)", A, MakefileName)}
1630 SubBuildCommandList.append(Command)
1632 MakefileTemplateDict = {
1633 "makefile_header
" : self._FILE_HEADER_[self._FileType],
1634 "makefile_path
" : os.path.join("$
(BUILD_DIR
)", MakefileName),
1635 "make_path
" : MyAgo.ToolDefinition["MAKE
"]["PATH
"],
1636 "platform_name
" : MyAgo.Name,
1637 "platform_guid
" : MyAgo.Guid,
1638 "platform_version
" : MyAgo.Version,
1639 "platform_build_directory
" : MyAgo.BuildDir,
1640 "conf_directory
" : GlobalData.gConfDirectory,
1642 "toolchain_tag
" : MyAgo.ToolChain,
1643 "build_target
" : MyAgo.BuildTarget,
1644 "shell_command_code
" : list(self._SHELL_CMD_[self._Platform].keys()),
1645 "shell_command
" : list(self._SHELL_CMD_[self._Platform].values()),
1646 'arch' : list(MyAgo.ArchList),
1647 "build_architecture_list
" : ','.join(MyAgo.ArchList),
1648 "separator
" : Separator,
1649 "create_directory_command
" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1650 "cleanall_command
" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1651 "sub_build_command
" : SubBuildCommandList,
1652 "fdf_file
" : FdfFileList,
1653 "active_platform
" : str(MyAgo),
1654 "fd
" : MyAgo.FdTargetList,
1655 "fv
" : MyAgo.FvTargetList,
1656 "cap
" : MyAgo.CapTargetList,
1657 "extra_options
" : ExtraOption,
1658 "macro
" : MacroList,
1661 return MakefileTemplateDict
1663 ## Get the root directory list for intermediate files of all modules build
1665 # @retval list The list of directory
1667 def GetModuleBuildDirectoryList(self):
1669 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1670 if not ModuleAutoGen.IsBinaryModule:
1671 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1674 ## Get the root directory list for intermediate files of all libraries build
1676 # @retval list The list of directory
1678 def GetLibraryBuildDirectoryList(self):
1680 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1681 if not LibraryAutoGen.IsBinaryModule:
1682 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1685 ## Find dependencies for one source file
1687 # By searching recursively "#include" directive in file, find out all the
1688 # files needed by given source file. The dependencies will be only searched
1689 # in given search path list.
1691 # @param File The source file
1692 # @param ForceInculeList The list of files which will be included forcely
1693 # @param SearchPathList The list of search path
1695 # @retval list The list of files the given source file depends on
1697 def GetDependencyList(AutoGenObject
, FileCache
, File
, ForceList
, SearchPathList
):
1698 EdkLogger
.debug(EdkLogger
.DEBUG_1
, "Try to get dependency files for %s" % File
)
1699 FileStack
= [File
] + ForceList
1700 DependencySet
= set()
1702 if AutoGenObject
.Arch
not in gDependencyDatabase
:
1703 gDependencyDatabase
[AutoGenObject
.Arch
] = {}
1704 DepDb
= gDependencyDatabase
[AutoGenObject
.Arch
]
1706 while len(FileStack
) > 0:
1709 FullPathDependList
= []
1711 for CacheFile
in FileCache
[F
]:
1712 FullPathDependList
.append(CacheFile
)
1713 if CacheFile
not in DependencySet
:
1714 FileStack
.append(CacheFile
)
1715 DependencySet
.update(FullPathDependList
)
1718 CurrentFileDependencyList
= []
1720 CurrentFileDependencyList
= DepDb
[F
]
1723 Fd
= open(F
.Path
, 'rb')
1724 FileContent
= Fd
.read()
1726 except BaseException
as X
:
1727 EdkLogger
.error("build", FILE_OPEN_FAILURE
, ExtraData
=F
.Path
+ "\n\t" + str(X
))
1728 if len(FileContent
) == 0:
1731 if FileContent
[0] == 0xff or FileContent
[0] == 0xfe:
1732 FileContent
= FileContent
.decode('utf-16')
1734 FileContent
= FileContent
.decode()
1736 # The file is not txt file. for example .mcb file
1738 IncludedFileList
= gIncludePattern
.findall(FileContent
)
1740 for Inc
in IncludedFileList
:
1742 # if there's macro used to reference header file, expand it
1743 HeaderList
= gMacroPattern
.findall(Inc
)
1744 if len(HeaderList
) == 1 and len(HeaderList
[0]) == 2:
1745 HeaderType
= HeaderList
[0][0]
1746 HeaderKey
= HeaderList
[0][1]
1747 if HeaderType
in gIncludeMacroConversion
:
1748 Inc
= gIncludeMacroConversion
[HeaderType
] % {"HeaderKey" : HeaderKey
}
1750 # not known macro used in #include, always build the file by
1751 # returning a empty dependency
1752 FileCache
[File
] = []
1754 Inc
= os
.path
.normpath(Inc
)
1755 CurrentFileDependencyList
.append(Inc
)
1756 DepDb
[F
] = CurrentFileDependencyList
1758 CurrentFilePath
= F
.Dir
1759 PathList
= [CurrentFilePath
] + SearchPathList
1760 for Inc
in CurrentFileDependencyList
:
1761 for SearchPath
in PathList
:
1762 FilePath
= os
.path
.join(SearchPath
, Inc
)
1763 if FilePath
in gIsFileMap
:
1764 if not gIsFileMap
[FilePath
]:
1766 # If isfile is called too many times, the performance is slow down.
1767 elif not os
.path
.isfile(FilePath
):
1768 gIsFileMap
[FilePath
] = False
1771 gIsFileMap
[FilePath
] = True
1772 FilePath
= PathClass(FilePath
)
1773 FullPathDependList
.append(FilePath
)
1774 if FilePath
not in DependencySet
:
1775 FileStack
.append(FilePath
)
1778 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "%s included by %s was not found "\
1779 "in any given path:\n\t%s" % (Inc
, F
, "\n\t".join(SearchPathList
)))
1781 FileCache
[F
] = FullPathDependList
1782 DependencySet
.update(FullPathDependList
)
1784 DependencySet
.update(ForceList
)
1785 if File
in DependencySet
:
1786 DependencySet
.remove(File
)
1787 DependencyList
= list(DependencySet
) # remove duplicate ones
1789 return DependencyList
1791 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1792 if __name__
== '__main__':