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