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