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