]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/AutoGen/GenMake.py
BaseTools: add new command line option to support override PCD value
[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
1be2ed90 4# Copyright (c) 2007 - 2014, 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
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
47fea6af 30gIncludePattern = 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
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\r
147 _CD_TEMPLATE_ = {\r
148 "nmake" : 'if exist %(dir)s cd %(dir)s',\r
149 "gmake" : "test -e %(dir)s && cd %(dir)s"\r
150 }\r
151\r
152 _MAKE_TEMPLATE_ = {\r
153 "nmake" : 'if exist %(file)s "$(MAKE)" $(MAKE_FLAGS) -f %(file)s',\r
154 "gmake" : 'test -e %(file)s && "$(MAKE)" $(MAKE_FLAGS) -f %(file)s'\r
155 }\r
156\r
157 _INCLUDE_CMD_ = {\r
158 "nmake" : '!INCLUDE',\r
159 "gmake" : "include"\r
160 }\r
161\r
162 _INC_FLAG_ = {"MSFT" : "/I", "GCC" : "-I", "INTEL" : "-I", "RVCT" : "-I"}\r
163\r
164 ## Constructor of BuildFile\r
165 #\r
166 # @param AutoGenObject Object of AutoGen class\r
167 #\r
168 def __init__(self, AutoGenObject):\r
169 self._AutoGenObject = AutoGenObject\r
170 self._FileType = gMakeType\r
171\r
172 ## Create build file\r
173 #\r
174 # @param FileType Type of build file. Only nmake and gmake are supported now.\r
175 #\r
176 # @retval TRUE The build file is created or re-created successfully\r
177 # @retval FALSE The build file exists and is the same as the one to be generated\r
178 #\r
179 def Generate(self, FileType=gMakeType):\r
180 if FileType not in self._FILE_NAME_:\r
181 EdkLogger.error("build", PARAMETER_INVALID, "Invalid build type [%s]" % FileType,\r
182 ExtraData="[%s]" % str(self._AutoGenObject))\r
183 self._FileType = FileType\r
184 FileContent = self._TEMPLATE_.Replace(self._TemplateDict)\r
185 FileName = self._FILE_NAME_[FileType]\r
186 return SaveFileOnChange(os.path.join(self._AutoGenObject.MakeFileDir, FileName), FileContent, False)\r
187\r
188 ## Return a list of directory creation command string\r
189 #\r
190 # @param DirList The list of directory to be created\r
191 #\r
192 # @retval list The directory creation command list\r
193 #\r
194 def GetCreateDirectoryCommand(self, DirList):\r
195 return [self._MD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]\r
196\r
197 ## Return a list of directory removal command string\r
198 #\r
199 # @param DirList The list of directory to be removed\r
200 #\r
201 # @retval list The directory removal command list\r
202 #\r
203 def GetRemoveDirectoryCommand(self, DirList):\r
204 return [self._RD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]\r
205\r
206 def PlaceMacro(self, Path, MacroDefinitions={}):\r
207 if Path.startswith("$("):\r
208 return Path\r
209 else:\r
210 PathLength = len(Path)\r
211 for MacroName in MacroDefinitions:\r
212 MacroValue = MacroDefinitions[MacroName]\r
213 MacroValueLength = len(MacroValue)\r
214 if MacroValueLength <= PathLength and Path.startswith(MacroValue):\r
215 Path = "$(%s)%s" % (MacroName, Path[MacroValueLength:])\r
216 break\r
217 return Path\r
218\r
219## ModuleMakefile class\r
220#\r
221# This class encapsules makefie and its generation for module. It uses template to generate\r
222# the content of makefile. The content of makefile will be got from ModuleAutoGen object.\r
223#\r
224class ModuleMakefile(BuildFile):\r
225 ## template used to generate the makefile for module\r
226 _TEMPLATE_ = TemplateString('''\\r
227${makefile_header}\r
228\r
229#\r
230# Platform Macro Definition\r
231#\r
232PLATFORM_NAME = ${platform_name}\r
233PLATFORM_GUID = ${platform_guid}\r
234PLATFORM_VERSION = ${platform_version}\r
235PLATFORM_RELATIVE_DIR = ${platform_relative_directory}\r
236PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}\r
237PLATFORM_OUTPUT_DIR = ${platform_output_directory}\r
238\r
239#\r
240# Module Macro Definition\r
241#\r
242MODULE_NAME = ${module_name}\r
243MODULE_GUID = ${module_guid}\r
867d1cd4 244MODULE_NAME_GUID = ${module_name_guid}\r
f51461c8
LG
245MODULE_VERSION = ${module_version}\r
246MODULE_TYPE = ${module_type}\r
247MODULE_FILE = ${module_file}\r
248MODULE_FILE_BASE_NAME = ${module_file_base_name}\r
249BASE_NAME = $(MODULE_NAME)\r
250MODULE_RELATIVE_DIR = ${module_relative_directory}\r
97fa0ee9 251PACKAGE_RELATIVE_DIR = ${package_relative_directory}\r
01e418d6 252MODULE_DIR = ${module_dir}\r
f51461c8
LG
253\r
254MODULE_ENTRY_POINT = ${module_entry_point}\r
255ARCH_ENTRY_POINT = ${arch_entry_point}\r
256IMAGE_ENTRY_POINT = ${image_entry_point}\r
257\r
258${BEGIN}${module_extra_defines}\r
259${END}\r
260#\r
261# Build Configuration Macro Definition\r
262#\r
263ARCH = ${architecture}\r
264TOOLCHAIN = ${toolchain_tag}\r
265TOOLCHAIN_TAG = ${toolchain_tag}\r
266TARGET = ${build_target}\r
267\r
268#\r
269# Build Directory Macro Definition\r
270#\r
271# PLATFORM_BUILD_DIR = ${platform_build_directory}\r
272BUILD_DIR = ${platform_build_directory}\r
273BIN_DIR = $(BUILD_DIR)${separator}${architecture}\r
274LIB_DIR = $(BIN_DIR)\r
275MODULE_BUILD_DIR = ${module_build_directory}\r
276OUTPUT_DIR = ${module_output_directory}\r
277DEBUG_DIR = ${module_debug_directory}\r
278DEST_DIR_OUTPUT = $(OUTPUT_DIR)\r
279DEST_DIR_DEBUG = $(DEBUG_DIR)\r
280\r
281#\r
282# Shell Command Macro\r
283#\r
284${BEGIN}${shell_command_code} = ${shell_command}\r
285${END}\r
286\r
287#\r
288# Tools definitions specific to this module\r
289#\r
290${BEGIN}${module_tool_definitions}\r
291${END}\r
292MAKE_FILE = ${makefile_path}\r
293\r
294#\r
295# Build Macro\r
296#\r
297${BEGIN}${file_macro}\r
298${END}\r
299\r
300COMMON_DEPS = ${BEGIN}${common_dependency_file} \\\r
301 ${END}\r
302\r
303#\r
304# Overridable Target Macro Definitions\r
305#\r
306FORCE_REBUILD = force_build\r
307INIT_TARGET = init\r
308PCH_TARGET =\r
309BC_TARGET = ${BEGIN}${backward_compatible_target} ${END}\r
310CODA_TARGET = ${BEGIN}${remaining_build_target} \\\r
311 ${END}\r
312\r
313#\r
314# Default target, which will build dependent libraries in addition to source files\r
315#\r
316\r
317all: mbuild\r
318\r
319\r
320#\r
321# Target used when called from platform makefile, which will bypass the build of dependent libraries\r
322#\r
323\r
324pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)\r
325\r
326#\r
327# ModuleTarget\r
328#\r
329\r
330mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET)\r
331\r
332#\r
333# Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets\r
334#\r
335\r
336tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET)\r
337\r
338#\r
339# Phony target which is used to force executing commands for a target\r
340#\r
341force_build:\r
342\t-@\r
343\r
344#\r
345# Target to update the FD\r
346#\r
347\r
348fds: mbuild gen_fds\r
349\r
350#\r
351# Initialization target: print build information and create necessary directories\r
352#\r
353init: info dirs\r
354\r
355info:\r
356\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]\r
357\r
358dirs:\r
359${BEGIN}\t-@${create_directory_command}\n${END}\r
360\r
361strdefs:\r
362\t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h\r
363\r
364#\r
365# GenLibsTarget\r
366#\r
367gen_libs:\r
368\t${BEGIN}@"$(MAKE)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name}\r
369\t${END}@cd $(MODULE_BUILD_DIR)\r
370\r
371#\r
372# Build Flash Device Image\r
373#\r
374gen_fds:\r
375\t@"$(MAKE)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds\r
376\t@cd $(MODULE_BUILD_DIR)\r
377\r
378#\r
379# Individual Object Build Targets\r
380#\r
381${BEGIN}${file_build_target}\r
382${END}\r
383\r
384#\r
385# clean all intermediate files\r
386#\r
387clean:\r
388\t${BEGIN}${clean_command}\r
389\t${END}\r
390\r
391#\r
392# clean all generated files\r
393#\r
394cleanall:\r
395${BEGIN}\t${cleanall_command}\r
396${END}\t$(RM) *.pdb *.idb > NUL 2>&1\r
397\t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi\r
398\r
399#\r
400# clean all dependent libraries built\r
401#\r
402cleanlib:\r
403\t${BEGIN}-@${library_build_command} cleanall\r
404\t${END}@cd $(MODULE_BUILD_DIR)\n\n''')\r
405\r
406 _FILE_MACRO_TEMPLATE = TemplateString("${macro_name} = ${BEGIN} \\\n ${source_file}${END}\n")\r
407 _BUILD_TARGET_TEMPLATE = TemplateString("${BEGIN}${target} : ${deps}\n${END}\t${cmd}\n")\r
408\r
409 ## Constructor of ModuleMakefile\r
410 #\r
411 # @param ModuleAutoGen Object of ModuleAutoGen class\r
412 #\r
413 def __init__(self, ModuleAutoGen):\r
414 BuildFile.__init__(self, ModuleAutoGen)\r
415 self.PlatformInfo = self._AutoGenObject.PlatformInfo\r
416\r
417 self.ResultFileList = []\r
418 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]\r
419\r
420 self.SourceFileDatabase = {} # {file type : file path}\r
421 self.DestFileDatabase = {} # {file type : file path}\r
422 self.FileBuildTargetList = [] # [(src, target string)]\r
423 self.BuildTargetList = [] # [target string]\r
424 self.PendingBuildTargetList = [] # [FileBuildRule objects]\r
425 self.CommonFileDependency = []\r
426 self.FileListMacros = {}\r
427 self.ListFileMacros = {}\r
428\r
429 self.FileCache = {}\r
430 self.FileDependency = []\r
431 self.LibraryBuildCommandList = []\r
432 self.LibraryFileList = []\r
433 self.LibraryMakefileList = []\r
434 self.LibraryBuildDirectoryList = []\r
435 self.SystemLibraryList = []\r
436 self.Macros = sdict()\r
437 self.Macros["OUTPUT_DIR" ] = self._AutoGenObject.Macros["OUTPUT_DIR"]\r
438 self.Macros["DEBUG_DIR" ] = self._AutoGenObject.Macros["DEBUG_DIR"]\r
439 self.Macros["MODULE_BUILD_DIR"] = self._AutoGenObject.Macros["MODULE_BUILD_DIR"]\r
440 self.Macros["BIN_DIR" ] = self._AutoGenObject.Macros["BIN_DIR"]\r
441 self.Macros["BUILD_DIR" ] = self._AutoGenObject.Macros["BUILD_DIR"]\r
442 self.Macros["WORKSPACE" ] = self._AutoGenObject.Macros["WORKSPACE"]\r
443\r
444 # Compose a dict object containing information used to do replacement in template\r
445 def _CreateTemplateDict(self):\r
446 if self._FileType not in self._SEP_:\r
447 EdkLogger.error("build", PARAMETER_INVALID, "Invalid Makefile type [%s]" % self._FileType,\r
448 ExtraData="[%s]" % str(self._AutoGenObject))\r
449 Separator = self._SEP_[self._FileType]\r
450\r
451 # break build if no source files and binary files are found\r
452 if len(self._AutoGenObject.SourceFileList) == 0 and len(self._AutoGenObject.BinaryFileList) == 0:\r
453 EdkLogger.error("build", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]"\r
454 % (self._AutoGenObject.BuildTarget, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch),\r
455 ExtraData="[%s]" % str(self._AutoGenObject))\r
456\r
457 # convert dependent libraries to build command\r
458 self.ProcessDependentLibrary()\r
459 if len(self._AutoGenObject.Module.ModuleEntryPointList) > 0:\r
460 ModuleEntryPoint = self._AutoGenObject.Module.ModuleEntryPointList[0]\r
461 else:\r
462 ModuleEntryPoint = "_ModuleEntryPoint"\r
463\r
464 # Intel EBC compiler enforces EfiMain\r
465 if self._AutoGenObject.AutoGenVersion < 0x00010005 and self._AutoGenObject.Arch == "EBC":\r
466 ArchEntryPoint = "EfiMain"\r
467 else:\r
468 ArchEntryPoint = ModuleEntryPoint\r
469\r
470 if self._AutoGenObject.Arch == "EBC":\r
471 # EBC compiler always use "EfiStart" as entry point. Only applies to EdkII modules\r
472 ImageEntryPoint = "EfiStart"\r
473 elif self._AutoGenObject.AutoGenVersion < 0x00010005:\r
474 # Edk modules use entry point specified in INF file\r
475 ImageEntryPoint = ModuleEntryPoint\r
476 else:\r
477 # EdkII modules always use "_ModuleEntryPoint" as entry point\r
478 ImageEntryPoint = "_ModuleEntryPoint"\r
479\r
480 # tools definitions\r
481 ToolsDef = []\r
482 IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily]\r
483 for Tool in self._AutoGenObject.BuildOption:\r
484 for Attr in self._AutoGenObject.BuildOption[Tool]:\r
485 Value = self._AutoGenObject.BuildOption[Tool][Attr]\r
486 if Attr == "FAMILY":\r
487 continue\r
488 elif Attr == "PATH":\r
489 ToolsDef.append("%s = %s" % (Tool, Value))\r
490 else:\r
491 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.\r
492 if Tool == "MAKE":\r
493 continue\r
494 # Remove duplicated include path, if any\r
495 if Attr == "FLAGS":\r
496 Value = RemoveDupOption(Value, IncPrefix, self._AutoGenObject.IncludePathList)\r
497 ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))\r
498 ToolsDef.append("")\r
499\r
500 # convert source files and binary files to build targets\r
501 self.ResultFileList = [str(T.Target) for T in self._AutoGenObject.CodaTargetList]\r
47fea6af 502 if len(self.ResultFileList) == 0 and len(self._AutoGenObject.SourceFileList) <> 0:\r
f51461c8
LG
503 EdkLogger.error("build", AUTOGEN_ERROR, "Nothing to build",\r
504 ExtraData="[%s]" % str(self._AutoGenObject))\r
505\r
506 self.ProcessBuildTargetList()\r
507\r
508 # Generate macros used to represent input files\r
509 FileMacroList = [] # macro name = file list\r
510 for FileListMacro in self.FileListMacros:\r
511 FileMacro = self._FILE_MACRO_TEMPLATE.Replace(\r
512 {\r
513 "macro_name" : FileListMacro,\r
514 "source_file" : self.FileListMacros[FileListMacro]\r
515 }\r
516 )\r
517 FileMacroList.append(FileMacro)\r
518\r
519 # INC_LIST is special\r
520 FileMacro = ""\r
521 IncludePathList = []\r
522 for P in self._AutoGenObject.IncludePathList:\r
47fea6af 523 IncludePathList.append(IncPrefix + self.PlaceMacro(P, self.Macros))\r
f51461c8 524 if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:\r
47fea6af 525 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix + P)\r
f51461c8
LG
526 FileMacro += self._FILE_MACRO_TEMPLATE.Replace(\r
527 {\r
528 "macro_name" : "INC",\r
529 "source_file" : IncludePathList\r
530 }\r
531 )\r
532 FileMacroList.append(FileMacro)\r
533\r
534 # Generate macros used to represent files containing list of input files\r
535 for ListFileMacro in self.ListFileMacros:\r
47fea6af 536 ListFileName = os.path.join(self._AutoGenObject.OutputDir, "%s.lst" % ListFileMacro.lower()[:len(ListFileMacro) - 5])\r
f51461c8
LG
537 FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName))\r
538 SaveFileOnChange(\r
539 ListFileName,\r
540 "\n".join(self.ListFileMacros[ListFileMacro]),\r
541 False\r
542 )\r
543\r
544 # Edk modules need <BaseName>StrDefs.h for string ID\r
545 #if self._AutoGenObject.AutoGenVersion < 0x00010005 and len(self._AutoGenObject.UnicodeFileList) > 0:\r
546 # BcTargetList = ['strdefs']\r
547 #else:\r
548 # BcTargetList = []\r
549 BcTargetList = []\r
550\r
551 MakefileName = self._FILE_NAME_[self._FileType]\r
552 LibraryMakeCommandList = []\r
553 for D in self.LibraryBuildDirectoryList:\r
554 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)}\r
555 LibraryMakeCommandList.append(Command)\r
556\r
97fa0ee9 557 package_rel_dir = self._AutoGenObject.SourceDir\r
b442ad5c
YL
558 current_dir = self.Macros["WORKSPACE"]\r
559 found = False\r
560 while not found and os.sep in package_rel_dir:\r
561 index = package_rel_dir.index(os.sep)\r
05cc51ad 562 current_dir = mws.join(current_dir, package_rel_dir[:index])\r
b442ad5c
YL
563 for fl in os.listdir(current_dir):\r
564 if fl.endswith('.dec'):\r
565 found = True\r
566 break\r
567 package_rel_dir = package_rel_dir[index + 1:]\r
97fa0ee9 568\r
f51461c8
LG
569 MakefileTemplateDict = {\r
570 "makefile_header" : self._FILE_HEADER_[self._FileType],\r
571 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),\r
572 "makefile_name" : MakefileName,\r
573 "platform_name" : self.PlatformInfo.Name,\r
574 "platform_guid" : self.PlatformInfo.Guid,\r
575 "platform_version" : self.PlatformInfo.Version,\r
576 "platform_relative_directory": self.PlatformInfo.SourceDir,\r
577 "platform_output_directory" : self.PlatformInfo.OutputDir,\r
578\r
579 "module_name" : self._AutoGenObject.Name,\r
580 "module_guid" : self._AutoGenObject.Guid,\r
867d1cd4 581 "module_name_guid" : self._AutoGenObject._GetUniqueBaseName(),\r
f51461c8
LG
582 "module_version" : self._AutoGenObject.Version,\r
583 "module_type" : self._AutoGenObject.ModuleType,\r
584 "module_file" : self._AutoGenObject.MetaFile.Name,\r
585 "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName,\r
586 "module_relative_directory" : self._AutoGenObject.SourceDir,\r
01e418d6 587 "module_dir" : mws.join (self.Macros["WORKSPACE"], self._AutoGenObject.SourceDir),\r
97fa0ee9
YL
588 "package_relative_directory": package_rel_dir,\r
589 "module_extra_defines" : ["%s = %s" % (k, v) for k, v in self._AutoGenObject.Module.Defines.iteritems()],\r
f51461c8
LG
590\r
591 "architecture" : self._AutoGenObject.Arch,\r
592 "toolchain_tag" : self._AutoGenObject.ToolChain,\r
593 "build_target" : self._AutoGenObject.BuildTarget,\r
594\r
595 "platform_build_directory" : self.PlatformInfo.BuildDir,\r
596 "module_build_directory" : self._AutoGenObject.BuildDir,\r
597 "module_output_directory" : self._AutoGenObject.OutputDir,\r
598 "module_debug_directory" : self._AutoGenObject.DebugDir,\r
599\r
600 "separator" : Separator,\r
601 "module_tool_definitions" : ToolsDef,\r
602\r
603 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),\r
604 "shell_command" : self._SHELL_CMD_[self._FileType].values(),\r
605\r
606 "module_entry_point" : ModuleEntryPoint,\r
607 "image_entry_point" : ImageEntryPoint,\r
608 "arch_entry_point" : ArchEntryPoint,\r
609 "remaining_build_target" : self.ResultFileList,\r
610 "common_dependency_file" : self.CommonFileDependency,\r
611 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
612 "clean_command" : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]),\r
613 "cleanall_command" : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]),\r
614 "dependent_library_build_directory" : self.LibraryBuildDirectoryList,\r
615 "library_build_command" : LibraryMakeCommandList,\r
616 "file_macro" : FileMacroList,\r
617 "file_build_target" : self.BuildTargetList,\r
618 "backward_compatible_target": BcTargetList,\r
619 }\r
620\r
621 return MakefileTemplateDict\r
622\r
623 def ProcessBuildTargetList(self):\r
624 #\r
625 # Search dependency file list for each source file\r
626 #\r
627 ForceIncludedFile = []\r
628 for File in self._AutoGenObject.AutoGenFileList:\r
629 if File.Ext == '.h':\r
630 ForceIncludedFile.append(File)\r
631 SourceFileList = []\r
632 for Target in self._AutoGenObject.IntroTargetList:\r
633 SourceFileList.extend(Target.Inputs)\r
634\r
635 self.FileDependency = self.GetFileDependency(\r
636 SourceFileList,\r
637 ForceIncludedFile,\r
638 self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList\r
639 )\r
640 DepSet = None\r
641 for File in self.FileDependency:\r
642 if not self.FileDependency[File]:\r
643 self.FileDependency[File] = ['$(FORCE_REBUILD)']\r
644 continue\r
645 # skip non-C files\r
646 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":\r
647 continue\r
648 elif DepSet == None:\r
649 DepSet = set(self.FileDependency[File])\r
650 else:\r
651 DepSet &= set(self.FileDependency[File])\r
652 # in case nothing in SourceFileList\r
653 if DepSet == None:\r
654 DepSet = set()\r
655 #\r
656 # Extract common files list in the dependency files\r
657 #\r
658 for File in DepSet:\r
659 self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros))\r
660\r
661 for File in self.FileDependency:\r
662 # skip non-C files\r
663 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":\r
664 continue\r
665 NewDepSet = set(self.FileDependency[File])\r
666 NewDepSet -= DepSet\r
667 self.FileDependency[File] = ["$(COMMON_DEPS)"] + list(NewDepSet)\r
668\r
669 # Convert target description object to target string in makefile\r
670 for Type in self._AutoGenObject.Targets:\r
671 for T in self._AutoGenObject.Targets[Type]:\r
672 # Generate related macros if needed\r
673 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:\r
674 self.FileListMacros[T.FileListMacro] = []\r
675 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:\r
676 self.ListFileMacros[T.ListFileMacro] = []\r
677 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:\r
678 self.ListFileMacros[T.IncListFileMacro] = []\r
679\r
680 Deps = []\r
681 # Add force-dependencies\r
682 for Dep in T.Dependencies:\r
683 Deps.append(self.PlaceMacro(str(Dep), self.Macros))\r
684 # Add inclusion-dependencies\r
685 if len(T.Inputs) == 1 and T.Inputs[0] in self.FileDependency:\r
686 for F in self.FileDependency[T.Inputs[0]]:\r
687 Deps.append(self.PlaceMacro(str(F), self.Macros))\r
688 # Add source-dependencies\r
689 for F in T.Inputs:\r
690 NewFile = self.PlaceMacro(str(F), self.Macros)\r
691 # In order to use file list macro as dependency\r
692 if T.GenListFile:\r
285a1754
SD
693 # gnu tools need forward slash path separater, even on Windows\r
694 self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/'))\r
f51461c8
LG
695 self.FileListMacros[T.FileListMacro].append(NewFile)\r
696 elif T.GenFileListMacro:\r
697 self.FileListMacros[T.FileListMacro].append(NewFile)\r
698 else:\r
699 Deps.append(NewFile)\r
700\r
701 # Use file list macro as dependency\r
702 if T.GenFileListMacro:\r
703 Deps.append("$(%s)" % T.FileListMacro)\r
704\r
705 TargetDict = {\r
706 "target" : self.PlaceMacro(T.Target.Path, self.Macros),\r
707 "cmd" : "\n\t".join(T.Commands),\r
708 "deps" : Deps\r
709 }\r
710 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))\r
711\r
712 ## For creating makefile targets for dependent libraries\r
713 def ProcessDependentLibrary(self):\r
714 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:\r
715 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))\r
716\r
717 ## Return a list containing source file's dependencies\r
718 #\r
719 # @param FileList The list of source files\r
720 # @param ForceInculeList The list of files which will be included forcely\r
721 # @param SearchPathList The list of search path\r
722 #\r
723 # @retval dict The mapping between source file path and its dependencies\r
724 #\r
725 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):\r
726 Dependency = {}\r
727 for F in FileList:\r
728 Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)\r
729 return Dependency\r
730\r
731 ## Find dependencies for one source file\r
732 #\r
733 # By searching recursively "#include" directive in file, find out all the\r
734 # files needed by given source file. The dependecies will be only searched\r
735 # in given search path list.\r
736 #\r
737 # @param File The source file\r
738 # @param ForceInculeList The list of files which will be included forcely\r
739 # @param SearchPathList The list of search path\r
740 #\r
741 # @retval list The list of files the given source file depends on\r
742 #\r
743 def GetDependencyList(self, File, ForceList, SearchPathList):\r
744 EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File)\r
745 FileStack = [File] + ForceList\r
746 DependencySet = set()\r
747\r
748 if self._AutoGenObject.Arch not in gDependencyDatabase:\r
749 gDependencyDatabase[self._AutoGenObject.Arch] = {}\r
750 DepDb = gDependencyDatabase[self._AutoGenObject.Arch]\r
751\r
752 while len(FileStack) > 0:\r
753 F = FileStack.pop()\r
754\r
755 FullPathDependList = []\r
756 if F in self.FileCache:\r
757 for CacheFile in self.FileCache[F]:\r
758 FullPathDependList.append(CacheFile)\r
759 if CacheFile not in DependencySet:\r
760 FileStack.append(CacheFile)\r
761 DependencySet.update(FullPathDependList)\r
762 continue\r
763\r
764 CurrentFileDependencyList = []\r
765 if F in DepDb:\r
766 CurrentFileDependencyList = DepDb[F]\r
767 else:\r
768 try:\r
769 Fd = open(F.Path, 'r')\r
770 except BaseException, X:\r
47fea6af 771 EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path + "\n\t" + str(X))\r
f51461c8
LG
772\r
773 FileContent = Fd.read()\r
774 Fd.close()\r
775 if len(FileContent) == 0:\r
776 continue\r
777\r
778 if FileContent[0] == 0xff or FileContent[0] == 0xfe:\r
779 FileContent = unicode(FileContent, "utf-16")\r
780 IncludedFileList = gIncludePattern.findall(FileContent)\r
781\r
782 for Inc in IncludedFileList:\r
783 Inc = Inc.strip()\r
784 # if there's macro used to reference header file, expand it\r
785 HeaderList = gMacroPattern.findall(Inc)\r
786 if len(HeaderList) == 1 and len(HeaderList[0]) == 2:\r
787 HeaderType = HeaderList[0][0]\r
788 HeaderKey = HeaderList[0][1]\r
789 if HeaderType in gIncludeMacroConversion:\r
790 Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey}\r
791 else:\r
792 # not known macro used in #include, always build the file by\r
793 # returning a empty dependency\r
794 self.FileCache[File] = []\r
795 return []\r
796 Inc = os.path.normpath(Inc)\r
797 CurrentFileDependencyList.append(Inc)\r
798 DepDb[F] = CurrentFileDependencyList\r
799\r
800 CurrentFilePath = F.Dir\r
801 PathList = [CurrentFilePath] + SearchPathList\r
802 for Inc in CurrentFileDependencyList:\r
803 for SearchPath in PathList:\r
804 FilePath = os.path.join(SearchPath, Inc)\r
805 if FilePath in gIsFileMap:\r
806 if not gIsFileMap[FilePath]:\r
807 continue\r
808 # If isfile is called too many times, the performance is slow down.\r
809 elif not os.path.isfile(FilePath):\r
810 gIsFileMap[FilePath] = False\r
811 continue\r
812 else:\r
813 gIsFileMap[FilePath] = True\r
814 FilePath = PathClass(FilePath)\r
815 FullPathDependList.append(FilePath)\r
816 if FilePath not in DependencySet:\r
817 FileStack.append(FilePath)\r
818 break\r
819 else:\r
820 EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\\r
821 "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList)))\r
822\r
823 self.FileCache[F] = FullPathDependList\r
824 DependencySet.update(FullPathDependList)\r
825\r
826 DependencySet.update(ForceList)\r
827 if File in DependencySet:\r
828 DependencySet.remove(File)\r
829 DependencyList = list(DependencySet) # remove duplicate ones\r
830\r
831 return DependencyList\r
832\r
833 _TemplateDict = property(_CreateTemplateDict)\r
834\r
835## CustomMakefile class\r
836#\r
837# This class encapsules makefie and its generation for module. It uses template to generate\r
838# the content of makefile. The content of makefile will be got from ModuleAutoGen object.\r
839#\r
840class CustomMakefile(BuildFile):\r
841 ## template used to generate the makefile for module with custom makefile\r
842 _TEMPLATE_ = TemplateString('''\\r
843${makefile_header}\r
844\r
845#\r
846# Platform Macro Definition\r
847#\r
848PLATFORM_NAME = ${platform_name}\r
849PLATFORM_GUID = ${platform_guid}\r
850PLATFORM_VERSION = ${platform_version}\r
851PLATFORM_RELATIVE_DIR = ${platform_relative_directory}\r
852PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}\r
853PLATFORM_OUTPUT_DIR = ${platform_output_directory}\r
854\r
855#\r
856# Module Macro Definition\r
857#\r
858MODULE_NAME = ${module_name}\r
859MODULE_GUID = ${module_guid}\r
867d1cd4 860MODULE_NAME_GUID = ${module_name_guid}\r
f51461c8
LG
861MODULE_VERSION = ${module_version}\r
862MODULE_TYPE = ${module_type}\r
863MODULE_FILE = ${module_file}\r
864MODULE_FILE_BASE_NAME = ${module_file_base_name}\r
865BASE_NAME = $(MODULE_NAME)\r
866MODULE_RELATIVE_DIR = ${module_relative_directory}\r
01e418d6 867MODULE_DIR = ${module_dir}\r
f51461c8
LG
868\r
869#\r
870# Build Configuration Macro Definition\r
871#\r
872ARCH = ${architecture}\r
873TOOLCHAIN = ${toolchain_tag}\r
874TOOLCHAIN_TAG = ${toolchain_tag}\r
875TARGET = ${build_target}\r
876\r
877#\r
878# Build Directory Macro Definition\r
879#\r
880# PLATFORM_BUILD_DIR = ${platform_build_directory}\r
881BUILD_DIR = ${platform_build_directory}\r
882BIN_DIR = $(BUILD_DIR)${separator}${architecture}\r
883LIB_DIR = $(BIN_DIR)\r
884MODULE_BUILD_DIR = ${module_build_directory}\r
885OUTPUT_DIR = ${module_output_directory}\r
886DEBUG_DIR = ${module_debug_directory}\r
887DEST_DIR_OUTPUT = $(OUTPUT_DIR)\r
888DEST_DIR_DEBUG = $(DEBUG_DIR)\r
889\r
890#\r
891# Tools definitions specific to this module\r
892#\r
893${BEGIN}${module_tool_definitions}\r
894${END}\r
895MAKE_FILE = ${makefile_path}\r
896\r
897#\r
898# Shell Command Macro\r
899#\r
900${BEGIN}${shell_command_code} = ${shell_command}\r
901${END}\r
902\r
903${custom_makefile_content}\r
904\r
905#\r
906# Target used when called from platform makefile, which will bypass the build of dependent libraries\r
907#\r
908\r
909pbuild: init all\r
910\r
911\r
912#\r
913# ModuleTarget\r
914#\r
915\r
916mbuild: init all\r
917\r
918#\r
919# Build Target used in multi-thread build mode, which no init target is needed\r
920#\r
921\r
922tbuild: all\r
923\r
924#\r
925# Initialization target: print build information and create necessary directories\r
926#\r
927init:\r
928\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]\r
929${BEGIN}\t-@${create_directory_command}\n${END}\\r
930\r
931''')\r
932\r
933 ## Constructor of CustomMakefile\r
934 #\r
935 # @param ModuleAutoGen Object of ModuleAutoGen class\r
936 #\r
937 def __init__(self, ModuleAutoGen):\r
938 BuildFile.__init__(self, ModuleAutoGen)\r
939 self.PlatformInfo = self._AutoGenObject.PlatformInfo\r
940 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]\r
941\r
942 # Compose a dict object containing information used to do replacement in template\r
943 def _CreateTemplateDict(self):\r
944 Separator = self._SEP_[self._FileType]\r
945 if self._FileType not in self._AutoGenObject.CustomMakefile:\r
946 EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType,\r
947 ExtraData="[%s]" % str(self._AutoGenObject))\r
01e418d6 948 MakefilePath = mws.join(\r
f51461c8
LG
949 self._AutoGenObject.WorkspaceDir,\r
950 self._AutoGenObject.CustomMakefile[self._FileType]\r
951 )\r
952 try:\r
953 CustomMakefile = open(MakefilePath, 'r').read()\r
954 except:\r
955 EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(self._AutoGenObject),\r
956 ExtraData=self._AutoGenObject.CustomMakefile[self._FileType])\r
957\r
958 # tools definitions\r
959 ToolsDef = []\r
960 for Tool in self._AutoGenObject.BuildOption:\r
961 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.\r
962 if Tool == "MAKE":\r
963 continue\r
964 for Attr in self._AutoGenObject.BuildOption[Tool]:\r
965 if Attr == "FAMILY":\r
966 continue\r
967 elif Attr == "PATH":\r
968 ToolsDef.append("%s = %s" % (Tool, self._AutoGenObject.BuildOption[Tool][Attr]))\r
969 else:\r
970 ToolsDef.append("%s_%s = %s" % (Tool, Attr, self._AutoGenObject.BuildOption[Tool][Attr]))\r
971 ToolsDef.append("")\r
972\r
973 MakefileName = self._FILE_NAME_[self._FileType]\r
974 MakefileTemplateDict = {\r
975 "makefile_header" : self._FILE_HEADER_[self._FileType],\r
976 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),\r
977 "platform_name" : self.PlatformInfo.Name,\r
978 "platform_guid" : self.PlatformInfo.Guid,\r
979 "platform_version" : self.PlatformInfo.Version,\r
980 "platform_relative_directory": self.PlatformInfo.SourceDir,\r
981 "platform_output_directory" : self.PlatformInfo.OutputDir,\r
982\r
983 "module_name" : self._AutoGenObject.Name,\r
984 "module_guid" : self._AutoGenObject.Guid,\r
867d1cd4 985 "module_name_guid" : self._AutoGenObject._GetUniqueBaseName(),\r
f51461c8
LG
986 "module_version" : self._AutoGenObject.Version,\r
987 "module_type" : self._AutoGenObject.ModuleType,\r
988 "module_file" : self._AutoGenObject.MetaFile,\r
989 "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName,\r
990 "module_relative_directory" : self._AutoGenObject.SourceDir,\r
01e418d6 991 "module_dir" : mws.join (self._AutoGenObject.WorkspaceDir, self._AutoGenObject.SourceDir),\r
f51461c8
LG
992\r
993 "architecture" : self._AutoGenObject.Arch,\r
994 "toolchain_tag" : self._AutoGenObject.ToolChain,\r
995 "build_target" : self._AutoGenObject.BuildTarget,\r
996\r
997 "platform_build_directory" : self.PlatformInfo.BuildDir,\r
998 "module_build_directory" : self._AutoGenObject.BuildDir,\r
999 "module_output_directory" : self._AutoGenObject.OutputDir,\r
1000 "module_debug_directory" : self._AutoGenObject.DebugDir,\r
1001\r
1002 "separator" : Separator,\r
1003 "module_tool_definitions" : ToolsDef,\r
1004\r
1005 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),\r
1006 "shell_command" : self._SHELL_CMD_[self._FileType].values(),\r
1007\r
1008 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
1009 "custom_makefile_content" : CustomMakefile\r
1010 }\r
1011\r
1012 return MakefileTemplateDict\r
1013\r
1014 _TemplateDict = property(_CreateTemplateDict)\r
1015\r
1016## PlatformMakefile class\r
1017#\r
1018# This class encapsules makefie and its generation for platform. It uses\r
1019# template to generate the content of makefile. The content of makefile will be\r
1020# got from PlatformAutoGen object.\r
1021#\r
1022class PlatformMakefile(BuildFile):\r
1023 ## template used to generate the makefile for platform\r
1024 _TEMPLATE_ = TemplateString('''\\r
1025${makefile_header}\r
1026\r
1027#\r
1028# Platform Macro Definition\r
1029#\r
1030PLATFORM_NAME = ${platform_name}\r
1031PLATFORM_GUID = ${platform_guid}\r
1032PLATFORM_VERSION = ${platform_version}\r
1033PLATFORM_FILE = ${platform_file}\r
1034PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}\r
1035PLATFORM_OUTPUT_DIR = ${platform_output_directory}\r
1036\r
1037#\r
1038# Build Configuration Macro Definition\r
1039#\r
1040TOOLCHAIN = ${toolchain_tag}\r
1041TOOLCHAIN_TAG = ${toolchain_tag}\r
1042TARGET = ${build_target}\r
1043\r
1044#\r
1045# Build Directory Macro Definition\r
1046#\r
1047BUILD_DIR = ${platform_build_directory}\r
1048FV_DIR = ${platform_build_directory}${separator}FV\r
1049\r
1050#\r
1051# Shell Command Macro\r
1052#\r
1053${BEGIN}${shell_command_code} = ${shell_command}\r
1054${END}\r
1055\r
1056MAKE = ${make_path}\r
1057MAKE_FILE = ${makefile_path}\r
1058\r
1059#\r
1060# Default target\r
1061#\r
1062all: init build_libraries build_modules\r
1063\r
1064#\r
1065# Initialization target: print build information and create necessary directories\r
1066#\r
1067init:\r
1068\t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]\r
1069\t${BEGIN}-@${create_directory_command}\r
1070\t${END}\r
1071#\r
1072# library build target\r
1073#\r
1074libraries: init build_libraries\r
1075\r
1076#\r
1077# module build target\r
1078#\r
1079modules: init build_libraries build_modules\r
1080\r
1081#\r
1082# Build all libraries:\r
1083#\r
1084build_libraries:\r
1085${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild\r
1086${END}\t@cd $(BUILD_DIR)\r
1087\r
1088#\r
1089# Build all modules:\r
1090#\r
1091build_modules:\r
1092${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild\r
1093${END}\t@cd $(BUILD_DIR)\r
1094\r
1095#\r
1096# Clean intermediate files\r
1097#\r
1098clean:\r
1099\t${BEGIN}-@${library_build_command} clean\r
1100\t${END}${BEGIN}-@${module_build_command} clean\r
1101\t${END}@cd $(BUILD_DIR)\r
1102\r
1103#\r
1104# Clean all generated files except to makefile\r
1105#\r
1106cleanall:\r
1107${BEGIN}\t${cleanall_command}\r
1108${END}\r
1109\r
1110#\r
1111# Clean all library files\r
1112#\r
1113cleanlib:\r
1114\t${BEGIN}-@${library_build_command} cleanall\r
1115\t${END}@cd $(BUILD_DIR)\n\r
1116''')\r
1117\r
1118 ## Constructor of PlatformMakefile\r
1119 #\r
1120 # @param ModuleAutoGen Object of PlatformAutoGen class\r
1121 #\r
1122 def __init__(self, PlatformAutoGen):\r
1123 BuildFile.__init__(self, PlatformAutoGen)\r
1124 self.ModuleBuildCommandList = []\r
1125 self.ModuleMakefileList = []\r
1126 self.IntermediateDirectoryList = []\r
1127 self.ModuleBuildDirectoryList = []\r
1128 self.LibraryBuildDirectoryList = []\r
03af2753 1129 self.LibraryMakeCommandList = []\r
f51461c8
LG
1130\r
1131 # Compose a dict object containing information used to do replacement in template\r
1132 def _CreateTemplateDict(self):\r
1133 Separator = self._SEP_[self._FileType]\r
1134\r
1135 PlatformInfo = self._AutoGenObject\r
1136 if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:\r
1137 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",\r
1138 ExtraData="[%s]" % str(self._AutoGenObject))\r
1139\r
1140 self.IntermediateDirectoryList = ["$(BUILD_DIR)"]\r
1141 self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()\r
1142 self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()\r
1143\r
1144 MakefileName = self._FILE_NAME_[self._FileType]\r
1145 LibraryMakefileList = []\r
1146 LibraryMakeCommandList = []\r
1147 for D in self.LibraryBuildDirectoryList:\r
1148 D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})\r
1149 Makefile = os.path.join(D, MakefileName)\r
1150 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}\r
1151 LibraryMakefileList.append(Makefile)\r
1152 LibraryMakeCommandList.append(Command)\r
03af2753 1153 self.LibraryMakeCommandList = LibraryMakeCommandList\r
f51461c8
LG
1154\r
1155 ModuleMakefileList = []\r
1156 ModuleMakeCommandList = []\r
1157 for D in self.ModuleBuildDirectoryList:\r
1158 D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})\r
1159 Makefile = os.path.join(D, MakefileName)\r
1160 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}\r
1161 ModuleMakefileList.append(Makefile)\r
1162 ModuleMakeCommandList.append(Command)\r
1163\r
1164 MakefileTemplateDict = {\r
1165 "makefile_header" : self._FILE_HEADER_[self._FileType],\r
1166 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),\r
1167 "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"],\r
1168 "makefile_name" : MakefileName,\r
1169 "platform_name" : PlatformInfo.Name,\r
1170 "platform_guid" : PlatformInfo.Guid,\r
1171 "platform_version" : PlatformInfo.Version,\r
1172 "platform_file" : self._AutoGenObject.MetaFile,\r
1173 "platform_relative_directory": PlatformInfo.SourceDir,\r
1174 "platform_output_directory" : PlatformInfo.OutputDir,\r
1175 "platform_build_directory" : PlatformInfo.BuildDir,\r
1176\r
1177 "toolchain_tag" : PlatformInfo.ToolChain,\r
1178 "build_target" : PlatformInfo.BuildTarget,\r
1179 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),\r
1180 "shell_command" : self._SHELL_CMD_[self._FileType].values(),\r
1181 "build_architecture_list" : self._AutoGenObject.Arch,\r
1182 "architecture" : self._AutoGenObject.Arch,\r
1183 "separator" : Separator,\r
1184 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
1185 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),\r
1186 "library_makefile_list" : LibraryMakefileList,\r
1187 "module_makefile_list" : ModuleMakefileList,\r
1188 "library_build_command" : LibraryMakeCommandList,\r
1189 "module_build_command" : ModuleMakeCommandList,\r
1190 }\r
1191\r
1192 return MakefileTemplateDict\r
1193\r
1194 ## Get the root directory list for intermediate files of all modules build\r
1195 #\r
1196 # @retval list The list of directory\r
1197 #\r
1198 def GetModuleBuildDirectoryList(self):\r
1199 DirList = []\r
1200 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:\r
97fa0ee9
YL
1201 if not ModuleAutoGen.IsBinaryModule:\r
1202 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))\r
f51461c8
LG
1203 return DirList\r
1204\r
1205 ## Get the root directory list for intermediate files of all libraries build\r
1206 #\r
1207 # @retval list The list of directory\r
1208 #\r
1209 def GetLibraryBuildDirectoryList(self):\r
1210 DirList = []\r
1211 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:\r
97fa0ee9
YL
1212 if not LibraryAutoGen.IsBinaryModule:\r
1213 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))\r
f51461c8
LG
1214 return DirList\r
1215\r
1216 _TemplateDict = property(_CreateTemplateDict)\r
1217\r
1218## TopLevelMakefile class\r
1219#\r
1220# This class encapsules makefie and its generation for entrance makefile. It\r
1221# uses template to generate the content of makefile. The content of makefile\r
1222# will be got from WorkspaceAutoGen object.\r
1223#\r
1224class TopLevelMakefile(BuildFile):\r
1225 ## template used to generate toplevel makefile\r
97fa0ee9 1226 _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
1227\r
1228 ## Constructor of TopLevelMakefile\r
1229 #\r
1230 # @param Workspace Object of WorkspaceAutoGen class\r
1231 #\r
1232 def __init__(self, Workspace):\r
1233 BuildFile.__init__(self, Workspace)\r
1234 self.IntermediateDirectoryList = []\r
1235\r
1236 # Compose a dict object containing information used to do replacement in template\r
1237 def _CreateTemplateDict(self):\r
1238 Separator = self._SEP_[self._FileType]\r
1239\r
1240 # any platform autogen object is ok because we just need common information\r
1241 PlatformInfo = self._AutoGenObject\r
1242\r
1243 if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:\r
1244 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",\r
1245 ExtraData="[%s]" % str(self._AutoGenObject))\r
1246\r
1247 for Arch in PlatformInfo.ArchList:\r
1248 self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch]))\r
1249 self.IntermediateDirectoryList.append("$(FV_DIR)")\r
1250\r
1251 # TRICK: for not generating GenFds call in makefile if no FDF file\r
1252 MacroList = []\r
1253 if PlatformInfo.FdfFile != None and PlatformInfo.FdfFile != "":\r
1254 FdfFileList = [PlatformInfo.FdfFile]\r
1255 # macros passed to GenFds\r
1256 MacroList.append('"%s=%s"' % ("EFI_SOURCE", GlobalData.gEfiSource.replace('\\', '\\\\')))\r
1257 MacroList.append('"%s=%s"' % ("EDK_SOURCE", GlobalData.gEdkSource.replace('\\', '\\\\')))\r
1258 MacroDict = {}\r
1259 MacroDict.update(GlobalData.gGlobalDefines)\r
1260 MacroDict.update(GlobalData.gCommandLineDefines)\r
1261 MacroDict.pop("EFI_SOURCE", "dummy")\r
1262 MacroDict.pop("EDK_SOURCE", "dummy")\r
1263 for MacroName in MacroDict:\r
1264 if MacroDict[MacroName] != "":\r
1265 MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))\r
1266 else:\r
1267 MacroList.append('"%s"' % MacroName)\r
1268 else:\r
1269 FdfFileList = []\r
1270\r
1271 # pass extra common options to external program called in makefile, currently GenFds.exe\r
1272 ExtraOption = ''\r
1273 LogLevel = EdkLogger.GetLevel()\r
1274 if LogLevel == EdkLogger.VERBOSE:\r
1275 ExtraOption += " -v"\r
1276 elif LogLevel <= EdkLogger.DEBUG_9:\r
1277 ExtraOption += " -d %d" % (LogLevel - 1)\r
1278 elif LogLevel == EdkLogger.QUIET:\r
1279 ExtraOption += " -q"\r
1280\r
1281 if GlobalData.gCaseInsensitive:\r
1282 ExtraOption += " -c"\r
1283\r
97fa0ee9
YL
1284 if GlobalData.gIgnoreSource:\r
1285 ExtraOption += " --ignore-sources"\r
1286\r
f51461c8
LG
1287 MakefileName = self._FILE_NAME_[self._FileType]\r
1288 SubBuildCommandList = []\r
1289 for A in PlatformInfo.ArchList:\r
1290 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)}\r
1291 SubBuildCommandList.append(Command)\r
1292\r
1293 MakefileTemplateDict = {\r
1294 "makefile_header" : self._FILE_HEADER_[self._FileType],\r
1295 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),\r
1296 "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"],\r
1297 "platform_name" : PlatformInfo.Name,\r
1298 "platform_guid" : PlatformInfo.Guid,\r
1299 "platform_version" : PlatformInfo.Version,\r
1300 "platform_build_directory" : PlatformInfo.BuildDir,\r
97fa0ee9 1301 "conf_directory" : GlobalData.gConfDirectory,\r
f51461c8
LG
1302\r
1303 "toolchain_tag" : PlatformInfo.ToolChain,\r
1304 "build_target" : PlatformInfo.BuildTarget,\r
1305 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),\r
1306 "shell_command" : self._SHELL_CMD_[self._FileType].values(),\r
1307 'arch' : list(PlatformInfo.ArchList),\r
1308 "build_architecture_list" : ','.join(PlatformInfo.ArchList),\r
1309 "separator" : Separator,\r
1310 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
1311 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),\r
1312 "sub_build_command" : SubBuildCommandList,\r
1313 "fdf_file" : FdfFileList,\r
1314 "active_platform" : str(PlatformInfo),\r
1315 "fd" : PlatformInfo.FdTargetList,\r
1316 "fv" : PlatformInfo.FvTargetList,\r
1317 "cap" : PlatformInfo.CapTargetList,\r
1318 "extra_options" : ExtraOption,\r
1319 "macro" : MacroList,\r
1320 }\r
1321\r
1322 return MakefileTemplateDict\r
1323\r
1324 ## Get the root directory list for intermediate files of all modules build\r
1325 #\r
1326 # @retval list The list of directory\r
1327 #\r
1328 def GetModuleBuildDirectoryList(self):\r
1329 DirList = []\r
1330 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:\r
97fa0ee9
YL
1331 if not ModuleAutoGen.IsBinaryModule:\r
1332 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))\r
f51461c8
LG
1333 return DirList\r
1334\r
1335 ## Get the root directory list for intermediate files of all libraries build\r
1336 #\r
1337 # @retval list The list of directory\r
1338 #\r
1339 def GetLibraryBuildDirectoryList(self):\r
1340 DirList = []\r
1341 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:\r
97fa0ee9
YL
1342 if not LibraryAutoGen.IsBinaryModule:\r
1343 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))\r
f51461c8
LG
1344 return DirList\r
1345\r
1346 _TemplateDict = property(_CreateTemplateDict)\r
1347\r
1348# This acts like the main() function for the script, unless it is 'import'ed into another script.\r
1349if __name__ == '__main__':\r
1350 pass\r
1351\r