50bee0dbc114a71c84d32870737e1881ce4f2dab
[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 PACKAGE_RELATIVE_DIR = ${package_relative_directory}
251 MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory}
252
253 MODULE_ENTRY_POINT = ${module_entry_point}
254 ARCH_ENTRY_POINT = ${arch_entry_point}
255 IMAGE_ENTRY_POINT = ${image_entry_point}
256
257 ${BEGIN}${module_extra_defines}
258 ${END}
259 #
260 # Build Configuration Macro Definition
261 #
262 ARCH = ${architecture}
263 TOOLCHAIN = ${toolchain_tag}
264 TOOLCHAIN_TAG = ${toolchain_tag}
265 TARGET = ${build_target}
266
267 #
268 # Build Directory Macro Definition
269 #
270 # PLATFORM_BUILD_DIR = ${platform_build_directory}
271 BUILD_DIR = ${platform_build_directory}
272 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
273 LIB_DIR = $(BIN_DIR)
274 MODULE_BUILD_DIR = ${module_build_directory}
275 OUTPUT_DIR = ${module_output_directory}
276 DEBUG_DIR = ${module_debug_directory}
277 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
278 DEST_DIR_DEBUG = $(DEBUG_DIR)
279
280 #
281 # Shell Command Macro
282 #
283 ${BEGIN}${shell_command_code} = ${shell_command}
284 ${END}
285
286 #
287 # Tools definitions specific to this module
288 #
289 ${BEGIN}${module_tool_definitions}
290 ${END}
291 MAKE_FILE = ${makefile_path}
292
293 #
294 # Build Macro
295 #
296 ${BEGIN}${file_macro}
297 ${END}
298
299 COMMON_DEPS = ${BEGIN}${common_dependency_file} \\
300 ${END}
301
302 #
303 # Overridable Target Macro Definitions
304 #
305 FORCE_REBUILD = force_build
306 INIT_TARGET = init
307 PCH_TARGET =
308 BC_TARGET = ${BEGIN}${backward_compatible_target} ${END}
309 CODA_TARGET = ${BEGIN}${remaining_build_target} \\
310 ${END}
311
312 #
313 # Default target, which will build dependent libraries in addition to source files
314 #
315
316 all: mbuild
317
318
319 #
320 # Target used when called from platform makefile, which will bypass the build of dependent libraries
321 #
322
323 pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
324
325 #
326 # ModuleTarget
327 #
328
329 mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET)
330
331 #
332 # Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets
333 #
334
335 tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)
336
337 #
338 # Phony target which is used to force executing commands for a target
339 #
340 force_build:
341 \t-@
342
343 #
344 # Target to update the FD
345 #
346
347 fds: mbuild gen_fds
348
349 #
350 # Initialization target: print build information and create necessary directories
351 #
352 init: info dirs
353
354 info:
355 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
356
357 dirs:
358 ${BEGIN}\t-@${create_directory_command}\n${END}
359
360 strdefs:
361 \t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h
362
363 #
364 # GenLibsTarget
365 #
366 gen_libs:
367 \t${BEGIN}@"$(MAKE)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name}
368 \t${END}@cd $(MODULE_BUILD_DIR)
369
370 #
371 # Build Flash Device Image
372 #
373 gen_fds:
374 \t@"$(MAKE)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds
375 \t@cd $(MODULE_BUILD_DIR)
376
377 #
378 # Individual Object Build Targets
379 #
380 ${BEGIN}${file_build_target}
381 ${END}
382
383 #
384 # clean all intermediate files
385 #
386 clean:
387 \t${BEGIN}${clean_command}
388 \t${END}
389
390 #
391 # clean all generated files
392 #
393 cleanall:
394 ${BEGIN}\t${cleanall_command}
395 ${END}\t$(RM) *.pdb *.idb > NUL 2>&1
396 \t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi
397
398 #
399 # clean all dependent libraries built
400 #
401 cleanlib:
402 \t${BEGIN}-@${library_build_command} cleanall
403 \t${END}@cd $(MODULE_BUILD_DIR)\n\n''')
404
405 _FILE_MACRO_TEMPLATE = TemplateString("${macro_name} = ${BEGIN} \\\n ${source_file}${END}\n")
406 _BUILD_TARGET_TEMPLATE = TemplateString("${BEGIN}${target} : ${deps}\n${END}\t${cmd}\n")
407
408 ## Constructor of ModuleMakefile
409 #
410 # @param ModuleAutoGen Object of ModuleAutoGen class
411 #
412 def __init__(self, ModuleAutoGen):
413 BuildFile.__init__(self, ModuleAutoGen)
414 self.PlatformInfo = self._AutoGenObject.PlatformInfo
415
416 self.ResultFileList = []
417 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
418
419 self.SourceFileDatabase = {} # {file type : file path}
420 self.DestFileDatabase = {} # {file type : file path}
421 self.FileBuildTargetList = [] # [(src, target string)]
422 self.BuildTargetList = [] # [target string]
423 self.PendingBuildTargetList = [] # [FileBuildRule objects]
424 self.CommonFileDependency = []
425 self.FileListMacros = {}
426 self.ListFileMacros = {}
427
428 self.FileCache = {}
429 self.FileDependency = []
430 self.LibraryBuildCommandList = []
431 self.LibraryFileList = []
432 self.LibraryMakefileList = []
433 self.LibraryBuildDirectoryList = []
434 self.SystemLibraryList = []
435 self.Macros = sdict()
436 self.Macros["OUTPUT_DIR" ] = self._AutoGenObject.Macros["OUTPUT_DIR"]
437 self.Macros["DEBUG_DIR" ] = self._AutoGenObject.Macros["DEBUG_DIR"]
438 self.Macros["MODULE_BUILD_DIR"] = self._AutoGenObject.Macros["MODULE_BUILD_DIR"]
439 self.Macros["BIN_DIR" ] = self._AutoGenObject.Macros["BIN_DIR"]
440 self.Macros["BUILD_DIR" ] = self._AutoGenObject.Macros["BUILD_DIR"]
441 self.Macros["WORKSPACE" ] = self._AutoGenObject.Macros["WORKSPACE"]
442
443 # Compose a dict object containing information used to do replacement in template
444 def _CreateTemplateDict(self):
445 if self._FileType not in self._SEP_:
446 EdkLogger.error("build", PARAMETER_INVALID, "Invalid Makefile type [%s]" % self._FileType,
447 ExtraData="[%s]" % str(self._AutoGenObject))
448 Separator = self._SEP_[self._FileType]
449
450 # break build if no source files and binary files are found
451 if len(self._AutoGenObject.SourceFileList) == 0 and len(self._AutoGenObject.BinaryFileList) == 0:
452 EdkLogger.error("build", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]"
453 % (self._AutoGenObject.BuildTarget, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch),
454 ExtraData="[%s]" % str(self._AutoGenObject))
455
456 # convert dependent libraries to build command
457 self.ProcessDependentLibrary()
458 if len(self._AutoGenObject.Module.ModuleEntryPointList) > 0:
459 ModuleEntryPoint = self._AutoGenObject.Module.ModuleEntryPointList[0]
460 else:
461 ModuleEntryPoint = "_ModuleEntryPoint"
462
463 # Intel EBC compiler enforces EfiMain
464 if self._AutoGenObject.AutoGenVersion < 0x00010005 and self._AutoGenObject.Arch == "EBC":
465 ArchEntryPoint = "EfiMain"
466 else:
467 ArchEntryPoint = ModuleEntryPoint
468
469 if self._AutoGenObject.Arch == "EBC":
470 # EBC compiler always use "EfiStart" as entry point. Only applies to EdkII modules
471 ImageEntryPoint = "EfiStart"
472 elif self._AutoGenObject.AutoGenVersion < 0x00010005:
473 # Edk modules use entry point specified in INF file
474 ImageEntryPoint = ModuleEntryPoint
475 else:
476 # EdkII modules always use "_ModuleEntryPoint" as entry point
477 ImageEntryPoint = "_ModuleEntryPoint"
478
479 # tools definitions
480 ToolsDef = []
481 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
482 for Tool in self._AutoGenObject.BuildOption:
483 for Attr in self._AutoGenObject.BuildOption[Tool]:
484 Value = self._AutoGenObject.BuildOption[Tool][Attr]
485 if Attr == "FAMILY":
486 continue
487 elif Attr == "PATH":
488 ToolsDef.append("%s = %s" % (Tool, Value))
489 else:
490 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
491 if Tool == "MAKE":
492 continue
493 # Remove duplicated include path, if any
494 if Attr == "FLAGS":
495 Value = RemoveDupOption(Value, IncPrefix, self._AutoGenObject.IncludePathList)
496 ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
497 ToolsDef.append("")
498
499 # convert source files and binary files to build targets
500 self.ResultFileList = [str(T.Target) for T in self._AutoGenObject.CodaTargetList]
501 if len(self.ResultFileList) == 0 and len(self._AutoGenObject.SourceFileList) <> 0:
502 EdkLogger.error("build", AUTOGEN_ERROR, "Nothing to build",
503 ExtraData="[%s]" % str(self._AutoGenObject))
504
505 self.ProcessBuildTargetList()
506
507 # Generate macros used to represent input files
508 FileMacroList = [] # macro name = file list
509 for FileListMacro in self.FileListMacros:
510 FileMacro = self._FILE_MACRO_TEMPLATE.Replace(
511 {
512 "macro_name" : FileListMacro,
513 "source_file" : self.FileListMacros[FileListMacro]
514 }
515 )
516 FileMacroList.append(FileMacro)
517
518 # INC_LIST is special
519 FileMacro = ""
520 IncludePathList = []
521 for P in self._AutoGenObject.IncludePathList:
522 IncludePathList.append(IncPrefix+self.PlaceMacro(P, self.Macros))
523 if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:
524 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix+P)
525 FileMacro += self._FILE_MACRO_TEMPLATE.Replace(
526 {
527 "macro_name" : "INC",
528 "source_file" : IncludePathList
529 }
530 )
531 FileMacroList.append(FileMacro)
532
533 # Generate macros used to represent files containing list of input files
534 for ListFileMacro in self.ListFileMacros:
535 ListFileName = os.path.join(self._AutoGenObject.OutputDir, "%s.lst" % ListFileMacro.lower()[:len(ListFileMacro)-5])
536 FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))
537 SaveFileOnChange(
538 ListFileName,
539 "\n".join(self.ListFileMacros[ListFileMacro]),
540 False
541 )
542
543 # Edk modules need <BaseName>StrDefs.h for string ID
544 #if self._AutoGenObject.AutoGenVersion < 0x00010005 and len(self._AutoGenObject.UnicodeFileList) > 0:
545 # BcTargetList = ['strdefs']
546 #else:
547 # BcTargetList = []
548 BcTargetList = []
549
550 MakefileName = self._FILE_NAME_[self._FileType]
551 LibraryMakeCommandList = []
552 for D in self.LibraryBuildDirectoryList:
553 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)}
554 LibraryMakeCommandList.append(Command)
555
556 package_rel_dir = self._AutoGenObject.SourceDir
557 if os.sep in package_rel_dir:
558 package_rel_dir = package_rel_dir[package_rel_dir.index(os.sep) + 1:]
559
560 MakefileTemplateDict = {
561 "makefile_header" : self._FILE_HEADER_[self._FileType],
562 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
563 "makefile_name" : MakefileName,
564 "platform_name" : self.PlatformInfo.Name,
565 "platform_guid" : self.PlatformInfo.Guid,
566 "platform_version" : self.PlatformInfo.Version,
567 "platform_relative_directory": self.PlatformInfo.SourceDir,
568 "platform_output_directory" : self.PlatformInfo.OutputDir,
569
570 "module_name" : self._AutoGenObject.Name,
571 "module_guid" : self._AutoGenObject.Guid,
572 "module_version" : self._AutoGenObject.Version,
573 "module_type" : self._AutoGenObject.ModuleType,
574 "module_file" : self._AutoGenObject.MetaFile.Name,
575 "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName,
576 "module_relative_directory" : self._AutoGenObject.SourceDir,
577 "package_relative_directory": package_rel_dir,
578 "module_extra_defines" : ["%s = %s" % (k, v) for k, v in self._AutoGenObject.Module.Defines.iteritems()],
579
580 "architecture" : self._AutoGenObject.Arch,
581 "toolchain_tag" : self._AutoGenObject.ToolChain,
582 "build_target" : self._AutoGenObject.BuildTarget,
583
584 "platform_build_directory" : self.PlatformInfo.BuildDir,
585 "module_build_directory" : self._AutoGenObject.BuildDir,
586 "module_output_directory" : self._AutoGenObject.OutputDir,
587 "module_debug_directory" : self._AutoGenObject.DebugDir,
588
589 "separator" : Separator,
590 "module_tool_definitions" : ToolsDef,
591
592 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),
593 "shell_command" : self._SHELL_CMD_[self._FileType].values(),
594
595 "module_entry_point" : ModuleEntryPoint,
596 "image_entry_point" : ImageEntryPoint,
597 "arch_entry_point" : ArchEntryPoint,
598 "remaining_build_target" : self.ResultFileList,
599 "common_dependency_file" : self.CommonFileDependency,
600 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
601 "clean_command" : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]),
602 "cleanall_command" : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]),
603 "dependent_library_build_directory" : self.LibraryBuildDirectoryList,
604 "library_build_command" : LibraryMakeCommandList,
605 "file_macro" : FileMacroList,
606 "file_build_target" : self.BuildTargetList,
607 "backward_compatible_target": BcTargetList,
608 }
609
610 return MakefileTemplateDict
611
612 def ProcessBuildTargetList(self):
613 #
614 # Search dependency file list for each source file
615 #
616 ForceIncludedFile = []
617 for File in self._AutoGenObject.AutoGenFileList:
618 if File.Ext == '.h':
619 ForceIncludedFile.append(File)
620 SourceFileList = []
621 for Target in self._AutoGenObject.IntroTargetList:
622 SourceFileList.extend(Target.Inputs)
623
624 self.FileDependency = self.GetFileDependency(
625 SourceFileList,
626 ForceIncludedFile,
627 self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList
628 )
629 DepSet = None
630 for File in self.FileDependency:
631 if not self.FileDependency[File]:
632 self.FileDependency[File] = ['$(FORCE_REBUILD)']
633 continue
634 # skip non-C files
635 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
636 continue
637 elif DepSet == None:
638 DepSet = set(self.FileDependency[File])
639 else:
640 DepSet &= set(self.FileDependency[File])
641 # in case nothing in SourceFileList
642 if DepSet == None:
643 DepSet = set()
644 #
645 # Extract common files list in the dependency files
646 #
647 for File in DepSet:
648 self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros))
649
650 for File in self.FileDependency:
651 # skip non-C files
652 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
653 continue
654 NewDepSet = set(self.FileDependency[File])
655 NewDepSet -= DepSet
656 self.FileDependency[File] = ["$(COMMON_DEPS)"] + list(NewDepSet)
657
658 # Convert target description object to target string in makefile
659 for Type in self._AutoGenObject.Targets:
660 for T in self._AutoGenObject.Targets[Type]:
661 # Generate related macros if needed
662 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
663 self.FileListMacros[T.FileListMacro] = []
664 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:
665 self.ListFileMacros[T.ListFileMacro] = []
666 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:
667 self.ListFileMacros[T.IncListFileMacro] = []
668
669 Deps = []
670 # Add force-dependencies
671 for Dep in T.Dependencies:
672 Deps.append(self.PlaceMacro(str(Dep), self.Macros))
673 # Add inclusion-dependencies
674 if len(T.Inputs) == 1 and T.Inputs[0] in self.FileDependency:
675 for F in self.FileDependency[T.Inputs[0]]:
676 Deps.append(self.PlaceMacro(str(F), self.Macros))
677 # Add source-dependencies
678 for F in T.Inputs:
679 NewFile = self.PlaceMacro(str(F), self.Macros)
680 # In order to use file list macro as dependency
681 if T.GenListFile:
682 self.ListFileMacros[T.ListFileMacro].append(str(F))
683 self.FileListMacros[T.FileListMacro].append(NewFile)
684 elif T.GenFileListMacro:
685 self.FileListMacros[T.FileListMacro].append(NewFile)
686 else:
687 Deps.append(NewFile)
688
689 # Use file list macro as dependency
690 if T.GenFileListMacro:
691 Deps.append("$(%s)" % T.FileListMacro)
692
693 TargetDict = {
694 "target" : self.PlaceMacro(T.Target.Path, self.Macros),
695 "cmd" : "\n\t".join(T.Commands),
696 "deps" : Deps
697 }
698 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
699
700 ## For creating makefile targets for dependent libraries
701 def ProcessDependentLibrary(self):
702 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
703 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
704
705 ## Return a list containing source file's dependencies
706 #
707 # @param FileList The list of source files
708 # @param ForceInculeList The list of files which will be included forcely
709 # @param SearchPathList The list of search path
710 #
711 # @retval dict The mapping between source file path and its dependencies
712 #
713 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
714 Dependency = {}
715 for F in FileList:
716 Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)
717 return Dependency
718
719 ## Find dependencies for one source file
720 #
721 # By searching recursively "#include" directive in file, find out all the
722 # files needed by given source file. The dependecies will be only searched
723 # in given search path list.
724 #
725 # @param File The source file
726 # @param ForceInculeList The list of files which will be included forcely
727 # @param SearchPathList The list of search path
728 #
729 # @retval list The list of files the given source file depends on
730 #
731 def GetDependencyList(self, File, ForceList, SearchPathList):
732 EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File)
733 FileStack = [File] + ForceList
734 DependencySet = set()
735
736 if self._AutoGenObject.Arch not in gDependencyDatabase:
737 gDependencyDatabase[self._AutoGenObject.Arch] = {}
738 DepDb = gDependencyDatabase[self._AutoGenObject.Arch]
739
740 while len(FileStack) > 0:
741 F = FileStack.pop()
742
743 FullPathDependList = []
744 if F in self.FileCache:
745 for CacheFile in self.FileCache[F]:
746 FullPathDependList.append(CacheFile)
747 if CacheFile not in DependencySet:
748 FileStack.append(CacheFile)
749 DependencySet.update(FullPathDependList)
750 continue
751
752 CurrentFileDependencyList = []
753 if F in DepDb:
754 CurrentFileDependencyList = DepDb[F]
755 else:
756 try:
757 Fd = open(F.Path, 'r')
758 except BaseException, X:
759 EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path+"\n\t"+str(X))
760
761 FileContent = Fd.read()
762 Fd.close()
763 if len(FileContent) == 0:
764 continue
765
766 if FileContent[0] == 0xff or FileContent[0] == 0xfe:
767 FileContent = unicode(FileContent, "utf-16")
768 IncludedFileList = gIncludePattern.findall(FileContent)
769
770 for Inc in IncludedFileList:
771 Inc = Inc.strip()
772 # if there's macro used to reference header file, expand it
773 HeaderList = gMacroPattern.findall(Inc)
774 if len(HeaderList) == 1 and len(HeaderList[0]) == 2:
775 HeaderType = HeaderList[0][0]
776 HeaderKey = HeaderList[0][1]
777 if HeaderType in gIncludeMacroConversion:
778 Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey}
779 else:
780 # not known macro used in #include, always build the file by
781 # returning a empty dependency
782 self.FileCache[File] = []
783 return []
784 Inc = os.path.normpath(Inc)
785 CurrentFileDependencyList.append(Inc)
786 DepDb[F] = CurrentFileDependencyList
787
788 CurrentFilePath = F.Dir
789 PathList = [CurrentFilePath] + SearchPathList
790 for Inc in CurrentFileDependencyList:
791 for SearchPath in PathList:
792 FilePath = os.path.join(SearchPath, Inc)
793 if FilePath in gIsFileMap:
794 if not gIsFileMap[FilePath]:
795 continue
796 # If isfile is called too many times, the performance is slow down.
797 elif not os.path.isfile(FilePath):
798 gIsFileMap[FilePath] = False
799 continue
800 else:
801 gIsFileMap[FilePath] = True
802 FilePath = PathClass(FilePath)
803 FullPathDependList.append(FilePath)
804 if FilePath not in DependencySet:
805 FileStack.append(FilePath)
806 break
807 else:
808 EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\
809 "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList)))
810
811 self.FileCache[F] = FullPathDependList
812 DependencySet.update(FullPathDependList)
813
814 DependencySet.update(ForceList)
815 if File in DependencySet:
816 DependencySet.remove(File)
817 DependencyList = list(DependencySet) # remove duplicate ones
818
819 return DependencyList
820
821 _TemplateDict = property(_CreateTemplateDict)
822
823 ## CustomMakefile class
824 #
825 # This class encapsules makefie and its generation for module. It uses template to generate
826 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
827 #
828 class CustomMakefile(BuildFile):
829 ## template used to generate the makefile for module with custom makefile
830 _TEMPLATE_ = TemplateString('''\
831 ${makefile_header}
832
833 #
834 # Platform Macro Definition
835 #
836 PLATFORM_NAME = ${platform_name}
837 PLATFORM_GUID = ${platform_guid}
838 PLATFORM_VERSION = ${platform_version}
839 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
840 PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}
841 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
842
843 #
844 # Module Macro Definition
845 #
846 MODULE_NAME = ${module_name}
847 MODULE_GUID = ${module_guid}
848 MODULE_VERSION = ${module_version}
849 MODULE_TYPE = ${module_type}
850 MODULE_FILE = ${module_file}
851 MODULE_FILE_BASE_NAME = ${module_file_base_name}
852 BASE_NAME = $(MODULE_NAME)
853 MODULE_RELATIVE_DIR = ${module_relative_directory}
854 MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory}
855
856 #
857 # Build Configuration Macro Definition
858 #
859 ARCH = ${architecture}
860 TOOLCHAIN = ${toolchain_tag}
861 TOOLCHAIN_TAG = ${toolchain_tag}
862 TARGET = ${build_target}
863
864 #
865 # Build Directory Macro Definition
866 #
867 # PLATFORM_BUILD_DIR = ${platform_build_directory}
868 BUILD_DIR = ${platform_build_directory}
869 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
870 LIB_DIR = $(BIN_DIR)
871 MODULE_BUILD_DIR = ${module_build_directory}
872 OUTPUT_DIR = ${module_output_directory}
873 DEBUG_DIR = ${module_debug_directory}
874 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
875 DEST_DIR_DEBUG = $(DEBUG_DIR)
876
877 #
878 # Tools definitions specific to this module
879 #
880 ${BEGIN}${module_tool_definitions}
881 ${END}
882 MAKE_FILE = ${makefile_path}
883
884 #
885 # Shell Command Macro
886 #
887 ${BEGIN}${shell_command_code} = ${shell_command}
888 ${END}
889
890 ${custom_makefile_content}
891
892 #
893 # Target used when called from platform makefile, which will bypass the build of dependent libraries
894 #
895
896 pbuild: init all
897
898
899 #
900 # ModuleTarget
901 #
902
903 mbuild: init all
904
905 #
906 # Build Target used in multi-thread build mode, which no init target is needed
907 #
908
909 tbuild: all
910
911 #
912 # Initialization target: print build information and create necessary directories
913 #
914 init:
915 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
916 ${BEGIN}\t-@${create_directory_command}\n${END}\
917
918 ''')
919
920 ## Constructor of CustomMakefile
921 #
922 # @param ModuleAutoGen Object of ModuleAutoGen class
923 #
924 def __init__(self, ModuleAutoGen):
925 BuildFile.__init__(self, ModuleAutoGen)
926 self.PlatformInfo = self._AutoGenObject.PlatformInfo
927 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
928
929 # Compose a dict object containing information used to do replacement in template
930 def _CreateTemplateDict(self):
931 Separator = self._SEP_[self._FileType]
932 if self._FileType not in self._AutoGenObject.CustomMakefile:
933 EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType,
934 ExtraData="[%s]" % str(self._AutoGenObject))
935 MakefilePath = os.path.join(
936 self._AutoGenObject.WorkspaceDir,
937 self._AutoGenObject.CustomMakefile[self._FileType]
938 )
939 try:
940 CustomMakefile = open(MakefilePath, 'r').read()
941 except:
942 EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(self._AutoGenObject),
943 ExtraData=self._AutoGenObject.CustomMakefile[self._FileType])
944
945 # tools definitions
946 ToolsDef = []
947 for Tool in self._AutoGenObject.BuildOption:
948 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
949 if Tool == "MAKE":
950 continue
951 for Attr in self._AutoGenObject.BuildOption[Tool]:
952 if Attr == "FAMILY":
953 continue
954 elif Attr == "PATH":
955 ToolsDef.append("%s = %s" % (Tool, self._AutoGenObject.BuildOption[Tool][Attr]))
956 else:
957 ToolsDef.append("%s_%s = %s" % (Tool, Attr, self._AutoGenObject.BuildOption[Tool][Attr]))
958 ToolsDef.append("")
959
960 MakefileName = self._FILE_NAME_[self._FileType]
961 MakefileTemplateDict = {
962 "makefile_header" : self._FILE_HEADER_[self._FileType],
963 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
964 "platform_name" : self.PlatformInfo.Name,
965 "platform_guid" : self.PlatformInfo.Guid,
966 "platform_version" : self.PlatformInfo.Version,
967 "platform_relative_directory": self.PlatformInfo.SourceDir,
968 "platform_output_directory" : self.PlatformInfo.OutputDir,
969
970 "module_name" : self._AutoGenObject.Name,
971 "module_guid" : self._AutoGenObject.Guid,
972 "module_version" : self._AutoGenObject.Version,
973 "module_type" : self._AutoGenObject.ModuleType,
974 "module_file" : self._AutoGenObject.MetaFile,
975 "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName,
976 "module_relative_directory" : self._AutoGenObject.SourceDir,
977
978 "architecture" : self._AutoGenObject.Arch,
979 "toolchain_tag" : self._AutoGenObject.ToolChain,
980 "build_target" : self._AutoGenObject.BuildTarget,
981
982 "platform_build_directory" : self.PlatformInfo.BuildDir,
983 "module_build_directory" : self._AutoGenObject.BuildDir,
984 "module_output_directory" : self._AutoGenObject.OutputDir,
985 "module_debug_directory" : self._AutoGenObject.DebugDir,
986
987 "separator" : Separator,
988 "module_tool_definitions" : ToolsDef,
989
990 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),
991 "shell_command" : self._SHELL_CMD_[self._FileType].values(),
992
993 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
994 "custom_makefile_content" : CustomMakefile
995 }
996
997 return MakefileTemplateDict
998
999 _TemplateDict = property(_CreateTemplateDict)
1000
1001 ## PlatformMakefile class
1002 #
1003 # This class encapsules makefie and its generation for platform. It uses
1004 # template to generate the content of makefile. The content of makefile will be
1005 # got from PlatformAutoGen object.
1006 #
1007 class PlatformMakefile(BuildFile):
1008 ## template used to generate the makefile for platform
1009 _TEMPLATE_ = TemplateString('''\
1010 ${makefile_header}
1011
1012 #
1013 # Platform Macro Definition
1014 #
1015 PLATFORM_NAME = ${platform_name}
1016 PLATFORM_GUID = ${platform_guid}
1017 PLATFORM_VERSION = ${platform_version}
1018 PLATFORM_FILE = ${platform_file}
1019 PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}
1020 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1021
1022 #
1023 # Build Configuration Macro Definition
1024 #
1025 TOOLCHAIN = ${toolchain_tag}
1026 TOOLCHAIN_TAG = ${toolchain_tag}
1027 TARGET = ${build_target}
1028
1029 #
1030 # Build Directory Macro Definition
1031 #
1032 BUILD_DIR = ${platform_build_directory}
1033 FV_DIR = ${platform_build_directory}${separator}FV
1034
1035 #
1036 # Shell Command Macro
1037 #
1038 ${BEGIN}${shell_command_code} = ${shell_command}
1039 ${END}
1040
1041 MAKE = ${make_path}
1042 MAKE_FILE = ${makefile_path}
1043
1044 #
1045 # Default target
1046 #
1047 all: init build_libraries build_modules
1048
1049 #
1050 # Initialization target: print build information and create necessary directories
1051 #
1052 init:
1053 \t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
1054 \t${BEGIN}-@${create_directory_command}
1055 \t${END}
1056 #
1057 # library build target
1058 #
1059 libraries: init build_libraries
1060
1061 #
1062 # module build target
1063 #
1064 modules: init build_libraries build_modules
1065
1066 #
1067 # Build all libraries:
1068 #
1069 build_libraries:
1070 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
1071 ${END}\t@cd $(BUILD_DIR)
1072
1073 #
1074 # Build all modules:
1075 #
1076 build_modules:
1077 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
1078 ${END}\t@cd $(BUILD_DIR)
1079
1080 #
1081 # Clean intermediate files
1082 #
1083 clean:
1084 \t${BEGIN}-@${library_build_command} clean
1085 \t${END}${BEGIN}-@${module_build_command} clean
1086 \t${END}@cd $(BUILD_DIR)
1087
1088 #
1089 # Clean all generated files except to makefile
1090 #
1091 cleanall:
1092 ${BEGIN}\t${cleanall_command}
1093 ${END}
1094
1095 #
1096 # Clean all library files
1097 #
1098 cleanlib:
1099 \t${BEGIN}-@${library_build_command} cleanall
1100 \t${END}@cd $(BUILD_DIR)\n
1101 ''')
1102
1103 ## Constructor of PlatformMakefile
1104 #
1105 # @param ModuleAutoGen Object of PlatformAutoGen class
1106 #
1107 def __init__(self, PlatformAutoGen):
1108 BuildFile.__init__(self, PlatformAutoGen)
1109 self.ModuleBuildCommandList = []
1110 self.ModuleMakefileList = []
1111 self.IntermediateDirectoryList = []
1112 self.ModuleBuildDirectoryList = []
1113 self.LibraryBuildDirectoryList = []
1114 self.LibraryMakeCommandList = []
1115
1116 # Compose a dict object containing information used to do replacement in template
1117 def _CreateTemplateDict(self):
1118 Separator = self._SEP_[self._FileType]
1119
1120 PlatformInfo = self._AutoGenObject
1121 if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:
1122 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
1123 ExtraData="[%s]" % str(self._AutoGenObject))
1124
1125 self.IntermediateDirectoryList = ["$(BUILD_DIR)"]
1126 self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()
1127 self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()
1128
1129 MakefileName = self._FILE_NAME_[self._FileType]
1130 LibraryMakefileList = []
1131 LibraryMakeCommandList = []
1132 for D in self.LibraryBuildDirectoryList:
1133 D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})
1134 Makefile = os.path.join(D, MakefileName)
1135 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
1136 LibraryMakefileList.append(Makefile)
1137 LibraryMakeCommandList.append(Command)
1138 self.LibraryMakeCommandList = LibraryMakeCommandList
1139
1140 ModuleMakefileList = []
1141 ModuleMakeCommandList = []
1142 for D in self.ModuleBuildDirectoryList:
1143 D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})
1144 Makefile = os.path.join(D, MakefileName)
1145 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
1146 ModuleMakefileList.append(Makefile)
1147 ModuleMakeCommandList.append(Command)
1148
1149 MakefileTemplateDict = {
1150 "makefile_header" : self._FILE_HEADER_[self._FileType],
1151 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),
1152 "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"],
1153 "makefile_name" : MakefileName,
1154 "platform_name" : PlatformInfo.Name,
1155 "platform_guid" : PlatformInfo.Guid,
1156 "platform_version" : PlatformInfo.Version,
1157 "platform_file" : self._AutoGenObject.MetaFile,
1158 "platform_relative_directory": PlatformInfo.SourceDir,
1159 "platform_output_directory" : PlatformInfo.OutputDir,
1160 "platform_build_directory" : PlatformInfo.BuildDir,
1161
1162 "toolchain_tag" : PlatformInfo.ToolChain,
1163 "build_target" : PlatformInfo.BuildTarget,
1164 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),
1165 "shell_command" : self._SHELL_CMD_[self._FileType].values(),
1166 "build_architecture_list" : self._AutoGenObject.Arch,
1167 "architecture" : self._AutoGenObject.Arch,
1168 "separator" : Separator,
1169 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1170 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1171 "library_makefile_list" : LibraryMakefileList,
1172 "module_makefile_list" : ModuleMakefileList,
1173 "library_build_command" : LibraryMakeCommandList,
1174 "module_build_command" : ModuleMakeCommandList,
1175 }
1176
1177 return MakefileTemplateDict
1178
1179 ## Get the root directory list for intermediate files of all modules build
1180 #
1181 # @retval list The list of directory
1182 #
1183 def GetModuleBuildDirectoryList(self):
1184 DirList = []
1185 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1186 if not ModuleAutoGen.IsBinaryModule:
1187 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1188 return DirList
1189
1190 ## Get the root directory list for intermediate files of all libraries build
1191 #
1192 # @retval list The list of directory
1193 #
1194 def GetLibraryBuildDirectoryList(self):
1195 DirList = []
1196 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1197 if not LibraryAutoGen.IsBinaryModule:
1198 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1199 return DirList
1200
1201 _TemplateDict = property(_CreateTemplateDict)
1202
1203 ## TopLevelMakefile class
1204 #
1205 # This class encapsules makefie and its generation for entrance makefile. It
1206 # uses template to generate the content of makefile. The content of makefile
1207 # will be got from WorkspaceAutoGen object.
1208 #
1209 class TopLevelMakefile(BuildFile):
1210 ## template used to generate toplevel makefile
1211 _TEMPLATE_ = TemplateString('''${BEGIN}\tGenFds -f ${fdf_file} --conf=${conf_directory} -o ${platform_build_directory} -t ${toolchain_tag} -b ${build_target} -p ${active_platform} -a ${build_architecture_list} ${extra_options}${END}${BEGIN} -r ${fd} ${END}${BEGIN} -i ${fv} ${END}${BEGIN} -C ${cap} ${END}${BEGIN} -D ${macro} ${END}''')
1212
1213 ## Constructor of TopLevelMakefile
1214 #
1215 # @param Workspace Object of WorkspaceAutoGen class
1216 #
1217 def __init__(self, Workspace):
1218 BuildFile.__init__(self, Workspace)
1219 self.IntermediateDirectoryList = []
1220
1221 # Compose a dict object containing information used to do replacement in template
1222 def _CreateTemplateDict(self):
1223 Separator = self._SEP_[self._FileType]
1224
1225 # any platform autogen object is ok because we just need common information
1226 PlatformInfo = self._AutoGenObject
1227
1228 if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:
1229 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
1230 ExtraData="[%s]" % str(self._AutoGenObject))
1231
1232 for Arch in PlatformInfo.ArchList:
1233 self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch]))
1234 self.IntermediateDirectoryList.append("$(FV_DIR)")
1235
1236 # TRICK: for not generating GenFds call in makefile if no FDF file
1237 MacroList = []
1238 if PlatformInfo.FdfFile != None and PlatformInfo.FdfFile != "":
1239 FdfFileList = [PlatformInfo.FdfFile]
1240 # macros passed to GenFds
1241 MacroList.append('"%s=%s"' % ("EFI_SOURCE", GlobalData.gEfiSource.replace('\\', '\\\\')))
1242 MacroList.append('"%s=%s"' % ("EDK_SOURCE", GlobalData.gEdkSource.replace('\\', '\\\\')))
1243 MacroDict = {}
1244 MacroDict.update(GlobalData.gGlobalDefines)
1245 MacroDict.update(GlobalData.gCommandLineDefines)
1246 MacroDict.pop("EFI_SOURCE", "dummy")
1247 MacroDict.pop("EDK_SOURCE", "dummy")
1248 for MacroName in MacroDict:
1249 if MacroDict[MacroName] != "":
1250 MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))
1251 else:
1252 MacroList.append('"%s"' % MacroName)
1253 else:
1254 FdfFileList = []
1255
1256 # pass extra common options to external program called in makefile, currently GenFds.exe
1257 ExtraOption = ''
1258 LogLevel = EdkLogger.GetLevel()
1259 if LogLevel == EdkLogger.VERBOSE:
1260 ExtraOption += " -v"
1261 elif LogLevel <= EdkLogger.DEBUG_9:
1262 ExtraOption += " -d %d" % (LogLevel - 1)
1263 elif LogLevel == EdkLogger.QUIET:
1264 ExtraOption += " -q"
1265
1266 if GlobalData.gCaseInsensitive:
1267 ExtraOption += " -c"
1268
1269 if GlobalData.gIgnoreSource:
1270 ExtraOption += " --ignore-sources"
1271
1272 MakefileName = self._FILE_NAME_[self._FileType]
1273 SubBuildCommandList = []
1274 for A in PlatformInfo.ArchList:
1275 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)}
1276 SubBuildCommandList.append(Command)
1277
1278 MakefileTemplateDict = {
1279 "makefile_header" : self._FILE_HEADER_[self._FileType],
1280 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),
1281 "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"],
1282 "platform_name" : PlatformInfo.Name,
1283 "platform_guid" : PlatformInfo.Guid,
1284 "platform_version" : PlatformInfo.Version,
1285 "platform_build_directory" : PlatformInfo.BuildDir,
1286 "conf_directory" : GlobalData.gConfDirectory,
1287
1288 "toolchain_tag" : PlatformInfo.ToolChain,
1289 "build_target" : PlatformInfo.BuildTarget,
1290 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),
1291 "shell_command" : self._SHELL_CMD_[self._FileType].values(),
1292 'arch' : list(PlatformInfo.ArchList),
1293 "build_architecture_list" : ','.join(PlatformInfo.ArchList),
1294 "separator" : Separator,
1295 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1296 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1297 "sub_build_command" : SubBuildCommandList,
1298 "fdf_file" : FdfFileList,
1299 "active_platform" : str(PlatformInfo),
1300 "fd" : PlatformInfo.FdTargetList,
1301 "fv" : PlatformInfo.FvTargetList,
1302 "cap" : PlatformInfo.CapTargetList,
1303 "extra_options" : ExtraOption,
1304 "macro" : MacroList,
1305 }
1306
1307 return MakefileTemplateDict
1308
1309 ## Get the root directory list for intermediate files of all modules build
1310 #
1311 # @retval list The list of directory
1312 #
1313 def GetModuleBuildDirectoryList(self):
1314 DirList = []
1315 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1316 if not ModuleAutoGen.IsBinaryModule:
1317 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1318 return DirList
1319
1320 ## Get the root directory list for intermediate files of all libraries build
1321 #
1322 # @retval list The list of directory
1323 #
1324 def GetLibraryBuildDirectoryList(self):
1325 DirList = []
1326 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1327 if not LibraryAutoGen.IsBinaryModule:
1328 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1329 return DirList
1330
1331 _TemplateDict = property(_CreateTemplateDict)
1332
1333 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1334 if __name__ == '__main__':
1335 pass
1336