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