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