]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/AutoGen/GenMake.py
Sync BaseTool trunk (version r2610) into EDKII BaseTools.
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / GenMake.py
CommitLineData
30fdf114
LG
1## @file
2# Create makefile for MS nmake and GNU make
3#
40d841f6
LG
4# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
5# This program and the accompanying materials
30fdf114
LG
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#
16import os
17import sys
18import string
19import re
20import os.path as path
21
22from Common.BuildToolError import *
23from Common.Misc import *
24from Common.String import *
25from BuildEngine import *
26import Common.GlobalData as GlobalData
27
28## Regular expression for finding header file inclusions
08dd311f 29gIncludePattern = re.compile(r"^[ \t]*#?[ \t]*include(?:[ \t]*(?:\\(?:\r\n|\r|\n))*[ \t]*)*(?:\(?[\"<]?[ \t]*)([-\w.\\/() \t]+)(?:[ \t]*[\">]?\)?)", re.MULTILINE|re.UNICODE|re.IGNORECASE)
30fdf114
LG
30
31## Regular expression for matching macro used in header file inclusion
32gMacroPattern = re.compile("([_A-Z][_A-Z0-9]*)[ \t]*\((.+)\)", re.UNICODE)
33
2bcc713e
LG
34gIsFileMap = {}
35
b36d134f 36## pattern for include style in Edk.x code
30fdf114
LG
37gProtocolDefinition = "Protocol/%(HeaderKey)s/%(HeaderKey)s.h"
38gGuidDefinition = "Guid/%(HeaderKey)s/%(HeaderKey)s.h"
39gArchProtocolDefinition = "ArchProtocol/%(HeaderKey)s/%(HeaderKey)s.h"
40gPpiDefinition = "Ppi/%(HeaderKey)s/%(HeaderKey)s.h"
41gIncludeMacroConversion = {
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
58gMakeType = ""
59if sys.platform == "win32":
60 gMakeType = "nmake"
61else:
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#
70class 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#
223class ModuleMakefile(BuildFile):
224 ## template used to generate the makefile for module
225 _TEMPLATE_ = TemplateString('''\
226${makefile_header}
227
228#
229# Platform Macro Definition
230#
231PLATFORM_NAME = ${platform_name}
232PLATFORM_GUID = ${platform_guid}
233PLATFORM_VERSION = ${platform_version}
234PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
235PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}
236PLATFORM_OUTPUT_DIR = ${platform_output_directory}
237
238#
239# Module Macro Definition
240#
241MODULE_NAME = ${module_name}
242MODULE_GUID = ${module_guid}
243MODULE_VERSION = ${module_version}
244MODULE_TYPE = ${module_type}
245MODULE_FILE = ${module_file}
246MODULE_FILE_BASE_NAME = ${module_file_base_name}
247BASE_NAME = $(MODULE_NAME)
248MODULE_RELATIVE_DIR = ${module_relative_directory}
249MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory}
250
251MODULE_ENTRY_POINT = ${module_entry_point}
252ARCH_ENTRY_POINT = ${arch_entry_point}
253IMAGE_ENTRY_POINT = ${image_entry_point}
254
255${BEGIN}${module_extra_defines}
256${END}
257#
258# Build Configuration Macro Definition
259#
260ARCH = ${architecture}
261TOOLCHAIN = ${toolchain_tag}
262TOOLCHAIN_TAG = ${toolchain_tag}
263TARGET = ${build_target}
264
265#
266# Build Directory Macro Definition
267#
268# PLATFORM_BUILD_DIR = ${platform_build_directory}
269BUILD_DIR = ${platform_build_directory}
270BIN_DIR = $(BUILD_DIR)${separator}${architecture}
271LIB_DIR = $(BIN_DIR)
272MODULE_BUILD_DIR = ${module_build_directory}
273OUTPUT_DIR = ${module_output_directory}
274DEBUG_DIR = ${module_debug_directory}
275DEST_DIR_OUTPUT = $(OUTPUT_DIR)
276DEST_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}
289MAKE_FILE = ${makefile_path}
290
291#
292# Build Macro
293#
294${BEGIN}${file_macro}
295${END}
296
297COMMON_DEPS = ${BEGIN}${common_dependency_file} \\
298 ${END}
299
300#
301# Overridable Target Macro Definitions
302#
303FORCE_REBUILD = force_build
304INIT_TARGET = init
305PCH_TARGET =
306BC_TARGET = ${BEGIN}${backward_compatible_target} ${END}
307CODA_TARGET = ${BEGIN}${remaining_build_target} \\
308 ${END}
309
310#
311# Default target, which will build dependent libraries in addition to source files
312#
313
314all: mbuild
315
316
317#
318# Target used when called from platform makefile, which will bypass the build of dependent libraries
319#
320
321pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
322
323#
324# ModuleTarget
325#
326
327mbuild: $(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
333tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
334
335#
336# Phony target which is used to force executing commands for a target
337#
338force_build:
339\t-@
340
341#
342# Target to update the FD
343#
344
345fds: mbuild gen_fds
346
347#
348# Initialization target: print build information and create necessary directories
349#
350init: info dirs
351
352info:
353\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
354
355dirs:
356${BEGIN}\t-@${create_directory_command}\n${END}
357
358strdefs:
359\t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h
360
361#
362# GenLibsTarget
363#
364gen_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#
371gen_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#
384clean:
385\t${BEGIN}${clean_command}
386\t${END}
387
388#
389# clean all generated files
390#
391cleanall:
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#
399cleanlib:
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
2bcc713e 426 self.FileCache = {}
30fdf114
LG
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
64137027 454 # convert dependent libraries to build command
30fdf114
LG
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":
b36d134f 468 # EBC compiler always use "EfiStart" as entry point. Only applies to EdkII modules
30fdf114
LG
469 ImageEntryPoint = "EfiStart"
470 elif self._AutoGenObject.AutoGenVersion < 0x00010005:
b36d134f 471 # Edk modules use entry point specified in INF file
30fdf114
LG
472 ImageEntryPoint = ModuleEntryPoint
473 else:
b36d134f 474 # EdkII modules always use "_ModuleEntryPoint" as entry point
30fdf114
LG
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]
0d2711a6 499 if len(self.ResultFileList) == 0 and len(self._AutoGenObject.SourceFileList) <> 0:
30fdf114
LG
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
b36d134f 541 # Edk modules need <BaseName>StrDefs.h for string ID
30fdf114
LG
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,
79b74a03 620 self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList
30fdf114
LG
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 #
64137027 638 # Extract common files list in the dependency files
30fdf114
LG
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()
30fdf114
LG
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
2bcc713e
LG
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
30fdf114
LG
745 CurrentFileDependencyList = []
746 if F in DepDb:
747 CurrentFileDependencyList = DepDb[F]
30fdf114
LG
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
30fdf114 763 for Inc in IncludedFileList:
756ad8f8 764 Inc = Inc.strip()
30fdf114
LG
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:
2bcc713e
LG
773 # not known macro used in #include, always build the file by
774 # returning a empty dependency
775 self.FileCache[File] = []
776 return []
30fdf114 777 Inc = os.path.normpath(Inc)
2bcc713e
LG
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]:
30fdf114 788 continue
2bcc713e
LG
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
30fdf114 793 else:
2bcc713e
LG
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)))
30fdf114 803
2bcc713e
LG
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
30fdf114
LG
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#
821class 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#
829PLATFORM_NAME = ${platform_name}
830PLATFORM_GUID = ${platform_guid}
831PLATFORM_VERSION = ${platform_version}
832PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
833PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}
834PLATFORM_OUTPUT_DIR = ${platform_output_directory}
835
836#
837# Module Macro Definition
838#
839MODULE_NAME = ${module_name}
840MODULE_GUID = ${module_guid}
841MODULE_VERSION = ${module_version}
842MODULE_TYPE = ${module_type}
843MODULE_FILE = ${module_file}
844MODULE_FILE_BASE_NAME = ${module_file_base_name}
845BASE_NAME = $(MODULE_NAME)
846MODULE_RELATIVE_DIR = ${module_relative_directory}
847MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory}
848
849#
850# Build Configuration Macro Definition
851#
852ARCH = ${architecture}
853TOOLCHAIN = ${toolchain_tag}
854TOOLCHAIN_TAG = ${toolchain_tag}
855TARGET = ${build_target}
856
857#
858# Build Directory Macro Definition
859#
860# PLATFORM_BUILD_DIR = ${platform_build_directory}
861BUILD_DIR = ${platform_build_directory}
862BIN_DIR = $(BUILD_DIR)${separator}${architecture}
863LIB_DIR = $(BIN_DIR)
864MODULE_BUILD_DIR = ${module_build_directory}
865OUTPUT_DIR = ${module_output_directory}
866DEBUG_DIR = ${module_debug_directory}
867DEST_DIR_OUTPUT = $(OUTPUT_DIR)
868DEST_DIR_DEBUG = $(DEBUG_DIR)
869
870#
871# Tools definitions specific to this module
872#
873${BEGIN}${module_tool_definitions}
874${END}
875MAKE_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
889pbuild: init all
890
891
892#
893# ModuleTarget
894#
895
896mbuild: init all
897
898#
899# Build Target used in multi-thread build mode, which no init target is needed
900#
901
902tbuild: all
903
904#
905# Initialization target: print build information and create necessary directories
906#
907init:
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#
1000class PlatformMakefile(BuildFile):
1001 ## template used to generate the makefile for platform
1002 _TEMPLATE_ = TemplateString('''\
1003${makefile_header}
1004
1005#
1006# Platform Macro Definition
1007#
1008PLATFORM_NAME = ${platform_name}
1009PLATFORM_GUID = ${platform_guid}
1010PLATFORM_VERSION = ${platform_version}
1011PLATFORM_FILE = ${platform_file}
1012PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}
1013PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1014
1015#
1016# Build Configuration Macro Definition
1017#
1018TOOLCHAIN = ${toolchain_tag}
1019TOOLCHAIN_TAG = ${toolchain_tag}
1020TARGET = ${build_target}
1021
1022#
1023# Build Directory Macro Definition
1024#
1025BUILD_DIR = ${platform_build_directory}
1026FV_DIR = ${platform_build_directory}${separator}FV
1027
1028#
1029# Shell Command Macro
1030#
1031${BEGIN}${shell_command_code} = ${shell_command}
1032${END}
1033
1034MAKE = ${make_path}
1035MAKE_FILE = ${makefile_path}
1036
1037#
1038# Default target
1039#
1040all: init build_libraries build_modules
1041
1042#
1043# Initialization target: print build information and create necessary directories
1044#
1045init:
1046\t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
1047\t${BEGIN}-@${create_directory_command}
1048\t${END}
1049#
1050# library build target
1051#
1052libraries: init build_libraries
1053
1054#
1055# module build target
1056#
1057modules: init build_libraries build_modules
1058
1059#
1060# Build all libraries:
1061#
1062build_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#
1069build_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#
1076clean:
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#
1084cleanall:
1085${BEGIN}\t${cleanall_command}
1086${END}
1087
1088#
1089# Clean all library files
1090#
1091cleanlib:
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#
1198class TopLevelMakefile(BuildFile):
1199 ## template used to generate toplevel makefile
1200 _TEMPLATE_ = TemplateString('''\
1201${makefile_header}
1202
1203#
1204# Platform Macro Definition
1205#
1206PLATFORM_NAME = ${platform_name}
1207PLATFORM_GUID = ${platform_guid}
1208PLATFORM_VERSION = ${platform_version}
1209
1210#
1211# Build Configuration Macro Definition
1212#
1213TOOLCHAIN = ${toolchain_tag}
1214TOOLCHAIN_TAG = ${toolchain_tag}
1215TARGET = ${build_target}
1216
1217#
1218# Build Directory Macro Definition
1219#
1220BUILD_DIR = ${platform_build_directory}
1221FV_DIR = ${platform_build_directory}${separator}FV
1222
1223#
1224# Shell Command Macro
1225#
1226${BEGIN}${shell_command_code} = ${shell_command}
1227${END}
1228
1229MAKE = ${make_path}
1230MAKE_FILE = ${makefile_path}
1231
1232#
1233# Default target
1234#
1235all: modules fds
1236
1237#
1238# Initialization target: print build information and create necessary directories
1239#
1240init:
1241\t-@
1242\t${BEGIN}-@${create_directory_command}
1243\t${END}
1244#
1245# library build target
1246#
1247libraries: 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#
1254modules: 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#
1261fds: init
1262\t-@cd $(FV_DIR)
0d2711a6 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}
30fdf114
LG
1264
1265#
1266# run command for emulator platform only
1267#
1268run:
1269\tcd $(BUILD_DIR)${separator}IA32 && ".${separator}SecMain"
1270\tcd $(BUILD_DIR)
1271
1272#
1273# Clean intermediate files
1274#
1275clean:
1276${BEGIN}\t-@${sub_build_command} clean
1277${END}\t@cd $(BUILD_DIR)
1278
1279#
1280# Clean all generated files except to makefile
1281#
1282cleanall:
1283${BEGIN}\t${cleanall_command}
1284${END}
1285
1286#
1287# Clean all library files
1288#
1289cleanlib:
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
d40b2ee6
LG
1322 MacroList.append('"%s=%s"' % ("EFI_SOURCE", GlobalData.gEfiSource.replace('\\', '\\\\')))
1323 MacroList.append('"%s=%s"' % ("EDK_SOURCE", GlobalData.gEdkSource.replace('\\', '\\\\')))
2bcc713e
LG
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('\\', '\\\\')))
fd171542 1332 else:
1333 MacroList.append('"%s"' % MacroName)
30fdf114
LG
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,
4234283c 1379 "cap" : PlatformInfo.CapTargetList,
0d2711a6 1380 "extra_options" : ExtraOption,
30fdf114
LG
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.
1409if __name__ == '__main__':
1410 pass
1411