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