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