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