]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/GenMake.py
BaseTools: Fixed a bug to generate correct path of PACKAGE_RELATIVE_PATH
[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_NAME_GUID = ${module_name_guid}
245 MODULE_VERSION = ${module_version}
246 MODULE_TYPE = ${module_type}
247 MODULE_FILE = ${module_file}
248 MODULE_FILE_BASE_NAME = ${module_file_base_name}
249 BASE_NAME = $(MODULE_NAME)
250 MODULE_RELATIVE_DIR = ${module_relative_directory}
251 PACKAGE_RELATIVE_DIR = ${package_relative_directory}
252 MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory}
253
254 MODULE_ENTRY_POINT = ${module_entry_point}
255 ARCH_ENTRY_POINT = ${arch_entry_point}
256 IMAGE_ENTRY_POINT = ${image_entry_point}
257
258 ${BEGIN}${module_extra_defines}
259 ${END}
260 #
261 # Build Configuration Macro Definition
262 #
263 ARCH = ${architecture}
264 TOOLCHAIN = ${toolchain_tag}
265 TOOLCHAIN_TAG = ${toolchain_tag}
266 TARGET = ${build_target}
267
268 #
269 # Build Directory Macro Definition
270 #
271 # PLATFORM_BUILD_DIR = ${platform_build_directory}
272 BUILD_DIR = ${platform_build_directory}
273 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
274 LIB_DIR = $(BIN_DIR)
275 MODULE_BUILD_DIR = ${module_build_directory}
276 OUTPUT_DIR = ${module_output_directory}
277 DEBUG_DIR = ${module_debug_directory}
278 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
279 DEST_DIR_DEBUG = $(DEBUG_DIR)
280
281 #
282 # Shell Command Macro
283 #
284 ${BEGIN}${shell_command_code} = ${shell_command}
285 ${END}
286
287 #
288 # Tools definitions specific to this module
289 #
290 ${BEGIN}${module_tool_definitions}
291 ${END}
292 MAKE_FILE = ${makefile_path}
293
294 #
295 # Build Macro
296 #
297 ${BEGIN}${file_macro}
298 ${END}
299
300 COMMON_DEPS = ${BEGIN}${common_dependency_file} \\
301 ${END}
302
303 #
304 # Overridable Target Macro Definitions
305 #
306 FORCE_REBUILD = force_build
307 INIT_TARGET = init
308 PCH_TARGET =
309 BC_TARGET = ${BEGIN}${backward_compatible_target} ${END}
310 CODA_TARGET = ${BEGIN}${remaining_build_target} \\
311 ${END}
312
313 #
314 # Default target, which will build dependent libraries in addition to source files
315 #
316
317 all: mbuild
318
319
320 #
321 # Target used when called from platform makefile, which will bypass the build of dependent libraries
322 #
323
324 pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
325
326 #
327 # ModuleTarget
328 #
329
330 mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET)
331
332 #
333 # Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets
334 #
335
336 tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
337
338 #
339 # Phony target which is used to force executing commands for a target
340 #
341 force_build:
342 \t-@
343
344 #
345 # Target to update the FD
346 #
347
348 fds: mbuild gen_fds
349
350 #
351 # Initialization target: print build information and create necessary directories
352 #
353 init: info dirs
354
355 info:
356 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
357
358 dirs:
359 ${BEGIN}\t-@${create_directory_command}\n${END}
360
361 strdefs:
362 \t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h
363
364 #
365 # GenLibsTarget
366 #
367 gen_libs:
368 \t${BEGIN}@"$(MAKE)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name}
369 \t${END}@cd $(MODULE_BUILD_DIR)
370
371 #
372 # Build Flash Device Image
373 #
374 gen_fds:
375 \t@"$(MAKE)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds
376 \t@cd $(MODULE_BUILD_DIR)
377
378 #
379 # Individual Object Build Targets
380 #
381 ${BEGIN}${file_build_target}
382 ${END}
383
384 #
385 # clean all intermediate files
386 #
387 clean:
388 \t${BEGIN}${clean_command}
389 \t${END}
390
391 #
392 # clean all generated files
393 #
394 cleanall:
395 ${BEGIN}\t${cleanall_command}
396 ${END}\t$(RM) *.pdb *.idb > NUL 2>&1
397 \t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi
398
399 #
400 # clean all dependent libraries built
401 #
402 cleanlib:
403 \t${BEGIN}-@${library_build_command} cleanall
404 \t${END}@cd $(MODULE_BUILD_DIR)\n\n''')
405
406 _FILE_MACRO_TEMPLATE = TemplateString("${macro_name} = ${BEGIN} \\\n ${source_file}${END}\n")
407 _BUILD_TARGET_TEMPLATE = TemplateString("${BEGIN}${target} : ${deps}\n${END}\t${cmd}\n")
408
409 ## Constructor of ModuleMakefile
410 #
411 # @param ModuleAutoGen Object of ModuleAutoGen class
412 #
413 def __init__(self, ModuleAutoGen):
414 BuildFile.__init__(self, ModuleAutoGen)
415 self.PlatformInfo = self._AutoGenObject.PlatformInfo
416
417 self.ResultFileList = []
418 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
419
420 self.SourceFileDatabase = {} # {file type : file path}
421 self.DestFileDatabase = {} # {file type : file path}
422 self.FileBuildTargetList = [] # [(src, target string)]
423 self.BuildTargetList = [] # [target string]
424 self.PendingBuildTargetList = [] # [FileBuildRule objects]
425 self.CommonFileDependency = []
426 self.FileListMacros = {}
427 self.ListFileMacros = {}
428
429 self.FileCache = {}
430 self.FileDependency = []
431 self.LibraryBuildCommandList = []
432 self.LibraryFileList = []
433 self.LibraryMakefileList = []
434 self.LibraryBuildDirectoryList = []
435 self.SystemLibraryList = []
436 self.Macros = sdict()
437 self.Macros["OUTPUT_DIR" ] = self._AutoGenObject.Macros["OUTPUT_DIR"]
438 self.Macros["DEBUG_DIR" ] = self._AutoGenObject.Macros["DEBUG_DIR"]
439 self.Macros["MODULE_BUILD_DIR"] = self._AutoGenObject.Macros["MODULE_BUILD_DIR"]
440 self.Macros["BIN_DIR" ] = self._AutoGenObject.Macros["BIN_DIR"]
441 self.Macros["BUILD_DIR" ] = self._AutoGenObject.Macros["BUILD_DIR"]
442 self.Macros["WORKSPACE" ] = self._AutoGenObject.Macros["WORKSPACE"]
443
444 # Compose a dict object containing information used to do replacement in template
445 def _CreateTemplateDict(self):
446 if self._FileType not in self._SEP_:
447 EdkLogger.error("build", PARAMETER_INVALID, "Invalid Makefile type [%s]" % self._FileType,
448 ExtraData="[%s]" % str(self._AutoGenObject))
449 Separator = self._SEP_[self._FileType]
450
451 # break build if no source files and binary files are found
452 if len(self._AutoGenObject.SourceFileList) == 0 and len(self._AutoGenObject.BinaryFileList) == 0:
453 EdkLogger.error("build", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]"
454 % (self._AutoGenObject.BuildTarget, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch),
455 ExtraData="[%s]" % str(self._AutoGenObject))
456
457 # convert dependent libraries to build command
458 self.ProcessDependentLibrary()
459 if len(self._AutoGenObject.Module.ModuleEntryPointList) > 0:
460 ModuleEntryPoint = self._AutoGenObject.Module.ModuleEntryPointList[0]
461 else:
462 ModuleEntryPoint = "_ModuleEntryPoint"
463
464 # Intel EBC compiler enforces EfiMain
465 if self._AutoGenObject.AutoGenVersion < 0x00010005 and self._AutoGenObject.Arch == "EBC":
466 ArchEntryPoint = "EfiMain"
467 else:
468 ArchEntryPoint = ModuleEntryPoint
469
470 if self._AutoGenObject.Arch == "EBC":
471 # EBC compiler always use "EfiStart" as entry point. Only applies to EdkII modules
472 ImageEntryPoint = "EfiStart"
473 elif self._AutoGenObject.AutoGenVersion < 0x00010005:
474 # Edk modules use entry point specified in INF file
475 ImageEntryPoint = ModuleEntryPoint
476 else:
477 # EdkII modules always use "_ModuleEntryPoint" as entry point
478 ImageEntryPoint = "_ModuleEntryPoint"
479
480 # tools definitions
481 ToolsDef = []
482 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
483 for Tool in self._AutoGenObject.BuildOption:
484 for Attr in self._AutoGenObject.BuildOption[Tool]:
485 Value = self._AutoGenObject.BuildOption[Tool][Attr]
486 if Attr == "FAMILY":
487 continue
488 elif Attr == "PATH":
489 ToolsDef.append("%s = %s" % (Tool, Value))
490 else:
491 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
492 if Tool == "MAKE":
493 continue
494 # Remove duplicated include path, if any
495 if Attr == "FLAGS":
496 Value = RemoveDupOption(Value, IncPrefix, self._AutoGenObject.IncludePathList)
497 ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
498 ToolsDef.append("")
499
500 # convert source files and binary files to build targets
501 self.ResultFileList = [str(T.Target) for T in self._AutoGenObject.CodaTargetList]
502 if len(self.ResultFileList) == 0 and len(self._AutoGenObject.SourceFileList) <> 0:
503 EdkLogger.error("build", AUTOGEN_ERROR, "Nothing to build",
504 ExtraData="[%s]" % str(self._AutoGenObject))
505
506 self.ProcessBuildTargetList()
507
508 # Generate macros used to represent input files
509 FileMacroList = [] # macro name = file list
510 for FileListMacro in self.FileListMacros:
511 FileMacro = self._FILE_MACRO_TEMPLATE.Replace(
512 {
513 "macro_name" : FileListMacro,
514 "source_file" : self.FileListMacros[FileListMacro]
515 }
516 )
517 FileMacroList.append(FileMacro)
518
519 # INC_LIST is special
520 FileMacro = ""
521 IncludePathList = []
522 for P in self._AutoGenObject.IncludePathList:
523 IncludePathList.append(IncPrefix+self.PlaceMacro(P, self.Macros))
524 if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:
525 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix+P)
526 FileMacro += self._FILE_MACRO_TEMPLATE.Replace(
527 {
528 "macro_name" : "INC",
529 "source_file" : IncludePathList
530 }
531 )
532 FileMacroList.append(FileMacro)
533
534 # Generate macros used to represent files containing list of input files
535 for ListFileMacro in self.ListFileMacros:
536 ListFileName = os.path.join(self._AutoGenObject.OutputDir, "%s.lst" % ListFileMacro.lower()[:len(ListFileMacro)-5])
537 FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))
538 SaveFileOnChange(
539 ListFileName,
540 "\n".join(self.ListFileMacros[ListFileMacro]),
541 False
542 )
543
544 # Edk modules need <BaseName>StrDefs.h for string ID
545 #if self._AutoGenObject.AutoGenVersion < 0x00010005 and len(self._AutoGenObject.UnicodeFileList) > 0:
546 # BcTargetList = ['strdefs']
547 #else:
548 # BcTargetList = []
549 BcTargetList = []
550
551 MakefileName = self._FILE_NAME_[self._FileType]
552 LibraryMakeCommandList = []
553 for D in self.LibraryBuildDirectoryList:
554 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)}
555 LibraryMakeCommandList.append(Command)
556
557 package_rel_dir = self._AutoGenObject.SourceDir
558 current_dir = self.Macros["WORKSPACE"]
559 found = False
560 while not found and os.sep in package_rel_dir:
561 index = package_rel_dir.index(os.sep)
562 current_dir = os.path.join(current_dir, package_rel_dir[:index])
563 for fl in os.listdir(current_dir):
564 if fl.endswith('.dec'):
565 found = True
566 break
567 package_rel_dir = package_rel_dir[index + 1:]
568
569 MakefileTemplateDict = {
570 "makefile_header" : self._FILE_HEADER_[self._FileType],
571 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
572 "makefile_name" : MakefileName,
573 "platform_name" : self.PlatformInfo.Name,
574 "platform_guid" : self.PlatformInfo.Guid,
575 "platform_version" : self.PlatformInfo.Version,
576 "platform_relative_directory": self.PlatformInfo.SourceDir,
577 "platform_output_directory" : self.PlatformInfo.OutputDir,
578
579 "module_name" : self._AutoGenObject.Name,
580 "module_guid" : self._AutoGenObject.Guid,
581 "module_name_guid" : self._AutoGenObject._GetUniqueBaseName(),
582 "module_version" : self._AutoGenObject.Version,
583 "module_type" : self._AutoGenObject.ModuleType,
584 "module_file" : self._AutoGenObject.MetaFile.Name,
585 "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName,
586 "module_relative_directory" : self._AutoGenObject.SourceDir,
587 "package_relative_directory": package_rel_dir,
588 "module_extra_defines" : ["%s = %s" % (k, v) for k, v in self._AutoGenObject.Module.Defines.iteritems()],
589
590 "architecture" : self._AutoGenObject.Arch,
591 "toolchain_tag" : self._AutoGenObject.ToolChain,
592 "build_target" : self._AutoGenObject.BuildTarget,
593
594 "platform_build_directory" : self.PlatformInfo.BuildDir,
595 "module_build_directory" : self._AutoGenObject.BuildDir,
596 "module_output_directory" : self._AutoGenObject.OutputDir,
597 "module_debug_directory" : self._AutoGenObject.DebugDir,
598
599 "separator" : Separator,
600 "module_tool_definitions" : ToolsDef,
601
602 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),
603 "shell_command" : self._SHELL_CMD_[self._FileType].values(),
604
605 "module_entry_point" : ModuleEntryPoint,
606 "image_entry_point" : ImageEntryPoint,
607 "arch_entry_point" : ArchEntryPoint,
608 "remaining_build_target" : self.ResultFileList,
609 "common_dependency_file" : self.CommonFileDependency,
610 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
611 "clean_command" : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]),
612 "cleanall_command" : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]),
613 "dependent_library_build_directory" : self.LibraryBuildDirectoryList,
614 "library_build_command" : LibraryMakeCommandList,
615 "file_macro" : FileMacroList,
616 "file_build_target" : self.BuildTargetList,
617 "backward_compatible_target": BcTargetList,
618 }
619
620 return MakefileTemplateDict
621
622 def ProcessBuildTargetList(self):
623 #
624 # Search dependency file list for each source file
625 #
626 ForceIncludedFile = []
627 for File in self._AutoGenObject.AutoGenFileList:
628 if File.Ext == '.h':
629 ForceIncludedFile.append(File)
630 SourceFileList = []
631 for Target in self._AutoGenObject.IntroTargetList:
632 SourceFileList.extend(Target.Inputs)
633
634 self.FileDependency = self.GetFileDependency(
635 SourceFileList,
636 ForceIncludedFile,
637 self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList
638 )
639 DepSet = None
640 for File in self.FileDependency:
641 if not self.FileDependency[File]:
642 self.FileDependency[File] = ['$(FORCE_REBUILD)']
643 continue
644 # skip non-C files
645 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
646 continue
647 elif DepSet == None:
648 DepSet = set(self.FileDependency[File])
649 else:
650 DepSet &= set(self.FileDependency[File])
651 # in case nothing in SourceFileList
652 if DepSet == None:
653 DepSet = set()
654 #
655 # Extract common files list in the dependency files
656 #
657 for File in DepSet:
658 self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros))
659
660 for File in self.FileDependency:
661 # skip non-C files
662 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
663 continue
664 NewDepSet = set(self.FileDependency[File])
665 NewDepSet -= DepSet
666 self.FileDependency[File] = ["$(COMMON_DEPS)"] + list(NewDepSet)
667
668 # Convert target description object to target string in makefile
669 for Type in self._AutoGenObject.Targets:
670 for T in self._AutoGenObject.Targets[Type]:
671 # Generate related macros if needed
672 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
673 self.FileListMacros[T.FileListMacro] = []
674 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:
675 self.ListFileMacros[T.ListFileMacro] = []
676 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:
677 self.ListFileMacros[T.IncListFileMacro] = []
678
679 Deps = []
680 # Add force-dependencies
681 for Dep in T.Dependencies:
682 Deps.append(self.PlaceMacro(str(Dep), self.Macros))
683 # Add inclusion-dependencies
684 if len(T.Inputs) == 1 and T.Inputs[0] in self.FileDependency:
685 for F in self.FileDependency[T.Inputs[0]]:
686 Deps.append(self.PlaceMacro(str(F), self.Macros))
687 # Add source-dependencies
688 for F in T.Inputs:
689 NewFile = self.PlaceMacro(str(F), self.Macros)
690 # In order to use file list macro as dependency
691 if T.GenListFile:
692 # gnu tools need forward slash path separater, even on Windows
693 self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/'))
694 self.FileListMacros[T.FileListMacro].append(NewFile)
695 elif T.GenFileListMacro:
696 self.FileListMacros[T.FileListMacro].append(NewFile)
697 else:
698 Deps.append(NewFile)
699
700 # Use file list macro as dependency
701 if T.GenFileListMacro:
702 Deps.append("$(%s)" % T.FileListMacro)
703
704 TargetDict = {
705 "target" : self.PlaceMacro(T.Target.Path, self.Macros),
706 "cmd" : "\n\t".join(T.Commands),
707 "deps" : Deps
708 }
709 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
710
711 ## For creating makefile targets for dependent libraries
712 def ProcessDependentLibrary(self):
713 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
714 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
715
716 ## Return a list containing source file's dependencies
717 #
718 # @param FileList The list of source files
719 # @param ForceInculeList The list of files which will be included forcely
720 # @param SearchPathList The list of search path
721 #
722 # @retval dict The mapping between source file path and its dependencies
723 #
724 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
725 Dependency = {}
726 for F in FileList:
727 Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)
728 return Dependency
729
730 ## Find dependencies for one source file
731 #
732 # By searching recursively "#include" directive in file, find out all the
733 # files needed by given source file. The dependecies will be only searched
734 # in given search path list.
735 #
736 # @param File The source file
737 # @param ForceInculeList The list of files which will be included forcely
738 # @param SearchPathList The list of search path
739 #
740 # @retval list The list of files the given source file depends on
741 #
742 def GetDependencyList(self, File, ForceList, SearchPathList):
743 EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File)
744 FileStack = [File] + ForceList
745 DependencySet = set()
746
747 if self._AutoGenObject.Arch not in gDependencyDatabase:
748 gDependencyDatabase[self._AutoGenObject.Arch] = {}
749 DepDb = gDependencyDatabase[self._AutoGenObject.Arch]
750
751 while len(FileStack) > 0:
752 F = FileStack.pop()
753
754 FullPathDependList = []
755 if F in self.FileCache:
756 for CacheFile in self.FileCache[F]:
757 FullPathDependList.append(CacheFile)
758 if CacheFile not in DependencySet:
759 FileStack.append(CacheFile)
760 DependencySet.update(FullPathDependList)
761 continue
762
763 CurrentFileDependencyList = []
764 if F in DepDb:
765 CurrentFileDependencyList = DepDb[F]
766 else:
767 try:
768 Fd = open(F.Path, 'r')
769 except BaseException, X:
770 EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path+"\n\t"+str(X))
771
772 FileContent = Fd.read()
773 Fd.close()
774 if len(FileContent) == 0:
775 continue
776
777 if FileContent[0] == 0xff or FileContent[0] == 0xfe:
778 FileContent = unicode(FileContent, "utf-16")
779 IncludedFileList = gIncludePattern.findall(FileContent)
780
781 for Inc in IncludedFileList:
782 Inc = Inc.strip()
783 # if there's macro used to reference header file, expand it
784 HeaderList = gMacroPattern.findall(Inc)
785 if len(HeaderList) == 1 and len(HeaderList[0]) == 2:
786 HeaderType = HeaderList[0][0]
787 HeaderKey = HeaderList[0][1]
788 if HeaderType in gIncludeMacroConversion:
789 Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey}
790 else:
791 # not known macro used in #include, always build the file by
792 # returning a empty dependency
793 self.FileCache[File] = []
794 return []
795 Inc = os.path.normpath(Inc)
796 CurrentFileDependencyList.append(Inc)
797 DepDb[F] = CurrentFileDependencyList
798
799 CurrentFilePath = F.Dir
800 PathList = [CurrentFilePath] + SearchPathList
801 for Inc in CurrentFileDependencyList:
802 for SearchPath in PathList:
803 FilePath = os.path.join(SearchPath, Inc)
804 if FilePath in gIsFileMap:
805 if not gIsFileMap[FilePath]:
806 continue
807 # If isfile is called too many times, the performance is slow down.
808 elif not os.path.isfile(FilePath):
809 gIsFileMap[FilePath] = False
810 continue
811 else:
812 gIsFileMap[FilePath] = True
813 FilePath = PathClass(FilePath)
814 FullPathDependList.append(FilePath)
815 if FilePath not in DependencySet:
816 FileStack.append(FilePath)
817 break
818 else:
819 EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\
820 "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList)))
821
822 self.FileCache[F] = FullPathDependList
823 DependencySet.update(FullPathDependList)
824
825 DependencySet.update(ForceList)
826 if File in DependencySet:
827 DependencySet.remove(File)
828 DependencyList = list(DependencySet) # remove duplicate ones
829
830 return DependencyList
831
832 _TemplateDict = property(_CreateTemplateDict)
833
834 ## CustomMakefile class
835 #
836 # This class encapsules makefie and its generation for module. It uses template to generate
837 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
838 #
839 class CustomMakefile(BuildFile):
840 ## template used to generate the makefile for module with custom makefile
841 _TEMPLATE_ = TemplateString('''\
842 ${makefile_header}
843
844 #
845 # Platform Macro Definition
846 #
847 PLATFORM_NAME = ${platform_name}
848 PLATFORM_GUID = ${platform_guid}
849 PLATFORM_VERSION = ${platform_version}
850 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
851 PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}
852 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
853
854 #
855 # Module Macro Definition
856 #
857 MODULE_NAME = ${module_name}
858 MODULE_GUID = ${module_guid}
859 MODULE_NAME_GUID = ${module_name_guid}
860 MODULE_VERSION = ${module_version}
861 MODULE_TYPE = ${module_type}
862 MODULE_FILE = ${module_file}
863 MODULE_FILE_BASE_NAME = ${module_file_base_name}
864 BASE_NAME = $(MODULE_NAME)
865 MODULE_RELATIVE_DIR = ${module_relative_directory}
866 MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory}
867
868 #
869 # Build Configuration Macro Definition
870 #
871 ARCH = ${architecture}
872 TOOLCHAIN = ${toolchain_tag}
873 TOOLCHAIN_TAG = ${toolchain_tag}
874 TARGET = ${build_target}
875
876 #
877 # Build Directory Macro Definition
878 #
879 # PLATFORM_BUILD_DIR = ${platform_build_directory}
880 BUILD_DIR = ${platform_build_directory}
881 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
882 LIB_DIR = $(BIN_DIR)
883 MODULE_BUILD_DIR = ${module_build_directory}
884 OUTPUT_DIR = ${module_output_directory}
885 DEBUG_DIR = ${module_debug_directory}
886 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
887 DEST_DIR_DEBUG = $(DEBUG_DIR)
888
889 #
890 # Tools definitions specific to this module
891 #
892 ${BEGIN}${module_tool_definitions}
893 ${END}
894 MAKE_FILE = ${makefile_path}
895
896 #
897 # Shell Command Macro
898 #
899 ${BEGIN}${shell_command_code} = ${shell_command}
900 ${END}
901
902 ${custom_makefile_content}
903
904 #
905 # Target used when called from platform makefile, which will bypass the build of dependent libraries
906 #
907
908 pbuild: init all
909
910
911 #
912 # ModuleTarget
913 #
914
915 mbuild: init all
916
917 #
918 # Build Target used in multi-thread build mode, which no init target is needed
919 #
920
921 tbuild: all
922
923 #
924 # Initialization target: print build information and create necessary directories
925 #
926 init:
927 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
928 ${BEGIN}\t-@${create_directory_command}\n${END}\
929
930 ''')
931
932 ## Constructor of CustomMakefile
933 #
934 # @param ModuleAutoGen Object of ModuleAutoGen class
935 #
936 def __init__(self, ModuleAutoGen):
937 BuildFile.__init__(self, ModuleAutoGen)
938 self.PlatformInfo = self._AutoGenObject.PlatformInfo
939 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
940
941 # Compose a dict object containing information used to do replacement in template
942 def _CreateTemplateDict(self):
943 Separator = self._SEP_[self._FileType]
944 if self._FileType not in self._AutoGenObject.CustomMakefile:
945 EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType,
946 ExtraData="[%s]" % str(self._AutoGenObject))
947 MakefilePath = os.path.join(
948 self._AutoGenObject.WorkspaceDir,
949 self._AutoGenObject.CustomMakefile[self._FileType]
950 )
951 try:
952 CustomMakefile = open(MakefilePath, 'r').read()
953 except:
954 EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(self._AutoGenObject),
955 ExtraData=self._AutoGenObject.CustomMakefile[self._FileType])
956
957 # tools definitions
958 ToolsDef = []
959 for Tool in self._AutoGenObject.BuildOption:
960 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
961 if Tool == "MAKE":
962 continue
963 for Attr in self._AutoGenObject.BuildOption[Tool]:
964 if Attr == "FAMILY":
965 continue
966 elif Attr == "PATH":
967 ToolsDef.append("%s = %s" % (Tool, self._AutoGenObject.BuildOption[Tool][Attr]))
968 else:
969 ToolsDef.append("%s_%s = %s" % (Tool, Attr, self._AutoGenObject.BuildOption[Tool][Attr]))
970 ToolsDef.append("")
971
972 MakefileName = self._FILE_NAME_[self._FileType]
973 MakefileTemplateDict = {
974 "makefile_header" : self._FILE_HEADER_[self._FileType],
975 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
976 "platform_name" : self.PlatformInfo.Name,
977 "platform_guid" : self.PlatformInfo.Guid,
978 "platform_version" : self.PlatformInfo.Version,
979 "platform_relative_directory": self.PlatformInfo.SourceDir,
980 "platform_output_directory" : self.PlatformInfo.OutputDir,
981
982 "module_name" : self._AutoGenObject.Name,
983 "module_guid" : self._AutoGenObject.Guid,
984 "module_name_guid" : self._AutoGenObject._GetUniqueBaseName(),
985 "module_version" : self._AutoGenObject.Version,
986 "module_type" : self._AutoGenObject.ModuleType,
987 "module_file" : self._AutoGenObject.MetaFile,
988 "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName,
989 "module_relative_directory" : self._AutoGenObject.SourceDir,
990
991 "architecture" : self._AutoGenObject.Arch,
992 "toolchain_tag" : self._AutoGenObject.ToolChain,
993 "build_target" : self._AutoGenObject.BuildTarget,
994
995 "platform_build_directory" : self.PlatformInfo.BuildDir,
996 "module_build_directory" : self._AutoGenObject.BuildDir,
997 "module_output_directory" : self._AutoGenObject.OutputDir,
998 "module_debug_directory" : self._AutoGenObject.DebugDir,
999
1000 "separator" : Separator,
1001 "module_tool_definitions" : ToolsDef,
1002
1003 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),
1004 "shell_command" : self._SHELL_CMD_[self._FileType].values(),
1005
1006 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1007 "custom_makefile_content" : CustomMakefile
1008 }
1009
1010 return MakefileTemplateDict
1011
1012 _TemplateDict = property(_CreateTemplateDict)
1013
1014 ## PlatformMakefile class
1015 #
1016 # This class encapsules makefie and its generation for platform. It uses
1017 # template to generate the content of makefile. The content of makefile will be
1018 # got from PlatformAutoGen object.
1019 #
1020 class PlatformMakefile(BuildFile):
1021 ## template used to generate the makefile for platform
1022 _TEMPLATE_ = TemplateString('''\
1023 ${makefile_header}
1024
1025 #
1026 # Platform Macro Definition
1027 #
1028 PLATFORM_NAME = ${platform_name}
1029 PLATFORM_GUID = ${platform_guid}
1030 PLATFORM_VERSION = ${platform_version}
1031 PLATFORM_FILE = ${platform_file}
1032 PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}
1033 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1034
1035 #
1036 # Build Configuration Macro Definition
1037 #
1038 TOOLCHAIN = ${toolchain_tag}
1039 TOOLCHAIN_TAG = ${toolchain_tag}
1040 TARGET = ${build_target}
1041
1042 #
1043 # Build Directory Macro Definition
1044 #
1045 BUILD_DIR = ${platform_build_directory}
1046 FV_DIR = ${platform_build_directory}${separator}FV
1047
1048 #
1049 # Shell Command Macro
1050 #
1051 ${BEGIN}${shell_command_code} = ${shell_command}
1052 ${END}
1053
1054 MAKE = ${make_path}
1055 MAKE_FILE = ${makefile_path}
1056
1057 #
1058 # Default target
1059 #
1060 all: init build_libraries build_modules
1061
1062 #
1063 # Initialization target: print build information and create necessary directories
1064 #
1065 init:
1066 \t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
1067 \t${BEGIN}-@${create_directory_command}
1068 \t${END}
1069 #
1070 # library build target
1071 #
1072 libraries: init build_libraries
1073
1074 #
1075 # module build target
1076 #
1077 modules: init build_libraries build_modules
1078
1079 #
1080 # Build all libraries:
1081 #
1082 build_libraries:
1083 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
1084 ${END}\t@cd $(BUILD_DIR)
1085
1086 #
1087 # Build all modules:
1088 #
1089 build_modules:
1090 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
1091 ${END}\t@cd $(BUILD_DIR)
1092
1093 #
1094 # Clean intermediate files
1095 #
1096 clean:
1097 \t${BEGIN}-@${library_build_command} clean
1098 \t${END}${BEGIN}-@${module_build_command} clean
1099 \t${END}@cd $(BUILD_DIR)
1100
1101 #
1102 # Clean all generated files except to makefile
1103 #
1104 cleanall:
1105 ${BEGIN}\t${cleanall_command}
1106 ${END}
1107
1108 #
1109 # Clean all library files
1110 #
1111 cleanlib:
1112 \t${BEGIN}-@${library_build_command} cleanall
1113 \t${END}@cd $(BUILD_DIR)\n
1114 ''')
1115
1116 ## Constructor of PlatformMakefile
1117 #
1118 # @param ModuleAutoGen Object of PlatformAutoGen class
1119 #
1120 def __init__(self, PlatformAutoGen):
1121 BuildFile.__init__(self, PlatformAutoGen)
1122 self.ModuleBuildCommandList = []
1123 self.ModuleMakefileList = []
1124 self.IntermediateDirectoryList = []
1125 self.ModuleBuildDirectoryList = []
1126 self.LibraryBuildDirectoryList = []
1127 self.LibraryMakeCommandList = []
1128
1129 # Compose a dict object containing information used to do replacement in template
1130 def _CreateTemplateDict(self):
1131 Separator = self._SEP_[self._FileType]
1132
1133 PlatformInfo = self._AutoGenObject
1134 if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:
1135 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
1136 ExtraData="[%s]" % str(self._AutoGenObject))
1137
1138 self.IntermediateDirectoryList = ["$(BUILD_DIR)"]
1139 self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()
1140 self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()
1141
1142 MakefileName = self._FILE_NAME_[self._FileType]
1143 LibraryMakefileList = []
1144 LibraryMakeCommandList = []
1145 for D in self.LibraryBuildDirectoryList:
1146 D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})
1147 Makefile = os.path.join(D, MakefileName)
1148 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
1149 LibraryMakefileList.append(Makefile)
1150 LibraryMakeCommandList.append(Command)
1151 self.LibraryMakeCommandList = LibraryMakeCommandList
1152
1153 ModuleMakefileList = []
1154 ModuleMakeCommandList = []
1155 for D in self.ModuleBuildDirectoryList:
1156 D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})
1157 Makefile = os.path.join(D, MakefileName)
1158 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
1159 ModuleMakefileList.append(Makefile)
1160 ModuleMakeCommandList.append(Command)
1161
1162 MakefileTemplateDict = {
1163 "makefile_header" : self._FILE_HEADER_[self._FileType],
1164 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),
1165 "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"],
1166 "makefile_name" : MakefileName,
1167 "platform_name" : PlatformInfo.Name,
1168 "platform_guid" : PlatformInfo.Guid,
1169 "platform_version" : PlatformInfo.Version,
1170 "platform_file" : self._AutoGenObject.MetaFile,
1171 "platform_relative_directory": PlatformInfo.SourceDir,
1172 "platform_output_directory" : PlatformInfo.OutputDir,
1173 "platform_build_directory" : PlatformInfo.BuildDir,
1174
1175 "toolchain_tag" : PlatformInfo.ToolChain,
1176 "build_target" : PlatformInfo.BuildTarget,
1177 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),
1178 "shell_command" : self._SHELL_CMD_[self._FileType].values(),
1179 "build_architecture_list" : self._AutoGenObject.Arch,
1180 "architecture" : self._AutoGenObject.Arch,
1181 "separator" : Separator,
1182 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1183 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1184 "library_makefile_list" : LibraryMakefileList,
1185 "module_makefile_list" : ModuleMakefileList,
1186 "library_build_command" : LibraryMakeCommandList,
1187 "module_build_command" : ModuleMakeCommandList,
1188 }
1189
1190 return MakefileTemplateDict
1191
1192 ## Get the root directory list for intermediate files of all modules build
1193 #
1194 # @retval list The list of directory
1195 #
1196 def GetModuleBuildDirectoryList(self):
1197 DirList = []
1198 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1199 if not ModuleAutoGen.IsBinaryModule:
1200 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1201 return DirList
1202
1203 ## Get the root directory list for intermediate files of all libraries build
1204 #
1205 # @retval list The list of directory
1206 #
1207 def GetLibraryBuildDirectoryList(self):
1208 DirList = []
1209 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1210 if not LibraryAutoGen.IsBinaryModule:
1211 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1212 return DirList
1213
1214 _TemplateDict = property(_CreateTemplateDict)
1215
1216 ## TopLevelMakefile class
1217 #
1218 # This class encapsules makefie and its generation for entrance makefile. It
1219 # uses template to generate the content of makefile. The content of makefile
1220 # will be got from WorkspaceAutoGen object.
1221 #
1222 class TopLevelMakefile(BuildFile):
1223 ## template used to generate toplevel makefile
1224 _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}''')
1225
1226 ## Constructor of TopLevelMakefile
1227 #
1228 # @param Workspace Object of WorkspaceAutoGen class
1229 #
1230 def __init__(self, Workspace):
1231 BuildFile.__init__(self, Workspace)
1232 self.IntermediateDirectoryList = []
1233
1234 # Compose a dict object containing information used to do replacement in template
1235 def _CreateTemplateDict(self):
1236 Separator = self._SEP_[self._FileType]
1237
1238 # any platform autogen object is ok because we just need common information
1239 PlatformInfo = self._AutoGenObject
1240
1241 if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:
1242 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
1243 ExtraData="[%s]" % str(self._AutoGenObject))
1244
1245 for Arch in PlatformInfo.ArchList:
1246 self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch]))
1247 self.IntermediateDirectoryList.append("$(FV_DIR)")
1248
1249 # TRICK: for not generating GenFds call in makefile if no FDF file
1250 MacroList = []
1251 if PlatformInfo.FdfFile != None and PlatformInfo.FdfFile != "":
1252 FdfFileList = [PlatformInfo.FdfFile]
1253 # macros passed to GenFds
1254 MacroList.append('"%s=%s"' % ("EFI_SOURCE", GlobalData.gEfiSource.replace('\\', '\\\\')))
1255 MacroList.append('"%s=%s"' % ("EDK_SOURCE", GlobalData.gEdkSource.replace('\\', '\\\\')))
1256 MacroDict = {}
1257 MacroDict.update(GlobalData.gGlobalDefines)
1258 MacroDict.update(GlobalData.gCommandLineDefines)
1259 MacroDict.pop("EFI_SOURCE", "dummy")
1260 MacroDict.pop("EDK_SOURCE", "dummy")
1261 for MacroName in MacroDict:
1262 if MacroDict[MacroName] != "":
1263 MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))
1264 else:
1265 MacroList.append('"%s"' % MacroName)
1266 else:
1267 FdfFileList = []
1268
1269 # pass extra common options to external program called in makefile, currently GenFds.exe
1270 ExtraOption = ''
1271 LogLevel = EdkLogger.GetLevel()
1272 if LogLevel == EdkLogger.VERBOSE:
1273 ExtraOption += " -v"
1274 elif LogLevel <= EdkLogger.DEBUG_9:
1275 ExtraOption += " -d %d" % (LogLevel - 1)
1276 elif LogLevel == EdkLogger.QUIET:
1277 ExtraOption += " -q"
1278
1279 if GlobalData.gCaseInsensitive:
1280 ExtraOption += " -c"
1281
1282 if GlobalData.gIgnoreSource:
1283 ExtraOption += " --ignore-sources"
1284
1285 MakefileName = self._FILE_NAME_[self._FileType]
1286 SubBuildCommandList = []
1287 for A in PlatformInfo.ArchList:
1288 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)}
1289 SubBuildCommandList.append(Command)
1290
1291 MakefileTemplateDict = {
1292 "makefile_header" : self._FILE_HEADER_[self._FileType],
1293 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),
1294 "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"],
1295 "platform_name" : PlatformInfo.Name,
1296 "platform_guid" : PlatformInfo.Guid,
1297 "platform_version" : PlatformInfo.Version,
1298 "platform_build_directory" : PlatformInfo.BuildDir,
1299 "conf_directory" : GlobalData.gConfDirectory,
1300
1301 "toolchain_tag" : PlatformInfo.ToolChain,
1302 "build_target" : PlatformInfo.BuildTarget,
1303 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),
1304 "shell_command" : self._SHELL_CMD_[self._FileType].values(),
1305 'arch' : list(PlatformInfo.ArchList),
1306 "build_architecture_list" : ','.join(PlatformInfo.ArchList),
1307 "separator" : Separator,
1308 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1309 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1310 "sub_build_command" : SubBuildCommandList,
1311 "fdf_file" : FdfFileList,
1312 "active_platform" : str(PlatformInfo),
1313 "fd" : PlatformInfo.FdTargetList,
1314 "fv" : PlatformInfo.FvTargetList,
1315 "cap" : PlatformInfo.CapTargetList,
1316 "extra_options" : ExtraOption,
1317 "macro" : MacroList,
1318 }
1319
1320 return MakefileTemplateDict
1321
1322 ## Get the root directory list for intermediate files of all modules build
1323 #
1324 # @retval list The list of directory
1325 #
1326 def GetModuleBuildDirectoryList(self):
1327 DirList = []
1328 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1329 if not ModuleAutoGen.IsBinaryModule:
1330 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1331 return DirList
1332
1333 ## Get the root directory list for intermediate files of all libraries build
1334 #
1335 # @retval list The list of directory
1336 #
1337 def GetLibraryBuildDirectoryList(self):
1338 DirList = []
1339 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1340 if not LibraryAutoGen.IsBinaryModule:
1341 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1342 return DirList
1343
1344 _TemplateDict = property(_CreateTemplateDict)
1345
1346 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1347 if __name__ == '__main__':
1348 pass
1349