]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/AutoGen/GenMake.py
Basetools: It went wrong when use os.linesep
[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
1ccc4d89
LG
678 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),\r
679 "shell_command" : 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
285a1754
SD
962 # gnu tools need forward slash path separater, even on Windows\r
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
1006 # files needed by given source file. The dependecies will be only searched\r
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
1ccc4d89 1041 Fd = open(F.Path, 'r')\r
5b0671c1 1042 except BaseException as X:\r
47fea6af 1043 EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path + "\n\t" + str(X))\r
f51461c8
LG
1044\r
1045 FileContent = Fd.read()\r
1046 Fd.close()\r
1047 if len(FileContent) == 0:\r
1048 continue\r
1049\r
1050 if FileContent[0] == 0xff or FileContent[0] == 0xfe:\r
1ccc4d89
LG
1051 FileContent = unicode(FileContent, "utf-16")\r
1052 IncludedFileList = gIncludePattern.findall(FileContent)\r
f51461c8
LG
1053\r
1054 for Inc in IncludedFileList:\r
1055 Inc = Inc.strip()\r
1056 # if there's macro used to reference header file, expand it\r
1057 HeaderList = gMacroPattern.findall(Inc)\r
1058 if len(HeaderList) == 1 and len(HeaderList[0]) == 2:\r
1059 HeaderType = HeaderList[0][0]\r
1060 HeaderKey = HeaderList[0][1]\r
1061 if HeaderType in gIncludeMacroConversion:\r
1062 Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey}\r
1063 else:\r
1064 # not known macro used in #include, always build the file by\r
1065 # returning a empty dependency\r
1066 self.FileCache[File] = []\r
1067 return []\r
1068 Inc = os.path.normpath(Inc)\r
1069 CurrentFileDependencyList.append(Inc)\r
1070 DepDb[F] = CurrentFileDependencyList\r
1071\r
1072 CurrentFilePath = F.Dir\r
1073 PathList = [CurrentFilePath] + SearchPathList\r
1074 for Inc in CurrentFileDependencyList:\r
1075 for SearchPath in PathList:\r
1076 FilePath = os.path.join(SearchPath, Inc)\r
1077 if FilePath in gIsFileMap:\r
1078 if not gIsFileMap[FilePath]:\r
1079 continue\r
1080 # If isfile is called too many times, the performance is slow down.\r
1081 elif not os.path.isfile(FilePath):\r
1082 gIsFileMap[FilePath] = False\r
1083 continue\r
1084 else:\r
1085 gIsFileMap[FilePath] = True\r
1086 FilePath = PathClass(FilePath)\r
1087 FullPathDependList.append(FilePath)\r
1088 if FilePath not in DependencySet:\r
1089 FileStack.append(FilePath)\r
1090 break\r
1091 else:\r
1092 EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\\r
1093 "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList)))\r
1094\r
1095 self.FileCache[F] = FullPathDependList\r
1096 DependencySet.update(FullPathDependList)\r
1097\r
1098 DependencySet.update(ForceList)\r
1099 if File in DependencySet:\r
1100 DependencySet.remove(File)\r
1ccc4d89 1101 DependencyList = list(DependencySet) # remove duplicate ones\r
f51461c8
LG
1102\r
1103 return DependencyList\r
1104\r
f51461c8
LG
1105## CustomMakefile class\r
1106#\r
1107# This class encapsules makefie and its generation for module. It uses template to generate\r
1108# the content of makefile. The content of makefile will be got from ModuleAutoGen object.\r
1109#\r
1110class CustomMakefile(BuildFile):\r
1111 ## template used to generate the makefile for module with custom makefile\r
1112 _TEMPLATE_ = TemplateString('''\\r
1113${makefile_header}\r
1114\r
1115#\r
1116# Platform Macro Definition\r
1117#\r
1118PLATFORM_NAME = ${platform_name}\r
1119PLATFORM_GUID = ${platform_guid}\r
1120PLATFORM_VERSION = ${platform_version}\r
1121PLATFORM_RELATIVE_DIR = ${platform_relative_directory}\r
7a5f1426 1122PLATFORM_DIR = ${platform_dir}\r
f51461c8
LG
1123PLATFORM_OUTPUT_DIR = ${platform_output_directory}\r
1124\r
1125#\r
1126# Module Macro Definition\r
1127#\r
1128MODULE_NAME = ${module_name}\r
1129MODULE_GUID = ${module_guid}\r
867d1cd4 1130MODULE_NAME_GUID = ${module_name_guid}\r
f51461c8
LG
1131MODULE_VERSION = ${module_version}\r
1132MODULE_TYPE = ${module_type}\r
1133MODULE_FILE = ${module_file}\r
1134MODULE_FILE_BASE_NAME = ${module_file_base_name}\r
1135BASE_NAME = $(MODULE_NAME)\r
1136MODULE_RELATIVE_DIR = ${module_relative_directory}\r
01e418d6 1137MODULE_DIR = ${module_dir}\r
f51461c8
LG
1138\r
1139#\r
1140# Build Configuration Macro Definition\r
1141#\r
1142ARCH = ${architecture}\r
1143TOOLCHAIN = ${toolchain_tag}\r
1144TOOLCHAIN_TAG = ${toolchain_tag}\r
1145TARGET = ${build_target}\r
1146\r
1147#\r
1148# Build Directory Macro Definition\r
1149#\r
1150# PLATFORM_BUILD_DIR = ${platform_build_directory}\r
1151BUILD_DIR = ${platform_build_directory}\r
1152BIN_DIR = $(BUILD_DIR)${separator}${architecture}\r
1153LIB_DIR = $(BIN_DIR)\r
1154MODULE_BUILD_DIR = ${module_build_directory}\r
1155OUTPUT_DIR = ${module_output_directory}\r
1156DEBUG_DIR = ${module_debug_directory}\r
1157DEST_DIR_OUTPUT = $(OUTPUT_DIR)\r
1158DEST_DIR_DEBUG = $(DEBUG_DIR)\r
1159\r
1160#\r
1161# Tools definitions specific to this module\r
1162#\r
1163${BEGIN}${module_tool_definitions}\r
1164${END}\r
1165MAKE_FILE = ${makefile_path}\r
1166\r
1167#\r
1168# Shell Command Macro\r
1169#\r
1170${BEGIN}${shell_command_code} = ${shell_command}\r
1171${END}\r
1172\r
1173${custom_makefile_content}\r
1174\r
1175#\r
1176# Target used when called from platform makefile, which will bypass the build of dependent libraries\r
1177#\r
1178\r
1179pbuild: init all\r
1180\r
1181\r
1182#\r
1183# ModuleTarget\r
1184#\r
1185\r
1186mbuild: init all\r
1187\r
1188#\r
1189# Build Target used in multi-thread build mode, which no init target is needed\r
1190#\r
1191\r
1192tbuild: all\r
1193\r
1194#\r
1195# Initialization target: print build information and create necessary directories\r
1196#\r
1197init:\r
1198\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]\r
1199${BEGIN}\t-@${create_directory_command}\n${END}\\r
1200\r
1201''')\r
1202\r
1203 ## Constructor of CustomMakefile\r
1204 #\r
1205 # @param ModuleAutoGen Object of ModuleAutoGen class\r
1206 #\r
1207 def __init__(self, ModuleAutoGen):\r
1208 BuildFile.__init__(self, ModuleAutoGen)\r
1209 self.PlatformInfo = self._AutoGenObject.PlatformInfo\r
1210 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]\r
1211\r
1212 # Compose a dict object containing information used to do replacement in template\r
4c92c81d
CJ
1213 @property\r
1214 def _TemplateDict(self):\r
f51461c8 1215 Separator = self._SEP_[self._FileType]\r
7c12d613
JC
1216 MyAgo = self._AutoGenObject\r
1217 if self._FileType not in MyAgo.CustomMakefile:\r
f51461c8 1218 EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType,\r
7c12d613 1219 ExtraData="[%s]" % str(MyAgo))\r
01e418d6 1220 MakefilePath = mws.join(\r
7c12d613
JC
1221 MyAgo.WorkspaceDir,\r
1222 MyAgo.CustomMakefile[self._FileType]\r
f51461c8
LG
1223 )\r
1224 try:\r
1225 CustomMakefile = open(MakefilePath, 'r').read()\r
1226 except:\r
7c12d613
JC
1227 EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(MyAgo),\r
1228 ExtraData=MyAgo.CustomMakefile[self._FileType])\r
f51461c8
LG
1229\r
1230 # tools definitions\r
1231 ToolsDef = []\r
7c12d613 1232 for Tool in MyAgo.BuildOption:\r
f51461c8
LG
1233 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.\r
1234 if Tool == "MAKE":\r
1235 continue\r
7c12d613 1236 for Attr in MyAgo.BuildOption[Tool]:\r
f51461c8
LG
1237 if Attr == "FAMILY":\r
1238 continue\r
1239 elif Attr == "PATH":\r
7c12d613 1240 ToolsDef.append("%s = %s" % (Tool, MyAgo.BuildOption[Tool][Attr]))\r
f51461c8 1241 else:\r
7c12d613 1242 ToolsDef.append("%s_%s = %s" % (Tool, Attr, MyAgo.BuildOption[Tool][Attr]))\r
f51461c8
LG
1243 ToolsDef.append("")\r
1244\r
1245 MakefileName = self._FILE_NAME_[self._FileType]\r
1246 MakefileTemplateDict = {\r
1247 "makefile_header" : self._FILE_HEADER_[self._FileType],\r
1248 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),\r
1249 "platform_name" : self.PlatformInfo.Name,\r
1250 "platform_guid" : self.PlatformInfo.Guid,\r
1251 "platform_version" : self.PlatformInfo.Version,\r
1252 "platform_relative_directory": self.PlatformInfo.SourceDir,\r
1253 "platform_output_directory" : self.PlatformInfo.OutputDir,\r
7c12d613
JC
1254 "platform_dir" : MyAgo.Macros["PLATFORM_DIR"],\r
1255\r
1256 "module_name" : MyAgo.Name,\r
1257 "module_guid" : MyAgo.Guid,\r
1258 "module_name_guid" : MyAgo.UniqueBaseName,\r
1259 "module_version" : MyAgo.Version,\r
1260 "module_type" : MyAgo.ModuleType,\r
1261 "module_file" : MyAgo.MetaFile,\r
1262 "module_file_base_name" : MyAgo.MetaFile.BaseName,\r
1263 "module_relative_directory" : MyAgo.SourceDir,\r
1264 "module_dir" : mws.join (MyAgo.WorkspaceDir, MyAgo.SourceDir),\r
1265\r
1266 "architecture" : MyAgo.Arch,\r
1267 "toolchain_tag" : MyAgo.ToolChain,\r
1268 "build_target" : MyAgo.BuildTarget,\r
f51461c8
LG
1269\r
1270 "platform_build_directory" : self.PlatformInfo.BuildDir,\r
7c12d613
JC
1271 "module_build_directory" : MyAgo.BuildDir,\r
1272 "module_output_directory" : MyAgo.OutputDir,\r
1273 "module_debug_directory" : MyAgo.DebugDir,\r
f51461c8
LG
1274\r
1275 "separator" : Separator,\r
1276 "module_tool_definitions" : ToolsDef,\r
1277\r
1ccc4d89
LG
1278 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),\r
1279 "shell_command" : self._SHELL_CMD_[self._FileType].values(),\r
f51461c8
LG
1280\r
1281 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
1282 "custom_makefile_content" : CustomMakefile\r
1283 }\r
1284\r
1285 return MakefileTemplateDict\r
1286\r
f51461c8
LG
1287## PlatformMakefile class\r
1288#\r
1289# This class encapsules makefie and its generation for platform. It uses\r
1290# template to generate the content of makefile. The content of makefile will be\r
1291# got from PlatformAutoGen object.\r
1292#\r
1293class PlatformMakefile(BuildFile):\r
1294 ## template used to generate the makefile for platform\r
1295 _TEMPLATE_ = TemplateString('''\\r
1296${makefile_header}\r
1297\r
1298#\r
1299# Platform Macro Definition\r
1300#\r
1301PLATFORM_NAME = ${platform_name}\r
1302PLATFORM_GUID = ${platform_guid}\r
1303PLATFORM_VERSION = ${platform_version}\r
1304PLATFORM_FILE = ${platform_file}\r
7a5f1426 1305PLATFORM_DIR = ${platform_dir}\r
f51461c8
LG
1306PLATFORM_OUTPUT_DIR = ${platform_output_directory}\r
1307\r
1308#\r
1309# Build Configuration Macro Definition\r
1310#\r
1311TOOLCHAIN = ${toolchain_tag}\r
1312TOOLCHAIN_TAG = ${toolchain_tag}\r
1313TARGET = ${build_target}\r
1314\r
1315#\r
1316# Build Directory Macro Definition\r
1317#\r
1318BUILD_DIR = ${platform_build_directory}\r
1319FV_DIR = ${platform_build_directory}${separator}FV\r
1320\r
1321#\r
1322# Shell Command Macro\r
1323#\r
1324${BEGIN}${shell_command_code} = ${shell_command}\r
1325${END}\r
1326\r
1327MAKE = ${make_path}\r
1328MAKE_FILE = ${makefile_path}\r
1329\r
1330#\r
1331# Default target\r
1332#\r
1333all: init build_libraries build_modules\r
1334\r
1335#\r
1336# Initialization target: print build information and create necessary directories\r
1337#\r
1338init:\r
1339\t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]\r
1340\t${BEGIN}-@${create_directory_command}\r
1341\t${END}\r
1342#\r
1343# library build target\r
1344#\r
1345libraries: init build_libraries\r
1346\r
1347#\r
1348# module build target\r
1349#\r
1350modules: init build_libraries build_modules\r
1351\r
1352#\r
1353# Build all libraries:\r
1354#\r
1355build_libraries:\r
1356${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild\r
1357${END}\t@cd $(BUILD_DIR)\r
1358\r
1359#\r
1360# Build all modules:\r
1361#\r
1362build_modules:\r
1363${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild\r
1364${END}\t@cd $(BUILD_DIR)\r
1365\r
1366#\r
1367# Clean intermediate files\r
1368#\r
1369clean:\r
1370\t${BEGIN}-@${library_build_command} clean\r
1371\t${END}${BEGIN}-@${module_build_command} clean\r
1372\t${END}@cd $(BUILD_DIR)\r
1373\r
1374#\r
1375# Clean all generated files except to makefile\r
1376#\r
1377cleanall:\r
1378${BEGIN}\t${cleanall_command}\r
1379${END}\r
1380\r
1381#\r
1382# Clean all library files\r
1383#\r
1384cleanlib:\r
1385\t${BEGIN}-@${library_build_command} cleanall\r
1386\t${END}@cd $(BUILD_DIR)\n\r
1387''')\r
1388\r
1389 ## Constructor of PlatformMakefile\r
1390 #\r
1391 # @param ModuleAutoGen Object of PlatformAutoGen class\r
1392 #\r
1393 def __init__(self, PlatformAutoGen):\r
1394 BuildFile.__init__(self, PlatformAutoGen)\r
1395 self.ModuleBuildCommandList = []\r
1396 self.ModuleMakefileList = []\r
1397 self.IntermediateDirectoryList = []\r
1398 self.ModuleBuildDirectoryList = []\r
1399 self.LibraryBuildDirectoryList = []\r
03af2753 1400 self.LibraryMakeCommandList = []\r
f51461c8
LG
1401\r
1402 # Compose a dict object containing information used to do replacement in template\r
4c92c81d
CJ
1403 @property\r
1404 def _TemplateDict(self):\r
f51461c8
LG
1405 Separator = self._SEP_[self._FileType]\r
1406\r
7c12d613
JC
1407 MyAgo = self._AutoGenObject\r
1408 if "MAKE" not in MyAgo.ToolDefinition or "PATH" not in MyAgo.ToolDefinition["MAKE"]:\r
f51461c8 1409 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",\r
7c12d613 1410 ExtraData="[%s]" % str(MyAgo))\r
f51461c8
LG
1411\r
1412 self.IntermediateDirectoryList = ["$(BUILD_DIR)"]\r
1413 self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()\r
1414 self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()\r
1415\r
1416 MakefileName = self._FILE_NAME_[self._FileType]\r
1417 LibraryMakefileList = []\r
1418 LibraryMakeCommandList = []\r
1419 for D in self.LibraryBuildDirectoryList:\r
7c12d613 1420 D = self.PlaceMacro(D, {"BUILD_DIR":MyAgo.BuildDir})\r
f51461c8
LG
1421 Makefile = os.path.join(D, MakefileName)\r
1422 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}\r
1423 LibraryMakefileList.append(Makefile)\r
1424 LibraryMakeCommandList.append(Command)\r
03af2753 1425 self.LibraryMakeCommandList = LibraryMakeCommandList\r
f51461c8
LG
1426\r
1427 ModuleMakefileList = []\r
1428 ModuleMakeCommandList = []\r
1429 for D in self.ModuleBuildDirectoryList:\r
7c12d613 1430 D = self.PlaceMacro(D, {"BUILD_DIR":MyAgo.BuildDir})\r
f51461c8
LG
1431 Makefile = os.path.join(D, MakefileName)\r
1432 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}\r
1433 ModuleMakefileList.append(Makefile)\r
1434 ModuleMakeCommandList.append(Command)\r
1435\r
1436 MakefileTemplateDict = {\r
1437 "makefile_header" : self._FILE_HEADER_[self._FileType],\r
1438 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),\r
7c12d613 1439 "make_path" : MyAgo.ToolDefinition["MAKE"]["PATH"],\r
f51461c8 1440 "makefile_name" : MakefileName,\r
7c12d613
JC
1441 "platform_name" : MyAgo.Name,\r
1442 "platform_guid" : MyAgo.Guid,\r
1443 "platform_version" : MyAgo.Version,\r
1444 "platform_file" : MyAgo.MetaFile,\r
1445 "platform_relative_directory": MyAgo.SourceDir,\r
1446 "platform_output_directory" : MyAgo.OutputDir,\r
1447 "platform_build_directory" : MyAgo.BuildDir,\r
1448 "platform_dir" : MyAgo.Macros["PLATFORM_DIR"],\r
1449\r
1450 "toolchain_tag" : MyAgo.ToolChain,\r
1451 "build_target" : MyAgo.BuildTarget,\r
1ccc4d89
LG
1452 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),\r
1453 "shell_command" : self._SHELL_CMD_[self._FileType].values(),\r
7c12d613
JC
1454 "build_architecture_list" : MyAgo.Arch,\r
1455 "architecture" : MyAgo.Arch,\r
f51461c8
LG
1456 "separator" : Separator,\r
1457 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
1458 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),\r
1459 "library_makefile_list" : LibraryMakefileList,\r
1460 "module_makefile_list" : ModuleMakefileList,\r
1461 "library_build_command" : LibraryMakeCommandList,\r
1462 "module_build_command" : ModuleMakeCommandList,\r
1463 }\r
1464\r
1465 return MakefileTemplateDict\r
1466\r
1467 ## Get the root directory list for intermediate files of all modules build\r
1468 #\r
1469 # @retval list The list of directory\r
1470 #\r
1471 def GetModuleBuildDirectoryList(self):\r
1472 DirList = []\r
1473 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:\r
97fa0ee9
YL
1474 if not ModuleAutoGen.IsBinaryModule:\r
1475 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))\r
f51461c8
LG
1476 return DirList\r
1477\r
1478 ## Get the root directory list for intermediate files of all libraries build\r
1479 #\r
1480 # @retval list The list of directory\r
1481 #\r
1482 def GetLibraryBuildDirectoryList(self):\r
1483 DirList = []\r
1484 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:\r
97fa0ee9
YL
1485 if not LibraryAutoGen.IsBinaryModule:\r
1486 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))\r
f51461c8
LG
1487 return DirList\r
1488\r
f51461c8
LG
1489## TopLevelMakefile class\r
1490#\r
1491# This class encapsules makefie and its generation for entrance makefile. It\r
1492# uses template to generate the content of makefile. The content of makefile\r
1493# will be got from WorkspaceAutoGen object.\r
1494#\r
1495class TopLevelMakefile(BuildFile):\r
1496 ## template used to generate toplevel makefile\r
97fa0ee9 1497 _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
1498\r
1499 ## Constructor of TopLevelMakefile\r
1500 #\r
1501 # @param Workspace Object of WorkspaceAutoGen class\r
1502 #\r
1503 def __init__(self, Workspace):\r
1504 BuildFile.__init__(self, Workspace)\r
1505 self.IntermediateDirectoryList = []\r
1506\r
1507 # Compose a dict object containing information used to do replacement in template\r
4c92c81d
CJ
1508 @property\r
1509 def _TemplateDict(self):\r
f51461c8
LG
1510 Separator = self._SEP_[self._FileType]\r
1511\r
1512 # any platform autogen object is ok because we just need common information\r
7c12d613 1513 MyAgo = self._AutoGenObject\r
f51461c8 1514\r
7c12d613 1515 if "MAKE" not in MyAgo.ToolDefinition or "PATH" not in MyAgo.ToolDefinition["MAKE"]:\r
f51461c8 1516 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",\r
7c12d613 1517 ExtraData="[%s]" % str(MyAgo))\r
f51461c8 1518\r
7c12d613 1519 for Arch in MyAgo.ArchList:\r
f51461c8
LG
1520 self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch]))\r
1521 self.IntermediateDirectoryList.append("$(FV_DIR)")\r
1522\r
1523 # TRICK: for not generating GenFds call in makefile if no FDF file\r
1524 MacroList = []\r
7c12d613
JC
1525 if MyAgo.FdfFile is not None and MyAgo.FdfFile != "":\r
1526 FdfFileList = [MyAgo.FdfFile]\r
f51461c8 1527 # macros passed to GenFds\r
f51461c8
LG
1528 MacroDict = {}\r
1529 MacroDict.update(GlobalData.gGlobalDefines)\r
1530 MacroDict.update(GlobalData.gCommandLineDefines)\r
f51461c8
LG
1531 for MacroName in MacroDict:\r
1532 if MacroDict[MacroName] != "":\r
1533 MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))\r
1534 else:\r
1535 MacroList.append('"%s"' % MacroName)\r
1536 else:\r
1537 FdfFileList = []\r
1538\r
1539 # pass extra common options to external program called in makefile, currently GenFds.exe\r
1540 ExtraOption = ''\r
1541 LogLevel = EdkLogger.GetLevel()\r
1542 if LogLevel == EdkLogger.VERBOSE:\r
1543 ExtraOption += " -v"\r
1544 elif LogLevel <= EdkLogger.DEBUG_9:\r
1545 ExtraOption += " -d %d" % (LogLevel - 1)\r
1546 elif LogLevel == EdkLogger.QUIET:\r
1547 ExtraOption += " -q"\r
1548\r
1549 if GlobalData.gCaseInsensitive:\r
1550 ExtraOption += " -c"\r
37de70b7
YZ
1551 if GlobalData.gEnableGenfdsMultiThread:\r
1552 ExtraOption += " --genfds-multi-thread"\r
97fa0ee9
YL
1553 if GlobalData.gIgnoreSource:\r
1554 ExtraOption += " --ignore-sources"\r
1555\r
0f228f19
B
1556 for pcd in GlobalData.BuildOptionPcd:\r
1557 if pcd[2]:\r
1558 pcdname = '.'.join(pcd[0:3])\r
1559 else:\r
1560 pcdname = '.'.join(pcd[0:2])\r
1561 if pcd[3].startswith('{'):\r
1562 ExtraOption += " --pcd " + pcdname + '=' + 'H' + '"' + pcd[3] + '"'\r
1563 else:\r
1564 ExtraOption += " --pcd " + pcdname + '=' + pcd[3]\r
6b17c11b 1565\r
f51461c8
LG
1566 MakefileName = self._FILE_NAME_[self._FileType]\r
1567 SubBuildCommandList = []\r
7c12d613 1568 for A in MyAgo.ArchList:\r
f51461c8
LG
1569 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)}\r
1570 SubBuildCommandList.append(Command)\r
1571\r
1572 MakefileTemplateDict = {\r
1573 "makefile_header" : self._FILE_HEADER_[self._FileType],\r
1574 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),\r
7c12d613
JC
1575 "make_path" : MyAgo.ToolDefinition["MAKE"]["PATH"],\r
1576 "platform_name" : MyAgo.Name,\r
1577 "platform_guid" : MyAgo.Guid,\r
1578 "platform_version" : MyAgo.Version,\r
1579 "platform_build_directory" : MyAgo.BuildDir,\r
97fa0ee9 1580 "conf_directory" : GlobalData.gConfDirectory,\r
f51461c8 1581\r
7c12d613
JC
1582 "toolchain_tag" : MyAgo.ToolChain,\r
1583 "build_target" : MyAgo.BuildTarget,\r
1ccc4d89
LG
1584 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),\r
1585 "shell_command" : self._SHELL_CMD_[self._FileType].values(),\r
7c12d613
JC
1586 'arch' : list(MyAgo.ArchList),\r
1587 "build_architecture_list" : ','.join(MyAgo.ArchList),\r
f51461c8
LG
1588 "separator" : Separator,\r
1589 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
1590 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),\r
1591 "sub_build_command" : SubBuildCommandList,\r
1592 "fdf_file" : FdfFileList,\r
7c12d613
JC
1593 "active_platform" : str(MyAgo),\r
1594 "fd" : MyAgo.FdTargetList,\r
1595 "fv" : MyAgo.FvTargetList,\r
1596 "cap" : MyAgo.CapTargetList,\r
f51461c8
LG
1597 "extra_options" : ExtraOption,\r
1598 "macro" : MacroList,\r
1599 }\r
1600\r
1601 return MakefileTemplateDict\r
1602\r
1603 ## Get the root directory list for intermediate files of all modules build\r
1604 #\r
1605 # @retval list The list of directory\r
1606 #\r
1607 def GetModuleBuildDirectoryList(self):\r
1608 DirList = []\r
1609 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:\r
97fa0ee9
YL
1610 if not ModuleAutoGen.IsBinaryModule:\r
1611 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))\r
f51461c8
LG
1612 return DirList\r
1613\r
1614 ## Get the root directory list for intermediate files of all libraries build\r
1615 #\r
1616 # @retval list The list of directory\r
1617 #\r
1618 def GetLibraryBuildDirectoryList(self):\r
1619 DirList = []\r
1620 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:\r
97fa0ee9
YL
1621 if not LibraryAutoGen.IsBinaryModule:\r
1622 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))\r
f51461c8
LG
1623 return DirList\r
1624\r
f51461c8
LG
1625# This acts like the main() function for the script, unless it is 'import'ed into another script.\r
1626if __name__ == '__main__':\r
1627 pass\r
1628\r