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