]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/AutoGen/GenMake.py
BaseTools: Correct NASM output file type for UNIXGCC and CYGGCC.
[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
682 self.ListFileMacros[T.ListFileMacro].append(str(F))\r
683 self.FileListMacros[T.FileListMacro].append(NewFile)\r
684 elif T.GenFileListMacro:\r
685 self.FileListMacros[T.FileListMacro].append(NewFile)\r
686 else:\r
687 Deps.append(NewFile)\r
688\r
689 # Use file list macro as dependency\r
690 if T.GenFileListMacro:\r
691 Deps.append("$(%s)" % T.FileListMacro)\r
692\r
693 TargetDict = {\r
694 "target" : self.PlaceMacro(T.Target.Path, self.Macros),\r
695 "cmd" : "\n\t".join(T.Commands),\r
696 "deps" : Deps\r
697 }\r
698 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))\r
699\r
700 ## For creating makefile targets for dependent libraries\r
701 def ProcessDependentLibrary(self):\r
702 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:\r
703 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))\r
704\r
705 ## Return a list containing source file's dependencies\r
706 #\r
707 # @param FileList The list of source files\r
708 # @param ForceInculeList The list of files which will be included forcely\r
709 # @param SearchPathList The list of search path\r
710 #\r
711 # @retval dict The mapping between source file path and its dependencies\r
712 #\r
713 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):\r
714 Dependency = {}\r
715 for F in FileList:\r
716 Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)\r
717 return Dependency\r
718\r
719 ## Find dependencies for one source file\r
720 #\r
721 # By searching recursively "#include" directive in file, find out all the\r
722 # files needed by given source file. The dependecies will be only searched\r
723 # in given search path list.\r
724 #\r
725 # @param File The source file\r
726 # @param ForceInculeList The list of files which will be included forcely\r
727 # @param SearchPathList The list of search path\r
728 #\r
729 # @retval list The list of files the given source file depends on\r
730 #\r
731 def GetDependencyList(self, File, ForceList, SearchPathList):\r
732 EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File)\r
733 FileStack = [File] + ForceList\r
734 DependencySet = set()\r
735\r
736 if self._AutoGenObject.Arch not in gDependencyDatabase:\r
737 gDependencyDatabase[self._AutoGenObject.Arch] = {}\r
738 DepDb = gDependencyDatabase[self._AutoGenObject.Arch]\r
739\r
740 while len(FileStack) > 0:\r
741 F = FileStack.pop()\r
742\r
743 FullPathDependList = []\r
744 if F in self.FileCache:\r
745 for CacheFile in self.FileCache[F]:\r
746 FullPathDependList.append(CacheFile)\r
747 if CacheFile not in DependencySet:\r
748 FileStack.append(CacheFile)\r
749 DependencySet.update(FullPathDependList)\r
750 continue\r
751\r
752 CurrentFileDependencyList = []\r
753 if F in DepDb:\r
754 CurrentFileDependencyList = DepDb[F]\r
755 else:\r
756 try:\r
757 Fd = open(F.Path, 'r')\r
758 except BaseException, X:\r
759 EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path+"\n\t"+str(X))\r
760\r
761 FileContent = Fd.read()\r
762 Fd.close()\r
763 if len(FileContent) == 0:\r
764 continue\r
765\r
766 if FileContent[0] == 0xff or FileContent[0] == 0xfe:\r
767 FileContent = unicode(FileContent, "utf-16")\r
768 IncludedFileList = gIncludePattern.findall(FileContent)\r
769\r
770 for Inc in IncludedFileList:\r
771 Inc = Inc.strip()\r
772 # if there's macro used to reference header file, expand it\r
773 HeaderList = gMacroPattern.findall(Inc)\r
774 if len(HeaderList) == 1 and len(HeaderList[0]) == 2:\r
775 HeaderType = HeaderList[0][0]\r
776 HeaderKey = HeaderList[0][1]\r
777 if HeaderType in gIncludeMacroConversion:\r
778 Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey}\r
779 else:\r
780 # not known macro used in #include, always build the file by\r
781 # returning a empty dependency\r
782 self.FileCache[File] = []\r
783 return []\r
784 Inc = os.path.normpath(Inc)\r
785 CurrentFileDependencyList.append(Inc)\r
786 DepDb[F] = CurrentFileDependencyList\r
787\r
788 CurrentFilePath = F.Dir\r
789 PathList = [CurrentFilePath] + SearchPathList\r
790 for Inc in CurrentFileDependencyList:\r
791 for SearchPath in PathList:\r
792 FilePath = os.path.join(SearchPath, Inc)\r
793 if FilePath in gIsFileMap:\r
794 if not gIsFileMap[FilePath]:\r
795 continue\r
796 # If isfile is called too many times, the performance is slow down.\r
797 elif not os.path.isfile(FilePath):\r
798 gIsFileMap[FilePath] = False\r
799 continue\r
800 else:\r
801 gIsFileMap[FilePath] = True\r
802 FilePath = PathClass(FilePath)\r
803 FullPathDependList.append(FilePath)\r
804 if FilePath not in DependencySet:\r
805 FileStack.append(FilePath)\r
806 break\r
807 else:\r
808 EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\\r
809 "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList)))\r
810\r
811 self.FileCache[F] = FullPathDependList\r
812 DependencySet.update(FullPathDependList)\r
813\r
814 DependencySet.update(ForceList)\r
815 if File in DependencySet:\r
816 DependencySet.remove(File)\r
817 DependencyList = list(DependencySet) # remove duplicate ones\r
818\r
819 return DependencyList\r
820\r
821 _TemplateDict = property(_CreateTemplateDict)\r
822\r
823## CustomMakefile class\r
824#\r
825# This class encapsules makefie and its generation for module. It uses template to generate\r
826# the content of makefile. The content of makefile will be got from ModuleAutoGen object.\r
827#\r
828class CustomMakefile(BuildFile):\r
829 ## template used to generate the makefile for module with custom makefile\r
830 _TEMPLATE_ = TemplateString('''\\r
831${makefile_header}\r
832\r
833#\r
834# Platform Macro Definition\r
835#\r
836PLATFORM_NAME = ${platform_name}\r
837PLATFORM_GUID = ${platform_guid}\r
838PLATFORM_VERSION = ${platform_version}\r
839PLATFORM_RELATIVE_DIR = ${platform_relative_directory}\r
840PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}\r
841PLATFORM_OUTPUT_DIR = ${platform_output_directory}\r
842\r
843#\r
844# Module Macro Definition\r
845#\r
846MODULE_NAME = ${module_name}\r
847MODULE_GUID = ${module_guid}\r
848MODULE_VERSION = ${module_version}\r
849MODULE_TYPE = ${module_type}\r
850MODULE_FILE = ${module_file}\r
851MODULE_FILE_BASE_NAME = ${module_file_base_name}\r
852BASE_NAME = $(MODULE_NAME)\r
853MODULE_RELATIVE_DIR = ${module_relative_directory}\r
854MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory}\r
855\r
856#\r
857# Build Configuration Macro Definition\r
858#\r
859ARCH = ${architecture}\r
860TOOLCHAIN = ${toolchain_tag}\r
861TOOLCHAIN_TAG = ${toolchain_tag}\r
862TARGET = ${build_target}\r
863\r
864#\r
865# Build Directory Macro Definition\r
866#\r
867# PLATFORM_BUILD_DIR = ${platform_build_directory}\r
868BUILD_DIR = ${platform_build_directory}\r
869BIN_DIR = $(BUILD_DIR)${separator}${architecture}\r
870LIB_DIR = $(BIN_DIR)\r
871MODULE_BUILD_DIR = ${module_build_directory}\r
872OUTPUT_DIR = ${module_output_directory}\r
873DEBUG_DIR = ${module_debug_directory}\r
874DEST_DIR_OUTPUT = $(OUTPUT_DIR)\r
875DEST_DIR_DEBUG = $(DEBUG_DIR)\r
876\r
877#\r
878# Tools definitions specific to this module\r
879#\r
880${BEGIN}${module_tool_definitions}\r
881${END}\r
882MAKE_FILE = ${makefile_path}\r
883\r
884#\r
885# Shell Command Macro\r
886#\r
887${BEGIN}${shell_command_code} = ${shell_command}\r
888${END}\r
889\r
890${custom_makefile_content}\r
891\r
892#\r
893# Target used when called from platform makefile, which will bypass the build of dependent libraries\r
894#\r
895\r
896pbuild: init all\r
897\r
898\r
899#\r
900# ModuleTarget\r
901#\r
902\r
903mbuild: init all\r
904\r
905#\r
906# Build Target used in multi-thread build mode, which no init target is needed\r
907#\r
908\r
909tbuild: all\r
910\r
911#\r
912# Initialization target: print build information and create necessary directories\r
913#\r
914init:\r
915\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]\r
916${BEGIN}\t-@${create_directory_command}\n${END}\\r
917\r
918''')\r
919\r
920 ## Constructor of CustomMakefile\r
921 #\r
922 # @param ModuleAutoGen Object of ModuleAutoGen class\r
923 #\r
924 def __init__(self, ModuleAutoGen):\r
925 BuildFile.__init__(self, ModuleAutoGen)\r
926 self.PlatformInfo = self._AutoGenObject.PlatformInfo\r
927 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]\r
928\r
929 # Compose a dict object containing information used to do replacement in template\r
930 def _CreateTemplateDict(self):\r
931 Separator = self._SEP_[self._FileType]\r
932 if self._FileType not in self._AutoGenObject.CustomMakefile:\r
933 EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType,\r
934 ExtraData="[%s]" % str(self._AutoGenObject))\r
935 MakefilePath = os.path.join(\r
936 self._AutoGenObject.WorkspaceDir,\r
937 self._AutoGenObject.CustomMakefile[self._FileType]\r
938 )\r
939 try:\r
940 CustomMakefile = open(MakefilePath, 'r').read()\r
941 except:\r
942 EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(self._AutoGenObject),\r
943 ExtraData=self._AutoGenObject.CustomMakefile[self._FileType])\r
944\r
945 # tools definitions\r
946 ToolsDef = []\r
947 for Tool in self._AutoGenObject.BuildOption:\r
948 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.\r
949 if Tool == "MAKE":\r
950 continue\r
951 for Attr in self._AutoGenObject.BuildOption[Tool]:\r
952 if Attr == "FAMILY":\r
953 continue\r
954 elif Attr == "PATH":\r
955 ToolsDef.append("%s = %s" % (Tool, self._AutoGenObject.BuildOption[Tool][Attr]))\r
956 else:\r
957 ToolsDef.append("%s_%s = %s" % (Tool, Attr, self._AutoGenObject.BuildOption[Tool][Attr]))\r
958 ToolsDef.append("")\r
959\r
960 MakefileName = self._FILE_NAME_[self._FileType]\r
961 MakefileTemplateDict = {\r
962 "makefile_header" : self._FILE_HEADER_[self._FileType],\r
963 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),\r
964 "platform_name" : self.PlatformInfo.Name,\r
965 "platform_guid" : self.PlatformInfo.Guid,\r
966 "platform_version" : self.PlatformInfo.Version,\r
967 "platform_relative_directory": self.PlatformInfo.SourceDir,\r
968 "platform_output_directory" : self.PlatformInfo.OutputDir,\r
969\r
970 "module_name" : self._AutoGenObject.Name,\r
971 "module_guid" : self._AutoGenObject.Guid,\r
972 "module_version" : self._AutoGenObject.Version,\r
973 "module_type" : self._AutoGenObject.ModuleType,\r
974 "module_file" : self._AutoGenObject.MetaFile,\r
975 "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName,\r
976 "module_relative_directory" : self._AutoGenObject.SourceDir,\r
977\r
978 "architecture" : self._AutoGenObject.Arch,\r
979 "toolchain_tag" : self._AutoGenObject.ToolChain,\r
980 "build_target" : self._AutoGenObject.BuildTarget,\r
981\r
982 "platform_build_directory" : self.PlatformInfo.BuildDir,\r
983 "module_build_directory" : self._AutoGenObject.BuildDir,\r
984 "module_output_directory" : self._AutoGenObject.OutputDir,\r
985 "module_debug_directory" : self._AutoGenObject.DebugDir,\r
986\r
987 "separator" : Separator,\r
988 "module_tool_definitions" : ToolsDef,\r
989\r
990 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),\r
991 "shell_command" : self._SHELL_CMD_[self._FileType].values(),\r
992\r
993 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
994 "custom_makefile_content" : CustomMakefile\r
995 }\r
996\r
997 return MakefileTemplateDict\r
998\r
999 _TemplateDict = property(_CreateTemplateDict)\r
1000\r
1001## PlatformMakefile class\r
1002#\r
1003# This class encapsules makefie and its generation for platform. It uses\r
1004# template to generate the content of makefile. The content of makefile will be\r
1005# got from PlatformAutoGen object.\r
1006#\r
1007class PlatformMakefile(BuildFile):\r
1008 ## template used to generate the makefile for platform\r
1009 _TEMPLATE_ = TemplateString('''\\r
1010${makefile_header}\r
1011\r
1012#\r
1013# Platform Macro Definition\r
1014#\r
1015PLATFORM_NAME = ${platform_name}\r
1016PLATFORM_GUID = ${platform_guid}\r
1017PLATFORM_VERSION = ${platform_version}\r
1018PLATFORM_FILE = ${platform_file}\r
1019PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}\r
1020PLATFORM_OUTPUT_DIR = ${platform_output_directory}\r
1021\r
1022#\r
1023# Build Configuration Macro Definition\r
1024#\r
1025TOOLCHAIN = ${toolchain_tag}\r
1026TOOLCHAIN_TAG = ${toolchain_tag}\r
1027TARGET = ${build_target}\r
1028\r
1029#\r
1030# Build Directory Macro Definition\r
1031#\r
1032BUILD_DIR = ${platform_build_directory}\r
1033FV_DIR = ${platform_build_directory}${separator}FV\r
1034\r
1035#\r
1036# Shell Command Macro\r
1037#\r
1038${BEGIN}${shell_command_code} = ${shell_command}\r
1039${END}\r
1040\r
1041MAKE = ${make_path}\r
1042MAKE_FILE = ${makefile_path}\r
1043\r
1044#\r
1045# Default target\r
1046#\r
1047all: init build_libraries build_modules\r
1048\r
1049#\r
1050# Initialization target: print build information and create necessary directories\r
1051#\r
1052init:\r
1053\t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]\r
1054\t${BEGIN}-@${create_directory_command}\r
1055\t${END}\r
1056#\r
1057# library build target\r
1058#\r
1059libraries: init build_libraries\r
1060\r
1061#\r
1062# module build target\r
1063#\r
1064modules: init build_libraries build_modules\r
1065\r
1066#\r
1067# Build all libraries:\r
1068#\r
1069build_libraries:\r
1070${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild\r
1071${END}\t@cd $(BUILD_DIR)\r
1072\r
1073#\r
1074# Build all modules:\r
1075#\r
1076build_modules:\r
1077${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild\r
1078${END}\t@cd $(BUILD_DIR)\r
1079\r
1080#\r
1081# Clean intermediate files\r
1082#\r
1083clean:\r
1084\t${BEGIN}-@${library_build_command} clean\r
1085\t${END}${BEGIN}-@${module_build_command} clean\r
1086\t${END}@cd $(BUILD_DIR)\r
1087\r
1088#\r
1089# Clean all generated files except to makefile\r
1090#\r
1091cleanall:\r
1092${BEGIN}\t${cleanall_command}\r
1093${END}\r
1094\r
1095#\r
1096# Clean all library files\r
1097#\r
1098cleanlib:\r
1099\t${BEGIN}-@${library_build_command} cleanall\r
1100\t${END}@cd $(BUILD_DIR)\n\r
1101''')\r
1102\r
1103 ## Constructor of PlatformMakefile\r
1104 #\r
1105 # @param ModuleAutoGen Object of PlatformAutoGen class\r
1106 #\r
1107 def __init__(self, PlatformAutoGen):\r
1108 BuildFile.__init__(self, PlatformAutoGen)\r
1109 self.ModuleBuildCommandList = []\r
1110 self.ModuleMakefileList = []\r
1111 self.IntermediateDirectoryList = []\r
1112 self.ModuleBuildDirectoryList = []\r
1113 self.LibraryBuildDirectoryList = []\r
03af2753 1114 self.LibraryMakeCommandList = []\r
f51461c8
LG
1115\r
1116 # Compose a dict object containing information used to do replacement in template\r
1117 def _CreateTemplateDict(self):\r
1118 Separator = self._SEP_[self._FileType]\r
1119\r
1120 PlatformInfo = self._AutoGenObject\r
1121 if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:\r
1122 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",\r
1123 ExtraData="[%s]" % str(self._AutoGenObject))\r
1124\r
1125 self.IntermediateDirectoryList = ["$(BUILD_DIR)"]\r
1126 self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()\r
1127 self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()\r
1128\r
1129 MakefileName = self._FILE_NAME_[self._FileType]\r
1130 LibraryMakefileList = []\r
1131 LibraryMakeCommandList = []\r
1132 for D in self.LibraryBuildDirectoryList:\r
1133 D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})\r
1134 Makefile = os.path.join(D, MakefileName)\r
1135 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}\r
1136 LibraryMakefileList.append(Makefile)\r
1137 LibraryMakeCommandList.append(Command)\r
03af2753 1138 self.LibraryMakeCommandList = LibraryMakeCommandList\r
f51461c8
LG
1139\r
1140 ModuleMakefileList = []\r
1141 ModuleMakeCommandList = []\r
1142 for D in self.ModuleBuildDirectoryList:\r
1143 D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})\r
1144 Makefile = os.path.join(D, MakefileName)\r
1145 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}\r
1146 ModuleMakefileList.append(Makefile)\r
1147 ModuleMakeCommandList.append(Command)\r
1148\r
1149 MakefileTemplateDict = {\r
1150 "makefile_header" : self._FILE_HEADER_[self._FileType],\r
1151 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),\r
1152 "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"],\r
1153 "makefile_name" : MakefileName,\r
1154 "platform_name" : PlatformInfo.Name,\r
1155 "platform_guid" : PlatformInfo.Guid,\r
1156 "platform_version" : PlatformInfo.Version,\r
1157 "platform_file" : self._AutoGenObject.MetaFile,\r
1158 "platform_relative_directory": PlatformInfo.SourceDir,\r
1159 "platform_output_directory" : PlatformInfo.OutputDir,\r
1160 "platform_build_directory" : PlatformInfo.BuildDir,\r
1161\r
1162 "toolchain_tag" : PlatformInfo.ToolChain,\r
1163 "build_target" : PlatformInfo.BuildTarget,\r
1164 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),\r
1165 "shell_command" : self._SHELL_CMD_[self._FileType].values(),\r
1166 "build_architecture_list" : self._AutoGenObject.Arch,\r
1167 "architecture" : self._AutoGenObject.Arch,\r
1168 "separator" : Separator,\r
1169 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
1170 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),\r
1171 "library_makefile_list" : LibraryMakefileList,\r
1172 "module_makefile_list" : ModuleMakefileList,\r
1173 "library_build_command" : LibraryMakeCommandList,\r
1174 "module_build_command" : ModuleMakeCommandList,\r
1175 }\r
1176\r
1177 return MakefileTemplateDict\r
1178\r
1179 ## Get the root directory list for intermediate files of all modules build\r
1180 #\r
1181 # @retval list The list of directory\r
1182 #\r
1183 def GetModuleBuildDirectoryList(self):\r
1184 DirList = []\r
1185 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:\r
97fa0ee9
YL
1186 if not ModuleAutoGen.IsBinaryModule:\r
1187 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))\r
f51461c8
LG
1188 return DirList\r
1189\r
1190 ## Get the root directory list for intermediate files of all libraries build\r
1191 #\r
1192 # @retval list The list of directory\r
1193 #\r
1194 def GetLibraryBuildDirectoryList(self):\r
1195 DirList = []\r
1196 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:\r
97fa0ee9
YL
1197 if not LibraryAutoGen.IsBinaryModule:\r
1198 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))\r
f51461c8
LG
1199 return DirList\r
1200\r
1201 _TemplateDict = property(_CreateTemplateDict)\r
1202\r
1203## TopLevelMakefile class\r
1204#\r
1205# This class encapsules makefie and its generation for entrance makefile. It\r
1206# uses template to generate the content of makefile. The content of makefile\r
1207# will be got from WorkspaceAutoGen object.\r
1208#\r
1209class TopLevelMakefile(BuildFile):\r
1210 ## template used to generate toplevel makefile\r
97fa0ee9 1211 _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
1212\r
1213 ## Constructor of TopLevelMakefile\r
1214 #\r
1215 # @param Workspace Object of WorkspaceAutoGen class\r
1216 #\r
1217 def __init__(self, Workspace):\r
1218 BuildFile.__init__(self, Workspace)\r
1219 self.IntermediateDirectoryList = []\r
1220\r
1221 # Compose a dict object containing information used to do replacement in template\r
1222 def _CreateTemplateDict(self):\r
1223 Separator = self._SEP_[self._FileType]\r
1224\r
1225 # any platform autogen object is ok because we just need common information\r
1226 PlatformInfo = self._AutoGenObject\r
1227\r
1228 if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:\r
1229 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",\r
1230 ExtraData="[%s]" % str(self._AutoGenObject))\r
1231\r
1232 for Arch in PlatformInfo.ArchList:\r
1233 self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch]))\r
1234 self.IntermediateDirectoryList.append("$(FV_DIR)")\r
1235\r
1236 # TRICK: for not generating GenFds call in makefile if no FDF file\r
1237 MacroList = []\r
1238 if PlatformInfo.FdfFile != None and PlatformInfo.FdfFile != "":\r
1239 FdfFileList = [PlatformInfo.FdfFile]\r
1240 # macros passed to GenFds\r
1241 MacroList.append('"%s=%s"' % ("EFI_SOURCE", GlobalData.gEfiSource.replace('\\', '\\\\')))\r
1242 MacroList.append('"%s=%s"' % ("EDK_SOURCE", GlobalData.gEdkSource.replace('\\', '\\\\')))\r
1243 MacroDict = {}\r
1244 MacroDict.update(GlobalData.gGlobalDefines)\r
1245 MacroDict.update(GlobalData.gCommandLineDefines)\r
1246 MacroDict.pop("EFI_SOURCE", "dummy")\r
1247 MacroDict.pop("EDK_SOURCE", "dummy")\r
1248 for MacroName in MacroDict:\r
1249 if MacroDict[MacroName] != "":\r
1250 MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))\r
1251 else:\r
1252 MacroList.append('"%s"' % MacroName)\r
1253 else:\r
1254 FdfFileList = []\r
1255\r
1256 # pass extra common options to external program called in makefile, currently GenFds.exe\r
1257 ExtraOption = ''\r
1258 LogLevel = EdkLogger.GetLevel()\r
1259 if LogLevel == EdkLogger.VERBOSE:\r
1260 ExtraOption += " -v"\r
1261 elif LogLevel <= EdkLogger.DEBUG_9:\r
1262 ExtraOption += " -d %d" % (LogLevel - 1)\r
1263 elif LogLevel == EdkLogger.QUIET:\r
1264 ExtraOption += " -q"\r
1265\r
1266 if GlobalData.gCaseInsensitive:\r
1267 ExtraOption += " -c"\r
1268\r
97fa0ee9
YL
1269 if GlobalData.gIgnoreSource:\r
1270 ExtraOption += " --ignore-sources"\r
1271\r
f51461c8
LG
1272 MakefileName = self._FILE_NAME_[self._FileType]\r
1273 SubBuildCommandList = []\r
1274 for A in PlatformInfo.ArchList:\r
1275 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)}\r
1276 SubBuildCommandList.append(Command)\r
1277\r
1278 MakefileTemplateDict = {\r
1279 "makefile_header" : self._FILE_HEADER_[self._FileType],\r
1280 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),\r
1281 "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"],\r
1282 "platform_name" : PlatformInfo.Name,\r
1283 "platform_guid" : PlatformInfo.Guid,\r
1284 "platform_version" : PlatformInfo.Version,\r
1285 "platform_build_directory" : PlatformInfo.BuildDir,\r
97fa0ee9 1286 "conf_directory" : GlobalData.gConfDirectory,\r
f51461c8
LG
1287\r
1288 "toolchain_tag" : PlatformInfo.ToolChain,\r
1289 "build_target" : PlatformInfo.BuildTarget,\r
1290 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),\r
1291 "shell_command" : self._SHELL_CMD_[self._FileType].values(),\r
1292 'arch' : list(PlatformInfo.ArchList),\r
1293 "build_architecture_list" : ','.join(PlatformInfo.ArchList),\r
1294 "separator" : Separator,\r
1295 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
1296 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),\r
1297 "sub_build_command" : SubBuildCommandList,\r
1298 "fdf_file" : FdfFileList,\r
1299 "active_platform" : str(PlatformInfo),\r
1300 "fd" : PlatformInfo.FdTargetList,\r
1301 "fv" : PlatformInfo.FvTargetList,\r
1302 "cap" : PlatformInfo.CapTargetList,\r
1303 "extra_options" : ExtraOption,\r
1304 "macro" : MacroList,\r
1305 }\r
1306\r
1307 return MakefileTemplateDict\r
1308\r
1309 ## Get the root directory list for intermediate files of all modules build\r
1310 #\r
1311 # @retval list The list of directory\r
1312 #\r
1313 def GetModuleBuildDirectoryList(self):\r
1314 DirList = []\r
1315 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:\r
97fa0ee9
YL
1316 if not ModuleAutoGen.IsBinaryModule:\r
1317 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))\r
f51461c8
LG
1318 return DirList\r
1319\r
1320 ## Get the root directory list for intermediate files of all libraries build\r
1321 #\r
1322 # @retval list The list of directory\r
1323 #\r
1324 def GetLibraryBuildDirectoryList(self):\r
1325 DirList = []\r
1326 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:\r
97fa0ee9
YL
1327 if not LibraryAutoGen.IsBinaryModule:\r
1328 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))\r
f51461c8
LG
1329 return DirList\r
1330\r
1331 _TemplateDict = property(_CreateTemplateDict)\r
1332\r
1333# This acts like the main() function for the script, unless it is 'import'ed into another script.\r
1334if __name__ == '__main__':\r
1335 pass\r
1336\r