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