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