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