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