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