]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/GenMake.py
BaseTools: use stdint.h for GCC ProcessorBind.h typedefs
[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 try:
641 for fl in os.listdir(current_dir):
642 if fl.endswith('.dec'):
643 found = True
644 break
645 except:
646 EdkLogger.error('build', FILE_NOT_FOUND, "WORKSPACE does not exist.")
647 package_rel_dir = package_rel_dir[index + 1:]
648
649 MakefileTemplateDict = {
650 "makefile_header" : self._FILE_HEADER_[self._FileType],
651 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
652 "makefile_name" : MakefileName,
653 "platform_name" : self.PlatformInfo.Name,
654 "platform_guid" : self.PlatformInfo.Guid,
655 "platform_version" : self.PlatformInfo.Version,
656 "platform_relative_directory": self.PlatformInfo.SourceDir,
657 "platform_output_directory" : self.PlatformInfo.OutputDir,
658 "ffs_output_directory" : MyAgo.Macros["FFS_OUTPUT_DIR"],
659 "platform_dir" : MyAgo.Macros["PLATFORM_DIR"],
660
661 "module_name" : MyAgo.Name,
662 "module_guid" : MyAgo.Guid,
663 "module_name_guid" : MyAgo.UniqueBaseName,
664 "module_version" : MyAgo.Version,
665 "module_type" : MyAgo.ModuleType,
666 "module_file" : MyAgo.MetaFile.Name,
667 "module_file_base_name" : MyAgo.MetaFile.BaseName,
668 "module_relative_directory" : MyAgo.SourceDir,
669 "module_dir" : mws.join (self.Macros["WORKSPACE"], MyAgo.SourceDir),
670 "package_relative_directory": package_rel_dir,
671 "module_extra_defines" : ["%s = %s" % (k, v) for k, v in MyAgo.Module.Defines.items()],
672
673 "architecture" : MyAgo.Arch,
674 "toolchain_tag" : MyAgo.ToolChain,
675 "build_target" : MyAgo.BuildTarget,
676
677 "platform_build_directory" : self.PlatformInfo.BuildDir,
678 "module_build_directory" : MyAgo.BuildDir,
679 "module_output_directory" : MyAgo.OutputDir,
680 "module_debug_directory" : MyAgo.DebugDir,
681
682 "separator" : Separator,
683 "module_tool_definitions" : ToolsDef,
684
685 "shell_command_code" : list(self._SHELL_CMD_[self._FileType].keys()),
686 "shell_command" : list(self._SHELL_CMD_[self._FileType].values()),
687
688 "module_entry_point" : ModuleEntryPoint,
689 "image_entry_point" : ImageEntryPoint,
690 "arch_entry_point" : ArchEntryPoint,
691 "remaining_build_target" : self.ResultFileList,
692 "common_dependency_file" : self.CommonFileDependency,
693 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
694 "clean_command" : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]),
695 "cleanall_command" : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]),
696 "dependent_library_build_directory" : self.LibraryBuildDirectoryList,
697 "library_build_command" : LibraryMakeCommandList,
698 "file_macro" : FileMacroList,
699 "file_build_target" : self.BuildTargetList,
700 "backward_compatible_target": BcTargetList,
701 }
702
703 return MakefileTemplateDict
704
705 def ParserGenerateFfsCmd(self):
706 #Add Ffs cmd to self.BuildTargetList
707 OutputFile = ''
708 DepsFileList = []
709
710 for Cmd in self.GenFfsList:
711 if Cmd[2]:
712 for CopyCmd in Cmd[2]:
713 Src, Dst = CopyCmd
714 Src = self.ReplaceMacro(Src)
715 Dst = self.ReplaceMacro(Dst)
716 if Dst not in self.ResultFileList:
717 self.ResultFileList.append(Dst)
718 if '%s :' %(Dst) not in self.BuildTargetList:
719 self.BuildTargetList.append("%s :" %(Dst))
720 self.BuildTargetList.append('\t' + self._CP_TEMPLATE_[self._FileType] %{'Src': Src, 'Dst': Dst})
721
722 FfsCmdList = Cmd[0]
723 for index, Str in enumerate(FfsCmdList):
724 if '-o' == Str:
725 OutputFile = FfsCmdList[index + 1]
726 if '-i' == Str or "-oi" == Str:
727 if DepsFileList == []:
728 DepsFileList = [FfsCmdList[index + 1]]
729 else:
730 DepsFileList.append(FfsCmdList[index + 1])
731 DepsFileString = ' '.join(DepsFileList).strip()
732 if DepsFileString == '':
733 continue
734 OutputFile = self.ReplaceMacro(OutputFile)
735 self.ResultFileList.append(OutputFile)
736 DepsFileString = self.ReplaceMacro(DepsFileString)
737 self.BuildTargetList.append('%s : %s' % (OutputFile, DepsFileString))
738 CmdString = ' '.join(FfsCmdList).strip()
739 CmdString = self.ReplaceMacro(CmdString)
740 self.BuildTargetList.append('\t%s' % CmdString)
741
742 self.ParseSecCmd(DepsFileList, Cmd[1])
743 for SecOutputFile, SecDepsFile, SecCmd in self.FfsOutputFileList :
744 self.BuildTargetList.append('%s : %s' % (self.ReplaceMacro(SecOutputFile), self.ReplaceMacro(SecDepsFile)))
745 self.BuildTargetList.append('\t%s' % self.ReplaceMacro(SecCmd))
746 self.FfsOutputFileList = []
747
748 def ParseSecCmd(self, OutputFileList, CmdTuple):
749 for OutputFile in OutputFileList:
750 for SecCmdStr in CmdTuple:
751 SecDepsFileList = []
752 SecCmdList = SecCmdStr.split()
753 CmdName = SecCmdList[0]
754 for index, CmdItem in enumerate(SecCmdList):
755 if '-o' == CmdItem and OutputFile == SecCmdList[index + 1]:
756 index = index + 1
757 while index + 1 < len(SecCmdList):
758 if not SecCmdList[index+1].startswith('-'):
759 SecDepsFileList.append(SecCmdList[index + 1])
760 index = index + 1
761 if CmdName == 'Trim':
762 SecDepsFileList.append(os.path.join('$(DEBUG_DIR)', os.path.basename(OutputFile).replace('offset', 'efi')))
763 if OutputFile.endswith('.ui') or OutputFile.endswith('.ver'):
764 SecDepsFileList.append(os.path.join('$(MODULE_DIR)', '$(MODULE_FILE)'))
765 self.FfsOutputFileList.append((OutputFile, ' '.join(SecDepsFileList), SecCmdStr))
766 if len(SecDepsFileList) > 0:
767 self.ParseSecCmd(SecDepsFileList, CmdTuple)
768 break
769 else:
770 continue
771
772 def ReplaceMacro(self, str):
773 for Macro in self.MacroList:
774 if self._AutoGenObject.Macros[Macro] and self._AutoGenObject.Macros[Macro] in str:
775 str = str.replace(self._AutoGenObject.Macros[Macro], '$(' + Macro + ')')
776 return str
777
778 def CommandExceedLimit(self):
779 FlagDict = {
780 'CC' : { 'Macro' : '$(CC_FLAGS)', 'Value' : False},
781 'PP' : { 'Macro' : '$(PP_FLAGS)', 'Value' : False},
782 'APP' : { 'Macro' : '$(APP_FLAGS)', 'Value' : False},
783 'ASLPP' : { 'Macro' : '$(ASLPP_FLAGS)', 'Value' : False},
784 'VFRPP' : { 'Macro' : '$(VFRPP_FLAGS)', 'Value' : False},
785 'ASM' : { 'Macro' : '$(ASM_FLAGS)', 'Value' : False},
786 'ASLCC' : { 'Macro' : '$(ASLCC_FLAGS)', 'Value' : False},
787 }
788
789 RespDict = {}
790 FileTypeList = []
791 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
792
793 # base on the source files to decide the file type
794 for File in self._AutoGenObject.SourceFileList:
795 for type in self._AutoGenObject.FileTypes:
796 if File in self._AutoGenObject.FileTypes[type]:
797 if type not in FileTypeList:
798 FileTypeList.append(type)
799
800 # calculate the command-line length
801 if FileTypeList:
802 for type in FileTypeList:
803 BuildTargets = self._AutoGenObject.BuildRules[type].BuildTargets
804 for Target in BuildTargets:
805 CommandList = BuildTargets[Target].Commands
806 for SingleCommand in CommandList:
807 Tool = ''
808 SingleCommandLength = len(SingleCommand)
809 SingleCommandList = SingleCommand.split()
810 if len(SingleCommandList) > 0:
811 for Flag in FlagDict:
812 if '$('+ Flag +')' in SingleCommandList[0]:
813 Tool = Flag
814 break
815 if Tool:
816 if 'PATH' not in self._AutoGenObject.BuildOption[Tool]:
817 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))
818 SingleCommandLength += len(self._AutoGenObject.BuildOption[Tool]['PATH'])
819 for item in SingleCommandList[1:]:
820 if FlagDict[Tool]['Macro'] in item:
821 if 'FLAGS' not in self._AutoGenObject.BuildOption[Tool]:
822 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))
823 Str = self._AutoGenObject.BuildOption[Tool]['FLAGS']
824 for Option in self._AutoGenObject.BuildOption:
825 for Attr in self._AutoGenObject.BuildOption[Option]:
826 if Str.find(Option + '_' + Attr) != -1:
827 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
828 while(Str.find('$(') != -1):
829 for macro in self._AutoGenObject.Macros:
830 MacroName = '$('+ macro + ')'
831 if (Str.find(MacroName) != -1):
832 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
833 break
834 else:
835 break
836 SingleCommandLength += len(Str)
837 elif '$(INC)' in item:
838 SingleCommandLength += self._AutoGenObject.IncludePathLength + len(IncPrefix) * len(self._AutoGenObject.IncludePathList)
839 elif item.find('$(') != -1:
840 Str = item
841 for Option in self._AutoGenObject.BuildOption:
842 for Attr in self._AutoGenObject.BuildOption[Option]:
843 if Str.find(Option + '_' + Attr) != -1:
844 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
845 while(Str.find('$(') != -1):
846 for macro in self._AutoGenObject.Macros:
847 MacroName = '$('+ macro + ')'
848 if (Str.find(MacroName) != -1):
849 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
850 break
851 else:
852 break
853 SingleCommandLength += len(Str)
854
855 if SingleCommandLength > GlobalData.gCommandMaxLength:
856 FlagDict[Tool]['Value'] = True
857
858 # generate the response file content by combine the FLAGS and INC
859 for Flag in FlagDict:
860 if FlagDict[Flag]['Value']:
861 Key = Flag + '_RESP'
862 RespMacro = FlagDict[Flag]['Macro'].replace('FLAGS', 'RESP')
863 Value = self._AutoGenObject.BuildOption[Flag]['FLAGS']
864 for inc in self._AutoGenObject.IncludePathList:
865 Value += ' ' + IncPrefix + inc
866 for Option in self._AutoGenObject.BuildOption:
867 for Attr in self._AutoGenObject.BuildOption[Option]:
868 if Value.find(Option + '_' + Attr) != -1:
869 Value = Value.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
870 while (Value.find('$(') != -1):
871 for macro in self._AutoGenObject.Macros:
872 MacroName = '$('+ macro + ')'
873 if (Value.find(MacroName) != -1):
874 Value = Value.replace(MacroName, self._AutoGenObject.Macros[macro])
875 break
876 else:
877 break
878
879 if self._AutoGenObject.ToolChainFamily == 'GCC':
880 RespDict[Key] = Value.replace('\\', '/')
881 else:
882 RespDict[Key] = Value
883 for Target in BuildTargets:
884 for i, SingleCommand in enumerate(BuildTargets[Target].Commands):
885 if FlagDict[Flag]['Macro'] in SingleCommand:
886 BuildTargets[Target].Commands[i] = SingleCommand.replace('$(INC)', '').replace(FlagDict[Flag]['Macro'], RespMacro)
887 return RespDict
888
889 def ProcessBuildTargetList(self):
890 #
891 # Search dependency file list for each source file
892 #
893 ForceIncludedFile = []
894 for File in self._AutoGenObject.AutoGenFileList:
895 if File.Ext == '.h':
896 ForceIncludedFile.append(File)
897 SourceFileList = []
898 OutPutFileList = []
899 for Target in self._AutoGenObject.IntroTargetList:
900 SourceFileList.extend(Target.Inputs)
901 OutPutFileList.extend(Target.Outputs)
902
903 if OutPutFileList:
904 for Item in OutPutFileList:
905 if Item in SourceFileList:
906 SourceFileList.remove(Item)
907
908 FileDependencyDict = self.GetFileDependency(
909 SourceFileList,
910 ForceIncludedFile,
911 self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList
912 )
913
914
915 if FileDependencyDict:
916 for Dependency in FileDependencyDict.values():
917 self.DependencyHeaderFileSet.update(set(Dependency))
918
919 # Get a set of unique package includes from MetaFile
920 parentMetaFileIncludes = set()
921 for aInclude in self._AutoGenObject.PackageIncludePathList:
922 aIncludeName = str(aInclude)
923 parentMetaFileIncludes.add(aIncludeName.lower())
924
925 # Check if header files are listed in metafile
926 # Get a set of unique module header source files from MetaFile
927 headerFilesInMetaFileSet = set()
928 for aFile in self._AutoGenObject.SourceFileList:
929 aFileName = str(aFile)
930 if not aFileName.endswith('.h'):
931 continue
932 headerFilesInMetaFileSet.add(aFileName.lower())
933
934 # Get a set of unique module autogen files
935 localAutoGenFileSet = set()
936 for aFile in self._AutoGenObject.AutoGenFileList:
937 localAutoGenFileSet.add(str(aFile).lower())
938
939 # Get a set of unique module dependency header files
940 # Exclude autogen files and files not in the source directory
941 # and files that are under the package include list
942 headerFileDependencySet = set()
943 localSourceDir = str(self._AutoGenObject.SourceDir).lower()
944 for Dependency in FileDependencyDict.values():
945 for aFile in Dependency:
946 aFileName = str(aFile).lower()
947 # Exclude non-header files
948 if not aFileName.endswith('.h'):
949 continue
950 # Exclude autogen files
951 if aFileName in localAutoGenFileSet:
952 continue
953 # Exclude include out of local scope
954 if localSourceDir not in aFileName:
955 continue
956 # Exclude files covered by package includes
957 pathNeeded = True
958 for aIncludePath in parentMetaFileIncludes:
959 if aIncludePath in aFileName:
960 pathNeeded = False
961 break
962 if not pathNeeded:
963 continue
964 # Keep the file to be checked
965 headerFileDependencySet.add(aFileName)
966
967 # Check if a module dependency header file is missing from the module's MetaFile
968 for aFile in headerFileDependencySet:
969 if aFile in headerFilesInMetaFileSet:
970 continue
971 if GlobalData.gUseHashCache:
972 GlobalData.gModuleBuildTracking[self._AutoGenObject] = 'FAIL_METAFILE'
973 EdkLogger.warn("build","Module MetaFile [Sources] is missing local header!",
974 ExtraData = "Local Header: " + aFile + " not found in " + self._AutoGenObject.MetaFile.Path
975 )
976
977 DepSet = None
978 for File,Dependency in FileDependencyDict.items():
979 if not Dependency:
980 FileDependencyDict[File] = ['$(FORCE_REBUILD)']
981 continue
982
983 self._AutoGenObject.AutoGenDepSet |= set(Dependency)
984
985 # skip non-C files
986 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
987 continue
988 elif DepSet is None:
989 DepSet = set(Dependency)
990 else:
991 DepSet &= set(Dependency)
992 # in case nothing in SourceFileList
993 if DepSet is None:
994 DepSet = set()
995 #
996 # Extract common files list in the dependency files
997 #
998 for File in DepSet:
999 self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros))
1000
1001 CmdSumDict = {}
1002 CmdTargetDict = {}
1003 CmdCppDict = {}
1004 DependencyDict = FileDependencyDict.copy()
1005 for File in FileDependencyDict:
1006 # skip non-C files
1007 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
1008 continue
1009 NewDepSet = set(FileDependencyDict[File])
1010 NewDepSet -= DepSet
1011 FileDependencyDict[File] = ["$(COMMON_DEPS)"] + list(NewDepSet)
1012 DependencyDict[File] = list(NewDepSet)
1013
1014 # Convert target description object to target string in makefile
1015 if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and TAB_C_CODE_FILE in self._AutoGenObject.Targets:
1016 for T in self._AutoGenObject.Targets[TAB_C_CODE_FILE]:
1017 NewFile = self.PlaceMacro(str(T), self.Macros)
1018 if not self.ObjTargetDict.get(T.Target.SubDir):
1019 self.ObjTargetDict[T.Target.SubDir] = set()
1020 self.ObjTargetDict[T.Target.SubDir].add(NewFile)
1021 for Type in self._AutoGenObject.Targets:
1022 for T in self._AutoGenObject.Targets[Type]:
1023 # Generate related macros if needed
1024 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
1025 self.FileListMacros[T.FileListMacro] = []
1026 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:
1027 self.ListFileMacros[T.ListFileMacro] = []
1028 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:
1029 self.ListFileMacros[T.IncListFileMacro] = []
1030
1031 Deps = []
1032 CCodeDeps = []
1033 # Add force-dependencies
1034 for Dep in T.Dependencies:
1035 Deps.append(self.PlaceMacro(str(Dep), self.Macros))
1036 if Dep != '$(MAKE_FILE)':
1037 CCodeDeps.append(self.PlaceMacro(str(Dep), self.Macros))
1038 # Add inclusion-dependencies
1039 if len(T.Inputs) == 1 and T.Inputs[0] in FileDependencyDict:
1040 for F in FileDependencyDict[T.Inputs[0]]:
1041 Deps.append(self.PlaceMacro(str(F), self.Macros))
1042 # Add source-dependencies
1043 for F in T.Inputs:
1044 NewFile = self.PlaceMacro(str(F), self.Macros)
1045 # In order to use file list macro as dependency
1046 if T.GenListFile:
1047 # gnu tools need forward slash path separator, even on Windows
1048 self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/'))
1049 self.FileListMacros[T.FileListMacro].append(NewFile)
1050 elif T.GenFileListMacro:
1051 self.FileListMacros[T.FileListMacro].append(NewFile)
1052 else:
1053 Deps.append(NewFile)
1054 for key in self.FileListMacros:
1055 self.FileListMacros[key].sort()
1056 # Use file list macro as dependency
1057 if T.GenFileListMacro:
1058 Deps.append("$(%s)" % T.FileListMacro)
1059 if Type in [TAB_OBJECT_FILE, TAB_STATIC_LIBRARY]:
1060 Deps.append("$(%s)" % T.ListFileMacro)
1061
1062 if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and Type == TAB_C_CODE_FILE:
1063 T, CmdTarget, CmdTargetDict, CmdCppDict = self.ParserCCodeFile(T, Type, CmdSumDict, CmdTargetDict, CmdCppDict, DependencyDict)
1064 TargetDict = {"target": self.PlaceMacro(T.Target.Path, self.Macros), "cmd": "\n\t".join(T.Commands),"deps": CCodeDeps}
1065 CmdLine = self._BUILD_TARGET_TEMPLATE.Replace(TargetDict).rstrip().replace('\t$(OBJLIST', '$(OBJLIST')
1066 if T.Commands:
1067 CmdLine = '%s%s' %(CmdLine, TAB_LINE_BREAK)
1068 if CCodeDeps or CmdLine:
1069 self.BuildTargetList.append(CmdLine)
1070 else:
1071 TargetDict = {"target": self.PlaceMacro(T.Target.Path, self.Macros), "cmd": "\n\t".join(T.Commands),"deps": Deps}
1072 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
1073
1074 def ParserCCodeFile(self, T, Type, CmdSumDict, CmdTargetDict, CmdCppDict, DependencyDict):
1075 if not CmdSumDict:
1076 for item in self._AutoGenObject.Targets[Type]:
1077 CmdSumDict[item.Target.SubDir] = item.Target.BaseName
1078 for CppPath in item.Inputs:
1079 Path = self.PlaceMacro(CppPath.Path, self.Macros)
1080 if CmdCppDict.get(item.Target.SubDir):
1081 CmdCppDict[item.Target.SubDir].append(Path)
1082 else:
1083 CmdCppDict[item.Target.SubDir] = ['$(MAKE_FILE)', Path]
1084 if CppPath.Path in DependencyDict:
1085 for Temp in DependencyDict[CppPath.Path]:
1086 try:
1087 Path = self.PlaceMacro(Temp.Path, self.Macros)
1088 except:
1089 continue
1090 if Path not in (self.CommonFileDependency + CmdCppDict[item.Target.SubDir]):
1091 CmdCppDict[item.Target.SubDir].append(Path)
1092 if T.Commands:
1093 CommandList = T.Commands[:]
1094 for Item in CommandList[:]:
1095 SingleCommandList = Item.split()
1096 if len(SingleCommandList) > 0 and self.CheckCCCmd(SingleCommandList):
1097 for Temp in SingleCommandList:
1098 if Temp.startswith('/Fo'):
1099 CmdSign = '%s%s' % (Temp.rsplit(TAB_SLASH, 1)[0], TAB_SLASH)
1100 break
1101 else: continue
1102 if CmdSign not in list(CmdTargetDict.keys()):
1103 CmdTargetDict[CmdSign] = Item.replace(Temp, CmdSign)
1104 else:
1105 CmdTargetDict[CmdSign] = "%s %s" % (CmdTargetDict[CmdSign], SingleCommandList[-1])
1106 Index = CommandList.index(Item)
1107 CommandList.pop(Index)
1108 if SingleCommandList[-1].endswith("%s%s.c" % (TAB_SLASH, CmdSumDict[CmdSign[3:].rsplit(TAB_SLASH, 1)[0]])):
1109 Cpplist = CmdCppDict[T.Target.SubDir]
1110 Cpplist.insert(0, '$(OBJLIST_%d): $(COMMON_DEPS)' % list(self.ObjTargetDict.keys()).index(T.Target.SubDir))
1111 T.Commands[Index] = '%s\n\t%s' % (' \\\n\t'.join(Cpplist), CmdTargetDict[CmdSign])
1112 else:
1113 T.Commands.pop(Index)
1114 return T, CmdSumDict, CmdTargetDict, CmdCppDict
1115
1116 def CheckCCCmd(self, CommandList):
1117 for cmd in CommandList:
1118 if '$(CC)' in cmd:
1119 return True
1120 return False
1121 ## For creating makefile targets for dependent libraries
1122 def ProcessDependentLibrary(self):
1123 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1124 if not LibraryAutoGen.IsBinaryModule:
1125 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
1126
1127 ## Return a list containing source file's dependencies
1128 #
1129 # @param FileList The list of source files
1130 # @param ForceInculeList The list of files which will be included forcely
1131 # @param SearchPathList The list of search path
1132 #
1133 # @retval dict The mapping between source file path and its dependencies
1134 #
1135 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
1136 Dependency = {}
1137 for F in FileList:
1138 Dependency[F] = GetDependencyList(self._AutoGenObject, self.FileCache, F, ForceInculeList, SearchPathList)
1139 return Dependency
1140
1141
1142 ## CustomMakefile class
1143 #
1144 # This class encapsules makefie and its generation for module. It uses template to generate
1145 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
1146 #
1147 class CustomMakefile(BuildFile):
1148 ## template used to generate the makefile for module with custom makefile
1149 _TEMPLATE_ = TemplateString('''\
1150 ${makefile_header}
1151
1152 #
1153 # Platform Macro Definition
1154 #
1155 PLATFORM_NAME = ${platform_name}
1156 PLATFORM_GUID = ${platform_guid}
1157 PLATFORM_VERSION = ${platform_version}
1158 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
1159 PLATFORM_DIR = ${platform_dir}
1160 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1161
1162 #
1163 # Module Macro Definition
1164 #
1165 MODULE_NAME = ${module_name}
1166 MODULE_GUID = ${module_guid}
1167 MODULE_NAME_GUID = ${module_name_guid}
1168 MODULE_VERSION = ${module_version}
1169 MODULE_TYPE = ${module_type}
1170 MODULE_FILE = ${module_file}
1171 MODULE_FILE_BASE_NAME = ${module_file_base_name}
1172 BASE_NAME = $(MODULE_NAME)
1173 MODULE_RELATIVE_DIR = ${module_relative_directory}
1174 MODULE_DIR = ${module_dir}
1175
1176 #
1177 # Build Configuration Macro Definition
1178 #
1179 ARCH = ${architecture}
1180 TOOLCHAIN = ${toolchain_tag}
1181 TOOLCHAIN_TAG = ${toolchain_tag}
1182 TARGET = ${build_target}
1183
1184 #
1185 # Build Directory Macro Definition
1186 #
1187 # PLATFORM_BUILD_DIR = ${platform_build_directory}
1188 BUILD_DIR = ${platform_build_directory}
1189 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
1190 LIB_DIR = $(BIN_DIR)
1191 MODULE_BUILD_DIR = ${module_build_directory}
1192 OUTPUT_DIR = ${module_output_directory}
1193 DEBUG_DIR = ${module_debug_directory}
1194 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
1195 DEST_DIR_DEBUG = $(DEBUG_DIR)
1196
1197 #
1198 # Tools definitions specific to this module
1199 #
1200 ${BEGIN}${module_tool_definitions}
1201 ${END}
1202 MAKE_FILE = ${makefile_path}
1203
1204 #
1205 # Shell Command Macro
1206 #
1207 ${BEGIN}${shell_command_code} = ${shell_command}
1208 ${END}
1209
1210 ${custom_makefile_content}
1211
1212 #
1213 # Target used when called from platform makefile, which will bypass the build of dependent libraries
1214 #
1215
1216 pbuild: init all
1217
1218
1219 #
1220 # ModuleTarget
1221 #
1222
1223 mbuild: init all
1224
1225 #
1226 # Build Target used in multi-thread build mode, which no init target is needed
1227 #
1228
1229 tbuild: all
1230
1231 #
1232 # Initialization target: print build information and create necessary directories
1233 #
1234 init:
1235 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
1236 ${BEGIN}\t-@${create_directory_command}\n${END}\
1237
1238 ''')
1239
1240 ## Constructor of CustomMakefile
1241 #
1242 # @param ModuleAutoGen Object of ModuleAutoGen class
1243 #
1244 def __init__(self, ModuleAutoGen):
1245 BuildFile.__init__(self, ModuleAutoGen)
1246 self.PlatformInfo = self._AutoGenObject.PlatformInfo
1247 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
1248 self.DependencyHeaderFileSet = set()
1249
1250 # Compose a dict object containing information used to do replacement in template
1251 @property
1252 def _TemplateDict(self):
1253 Separator = self._SEP_[self._FileType]
1254 MyAgo = self._AutoGenObject
1255 if self._FileType not in MyAgo.CustomMakefile:
1256 EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType,
1257 ExtraData="[%s]" % str(MyAgo))
1258 MakefilePath = mws.join(
1259 MyAgo.WorkspaceDir,
1260 MyAgo.CustomMakefile[self._FileType]
1261 )
1262 try:
1263 CustomMakefile = open(MakefilePath, 'r').read()
1264 except:
1265 EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(MyAgo),
1266 ExtraData=MyAgo.CustomMakefile[self._FileType])
1267
1268 # tools definitions
1269 ToolsDef = []
1270 for Tool in MyAgo.BuildOption:
1271 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
1272 if Tool == "MAKE":
1273 continue
1274 for Attr in MyAgo.BuildOption[Tool]:
1275 if Attr == "FAMILY":
1276 continue
1277 elif Attr == "PATH":
1278 ToolsDef.append("%s = %s" % (Tool, MyAgo.BuildOption[Tool][Attr]))
1279 else:
1280 ToolsDef.append("%s_%s = %s" % (Tool, Attr, MyAgo.BuildOption[Tool][Attr]))
1281 ToolsDef.append("")
1282
1283 MakefileName = self._FILE_NAME_[self._FileType]
1284 MakefileTemplateDict = {
1285 "makefile_header" : self._FILE_HEADER_[self._FileType],
1286 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
1287 "platform_name" : self.PlatformInfo.Name,
1288 "platform_guid" : self.PlatformInfo.Guid,
1289 "platform_version" : self.PlatformInfo.Version,
1290 "platform_relative_directory": self.PlatformInfo.SourceDir,
1291 "platform_output_directory" : self.PlatformInfo.OutputDir,
1292 "platform_dir" : MyAgo.Macros["PLATFORM_DIR"],
1293
1294 "module_name" : MyAgo.Name,
1295 "module_guid" : MyAgo.Guid,
1296 "module_name_guid" : MyAgo.UniqueBaseName,
1297 "module_version" : MyAgo.Version,
1298 "module_type" : MyAgo.ModuleType,
1299 "module_file" : MyAgo.MetaFile,
1300 "module_file_base_name" : MyAgo.MetaFile.BaseName,
1301 "module_relative_directory" : MyAgo.SourceDir,
1302 "module_dir" : mws.join (MyAgo.WorkspaceDir, MyAgo.SourceDir),
1303
1304 "architecture" : MyAgo.Arch,
1305 "toolchain_tag" : MyAgo.ToolChain,
1306 "build_target" : MyAgo.BuildTarget,
1307
1308 "platform_build_directory" : self.PlatformInfo.BuildDir,
1309 "module_build_directory" : MyAgo.BuildDir,
1310 "module_output_directory" : MyAgo.OutputDir,
1311 "module_debug_directory" : MyAgo.DebugDir,
1312
1313 "separator" : Separator,
1314 "module_tool_definitions" : ToolsDef,
1315
1316 "shell_command_code" : list(self._SHELL_CMD_[self._FileType].keys()),
1317 "shell_command" : list(self._SHELL_CMD_[self._FileType].values()),
1318
1319 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1320 "custom_makefile_content" : CustomMakefile
1321 }
1322
1323 return MakefileTemplateDict
1324
1325 ## PlatformMakefile class
1326 #
1327 # This class encapsules makefie and its generation for platform. It uses
1328 # template to generate the content of makefile. The content of makefile will be
1329 # got from PlatformAutoGen object.
1330 #
1331 class PlatformMakefile(BuildFile):
1332 ## template used to generate the makefile for platform
1333 _TEMPLATE_ = TemplateString('''\
1334 ${makefile_header}
1335
1336 #
1337 # Platform Macro Definition
1338 #
1339 PLATFORM_NAME = ${platform_name}
1340 PLATFORM_GUID = ${platform_guid}
1341 PLATFORM_VERSION = ${platform_version}
1342 PLATFORM_FILE = ${platform_file}
1343 PLATFORM_DIR = ${platform_dir}
1344 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1345
1346 #
1347 # Build Configuration Macro Definition
1348 #
1349 TOOLCHAIN = ${toolchain_tag}
1350 TOOLCHAIN_TAG = ${toolchain_tag}
1351 TARGET = ${build_target}
1352
1353 #
1354 # Build Directory Macro Definition
1355 #
1356 BUILD_DIR = ${platform_build_directory}
1357 FV_DIR = ${platform_build_directory}${separator}FV
1358
1359 #
1360 # Shell Command Macro
1361 #
1362 ${BEGIN}${shell_command_code} = ${shell_command}
1363 ${END}
1364
1365 MAKE = ${make_path}
1366 MAKE_FILE = ${makefile_path}
1367
1368 #
1369 # Default target
1370 #
1371 all: init build_libraries build_modules
1372
1373 #
1374 # Initialization target: print build information and create necessary directories
1375 #
1376 init:
1377 \t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
1378 \t${BEGIN}-@${create_directory_command}
1379 \t${END}
1380 #
1381 # library build target
1382 #
1383 libraries: init build_libraries
1384
1385 #
1386 # module build target
1387 #
1388 modules: init build_libraries build_modules
1389
1390 #
1391 # Build all libraries:
1392 #
1393 build_libraries:
1394 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
1395 ${END}\t@cd $(BUILD_DIR)
1396
1397 #
1398 # Build all modules:
1399 #
1400 build_modules:
1401 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
1402 ${END}\t@cd $(BUILD_DIR)
1403
1404 #
1405 # Clean intermediate files
1406 #
1407 clean:
1408 \t${BEGIN}-@${library_build_command} clean
1409 \t${END}${BEGIN}-@${module_build_command} clean
1410 \t${END}@cd $(BUILD_DIR)
1411
1412 #
1413 # Clean all generated files except to makefile
1414 #
1415 cleanall:
1416 ${BEGIN}\t${cleanall_command}
1417 ${END}
1418
1419 #
1420 # Clean all library files
1421 #
1422 cleanlib:
1423 \t${BEGIN}-@${library_build_command} cleanall
1424 \t${END}@cd $(BUILD_DIR)\n
1425 ''')
1426
1427 ## Constructor of PlatformMakefile
1428 #
1429 # @param ModuleAutoGen Object of PlatformAutoGen class
1430 #
1431 def __init__(self, PlatformAutoGen):
1432 BuildFile.__init__(self, PlatformAutoGen)
1433 self.ModuleBuildCommandList = []
1434 self.ModuleMakefileList = []
1435 self.IntermediateDirectoryList = []
1436 self.ModuleBuildDirectoryList = []
1437 self.LibraryBuildDirectoryList = []
1438 self.LibraryMakeCommandList = []
1439 self.DependencyHeaderFileSet = set()
1440
1441 # Compose a dict object containing information used to do replacement in template
1442 @property
1443 def _TemplateDict(self):
1444 Separator = self._SEP_[self._FileType]
1445
1446 MyAgo = self._AutoGenObject
1447 if "MAKE" not in MyAgo.ToolDefinition or "PATH" not in MyAgo.ToolDefinition["MAKE"]:
1448 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
1449 ExtraData="[%s]" % str(MyAgo))
1450
1451 self.IntermediateDirectoryList = ["$(BUILD_DIR)"]
1452 self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()
1453 self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()
1454
1455 MakefileName = self._FILE_NAME_[self._FileType]
1456 LibraryMakefileList = []
1457 LibraryMakeCommandList = []
1458 for D in self.LibraryBuildDirectoryList:
1459 D = self.PlaceMacro(D, {"BUILD_DIR":MyAgo.BuildDir})
1460 Makefile = os.path.join(D, MakefileName)
1461 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
1462 LibraryMakefileList.append(Makefile)
1463 LibraryMakeCommandList.append(Command)
1464 self.LibraryMakeCommandList = LibraryMakeCommandList
1465
1466 ModuleMakefileList = []
1467 ModuleMakeCommandList = []
1468 for D in self.ModuleBuildDirectoryList:
1469 D = self.PlaceMacro(D, {"BUILD_DIR":MyAgo.BuildDir})
1470 Makefile = os.path.join(D, MakefileName)
1471 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
1472 ModuleMakefileList.append(Makefile)
1473 ModuleMakeCommandList.append(Command)
1474
1475 MakefileTemplateDict = {
1476 "makefile_header" : self._FILE_HEADER_[self._FileType],
1477 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),
1478 "make_path" : MyAgo.ToolDefinition["MAKE"]["PATH"],
1479 "makefile_name" : MakefileName,
1480 "platform_name" : MyAgo.Name,
1481 "platform_guid" : MyAgo.Guid,
1482 "platform_version" : MyAgo.Version,
1483 "platform_file" : MyAgo.MetaFile,
1484 "platform_relative_directory": MyAgo.SourceDir,
1485 "platform_output_directory" : MyAgo.OutputDir,
1486 "platform_build_directory" : MyAgo.BuildDir,
1487 "platform_dir" : MyAgo.Macros["PLATFORM_DIR"],
1488
1489 "toolchain_tag" : MyAgo.ToolChain,
1490 "build_target" : MyAgo.BuildTarget,
1491 "shell_command_code" : list(self._SHELL_CMD_[self._FileType].keys()),
1492 "shell_command" : list(self._SHELL_CMD_[self._FileType].values()),
1493 "build_architecture_list" : MyAgo.Arch,
1494 "architecture" : MyAgo.Arch,
1495 "separator" : Separator,
1496 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1497 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1498 "library_makefile_list" : LibraryMakefileList,
1499 "module_makefile_list" : ModuleMakefileList,
1500 "library_build_command" : LibraryMakeCommandList,
1501 "module_build_command" : ModuleMakeCommandList,
1502 }
1503
1504 return MakefileTemplateDict
1505
1506 ## Get the root directory list for intermediate files of all modules build
1507 #
1508 # @retval list The list of directory
1509 #
1510 def GetModuleBuildDirectoryList(self):
1511 DirList = []
1512 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1513 if not ModuleAutoGen.IsBinaryModule:
1514 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1515 return DirList
1516
1517 ## Get the root directory list for intermediate files of all libraries build
1518 #
1519 # @retval list The list of directory
1520 #
1521 def GetLibraryBuildDirectoryList(self):
1522 DirList = []
1523 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1524 if not LibraryAutoGen.IsBinaryModule:
1525 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1526 return DirList
1527
1528 ## TopLevelMakefile class
1529 #
1530 # This class encapsules makefie and its generation for entrance makefile. It
1531 # uses template to generate the content of makefile. The content of makefile
1532 # will be got from WorkspaceAutoGen object.
1533 #
1534 class TopLevelMakefile(BuildFile):
1535 ## template used to generate toplevel makefile
1536 _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}''')
1537
1538 ## Constructor of TopLevelMakefile
1539 #
1540 # @param Workspace Object of WorkspaceAutoGen class
1541 #
1542 def __init__(self, Workspace):
1543 BuildFile.__init__(self, Workspace)
1544 self.IntermediateDirectoryList = []
1545 self.DependencyHeaderFileSet = set()
1546
1547 # Compose a dict object containing information used to do replacement in template
1548 @property
1549 def _TemplateDict(self):
1550 Separator = self._SEP_[self._FileType]
1551
1552 # any platform autogen object is ok because we just need common information
1553 MyAgo = self._AutoGenObject
1554
1555 if "MAKE" not in MyAgo.ToolDefinition or "PATH" not in MyAgo.ToolDefinition["MAKE"]:
1556 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
1557 ExtraData="[%s]" % str(MyAgo))
1558
1559 for Arch in MyAgo.ArchList:
1560 self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch]))
1561 self.IntermediateDirectoryList.append("$(FV_DIR)")
1562
1563 # TRICK: for not generating GenFds call in makefile if no FDF file
1564 MacroList = []
1565 if MyAgo.FdfFile is not None and MyAgo.FdfFile != "":
1566 FdfFileList = [MyAgo.FdfFile]
1567 # macros passed to GenFds
1568 MacroDict = {}
1569 MacroDict.update(GlobalData.gGlobalDefines)
1570 MacroDict.update(GlobalData.gCommandLineDefines)
1571 for MacroName in MacroDict:
1572 if MacroDict[MacroName] != "":
1573 MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))
1574 else:
1575 MacroList.append('"%s"' % MacroName)
1576 else:
1577 FdfFileList = []
1578
1579 # pass extra common options to external program called in makefile, currently GenFds.exe
1580 ExtraOption = ''
1581 LogLevel = EdkLogger.GetLevel()
1582 if LogLevel == EdkLogger.VERBOSE:
1583 ExtraOption += " -v"
1584 elif LogLevel <= EdkLogger.DEBUG_9:
1585 ExtraOption += " -d %d" % (LogLevel - 1)
1586 elif LogLevel == EdkLogger.QUIET:
1587 ExtraOption += " -q"
1588
1589 if GlobalData.gCaseInsensitive:
1590 ExtraOption += " -c"
1591 if not GlobalData.gEnableGenfdsMultiThread:
1592 ExtraOption += " --no-genfds-multi-thread"
1593 if GlobalData.gIgnoreSource:
1594 ExtraOption += " --ignore-sources"
1595
1596 for pcd in GlobalData.BuildOptionPcd:
1597 if pcd[2]:
1598 pcdname = '.'.join(pcd[0:3])
1599 else:
1600 pcdname = '.'.join(pcd[0:2])
1601 if pcd[3].startswith('{'):
1602 ExtraOption += " --pcd " + pcdname + '=' + 'H' + '"' + pcd[3] + '"'
1603 else:
1604 ExtraOption += " --pcd " + pcdname + '=' + pcd[3]
1605
1606 MakefileName = self._FILE_NAME_[self._FileType]
1607 SubBuildCommandList = []
1608 for A in MyAgo.ArchList:
1609 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)}
1610 SubBuildCommandList.append(Command)
1611
1612 MakefileTemplateDict = {
1613 "makefile_header" : self._FILE_HEADER_[self._FileType],
1614 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),
1615 "make_path" : MyAgo.ToolDefinition["MAKE"]["PATH"],
1616 "platform_name" : MyAgo.Name,
1617 "platform_guid" : MyAgo.Guid,
1618 "platform_version" : MyAgo.Version,
1619 "platform_build_directory" : MyAgo.BuildDir,
1620 "conf_directory" : GlobalData.gConfDirectory,
1621
1622 "toolchain_tag" : MyAgo.ToolChain,
1623 "build_target" : MyAgo.BuildTarget,
1624 "shell_command_code" : list(self._SHELL_CMD_[self._FileType].keys()),
1625 "shell_command" : list(self._SHELL_CMD_[self._FileType].values()),
1626 'arch' : list(MyAgo.ArchList),
1627 "build_architecture_list" : ','.join(MyAgo.ArchList),
1628 "separator" : Separator,
1629 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1630 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1631 "sub_build_command" : SubBuildCommandList,
1632 "fdf_file" : FdfFileList,
1633 "active_platform" : str(MyAgo),
1634 "fd" : MyAgo.FdTargetList,
1635 "fv" : MyAgo.FvTargetList,
1636 "cap" : MyAgo.CapTargetList,
1637 "extra_options" : ExtraOption,
1638 "macro" : MacroList,
1639 }
1640
1641 return MakefileTemplateDict
1642
1643 ## Get the root directory list for intermediate files of all modules build
1644 #
1645 # @retval list The list of directory
1646 #
1647 def GetModuleBuildDirectoryList(self):
1648 DirList = []
1649 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1650 if not ModuleAutoGen.IsBinaryModule:
1651 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1652 return DirList
1653
1654 ## Get the root directory list for intermediate files of all libraries build
1655 #
1656 # @retval list The list of directory
1657 #
1658 def GetLibraryBuildDirectoryList(self):
1659 DirList = []
1660 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1661 if not LibraryAutoGen.IsBinaryModule:
1662 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1663 return DirList
1664
1665 ## Find dependencies for one source file
1666 #
1667 # By searching recursively "#include" directive in file, find out all the
1668 # files needed by given source file. The dependencies will be only searched
1669 # in given search path list.
1670 #
1671 # @param File The source file
1672 # @param ForceInculeList The list of files which will be included forcely
1673 # @param SearchPathList The list of search path
1674 #
1675 # @retval list The list of files the given source file depends on
1676 #
1677 def GetDependencyList(AutoGenObject, FileCache, File, ForceList, SearchPathList):
1678 EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File)
1679 FileStack = [File] + ForceList
1680 DependencySet = set()
1681
1682 if AutoGenObject.Arch not in gDependencyDatabase:
1683 gDependencyDatabase[AutoGenObject.Arch] = {}
1684 DepDb = gDependencyDatabase[AutoGenObject.Arch]
1685
1686 while len(FileStack) > 0:
1687 F = FileStack.pop()
1688
1689 FullPathDependList = []
1690 if F in FileCache:
1691 for CacheFile in FileCache[F]:
1692 FullPathDependList.append(CacheFile)
1693 if CacheFile not in DependencySet:
1694 FileStack.append(CacheFile)
1695 DependencySet.update(FullPathDependList)
1696 continue
1697
1698 CurrentFileDependencyList = []
1699 if F in DepDb:
1700 CurrentFileDependencyList = DepDb[F]
1701 else:
1702 try:
1703 Fd = open(F.Path, 'rb')
1704 FileContent = Fd.read()
1705 Fd.close()
1706 except BaseException as X:
1707 EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path + "\n\t" + str(X))
1708 if len(FileContent) == 0:
1709 continue
1710 try:
1711 if FileContent[0] == 0xff or FileContent[0] == 0xfe:
1712 FileContent = FileContent.decode('utf-16')
1713 else:
1714 FileContent = FileContent.decode()
1715 except:
1716 # The file is not txt file. for example .mcb file
1717 continue
1718 IncludedFileList = gIncludePattern.findall(FileContent)
1719
1720 for Inc in IncludedFileList:
1721 Inc = Inc.strip()
1722 # if there's macro used to reference header file, expand it
1723 HeaderList = gMacroPattern.findall(Inc)
1724 if len(HeaderList) == 1 and len(HeaderList[0]) == 2:
1725 HeaderType = HeaderList[0][0]
1726 HeaderKey = HeaderList[0][1]
1727 if HeaderType in gIncludeMacroConversion:
1728 Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey}
1729 else:
1730 # not known macro used in #include, always build the file by
1731 # returning a empty dependency
1732 FileCache[File] = []
1733 return []
1734 Inc = os.path.normpath(Inc)
1735 CurrentFileDependencyList.append(Inc)
1736 DepDb[F] = CurrentFileDependencyList
1737
1738 CurrentFilePath = F.Dir
1739 PathList = [CurrentFilePath] + SearchPathList
1740 for Inc in CurrentFileDependencyList:
1741 for SearchPath in PathList:
1742 FilePath = os.path.join(SearchPath, Inc)
1743 if FilePath in gIsFileMap:
1744 if not gIsFileMap[FilePath]:
1745 continue
1746 # If isfile is called too many times, the performance is slow down.
1747 elif not os.path.isfile(FilePath):
1748 gIsFileMap[FilePath] = False
1749 continue
1750 else:
1751 gIsFileMap[FilePath] = True
1752 FilePath = PathClass(FilePath)
1753 FullPathDependList.append(FilePath)
1754 if FilePath not in DependencySet:
1755 FileStack.append(FilePath)
1756 break
1757 else:
1758 EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\
1759 "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList)))
1760
1761 FileCache[F] = FullPathDependList
1762 DependencySet.update(FullPathDependList)
1763
1764 DependencySet.update(ForceList)
1765 if File in DependencySet:
1766 DependencySet.remove(File)
1767 DependencyList = list(DependencySet) # remove duplicate ones
1768
1769 return DependencyList
1770
1771 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1772 if __name__ == '__main__':
1773 pass