]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/GenMake.py
BaseTools: remove unnecessary calls of os.exist
[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
453 # Compose a dict object containing information used to do replacement in template
454 @property
455 def _TemplateDict(self):
456 if self._FileType not in self._SEP_:
457 EdkLogger.error("build", PARAMETER_INVALID, "Invalid Makefile type [%s]" % self._FileType,
458 ExtraData="[%s]" % str(self._AutoGenObject))
459 MyAgo = self._AutoGenObject
460 Separator = self._SEP_[self._FileType]
461
462 # break build if no source files and binary files are found
463 if len(MyAgo.SourceFileList) == 0 and len(MyAgo.BinaryFileList) == 0:
464 EdkLogger.error("build", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]"
465 % (MyAgo.BuildTarget, MyAgo.ToolChain, MyAgo.Arch),
466 ExtraData="[%s]" % str(MyAgo))
467
468 # convert dependent libraries to build command
469 self.ProcessDependentLibrary()
470 if len(MyAgo.Module.ModuleEntryPointList) > 0:
471 ModuleEntryPoint = MyAgo.Module.ModuleEntryPointList[0]
472 else:
473 ModuleEntryPoint = "_ModuleEntryPoint"
474
475 ArchEntryPoint = ModuleEntryPoint
476
477 if MyAgo.Arch == "EBC":
478 # EBC compiler always use "EfiStart" as entry point. Only applies to EdkII modules
479 ImageEntryPoint = "EfiStart"
480 else:
481 # EdkII modules always use "_ModuleEntryPoint" as entry point
482 ImageEntryPoint = "_ModuleEntryPoint"
483
484 for k, v in MyAgo.Module.Defines.items():
485 if k not in MyAgo.Macros:
486 MyAgo.Macros[k] = v
487
488 if 'MODULE_ENTRY_POINT' not in MyAgo.Macros:
489 MyAgo.Macros['MODULE_ENTRY_POINT'] = ModuleEntryPoint
490 if 'ARCH_ENTRY_POINT' not in MyAgo.Macros:
491 MyAgo.Macros['ARCH_ENTRY_POINT'] = ArchEntryPoint
492 if 'IMAGE_ENTRY_POINT' not in MyAgo.Macros:
493 MyAgo.Macros['IMAGE_ENTRY_POINT'] = ImageEntryPoint
494
495 PCI_COMPRESS_Flag = False
496 for k, v in MyAgo.Module.Defines.items():
497 if 'PCI_COMPRESS' == k and 'TRUE' == v:
498 PCI_COMPRESS_Flag = True
499
500 # tools definitions
501 ToolsDef = []
502 IncPrefix = self._INC_FLAG_[MyAgo.ToolChainFamily]
503 for Tool in MyAgo.BuildOption:
504 for Attr in MyAgo.BuildOption[Tool]:
505 Value = MyAgo.BuildOption[Tool][Attr]
506 if Attr == "FAMILY":
507 continue
508 elif Attr == "PATH":
509 ToolsDef.append("%s = %s" % (Tool, Value))
510 else:
511 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
512 if Tool == "MAKE":
513 continue
514 # Remove duplicated include path, if any
515 if Attr == "FLAGS":
516 Value = RemoveDupOption(Value, IncPrefix, MyAgo.IncludePathList)
517 if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and Tool == 'CC' and '/GM' in Value:
518 Value = Value.replace(' /MP', '')
519 MyAgo.BuildOption[Tool][Attr] = Value
520 if Tool == "OPTROM" and PCI_COMPRESS_Flag:
521 ValueList = Value.split()
522 if ValueList:
523 for i, v in enumerate(ValueList):
524 if '-e' == v:
525 ValueList[i] = '-ec'
526 Value = ' '.join(ValueList)
527
528 ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
529 ToolsDef.append("")
530
531 # generate the Response file and Response flag
532 RespDict = self.CommandExceedLimit()
533 RespFileList = os.path.join(MyAgo.OutputDir, 'respfilelist.txt')
534 if RespDict:
535 RespFileListContent = ''
536 for Resp in RespDict:
537 RespFile = os.path.join(MyAgo.OutputDir, str(Resp).lower() + '.txt')
538 StrList = RespDict[Resp].split(' ')
539 UnexpandMacro = []
540 NewStr = []
541 for Str in StrList:
542 if '$' in Str:
543 UnexpandMacro.append(Str)
544 else:
545 NewStr.append(Str)
546 UnexpandMacroStr = ' '.join(UnexpandMacro)
547 NewRespStr = ' '.join(NewStr)
548 SaveFileOnChange(RespFile, NewRespStr, False)
549 ToolsDef.append("%s = %s" % (Resp, UnexpandMacroStr + ' @' + RespFile))
550 RespFileListContent += '@' + RespFile + TAB_LINE_BREAK
551 RespFileListContent += NewRespStr + TAB_LINE_BREAK
552 SaveFileOnChange(RespFileList, RespFileListContent, False)
553 else:
554 if os.path.exists(RespFileList):
555 os.remove(RespFileList)
556
557 # convert source files and binary files to build targets
558 self.ResultFileList = [str(T.Target) for T in MyAgo.CodaTargetList]
559 if len(self.ResultFileList) == 0 and len(MyAgo.SourceFileList) != 0:
560 EdkLogger.error("build", AUTOGEN_ERROR, "Nothing to build",
561 ExtraData="[%s]" % str(MyAgo))
562
563 self.ProcessBuildTargetList()
564 self.ParserGenerateFfsCmd()
565
566 # Generate macros used to represent input files
567 FileMacroList = [] # macro name = file list
568 for FileListMacro in self.FileListMacros:
569 FileMacro = self._FILE_MACRO_TEMPLATE.Replace(
570 {
571 "macro_name" : FileListMacro,
572 "source_file" : self.FileListMacros[FileListMacro]
573 }
574 )
575 FileMacroList.append(FileMacro)
576
577 # INC_LIST is special
578 FileMacro = ""
579 IncludePathList = []
580 for P in MyAgo.IncludePathList:
581 IncludePathList.append(IncPrefix + self.PlaceMacro(P, self.Macros))
582 if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:
583 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix + P)
584 FileMacro += self._FILE_MACRO_TEMPLATE.Replace(
585 {
586 "macro_name" : "INC",
587 "source_file" : IncludePathList
588 }
589 )
590 FileMacroList.append(FileMacro)
591 # Add support when compiling .nasm source files
592 for File in self.FileCache.keys():
593 if not str(File).endswith('.nasm'):
594 continue
595 IncludePathList = []
596 for P in MyAgo.IncludePathList:
597 IncludePath = self._INC_FLAG_['NASM'] + self.PlaceMacro(P, self.Macros)
598 if IncludePath.endswith(os.sep):
599 IncludePath = IncludePath.rstrip(os.sep)
600 # When compiling .nasm files, need to add a literal backslash at each path
601 # To specify a literal backslash at the end of the line, precede it with a caret (^)
602 if P == MyAgo.IncludePathList[-1] and os.sep == '\\':
603 IncludePath = ''.join([IncludePath, '^', os.sep])
604 else:
605 IncludePath = os.path.join(IncludePath, '')
606 IncludePathList.append(IncludePath)
607 FileMacroList.append(self._FILE_MACRO_TEMPLATE.Replace({"macro_name": "NASM_INC", "source_file": IncludePathList}))
608 break
609
610 # Generate macros used to represent files containing list of input files
611 for ListFileMacro in self.ListFileMacros:
612 ListFileName = os.path.join(MyAgo.OutputDir, "%s.lst" % ListFileMacro.lower()[:len(ListFileMacro) - 5])
613 FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))
614 SaveFileOnChange(
615 ListFileName,
616 "\n".join(self.ListFileMacros[ListFileMacro]),
617 False
618 )
619
620 # Generate objlist used to create .obj file
621 for Type in self.ObjTargetDict:
622 NewLine = ' '.join(list(self.ObjTargetDict[Type]))
623 FileMacroList.append("OBJLIST_%s = %s" % (list(self.ObjTargetDict.keys()).index(Type), NewLine))
624
625 BcTargetList = []
626
627 MakefileName = self._FILE_NAME_[self._FileType]
628 LibraryMakeCommandList = []
629 for D in self.LibraryBuildDirectoryList:
630 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)}
631 LibraryMakeCommandList.append(Command)
632
633 package_rel_dir = MyAgo.SourceDir
634 current_dir = self.Macros["WORKSPACE"]
635 found = False
636 while not found and os.sep in package_rel_dir:
637 index = package_rel_dir.index(os.sep)
638 current_dir = mws.join(current_dir, package_rel_dir[:index])
639 try:
640 for fl in os.listdir(current_dir):
641 if fl.endswith('.dec'):
642 found = True
643 break
644 except:
645 EdkLogger.error('build', FILE_NOT_FOUND, "WORKSPACE does not exist.")
646 package_rel_dir = package_rel_dir[index + 1:]
647
648 MakefileTemplateDict = {
649 "makefile_header" : self._FILE_HEADER_[self._FileType],
650 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
651 "makefile_name" : MakefileName,
652 "platform_name" : self.PlatformInfo.Name,
653 "platform_guid" : self.PlatformInfo.Guid,
654 "platform_version" : self.PlatformInfo.Version,
655 "platform_relative_directory": self.PlatformInfo.SourceDir,
656 "platform_output_directory" : self.PlatformInfo.OutputDir,
657 "ffs_output_directory" : MyAgo.Macros["FFS_OUTPUT_DIR"],
658 "platform_dir" : MyAgo.Macros["PLATFORM_DIR"],
659
660 "module_name" : MyAgo.Name,
661 "module_guid" : MyAgo.Guid,
662 "module_name_guid" : MyAgo.UniqueBaseName,
663 "module_version" : MyAgo.Version,
664 "module_type" : MyAgo.ModuleType,
665 "module_file" : MyAgo.MetaFile.Name,
666 "module_file_base_name" : MyAgo.MetaFile.BaseName,
667 "module_relative_directory" : MyAgo.SourceDir,
668 "module_dir" : mws.join (self.Macros["WORKSPACE"], MyAgo.SourceDir),
669 "package_relative_directory": package_rel_dir,
670 "module_extra_defines" : ["%s = %s" % (k, v) for k, v in MyAgo.Module.Defines.items()],
671
672 "architecture" : MyAgo.Arch,
673 "toolchain_tag" : MyAgo.ToolChain,
674 "build_target" : MyAgo.BuildTarget,
675
676 "platform_build_directory" : self.PlatformInfo.BuildDir,
677 "module_build_directory" : MyAgo.BuildDir,
678 "module_output_directory" : MyAgo.OutputDir,
679 "module_debug_directory" : MyAgo.DebugDir,
680
681 "separator" : Separator,
682 "module_tool_definitions" : ToolsDef,
683
684 "shell_command_code" : list(self._SHELL_CMD_[self._FileType].keys()),
685 "shell_command" : list(self._SHELL_CMD_[self._FileType].values()),
686
687 "module_entry_point" : ModuleEntryPoint,
688 "image_entry_point" : ImageEntryPoint,
689 "arch_entry_point" : ArchEntryPoint,
690 "remaining_build_target" : self.ResultFileList,
691 "common_dependency_file" : self.CommonFileDependency,
692 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
693 "clean_command" : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]),
694 "cleanall_command" : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]),
695 "dependent_library_build_directory" : self.LibraryBuildDirectoryList,
696 "library_build_command" : LibraryMakeCommandList,
697 "file_macro" : FileMacroList,
698 "file_build_target" : self.BuildTargetList,
699 "backward_compatible_target": BcTargetList,
700 }
701
702 return MakefileTemplateDict
703
704 def ParserGenerateFfsCmd(self):
705 #Add Ffs cmd to self.BuildTargetList
706 OutputFile = ''
707 DepsFileList = []
708
709 for Cmd in self.GenFfsList:
710 if Cmd[2]:
711 for CopyCmd in Cmd[2]:
712 Src, Dst = CopyCmd
713 Src = self.ReplaceMacro(Src)
714 Dst = self.ReplaceMacro(Dst)
715 if Dst not in self.ResultFileList:
716 self.ResultFileList.append(Dst)
717 if '%s :' %(Dst) not in self.BuildTargetList:
718 self.BuildTargetList.append("%s :" %(Dst))
719 self.BuildTargetList.append('\t' + self._CP_TEMPLATE_[self._FileType] %{'Src': Src, 'Dst': Dst})
720
721 FfsCmdList = Cmd[0]
722 for index, Str in enumerate(FfsCmdList):
723 if '-o' == Str:
724 OutputFile = FfsCmdList[index + 1]
725 if '-i' == Str or "-oi" == Str:
726 if DepsFileList == []:
727 DepsFileList = [FfsCmdList[index + 1]]
728 else:
729 DepsFileList.append(FfsCmdList[index + 1])
730 DepsFileString = ' '.join(DepsFileList).strip()
731 if DepsFileString == '':
732 continue
733 OutputFile = self.ReplaceMacro(OutputFile)
734 self.ResultFileList.append(OutputFile)
735 DepsFileString = self.ReplaceMacro(DepsFileString)
736 self.BuildTargetList.append('%s : %s' % (OutputFile, DepsFileString))
737 CmdString = ' '.join(FfsCmdList).strip()
738 CmdString = self.ReplaceMacro(CmdString)
739 self.BuildTargetList.append('\t%s' % CmdString)
740
741 self.ParseSecCmd(DepsFileList, Cmd[1])
742 for SecOutputFile, SecDepsFile, SecCmd in self.FfsOutputFileList :
743 self.BuildTargetList.append('%s : %s' % (self.ReplaceMacro(SecOutputFile), self.ReplaceMacro(SecDepsFile)))
744 self.BuildTargetList.append('\t%s' % self.ReplaceMacro(SecCmd))
745 self.FfsOutputFileList = []
746
747 def ParseSecCmd(self, OutputFileList, CmdTuple):
748 for OutputFile in OutputFileList:
749 for SecCmdStr in CmdTuple:
750 SecDepsFileList = []
751 SecCmdList = SecCmdStr.split()
752 CmdName = SecCmdList[0]
753 for index, CmdItem in enumerate(SecCmdList):
754 if '-o' == CmdItem and OutputFile == SecCmdList[index + 1]:
755 index = index + 1
756 while index + 1 < len(SecCmdList):
757 if not SecCmdList[index+1].startswith('-'):
758 SecDepsFileList.append(SecCmdList[index + 1])
759 index = index + 1
760 if CmdName == 'Trim':
761 SecDepsFileList.append(os.path.join('$(DEBUG_DIR)', os.path.basename(OutputFile).replace('offset', 'efi')))
762 if OutputFile.endswith('.ui') or OutputFile.endswith('.ver'):
763 SecDepsFileList.append(os.path.join('$(MODULE_DIR)', '$(MODULE_FILE)'))
764 self.FfsOutputFileList.append((OutputFile, ' '.join(SecDepsFileList), SecCmdStr))
765 if len(SecDepsFileList) > 0:
766 self.ParseSecCmd(SecDepsFileList, CmdTuple)
767 break
768 else:
769 continue
770
771 def ReplaceMacro(self, str):
772 for Macro in self.MacroList:
773 if self._AutoGenObject.Macros[Macro] and self._AutoGenObject.Macros[Macro] in str:
774 str = str.replace(self._AutoGenObject.Macros[Macro], '$(' + Macro + ')')
775 return str
776
777 def CommandExceedLimit(self):
778 FlagDict = {
779 'CC' : { 'Macro' : '$(CC_FLAGS)', 'Value' : False},
780 'PP' : { 'Macro' : '$(PP_FLAGS)', 'Value' : False},
781 'APP' : { 'Macro' : '$(APP_FLAGS)', 'Value' : False},
782 'ASLPP' : { 'Macro' : '$(ASLPP_FLAGS)', 'Value' : False},
783 'VFRPP' : { 'Macro' : '$(VFRPP_FLAGS)', 'Value' : False},
784 'ASM' : { 'Macro' : '$(ASM_FLAGS)', 'Value' : False},
785 'ASLCC' : { 'Macro' : '$(ASLCC_FLAGS)', 'Value' : False},
786 }
787
788 RespDict = {}
789 FileTypeList = []
790 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
791
792 # base on the source files to decide the file type
793 for File in self._AutoGenObject.SourceFileList:
794 for type in self._AutoGenObject.FileTypes:
795 if File in self._AutoGenObject.FileTypes[type]:
796 if type not in FileTypeList:
797 FileTypeList.append(type)
798
799 # calculate the command-line length
800 if FileTypeList:
801 for type in FileTypeList:
802 BuildTargets = self._AutoGenObject.BuildRules[type].BuildTargets
803 for Target in BuildTargets:
804 CommandList = BuildTargets[Target].Commands
805 for SingleCommand in CommandList:
806 Tool = ''
807 SingleCommandLength = len(SingleCommand)
808 SingleCommandList = SingleCommand.split()
809 if len(SingleCommandList) > 0:
810 for Flag in FlagDict:
811 if '$('+ Flag +')' in SingleCommandList[0]:
812 Tool = Flag
813 break
814 if Tool:
815 if 'PATH' not in self._AutoGenObject.BuildOption[Tool]:
816 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))
817 SingleCommandLength += len(self._AutoGenObject.BuildOption[Tool]['PATH'])
818 for item in SingleCommandList[1:]:
819 if FlagDict[Tool]['Macro'] in item:
820 if 'FLAGS' not in self._AutoGenObject.BuildOption[Tool]:
821 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))
822 Str = self._AutoGenObject.BuildOption[Tool]['FLAGS']
823 for Option in self._AutoGenObject.BuildOption:
824 for Attr in self._AutoGenObject.BuildOption[Option]:
825 if Str.find(Option + '_' + Attr) != -1:
826 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
827 while(Str.find('$(') != -1):
828 for macro in self._AutoGenObject.Macros:
829 MacroName = '$('+ macro + ')'
830 if (Str.find(MacroName) != -1):
831 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
832 break
833 else:
834 break
835 SingleCommandLength += len(Str)
836 elif '$(INC)' in item:
837 SingleCommandLength += self._AutoGenObject.IncludePathLength + len(IncPrefix) * len(self._AutoGenObject.IncludePathList)
838 elif item.find('$(') != -1:
839 Str = item
840 for Option in self._AutoGenObject.BuildOption:
841 for Attr in self._AutoGenObject.BuildOption[Option]:
842 if Str.find(Option + '_' + Attr) != -1:
843 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
844 while(Str.find('$(') != -1):
845 for macro in self._AutoGenObject.Macros:
846 MacroName = '$('+ macro + ')'
847 if (Str.find(MacroName) != -1):
848 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
849 break
850 else:
851 break
852 SingleCommandLength += len(Str)
853
854 if SingleCommandLength > GlobalData.gCommandMaxLength:
855 FlagDict[Tool]['Value'] = True
856
857 # generate the response file content by combine the FLAGS and INC
858 for Flag in FlagDict:
859 if FlagDict[Flag]['Value']:
860 Key = Flag + '_RESP'
861 RespMacro = FlagDict[Flag]['Macro'].replace('FLAGS', 'RESP')
862 Value = self._AutoGenObject.BuildOption[Flag]['FLAGS']
863 for inc in self._AutoGenObject.IncludePathList:
864 Value += ' ' + IncPrefix + inc
865 for Option in self._AutoGenObject.BuildOption:
866 for Attr in self._AutoGenObject.BuildOption[Option]:
867 if Value.find(Option + '_' + Attr) != -1:
868 Value = Value.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
869 while (Value.find('$(') != -1):
870 for macro in self._AutoGenObject.Macros:
871 MacroName = '$('+ macro + ')'
872 if (Value.find(MacroName) != -1):
873 Value = Value.replace(MacroName, self._AutoGenObject.Macros[macro])
874 break
875 else:
876 break
877
878 if self._AutoGenObject.ToolChainFamily == 'GCC':
879 RespDict[Key] = Value.replace('\\', '/')
880 else:
881 RespDict[Key] = Value
882 for Target in BuildTargets:
883 for i, SingleCommand in enumerate(BuildTargets[Target].Commands):
884 if FlagDict[Flag]['Macro'] in SingleCommand:
885 BuildTargets[Target].Commands[i] = SingleCommand.replace('$(INC)', '').replace(FlagDict[Flag]['Macro'], RespMacro)
886 return RespDict
887
888 def ProcessBuildTargetList(self):
889 #
890 # Search dependency file list for each source file
891 #
892 ForceIncludedFile = []
893 for File in self._AutoGenObject.AutoGenFileList:
894 if File.Ext == '.h':
895 ForceIncludedFile.append(File)
896 SourceFileList = []
897 OutPutFileList = []
898 for Target in self._AutoGenObject.IntroTargetList:
899 SourceFileList.extend(Target.Inputs)
900 OutPutFileList.extend(Target.Outputs)
901
902 if OutPutFileList:
903 for Item in OutPutFileList:
904 if Item in SourceFileList:
905 SourceFileList.remove(Item)
906
907 FileDependencyDict = self.GetFileDependency(
908 SourceFileList,
909 ForceIncludedFile,
910 self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList
911 )
912
913 self.DependencyHeaderFileSet = set()
914 if FileDependencyDict:
915 for Dependency in FileDependencyDict.values():
916 self.DependencyHeaderFileSet.update(set(Dependency))
917
918 # Get a set of unique package includes from MetaFile
919 parentMetaFileIncludes = set()
920 for aInclude in self._AutoGenObject.PackageIncludePathList:
921 aIncludeName = str(aInclude)
922 parentMetaFileIncludes.add(aIncludeName.lower())
923
924 # Check if header files are listed in metafile
925 # Get a set of unique module header source files from MetaFile
926 headerFilesInMetaFileSet = set()
927 for aFile in self._AutoGenObject.SourceFileList:
928 aFileName = str(aFile)
929 if not aFileName.endswith('.h'):
930 continue
931 headerFilesInMetaFileSet.add(aFileName.lower())
932
933 # Get a set of unique module autogen files
934 localAutoGenFileSet = set()
935 for aFile in self._AutoGenObject.AutoGenFileList:
936 localAutoGenFileSet.add(str(aFile).lower())
937
938 # Get a set of unique module dependency header files
939 # Exclude autogen files and files not in the source directory
940 # and files that are under the package include list
941 headerFileDependencySet = set()
942 localSourceDir = str(self._AutoGenObject.SourceDir).lower()
943 for Dependency in FileDependencyDict.values():
944 for aFile in Dependency:
945 aFileName = str(aFile).lower()
946 # Exclude non-header files
947 if not aFileName.endswith('.h'):
948 continue
949 # Exclude autogen files
950 if aFileName in localAutoGenFileSet:
951 continue
952 # Exclude include out of local scope
953 if localSourceDir not in aFileName:
954 continue
955 # Exclude files covered by package includes
956 pathNeeded = True
957 for aIncludePath in parentMetaFileIncludes:
958 if aIncludePath in aFileName:
959 pathNeeded = False
960 break
961 if not pathNeeded:
962 continue
963 # Keep the file to be checked
964 headerFileDependencySet.add(aFileName)
965
966 # Check if a module dependency header file is missing from the module's MetaFile
967 for aFile in headerFileDependencySet:
968 if aFile in headerFilesInMetaFileSet:
969 continue
970 if GlobalData.gUseHashCache:
971 GlobalData.gModuleBuildTracking[self._AutoGenObject] = 'FAIL_METAFILE'
972 EdkLogger.warn("build","Module MetaFile [Sources] is missing local header!",
973 ExtraData = "Local Header: " + aFile + " not found in " + self._AutoGenObject.MetaFile.Path
974 )
975
976 DepSet = None
977 for File,Dependency in FileDependencyDict.items():
978 if not Dependency:
979 FileDependencyDict[File] = ['$(FORCE_REBUILD)']
980 continue
981
982 self._AutoGenObject.AutoGenDepSet |= set(Dependency)
983
984 # skip non-C files
985 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
986 continue
987 elif DepSet is None:
988 DepSet = set(Dependency)
989 else:
990 DepSet &= set(Dependency)
991 # in case nothing in SourceFileList
992 if DepSet is None:
993 DepSet = set()
994 #
995 # Extract common files list in the dependency files
996 #
997 for File in DepSet:
998 self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros))
999
1000 CmdSumDict = {}
1001 CmdTargetDict = {}
1002 CmdCppDict = {}
1003 DependencyDict = FileDependencyDict.copy()
1004 for File in FileDependencyDict:
1005 # skip non-C files
1006 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
1007 continue
1008 NewDepSet = set(FileDependencyDict[File])
1009 NewDepSet -= DepSet
1010 FileDependencyDict[File] = ["$(COMMON_DEPS)"] + list(NewDepSet)
1011 DependencyDict[File] = list(NewDepSet)
1012
1013 # Convert target description object to target string in makefile
1014 if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and TAB_C_CODE_FILE in self._AutoGenObject.Targets:
1015 for T in self._AutoGenObject.Targets[TAB_C_CODE_FILE]:
1016 NewFile = self.PlaceMacro(str(T), self.Macros)
1017 if not self.ObjTargetDict.get(T.Target.SubDir):
1018 self.ObjTargetDict[T.Target.SubDir] = set()
1019 self.ObjTargetDict[T.Target.SubDir].add(NewFile)
1020 for Type in self._AutoGenObject.Targets:
1021 for T in self._AutoGenObject.Targets[Type]:
1022 # Generate related macros if needed
1023 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
1024 self.FileListMacros[T.FileListMacro] = []
1025 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:
1026 self.ListFileMacros[T.ListFileMacro] = []
1027 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:
1028 self.ListFileMacros[T.IncListFileMacro] = []
1029
1030 Deps = []
1031 CCodeDeps = []
1032 # Add force-dependencies
1033 for Dep in T.Dependencies:
1034 Deps.append(self.PlaceMacro(str(Dep), self.Macros))
1035 if Dep != '$(MAKE_FILE)':
1036 CCodeDeps.append(self.PlaceMacro(str(Dep), self.Macros))
1037 # Add inclusion-dependencies
1038 if len(T.Inputs) == 1 and T.Inputs[0] in FileDependencyDict:
1039 for F in FileDependencyDict[T.Inputs[0]]:
1040 Deps.append(self.PlaceMacro(str(F), self.Macros))
1041 # Add source-dependencies
1042 for F in T.Inputs:
1043 NewFile = self.PlaceMacro(str(F), self.Macros)
1044 # In order to use file list macro as dependency
1045 if T.GenListFile:
1046 # gnu tools need forward slash path separator, even on Windows
1047 self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/'))
1048 self.FileListMacros[T.FileListMacro].append(NewFile)
1049 elif T.GenFileListMacro:
1050 self.FileListMacros[T.FileListMacro].append(NewFile)
1051 else:
1052 Deps.append(NewFile)
1053 for key in self.FileListMacros:
1054 self.FileListMacros[key].sort()
1055 # Use file list macro as dependency
1056 if T.GenFileListMacro:
1057 Deps.append("$(%s)" % T.FileListMacro)
1058 if Type in [TAB_OBJECT_FILE, TAB_STATIC_LIBRARY]:
1059 Deps.append("$(%s)" % T.ListFileMacro)
1060
1061 if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and Type == TAB_C_CODE_FILE:
1062 T, CmdTarget, CmdTargetDict, CmdCppDict = self.ParserCCodeFile(T, Type, CmdSumDict, CmdTargetDict, CmdCppDict, DependencyDict)
1063 TargetDict = {"target": self.PlaceMacro(T.Target.Path, self.Macros), "cmd": "\n\t".join(T.Commands),"deps": CCodeDeps}
1064 CmdLine = self._BUILD_TARGET_TEMPLATE.Replace(TargetDict).rstrip().replace('\t$(OBJLIST', '$(OBJLIST')
1065 if T.Commands:
1066 CmdLine = '%s%s' %(CmdLine, TAB_LINE_BREAK)
1067 if CCodeDeps or CmdLine:
1068 self.BuildTargetList.append(CmdLine)
1069 else:
1070 TargetDict = {"target": self.PlaceMacro(T.Target.Path, self.Macros), "cmd": "\n\t".join(T.Commands),"deps": Deps}
1071 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
1072
1073 def ParserCCodeFile(self, T, Type, CmdSumDict, CmdTargetDict, CmdCppDict, DependencyDict):
1074 if not CmdSumDict:
1075 for item in self._AutoGenObject.Targets[Type]:
1076 CmdSumDict[item.Target.SubDir] = item.Target.BaseName
1077 for CppPath in item.Inputs:
1078 Path = self.PlaceMacro(CppPath.Path, self.Macros)
1079 if CmdCppDict.get(item.Target.SubDir):
1080 CmdCppDict[item.Target.SubDir].append(Path)
1081 else:
1082 CmdCppDict[item.Target.SubDir] = ['$(MAKE_FILE)', Path]
1083 if CppPath.Path in DependencyDict:
1084 for Temp in DependencyDict[CppPath.Path]:
1085 try:
1086 Path = self.PlaceMacro(Temp.Path, self.Macros)
1087 except:
1088 continue
1089 if Path not in (self.CommonFileDependency + CmdCppDict[item.Target.SubDir]):
1090 CmdCppDict[item.Target.SubDir].append(Path)
1091 if T.Commands:
1092 CommandList = T.Commands[:]
1093 for Item in CommandList[:]:
1094 SingleCommandList = Item.split()
1095 if len(SingleCommandList) > 0 and self.CheckCCCmd(SingleCommandList):
1096 for Temp in SingleCommandList:
1097 if Temp.startswith('/Fo'):
1098 CmdSign = '%s%s' % (Temp.rsplit(TAB_SLASH, 1)[0], TAB_SLASH)
1099 break
1100 else: continue
1101 if CmdSign not in list(CmdTargetDict.keys()):
1102 CmdTargetDict[CmdSign] = Item.replace(Temp, CmdSign)
1103 else:
1104 CmdTargetDict[CmdSign] = "%s %s" % (CmdTargetDict[CmdSign], SingleCommandList[-1])
1105 Index = CommandList.index(Item)
1106 CommandList.pop(Index)
1107 if SingleCommandList[-1].endswith("%s%s.c" % (TAB_SLASH, CmdSumDict[CmdSign[3:].rsplit(TAB_SLASH, 1)[0]])):
1108 Cpplist = CmdCppDict[T.Target.SubDir]
1109 Cpplist.insert(0, '$(OBJLIST_%d): $(COMMON_DEPS)' % list(self.ObjTargetDict.keys()).index(T.Target.SubDir))
1110 T.Commands[Index] = '%s\n\t%s' % (' \\\n\t'.join(Cpplist), CmdTargetDict[CmdSign])
1111 else:
1112 T.Commands.pop(Index)
1113 return T, CmdSumDict, CmdTargetDict, CmdCppDict
1114
1115 def CheckCCCmd(self, CommandList):
1116 for cmd in CommandList:
1117 if '$(CC)' in cmd:
1118 return True
1119 return False
1120 ## For creating makefile targets for dependent libraries
1121 def ProcessDependentLibrary(self):
1122 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1123 if not LibraryAutoGen.IsBinaryModule:
1124 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
1125
1126 ## Return a list containing source file's dependencies
1127 #
1128 # @param FileList The list of source files
1129 # @param ForceInculeList The list of files which will be included forcely
1130 # @param SearchPathList The list of search path
1131 #
1132 # @retval dict The mapping between source file path and its dependencies
1133 #
1134 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
1135 Dependency = {}
1136 for F in FileList:
1137 Dependency[F] = GetDependencyList(self._AutoGenObject, self.FileCache, F, ForceInculeList, SearchPathList)
1138 return Dependency
1139
1140
1141 ## CustomMakefile class
1142 #
1143 # This class encapsules makefie and its generation for module. It uses template to generate
1144 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
1145 #
1146 class CustomMakefile(BuildFile):
1147 ## template used to generate the makefile for module with custom makefile
1148 _TEMPLATE_ = TemplateString('''\
1149 ${makefile_header}
1150
1151 #
1152 # Platform Macro Definition
1153 #
1154 PLATFORM_NAME = ${platform_name}
1155 PLATFORM_GUID = ${platform_guid}
1156 PLATFORM_VERSION = ${platform_version}
1157 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
1158 PLATFORM_DIR = ${platform_dir}
1159 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1160
1161 #
1162 # Module Macro Definition
1163 #
1164 MODULE_NAME = ${module_name}
1165 MODULE_GUID = ${module_guid}
1166 MODULE_NAME_GUID = ${module_name_guid}
1167 MODULE_VERSION = ${module_version}
1168 MODULE_TYPE = ${module_type}
1169 MODULE_FILE = ${module_file}
1170 MODULE_FILE_BASE_NAME = ${module_file_base_name}
1171 BASE_NAME = $(MODULE_NAME)
1172 MODULE_RELATIVE_DIR = ${module_relative_directory}
1173 MODULE_DIR = ${module_dir}
1174
1175 #
1176 # Build Configuration Macro Definition
1177 #
1178 ARCH = ${architecture}
1179 TOOLCHAIN = ${toolchain_tag}
1180 TOOLCHAIN_TAG = ${toolchain_tag}
1181 TARGET = ${build_target}
1182
1183 #
1184 # Build Directory Macro Definition
1185 #
1186 # PLATFORM_BUILD_DIR = ${platform_build_directory}
1187 BUILD_DIR = ${platform_build_directory}
1188 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
1189 LIB_DIR = $(BIN_DIR)
1190 MODULE_BUILD_DIR = ${module_build_directory}
1191 OUTPUT_DIR = ${module_output_directory}
1192 DEBUG_DIR = ${module_debug_directory}
1193 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
1194 DEST_DIR_DEBUG = $(DEBUG_DIR)
1195
1196 #
1197 # Tools definitions specific to this module
1198 #
1199 ${BEGIN}${module_tool_definitions}
1200 ${END}
1201 MAKE_FILE = ${makefile_path}
1202
1203 #
1204 # Shell Command Macro
1205 #
1206 ${BEGIN}${shell_command_code} = ${shell_command}
1207 ${END}
1208
1209 ${custom_makefile_content}
1210
1211 #
1212 # Target used when called from platform makefile, which will bypass the build of dependent libraries
1213 #
1214
1215 pbuild: init all
1216
1217
1218 #
1219 # ModuleTarget
1220 #
1221
1222 mbuild: init all
1223
1224 #
1225 # Build Target used in multi-thread build mode, which no init target is needed
1226 #
1227
1228 tbuild: all
1229
1230 #
1231 # Initialization target: print build information and create necessary directories
1232 #
1233 init:
1234 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
1235 ${BEGIN}\t-@${create_directory_command}\n${END}\
1236
1237 ''')
1238
1239 ## Constructor of CustomMakefile
1240 #
1241 # @param ModuleAutoGen Object of ModuleAutoGen class
1242 #
1243 def __init__(self, ModuleAutoGen):
1244 BuildFile.__init__(self, ModuleAutoGen)
1245 self.PlatformInfo = self._AutoGenObject.PlatformInfo
1246 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
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
1438 # Compose a dict object containing information used to do replacement in template
1439 @property
1440 def _TemplateDict(self):
1441 Separator = self._SEP_[self._FileType]
1442
1443 MyAgo = self._AutoGenObject
1444 if "MAKE" not in MyAgo.ToolDefinition or "PATH" not in MyAgo.ToolDefinition["MAKE"]:
1445 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
1446 ExtraData="[%s]" % str(MyAgo))
1447
1448 self.IntermediateDirectoryList = ["$(BUILD_DIR)"]
1449 self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()
1450 self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()
1451
1452 MakefileName = self._FILE_NAME_[self._FileType]
1453 LibraryMakefileList = []
1454 LibraryMakeCommandList = []
1455 for D in self.LibraryBuildDirectoryList:
1456 D = self.PlaceMacro(D, {"BUILD_DIR":MyAgo.BuildDir})
1457 Makefile = os.path.join(D, MakefileName)
1458 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
1459 LibraryMakefileList.append(Makefile)
1460 LibraryMakeCommandList.append(Command)
1461 self.LibraryMakeCommandList = LibraryMakeCommandList
1462
1463 ModuleMakefileList = []
1464 ModuleMakeCommandList = []
1465 for D in self.ModuleBuildDirectoryList:
1466 D = self.PlaceMacro(D, {"BUILD_DIR":MyAgo.BuildDir})
1467 Makefile = os.path.join(D, MakefileName)
1468 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
1469 ModuleMakefileList.append(Makefile)
1470 ModuleMakeCommandList.append(Command)
1471
1472 MakefileTemplateDict = {
1473 "makefile_header" : self._FILE_HEADER_[self._FileType],
1474 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),
1475 "make_path" : MyAgo.ToolDefinition["MAKE"]["PATH"],
1476 "makefile_name" : MakefileName,
1477 "platform_name" : MyAgo.Name,
1478 "platform_guid" : MyAgo.Guid,
1479 "platform_version" : MyAgo.Version,
1480 "platform_file" : MyAgo.MetaFile,
1481 "platform_relative_directory": MyAgo.SourceDir,
1482 "platform_output_directory" : MyAgo.OutputDir,
1483 "platform_build_directory" : MyAgo.BuildDir,
1484 "platform_dir" : MyAgo.Macros["PLATFORM_DIR"],
1485
1486 "toolchain_tag" : MyAgo.ToolChain,
1487 "build_target" : MyAgo.BuildTarget,
1488 "shell_command_code" : list(self._SHELL_CMD_[self._FileType].keys()),
1489 "shell_command" : list(self._SHELL_CMD_[self._FileType].values()),
1490 "build_architecture_list" : MyAgo.Arch,
1491 "architecture" : MyAgo.Arch,
1492 "separator" : Separator,
1493 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1494 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1495 "library_makefile_list" : LibraryMakefileList,
1496 "module_makefile_list" : ModuleMakefileList,
1497 "library_build_command" : LibraryMakeCommandList,
1498 "module_build_command" : ModuleMakeCommandList,
1499 }
1500
1501 return MakefileTemplateDict
1502
1503 ## Get the root directory list for intermediate files of all modules build
1504 #
1505 # @retval list The list of directory
1506 #
1507 def GetModuleBuildDirectoryList(self):
1508 DirList = []
1509 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1510 if not ModuleAutoGen.IsBinaryModule:
1511 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1512 return DirList
1513
1514 ## Get the root directory list for intermediate files of all libraries build
1515 #
1516 # @retval list The list of directory
1517 #
1518 def GetLibraryBuildDirectoryList(self):
1519 DirList = []
1520 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1521 if not LibraryAutoGen.IsBinaryModule:
1522 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1523 return DirList
1524
1525 ## TopLevelMakefile class
1526 #
1527 # This class encapsules makefie and its generation for entrance makefile. It
1528 # uses template to generate the content of makefile. The content of makefile
1529 # will be got from WorkspaceAutoGen object.
1530 #
1531 class TopLevelMakefile(BuildFile):
1532 ## template used to generate toplevel makefile
1533 _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}''')
1534
1535 ## Constructor of TopLevelMakefile
1536 #
1537 # @param Workspace Object of WorkspaceAutoGen class
1538 #
1539 def __init__(self, Workspace):
1540 BuildFile.__init__(self, Workspace)
1541 self.IntermediateDirectoryList = []
1542
1543 # Compose a dict object containing information used to do replacement in template
1544 @property
1545 def _TemplateDict(self):
1546 Separator = self._SEP_[self._FileType]
1547
1548 # any platform autogen object is ok because we just need common information
1549 MyAgo = self._AutoGenObject
1550
1551 if "MAKE" not in MyAgo.ToolDefinition or "PATH" not in MyAgo.ToolDefinition["MAKE"]:
1552 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
1553 ExtraData="[%s]" % str(MyAgo))
1554
1555 for Arch in MyAgo.ArchList:
1556 self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch]))
1557 self.IntermediateDirectoryList.append("$(FV_DIR)")
1558
1559 # TRICK: for not generating GenFds call in makefile if no FDF file
1560 MacroList = []
1561 if MyAgo.FdfFile is not None and MyAgo.FdfFile != "":
1562 FdfFileList = [MyAgo.FdfFile]
1563 # macros passed to GenFds
1564 MacroDict = {}
1565 MacroDict.update(GlobalData.gGlobalDefines)
1566 MacroDict.update(GlobalData.gCommandLineDefines)
1567 for MacroName in MacroDict:
1568 if MacroDict[MacroName] != "":
1569 MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))
1570 else:
1571 MacroList.append('"%s"' % MacroName)
1572 else:
1573 FdfFileList = []
1574
1575 # pass extra common options to external program called in makefile, currently GenFds.exe
1576 ExtraOption = ''
1577 LogLevel = EdkLogger.GetLevel()
1578 if LogLevel == EdkLogger.VERBOSE:
1579 ExtraOption += " -v"
1580 elif LogLevel <= EdkLogger.DEBUG_9:
1581 ExtraOption += " -d %d" % (LogLevel - 1)
1582 elif LogLevel == EdkLogger.QUIET:
1583 ExtraOption += " -q"
1584
1585 if GlobalData.gCaseInsensitive:
1586 ExtraOption += " -c"
1587 if not GlobalData.gEnableGenfdsMultiThread:
1588 ExtraOption += " --no-genfds-multi-thread"
1589 if GlobalData.gIgnoreSource:
1590 ExtraOption += " --ignore-sources"
1591
1592 for pcd in GlobalData.BuildOptionPcd:
1593 if pcd[2]:
1594 pcdname = '.'.join(pcd[0:3])
1595 else:
1596 pcdname = '.'.join(pcd[0:2])
1597 if pcd[3].startswith('{'):
1598 ExtraOption += " --pcd " + pcdname + '=' + 'H' + '"' + pcd[3] + '"'
1599 else:
1600 ExtraOption += " --pcd " + pcdname + '=' + pcd[3]
1601
1602 MakefileName = self._FILE_NAME_[self._FileType]
1603 SubBuildCommandList = []
1604 for A in MyAgo.ArchList:
1605 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)}
1606 SubBuildCommandList.append(Command)
1607
1608 MakefileTemplateDict = {
1609 "makefile_header" : self._FILE_HEADER_[self._FileType],
1610 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),
1611 "make_path" : MyAgo.ToolDefinition["MAKE"]["PATH"],
1612 "platform_name" : MyAgo.Name,
1613 "platform_guid" : MyAgo.Guid,
1614 "platform_version" : MyAgo.Version,
1615 "platform_build_directory" : MyAgo.BuildDir,
1616 "conf_directory" : GlobalData.gConfDirectory,
1617
1618 "toolchain_tag" : MyAgo.ToolChain,
1619 "build_target" : MyAgo.BuildTarget,
1620 "shell_command_code" : list(self._SHELL_CMD_[self._FileType].keys()),
1621 "shell_command" : list(self._SHELL_CMD_[self._FileType].values()),
1622 'arch' : list(MyAgo.ArchList),
1623 "build_architecture_list" : ','.join(MyAgo.ArchList),
1624 "separator" : Separator,
1625 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1626 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1627 "sub_build_command" : SubBuildCommandList,
1628 "fdf_file" : FdfFileList,
1629 "active_platform" : str(MyAgo),
1630 "fd" : MyAgo.FdTargetList,
1631 "fv" : MyAgo.FvTargetList,
1632 "cap" : MyAgo.CapTargetList,
1633 "extra_options" : ExtraOption,
1634 "macro" : MacroList,
1635 }
1636
1637 return MakefileTemplateDict
1638
1639 ## Get the root directory list for intermediate files of all modules build
1640 #
1641 # @retval list The list of directory
1642 #
1643 def GetModuleBuildDirectoryList(self):
1644 DirList = []
1645 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1646 if not ModuleAutoGen.IsBinaryModule:
1647 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1648 return DirList
1649
1650 ## Get the root directory list for intermediate files of all libraries build
1651 #
1652 # @retval list The list of directory
1653 #
1654 def GetLibraryBuildDirectoryList(self):
1655 DirList = []
1656 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1657 if not LibraryAutoGen.IsBinaryModule:
1658 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1659 return DirList
1660
1661 ## Find dependencies for one source file
1662 #
1663 # By searching recursively "#include" directive in file, find out all the
1664 # files needed by given source file. The dependencies will be only searched
1665 # in given search path list.
1666 #
1667 # @param File The source file
1668 # @param ForceInculeList The list of files which will be included forcely
1669 # @param SearchPathList The list of search path
1670 #
1671 # @retval list The list of files the given source file depends on
1672 #
1673 def GetDependencyList(AutoGenObject, FileCache, File, ForceList, SearchPathList):
1674 EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File)
1675 FileStack = [File] + ForceList
1676 DependencySet = set()
1677
1678 if AutoGenObject.Arch not in gDependencyDatabase:
1679 gDependencyDatabase[AutoGenObject.Arch] = {}
1680 DepDb = gDependencyDatabase[AutoGenObject.Arch]
1681
1682 while len(FileStack) > 0:
1683 F = FileStack.pop()
1684
1685 FullPathDependList = []
1686 if F in FileCache:
1687 for CacheFile in FileCache[F]:
1688 FullPathDependList.append(CacheFile)
1689 if CacheFile not in DependencySet:
1690 FileStack.append(CacheFile)
1691 DependencySet.update(FullPathDependList)
1692 continue
1693
1694 CurrentFileDependencyList = []
1695 if F in DepDb:
1696 CurrentFileDependencyList = DepDb[F]
1697 else:
1698 try:
1699 with open(F.Path, 'rb') as Fd:
1700 FileContent = Fd.read(1)
1701 Fd.seek(0)
1702 if not FileContent:
1703 continue
1704 if FileContent[0] == 0xff or FileContent[0] == 0xfe:
1705 FileContent2 = Fd.read()
1706 FileContent2 = FileContent2.decode('utf-16')
1707 IncludedFileList = gIncludePattern.findall(FileContent2)
1708 else:
1709 FileLines = Fd.readlines()
1710 FileContent2 = [line for line in FileLines if str(line).lstrip("#\t ")[:8] == "include "]
1711 simpleFileContent="".join(FileContent2)
1712
1713 IncludedFileList = gIncludePattern.findall(simpleFileContent)
1714 except BaseException as X:
1715 EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path + "\n\t" + str(X))
1716 if not FileContent:
1717 continue
1718
1719 for Inc in IncludedFileList:
1720 Inc = Inc.strip()
1721 # if there's macro used to reference header file, expand it
1722 HeaderList = gMacroPattern.findall(Inc)
1723 if len(HeaderList) == 1 and len(HeaderList[0]) == 2:
1724 HeaderType = HeaderList[0][0]
1725 HeaderKey = HeaderList[0][1]
1726 if HeaderType in gIncludeMacroConversion:
1727 Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey}
1728 else:
1729 # not known macro used in #include, always build the file by
1730 # returning a empty dependency
1731 FileCache[File] = []
1732 return []
1733 Inc = os.path.normpath(Inc)
1734 CurrentFileDependencyList.append(Inc)
1735 DepDb[F] = CurrentFileDependencyList
1736
1737 CurrentFilePath = F.Dir
1738 PathList = [CurrentFilePath] + SearchPathList
1739 for Inc in CurrentFileDependencyList:
1740 for SearchPath in PathList:
1741 FilePath = os.path.join(SearchPath, Inc)
1742 if FilePath in gIsFileMap:
1743 if not gIsFileMap[FilePath]:
1744 continue
1745 # If isfile is called too many times, the performance is slow down.
1746 elif not os.path.isfile(FilePath):
1747 gIsFileMap[FilePath] = False
1748 continue
1749 else:
1750 gIsFileMap[FilePath] = True
1751 FilePath = PathClass(FilePath)
1752 FullPathDependList.append(FilePath)
1753 if FilePath not in DependencySet:
1754 FileStack.append(FilePath)
1755 break
1756 else:
1757 EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\
1758 "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList)))
1759
1760 FileCache[F] = FullPathDependList
1761 DependencySet.update(FullPathDependList)
1762
1763 DependencySet.update(ForceList)
1764 if File in DependencySet:
1765 DependencySet.remove(File)
1766 DependencyList = list(DependencySet) # remove duplicate ones
1767
1768 return DependencyList
1769
1770 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1771 if __name__ == '__main__':
1772 pass