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