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