BaseTools: Modify gcc 4.8 and 4.9 tool chain definition to support building from...
[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 - 2014, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
9 #
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 #
13
14 ## Import Modules
15 #
16 import Common.LongFilePathOs as os
17 import sys
18 import string
19 import re
20 import os.path as path
21 from Common.LongFilePathSupport import OpenLongFilePath as open
22
23 from Common.BuildToolError import *
24 from Common.Misc import *
25 from Common.String import *
26 from BuildEngine import *
27 import Common.GlobalData as GlobalData
28
29 ## Regular expression for finding header file inclusions
30 gIncludePattern = re.compile(r"^[ \t]*#?[ \t]*include(?:[ \t]*(?:\\(?:\r\n|\r|\n))*[ \t]*)*(?:\(?[\"<]?[ \t]*)([-\w.\\/() \t]+)(?:[ \t]*[\">]?\)?)", re.MULTILINE|re.UNICODE|re.IGNORECASE)
31
32 ## Regular expression for matching macro used in header file inclusion
33 gMacroPattern = re.compile("([_A-Z][_A-Z0-9]*)[ \t]*\((.+)\)", re.UNICODE)
34
35 gIsFileMap = {}
36
37 ## pattern for include style in Edk.x code
38 gProtocolDefinition = "Protocol/%(HeaderKey)s/%(HeaderKey)s.h"
39 gGuidDefinition = "Guid/%(HeaderKey)s/%(HeaderKey)s.h"
40 gArchProtocolDefinition = "ArchProtocol/%(HeaderKey)s/%(HeaderKey)s.h"
41 gPpiDefinition = "Ppi/%(HeaderKey)s/%(HeaderKey)s.h"
42 gIncludeMacroConversion = {
43 "EFI_PROTOCOL_DEFINITION" : gProtocolDefinition,
44 "EFI_GUID_DEFINITION" : gGuidDefinition,
45 "EFI_ARCH_PROTOCOL_DEFINITION" : gArchProtocolDefinition,
46 "EFI_PROTOCOL_PRODUCER" : gProtocolDefinition,
47 "EFI_PROTOCOL_CONSUMER" : gProtocolDefinition,
48 "EFI_PROTOCOL_DEPENDENCY" : gProtocolDefinition,
49 "EFI_ARCH_PROTOCOL_PRODUCER" : gArchProtocolDefinition,
50 "EFI_ARCH_PROTOCOL_CONSUMER" : gArchProtocolDefinition,
51 "EFI_ARCH_PROTOCOL_DEPENDENCY" : gArchProtocolDefinition,
52 "EFI_PPI_DEFINITION" : gPpiDefinition,
53 "EFI_PPI_PRODUCER" : gPpiDefinition,
54 "EFI_PPI_CONSUMER" : gPpiDefinition,
55 "EFI_PPI_DEPENDENCY" : gPpiDefinition,
56 }
57
58 ## default makefile type
59 gMakeType = ""
60 if sys.platform == "win32":
61 gMakeType = "nmake"
62 else:
63 gMakeType = "gmake"
64
65
66 ## BuildFile class
67 #
68 # This base class encapsules build file and its generation. It uses template to generate
69 # the content of build file. The content of build file will be got from AutoGen objects.
70 #
71 class BuildFile(object):
72 ## template used to generate the build file (i.e. makefile if using make)
73 _TEMPLATE_ = TemplateString('')
74
75 _DEFAULT_FILE_NAME_ = "Makefile"
76
77 ## default file name for each type of build file
78 _FILE_NAME_ = {
79 "nmake" : "Makefile",
80 "gmake" : "GNUmakefile"
81 }
82
83 ## Fixed header string for makefile
84 _MAKEFILE_HEADER = '''#
85 # DO NOT EDIT
86 # This file is auto-generated by build utility
87 #
88 # Module Name:
89 #
90 # %s
91 #
92 # Abstract:
93 #
94 # Auto-generated makefile for building modules, libraries or platform
95 #
96 '''
97
98 ## Header string for each type of build file
99 _FILE_HEADER_ = {
100 "nmake" : _MAKEFILE_HEADER % _FILE_NAME_["nmake"],
101 "gmake" : _MAKEFILE_HEADER % _FILE_NAME_["gmake"]
102 }
103
104 ## shell commands which can be used in build file in the form of macro
105 # $(CP) copy file command
106 # $(MV) move file command
107 # $(RM) remove file command
108 # $(MD) create dir command
109 # $(RD) remove dir command
110 #
111 _SHELL_CMD_ = {
112 "nmake" : {
113 "CP" : "copy /y",
114 "MV" : "move /y",
115 "RM" : "del /f /q",
116 "MD" : "mkdir",
117 "RD" : "rmdir /s /q",
118 },
119
120 "gmake" : {
121 "CP" : "cp -f",
122 "MV" : "mv -f",
123 "RM" : "rm -f",
124 "MD" : "mkdir -p",
125 "RD" : "rm -r -f",
126 }
127 }
128
129 ## directory separator
130 _SEP_ = {
131 "nmake" : "\\",
132 "gmake" : "/"
133 }
134
135 ## directory creation template
136 _MD_TEMPLATE_ = {
137 "nmake" : 'if not exist %(dir)s $(MD) %(dir)s',
138 "gmake" : "$(MD) %(dir)s"
139 }
140
141 ## directory removal template
142 _RD_TEMPLATE_ = {
143 "nmake" : 'if exist %(dir)s $(RD) %(dir)s',
144 "gmake" : "$(RD) %(dir)s"
145 }
146
147 _CD_TEMPLATE_ = {
148 "nmake" : 'if exist %(dir)s cd %(dir)s',
149 "gmake" : "test -e %(dir)s && cd %(dir)s"
150 }
151
152 _MAKE_TEMPLATE_ = {
153 "nmake" : 'if exist %(file)s "$(MAKE)" $(MAKE_FLAGS) -f %(file)s',
154 "gmake" : 'test -e %(file)s && "$(MAKE)" $(MAKE_FLAGS) -f %(file)s'
155 }
156
157 _INCLUDE_CMD_ = {
158 "nmake" : '!INCLUDE',
159 "gmake" : "include"
160 }
161
162 _INC_FLAG_ = {"MSFT" : "/I", "GCC" : "-I", "INTEL" : "-I", "RVCT" : "-I"}
163
164 ## Constructor of BuildFile
165 #
166 # @param AutoGenObject Object of AutoGen class
167 #
168 def __init__(self, AutoGenObject):
169 self._AutoGenObject = AutoGenObject
170 self._FileType = gMakeType
171
172 ## Create build file
173 #
174 # @param FileType Type of build file. Only nmake and gmake are supported now.
175 #
176 # @retval TRUE The build file is created or re-created successfully
177 # @retval FALSE The build file exists and is the same as the one to be generated
178 #
179 def Generate(self, FileType=gMakeType):
180 if FileType not in self._FILE_NAME_:
181 EdkLogger.error("build", PARAMETER_INVALID, "Invalid build type [%s]" % FileType,
182 ExtraData="[%s]" % str(self._AutoGenObject))
183 self._FileType = FileType
184 FileContent = self._TEMPLATE_.Replace(self._TemplateDict)
185 FileName = self._FILE_NAME_[FileType]
186 return SaveFileOnChange(os.path.join(self._AutoGenObject.MakeFileDir, FileName), FileContent, False)
187
188 ## Return a list of directory creation command string
189 #
190 # @param DirList The list of directory to be created
191 #
192 # @retval list The directory creation command list
193 #
194 def GetCreateDirectoryCommand(self, DirList):
195 return [self._MD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
196
197 ## Return a list of directory removal command string
198 #
199 # @param DirList The list of directory to be removed
200 #
201 # @retval list The directory removal command list
202 #
203 def GetRemoveDirectoryCommand(self, DirList):
204 return [self._RD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
205
206 def PlaceMacro(self, Path, MacroDefinitions={}):
207 if Path.startswith("$("):
208 return Path
209 else:
210 PathLength = len(Path)
211 for MacroName in MacroDefinitions:
212 MacroValue = MacroDefinitions[MacroName]
213 MacroValueLength = len(MacroValue)
214 if MacroValueLength <= PathLength and Path.startswith(MacroValue):
215 Path = "$(%s)%s" % (MacroName, Path[MacroValueLength:])
216 break
217 return Path
218
219 ## ModuleMakefile class
220 #
221 # This class encapsules makefie and its generation for module. It uses template to generate
222 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
223 #
224 class ModuleMakefile(BuildFile):
225 ## template used to generate the makefile for module
226 _TEMPLATE_ = TemplateString('''\
227 ${makefile_header}
228
229 #
230 # Platform Macro Definition
231 #
232 PLATFORM_NAME = ${platform_name}
233 PLATFORM_GUID = ${platform_guid}
234 PLATFORM_VERSION = ${platform_version}
235 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
236 PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}
237 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
238
239 #
240 # Module Macro Definition
241 #
242 MODULE_NAME = ${module_name}
243 MODULE_GUID = ${module_guid}
244 MODULE_VERSION = ${module_version}
245 MODULE_TYPE = ${module_type}
246 MODULE_FILE = ${module_file}
247 MODULE_FILE_BASE_NAME = ${module_file_base_name}
248 BASE_NAME = $(MODULE_NAME)
249 MODULE_RELATIVE_DIR = ${module_relative_directory}
250 PACKAGE_RELATIVE_DIR = ${package_relative_directory}
251 MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory}
252
253 MODULE_ENTRY_POINT = ${module_entry_point}
254 ARCH_ENTRY_POINT = ${arch_entry_point}
255 IMAGE_ENTRY_POINT = ${image_entry_point}
256
257 ${BEGIN}${module_extra_defines}
258 ${END}
259 #
260 # Build Configuration Macro Definition
261 #
262 ARCH = ${architecture}
263 TOOLCHAIN = ${toolchain_tag}
264 TOOLCHAIN_TAG = ${toolchain_tag}
265 TARGET = ${build_target}
266
267 #
268 # Build Directory Macro Definition
269 #
270 # PLATFORM_BUILD_DIR = ${platform_build_directory}
271 BUILD_DIR = ${platform_build_directory}
272 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
273 LIB_DIR = $(BIN_DIR)
274 MODULE_BUILD_DIR = ${module_build_directory}
275 OUTPUT_DIR = ${module_output_directory}
276 DEBUG_DIR = ${module_debug_directory}
277 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
278 DEST_DIR_DEBUG = $(DEBUG_DIR)
279
280 #
281 # Shell Command Macro
282 #
283 ${BEGIN}${shell_command_code} = ${shell_command}
284 ${END}
285
286 #
287 # Tools definitions specific to this module
288 #
289 ${BEGIN}${module_tool_definitions}
290 ${END}
291 MAKE_FILE = ${makefile_path}
292
293 #
294 # Build Macro
295 #
296 ${BEGIN}${file_macro}
297 ${END}
298
299 COMMON_DEPS = ${BEGIN}${common_dependency_file} \\
300 ${END}
301
302 #
303 # Overridable Target Macro Definitions
304 #
305 FORCE_REBUILD = force_build
306 INIT_TARGET = init
307 PCH_TARGET =
308 BC_TARGET = ${BEGIN}${backward_compatible_target} ${END}
309 CODA_TARGET = ${BEGIN}${remaining_build_target} \\
310 ${END}
311
312 #
313 # Default target, which will build dependent libraries in addition to source files
314 #
315
316 all: mbuild
317
318
319 #
320 # Target used when called from platform makefile, which will bypass the build of dependent libraries
321 #
322
323 pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
324
325 #
326 # ModuleTarget
327 #
328
329 mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET)
330
331 #
332 # Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets
333 #
334
335 tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
336
337 #
338 # Phony target which is used to force executing commands for a target
339 #
340 force_build:
341 \t-@
342
343 #
344 # Target to update the FD
345 #
346
347 fds: mbuild gen_fds
348
349 #
350 # Initialization target: print build information and create necessary directories
351 #
352 init: info dirs
353
354 info:
355 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
356
357 dirs:
358 ${BEGIN}\t-@${create_directory_command}\n${END}
359
360 strdefs:
361 \t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h
362
363 #
364 # GenLibsTarget
365 #
366 gen_libs:
367 \t${BEGIN}@"$(MAKE)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name}
368 \t${END}@cd $(MODULE_BUILD_DIR)
369
370 #
371 # Build Flash Device Image
372 #
373 gen_fds:
374 \t@"$(MAKE)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds
375 \t@cd $(MODULE_BUILD_DIR)
376
377 #
378 # Individual Object Build Targets
379 #
380 ${BEGIN}${file_build_target}
381 ${END}
382
383 #
384 # clean all intermediate files
385 #
386 clean:
387 \t${BEGIN}${clean_command}
388 \t${END}
389
390 #
391 # clean all generated files
392 #
393 cleanall:
394 ${BEGIN}\t${cleanall_command}
395 ${END}\t$(RM) *.pdb *.idb > NUL 2>&1
396 \t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi
397
398 #
399 # clean all dependent libraries built
400 #
401 cleanlib:
402 \t${BEGIN}-@${library_build_command} cleanall
403 \t${END}@cd $(MODULE_BUILD_DIR)\n\n''')
404
405 _FILE_MACRO_TEMPLATE = TemplateString("${macro_name} = ${BEGIN} \\\n ${source_file}${END}\n")
406 _BUILD_TARGET_TEMPLATE = TemplateString("${BEGIN}${target} : ${deps}\n${END}\t${cmd}\n")
407
408 ## Constructor of ModuleMakefile
409 #
410 # @param ModuleAutoGen Object of ModuleAutoGen class
411 #
412 def __init__(self, ModuleAutoGen):
413 BuildFile.__init__(self, ModuleAutoGen)
414 self.PlatformInfo = self._AutoGenObject.PlatformInfo
415
416 self.ResultFileList = []
417 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
418
419 self.SourceFileDatabase = {} # {file type : file path}
420 self.DestFileDatabase = {} # {file type : file path}
421 self.FileBuildTargetList = [] # [(src, target string)]
422 self.BuildTargetList = [] # [target string]
423 self.PendingBuildTargetList = [] # [FileBuildRule objects]
424 self.CommonFileDependency = []
425 self.FileListMacros = {}
426 self.ListFileMacros = {}
427
428 self.FileCache = {}
429 self.FileDependency = []
430 self.LibraryBuildCommandList = []
431 self.LibraryFileList = []
432 self.LibraryMakefileList = []
433 self.LibraryBuildDirectoryList = []
434 self.SystemLibraryList = []
435 self.Macros = sdict()
436 self.Macros["OUTPUT_DIR" ] = self._AutoGenObject.Macros["OUTPUT_DIR"]
437 self.Macros["DEBUG_DIR" ] = self._AutoGenObject.Macros["DEBUG_DIR"]
438 self.Macros["MODULE_BUILD_DIR"] = self._AutoGenObject.Macros["MODULE_BUILD_DIR"]
439 self.Macros["BIN_DIR" ] = self._AutoGenObject.Macros["BIN_DIR"]
440 self.Macros["BUILD_DIR" ] = self._AutoGenObject.Macros["BUILD_DIR"]
441 self.Macros["WORKSPACE" ] = self._AutoGenObject.Macros["WORKSPACE"]
442
443 # Compose a dict object containing information used to do replacement in template
444 def _CreateTemplateDict(self):
445 if self._FileType not in self._SEP_:
446 EdkLogger.error("build", PARAMETER_INVALID, "Invalid Makefile type [%s]" % self._FileType,
447 ExtraData="[%s]" % str(self._AutoGenObject))
448 Separator = self._SEP_[self._FileType]
449
450 # break build if no source files and binary files are found
451 if len(self._AutoGenObject.SourceFileList) == 0 and len(self._AutoGenObject.BinaryFileList) == 0:
452 EdkLogger.error("build", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]"
453 % (self._AutoGenObject.BuildTarget, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch),
454 ExtraData="[%s]" % str(self._AutoGenObject))
455
456 # convert dependent libraries to build command
457 self.ProcessDependentLibrary()
458 if len(self._AutoGenObject.Module.ModuleEntryPointList) > 0:
459 ModuleEntryPoint = self._AutoGenObject.Module.ModuleEntryPointList[0]
460 else:
461 ModuleEntryPoint = "_ModuleEntryPoint"
462
463 # Intel EBC compiler enforces EfiMain
464 if self._AutoGenObject.AutoGenVersion < 0x00010005 and self._AutoGenObject.Arch == "EBC":
465 ArchEntryPoint = "EfiMain"
466 else:
467 ArchEntryPoint = ModuleEntryPoint
468
469 if self._AutoGenObject.Arch == "EBC":
470 # EBC compiler always use "EfiStart" as entry point. Only applies to EdkII modules
471 ImageEntryPoint = "EfiStart"
472 elif self._AutoGenObject.AutoGenVersion < 0x00010005:
473 # Edk modules use entry point specified in INF file
474 ImageEntryPoint = ModuleEntryPoint
475 else:
476 # EdkII modules always use "_ModuleEntryPoint" as entry point
477 ImageEntryPoint = "_ModuleEntryPoint"
478
479 # tools definitions
480 ToolsDef = []
481 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
482 for Tool in self._AutoGenObject.BuildOption:
483 for Attr in self._AutoGenObject.BuildOption[Tool]:
484 Value = self._AutoGenObject.BuildOption[Tool][Attr]
485 if Attr == "FAMILY":
486 continue
487 elif Attr == "PATH":
488 ToolsDef.append("%s = %s" % (Tool, Value))
489 else:
490 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
491 if Tool == "MAKE":
492 continue
493 # Remove duplicated include path, if any
494 if Attr == "FLAGS":
495 Value = RemoveDupOption(Value, IncPrefix, self._AutoGenObject.IncludePathList)
496 ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
497 ToolsDef.append("")
498
499 # convert source files and binary files to build targets
500 self.ResultFileList = [str(T.Target) for T in self._AutoGenObject.CodaTargetList]
501 if len(self.ResultFileList) == 0 and len(self._AutoGenObject.SourceFileList) <> 0:
502 EdkLogger.error("build", AUTOGEN_ERROR, "Nothing to build",
503 ExtraData="[%s]" % str(self._AutoGenObject))
504
505 self.ProcessBuildTargetList()
506
507 # Generate macros used to represent input files
508 FileMacroList = [] # macro name = file list
509 for FileListMacro in self.FileListMacros:
510 FileMacro = self._FILE_MACRO_TEMPLATE.Replace(
511 {
512 "macro_name" : FileListMacro,
513 "source_file" : self.FileListMacros[FileListMacro]
514 }
515 )
516 FileMacroList.append(FileMacro)
517
518 # INC_LIST is special
519 FileMacro = ""
520 IncludePathList = []
521 for P in self._AutoGenObject.IncludePathList:
522 IncludePathList.append(IncPrefix+self.PlaceMacro(P, self.Macros))
523 if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:
524 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix+P)
525 FileMacro += self._FILE_MACRO_TEMPLATE.Replace(
526 {
527 "macro_name" : "INC",
528 "source_file" : IncludePathList
529 }
530 )
531 FileMacroList.append(FileMacro)
532
533 # Generate macros used to represent files containing list of input files
534 for ListFileMacro in self.ListFileMacros:
535 ListFileName = os.path.join(self._AutoGenObject.OutputDir, "%s.lst" % ListFileMacro.lower()[:len(ListFileMacro)-5])
536 FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))
537 SaveFileOnChange(
538 ListFileName,
539 "\n".join(self.ListFileMacros[ListFileMacro]),
540 False
541 )
542
543 # Edk modules need <BaseName>StrDefs.h for string ID
544 #if self._AutoGenObject.AutoGenVersion < 0x00010005 and len(self._AutoGenObject.UnicodeFileList) > 0:
545 # BcTargetList = ['strdefs']
546 #else:
547 # BcTargetList = []
548 BcTargetList = []
549
550 MakefileName = self._FILE_NAME_[self._FileType]
551 LibraryMakeCommandList = []
552 for D in self.LibraryBuildDirectoryList:
553 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)}
554 LibraryMakeCommandList.append(Command)
555
556 package_rel_dir = self._AutoGenObject.SourceDir
557 if os.sep in package_rel_dir:
558 package_rel_dir = package_rel_dir[package_rel_dir.index(os.sep) + 1:]
559
560 MakefileTemplateDict = {
561 "makefile_header" : self._FILE_HEADER_[self._FileType],
562 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
563 "makefile_name" : MakefileName,
564 "platform_name" : self.PlatformInfo.Name,
565 "platform_guid" : self.PlatformInfo.Guid,
566 "platform_version" : self.PlatformInfo.Version,
567 "platform_relative_directory": self.PlatformInfo.SourceDir,
568 "platform_output_directory" : self.PlatformInfo.OutputDir,
569
570 "module_name" : self._AutoGenObject.Name,
571 "module_guid" : self._AutoGenObject.Guid,
572 "module_version" : self._AutoGenObject.Version,
573 "module_type" : self._AutoGenObject.ModuleType,
574 "module_file" : self._AutoGenObject.MetaFile.Name,
575 "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName,
576 "module_relative_directory" : self._AutoGenObject.SourceDir,
577 "package_relative_directory": package_rel_dir,
578 "module_extra_defines" : ["%s = %s" % (k, v) for k, v in self._AutoGenObject.Module.Defines.iteritems()],
579
580 "architecture" : self._AutoGenObject.Arch,
581 "toolchain_tag" : self._AutoGenObject.ToolChain,
582 "build_target" : self._AutoGenObject.BuildTarget,
583
584 "platform_build_directory" : self.PlatformInfo.BuildDir,
585 "module_build_directory" : self._AutoGenObject.BuildDir,
586 "module_output_directory" : self._AutoGenObject.OutputDir,
587 "module_debug_directory" : self._AutoGenObject.DebugDir,
588
589 "separator" : Separator,
590 "module_tool_definitions" : ToolsDef,
591
592 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),
593 "shell_command" : self._SHELL_CMD_[self._FileType].values(),
594
595 "module_entry_point" : ModuleEntryPoint,
596 "image_entry_point" : ImageEntryPoint,
597 "arch_entry_point" : ArchEntryPoint,
598 "remaining_build_target" : self.ResultFileList,
599 "common_dependency_file" : self.CommonFileDependency,
600 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
601 "clean_command" : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]),
602 "cleanall_command" : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]),
603 "dependent_library_build_directory" : self.LibraryBuildDirectoryList,
604 "library_build_command" : LibraryMakeCommandList,
605 "file_macro" : FileMacroList,
606 "file_build_target" : self.BuildTargetList,
607 "backward_compatible_target": BcTargetList,
608 }
609
610 return MakefileTemplateDict
611
612 def ProcessBuildTargetList(self):
613 #
614 # Search dependency file list for each source file
615 #
616 ForceIncludedFile = []
617 for File in self._AutoGenObject.AutoGenFileList:
618 if File.Ext == '.h':
619 ForceIncludedFile.append(File)
620 SourceFileList = []
621 for Target in self._AutoGenObject.IntroTargetList:
622 SourceFileList.extend(Target.Inputs)
623
624 self.FileDependency = self.GetFileDependency(
625 SourceFileList,
626 ForceIncludedFile,
627 self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList
628 )
629 DepSet = None
630 for File in self.FileDependency:
631 if not self.FileDependency[File]:
632 self.FileDependency[File] = ['$(FORCE_REBUILD)']
633 continue
634 # skip non-C files
635 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
636 continue
637 elif DepSet == None:
638 DepSet = set(self.FileDependency[File])
639 else:
640 DepSet &= set(self.FileDependency[File])
641 # in case nothing in SourceFileList
642 if DepSet == None:
643 DepSet = set()
644 #
645 # Extract common files list in the dependency files
646 #
647 for File in DepSet:
648 self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros))
649
650 for File in self.FileDependency:
651 # skip non-C files
652 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
653 continue
654 NewDepSet = set(self.FileDependency[File])
655 NewDepSet -= DepSet
656 self.FileDependency[File] = ["$(COMMON_DEPS)"] + list(NewDepSet)
657
658 # Convert target description object to target string in makefile
659 for Type in self._AutoGenObject.Targets:
660 for T in self._AutoGenObject.Targets[Type]:
661 # Generate related macros if needed
662 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
663 self.FileListMacros[T.FileListMacro] = []
664 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:
665 self.ListFileMacros[T.ListFileMacro] = []
666 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:
667 self.ListFileMacros[T.IncListFileMacro] = []
668
669 Deps = []
670 # Add force-dependencies
671 for Dep in T.Dependencies:
672 Deps.append(self.PlaceMacro(str(Dep), self.Macros))
673 # Add inclusion-dependencies
674 if len(T.Inputs) == 1 and T.Inputs[0] in self.FileDependency:
675 for F in self.FileDependency[T.Inputs[0]]:
676 Deps.append(self.PlaceMacro(str(F), self.Macros))
677 # Add source-dependencies
678 for F in T.Inputs:
679 NewFile = self.PlaceMacro(str(F), self.Macros)
680 # In order to use file list macro as dependency
681 if T.GenListFile:
682 # gnu tools need forward slash path separater, even on Windows
683 self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/'))
684 self.FileListMacros[T.FileListMacro].append(NewFile)
685 elif T.GenFileListMacro:
686 self.FileListMacros[T.FileListMacro].append(NewFile)
687 else:
688 Deps.append(NewFile)
689
690 # Use file list macro as dependency
691 if T.GenFileListMacro:
692 Deps.append("$(%s)" % T.FileListMacro)
693
694 TargetDict = {
695 "target" : self.PlaceMacro(T.Target.Path, self.Macros),
696 "cmd" : "\n\t".join(T.Commands),
697 "deps" : Deps
698 }
699 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
700
701 ## For creating makefile targets for dependent libraries
702 def ProcessDependentLibrary(self):
703 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
704 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
705
706 ## Return a list containing source file's dependencies
707 #
708 # @param FileList The list of source files
709 # @param ForceInculeList The list of files which will be included forcely
710 # @param SearchPathList The list of search path
711 #
712 # @retval dict The mapping between source file path and its dependencies
713 #
714 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
715 Dependency = {}
716 for F in FileList:
717 Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)
718 return Dependency
719
720 ## Find dependencies for one source file
721 #
722 # By searching recursively "#include" directive in file, find out all the
723 # files needed by given source file. The dependecies will be only searched
724 # in given search path list.
725 #
726 # @param File The source file
727 # @param ForceInculeList The list of files which will be included forcely
728 # @param SearchPathList The list of search path
729 #
730 # @retval list The list of files the given source file depends on
731 #
732 def GetDependencyList(self, File, ForceList, SearchPathList):
733 EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File)
734 FileStack = [File] + ForceList
735 DependencySet = set()
736
737 if self._AutoGenObject.Arch not in gDependencyDatabase:
738 gDependencyDatabase[self._AutoGenObject.Arch] = {}
739 DepDb = gDependencyDatabase[self._AutoGenObject.Arch]
740
741 while len(FileStack) > 0:
742 F = FileStack.pop()
743
744 FullPathDependList = []
745 if F in self.FileCache:
746 for CacheFile in self.FileCache[F]:
747 FullPathDependList.append(CacheFile)
748 if CacheFile not in DependencySet:
749 FileStack.append(CacheFile)
750 DependencySet.update(FullPathDependList)
751 continue
752
753 CurrentFileDependencyList = []
754 if F in DepDb:
755 CurrentFileDependencyList = DepDb[F]
756 else:
757 try:
758 Fd = open(F.Path, 'r')
759 except BaseException, X:
760 EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path+"\n\t"+str(X))
761
762 FileContent = Fd.read()
763 Fd.close()
764 if len(FileContent) == 0:
765 continue
766
767 if FileContent[0] == 0xff or FileContent[0] == 0xfe:
768 FileContent = unicode(FileContent, "utf-16")
769 IncludedFileList = gIncludePattern.findall(FileContent)
770
771 for Inc in IncludedFileList:
772 Inc = Inc.strip()
773 # if there's macro used to reference header file, expand it
774 HeaderList = gMacroPattern.findall(Inc)
775 if len(HeaderList) == 1 and len(HeaderList[0]) == 2:
776 HeaderType = HeaderList[0][0]
777 HeaderKey = HeaderList[0][1]
778 if HeaderType in gIncludeMacroConversion:
779 Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey}
780 else:
781 # not known macro used in #include, always build the file by
782 # returning a empty dependency
783 self.FileCache[File] = []
784 return []
785 Inc = os.path.normpath(Inc)
786 CurrentFileDependencyList.append(Inc)
787 DepDb[F] = CurrentFileDependencyList
788
789 CurrentFilePath = F.Dir
790 PathList = [CurrentFilePath] + SearchPathList
791 for Inc in CurrentFileDependencyList:
792 for SearchPath in PathList:
793 FilePath = os.path.join(SearchPath, Inc)
794 if FilePath in gIsFileMap:
795 if not gIsFileMap[FilePath]:
796 continue
797 # If isfile is called too many times, the performance is slow down.
798 elif not os.path.isfile(FilePath):
799 gIsFileMap[FilePath] = False
800 continue
801 else:
802 gIsFileMap[FilePath] = True
803 FilePath = PathClass(FilePath)
804 FullPathDependList.append(FilePath)
805 if FilePath not in DependencySet:
806 FileStack.append(FilePath)
807 break
808 else:
809 EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\
810 "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList)))
811
812 self.FileCache[F] = FullPathDependList
813 DependencySet.update(FullPathDependList)
814
815 DependencySet.update(ForceList)
816 if File in DependencySet:
817 DependencySet.remove(File)
818 DependencyList = list(DependencySet) # remove duplicate ones
819
820 return DependencyList
821
822 _TemplateDict = property(_CreateTemplateDict)
823
824 ## CustomMakefile class
825 #
826 # This class encapsules makefie and its generation for module. It uses template to generate
827 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
828 #
829 class CustomMakefile(BuildFile):
830 ## template used to generate the makefile for module with custom makefile
831 _TEMPLATE_ = TemplateString('''\
832 ${makefile_header}
833
834 #
835 # Platform Macro Definition
836 #
837 PLATFORM_NAME = ${platform_name}
838 PLATFORM_GUID = ${platform_guid}
839 PLATFORM_VERSION = ${platform_version}
840 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
841 PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}
842 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
843
844 #
845 # Module Macro Definition
846 #
847 MODULE_NAME = ${module_name}
848 MODULE_GUID = ${module_guid}
849 MODULE_VERSION = ${module_version}
850 MODULE_TYPE = ${module_type}
851 MODULE_FILE = ${module_file}
852 MODULE_FILE_BASE_NAME = ${module_file_base_name}
853 BASE_NAME = $(MODULE_NAME)
854 MODULE_RELATIVE_DIR = ${module_relative_directory}
855 MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory}
856
857 #
858 # Build Configuration Macro Definition
859 #
860 ARCH = ${architecture}
861 TOOLCHAIN = ${toolchain_tag}
862 TOOLCHAIN_TAG = ${toolchain_tag}
863 TARGET = ${build_target}
864
865 #
866 # Build Directory Macro Definition
867 #
868 # PLATFORM_BUILD_DIR = ${platform_build_directory}
869 BUILD_DIR = ${platform_build_directory}
870 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
871 LIB_DIR = $(BIN_DIR)
872 MODULE_BUILD_DIR = ${module_build_directory}
873 OUTPUT_DIR = ${module_output_directory}
874 DEBUG_DIR = ${module_debug_directory}
875 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
876 DEST_DIR_DEBUG = $(DEBUG_DIR)
877
878 #
879 # Tools definitions specific to this module
880 #
881 ${BEGIN}${module_tool_definitions}
882 ${END}
883 MAKE_FILE = ${makefile_path}
884
885 #
886 # Shell Command Macro
887 #
888 ${BEGIN}${shell_command_code} = ${shell_command}
889 ${END}
890
891 ${custom_makefile_content}
892
893 #
894 # Target used when called from platform makefile, which will bypass the build of dependent libraries
895 #
896
897 pbuild: init all
898
899
900 #
901 # ModuleTarget
902 #
903
904 mbuild: init all
905
906 #
907 # Build Target used in multi-thread build mode, which no init target is needed
908 #
909
910 tbuild: all
911
912 #
913 # Initialization target: print build information and create necessary directories
914 #
915 init:
916 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
917 ${BEGIN}\t-@${create_directory_command}\n${END}\
918
919 ''')
920
921 ## Constructor of CustomMakefile
922 #
923 # @param ModuleAutoGen Object of ModuleAutoGen class
924 #
925 def __init__(self, ModuleAutoGen):
926 BuildFile.__init__(self, ModuleAutoGen)
927 self.PlatformInfo = self._AutoGenObject.PlatformInfo
928 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
929
930 # Compose a dict object containing information used to do replacement in template
931 def _CreateTemplateDict(self):
932 Separator = self._SEP_[self._FileType]
933 if self._FileType not in self._AutoGenObject.CustomMakefile:
934 EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType,
935 ExtraData="[%s]" % str(self._AutoGenObject))
936 MakefilePath = os.path.join(
937 self._AutoGenObject.WorkspaceDir,
938 self._AutoGenObject.CustomMakefile[self._FileType]
939 )
940 try:
941 CustomMakefile = open(MakefilePath, 'r').read()
942 except:
943 EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(self._AutoGenObject),
944 ExtraData=self._AutoGenObject.CustomMakefile[self._FileType])
945
946 # tools definitions
947 ToolsDef = []
948 for Tool in self._AutoGenObject.BuildOption:
949 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
950 if Tool == "MAKE":
951 continue
952 for Attr in self._AutoGenObject.BuildOption[Tool]:
953 if Attr == "FAMILY":
954 continue
955 elif Attr == "PATH":
956 ToolsDef.append("%s = %s" % (Tool, self._AutoGenObject.BuildOption[Tool][Attr]))
957 else:
958 ToolsDef.append("%s_%s = %s" % (Tool, Attr, self._AutoGenObject.BuildOption[Tool][Attr]))
959 ToolsDef.append("")
960
961 MakefileName = self._FILE_NAME_[self._FileType]
962 MakefileTemplateDict = {
963 "makefile_header" : self._FILE_HEADER_[self._FileType],
964 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
965 "platform_name" : self.PlatformInfo.Name,
966 "platform_guid" : self.PlatformInfo.Guid,
967 "platform_version" : self.PlatformInfo.Version,
968 "platform_relative_directory": self.PlatformInfo.SourceDir,
969 "platform_output_directory" : self.PlatformInfo.OutputDir,
970
971 "module_name" : self._AutoGenObject.Name,
972 "module_guid" : self._AutoGenObject.Guid,
973 "module_version" : self._AutoGenObject.Version,
974 "module_type" : self._AutoGenObject.ModuleType,
975 "module_file" : self._AutoGenObject.MetaFile,
976 "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName,
977 "module_relative_directory" : self._AutoGenObject.SourceDir,
978
979 "architecture" : self._AutoGenObject.Arch,
980 "toolchain_tag" : self._AutoGenObject.ToolChain,
981 "build_target" : self._AutoGenObject.BuildTarget,
982
983 "platform_build_directory" : self.PlatformInfo.BuildDir,
984 "module_build_directory" : self._AutoGenObject.BuildDir,
985 "module_output_directory" : self._AutoGenObject.OutputDir,
986 "module_debug_directory" : self._AutoGenObject.DebugDir,
987
988 "separator" : Separator,
989 "module_tool_definitions" : ToolsDef,
990
991 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),
992 "shell_command" : self._SHELL_CMD_[self._FileType].values(),
993
994 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
995 "custom_makefile_content" : CustomMakefile
996 }
997
998 return MakefileTemplateDict
999
1000 _TemplateDict = property(_CreateTemplateDict)
1001
1002 ## PlatformMakefile class
1003 #
1004 # This class encapsules makefie and its generation for platform. It uses
1005 # template to generate the content of makefile. The content of makefile will be
1006 # got from PlatformAutoGen object.
1007 #
1008 class PlatformMakefile(BuildFile):
1009 ## template used to generate the makefile for platform
1010 _TEMPLATE_ = TemplateString('''\
1011 ${makefile_header}
1012
1013 #
1014 # Platform Macro Definition
1015 #
1016 PLATFORM_NAME = ${platform_name}
1017 PLATFORM_GUID = ${platform_guid}
1018 PLATFORM_VERSION = ${platform_version}
1019 PLATFORM_FILE = ${platform_file}
1020 PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}
1021 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1022
1023 #
1024 # Build Configuration Macro Definition
1025 #
1026 TOOLCHAIN = ${toolchain_tag}
1027 TOOLCHAIN_TAG = ${toolchain_tag}
1028 TARGET = ${build_target}
1029
1030 #
1031 # Build Directory Macro Definition
1032 #
1033 BUILD_DIR = ${platform_build_directory}
1034 FV_DIR = ${platform_build_directory}${separator}FV
1035
1036 #
1037 # Shell Command Macro
1038 #
1039 ${BEGIN}${shell_command_code} = ${shell_command}
1040 ${END}
1041
1042 MAKE = ${make_path}
1043 MAKE_FILE = ${makefile_path}
1044
1045 #
1046 # Default target
1047 #
1048 all: init build_libraries build_modules
1049
1050 #
1051 # Initialization target: print build information and create necessary directories
1052 #
1053 init:
1054 \t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
1055 \t${BEGIN}-@${create_directory_command}
1056 \t${END}
1057 #
1058 # library build target
1059 #
1060 libraries: init build_libraries
1061
1062 #
1063 # module build target
1064 #
1065 modules: init build_libraries build_modules
1066
1067 #
1068 # Build all libraries:
1069 #
1070 build_libraries:
1071 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
1072 ${END}\t@cd $(BUILD_DIR)
1073
1074 #
1075 # Build all modules:
1076 #
1077 build_modules:
1078 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
1079 ${END}\t@cd $(BUILD_DIR)
1080
1081 #
1082 # Clean intermediate files
1083 #
1084 clean:
1085 \t${BEGIN}-@${library_build_command} clean
1086 \t${END}${BEGIN}-@${module_build_command} clean
1087 \t${END}@cd $(BUILD_DIR)
1088
1089 #
1090 # Clean all generated files except to makefile
1091 #
1092 cleanall:
1093 ${BEGIN}\t${cleanall_command}
1094 ${END}
1095
1096 #
1097 # Clean all library files
1098 #
1099 cleanlib:
1100 \t${BEGIN}-@${library_build_command} cleanall
1101 \t${END}@cd $(BUILD_DIR)\n
1102 ''')
1103
1104 ## Constructor of PlatformMakefile
1105 #
1106 # @param ModuleAutoGen Object of PlatformAutoGen class
1107 #
1108 def __init__(self, PlatformAutoGen):
1109 BuildFile.__init__(self, PlatformAutoGen)
1110 self.ModuleBuildCommandList = []
1111 self.ModuleMakefileList = []
1112 self.IntermediateDirectoryList = []
1113 self.ModuleBuildDirectoryList = []
1114 self.LibraryBuildDirectoryList = []
1115 self.LibraryMakeCommandList = []
1116
1117 # Compose a dict object containing information used to do replacement in template
1118 def _CreateTemplateDict(self):
1119 Separator = self._SEP_[self._FileType]
1120
1121 PlatformInfo = self._AutoGenObject
1122 if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:
1123 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
1124 ExtraData="[%s]" % str(self._AutoGenObject))
1125
1126 self.IntermediateDirectoryList = ["$(BUILD_DIR)"]
1127 self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()
1128 self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()
1129
1130 MakefileName = self._FILE_NAME_[self._FileType]
1131 LibraryMakefileList = []
1132 LibraryMakeCommandList = []
1133 for D in self.LibraryBuildDirectoryList:
1134 D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})
1135 Makefile = os.path.join(D, MakefileName)
1136 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
1137 LibraryMakefileList.append(Makefile)
1138 LibraryMakeCommandList.append(Command)
1139 self.LibraryMakeCommandList = LibraryMakeCommandList
1140
1141 ModuleMakefileList = []
1142 ModuleMakeCommandList = []
1143 for D in self.ModuleBuildDirectoryList:
1144 D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})
1145 Makefile = os.path.join(D, MakefileName)
1146 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
1147 ModuleMakefileList.append(Makefile)
1148 ModuleMakeCommandList.append(Command)
1149
1150 MakefileTemplateDict = {
1151 "makefile_header" : self._FILE_HEADER_[self._FileType],
1152 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),
1153 "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"],
1154 "makefile_name" : MakefileName,
1155 "platform_name" : PlatformInfo.Name,
1156 "platform_guid" : PlatformInfo.Guid,
1157 "platform_version" : PlatformInfo.Version,
1158 "platform_file" : self._AutoGenObject.MetaFile,
1159 "platform_relative_directory": PlatformInfo.SourceDir,
1160 "platform_output_directory" : PlatformInfo.OutputDir,
1161 "platform_build_directory" : PlatformInfo.BuildDir,
1162
1163 "toolchain_tag" : PlatformInfo.ToolChain,
1164 "build_target" : PlatformInfo.BuildTarget,
1165 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),
1166 "shell_command" : self._SHELL_CMD_[self._FileType].values(),
1167 "build_architecture_list" : self._AutoGenObject.Arch,
1168 "architecture" : self._AutoGenObject.Arch,
1169 "separator" : Separator,
1170 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1171 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1172 "library_makefile_list" : LibraryMakefileList,
1173 "module_makefile_list" : ModuleMakefileList,
1174 "library_build_command" : LibraryMakeCommandList,
1175 "module_build_command" : ModuleMakeCommandList,
1176 }
1177
1178 return MakefileTemplateDict
1179
1180 ## Get the root directory list for intermediate files of all modules build
1181 #
1182 # @retval list The list of directory
1183 #
1184 def GetModuleBuildDirectoryList(self):
1185 DirList = []
1186 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1187 if not ModuleAutoGen.IsBinaryModule:
1188 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1189 return DirList
1190
1191 ## Get the root directory list for intermediate files of all libraries build
1192 #
1193 # @retval list The list of directory
1194 #
1195 def GetLibraryBuildDirectoryList(self):
1196 DirList = []
1197 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1198 if not LibraryAutoGen.IsBinaryModule:
1199 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1200 return DirList
1201
1202 _TemplateDict = property(_CreateTemplateDict)
1203
1204 ## TopLevelMakefile class
1205 #
1206 # This class encapsules makefie and its generation for entrance makefile. It
1207 # uses template to generate the content of makefile. The content of makefile
1208 # will be got from WorkspaceAutoGen object.
1209 #
1210 class TopLevelMakefile(BuildFile):
1211 ## template used to generate toplevel makefile
1212 _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}''')
1213
1214 ## Constructor of TopLevelMakefile
1215 #
1216 # @param Workspace Object of WorkspaceAutoGen class
1217 #
1218 def __init__(self, Workspace):
1219 BuildFile.__init__(self, Workspace)
1220 self.IntermediateDirectoryList = []
1221
1222 # Compose a dict object containing information used to do replacement in template
1223 def _CreateTemplateDict(self):
1224 Separator = self._SEP_[self._FileType]
1225
1226 # any platform autogen object is ok because we just need common information
1227 PlatformInfo = self._AutoGenObject
1228
1229 if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:
1230 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
1231 ExtraData="[%s]" % str(self._AutoGenObject))
1232
1233 for Arch in PlatformInfo.ArchList:
1234 self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch]))
1235 self.IntermediateDirectoryList.append("$(FV_DIR)")
1236
1237 # TRICK: for not generating GenFds call in makefile if no FDF file
1238 MacroList = []
1239 if PlatformInfo.FdfFile != None and PlatformInfo.FdfFile != "":
1240 FdfFileList = [PlatformInfo.FdfFile]
1241 # macros passed to GenFds
1242 MacroList.append('"%s=%s"' % ("EFI_SOURCE", GlobalData.gEfiSource.replace('\\', '\\\\')))
1243 MacroList.append('"%s=%s"' % ("EDK_SOURCE", GlobalData.gEdkSource.replace('\\', '\\\\')))
1244 MacroDict = {}
1245 MacroDict.update(GlobalData.gGlobalDefines)
1246 MacroDict.update(GlobalData.gCommandLineDefines)
1247 MacroDict.pop("EFI_SOURCE", "dummy")
1248 MacroDict.pop("EDK_SOURCE", "dummy")
1249 for MacroName in MacroDict:
1250 if MacroDict[MacroName] != "":
1251 MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))
1252 else:
1253 MacroList.append('"%s"' % MacroName)
1254 else:
1255 FdfFileList = []
1256
1257 # pass extra common options to external program called in makefile, currently GenFds.exe
1258 ExtraOption = ''
1259 LogLevel = EdkLogger.GetLevel()
1260 if LogLevel == EdkLogger.VERBOSE:
1261 ExtraOption += " -v"
1262 elif LogLevel <= EdkLogger.DEBUG_9:
1263 ExtraOption += " -d %d" % (LogLevel - 1)
1264 elif LogLevel == EdkLogger.QUIET:
1265 ExtraOption += " -q"
1266
1267 if GlobalData.gCaseInsensitive:
1268 ExtraOption += " -c"
1269
1270 if GlobalData.gIgnoreSource:
1271 ExtraOption += " --ignore-sources"
1272
1273 MakefileName = self._FILE_NAME_[self._FileType]
1274 SubBuildCommandList = []
1275 for A in PlatformInfo.ArchList:
1276 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)}
1277 SubBuildCommandList.append(Command)
1278
1279 MakefileTemplateDict = {
1280 "makefile_header" : self._FILE_HEADER_[self._FileType],
1281 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),
1282 "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"],
1283 "platform_name" : PlatformInfo.Name,
1284 "platform_guid" : PlatformInfo.Guid,
1285 "platform_version" : PlatformInfo.Version,
1286 "platform_build_directory" : PlatformInfo.BuildDir,
1287 "conf_directory" : GlobalData.gConfDirectory,
1288
1289 "toolchain_tag" : PlatformInfo.ToolChain,
1290 "build_target" : PlatformInfo.BuildTarget,
1291 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),
1292 "shell_command" : self._SHELL_CMD_[self._FileType].values(),
1293 'arch' : list(PlatformInfo.ArchList),
1294 "build_architecture_list" : ','.join(PlatformInfo.ArchList),
1295 "separator" : Separator,
1296 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1297 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1298 "sub_build_command" : SubBuildCommandList,
1299 "fdf_file" : FdfFileList,
1300 "active_platform" : str(PlatformInfo),
1301 "fd" : PlatformInfo.FdTargetList,
1302 "fv" : PlatformInfo.FvTargetList,
1303 "cap" : PlatformInfo.CapTargetList,
1304 "extra_options" : ExtraOption,
1305 "macro" : MacroList,
1306 }
1307
1308 return MakefileTemplateDict
1309
1310 ## Get the root directory list for intermediate files of all modules build
1311 #
1312 # @retval list The list of directory
1313 #
1314 def GetModuleBuildDirectoryList(self):
1315 DirList = []
1316 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1317 if not ModuleAutoGen.IsBinaryModule:
1318 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1319 return DirList
1320
1321 ## Get the root directory list for intermediate files of all libraries build
1322 #
1323 # @retval list The list of directory
1324 #
1325 def GetLibraryBuildDirectoryList(self):
1326 DirList = []
1327 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1328 if not LibraryAutoGen.IsBinaryModule:
1329 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1330 return DirList
1331
1332 _TemplateDict = property(_CreateTemplateDict)
1333
1334 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1335 if __name__ == '__main__':
1336 pass
1337