]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/GenMake.py
BaseTools: Remove caret in NASM_INC macro
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / GenMake.py
1 ## @file
2 # Create makefile for MS nmake and GNU make
3 #
4 # Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>
5 # Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
7 #
8
9 ## Import Modules
10 #
11 from __future__ import absolute_import
12 import Common.LongFilePathOs as os
13 import sys
14 import string
15 import re
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
26
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)
29
30 ## Regular expression for matching macro used in header file inclusion
31 gMacroPattern = re.compile("([_A-Z][_A-Z0-9]*)[ \t]*\((.+)\)", re.UNICODE)
32
33 gIsFileMap = {}
34
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,
54 }
55
56 NMAKE_FILETYPE = "nmake"
57 GMAKE_FILETYPE = "gmake"
58 WIN32_PLATFORM = "win32"
59 POSIX_PLATFORM = "posix"
60
61 ## BuildFile class
62 #
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.
65 #
66 class BuildFile(object):
67 ## template used to generate the build file (i.e. makefile if using make)
68 _TEMPLATE_ = TemplateString('')
69
70 _DEFAULT_FILE_NAME_ = "Makefile"
71
72 ## default file name for each type of build file
73 _FILE_NAME_ = {
74 NMAKE_FILETYPE : "Makefile",
75 GMAKE_FILETYPE : "GNUmakefile"
76 }
77
78 # Get Makefile name.
79 def getMakefileName(self):
80 if not self._FileType:
81 return self._DEFAULT_FILE_NAME_
82 else:
83 return self._FILE_NAME_[self._FileType]
84
85 ## Fixed header string for makefile
86 _MAKEFILE_HEADER = '''#
87 # DO NOT EDIT
88 # This file is auto-generated by build utility
89 #
90 # Module Name:
91 #
92 # %s
93 #
94 # Abstract:
95 #
96 # Auto-generated makefile for building modules, libraries or platform
97 #
98 '''
99
100 ## Header string for each type of build file
101 _FILE_HEADER_ = {
102 NMAKE_FILETYPE : _MAKEFILE_HEADER % _FILE_NAME_[NMAKE_FILETYPE],
103 GMAKE_FILETYPE : _MAKEFILE_HEADER % _FILE_NAME_[GMAKE_FILETYPE]
104 }
105
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
112 #
113 _SHELL_CMD_ = {
114 WIN32_PLATFORM : {
115 "CP" : "copy /y",
116 "MV" : "move /y",
117 "RM" : "del /f /q",
118 "MD" : "mkdir",
119 "RD" : "rmdir /s /q",
120 },
121
122 POSIX_PLATFORM : {
123 "CP" : "cp -f",
124 "MV" : "mv -f",
125 "RM" : "rm -f",
126 "MD" : "mkdir -p",
127 "RD" : "rm -r -f",
128 }
129 }
130
131 ## directory separator
132 _SEP_ = {
133 WIN32_PLATFORM : "\\",
134 POSIX_PLATFORM : "/"
135 }
136
137 ## directory creation template
138 _MD_TEMPLATE_ = {
139 WIN32_PLATFORM : 'if not exist %(dir)s $(MD) %(dir)s',
140 POSIX_PLATFORM : "$(MD) %(dir)s"
141 }
142
143 ## directory removal template
144 _RD_TEMPLATE_ = {
145 WIN32_PLATFORM : 'if exist %(dir)s $(RD) %(dir)s',
146 POSIX_PLATFORM : "$(RD) %(dir)s"
147 }
148 ## cp if exist
149 _CP_TEMPLATE_ = {
150 WIN32_PLATFORM : 'if exist %(Src)s $(CP) %(Src)s %(Dst)s',
151 POSIX_PLATFORM : "test -f %(Src)s && $(CP) %(Src)s %(Dst)s"
152 }
153
154 _CD_TEMPLATE_ = {
155 WIN32_PLATFORM : 'if exist %(dir)s cd %(dir)s',
156 POSIX_PLATFORM : "test -e %(dir)s && cd %(dir)s"
157 }
158
159 _MAKE_TEMPLATE_ = {
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'
162 }
163
164 _INCLUDE_CMD_ = {
165 NMAKE_FILETYPE : '!INCLUDE',
166 GMAKE_FILETYPE : "include"
167 }
168
169 _INC_FLAG_ = {TAB_COMPILER_MSFT : "/I", "GCC" : "-I", "INTEL" : "-I", "RVCT" : "-I", "NASM" : "-I"}
170
171 ## Constructor of BuildFile
172 #
173 # @param AutoGenObject Object of AutoGen class
174 #
175 def __init__(self, AutoGenObject):
176 self._AutoGenObject = AutoGenObject
177
178 MakePath = AutoGenObject.BuildOption.get('MAKE', {}).get('PATH')
179 if not MakePath:
180 self._FileType = ""
181 elif "nmake" in MakePath:
182 self._FileType = NMAKE_FILETYPE
183 else:
184 self._FileType = "gmake"
185
186 if sys.platform == "win32":
187 self._Platform = WIN32_PLATFORM
188 else:
189 self._Platform = POSIX_PLATFORM
190
191 ## Create build file.
192 #
193 # Only nmake and gmake are supported.
194 #
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.
197 #
198 def Generate(self):
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:
203 fd.write("")
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:
206 fd.write("")
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:
209 fd.write("")
210 return SaveFileOnChange(os.path.join(self._AutoGenObject.MakeFileDir, FileName), FileContent, False)
211
212 ## Return a list of directory creation command string
213 #
214 # @param DirList The list of directory to be created
215 #
216 # @retval list The directory creation command list
217 #
218 def GetCreateDirectoryCommand(self, DirList):
219 return [self._MD_TEMPLATE_[self._Platform] % {'dir':Dir} for Dir in DirList]
220
221 ## Return a list of directory removal command string
222 #
223 # @param DirList The list of directory to be removed
224 #
225 # @retval list The directory removal command list
226 #
227 def GetRemoveDirectoryCommand(self, DirList):
228 return [self._RD_TEMPLATE_[self._Platform] % {'dir':Dir} for Dir in DirList]
229
230 def PlaceMacro(self, Path, MacroDefinitions=None):
231 if Path.startswith("$("):
232 return Path
233 else:
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:
241 continue
242 if MacroValueLength <= PathLength and Path.startswith(MacroValue):
243 Path = "$(%s)%s" % (MacroName, Path[MacroValueLength:])
244 break
245 return Path
246
247 ## ModuleMakefile class
248 #
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.
251 #
252 class ModuleMakefile(BuildFile):
253 ## template used to generate the makefile for module
254 _TEMPLATE_ = TemplateString('''\
255 ${makefile_header}
256
257 #
258 # Platform Macro Definition
259 #
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}
266
267 #
268 # Module Macro Definition
269 #
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}
282
283 MODULE_ENTRY_POINT = ${module_entry_point}
284 ARCH_ENTRY_POINT = ${arch_entry_point}
285 IMAGE_ENTRY_POINT = ${image_entry_point}
286
287 ${BEGIN}${module_extra_defines}
288 ${END}
289 #
290 # Build Configuration Macro Definition
291 #
292 ARCH = ${architecture}
293 TOOLCHAIN = ${toolchain_tag}
294 TOOLCHAIN_TAG = ${toolchain_tag}
295 TARGET = ${build_target}
296
297 #
298 # Build Directory Macro Definition
299 #
300 # PLATFORM_BUILD_DIR = ${platform_build_directory}
301 BUILD_DIR = ${platform_build_directory}
302 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
303 LIB_DIR = $(BIN_DIR)
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)
309
310 #
311 # Shell Command Macro
312 #
313 ${BEGIN}${shell_command_code} = ${shell_command}
314 ${END}
315
316 #
317 # Tools definitions specific to this module
318 #
319 ${BEGIN}${module_tool_definitions}
320 ${END}
321 MAKE_FILE = ${makefile_path}
322
323 #
324 # Build Macro
325 #
326 ${BEGIN}${file_macro}
327 ${END}
328
329 #
330 # Overridable Target Macro Definitions
331 #
332 FORCE_REBUILD = force_build
333 INIT_TARGET = init
334 PCH_TARGET =
335 BC_TARGET = ${BEGIN}${backward_compatible_target} ${END}
336 CODA_TARGET = ${BEGIN}${remaining_build_target} \\
337 ${END}
338
339 #
340 # Default target, which will build dependent libraries in addition to source files
341 #
342
343 all: mbuild
344
345
346 #
347 # Target used when called from platform makefile, which will bypass the build of dependent libraries
348 #
349
350 pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
351
352 #
353 # ModuleTarget
354 #
355
356 mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET)
357
358 #
359 # Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets
360 #
361
362 tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
363
364 #
365 # Phony target which is used to force executing commands for a target
366 #
367 force_build:
368 \t-@
369
370 #
371 # Target to update the FD
372 #
373
374 fds: mbuild gen_fds
375
376 #
377 # Initialization target: print build information and create necessary directories
378 #
379 init: info dirs
380
381 info:
382 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
383
384 dirs:
385 ${BEGIN}\t-@${create_directory_command}\n${END}
386
387 strdefs:
388 \t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h
389
390 #
391 # GenLibsTarget
392 #
393 gen_libs:
394 \t${BEGIN}@"$(MAKE)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name}
395 \t${END}@cd $(MODULE_BUILD_DIR)
396
397 #
398 # Build Flash Device Image
399 #
400 gen_fds:
401 \t@"$(MAKE)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds
402 \t@cd $(MODULE_BUILD_DIR)
403
404 ${INCLUDETAG}
405
406 #
407 # Individual Object Build Targets
408 #
409 ${BEGIN}${file_build_target}
410 ${END}
411
412 #
413 # clean all intermediate files
414 #
415 clean:
416 \t${BEGIN}${clean_command}
417 \t${END}\t$(RM) AutoGenTimeStamp
418
419 #
420 # clean all generated files
421 #
422 cleanall:
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
427
428 #
429 # clean all dependent libraries built
430 #
431 cleanlib:
432 \t${BEGIN}-@${library_build_command} cleanall
433 \t${END}@cd $(MODULE_BUILD_DIR)\n\n''')
434
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")
437
438 ## Constructor of ModuleMakefile
439 #
440 # @param ModuleAutoGen Object of ModuleAutoGen class
441 #
442 def __init__(self, ModuleAutoGen):
443 BuildFile.__init__(self, ModuleAutoGen)
444 self.PlatformInfo = self._AutoGenObject.PlatformInfo
445
446 self.ResultFileList = []
447 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
448
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()
456 self.FileCache = {}
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()
474
475 # Compose a dict object containing information used to do replacement in template
476 @property
477 def _TemplateDict(self):
478 MyAgo = self._AutoGenObject
479 Separator = self._SEP_[self._Platform]
480
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))
486
487 # convert dependent libraries to build command
488 self.ProcessDependentLibrary()
489 if len(MyAgo.Module.ModuleEntryPointList) > 0:
490 ModuleEntryPoint = MyAgo.Module.ModuleEntryPointList[0]
491 else:
492 ModuleEntryPoint = "_ModuleEntryPoint"
493
494 ArchEntryPoint = ModuleEntryPoint
495
496 if MyAgo.Arch == "EBC":
497 # EBC compiler always use "EfiStart" as entry point. Only applies to EdkII modules
498 ImageEntryPoint = "EfiStart"
499 else:
500 # EdkII modules always use "_ModuleEntryPoint" as entry point
501 ImageEntryPoint = "_ModuleEntryPoint"
502
503 for k, v in MyAgo.Module.Defines.items():
504 if k not in MyAgo.Macros:
505 MyAgo.Macros[k] = v
506
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
513
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
518
519 # tools definitions
520 ToolsDef = []
521 IncPrefix = self._INC_FLAG_[MyAgo.ToolChainFamily]
522 for Tool in MyAgo.BuildOption:
523 for Attr in MyAgo.BuildOption[Tool]:
524 Value = MyAgo.BuildOption[Tool][Attr]
525 if Attr == "FAMILY":
526 continue
527 elif Attr == "PATH":
528 ToolsDef.append("%s = %s" % (Tool, Value))
529 else:
530 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
531 if Tool == "MAKE":
532 continue
533 # Remove duplicated include path, if any
534 if Attr == "FLAGS":
535 Value = RemoveDupOption(Value, IncPrefix, MyAgo.IncludePathList)
536 if Tool == "OPTROM" and PCI_COMPRESS_Flag:
537 ValueList = Value.split()
538 if ValueList:
539 for i, v in enumerate(ValueList):
540 if '-e' == v:
541 ValueList[i] = '-ec'
542 Value = ' '.join(ValueList)
543
544 ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
545 ToolsDef.append("")
546
547 # generate the Response file and Response flag
548 RespDict = self.CommandExceedLimit()
549 RespFileList = os.path.join(MyAgo.OutputDir, 'respfilelist.txt')
550 if RespDict:
551 RespFileListContent = ''
552 for Resp in RespDict:
553 RespFile = os.path.join(MyAgo.OutputDir, str(Resp).lower() + '.txt')
554 StrList = RespDict[Resp].split(' ')
555 UnexpandMacro = []
556 NewStr = []
557 for Str in StrList:
558 if '$' in Str or '-MMD' in Str or '-MF' in Str:
559 UnexpandMacro.append(Str)
560 else:
561 NewStr.append(Str)
562 UnexpandMacroStr = ' '.join(UnexpandMacro)
563 NewRespStr = ' '.join(NewStr)
564 SaveFileOnChange(RespFile, NewRespStr, False)
565 ToolsDef.append("%s = %s" % (Resp, UnexpandMacroStr + ' @' + RespFile))
566 RespFileListContent += '@' + RespFile + TAB_LINE_BREAK
567 RespFileListContent += NewRespStr + TAB_LINE_BREAK
568 SaveFileOnChange(RespFileList, RespFileListContent, False)
569 else:
570 if os.path.exists(RespFileList):
571 os.remove(RespFileList)
572
573 # convert source files and binary files to build targets
574 self.ResultFileList = [str(T.Target) for T in MyAgo.CodaTargetList]
575 if len(self.ResultFileList) == 0 and len(MyAgo.SourceFileList) != 0:
576 EdkLogger.error("build", AUTOGEN_ERROR, "Nothing to build",
577 ExtraData="[%s]" % str(MyAgo))
578
579 self.ProcessBuildTargetList()
580 self.ParserGenerateFfsCmd()
581
582 # Generate macros used to represent input files
583 FileMacroList = [] # macro name = file list
584 for FileListMacro in self.FileListMacros:
585 FileMacro = self._FILE_MACRO_TEMPLATE.Replace(
586 {
587 "macro_name" : FileListMacro,
588 "source_file" : self.FileListMacros[FileListMacro]
589 }
590 )
591 FileMacroList.append(FileMacro)
592
593 # INC_LIST is special
594 FileMacro = ""
595 IncludePathList = []
596 for P in MyAgo.IncludePathList:
597 IncludePathList.append(IncPrefix + self.PlaceMacro(P, self.Macros))
598 if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:
599 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix + P)
600 FileMacro += self._FILE_MACRO_TEMPLATE.Replace(
601 {
602 "macro_name" : "INC",
603 "source_file" : IncludePathList
604 }
605 )
606 FileMacroList.append(FileMacro)
607 # Add support when compiling .nasm source files
608 IncludePathList = []
609 asmsource = [item for item in MyAgo.SourceFileList if item.File.upper().endswith((".NASM",".ASM",".NASMB","S"))]
610 if asmsource:
611 for P in MyAgo.IncludePathList:
612 IncludePath = self._INC_FLAG_['NASM'] + self.PlaceMacro(P, self.Macros)
613 if IncludePath.endswith(os.sep):
614 IncludePath = IncludePath.rstrip(os.sep)
615 # When compiling .nasm files, need to add a literal backslash at each path.
616 # In nmake makfiles, a trailing literal backslash must be escaped with a caret ('^').
617 # It is otherwise replaced with a space (' '). This is not necessary for GNU makfefiles.
618 if P == MyAgo.IncludePathList[-1] and self._Platform == WIN32_PLATFORM and self._FileType == NMAKE_FILETYPE:
619 IncludePath = ''.join([IncludePath, '^', os.sep])
620 else:
621 IncludePath = os.path.join(IncludePath, '')
622 IncludePathList.append(IncludePath)
623 FileMacroList.append(self._FILE_MACRO_TEMPLATE.Replace({"macro_name": "NASM_INC", "source_file": IncludePathList}))
624
625 # Generate macros used to represent files containing list of input files
626 for ListFileMacro in self.ListFileMacros:
627 ListFileName = os.path.join(MyAgo.OutputDir, "%s.lst" % ListFileMacro.lower()[:len(ListFileMacro) - 5])
628 FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))
629 SaveFileOnChange(
630 ListFileName,
631 "\n".join(self.ListFileMacros[ListFileMacro]),
632 False
633 )
634
635 # Generate objlist used to create .obj file
636 for Type in self.ObjTargetDict:
637 NewLine = ' '.join(list(self.ObjTargetDict[Type]))
638 FileMacroList.append("OBJLIST_%s = %s" % (list(self.ObjTargetDict.keys()).index(Type), NewLine))
639
640 BcTargetList = []
641
642 MakefileName = self.getMakefileName()
643 LibraryMakeCommandList = []
644 for D in self.LibraryBuildDirectoryList:
645 Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":os.path.join(D, MakefileName)}
646 LibraryMakeCommandList.append(Command)
647
648 package_rel_dir = MyAgo.SourceDir
649 current_dir = self.Macros["WORKSPACE"]
650 found = False
651 while not found and os.sep in package_rel_dir:
652 index = package_rel_dir.index(os.sep)
653 current_dir = mws.join(current_dir, package_rel_dir[:index])
654 if os.path.exists(current_dir):
655 for fl in os.listdir(current_dir):
656 if fl.endswith('.dec'):
657 found = True
658 break
659 package_rel_dir = package_rel_dir[index + 1:]
660
661 MakefileTemplateDict = {
662 "makefile_header" : self._FILE_HEADER_[self._FileType],
663 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
664 "makefile_name" : MakefileName,
665 "platform_name" : self.PlatformInfo.Name,
666 "platform_guid" : self.PlatformInfo.Guid,
667 "platform_version" : self.PlatformInfo.Version,
668 "platform_relative_directory": self.PlatformInfo.SourceDir,
669 "platform_output_directory" : self.PlatformInfo.OutputDir,
670 "ffs_output_directory" : MyAgo.Macros["FFS_OUTPUT_DIR"],
671 "platform_dir" : MyAgo.Macros["PLATFORM_DIR"],
672
673 "module_name" : MyAgo.Name,
674 "module_guid" : MyAgo.Guid,
675 "module_name_guid" : MyAgo.UniqueBaseName,
676 "module_version" : MyAgo.Version,
677 "module_type" : MyAgo.ModuleType,
678 "module_file" : MyAgo.MetaFile.Name,
679 "module_file_base_name" : MyAgo.MetaFile.BaseName,
680 "module_relative_directory" : MyAgo.SourceDir,
681 "module_dir" : mws.join (self.Macros["WORKSPACE"], MyAgo.SourceDir),
682 "package_relative_directory": package_rel_dir,
683 "module_extra_defines" : ["%s = %s" % (k, v) for k, v in MyAgo.Module.Defines.items()],
684
685 "architecture" : MyAgo.Arch,
686 "toolchain_tag" : MyAgo.ToolChain,
687 "build_target" : MyAgo.BuildTarget,
688
689 "platform_build_directory" : self.PlatformInfo.BuildDir,
690 "module_build_directory" : MyAgo.BuildDir,
691 "module_output_directory" : MyAgo.OutputDir,
692 "module_debug_directory" : MyAgo.DebugDir,
693
694 "separator" : Separator,
695 "module_tool_definitions" : ToolsDef,
696
697 "shell_command_code" : list(self._SHELL_CMD_[self._Platform].keys()),
698 "shell_command" : list(self._SHELL_CMD_[self._Platform].values()),
699
700 "module_entry_point" : ModuleEntryPoint,
701 "image_entry_point" : ImageEntryPoint,
702 "arch_entry_point" : ArchEntryPoint,
703 "remaining_build_target" : self.ResultFileList,
704 "common_dependency_file" : self.CommonFileDependency,
705 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
706 "clean_command" : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]),
707 "cleanall_command" : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]),
708 "dependent_library_build_directory" : self.LibraryBuildDirectoryList,
709 "library_build_command" : LibraryMakeCommandList,
710 "file_macro" : FileMacroList,
711 "file_build_target" : self.BuildTargetList,
712 "backward_compatible_target": BcTargetList,
713 "INCLUDETAG" : "\n".join([self._INCLUDE_CMD_[self._FileType] + " " + os.path.join("$(MODULE_BUILD_DIR)","dependency"),
714 self._INCLUDE_CMD_[self._FileType] + " " + os.path.join("$(MODULE_BUILD_DIR)","deps_target")
715 ])
716 }
717
718 return MakefileTemplateDict
719
720 def ParserGenerateFfsCmd(self):
721 #Add Ffs cmd to self.BuildTargetList
722 OutputFile = ''
723 DepsFileList = []
724
725 for Cmd in self.GenFfsList:
726 if Cmd[2]:
727 for CopyCmd in Cmd[2]:
728 Src, Dst = CopyCmd
729 Src = self.ReplaceMacro(Src)
730 Dst = self.ReplaceMacro(Dst)
731 if Dst not in self.ResultFileList:
732 self.ResultFileList.append(Dst)
733 if '%s :' %(Dst) not in self.BuildTargetList:
734 self.BuildTargetList.append("%s : %s" %(Dst,Src))
735 self.BuildTargetList.append('\t' + self._CP_TEMPLATE_[self._Platform] %{'Src': Src, 'Dst': Dst})
736
737 FfsCmdList = Cmd[0]
738 for index, Str in enumerate(FfsCmdList):
739 if '-o' == Str:
740 OutputFile = FfsCmdList[index + 1]
741 if '-i' == Str or "-oi" == Str:
742 if DepsFileList == []:
743 DepsFileList = [FfsCmdList[index + 1]]
744 else:
745 DepsFileList.append(FfsCmdList[index + 1])
746 DepsFileString = ' '.join(DepsFileList).strip()
747 if DepsFileString == '':
748 continue
749 OutputFile = self.ReplaceMacro(OutputFile)
750 self.ResultFileList.append(OutputFile)
751 DepsFileString = self.ReplaceMacro(DepsFileString)
752 self.BuildTargetList.append('%s : %s' % (OutputFile, DepsFileString))
753 CmdString = ' '.join(FfsCmdList).strip()
754 CmdString = self.ReplaceMacro(CmdString)
755 self.BuildTargetList.append('\t%s' % CmdString)
756
757 self.ParseSecCmd(DepsFileList, Cmd[1])
758 for SecOutputFile, SecDepsFile, SecCmd in self.FfsOutputFileList :
759 self.BuildTargetList.append('%s : %s' % (self.ReplaceMacro(SecOutputFile), self.ReplaceMacro(SecDepsFile)))
760 self.BuildTargetList.append('\t%s' % self.ReplaceMacro(SecCmd))
761 self.FfsOutputFileList = []
762
763 def ParseSecCmd(self, OutputFileList, CmdTuple):
764 for OutputFile in OutputFileList:
765 for SecCmdStr in CmdTuple:
766 SecDepsFileList = []
767 SecCmdList = SecCmdStr.split()
768 CmdName = SecCmdList[0]
769 for index, CmdItem in enumerate(SecCmdList):
770 if '-o' == CmdItem and OutputFile == SecCmdList[index + 1]:
771 index = index + 1
772 while index + 1 < len(SecCmdList):
773 if not SecCmdList[index+1].startswith('-'):
774 SecDepsFileList.append(SecCmdList[index + 1])
775 index = index + 1
776 if CmdName == 'Trim':
777 SecDepsFileList.append(os.path.join('$(DEBUG_DIR)', os.path.basename(OutputFile).replace('offset', 'efi')))
778 if OutputFile.endswith('.ui') or OutputFile.endswith('.ver'):
779 SecDepsFileList.append(os.path.join('$(MODULE_DIR)', '$(MODULE_FILE)'))
780 self.FfsOutputFileList.append((OutputFile, ' '.join(SecDepsFileList), SecCmdStr))
781 if len(SecDepsFileList) > 0:
782 self.ParseSecCmd(SecDepsFileList, CmdTuple)
783 break
784 else:
785 continue
786
787 def ReplaceMacro(self, str):
788 for Macro in self.MacroList:
789 if self._AutoGenObject.Macros[Macro] and self._AutoGenObject.Macros[Macro] in str:
790 str = str.replace(self._AutoGenObject.Macros[Macro], '$(' + Macro + ')')
791 return str
792
793 def CommandExceedLimit(self):
794 FlagDict = {
795 'CC' : { 'Macro' : '$(CC_FLAGS)', 'Value' : False},
796 'PP' : { 'Macro' : '$(PP_FLAGS)', 'Value' : False},
797 'APP' : { 'Macro' : '$(APP_FLAGS)', 'Value' : False},
798 'ASLPP' : { 'Macro' : '$(ASLPP_FLAGS)', 'Value' : False},
799 'VFRPP' : { 'Macro' : '$(VFRPP_FLAGS)', 'Value' : False},
800 'ASM' : { 'Macro' : '$(ASM_FLAGS)', 'Value' : False},
801 'ASLCC' : { 'Macro' : '$(ASLCC_FLAGS)', 'Value' : False},
802 }
803
804 RespDict = {}
805 FileTypeList = []
806 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
807
808 # base on the source files to decide the file type
809 for File in self._AutoGenObject.SourceFileList:
810 for type in self._AutoGenObject.FileTypes:
811 if File in self._AutoGenObject.FileTypes[type]:
812 if type not in FileTypeList:
813 FileTypeList.append(type)
814
815 # calculate the command-line length
816 if FileTypeList:
817 for type in FileTypeList:
818 BuildTargets = self._AutoGenObject.BuildRules[type].BuildTargets
819 for Target in BuildTargets:
820 CommandList = BuildTargets[Target].Commands
821 for SingleCommand in CommandList:
822 Tool = ''
823 SingleCommandLength = len(SingleCommand)
824 SingleCommandList = SingleCommand.split()
825 if len(SingleCommandList) > 0:
826 for Flag in FlagDict:
827 if '$('+ Flag +')' in SingleCommandList[0]:
828 Tool = Flag
829 break
830 if Tool:
831 if 'PATH' not in self._AutoGenObject.BuildOption[Tool]:
832 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))
833 SingleCommandLength += len(self._AutoGenObject.BuildOption[Tool]['PATH'])
834 for item in SingleCommandList[1:]:
835 if FlagDict[Tool]['Macro'] in item:
836 if 'FLAGS' not in self._AutoGenObject.BuildOption[Tool]:
837 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))
838 Str = self._AutoGenObject.BuildOption[Tool]['FLAGS']
839 for Option in self._AutoGenObject.BuildOption:
840 for Attr in self._AutoGenObject.BuildOption[Option]:
841 if Str.find(Option + '_' + Attr) != -1:
842 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
843 while(Str.find('$(') != -1):
844 for macro in self._AutoGenObject.Macros:
845 MacroName = '$('+ macro + ')'
846 if (Str.find(MacroName) != -1):
847 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
848 break
849 else:
850 break
851 SingleCommandLength += len(Str)
852 elif '$(INC)' in item:
853 SingleCommandLength += self._AutoGenObject.IncludePathLength + len(IncPrefix) * len(self._AutoGenObject.IncludePathList)
854 elif item.find('$(') != -1:
855 Str = item
856 for Option in self._AutoGenObject.BuildOption:
857 for Attr in self._AutoGenObject.BuildOption[Option]:
858 if Str.find(Option + '_' + Attr) != -1:
859 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
860 while(Str.find('$(') != -1):
861 for macro in self._AutoGenObject.Macros:
862 MacroName = '$('+ macro + ')'
863 if (Str.find(MacroName) != -1):
864 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
865 break
866 else:
867 break
868 SingleCommandLength += len(Str)
869
870 if SingleCommandLength > GlobalData.gCommandMaxLength:
871 FlagDict[Tool]['Value'] = True
872
873 # generate the response file content by combine the FLAGS and INC
874 for Flag in FlagDict:
875 if FlagDict[Flag]['Value']:
876 Key = Flag + '_RESP'
877 RespMacro = FlagDict[Flag]['Macro'].replace('FLAGS', 'RESP')
878 Value = self._AutoGenObject.BuildOption[Flag]['FLAGS']
879 for inc in self._AutoGenObject.IncludePathList:
880 Value += ' ' + IncPrefix + inc
881 for Option in self._AutoGenObject.BuildOption:
882 for Attr in self._AutoGenObject.BuildOption[Option]:
883 if Value.find(Option + '_' + Attr) != -1:
884 Value = Value.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
885 while (Value.find('$(') != -1):
886 for macro in self._AutoGenObject.Macros:
887 MacroName = '$('+ macro + ')'
888 if (Value.find(MacroName) != -1):
889 Value = Value.replace(MacroName, self._AutoGenObject.Macros[macro])
890 break
891 else:
892 break
893
894 if self._AutoGenObject.ToolChainFamily == 'GCC':
895 RespDict[Key] = Value.replace('\\', '/')
896 else:
897 RespDict[Key] = Value
898 for Target in BuildTargets:
899 for i, SingleCommand in enumerate(BuildTargets[Target].Commands):
900 if FlagDict[Flag]['Macro'] in SingleCommand:
901 BuildTargets[Target].Commands[i] = SingleCommand.replace('$(INC)', '').replace(FlagDict[Flag]['Macro'], RespMacro)
902 return RespDict
903
904 def ProcessBuildTargetList(self):
905 #
906 # Search dependency file list for each source file
907 #
908 ForceIncludedFile = []
909 for File in self._AutoGenObject.AutoGenFileList:
910 if File.Ext == '.h':
911 ForceIncludedFile.append(File)
912 SourceFileList = []
913 OutPutFileList = []
914 for Target in self._AutoGenObject.IntroTargetList:
915 SourceFileList.extend(Target.Inputs)
916 OutPutFileList.extend(Target.Outputs)
917
918 if OutPutFileList:
919 for Item in OutPutFileList:
920 if Item in SourceFileList:
921 SourceFileList.remove(Item)
922
923 FileDependencyDict = {item:ForceIncludedFile for item in SourceFileList}
924
925 for Dependency in FileDependencyDict.values():
926 self.DependencyHeaderFileSet.update(set(Dependency))
927
928 # Get a set of unique package includes from MetaFile
929 parentMetaFileIncludes = set()
930 for aInclude in self._AutoGenObject.PackageIncludePathList:
931 aIncludeName = str(aInclude)
932 parentMetaFileIncludes.add(aIncludeName.lower())
933
934 # Check if header files are listed in metafile
935 # Get a set of unique module header source files from MetaFile
936 headerFilesInMetaFileSet = set()
937 for aFile in self._AutoGenObject.SourceFileList:
938 aFileName = str(aFile)
939 if not aFileName.endswith('.h'):
940 continue
941 headerFilesInMetaFileSet.add(aFileName.lower())
942
943 # Get a set of unique module autogen files
944 localAutoGenFileSet = set()
945 for aFile in self._AutoGenObject.AutoGenFileList:
946 localAutoGenFileSet.add(str(aFile).lower())
947
948 # Get a set of unique module dependency header files
949 # Exclude autogen files and files not in the source directory
950 # and files that are under the package include list
951 headerFileDependencySet = set()
952 localSourceDir = str(self._AutoGenObject.SourceDir).lower()
953 for Dependency in FileDependencyDict.values():
954 for aFile in Dependency:
955 aFileName = str(aFile).lower()
956 # Exclude non-header files
957 if not aFileName.endswith('.h'):
958 continue
959 # Exclude autogen files
960 if aFileName in localAutoGenFileSet:
961 continue
962 # Exclude include out of local scope
963 if localSourceDir not in aFileName:
964 continue
965 # Exclude files covered by package includes
966 pathNeeded = True
967 for aIncludePath in parentMetaFileIncludes:
968 if aIncludePath in aFileName:
969 pathNeeded = False
970 break
971 if not pathNeeded:
972 continue
973 # Keep the file to be checked
974 headerFileDependencySet.add(aFileName)
975
976 # Check if a module dependency header file is missing from the module's MetaFile
977 for aFile in headerFileDependencySet:
978 if aFile in headerFilesInMetaFileSet:
979 continue
980 if GlobalData.gUseHashCache:
981 GlobalData.gModuleBuildTracking[self._AutoGenObject] = 'FAIL_METAFILE'
982 EdkLogger.warn("build","Module MetaFile [Sources] is missing local header!",
983 ExtraData = "Local Header: " + aFile + " not found in " + self._AutoGenObject.MetaFile.Path
984 )
985
986 for File,Dependency in FileDependencyDict.items():
987 if not Dependency:
988 continue
989
990 self._AutoGenObject.AutoGenDepSet |= set(Dependency)
991
992 CmdSumDict = {}
993 CmdTargetDict = {}
994 CmdCppDict = {}
995 DependencyDict = FileDependencyDict.copy()
996
997 # Convert target description object to target string in makefile
998 if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and TAB_C_CODE_FILE in self._AutoGenObject.Targets:
999 for T in self._AutoGenObject.Targets[TAB_C_CODE_FILE]:
1000 NewFile = self.PlaceMacro(str(T), self.Macros)
1001 if not self.ObjTargetDict.get(T.Target.SubDir):
1002 self.ObjTargetDict[T.Target.SubDir] = set()
1003 self.ObjTargetDict[T.Target.SubDir].add(NewFile)
1004 for Type in self._AutoGenObject.Targets:
1005 for T in self._AutoGenObject.Targets[Type]:
1006 # Generate related macros if needed
1007 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
1008 self.FileListMacros[T.FileListMacro] = []
1009 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:
1010 self.ListFileMacros[T.ListFileMacro] = []
1011 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:
1012 self.ListFileMacros[T.IncListFileMacro] = []
1013
1014 Deps = []
1015 CCodeDeps = []
1016 # Add force-dependencies
1017 for Dep in T.Dependencies:
1018 Deps.append(self.PlaceMacro(str(Dep), self.Macros))
1019 if Dep != '$(MAKE_FILE)':
1020 CCodeDeps.append(self.PlaceMacro(str(Dep), self.Macros))
1021 # Add inclusion-dependencies
1022 if len(T.Inputs) == 1 and T.Inputs[0] in FileDependencyDict:
1023 for F in FileDependencyDict[T.Inputs[0]]:
1024 Deps.append(self.PlaceMacro(str(F), self.Macros))
1025 # Add source-dependencies
1026 for F in T.Inputs:
1027 NewFile = self.PlaceMacro(str(F), self.Macros)
1028 # In order to use file list macro as dependency
1029 if T.GenListFile:
1030 # gnu tools need forward slash path separator, even on Windows
1031 self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/'))
1032 self.FileListMacros[T.FileListMacro].append(NewFile)
1033 elif T.GenFileListMacro:
1034 self.FileListMacros[T.FileListMacro].append(NewFile)
1035 else:
1036 Deps.append(NewFile)
1037 for key in self.FileListMacros:
1038 self.FileListMacros[key].sort()
1039 # Use file list macro as dependency
1040 if T.GenFileListMacro:
1041 Deps.append("$(%s)" % T.FileListMacro)
1042 if Type in [TAB_OBJECT_FILE, TAB_STATIC_LIBRARY]:
1043 Deps.append("$(%s)" % T.ListFileMacro)
1044
1045 if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and Type == TAB_C_CODE_FILE:
1046 T, CmdTarget, CmdTargetDict, CmdCppDict = self.ParserCCodeFile(T, Type, CmdSumDict, CmdTargetDict, CmdCppDict, DependencyDict)
1047 TargetDict = {"target": self.PlaceMacro(T.Target.Path, self.Macros), "cmd": "\n\t".join(T.Commands),"deps": CCodeDeps}
1048 CmdLine = self._BUILD_TARGET_TEMPLATE.Replace(TargetDict).rstrip().replace('\t$(OBJLIST', '$(OBJLIST')
1049 if T.Commands:
1050 CmdLine = '%s%s' %(CmdLine, TAB_LINE_BREAK)
1051 if CCodeDeps or CmdLine:
1052 self.BuildTargetList.append(CmdLine)
1053 else:
1054 TargetDict = {"target": self.PlaceMacro(T.Target.Path, self.Macros), "cmd": "\n\t".join(T.Commands),"deps": Deps}
1055 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
1056
1057 def ParserCCodeFile(self, T, Type, CmdSumDict, CmdTargetDict, CmdCppDict, DependencyDict):
1058 if not CmdSumDict:
1059 for item in self._AutoGenObject.Targets[Type]:
1060 CmdSumDict[item.Target.SubDir] = item.Target.BaseName
1061 for CppPath in item.Inputs:
1062 Path = self.PlaceMacro(CppPath.Path, self.Macros)
1063 if CmdCppDict.get(item.Target.SubDir):
1064 CmdCppDict[item.Target.SubDir].append(Path)
1065 else:
1066 CmdCppDict[item.Target.SubDir] = ['$(MAKE_FILE)', Path]
1067 if CppPath.Path in DependencyDict:
1068 for Temp in DependencyDict[CppPath.Path]:
1069 try:
1070 Path = self.PlaceMacro(Temp.Path, self.Macros)
1071 except:
1072 continue
1073 if Path not in (self.CommonFileDependency + CmdCppDict[item.Target.SubDir]):
1074 CmdCppDict[item.Target.SubDir].append(Path)
1075 if T.Commands:
1076 CommandList = T.Commands[:]
1077 for Item in CommandList[:]:
1078 SingleCommandList = Item.split()
1079 if len(SingleCommandList) > 0 and self.CheckCCCmd(SingleCommandList):
1080 for Temp in SingleCommandList:
1081 if Temp.startswith('/Fo'):
1082 CmdSign = '%s%s' % (Temp.rsplit(TAB_SLASH, 1)[0], TAB_SLASH)
1083 break
1084 else: continue
1085 if CmdSign not in list(CmdTargetDict.keys()):
1086 CmdTargetDict[CmdSign] = Item.replace(Temp, CmdSign)
1087 else:
1088 CmdTargetDict[CmdSign] = "%s %s" % (CmdTargetDict[CmdSign], SingleCommandList[-1])
1089 Index = CommandList.index(Item)
1090 CommandList.pop(Index)
1091 if SingleCommandList[-1].endswith("%s%s.c" % (TAB_SLASH, CmdSumDict[CmdSign[3:].rsplit(TAB_SLASH, 1)[0]])):
1092 Cpplist = CmdCppDict[T.Target.SubDir]
1093 Cpplist.insert(0, '$(OBJLIST_%d): ' % list(self.ObjTargetDict.keys()).index(T.Target.SubDir))
1094 T.Commands[Index] = '%s\n\t%s' % (' \\\n\t'.join(Cpplist), CmdTargetDict[CmdSign])
1095 else:
1096 T.Commands.pop(Index)
1097 return T, CmdSumDict, CmdTargetDict, CmdCppDict
1098
1099 def CheckCCCmd(self, CommandList):
1100 for cmd in CommandList:
1101 if '$(CC)' in cmd:
1102 return True
1103 return False
1104 ## For creating makefile targets for dependent libraries
1105 def ProcessDependentLibrary(self):
1106 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1107 if not LibraryAutoGen.IsBinaryModule:
1108 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
1109
1110 ## Return a list containing source file's dependencies
1111 #
1112 # @param FileList The list of source files
1113 # @param ForceInculeList The list of files which will be included forcely
1114 # @param SearchPathList The list of search path
1115 #
1116 # @retval dict The mapping between source file path and its dependencies
1117 #
1118 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
1119 Dependency = {}
1120 for F in FileList:
1121 Dependency[F] = GetDependencyList(self._AutoGenObject, self.FileCache, F, ForceInculeList, SearchPathList)
1122 return Dependency
1123
1124
1125 ## CustomMakefile class
1126 #
1127 # This class encapsules makefie and its generation for module. It uses template to generate
1128 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
1129 #
1130 class CustomMakefile(BuildFile):
1131 ## template used to generate the makefile for module with custom makefile
1132 _TEMPLATE_ = TemplateString('''\
1133 ${makefile_header}
1134
1135 #
1136 # Platform Macro Definition
1137 #
1138 PLATFORM_NAME = ${platform_name}
1139 PLATFORM_GUID = ${platform_guid}
1140 PLATFORM_VERSION = ${platform_version}
1141 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
1142 PLATFORM_DIR = ${platform_dir}
1143 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1144
1145 #
1146 # Module Macro Definition
1147 #
1148 MODULE_NAME = ${module_name}
1149 MODULE_GUID = ${module_guid}
1150 MODULE_NAME_GUID = ${module_name_guid}
1151 MODULE_VERSION = ${module_version}
1152 MODULE_TYPE = ${module_type}
1153 MODULE_FILE = ${module_file}
1154 MODULE_FILE_BASE_NAME = ${module_file_base_name}
1155 BASE_NAME = $(MODULE_NAME)
1156 MODULE_RELATIVE_DIR = ${module_relative_directory}
1157 MODULE_DIR = ${module_dir}
1158
1159 #
1160 # Build Configuration Macro Definition
1161 #
1162 ARCH = ${architecture}
1163 TOOLCHAIN = ${toolchain_tag}
1164 TOOLCHAIN_TAG = ${toolchain_tag}
1165 TARGET = ${build_target}
1166
1167 #
1168 # Build Directory Macro Definition
1169 #
1170 # PLATFORM_BUILD_DIR = ${platform_build_directory}
1171 BUILD_DIR = ${platform_build_directory}
1172 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
1173 LIB_DIR = $(BIN_DIR)
1174 MODULE_BUILD_DIR = ${module_build_directory}
1175 OUTPUT_DIR = ${module_output_directory}
1176 DEBUG_DIR = ${module_debug_directory}
1177 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
1178 DEST_DIR_DEBUG = $(DEBUG_DIR)
1179
1180 #
1181 # Tools definitions specific to this module
1182 #
1183 ${BEGIN}${module_tool_definitions}
1184 ${END}
1185 MAKE_FILE = ${makefile_path}
1186
1187 #
1188 # Shell Command Macro
1189 #
1190 ${BEGIN}${shell_command_code} = ${shell_command}
1191 ${END}
1192
1193 ${custom_makefile_content}
1194
1195 #
1196 # Target used when called from platform makefile, which will bypass the build of dependent libraries
1197 #
1198
1199 pbuild: init all
1200
1201
1202 #
1203 # ModuleTarget
1204 #
1205
1206 mbuild: init all
1207
1208 #
1209 # Build Target used in multi-thread build mode, which no init target is needed
1210 #
1211
1212 tbuild: all
1213
1214 #
1215 # Initialization target: print build information and create necessary directories
1216 #
1217 init:
1218 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
1219 ${BEGIN}\t-@${create_directory_command}\n${END}\
1220
1221 ''')
1222
1223 ## Constructor of CustomMakefile
1224 #
1225 # @param ModuleAutoGen Object of ModuleAutoGen class
1226 #
1227 def __init__(self, ModuleAutoGen):
1228 BuildFile.__init__(self, ModuleAutoGen)
1229 self.PlatformInfo = self._AutoGenObject.PlatformInfo
1230 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
1231 self.DependencyHeaderFileSet = set()
1232
1233 # Compose a dict object containing information used to do replacement in template
1234 @property
1235 def _TemplateDict(self):
1236 Separator = self._SEP_[self._Platform]
1237 MyAgo = self._AutoGenObject
1238 if self._FileType not in MyAgo.CustomMakefile:
1239 EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType,
1240 ExtraData="[%s]" % str(MyAgo))
1241 MakefilePath = mws.join(
1242 MyAgo.WorkspaceDir,
1243 MyAgo.CustomMakefile[self._FileType]
1244 )
1245 try:
1246 CustomMakefile = open(MakefilePath, 'r').read()
1247 except:
1248 EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(MyAgo),
1249 ExtraData=MyAgo.CustomMakefile[self._FileType])
1250
1251 # tools definitions
1252 ToolsDef = []
1253 for Tool in MyAgo.BuildOption:
1254 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
1255 if Tool == "MAKE":
1256 continue
1257 for Attr in MyAgo.BuildOption[Tool]:
1258 if Attr == "FAMILY":
1259 continue
1260 elif Attr == "PATH":
1261 ToolsDef.append("%s = %s" % (Tool, MyAgo.BuildOption[Tool][Attr]))
1262 else:
1263 ToolsDef.append("%s_%s = %s" % (Tool, Attr, MyAgo.BuildOption[Tool][Attr]))
1264 ToolsDef.append("")
1265
1266 MakefileName = self.getMakefileName()
1267 MakefileTemplateDict = {
1268 "makefile_header" : self._FILE_HEADER_[self._FileType],
1269 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
1270 "platform_name" : self.PlatformInfo.Name,
1271 "platform_guid" : self.PlatformInfo.Guid,
1272 "platform_version" : self.PlatformInfo.Version,
1273 "platform_relative_directory": self.PlatformInfo.SourceDir,
1274 "platform_output_directory" : self.PlatformInfo.OutputDir,
1275 "platform_dir" : MyAgo.Macros["PLATFORM_DIR"],
1276
1277 "module_name" : MyAgo.Name,
1278 "module_guid" : MyAgo.Guid,
1279 "module_name_guid" : MyAgo.UniqueBaseName,
1280 "module_version" : MyAgo.Version,
1281 "module_type" : MyAgo.ModuleType,
1282 "module_file" : MyAgo.MetaFile,
1283 "module_file_base_name" : MyAgo.MetaFile.BaseName,
1284 "module_relative_directory" : MyAgo.SourceDir,
1285 "module_dir" : mws.join (MyAgo.WorkspaceDir, MyAgo.SourceDir),
1286
1287 "architecture" : MyAgo.Arch,
1288 "toolchain_tag" : MyAgo.ToolChain,
1289 "build_target" : MyAgo.BuildTarget,
1290
1291 "platform_build_directory" : self.PlatformInfo.BuildDir,
1292 "module_build_directory" : MyAgo.BuildDir,
1293 "module_output_directory" : MyAgo.OutputDir,
1294 "module_debug_directory" : MyAgo.DebugDir,
1295
1296 "separator" : Separator,
1297 "module_tool_definitions" : ToolsDef,
1298
1299 "shell_command_code" : list(self._SHELL_CMD_[self._Platform].keys()),
1300 "shell_command" : list(self._SHELL_CMD_[self._Platform].values()),
1301
1302 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1303 "custom_makefile_content" : CustomMakefile
1304 }
1305
1306 return MakefileTemplateDict
1307
1308 ## PlatformMakefile class
1309 #
1310 # This class encapsules makefie and its generation for platform. It uses
1311 # template to generate the content of makefile. The content of makefile will be
1312 # got from PlatformAutoGen object.
1313 #
1314 class PlatformMakefile(BuildFile):
1315 ## template used to generate the makefile for platform
1316 _TEMPLATE_ = TemplateString('''\
1317 ${makefile_header}
1318
1319 #
1320 # Platform Macro Definition
1321 #
1322 PLATFORM_NAME = ${platform_name}
1323 PLATFORM_GUID = ${platform_guid}
1324 PLATFORM_VERSION = ${platform_version}
1325 PLATFORM_FILE = ${platform_file}
1326 PLATFORM_DIR = ${platform_dir}
1327 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1328
1329 #
1330 # Build Configuration Macro Definition
1331 #
1332 TOOLCHAIN = ${toolchain_tag}
1333 TOOLCHAIN_TAG = ${toolchain_tag}
1334 TARGET = ${build_target}
1335
1336 #
1337 # Build Directory Macro Definition
1338 #
1339 BUILD_DIR = ${platform_build_directory}
1340 FV_DIR = ${platform_build_directory}${separator}FV
1341
1342 #
1343 # Shell Command Macro
1344 #
1345 ${BEGIN}${shell_command_code} = ${shell_command}
1346 ${END}
1347
1348 MAKE = ${make_path}
1349 MAKE_FILE = ${makefile_path}
1350
1351 #
1352 # Default target
1353 #
1354 all: init build_libraries build_modules
1355
1356 #
1357 # Initialization target: print build information and create necessary directories
1358 #
1359 init:
1360 \t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
1361 \t${BEGIN}-@${create_directory_command}
1362 \t${END}
1363 #
1364 # library build target
1365 #
1366 libraries: init build_libraries
1367
1368 #
1369 # module build target
1370 #
1371 modules: init build_libraries build_modules
1372
1373 #
1374 # Build all libraries:
1375 #
1376 build_libraries:
1377 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
1378 ${END}\t@cd $(BUILD_DIR)
1379
1380 #
1381 # Build all modules:
1382 #
1383 build_modules:
1384 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
1385 ${END}\t@cd $(BUILD_DIR)
1386
1387 #
1388 # Clean intermediate files
1389 #
1390 clean:
1391 \t${BEGIN}-@${library_build_command} clean
1392 \t${END}${BEGIN}-@${module_build_command} clean
1393 \t${END}@cd $(BUILD_DIR)
1394
1395 #
1396 # Clean all generated files except to makefile
1397 #
1398 cleanall:
1399 ${BEGIN}\t${cleanall_command}
1400 ${END}
1401
1402 #
1403 # Clean all library files
1404 #
1405 cleanlib:
1406 \t${BEGIN}-@${library_build_command} cleanall
1407 \t${END}@cd $(BUILD_DIR)\n
1408 ''')
1409
1410 ## Constructor of PlatformMakefile
1411 #
1412 # @param ModuleAutoGen Object of PlatformAutoGen class
1413 #
1414 def __init__(self, PlatformAutoGen):
1415 BuildFile.__init__(self, PlatformAutoGen)
1416 self.ModuleBuildCommandList = []
1417 self.ModuleMakefileList = []
1418 self.IntermediateDirectoryList = []
1419 self.ModuleBuildDirectoryList = []
1420 self.LibraryBuildDirectoryList = []
1421 self.LibraryMakeCommandList = []
1422 self.DependencyHeaderFileSet = set()
1423
1424 # Compose a dict object containing information used to do replacement in template
1425 @property
1426 def _TemplateDict(self):
1427 Separator = self._SEP_[self._Platform]
1428
1429 MyAgo = self._AutoGenObject
1430 if "MAKE" not in MyAgo.ToolDefinition or "PATH" not in MyAgo.ToolDefinition["MAKE"]:
1431 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
1432 ExtraData="[%s]" % str(MyAgo))
1433
1434 self.IntermediateDirectoryList = ["$(BUILD_DIR)"]
1435 self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()
1436 self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()
1437
1438 MakefileName = self.getMakefileName()
1439 LibraryMakefileList = []
1440 LibraryMakeCommandList = []
1441 for D in self.LibraryBuildDirectoryList:
1442 D = self.PlaceMacro(D, {"BUILD_DIR":MyAgo.BuildDir})
1443 Makefile = os.path.join(D, MakefileName)
1444 Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":Makefile}
1445 LibraryMakefileList.append(Makefile)
1446 LibraryMakeCommandList.append(Command)
1447 self.LibraryMakeCommandList = LibraryMakeCommandList
1448
1449 ModuleMakefileList = []
1450 ModuleMakeCommandList = []
1451 for D in self.ModuleBuildDirectoryList:
1452 D = self.PlaceMacro(D, {"BUILD_DIR":MyAgo.BuildDir})
1453 Makefile = os.path.join(D, MakefileName)
1454 Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":Makefile}
1455 ModuleMakefileList.append(Makefile)
1456 ModuleMakeCommandList.append(Command)
1457
1458 MakefileTemplateDict = {
1459 "makefile_header" : self._FILE_HEADER_[self._FileType],
1460 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),
1461 "make_path" : MyAgo.ToolDefinition["MAKE"]["PATH"],
1462 "makefile_name" : MakefileName,
1463 "platform_name" : MyAgo.Name,
1464 "platform_guid" : MyAgo.Guid,
1465 "platform_version" : MyAgo.Version,
1466 "platform_file" : MyAgo.MetaFile,
1467 "platform_relative_directory": MyAgo.SourceDir,
1468 "platform_output_directory" : MyAgo.OutputDir,
1469 "platform_build_directory" : MyAgo.BuildDir,
1470 "platform_dir" : MyAgo.Macros["PLATFORM_DIR"],
1471
1472 "toolchain_tag" : MyAgo.ToolChain,
1473 "build_target" : MyAgo.BuildTarget,
1474 "shell_command_code" : list(self._SHELL_CMD_[self._Platform].keys()),
1475 "shell_command" : list(self._SHELL_CMD_[self._Platform].values()),
1476 "build_architecture_list" : MyAgo.Arch,
1477 "architecture" : MyAgo.Arch,
1478 "separator" : Separator,
1479 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1480 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1481 "library_makefile_list" : LibraryMakefileList,
1482 "module_makefile_list" : ModuleMakefileList,
1483 "library_build_command" : LibraryMakeCommandList,
1484 "module_build_command" : ModuleMakeCommandList,
1485 }
1486
1487 return MakefileTemplateDict
1488
1489 ## Get the root directory list for intermediate files of all modules build
1490 #
1491 # @retval list The list of directory
1492 #
1493 def GetModuleBuildDirectoryList(self):
1494 DirList = []
1495 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1496 if not ModuleAutoGen.IsBinaryModule:
1497 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1498 return DirList
1499
1500 ## Get the root directory list for intermediate files of all libraries build
1501 #
1502 # @retval list The list of directory
1503 #
1504 def GetLibraryBuildDirectoryList(self):
1505 DirList = []
1506 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1507 if not LibraryAutoGen.IsBinaryModule:
1508 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1509 return DirList
1510
1511 ## TopLevelMakefile class
1512 #
1513 # This class encapsules makefie and its generation for entrance makefile. It
1514 # uses template to generate the content of makefile. The content of makefile
1515 # will be got from WorkspaceAutoGen object.
1516 #
1517 class TopLevelMakefile(BuildFile):
1518 ## template used to generate toplevel makefile
1519 _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}''')
1520
1521 ## Constructor of TopLevelMakefile
1522 #
1523 # @param Workspace Object of WorkspaceAutoGen class
1524 #
1525 def __init__(self, Workspace):
1526 BuildFile.__init__(self, Workspace)
1527 self.IntermediateDirectoryList = []
1528 self.DependencyHeaderFileSet = set()
1529
1530 # Compose a dict object containing information used to do replacement in template
1531 @property
1532 def _TemplateDict(self):
1533 Separator = self._SEP_[self._Platform]
1534
1535 # any platform autogen object is ok because we just need common information
1536 MyAgo = self._AutoGenObject
1537
1538 if "MAKE" not in MyAgo.ToolDefinition or "PATH" not in MyAgo.ToolDefinition["MAKE"]:
1539 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
1540 ExtraData="[%s]" % str(MyAgo))
1541
1542 for Arch in MyAgo.ArchList:
1543 self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch]))
1544 self.IntermediateDirectoryList.append("$(FV_DIR)")
1545
1546 # TRICK: for not generating GenFds call in makefile if no FDF file
1547 MacroList = []
1548 if MyAgo.FdfFile is not None and MyAgo.FdfFile != "":
1549 FdfFileList = [MyAgo.FdfFile]
1550 # macros passed to GenFds
1551 MacroDict = {}
1552 MacroDict.update(GlobalData.gGlobalDefines)
1553 MacroDict.update(GlobalData.gCommandLineDefines)
1554 for MacroName in MacroDict:
1555 if MacroDict[MacroName] != "":
1556 MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))
1557 else:
1558 MacroList.append('"%s"' % MacroName)
1559 else:
1560 FdfFileList = []
1561
1562 # pass extra common options to external program called in makefile, currently GenFds.exe
1563 ExtraOption = ''
1564 LogLevel = EdkLogger.GetLevel()
1565 if LogLevel == EdkLogger.VERBOSE:
1566 ExtraOption += " -v"
1567 elif LogLevel <= EdkLogger.DEBUG_9:
1568 ExtraOption += " -d %d" % (LogLevel - 1)
1569 elif LogLevel == EdkLogger.QUIET:
1570 ExtraOption += " -q"
1571
1572 if GlobalData.gCaseInsensitive:
1573 ExtraOption += " -c"
1574 if not GlobalData.gEnableGenfdsMultiThread:
1575 ExtraOption += " --no-genfds-multi-thread"
1576 if GlobalData.gIgnoreSource:
1577 ExtraOption += " --ignore-sources"
1578
1579 for pcd in GlobalData.BuildOptionPcd:
1580 if pcd[2]:
1581 pcdname = '.'.join(pcd[0:3])
1582 else:
1583 pcdname = '.'.join(pcd[0:2])
1584 if pcd[3].startswith('{'):
1585 ExtraOption += " --pcd " + pcdname + '=' + 'H' + '"' + pcd[3] + '"'
1586 else:
1587 ExtraOption += " --pcd " + pcdname + '=' + pcd[3]
1588
1589 MakefileName = self.getMakefileName()
1590 SubBuildCommandList = []
1591 for A in MyAgo.ArchList:
1592 Command = self._MAKE_TEMPLATE_[self._Platform] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)}
1593 SubBuildCommandList.append(Command)
1594
1595 MakefileTemplateDict = {
1596 "makefile_header" : self._FILE_HEADER_[self._FileType],
1597 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),
1598 "make_path" : MyAgo.ToolDefinition["MAKE"]["PATH"],
1599 "platform_name" : MyAgo.Name,
1600 "platform_guid" : MyAgo.Guid,
1601 "platform_version" : MyAgo.Version,
1602 "platform_build_directory" : MyAgo.BuildDir,
1603 "conf_directory" : GlobalData.gConfDirectory,
1604
1605 "toolchain_tag" : MyAgo.ToolChain,
1606 "build_target" : MyAgo.BuildTarget,
1607 "shell_command_code" : list(self._SHELL_CMD_[self._Platform].keys()),
1608 "shell_command" : list(self._SHELL_CMD_[self._Platform].values()),
1609 'arch' : list(MyAgo.ArchList),
1610 "build_architecture_list" : ','.join(MyAgo.ArchList),
1611 "separator" : Separator,
1612 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1613 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1614 "sub_build_command" : SubBuildCommandList,
1615 "fdf_file" : FdfFileList,
1616 "active_platform" : str(MyAgo),
1617 "fd" : MyAgo.FdTargetList,
1618 "fv" : MyAgo.FvTargetList,
1619 "cap" : MyAgo.CapTargetList,
1620 "extra_options" : ExtraOption,
1621 "macro" : MacroList,
1622 }
1623
1624 return MakefileTemplateDict
1625
1626 ## Get the root directory list for intermediate files of all modules build
1627 #
1628 # @retval list The list of directory
1629 #
1630 def GetModuleBuildDirectoryList(self):
1631 DirList = []
1632 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1633 if not ModuleAutoGen.IsBinaryModule:
1634 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1635 return DirList
1636
1637 ## Get the root directory list for intermediate files of all libraries build
1638 #
1639 # @retval list The list of directory
1640 #
1641 def GetLibraryBuildDirectoryList(self):
1642 DirList = []
1643 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1644 if not LibraryAutoGen.IsBinaryModule:
1645 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1646 return DirList
1647
1648 ## Find dependencies for one source file
1649 #
1650 # By searching recursively "#include" directive in file, find out all the
1651 # files needed by given source file. The dependencies will be only searched
1652 # in given search path list.
1653 #
1654 # @param File The source file
1655 # @param ForceInculeList The list of files which will be included forcely
1656 # @param SearchPathList The list of search path
1657 #
1658 # @retval list The list of files the given source file depends on
1659 #
1660 def GetDependencyList(AutoGenObject, FileCache, File, ForceList, SearchPathList):
1661 EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File)
1662 FileStack = [File] + ForceList
1663 DependencySet = set()
1664
1665 if AutoGenObject.Arch not in gDependencyDatabase:
1666 gDependencyDatabase[AutoGenObject.Arch] = {}
1667 DepDb = gDependencyDatabase[AutoGenObject.Arch]
1668
1669 while len(FileStack) > 0:
1670 F = FileStack.pop()
1671
1672 FullPathDependList = []
1673 if F in FileCache:
1674 for CacheFile in FileCache[F]:
1675 FullPathDependList.append(CacheFile)
1676 if CacheFile not in DependencySet:
1677 FileStack.append(CacheFile)
1678 DependencySet.update(FullPathDependList)
1679 continue
1680
1681 CurrentFileDependencyList = []
1682 if F in DepDb:
1683 CurrentFileDependencyList = DepDb[F]
1684 else:
1685 try:
1686 Fd = open(F.Path, 'rb')
1687 FileContent = Fd.read()
1688 Fd.close()
1689 except BaseException as X:
1690 EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path + "\n\t" + str(X))
1691 if len(FileContent) == 0:
1692 continue
1693 try:
1694 if FileContent[0] == 0xff or FileContent[0] == 0xfe:
1695 FileContent = FileContent.decode('utf-16')
1696 else:
1697 FileContent = FileContent.decode()
1698 except:
1699 # The file is not txt file. for example .mcb file
1700 continue
1701 IncludedFileList = gIncludePattern.findall(FileContent)
1702
1703 for Inc in IncludedFileList:
1704 Inc = Inc.strip()
1705 # if there's macro used to reference header file, expand it
1706 HeaderList = gMacroPattern.findall(Inc)
1707 if len(HeaderList) == 1 and len(HeaderList[0]) == 2:
1708 HeaderType = HeaderList[0][0]
1709 HeaderKey = HeaderList[0][1]
1710 if HeaderType in gIncludeMacroConversion:
1711 Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey}
1712 else:
1713 # not known macro used in #include, always build the file by
1714 # returning a empty dependency
1715 FileCache[File] = []
1716 return []
1717 Inc = os.path.normpath(Inc)
1718 CurrentFileDependencyList.append(Inc)
1719 DepDb[F] = CurrentFileDependencyList
1720
1721 CurrentFilePath = F.Dir
1722 PathList = [CurrentFilePath] + SearchPathList
1723 for Inc in CurrentFileDependencyList:
1724 for SearchPath in PathList:
1725 FilePath = os.path.join(SearchPath, Inc)
1726 if FilePath in gIsFileMap:
1727 if not gIsFileMap[FilePath]:
1728 continue
1729 # If isfile is called too many times, the performance is slow down.
1730 elif not os.path.isfile(FilePath):
1731 gIsFileMap[FilePath] = False
1732 continue
1733 else:
1734 gIsFileMap[FilePath] = True
1735 FilePath = PathClass(FilePath)
1736 FullPathDependList.append(FilePath)
1737 if FilePath not in DependencySet:
1738 FileStack.append(FilePath)
1739 break
1740 else:
1741 EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\
1742 "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList)))
1743
1744 FileCache[F] = FullPathDependList
1745 DependencySet.update(FullPathDependList)
1746
1747 DependencySet.update(ForceList)
1748 if File in DependencySet:
1749 DependencySet.remove(File)
1750 DependencyList = list(DependencySet) # remove duplicate ones
1751
1752 return DependencyList
1753
1754 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1755 if __name__ == '__main__':
1756 pass