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