]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/GenMake.py
BaseTools: Add error handling for current_dir is not exist
[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 - 2016, 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 from Common.MultipleWorkspace import MultipleWorkspace as mws
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 = ${platform_dir}
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 = ${module_dir}
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 for k, v in self._AutoGenObject.Module.Defines.iteritems():
481 if k not in self._AutoGenObject.Macros.keys():
482 self._AutoGenObject.Macros[k] = v
483
484 if 'MODULE_ENTRY_POINT' not in self._AutoGenObject.Macros.keys():
485 self._AutoGenObject.Macros['MODULE_ENTRY_POINT'] = ModuleEntryPoint
486 if 'ARCH_ENTRY_POINT' not in self._AutoGenObject.Macros.keys():
487 self._AutoGenObject.Macros['ARCH_ENTRY_POINT'] = ArchEntryPoint
488 if 'IMAGE_ENTRY_POINT' not in self._AutoGenObject.Macros.keys():
489 self._AutoGenObject.Macros['IMAGE_ENTRY_POINT'] = ImageEntryPoint
490
491 # tools definitions
492 ToolsDef = []
493 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
494 for Tool in self._AutoGenObject.BuildOption:
495 for Attr in self._AutoGenObject.BuildOption[Tool]:
496 Value = self._AutoGenObject.BuildOption[Tool][Attr]
497 if Attr == "FAMILY":
498 continue
499 elif Attr == "PATH":
500 ToolsDef.append("%s = %s" % (Tool, Value))
501 else:
502 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
503 if Tool == "MAKE":
504 continue
505 # Remove duplicated include path, if any
506 if Attr == "FLAGS":
507 Value = RemoveDupOption(Value, IncPrefix, self._AutoGenObject.IncludePathList)
508 ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
509 ToolsDef.append("")
510
511 # generate the Response file and Response flag
512 RespDict = self.CommandExceedLimit()
513 RespFileList = os.path.join(self._AutoGenObject.OutputDir, 'respfilelist.txt')
514 if RespDict:
515 RespFileListContent = ''
516 for Resp in RespDict.keys():
517 RespFile = os.path.join(self._AutoGenObject.OutputDir, str(Resp).lower() + '.txt')
518 StrList = RespDict[Resp].split(' ')
519 UnexpandMacro = []
520 NewStr = []
521 for Str in StrList:
522 if '$' in Str:
523 UnexpandMacro.append(Str)
524 else:
525 NewStr.append(Str)
526 UnexpandMacroStr = ' '.join(UnexpandMacro)
527 NewRespStr = ' '.join(NewStr)
528 SaveFileOnChange(RespFile, NewRespStr, False)
529 ToolsDef.append("%s = %s" % (Resp, UnexpandMacroStr + ' @' + RespFile))
530 RespFileListContent += '@' + RespFile + os.linesep
531 RespFileListContent += NewRespStr + os.linesep
532 SaveFileOnChange(RespFileList, RespFileListContent, False)
533 else:
534 if os.path.exists(RespFileList):
535 os.remove(RespFileList)
536
537 # convert source files and binary files to build targets
538 self.ResultFileList = [str(T.Target) for T in self._AutoGenObject.CodaTargetList]
539 if len(self.ResultFileList) == 0 and len(self._AutoGenObject.SourceFileList) <> 0:
540 EdkLogger.error("build", AUTOGEN_ERROR, "Nothing to build",
541 ExtraData="[%s]" % str(self._AutoGenObject))
542
543 self.ProcessBuildTargetList()
544
545 # Generate macros used to represent input files
546 FileMacroList = [] # macro name = file list
547 for FileListMacro in self.FileListMacros:
548 FileMacro = self._FILE_MACRO_TEMPLATE.Replace(
549 {
550 "macro_name" : FileListMacro,
551 "source_file" : self.FileListMacros[FileListMacro]
552 }
553 )
554 FileMacroList.append(FileMacro)
555
556 # INC_LIST is special
557 FileMacro = ""
558 IncludePathList = []
559 for P in self._AutoGenObject.IncludePathList:
560 IncludePathList.append(IncPrefix + self.PlaceMacro(P, self.Macros))
561 if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:
562 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix + P)
563 FileMacro += self._FILE_MACRO_TEMPLATE.Replace(
564 {
565 "macro_name" : "INC",
566 "source_file" : IncludePathList
567 }
568 )
569 FileMacroList.append(FileMacro)
570
571 # Generate macros used to represent files containing list of input files
572 for ListFileMacro in self.ListFileMacros:
573 ListFileName = os.path.join(self._AutoGenObject.OutputDir, "%s.lst" % ListFileMacro.lower()[:len(ListFileMacro) - 5])
574 FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))
575 SaveFileOnChange(
576 ListFileName,
577 "\n".join(self.ListFileMacros[ListFileMacro]),
578 False
579 )
580
581 # Edk modules need <BaseName>StrDefs.h for string ID
582 #if self._AutoGenObject.AutoGenVersion < 0x00010005 and len(self._AutoGenObject.UnicodeFileList) > 0:
583 # BcTargetList = ['strdefs']
584 #else:
585 # BcTargetList = []
586 BcTargetList = []
587
588 MakefileName = self._FILE_NAME_[self._FileType]
589 LibraryMakeCommandList = []
590 for D in self.LibraryBuildDirectoryList:
591 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)}
592 LibraryMakeCommandList.append(Command)
593
594 package_rel_dir = self._AutoGenObject.SourceDir
595 current_dir = self.Macros["WORKSPACE"]
596 found = False
597 while not found and os.sep in package_rel_dir:
598 index = package_rel_dir.index(os.sep)
599 current_dir = mws.join(current_dir, package_rel_dir[:index])
600 if os.path.exists(current_dir):
601 for fl in os.listdir(current_dir):
602 if fl.endswith('.dec'):
603 found = True
604 break
605 package_rel_dir = package_rel_dir[index + 1:]
606
607 MakefileTemplateDict = {
608 "makefile_header" : self._FILE_HEADER_[self._FileType],
609 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
610 "makefile_name" : MakefileName,
611 "platform_name" : self.PlatformInfo.Name,
612 "platform_guid" : self.PlatformInfo.Guid,
613 "platform_version" : self.PlatformInfo.Version,
614 "platform_relative_directory": self.PlatformInfo.SourceDir,
615 "platform_output_directory" : self.PlatformInfo.OutputDir,
616 "platform_dir" : self._AutoGenObject.Macros["PLATFORM_DIR"],
617
618 "module_name" : self._AutoGenObject.Name,
619 "module_guid" : self._AutoGenObject.Guid,
620 "module_name_guid" : self._AutoGenObject._GetUniqueBaseName(),
621 "module_version" : self._AutoGenObject.Version,
622 "module_type" : self._AutoGenObject.ModuleType,
623 "module_file" : self._AutoGenObject.MetaFile.Name,
624 "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName,
625 "module_relative_directory" : self._AutoGenObject.SourceDir,
626 "module_dir" : mws.join (self.Macros["WORKSPACE"], self._AutoGenObject.SourceDir),
627 "package_relative_directory": package_rel_dir,
628 "module_extra_defines" : ["%s = %s" % (k, v) for k, v in self._AutoGenObject.Module.Defines.iteritems()],
629
630 "architecture" : self._AutoGenObject.Arch,
631 "toolchain_tag" : self._AutoGenObject.ToolChain,
632 "build_target" : self._AutoGenObject.BuildTarget,
633
634 "platform_build_directory" : self.PlatformInfo.BuildDir,
635 "module_build_directory" : self._AutoGenObject.BuildDir,
636 "module_output_directory" : self._AutoGenObject.OutputDir,
637 "module_debug_directory" : self._AutoGenObject.DebugDir,
638
639 "separator" : Separator,
640 "module_tool_definitions" : ToolsDef,
641
642 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),
643 "shell_command" : self._SHELL_CMD_[self._FileType].values(),
644
645 "module_entry_point" : ModuleEntryPoint,
646 "image_entry_point" : ImageEntryPoint,
647 "arch_entry_point" : ArchEntryPoint,
648 "remaining_build_target" : self.ResultFileList,
649 "common_dependency_file" : self.CommonFileDependency,
650 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
651 "clean_command" : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]),
652 "cleanall_command" : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]),
653 "dependent_library_build_directory" : self.LibraryBuildDirectoryList,
654 "library_build_command" : LibraryMakeCommandList,
655 "file_macro" : FileMacroList,
656 "file_build_target" : self.BuildTargetList,
657 "backward_compatible_target": BcTargetList,
658 }
659
660 return MakefileTemplateDict
661
662 def CommandExceedLimit(self):
663 FlagDict = {
664 'CC' : { 'Macro' : '$(CC_FLAGS)', 'Value' : False},
665 'PP' : { 'Macro' : '$(PP_FLAGS)', 'Value' : False},
666 'APP' : { 'Macro' : '$(APP_FLAGS)', 'Value' : False},
667 'ASLPP' : { 'Macro' : '$(ASLPP_FLAGS)', 'Value' : False},
668 'VFRPP' : { 'Macro' : '$(VFRPP_FLAGS)', 'Value' : False},
669 'ASM' : { 'Macro' : '$(ASM_FLAGS)', 'Value' : False},
670 'ASLCC' : { 'Macro' : '$(ASLCC_FLAGS)', 'Value' : False},
671 }
672
673 RespDict = {}
674 FileTypeList = []
675 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]
676
677 # base on the source files to decide the file type
678 for File in self._AutoGenObject.SourceFileList:
679 for type in self._AutoGenObject.FileTypes:
680 if File in self._AutoGenObject.FileTypes[type]:
681 if type not in FileTypeList:
682 FileTypeList.append(type)
683
684 # calculate the command-line length
685 if FileTypeList:
686 for type in FileTypeList:
687 BuildTargets = self._AutoGenObject.BuildRules[type].BuildTargets
688 for Target in BuildTargets:
689 CommandList = BuildTargets[Target].Commands
690 for SingleCommand in CommandList:
691 Tool = ''
692 SingleCommandLength = len(SingleCommand)
693 SingleCommandList = SingleCommand.split()
694 if len(SingleCommandList) > 0:
695 for Flag in FlagDict.keys():
696 if '$('+ Flag +')' in SingleCommandList[0]:
697 Tool = Flag
698 break
699 if Tool:
700 SingleCommandLength += len(self._AutoGenObject._BuildOption[Tool]['PATH'])
701 for item in SingleCommandList[1:]:
702 if FlagDict[Tool]['Macro'] in item:
703 Str = self._AutoGenObject._BuildOption[Tool]['FLAGS']
704 for Option in self._AutoGenObject.BuildOption.keys():
705 for Attr in self._AutoGenObject.BuildOption[Option]:
706 if Str.find(Option + '_' + Attr) != -1:
707 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
708 while(Str.find('$(') != -1):
709 for macro in self._AutoGenObject.Macros.keys():
710 MacroName = '$('+ macro + ')'
711 if (Str.find(MacroName) != -1):
712 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
713 break
714 else:
715 break
716 SingleCommandLength += len(Str)
717 elif '$(INC)' in item:
718 SingleCommandLength += self._AutoGenObject.IncludePathLength + len(IncPrefix) * len(self._AutoGenObject._IncludePathList)
719 elif item.find('$(') != -1:
720 Str = item
721 for Option in self._AutoGenObject.BuildOption.keys():
722 for Attr in self._AutoGenObject.BuildOption[Option]:
723 if Str.find(Option + '_' + Attr) != -1:
724 Str = Str.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
725 while(Str.find('$(') != -1):
726 for macro in self._AutoGenObject.Macros.keys():
727 MacroName = '$('+ macro + ')'
728 if (Str.find(MacroName) != -1):
729 Str = Str.replace(MacroName, self._AutoGenObject.Macros[macro])
730 break
731 else:
732 break
733 SingleCommandLength += len(Str)
734
735 if SingleCommandLength > GlobalData.gCommandMaxLength:
736 FlagDict[Tool]['Value'] = True
737
738 # generate the response file content by combine the FLAGS and INC
739 for Flag in FlagDict.keys():
740 if FlagDict[Flag]['Value']:
741 Key = Flag + '_RESP'
742 RespMacro = FlagDict[Flag]['Macro'].replace('FLAGS', 'RESP')
743 Value = self._AutoGenObject.BuildOption[Flag]['FLAGS']
744 for inc in self._AutoGenObject._IncludePathList:
745 Value += ' ' + IncPrefix + inc
746 for Option in self._AutoGenObject.BuildOption.keys():
747 for Attr in self._AutoGenObject.BuildOption[Option]:
748 if Value.find(Option + '_' + Attr) != -1:
749 Value = Value.replace('$(' + Option + '_' + Attr + ')', self._AutoGenObject.BuildOption[Option][Attr])
750 while (Value.find('$(') != -1):
751 for macro in self._AutoGenObject.Macros.keys():
752 MacroName = '$('+ macro + ')'
753 if (Value.find(MacroName) != -1):
754 Value = Value.replace(MacroName, self._AutoGenObject.Macros[macro])
755 break
756 else:
757 break
758 RespDict[Key] = Value
759 for Target in BuildTargets:
760 for i, SingleCommand in enumerate(BuildTargets[Target].Commands):
761 if FlagDict[Flag]['Macro'] in SingleCommand:
762 BuildTargets[Target].Commands[i] = SingleCommand.replace('$(INC)','').replace(FlagDict[Flag]['Macro'], RespMacro)
763 return RespDict
764
765 def ProcessBuildTargetList(self):
766 #
767 # Search dependency file list for each source file
768 #
769 ForceIncludedFile = []
770 for File in self._AutoGenObject.AutoGenFileList:
771 if File.Ext == '.h':
772 ForceIncludedFile.append(File)
773 SourceFileList = []
774 for Target in self._AutoGenObject.IntroTargetList:
775 SourceFileList.extend(Target.Inputs)
776
777 self.FileDependency = self.GetFileDependency(
778 SourceFileList,
779 ForceIncludedFile,
780 self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList
781 )
782 DepSet = None
783 for File in self.FileDependency:
784 if not self.FileDependency[File]:
785 self.FileDependency[File] = ['$(FORCE_REBUILD)']
786 continue
787 # skip non-C files
788 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
789 continue
790 elif DepSet == None:
791 DepSet = set(self.FileDependency[File])
792 else:
793 DepSet &= set(self.FileDependency[File])
794 # in case nothing in SourceFileList
795 if DepSet == None:
796 DepSet = set()
797 #
798 # Extract common files list in the dependency files
799 #
800 for File in DepSet:
801 self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros))
802
803 for File in self.FileDependency:
804 # skip non-C files
805 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":
806 continue
807 NewDepSet = set(self.FileDependency[File])
808 NewDepSet -= DepSet
809 self.FileDependency[File] = ["$(COMMON_DEPS)"] + list(NewDepSet)
810
811 # Convert target description object to target string in makefile
812 for Type in self._AutoGenObject.Targets:
813 for T in self._AutoGenObject.Targets[Type]:
814 # Generate related macros if needed
815 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
816 self.FileListMacros[T.FileListMacro] = []
817 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:
818 self.ListFileMacros[T.ListFileMacro] = []
819 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:
820 self.ListFileMacros[T.IncListFileMacro] = []
821
822 Deps = []
823 # Add force-dependencies
824 for Dep in T.Dependencies:
825 Deps.append(self.PlaceMacro(str(Dep), self.Macros))
826 # Add inclusion-dependencies
827 if len(T.Inputs) == 1 and T.Inputs[0] in self.FileDependency:
828 for F in self.FileDependency[T.Inputs[0]]:
829 Deps.append(self.PlaceMacro(str(F), self.Macros))
830 # Add source-dependencies
831 for F in T.Inputs:
832 NewFile = self.PlaceMacro(str(F), self.Macros)
833 # In order to use file list macro as dependency
834 if T.GenListFile:
835 # gnu tools need forward slash path separater, even on Windows
836 self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/'))
837 self.FileListMacros[T.FileListMacro].append(NewFile)
838 elif T.GenFileListMacro:
839 self.FileListMacros[T.FileListMacro].append(NewFile)
840 else:
841 Deps.append(NewFile)
842
843 # Use file list macro as dependency
844 if T.GenFileListMacro:
845 Deps.append("$(%s)" % T.FileListMacro)
846
847 TargetDict = {
848 "target" : self.PlaceMacro(T.Target.Path, self.Macros),
849 "cmd" : "\n\t".join(T.Commands),
850 "deps" : Deps
851 }
852 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
853
854 ## For creating makefile targets for dependent libraries
855 def ProcessDependentLibrary(self):
856 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
857 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))
858
859 ## Return a list containing source file's dependencies
860 #
861 # @param FileList The list of source files
862 # @param ForceInculeList The list of files which will be included forcely
863 # @param SearchPathList The list of search path
864 #
865 # @retval dict The mapping between source file path and its dependencies
866 #
867 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):
868 Dependency = {}
869 for F in FileList:
870 Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)
871 return Dependency
872
873 ## Find dependencies for one source file
874 #
875 # By searching recursively "#include" directive in file, find out all the
876 # files needed by given source file. The dependecies will be only searched
877 # in given search path list.
878 #
879 # @param File The source file
880 # @param ForceInculeList The list of files which will be included forcely
881 # @param SearchPathList The list of search path
882 #
883 # @retval list The list of files the given source file depends on
884 #
885 def GetDependencyList(self, File, ForceList, SearchPathList):
886 EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File)
887 FileStack = [File] + ForceList
888 DependencySet = set()
889
890 if self._AutoGenObject.Arch not in gDependencyDatabase:
891 gDependencyDatabase[self._AutoGenObject.Arch] = {}
892 DepDb = gDependencyDatabase[self._AutoGenObject.Arch]
893
894 while len(FileStack) > 0:
895 F = FileStack.pop()
896
897 FullPathDependList = []
898 if F in self.FileCache:
899 for CacheFile in self.FileCache[F]:
900 FullPathDependList.append(CacheFile)
901 if CacheFile not in DependencySet:
902 FileStack.append(CacheFile)
903 DependencySet.update(FullPathDependList)
904 continue
905
906 CurrentFileDependencyList = []
907 if F in DepDb:
908 CurrentFileDependencyList = DepDb[F]
909 else:
910 try:
911 Fd = open(F.Path, 'r')
912 except BaseException, X:
913 EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path + "\n\t" + str(X))
914
915 FileContent = Fd.read()
916 Fd.close()
917 if len(FileContent) == 0:
918 continue
919
920 if FileContent[0] == 0xff or FileContent[0] == 0xfe:
921 FileContent = unicode(FileContent, "utf-16")
922 IncludedFileList = gIncludePattern.findall(FileContent)
923
924 for Inc in IncludedFileList:
925 Inc = Inc.strip()
926 # if there's macro used to reference header file, expand it
927 HeaderList = gMacroPattern.findall(Inc)
928 if len(HeaderList) == 1 and len(HeaderList[0]) == 2:
929 HeaderType = HeaderList[0][0]
930 HeaderKey = HeaderList[0][1]
931 if HeaderType in gIncludeMacroConversion:
932 Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey}
933 else:
934 # not known macro used in #include, always build the file by
935 # returning a empty dependency
936 self.FileCache[File] = []
937 return []
938 Inc = os.path.normpath(Inc)
939 CurrentFileDependencyList.append(Inc)
940 DepDb[F] = CurrentFileDependencyList
941
942 CurrentFilePath = F.Dir
943 PathList = [CurrentFilePath] + SearchPathList
944 for Inc in CurrentFileDependencyList:
945 for SearchPath in PathList:
946 FilePath = os.path.join(SearchPath, Inc)
947 if FilePath in gIsFileMap:
948 if not gIsFileMap[FilePath]:
949 continue
950 # If isfile is called too many times, the performance is slow down.
951 elif not os.path.isfile(FilePath):
952 gIsFileMap[FilePath] = False
953 continue
954 else:
955 gIsFileMap[FilePath] = True
956 FilePath = PathClass(FilePath)
957 FullPathDependList.append(FilePath)
958 if FilePath not in DependencySet:
959 FileStack.append(FilePath)
960 break
961 else:
962 EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\
963 "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList)))
964
965 self.FileCache[F] = FullPathDependList
966 DependencySet.update(FullPathDependList)
967
968 DependencySet.update(ForceList)
969 if File in DependencySet:
970 DependencySet.remove(File)
971 DependencyList = list(DependencySet) # remove duplicate ones
972
973 return DependencyList
974
975 _TemplateDict = property(_CreateTemplateDict)
976
977 ## CustomMakefile class
978 #
979 # This class encapsules makefie and its generation for module. It uses template to generate
980 # the content of makefile. The content of makefile will be got from ModuleAutoGen object.
981 #
982 class CustomMakefile(BuildFile):
983 ## template used to generate the makefile for module with custom makefile
984 _TEMPLATE_ = TemplateString('''\
985 ${makefile_header}
986
987 #
988 # Platform Macro Definition
989 #
990 PLATFORM_NAME = ${platform_name}
991 PLATFORM_GUID = ${platform_guid}
992 PLATFORM_VERSION = ${platform_version}
993 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}
994 PLATFORM_DIR = ${platform_dir}
995 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
996
997 #
998 # Module Macro Definition
999 #
1000 MODULE_NAME = ${module_name}
1001 MODULE_GUID = ${module_guid}
1002 MODULE_NAME_GUID = ${module_name_guid}
1003 MODULE_VERSION = ${module_version}
1004 MODULE_TYPE = ${module_type}
1005 MODULE_FILE = ${module_file}
1006 MODULE_FILE_BASE_NAME = ${module_file_base_name}
1007 BASE_NAME = $(MODULE_NAME)
1008 MODULE_RELATIVE_DIR = ${module_relative_directory}
1009 MODULE_DIR = ${module_dir}
1010
1011 #
1012 # Build Configuration Macro Definition
1013 #
1014 ARCH = ${architecture}
1015 TOOLCHAIN = ${toolchain_tag}
1016 TOOLCHAIN_TAG = ${toolchain_tag}
1017 TARGET = ${build_target}
1018
1019 #
1020 # Build Directory Macro Definition
1021 #
1022 # PLATFORM_BUILD_DIR = ${platform_build_directory}
1023 BUILD_DIR = ${platform_build_directory}
1024 BIN_DIR = $(BUILD_DIR)${separator}${architecture}
1025 LIB_DIR = $(BIN_DIR)
1026 MODULE_BUILD_DIR = ${module_build_directory}
1027 OUTPUT_DIR = ${module_output_directory}
1028 DEBUG_DIR = ${module_debug_directory}
1029 DEST_DIR_OUTPUT = $(OUTPUT_DIR)
1030 DEST_DIR_DEBUG = $(DEBUG_DIR)
1031
1032 #
1033 # Tools definitions specific to this module
1034 #
1035 ${BEGIN}${module_tool_definitions}
1036 ${END}
1037 MAKE_FILE = ${makefile_path}
1038
1039 #
1040 # Shell Command Macro
1041 #
1042 ${BEGIN}${shell_command_code} = ${shell_command}
1043 ${END}
1044
1045 ${custom_makefile_content}
1046
1047 #
1048 # Target used when called from platform makefile, which will bypass the build of dependent libraries
1049 #
1050
1051 pbuild: init all
1052
1053
1054 #
1055 # ModuleTarget
1056 #
1057
1058 mbuild: init all
1059
1060 #
1061 # Build Target used in multi-thread build mode, which no init target is needed
1062 #
1063
1064 tbuild: all
1065
1066 #
1067 # Initialization target: print build information and create necessary directories
1068 #
1069 init:
1070 \t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]
1071 ${BEGIN}\t-@${create_directory_command}\n${END}\
1072
1073 ''')
1074
1075 ## Constructor of CustomMakefile
1076 #
1077 # @param ModuleAutoGen Object of ModuleAutoGen class
1078 #
1079 def __init__(self, ModuleAutoGen):
1080 BuildFile.__init__(self, ModuleAutoGen)
1081 self.PlatformInfo = self._AutoGenObject.PlatformInfo
1082 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]
1083
1084 # Compose a dict object containing information used to do replacement in template
1085 def _CreateTemplateDict(self):
1086 Separator = self._SEP_[self._FileType]
1087 if self._FileType not in self._AutoGenObject.CustomMakefile:
1088 EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType,
1089 ExtraData="[%s]" % str(self._AutoGenObject))
1090 MakefilePath = mws.join(
1091 self._AutoGenObject.WorkspaceDir,
1092 self._AutoGenObject.CustomMakefile[self._FileType]
1093 )
1094 try:
1095 CustomMakefile = open(MakefilePath, 'r').read()
1096 except:
1097 EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(self._AutoGenObject),
1098 ExtraData=self._AutoGenObject.CustomMakefile[self._FileType])
1099
1100 # tools definitions
1101 ToolsDef = []
1102 for Tool in self._AutoGenObject.BuildOption:
1103 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
1104 if Tool == "MAKE":
1105 continue
1106 for Attr in self._AutoGenObject.BuildOption[Tool]:
1107 if Attr == "FAMILY":
1108 continue
1109 elif Attr == "PATH":
1110 ToolsDef.append("%s = %s" % (Tool, self._AutoGenObject.BuildOption[Tool][Attr]))
1111 else:
1112 ToolsDef.append("%s_%s = %s" % (Tool, Attr, self._AutoGenObject.BuildOption[Tool][Attr]))
1113 ToolsDef.append("")
1114
1115 MakefileName = self._FILE_NAME_[self._FileType]
1116 MakefileTemplateDict = {
1117 "makefile_header" : self._FILE_HEADER_[self._FileType],
1118 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
1119 "platform_name" : self.PlatformInfo.Name,
1120 "platform_guid" : self.PlatformInfo.Guid,
1121 "platform_version" : self.PlatformInfo.Version,
1122 "platform_relative_directory": self.PlatformInfo.SourceDir,
1123 "platform_output_directory" : self.PlatformInfo.OutputDir,
1124 "platform_dir" : self._AutoGenObject.Macros["PLATFORM_DIR"],
1125
1126 "module_name" : self._AutoGenObject.Name,
1127 "module_guid" : self._AutoGenObject.Guid,
1128 "module_name_guid" : self._AutoGenObject._GetUniqueBaseName(),
1129 "module_version" : self._AutoGenObject.Version,
1130 "module_type" : self._AutoGenObject.ModuleType,
1131 "module_file" : self._AutoGenObject.MetaFile,
1132 "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName,
1133 "module_relative_directory" : self._AutoGenObject.SourceDir,
1134 "module_dir" : mws.join (self._AutoGenObject.WorkspaceDir, self._AutoGenObject.SourceDir),
1135
1136 "architecture" : self._AutoGenObject.Arch,
1137 "toolchain_tag" : self._AutoGenObject.ToolChain,
1138 "build_target" : self._AutoGenObject.BuildTarget,
1139
1140 "platform_build_directory" : self.PlatformInfo.BuildDir,
1141 "module_build_directory" : self._AutoGenObject.BuildDir,
1142 "module_output_directory" : self._AutoGenObject.OutputDir,
1143 "module_debug_directory" : self._AutoGenObject.DebugDir,
1144
1145 "separator" : Separator,
1146 "module_tool_definitions" : ToolsDef,
1147
1148 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),
1149 "shell_command" : self._SHELL_CMD_[self._FileType].values(),
1150
1151 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1152 "custom_makefile_content" : CustomMakefile
1153 }
1154
1155 return MakefileTemplateDict
1156
1157 _TemplateDict = property(_CreateTemplateDict)
1158
1159 ## PlatformMakefile class
1160 #
1161 # This class encapsules makefie and its generation for platform. It uses
1162 # template to generate the content of makefile. The content of makefile will be
1163 # got from PlatformAutoGen object.
1164 #
1165 class PlatformMakefile(BuildFile):
1166 ## template used to generate the makefile for platform
1167 _TEMPLATE_ = TemplateString('''\
1168 ${makefile_header}
1169
1170 #
1171 # Platform Macro Definition
1172 #
1173 PLATFORM_NAME = ${platform_name}
1174 PLATFORM_GUID = ${platform_guid}
1175 PLATFORM_VERSION = ${platform_version}
1176 PLATFORM_FILE = ${platform_file}
1177 PLATFORM_DIR = ${platform_dir}
1178 PLATFORM_OUTPUT_DIR = ${platform_output_directory}
1179
1180 #
1181 # Build Configuration Macro Definition
1182 #
1183 TOOLCHAIN = ${toolchain_tag}
1184 TOOLCHAIN_TAG = ${toolchain_tag}
1185 TARGET = ${build_target}
1186
1187 #
1188 # Build Directory Macro Definition
1189 #
1190 BUILD_DIR = ${platform_build_directory}
1191 FV_DIR = ${platform_build_directory}${separator}FV
1192
1193 #
1194 # Shell Command Macro
1195 #
1196 ${BEGIN}${shell_command_code} = ${shell_command}
1197 ${END}
1198
1199 MAKE = ${make_path}
1200 MAKE_FILE = ${makefile_path}
1201
1202 #
1203 # Default target
1204 #
1205 all: init build_libraries build_modules
1206
1207 #
1208 # Initialization target: print build information and create necessary directories
1209 #
1210 init:
1211 \t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]
1212 \t${BEGIN}-@${create_directory_command}
1213 \t${END}
1214 #
1215 # library build target
1216 #
1217 libraries: init build_libraries
1218
1219 #
1220 # module build target
1221 #
1222 modules: init build_libraries build_modules
1223
1224 #
1225 # Build all libraries:
1226 #
1227 build_libraries:
1228 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild
1229 ${END}\t@cd $(BUILD_DIR)
1230
1231 #
1232 # Build all modules:
1233 #
1234 build_modules:
1235 ${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild
1236 ${END}\t@cd $(BUILD_DIR)
1237
1238 #
1239 # Clean intermediate files
1240 #
1241 clean:
1242 \t${BEGIN}-@${library_build_command} clean
1243 \t${END}${BEGIN}-@${module_build_command} clean
1244 \t${END}@cd $(BUILD_DIR)
1245
1246 #
1247 # Clean all generated files except to makefile
1248 #
1249 cleanall:
1250 ${BEGIN}\t${cleanall_command}
1251 ${END}
1252
1253 #
1254 # Clean all library files
1255 #
1256 cleanlib:
1257 \t${BEGIN}-@${library_build_command} cleanall
1258 \t${END}@cd $(BUILD_DIR)\n
1259 ''')
1260
1261 ## Constructor of PlatformMakefile
1262 #
1263 # @param ModuleAutoGen Object of PlatformAutoGen class
1264 #
1265 def __init__(self, PlatformAutoGen):
1266 BuildFile.__init__(self, PlatformAutoGen)
1267 self.ModuleBuildCommandList = []
1268 self.ModuleMakefileList = []
1269 self.IntermediateDirectoryList = []
1270 self.ModuleBuildDirectoryList = []
1271 self.LibraryBuildDirectoryList = []
1272 self.LibraryMakeCommandList = []
1273
1274 # Compose a dict object containing information used to do replacement in template
1275 def _CreateTemplateDict(self):
1276 Separator = self._SEP_[self._FileType]
1277
1278 PlatformInfo = self._AutoGenObject
1279 if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:
1280 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
1281 ExtraData="[%s]" % str(self._AutoGenObject))
1282
1283 self.IntermediateDirectoryList = ["$(BUILD_DIR)"]
1284 self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()
1285 self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()
1286
1287 MakefileName = self._FILE_NAME_[self._FileType]
1288 LibraryMakefileList = []
1289 LibraryMakeCommandList = []
1290 for D in self.LibraryBuildDirectoryList:
1291 D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})
1292 Makefile = os.path.join(D, MakefileName)
1293 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
1294 LibraryMakefileList.append(Makefile)
1295 LibraryMakeCommandList.append(Command)
1296 self.LibraryMakeCommandList = LibraryMakeCommandList
1297
1298 ModuleMakefileList = []
1299 ModuleMakeCommandList = []
1300 for D in self.ModuleBuildDirectoryList:
1301 D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})
1302 Makefile = os.path.join(D, MakefileName)
1303 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
1304 ModuleMakefileList.append(Makefile)
1305 ModuleMakeCommandList.append(Command)
1306
1307 MakefileTemplateDict = {
1308 "makefile_header" : self._FILE_HEADER_[self._FileType],
1309 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),
1310 "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"],
1311 "makefile_name" : MakefileName,
1312 "platform_name" : PlatformInfo.Name,
1313 "platform_guid" : PlatformInfo.Guid,
1314 "platform_version" : PlatformInfo.Version,
1315 "platform_file" : self._AutoGenObject.MetaFile,
1316 "platform_relative_directory": PlatformInfo.SourceDir,
1317 "platform_output_directory" : PlatformInfo.OutputDir,
1318 "platform_build_directory" : PlatformInfo.BuildDir,
1319 "platform_dir" : self._AutoGenObject.Macros["PLATFORM_DIR"],
1320
1321 "toolchain_tag" : PlatformInfo.ToolChain,
1322 "build_target" : PlatformInfo.BuildTarget,
1323 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),
1324 "shell_command" : self._SHELL_CMD_[self._FileType].values(),
1325 "build_architecture_list" : self._AutoGenObject.Arch,
1326 "architecture" : self._AutoGenObject.Arch,
1327 "separator" : Separator,
1328 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1329 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1330 "library_makefile_list" : LibraryMakefileList,
1331 "module_makefile_list" : ModuleMakefileList,
1332 "library_build_command" : LibraryMakeCommandList,
1333 "module_build_command" : ModuleMakeCommandList,
1334 }
1335
1336 return MakefileTemplateDict
1337
1338 ## Get the root directory list for intermediate files of all modules build
1339 #
1340 # @retval list The list of directory
1341 #
1342 def GetModuleBuildDirectoryList(self):
1343 DirList = []
1344 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1345 if not ModuleAutoGen.IsBinaryModule:
1346 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1347 return DirList
1348
1349 ## Get the root directory list for intermediate files of all libraries build
1350 #
1351 # @retval list The list of directory
1352 #
1353 def GetLibraryBuildDirectoryList(self):
1354 DirList = []
1355 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1356 if not LibraryAutoGen.IsBinaryModule:
1357 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1358 return DirList
1359
1360 _TemplateDict = property(_CreateTemplateDict)
1361
1362 ## TopLevelMakefile class
1363 #
1364 # This class encapsules makefie and its generation for entrance makefile. It
1365 # uses template to generate the content of makefile. The content of makefile
1366 # will be got from WorkspaceAutoGen object.
1367 #
1368 class TopLevelMakefile(BuildFile):
1369 ## template used to generate toplevel makefile
1370 _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}''')
1371
1372 ## Constructor of TopLevelMakefile
1373 #
1374 # @param Workspace Object of WorkspaceAutoGen class
1375 #
1376 def __init__(self, Workspace):
1377 BuildFile.__init__(self, Workspace)
1378 self.IntermediateDirectoryList = []
1379
1380 # Compose a dict object containing information used to do replacement in template
1381 def _CreateTemplateDict(self):
1382 Separator = self._SEP_[self._FileType]
1383
1384 # any platform autogen object is ok because we just need common information
1385 PlatformInfo = self._AutoGenObject
1386
1387 if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:
1388 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",
1389 ExtraData="[%s]" % str(self._AutoGenObject))
1390
1391 for Arch in PlatformInfo.ArchList:
1392 self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch]))
1393 self.IntermediateDirectoryList.append("$(FV_DIR)")
1394
1395 # TRICK: for not generating GenFds call in makefile if no FDF file
1396 MacroList = []
1397 if PlatformInfo.FdfFile != None and PlatformInfo.FdfFile != "":
1398 FdfFileList = [PlatformInfo.FdfFile]
1399 # macros passed to GenFds
1400 MacroList.append('"%s=%s"' % ("EFI_SOURCE", GlobalData.gEfiSource.replace('\\', '\\\\')))
1401 MacroList.append('"%s=%s"' % ("EDK_SOURCE", GlobalData.gEdkSource.replace('\\', '\\\\')))
1402 MacroDict = {}
1403 MacroDict.update(GlobalData.gGlobalDefines)
1404 MacroDict.update(GlobalData.gCommandLineDefines)
1405 MacroDict.pop("EFI_SOURCE", "dummy")
1406 MacroDict.pop("EDK_SOURCE", "dummy")
1407 for MacroName in MacroDict:
1408 if MacroDict[MacroName] != "":
1409 MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))
1410 else:
1411 MacroList.append('"%s"' % MacroName)
1412 else:
1413 FdfFileList = []
1414
1415 # pass extra common options to external program called in makefile, currently GenFds.exe
1416 ExtraOption = ''
1417 LogLevel = EdkLogger.GetLevel()
1418 if LogLevel == EdkLogger.VERBOSE:
1419 ExtraOption += " -v"
1420 elif LogLevel <= EdkLogger.DEBUG_9:
1421 ExtraOption += " -d %d" % (LogLevel - 1)
1422 elif LogLevel == EdkLogger.QUIET:
1423 ExtraOption += " -q"
1424
1425 if GlobalData.gCaseInsensitive:
1426 ExtraOption += " -c"
1427
1428 if GlobalData.gIgnoreSource:
1429 ExtraOption += " --ignore-sources"
1430
1431 if GlobalData.BuildOptionPcd:
1432 for index, option in enumerate(GlobalData.gCommand):
1433 if "--pcd" == option and GlobalData.gCommand[index+1]:
1434 ExtraOption += " --pcd " + GlobalData.gCommand[index+1]
1435
1436 MakefileName = self._FILE_NAME_[self._FileType]
1437 SubBuildCommandList = []
1438 for A in PlatformInfo.ArchList:
1439 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)}
1440 SubBuildCommandList.append(Command)
1441
1442 MakefileTemplateDict = {
1443 "makefile_header" : self._FILE_HEADER_[self._FileType],
1444 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),
1445 "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"],
1446 "platform_name" : PlatformInfo.Name,
1447 "platform_guid" : PlatformInfo.Guid,
1448 "platform_version" : PlatformInfo.Version,
1449 "platform_build_directory" : PlatformInfo.BuildDir,
1450 "conf_directory" : GlobalData.gConfDirectory,
1451
1452 "toolchain_tag" : PlatformInfo.ToolChain,
1453 "build_target" : PlatformInfo.BuildTarget,
1454 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),
1455 "shell_command" : self._SHELL_CMD_[self._FileType].values(),
1456 'arch' : list(PlatformInfo.ArchList),
1457 "build_architecture_list" : ','.join(PlatformInfo.ArchList),
1458 "separator" : Separator,
1459 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
1460 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),
1461 "sub_build_command" : SubBuildCommandList,
1462 "fdf_file" : FdfFileList,
1463 "active_platform" : str(PlatformInfo),
1464 "fd" : PlatformInfo.FdTargetList,
1465 "fv" : PlatformInfo.FvTargetList,
1466 "cap" : PlatformInfo.CapTargetList,
1467 "extra_options" : ExtraOption,
1468 "macro" : MacroList,
1469 }
1470
1471 return MakefileTemplateDict
1472
1473 ## Get the root directory list for intermediate files of all modules build
1474 #
1475 # @retval list The list of directory
1476 #
1477 def GetModuleBuildDirectoryList(self):
1478 DirList = []
1479 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:
1480 if not ModuleAutoGen.IsBinaryModule:
1481 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))
1482 return DirList
1483
1484 ## Get the root directory list for intermediate files of all libraries build
1485 #
1486 # @retval list The list of directory
1487 #
1488 def GetLibraryBuildDirectoryList(self):
1489 DirList = []
1490 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:
1491 if not LibraryAutoGen.IsBinaryModule:
1492 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))
1493 return DirList
1494
1495 _TemplateDict = property(_CreateTemplateDict)
1496
1497 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1498 if __name__ == '__main__':
1499 pass
1500