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 BaseName = SingleCommandList[-1].rsplit('.',1)[0]
1114 if BaseName.endswith("%s%s" % (TAB_SLASH, CmdSumDict[CmdSign[3:].rsplit(TAB_SLASH, 1)[0]])):
1115 Cpplist = CmdCppDict[T.Target.SubDir]
1116 Cpplist.insert(0, '$(OBJLIST_%d): ' % list(self.ObjTargetDict.keys()).index(T.Target.SubDir))
1117 source_files = CmdTargetDict[CmdSign][1:]
1118 source_files.insert(0, " ")
1119 if len(source_files)>2:
1120 SaveFileOnChange(SaveFilePath, " ".join(source_files), False)
1121 T.Commands[Index] = '%s\n\t%s $(cc_resp_%s)' % (
1122 ' \\\n\t'.join(Cpplist), CmdTargetDict[CmdSign][0], resp_file_number)
1123 ToolsDef.append("cc_resp_
%s = @%s" % (resp_file_number, SaveFilePath))
1125 elif len(source_files)<=2 and len(" ".join(CmdTargetDict[CmdSign][:2]))>GlobalData.gCommandMaxLength:
1126 SaveFileOnChange(SaveFilePath, " ".join(source_files), False)
1127 T.Commands[Index] = '%s\n\t%s $(cc_resp_%s)' % (
1128 ' \\\n\t'.join(Cpplist), CmdTargetDict[CmdSign][0], resp_file_number)
1129 ToolsDef.append("cc_resp_
%s = @%s" % (resp_file_number, SaveFilePath))
1132 T.Commands[Index] = '%s\n\t%s' % (' \\\n\t'.join(Cpplist), " ".join(CmdTargetDict[CmdSign]))
1134 T.Commands.pop(Index)
1135 return T, CmdSumDict, CmdTargetDict, CmdCppDict
1137 def CheckCCCmd(self, CommandList):
1138 for cmd in CommandList:
1142 ## For creating makefile targets for dependent libraries
1143 def ProcessDependentLibrary(self):
1144 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1145 if not LibraryAutoGen.IsBinaryModule:
1146 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
1148 ## Return a list containing source file's dependencies
1150 # @param FileList The list of source files
1151 # @param ForceInculeList The list of files which will be included forcely
1152 # @param SearchPathList The list of search path
1154 # @retval dict The mapping between source file path and its dependencies
1156 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
1159 Dependency[F] = GetDependencyList(self._AutoGenObject, self.FileCache, F, ForceInculeList, SearchPathList)
1163 ## CustomMakefile class
1165 # This class encapsules makefie and its generation for module. It uses template to generate
1166 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
1168 class CustomMakefile(BuildFile):
1169 ## template used to generate the makefile for module with custom makefile
1170 _TEMPLATE_ = TemplateString('''\
1174 # Platform Macro Definition
1176 PLATFORM_NAME = ${platform_name}
1177 PLATFORM_GUID = ${platform_guid}
1178 PLATFORM_VERSION = ${platform_version}
1179 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
1180 PLATFORM_DIR = ${platform_dir}
1181 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1184 # Module Macro Definition
1186 MODULE_NAME = ${module_name}
1187 MODULE_GUID = ${module_guid}
1188 MODULE_NAME_GUID = ${module_name_guid}
1189 MODULE_VERSION = ${module_version}
1190 MODULE_TYPE = ${module_type}
1191 MODULE_FILE = ${module_file}
1192 MODULE_FILE_BASE_NAME = ${module_file_base_name}
1193 BASE_NAME = $(MODULE_NAME)
1194 MODULE_RELATIVE_DIR = ${module_relative_directory}
1195 MODULE_DIR = ${module_dir}
1198 # Build Configuration Macro Definition
1200 ARCH = ${architecture}
1201 TOOLCHAIN = ${toolchain_tag}
1202 TOOLCHAIN_TAG = ${toolchain_tag}
1203 TARGET = ${build_target}
1206 # Build Directory Macro Definition
1208 # PLATFORM_BUILD_DIR = ${platform_build_directory}
1209 BUILD_DIR = ${platform_build_directory}
1210 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
1211 LIB_DIR = $(BIN_DIR)
1212 MODULE_BUILD_DIR = ${module_build_directory}
1213 OUTPUT_DIR = ${module_output_directory}
1214 DEBUG_DIR = ${module_debug_directory}
1215 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
1216 DEST_DIR_DEBUG = $(DEBUG_DIR)
1219 # Tools definitions specific to this module
1221 ${BEGIN}${module_tool_definitions}
1223 MAKE_FILE = ${makefile_path}
1226 # Shell Command Macro
1228 ${BEGIN}${shell_command_code} = ${shell_command}
1231 ${custom_makefile_content}
1234 # Target used when called from platform makefile, which will bypass the build of dependent libraries
1247 # Build Target used in multi-thread build mode, which no init target is needed
1253 # Initialization target: print build information and create necessary directories
1256 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
1257 ${BEGIN}\t-@${create_directory_command}\n${END}\
1261 ## Constructor of CustomMakefile
1263 # @param ModuleAutoGen Object of ModuleAutoGen class
1265 def __init__(self, ModuleAutoGen):
1266 BuildFile.__init__(self, ModuleAutoGen)
1267 self.PlatformInfo = self._AutoGenObject.PlatformInfo
1268 self.IntermediateDirectoryList = ["$
(DEBUG_DIR
)", "$
(OUTPUT_DIR
)"]
1269 self.DependencyHeaderFileSet = set()
1271 # Compose a dict object containing information used to do replacement in template
1273 def _TemplateDict(self):
1274 Separator = self._SEP_[self._Platform]
1275 MyAgo = self._AutoGenObject
1276 if self._FileType not in MyAgo.CustomMakefile:
1277 EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile
for %s" % self._FileType,
1278 ExtraData="[%s]" % str(MyAgo))
1279 MakefilePath = mws.join(
1281 MyAgo.CustomMakefile[self._FileType]
1284 CustomMakefile = open(MakefilePath, 'r').read()
1286 EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(MyAgo),
1287 ExtraData=MyAgo.CustomMakefile[self._FileType])
1291 for Tool in MyAgo.BuildOption:
1292 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
1295 for Attr in MyAgo.BuildOption[Tool]:
1296 if Attr == "FAMILY
":
1298 elif Attr == "PATH
":
1299 ToolsDef.append("%s = %s" % (Tool, MyAgo.BuildOption[Tool][Attr]))
1301 ToolsDef.append("%s_%s = %s" % (Tool, Attr, MyAgo.BuildOption[Tool][Attr]))
1304 MakefileName = self.getMakefileName()
1305 MakefileTemplateDict = {
1306 "makefile_header
" : self._FILE_HEADER_[self._FileType],
1307 "makefile_path
" : os.path.join("$
(MODULE_BUILD_DIR
)", MakefileName),
1308 "platform_name
" : self.PlatformInfo.Name,
1309 "platform_guid
" : self.PlatformInfo.Guid,
1310 "platform_version
" : self.PlatformInfo.Version,
1311 "platform_relative_directory
": self.PlatformInfo.SourceDir,
1312 "platform_output_directory
" : self.PlatformInfo.OutputDir,
1313 "platform_dir
" : MyAgo.Macros["PLATFORM_DIR
"],
1315 "module_name
" : MyAgo.Name,
1316 "module_guid
" : MyAgo.Guid,
1317 "module_name_guid
" : MyAgo.UniqueBaseName,
1318 "module_version
" : MyAgo.Version,
1319 "module_type
" : MyAgo.ModuleType,
1320 "module_file
" : MyAgo.MetaFile,
1321 "module_file_base_name
" : MyAgo.MetaFile.BaseName,
1322 "module_relative_directory
" : MyAgo.SourceDir,
1323 "module_dir
" : mws.join (MyAgo.WorkspaceDir, MyAgo.SourceDir),
1325 "architecture
" : MyAgo.Arch,
1326 "toolchain_tag
" : MyAgo.ToolChain,
1327 "build_target
" : MyAgo.BuildTarget,
1329 "platform_build_directory
" : self.PlatformInfo.BuildDir,
1330 "module_build_directory
" : MyAgo.BuildDir,
1331 "module_output_directory
" : MyAgo.OutputDir,
1332 "module_debug_directory
" : MyAgo.DebugDir,
1334 "separator
" : Separator,
1335 "module_tool_definitions
" : ToolsDef,
1337 "shell_command_code
" : list(self._SHELL_CMD_[self._Platform].keys()),
1338 "shell_command
" : list(self._SHELL_CMD_[self._Platform].values()),
1340 "create_directory_command
" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1341 "custom_makefile_content
" : CustomMakefile
1344 return MakefileTemplateDict
1346 ## PlatformMakefile class
1348 # This class encapsules makefie and its generation for platform. It uses
1349 # template to generate the content of makefile. The content of makefile will be
1350 # got from PlatformAutoGen object.
1352 class PlatformMakefile(BuildFile):
1353 ## template used to generate the makefile for platform
1354 _TEMPLATE_ = TemplateString('''\
1358 # Platform Macro Definition
1360 PLATFORM_NAME = ${platform_name}
1361 PLATFORM_GUID = ${platform_guid}
1362 PLATFORM_VERSION = ${platform_version}
1363 PLATFORM_FILE = ${platform_file}
1364 PLATFORM_DIR = ${platform_dir}
1365 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1368 # Build Configuration Macro Definition
1370 TOOLCHAIN = ${toolchain_tag}
1371 TOOLCHAIN_TAG = ${toolchain_tag}
1372 TARGET = ${build_target}
1375 # Build Directory Macro Definition
1377 BUILD_DIR = ${platform_build_directory}
1378 FV_DIR = ${platform_build_directory}${separator}FV
1381 # Shell Command Macro
1383 ${BEGIN}${shell_command_code} = ${shell_command}
1387 MAKE_FILE = ${makefile_path}
1392 all: init build_libraries build_modules
1395 # Initialization target: print build information and create necessary directories
1398 \t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
1399 \t${BEGIN}-@${create_directory_command}
1402 # library build target
1404 libraries: init build_libraries
1407 # module build target
1409 modules: init build_libraries build_modules
1412 # Build all libraries:
1415 ${BEGIN}\t@"$
(MAKE
)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
1416 ${END}\t@cd $(BUILD_DIR)
1419 # Build all modules:
1422 ${BEGIN}\t@"$
(MAKE
)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
1423 ${END}\t@cd $(BUILD_DIR)
1426 # Clean intermediate files
1429 \t${BEGIN}-@${library_build_command} clean
1430 \t${END}${BEGIN}-@${module_build_command} clean
1431 \t${END}@cd $(BUILD_DIR)
1434 # Clean all generated files except to makefile
1437 ${BEGIN}\t${cleanall_command}
1441 # Clean all library files
1444 \t${BEGIN}-@${library_build_command} cleanall
1445 \t${END}@cd $(BUILD_DIR)\n
1448 ## Constructor of PlatformMakefile
1450 # @param ModuleAutoGen Object of PlatformAutoGen class
1452 def __init__(self, PlatformAutoGen):
1453 BuildFile.__init__(self, PlatformAutoGen)
1454 self.ModuleBuildCommandList = []
1455 self.ModuleMakefileList = []
1456 self.IntermediateDirectoryList = []
1457 self.ModuleBuildDirectoryList = []
1458 self.LibraryBuildDirectoryList = []
1459 self.LibraryMakeCommandList = []
1460 self.DependencyHeaderFileSet = set()
1462 # Compose a dict object containing information used to do replacement in template
1464 def _TemplateDict(self):
1465 Separator = self._SEP_[self._Platform]
1467 MyAgo = self._AutoGenObject
1468 if "MAKE
" not in MyAgo.ToolDefinition or "PATH
" not in MyAgo.ToolDefinition["MAKE
"]:
1469 EdkLogger.error("build
", OPTION_MISSING, "No MAKE command defined
. Please check your tools_def
.txt
!",
1470 ExtraData="[%s]" % str(MyAgo))
1472 self.IntermediateDirectoryList = ["$
(BUILD_DIR
)"]
1473 self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()
1474 self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()
1476 MakefileName = self.getMakefileName()
1477 LibraryMakefileList = []
1478 LibraryMakeCommandList = []
1479 for D in self.LibraryBuildDirectoryList:
1480 D = self.PlaceMacro(D, {"BUILD_DIR
":MyAgo.BuildDir})
1481 Makefile = os.path.join(D, MakefileName)
1482 Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":Makefile}
1483 LibraryMakefileList.append(Makefile)
1484 LibraryMakeCommandList.append(Command)
1485 self.LibraryMakeCommandList = LibraryMakeCommandList
1487 ModuleMakefileList = []
1488 ModuleMakeCommandList = []
1489 for D in self.ModuleBuildDirectoryList:
1490 D = self.PlaceMacro(D, {"BUILD_DIR
":MyAgo.BuildDir})
1491 Makefile = os.path.join(D, MakefileName)
1492 Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":Makefile}
1493 ModuleMakefileList.append(Makefile)
1494 ModuleMakeCommandList.append(Command)
1496 MakefileTemplateDict = {
1497 "makefile_header
" : self._FILE_HEADER_[self._FileType],
1498 "makefile_path
" : os.path.join("$
(BUILD_DIR
)", MakefileName),
1499 "make_path
" : MyAgo.ToolDefinition["MAKE
"]["PATH
"],
1500 "makefile_name
" : MakefileName,
1501 "platform_name
" : MyAgo.Name,
1502 "platform_guid
" : MyAgo.Guid,
1503 "platform_version
" : MyAgo.Version,
1504 "platform_file
" : MyAgo.MetaFile,
1505 "platform_relative_directory
": MyAgo.SourceDir,
1506 "platform_output_directory
" : MyAgo.OutputDir,
1507 "platform_build_directory
" : MyAgo.BuildDir,
1508 "platform_dir
" : MyAgo.Macros["PLATFORM_DIR
"],
1510 "toolchain_tag
" : MyAgo.ToolChain,
1511 "build_target
" : MyAgo.BuildTarget,
1512 "shell_command_code
" : list(self._SHELL_CMD_[self._Platform].keys()),
1513 "shell_command
" : list(self._SHELL_CMD_[self._Platform].values()),
1514 "build_architecture_list
" : MyAgo.Arch,
1515 "architecture
" : MyAgo.Arch,
1516 "separator
" : Separator,
1517 "create_directory_command
" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1518 "cleanall_command
" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1519 "library_makefile_list
" : LibraryMakefileList,
1520 "module_makefile_list
" : ModuleMakefileList,
1521 "library_build_command
" : LibraryMakeCommandList,
1522 "module_build_command
" : ModuleMakeCommandList,
1525 return MakefileTemplateDict
1527 ## Get the root directory list for intermediate files of all modules build
1529 # @retval list The list of directory
1531 def GetModuleBuildDirectoryList(self):
1533 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1534 if not ModuleAutoGen.IsBinaryModule:
1535 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1538 ## Get the root directory list for intermediate files of all libraries build
1540 # @retval list The list of directory
1542 def GetLibraryBuildDirectoryList(self):
1544 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1545 if not LibraryAutoGen.IsBinaryModule:
1546 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1549 ## TopLevelMakefile class
1551 # This class encapsules makefie and its generation for entrance makefile. It
1552 # uses template to generate the content of makefile. The content of makefile
1553 # will be got from WorkspaceAutoGen object.
1555 class TopLevelMakefile(BuildFile):
1556 ## template used to generate toplevel makefile
1557 _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}''')
1559 ## Constructor of TopLevelMakefile
1561 # @param Workspace Object of WorkspaceAutoGen class
1563 def __init__(self, Workspace):
1564 BuildFile.__init__(self, Workspace)
1565 self.IntermediateDirectoryList = []
1566 self.DependencyHeaderFileSet = set()
1568 # Compose a dict object containing information used to do replacement in template
1570 def _TemplateDict(self):
1571 Separator = self._SEP_[self._Platform]
1573 # any platform autogen object is ok because we just need common information
1574 MyAgo = self._AutoGenObject
1576 if "MAKE
" not in MyAgo.ToolDefinition or "PATH
" not in MyAgo.ToolDefinition["MAKE
"]:
1577 EdkLogger.error("build
", OPTION_MISSING, "No MAKE command defined
. Please check your tools_def
.txt
!",
1578 ExtraData="[%s]" % str(MyAgo))
1580 for Arch in MyAgo.ArchList:
1581 self.IntermediateDirectoryList.append(Separator.join(["$
(BUILD_DIR
)", Arch]))
1582 self.IntermediateDirectoryList.append("$
(FV_DIR
)")
1584 # TRICK: for not generating GenFds call in makefile if no FDF file
1586 if MyAgo.FdfFile is not None and MyAgo.FdfFile != "":
1587 FdfFileList = [MyAgo.FdfFile]
1588 # macros passed to GenFds
1590 MacroDict.update(GlobalData.gGlobalDefines)
1591 MacroDict.update(GlobalData.gCommandLineDefines)
1592 for MacroName in MacroDict:
1593 if MacroDict[MacroName] != "":
1594 MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))
1596 MacroList.append('"%s"' % MacroName)
1600 # pass extra common options to external program called in makefile, currently GenFds.exe
1602 LogLevel = EdkLogger.GetLevel()
1603 if LogLevel == EdkLogger.VERBOSE:
1604 ExtraOption += " -v
"
1605 elif LogLevel <= EdkLogger.DEBUG_9:
1606 ExtraOption += " -d
%d" % (LogLevel - 1)
1607 elif LogLevel == EdkLogger.QUIET:
1608 ExtraOption += " -q
"
1610 if GlobalData.gCaseInsensitive:
1611 ExtraOption += " -c
"
1612 if not GlobalData.gEnableGenfdsMultiThread:
1613 ExtraOption += " --no
-genfds
-multi
-thread
"
1614 if GlobalData.gIgnoreSource:
1615 ExtraOption += " --ignore
-sources
"
1617 for pcd in GlobalData.BuildOptionPcd:
1619 pcdname = '.'.join(pcd[0:3])
1621 pcdname = '.'.join(pcd[0:2])
1622 if pcd[3].startswith('{'):
1623 ExtraOption += " --pcd
" + pcdname + '=' + 'H' + '"' + pcd[3] + '"'
1625 ExtraOption += " --pcd
" + pcdname + '=' + pcd[3]
1627 MakefileName = self.getMakefileName()
1628 SubBuildCommandList = []
1629 for A in MyAgo.ArchList:
1630 Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":os.path.join("$
(BUILD_DIR
)", A, MakefileName)}
1631 SubBuildCommandList.append(Command)
1633 MakefileTemplateDict = {
1634 "makefile_header
" : self._FILE_HEADER_[self._FileType],
1635 "makefile_path
" : os.path.join("$
(BUILD_DIR
)", MakefileName),
1636 "make_path
" : MyAgo.ToolDefinition["MAKE
"]["PATH
"],
1637 "platform_name
" : MyAgo.Name,
1638 "platform_guid
" : MyAgo.Guid,
1639 "platform_version
" : MyAgo.Version,
1640 "platform_build_directory
" : MyAgo.BuildDir,
1641 "conf_directory
" : GlobalData.gConfDirectory,
1643 "toolchain_tag
" : MyAgo.ToolChain,
1644 "build_target
" : MyAgo.BuildTarget,
1645 "shell_command_code
" : list(self._SHELL_CMD_[self._Platform].keys()),
1646 "shell_command
" : list(self._SHELL_CMD_[self._Platform].values()),
1647 'arch' : list(MyAgo.ArchList),
1648 "build_architecture_list
" : ','.join(MyAgo.ArchList),
1649 "separator
" : Separator,
1650 "create_directory_command
" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1651 "cleanall_command
" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1652 "sub_build_command
" : SubBuildCommandList,
1653 "fdf_file
" : FdfFileList,
1654 "active_platform
" : str(MyAgo),
1655 "fd
" : MyAgo.FdTargetList,
1656 "fv
" : MyAgo.FvTargetList,
1657 "cap
" : MyAgo.CapTargetList,
1658 "extra_options
" : ExtraOption,
1659 "macro
" : MacroList,
1662 return MakefileTemplateDict
1664 ## Get the root directory list for intermediate files of all modules build
1666 # @retval list The list of directory
1668 def GetModuleBuildDirectoryList(self):
1670 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1671 if not ModuleAutoGen.IsBinaryModule:
1672 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1675 ## Get the root directory list for intermediate files of all libraries build
1677 # @retval list The list of directory
1679 def GetLibraryBuildDirectoryList(self):
1681 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1682 if not LibraryAutoGen.IsBinaryModule:
1683 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1686 ## Find dependencies for one source file
1688 # By searching recursively "#include" directive in file, find out all the
1689 # files needed by given source file. The dependencies will be only searched
1690 # in given search path list.
1692 # @param File The source file
1693 # @param ForceInculeList The list of files which will be included forcely
1694 # @param SearchPathList The list of search path
1696 # @retval list The list of files the given source file depends on
1698 def GetDependencyList(AutoGenObject
, FileCache
, File
, ForceList
, SearchPathList
):
1699 EdkLogger
.debug(EdkLogger
.DEBUG_1
, "Try to get dependency files for %s" % File
)
1700 FileStack
= [File
] + ForceList
1701 DependencySet
= set()
1703 if AutoGenObject
.Arch
not in gDependencyDatabase
:
1704 gDependencyDatabase
[AutoGenObject
.Arch
] = {}
1705 DepDb
= gDependencyDatabase
[AutoGenObject
.Arch
]
1707 while len(FileStack
) > 0:
1710 FullPathDependList
= []
1712 for CacheFile
in FileCache
[F
]:
1713 FullPathDependList
.append(CacheFile
)
1714 if CacheFile
not in DependencySet
:
1715 FileStack
.append(CacheFile
)
1716 DependencySet
.update(FullPathDependList
)
1719 CurrentFileDependencyList
= []
1721 CurrentFileDependencyList
= DepDb
[F
]
1724 Fd
= open(F
.Path
, 'rb')
1725 FileContent
= Fd
.read()
1727 except BaseException
as X
:
1728 EdkLogger
.error("build", FILE_OPEN_FAILURE
, ExtraData
=F
.Path
+ "\n\t" + str(X
))
1729 if len(FileContent
) == 0:
1732 if FileContent
[0] == 0xff or FileContent
[0] == 0xfe:
1733 FileContent
= FileContent
.decode('utf-16')
1735 FileContent
= FileContent
.decode()
1737 # The file is not txt file. for example .mcb file
1739 IncludedFileList
= gIncludePattern
.findall(FileContent
)
1741 for Inc
in IncludedFileList
:
1743 # if there's macro used to reference header file, expand it
1744 HeaderList
= gMacroPattern
.findall(Inc
)
1745 if len(HeaderList
) == 1 and len(HeaderList
[0]) == 2:
1746 HeaderType
= HeaderList
[0][0]
1747 HeaderKey
= HeaderList
[0][1]
1748 if HeaderType
in gIncludeMacroConversion
:
1749 Inc
= gIncludeMacroConversion
[HeaderType
] % {"HeaderKey" : HeaderKey
}
1751 # not known macro used in #include, always build the file by
1752 # returning a empty dependency
1753 FileCache
[File
] = []
1755 Inc
= os
.path
.normpath(Inc
)
1756 CurrentFileDependencyList
.append(Inc
)
1757 DepDb
[F
] = CurrentFileDependencyList
1759 CurrentFilePath
= F
.Dir
1760 PathList
= [CurrentFilePath
] + SearchPathList
1761 for Inc
in CurrentFileDependencyList
:
1762 for SearchPath
in PathList
:
1763 FilePath
= os
.path
.join(SearchPath
, Inc
)
1764 if FilePath
in gIsFileMap
:
1765 if not gIsFileMap
[FilePath
]:
1767 # If isfile is called too many times, the performance is slow down.
1768 elif not os
.path
.isfile(FilePath
):
1769 gIsFileMap
[FilePath
] = False
1772 gIsFileMap
[FilePath
] = True
1773 FilePath
= PathClass(FilePath
)
1774 FullPathDependList
.append(FilePath
)
1775 if FilePath
not in DependencySet
:
1776 FileStack
.append(FilePath
)
1779 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "%s included by %s was not found "\
1780 "in any given path:\n\t%s" % (Inc
, F
, "\n\t".join(SearchPathList
)))
1782 FileCache
[F
] = FullPathDependList
1783 DependencySet
.update(FullPathDependList
)
1785 DependencySet
.update(ForceList
)
1786 if File
in DependencySet
:
1787 DependencySet
.remove(File
)
1788 DependencyList
= list(DependencySet
) # remove duplicate ones
1790 return DependencyList
1792 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1793 if __name__
== '__main__':