]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/GenMake.py
BaseTools: Update Build tool to support multiple workspaces
[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 from Common.MultipleWorkspace import MultipleWorkspace as mws
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 = mws.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