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