]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/AutoGen/GenMake.py
BaseTools: Update Build tool to support multiple workspaces
[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
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\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
f51461c8
LG
252MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory}\r
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
502 if len(self.ResultFileList) == 0 and len(self._AutoGenObject.SourceFileList) <> 0: \r
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
523 IncludePathList.append(IncPrefix+self.PlaceMacro(P, self.Macros))\r
524 if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros:\r
525 self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix+P)\r
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
536 ListFileName = os.path.join(self._AutoGenObject.OutputDir, "%s.lst" % ListFileMacro.lower()[:len(ListFileMacro)-5])\r
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
97fa0ee9
YL
587 "package_relative_directory": package_rel_dir,\r
588 "module_extra_defines" : ["%s = %s" % (k, v) for k, v in self._AutoGenObject.Module.Defines.iteritems()],\r
f51461c8
LG
589\r
590 "architecture" : self._AutoGenObject.Arch,\r
591 "toolchain_tag" : self._AutoGenObject.ToolChain,\r
592 "build_target" : self._AutoGenObject.BuildTarget,\r
593\r
594 "platform_build_directory" : self.PlatformInfo.BuildDir,\r
595 "module_build_directory" : self._AutoGenObject.BuildDir,\r
596 "module_output_directory" : self._AutoGenObject.OutputDir,\r
597 "module_debug_directory" : self._AutoGenObject.DebugDir,\r
598\r
599 "separator" : Separator,\r
600 "module_tool_definitions" : ToolsDef,\r
601\r
602 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),\r
603 "shell_command" : self._SHELL_CMD_[self._FileType].values(),\r
604\r
605 "module_entry_point" : ModuleEntryPoint,\r
606 "image_entry_point" : ImageEntryPoint,\r
607 "arch_entry_point" : ArchEntryPoint,\r
608 "remaining_build_target" : self.ResultFileList,\r
609 "common_dependency_file" : self.CommonFileDependency,\r
610 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
611 "clean_command" : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]),\r
612 "cleanall_command" : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]),\r
613 "dependent_library_build_directory" : self.LibraryBuildDirectoryList,\r
614 "library_build_command" : LibraryMakeCommandList,\r
615 "file_macro" : FileMacroList,\r
616 "file_build_target" : self.BuildTargetList,\r
617 "backward_compatible_target": BcTargetList,\r
618 }\r
619\r
620 return MakefileTemplateDict\r
621\r
622 def ProcessBuildTargetList(self):\r
623 #\r
624 # Search dependency file list for each source file\r
625 #\r
626 ForceIncludedFile = []\r
627 for File in self._AutoGenObject.AutoGenFileList:\r
628 if File.Ext == '.h':\r
629 ForceIncludedFile.append(File)\r
630 SourceFileList = []\r
631 for Target in self._AutoGenObject.IntroTargetList:\r
632 SourceFileList.extend(Target.Inputs)\r
633\r
634 self.FileDependency = self.GetFileDependency(\r
635 SourceFileList,\r
636 ForceIncludedFile,\r
637 self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList\r
638 )\r
639 DepSet = None\r
640 for File in self.FileDependency:\r
641 if not self.FileDependency[File]:\r
642 self.FileDependency[File] = ['$(FORCE_REBUILD)']\r
643 continue\r
644 # skip non-C files\r
645 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":\r
646 continue\r
647 elif DepSet == None:\r
648 DepSet = set(self.FileDependency[File])\r
649 else:\r
650 DepSet &= set(self.FileDependency[File])\r
651 # in case nothing in SourceFileList\r
652 if DepSet == None:\r
653 DepSet = set()\r
654 #\r
655 # Extract common files list in the dependency files\r
656 #\r
657 for File in DepSet:\r
658 self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros))\r
659\r
660 for File in self.FileDependency:\r
661 # skip non-C files\r
662 if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c":\r
663 continue\r
664 NewDepSet = set(self.FileDependency[File])\r
665 NewDepSet -= DepSet\r
666 self.FileDependency[File] = ["$(COMMON_DEPS)"] + list(NewDepSet)\r
667\r
668 # Convert target description object to target string in makefile\r
669 for Type in self._AutoGenObject.Targets:\r
670 for T in self._AutoGenObject.Targets[Type]:\r
671 # Generate related macros if needed\r
672 if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:\r
673 self.FileListMacros[T.FileListMacro] = []\r
674 if T.GenListFile and T.ListFileMacro not in self.ListFileMacros:\r
675 self.ListFileMacros[T.ListFileMacro] = []\r
676 if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros:\r
677 self.ListFileMacros[T.IncListFileMacro] = []\r
678\r
679 Deps = []\r
680 # Add force-dependencies\r
681 for Dep in T.Dependencies:\r
682 Deps.append(self.PlaceMacro(str(Dep), self.Macros))\r
683 # Add inclusion-dependencies\r
684 if len(T.Inputs) == 1 and T.Inputs[0] in self.FileDependency:\r
685 for F in self.FileDependency[T.Inputs[0]]:\r
686 Deps.append(self.PlaceMacro(str(F), self.Macros))\r
687 # Add source-dependencies\r
688 for F in T.Inputs:\r
689 NewFile = self.PlaceMacro(str(F), self.Macros)\r
690 # In order to use file list macro as dependency\r
691 if T.GenListFile:\r
285a1754
SD
692 # gnu tools need forward slash path separater, even on Windows\r
693 self.ListFileMacros[T.ListFileMacro].append(str(F).replace ('\\', '/'))\r
f51461c8
LG
694 self.FileListMacros[T.FileListMacro].append(NewFile)\r
695 elif T.GenFileListMacro:\r
696 self.FileListMacros[T.FileListMacro].append(NewFile)\r
697 else:\r
698 Deps.append(NewFile)\r
699\r
700 # Use file list macro as dependency\r
701 if T.GenFileListMacro:\r
702 Deps.append("$(%s)" % T.FileListMacro)\r
703\r
704 TargetDict = {\r
705 "target" : self.PlaceMacro(T.Target.Path, self.Macros),\r
706 "cmd" : "\n\t".join(T.Commands),\r
707 "deps" : Deps\r
708 }\r
709 self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))\r
710\r
711 ## For creating makefile targets for dependent libraries\r
712 def ProcessDependentLibrary(self):\r
713 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:\r
714 self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros))\r
715\r
716 ## Return a list containing source file's dependencies\r
717 #\r
718 # @param FileList The list of source files\r
719 # @param ForceInculeList The list of files which will be included forcely\r
720 # @param SearchPathList The list of search path\r
721 #\r
722 # @retval dict The mapping between source file path and its dependencies\r
723 #\r
724 def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):\r
725 Dependency = {}\r
726 for F in FileList:\r
727 Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)\r
728 return Dependency\r
729\r
730 ## Find dependencies for one source file\r
731 #\r
732 # By searching recursively "#include" directive in file, find out all the\r
733 # files needed by given source file. The dependecies will be only searched\r
734 # in given search path list.\r
735 #\r
736 # @param File The source file\r
737 # @param ForceInculeList The list of files which will be included forcely\r
738 # @param SearchPathList The list of search path\r
739 #\r
740 # @retval list The list of files the given source file depends on\r
741 #\r
742 def GetDependencyList(self, File, ForceList, SearchPathList):\r
743 EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File)\r
744 FileStack = [File] + ForceList\r
745 DependencySet = set()\r
746\r
747 if self._AutoGenObject.Arch not in gDependencyDatabase:\r
748 gDependencyDatabase[self._AutoGenObject.Arch] = {}\r
749 DepDb = gDependencyDatabase[self._AutoGenObject.Arch]\r
750\r
751 while len(FileStack) > 0:\r
752 F = FileStack.pop()\r
753\r
754 FullPathDependList = []\r
755 if F in self.FileCache:\r
756 for CacheFile in self.FileCache[F]:\r
757 FullPathDependList.append(CacheFile)\r
758 if CacheFile not in DependencySet:\r
759 FileStack.append(CacheFile)\r
760 DependencySet.update(FullPathDependList)\r
761 continue\r
762\r
763 CurrentFileDependencyList = []\r
764 if F in DepDb:\r
765 CurrentFileDependencyList = DepDb[F]\r
766 else:\r
767 try:\r
768 Fd = open(F.Path, 'r')\r
769 except BaseException, X:\r
770 EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path+"\n\t"+str(X))\r
771\r
772 FileContent = Fd.read()\r
773 Fd.close()\r
774 if len(FileContent) == 0:\r
775 continue\r
776\r
777 if FileContent[0] == 0xff or FileContent[0] == 0xfe:\r
778 FileContent = unicode(FileContent, "utf-16")\r
779 IncludedFileList = gIncludePattern.findall(FileContent)\r
780\r
781 for Inc in IncludedFileList:\r
782 Inc = Inc.strip()\r
783 # if there's macro used to reference header file, expand it\r
784 HeaderList = gMacroPattern.findall(Inc)\r
785 if len(HeaderList) == 1 and len(HeaderList[0]) == 2:\r
786 HeaderType = HeaderList[0][0]\r
787 HeaderKey = HeaderList[0][1]\r
788 if HeaderType in gIncludeMacroConversion:\r
789 Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey}\r
790 else:\r
791 # not known macro used in #include, always build the file by\r
792 # returning a empty dependency\r
793 self.FileCache[File] = []\r
794 return []\r
795 Inc = os.path.normpath(Inc)\r
796 CurrentFileDependencyList.append(Inc)\r
797 DepDb[F] = CurrentFileDependencyList\r
798\r
799 CurrentFilePath = F.Dir\r
800 PathList = [CurrentFilePath] + SearchPathList\r
801 for Inc in CurrentFileDependencyList:\r
802 for SearchPath in PathList:\r
803 FilePath = os.path.join(SearchPath, Inc)\r
804 if FilePath in gIsFileMap:\r
805 if not gIsFileMap[FilePath]:\r
806 continue\r
807 # If isfile is called too many times, the performance is slow down.\r
808 elif not os.path.isfile(FilePath):\r
809 gIsFileMap[FilePath] = False\r
810 continue\r
811 else:\r
812 gIsFileMap[FilePath] = True\r
813 FilePath = PathClass(FilePath)\r
814 FullPathDependList.append(FilePath)\r
815 if FilePath not in DependencySet:\r
816 FileStack.append(FilePath)\r
817 break\r
818 else:\r
819 EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\\r
820 "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList)))\r
821\r
822 self.FileCache[F] = FullPathDependList\r
823 DependencySet.update(FullPathDependList)\r
824\r
825 DependencySet.update(ForceList)\r
826 if File in DependencySet:\r
827 DependencySet.remove(File)\r
828 DependencyList = list(DependencySet) # remove duplicate ones\r
829\r
830 return DependencyList\r
831\r
832 _TemplateDict = property(_CreateTemplateDict)\r
833\r
834## CustomMakefile class\r
835#\r
836# This class encapsules makefie and its generation for module. It uses template to generate\r
837# the content of makefile. The content of makefile will be got from ModuleAutoGen object.\r
838#\r
839class CustomMakefile(BuildFile):\r
840 ## template used to generate the makefile for module with custom makefile\r
841 _TEMPLATE_ = TemplateString('''\\r
842${makefile_header}\r
843\r
844#\r
845# Platform Macro Definition\r
846#\r
847PLATFORM_NAME = ${platform_name}\r
848PLATFORM_GUID = ${platform_guid}\r
849PLATFORM_VERSION = ${platform_version}\r
850PLATFORM_RELATIVE_DIR = ${platform_relative_directory}\r
851PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}\r
852PLATFORM_OUTPUT_DIR = ${platform_output_directory}\r
853\r
854#\r
855# Module Macro Definition\r
856#\r
857MODULE_NAME = ${module_name}\r
858MODULE_GUID = ${module_guid}\r
867d1cd4 859MODULE_NAME_GUID = ${module_name_guid}\r
f51461c8
LG
860MODULE_VERSION = ${module_version}\r
861MODULE_TYPE = ${module_type}\r
862MODULE_FILE = ${module_file}\r
863MODULE_FILE_BASE_NAME = ${module_file_base_name}\r
864BASE_NAME = $(MODULE_NAME)\r
865MODULE_RELATIVE_DIR = ${module_relative_directory}\r
866MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory}\r
867\r
868#\r
869# Build Configuration Macro Definition\r
870#\r
871ARCH = ${architecture}\r
872TOOLCHAIN = ${toolchain_tag}\r
873TOOLCHAIN_TAG = ${toolchain_tag}\r
874TARGET = ${build_target}\r
875\r
876#\r
877# Build Directory Macro Definition\r
878#\r
879# PLATFORM_BUILD_DIR = ${platform_build_directory}\r
880BUILD_DIR = ${platform_build_directory}\r
881BIN_DIR = $(BUILD_DIR)${separator}${architecture}\r
882LIB_DIR = $(BIN_DIR)\r
883MODULE_BUILD_DIR = ${module_build_directory}\r
884OUTPUT_DIR = ${module_output_directory}\r
885DEBUG_DIR = ${module_debug_directory}\r
886DEST_DIR_OUTPUT = $(OUTPUT_DIR)\r
887DEST_DIR_DEBUG = $(DEBUG_DIR)\r
888\r
889#\r
890# Tools definitions specific to this module\r
891#\r
892${BEGIN}${module_tool_definitions}\r
893${END}\r
894MAKE_FILE = ${makefile_path}\r
895\r
896#\r
897# Shell Command Macro\r
898#\r
899${BEGIN}${shell_command_code} = ${shell_command}\r
900${END}\r
901\r
902${custom_makefile_content}\r
903\r
904#\r
905# Target used when called from platform makefile, which will bypass the build of dependent libraries\r
906#\r
907\r
908pbuild: init all\r
909\r
910\r
911#\r
912# ModuleTarget\r
913#\r
914\r
915mbuild: init all\r
916\r
917#\r
918# Build Target used in multi-thread build mode, which no init target is needed\r
919#\r
920\r
921tbuild: all\r
922\r
923#\r
924# Initialization target: print build information and create necessary directories\r
925#\r
926init:\r
927\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)]\r
928${BEGIN}\t-@${create_directory_command}\n${END}\\r
929\r
930''')\r
931\r
932 ## Constructor of CustomMakefile\r
933 #\r
934 # @param ModuleAutoGen Object of ModuleAutoGen class\r
935 #\r
936 def __init__(self, ModuleAutoGen):\r
937 BuildFile.__init__(self, ModuleAutoGen)\r
938 self.PlatformInfo = self._AutoGenObject.PlatformInfo\r
939 self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]\r
940\r
941 # Compose a dict object containing information used to do replacement in template\r
942 def _CreateTemplateDict(self):\r
943 Separator = self._SEP_[self._FileType]\r
944 if self._FileType not in self._AutoGenObject.CustomMakefile:\r
945 EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType,\r
946 ExtraData="[%s]" % str(self._AutoGenObject))\r
947 MakefilePath = os.path.join(\r
948 self._AutoGenObject.WorkspaceDir,\r
949 self._AutoGenObject.CustomMakefile[self._FileType]\r
950 )\r
951 try:\r
952 CustomMakefile = open(MakefilePath, 'r').read()\r
953 except:\r
954 EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(self._AutoGenObject),\r
955 ExtraData=self._AutoGenObject.CustomMakefile[self._FileType])\r
956\r
957 # tools definitions\r
958 ToolsDef = []\r
959 for Tool in self._AutoGenObject.BuildOption:\r
960 # Don't generate MAKE_FLAGS in makefile. It's put in environment variable.\r
961 if Tool == "MAKE":\r
962 continue\r
963 for Attr in self._AutoGenObject.BuildOption[Tool]:\r
964 if Attr == "FAMILY":\r
965 continue\r
966 elif Attr == "PATH":\r
967 ToolsDef.append("%s = %s" % (Tool, self._AutoGenObject.BuildOption[Tool][Attr]))\r
968 else:\r
969 ToolsDef.append("%s_%s = %s" % (Tool, Attr, self._AutoGenObject.BuildOption[Tool][Attr]))\r
970 ToolsDef.append("")\r
971\r
972 MakefileName = self._FILE_NAME_[self._FileType]\r
973 MakefileTemplateDict = {\r
974 "makefile_header" : self._FILE_HEADER_[self._FileType],\r
975 "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),\r
976 "platform_name" : self.PlatformInfo.Name,\r
977 "platform_guid" : self.PlatformInfo.Guid,\r
978 "platform_version" : self.PlatformInfo.Version,\r
979 "platform_relative_directory": self.PlatformInfo.SourceDir,\r
980 "platform_output_directory" : self.PlatformInfo.OutputDir,\r
981\r
982 "module_name" : self._AutoGenObject.Name,\r
983 "module_guid" : self._AutoGenObject.Guid,\r
867d1cd4 984 "module_name_guid" : self._AutoGenObject._GetUniqueBaseName(),\r
f51461c8
LG
985 "module_version" : self._AutoGenObject.Version,\r
986 "module_type" : self._AutoGenObject.ModuleType,\r
987 "module_file" : self._AutoGenObject.MetaFile,\r
988 "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName,\r
989 "module_relative_directory" : self._AutoGenObject.SourceDir,\r
990\r
991 "architecture" : self._AutoGenObject.Arch,\r
992 "toolchain_tag" : self._AutoGenObject.ToolChain,\r
993 "build_target" : self._AutoGenObject.BuildTarget,\r
994\r
995 "platform_build_directory" : self.PlatformInfo.BuildDir,\r
996 "module_build_directory" : self._AutoGenObject.BuildDir,\r
997 "module_output_directory" : self._AutoGenObject.OutputDir,\r
998 "module_debug_directory" : self._AutoGenObject.DebugDir,\r
999\r
1000 "separator" : Separator,\r
1001 "module_tool_definitions" : ToolsDef,\r
1002\r
1003 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),\r
1004 "shell_command" : self._SHELL_CMD_[self._FileType].values(),\r
1005\r
1006 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
1007 "custom_makefile_content" : CustomMakefile\r
1008 }\r
1009\r
1010 return MakefileTemplateDict\r
1011\r
1012 _TemplateDict = property(_CreateTemplateDict)\r
1013\r
1014## PlatformMakefile class\r
1015#\r
1016# This class encapsules makefie and its generation for platform. It uses\r
1017# template to generate the content of makefile. The content of makefile will be\r
1018# got from PlatformAutoGen object.\r
1019#\r
1020class PlatformMakefile(BuildFile):\r
1021 ## template used to generate the makefile for platform\r
1022 _TEMPLATE_ = TemplateString('''\\r
1023${makefile_header}\r
1024\r
1025#\r
1026# Platform Macro Definition\r
1027#\r
1028PLATFORM_NAME = ${platform_name}\r
1029PLATFORM_GUID = ${platform_guid}\r
1030PLATFORM_VERSION = ${platform_version}\r
1031PLATFORM_FILE = ${platform_file}\r
1032PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}\r
1033PLATFORM_OUTPUT_DIR = ${platform_output_directory}\r
1034\r
1035#\r
1036# Build Configuration Macro Definition\r
1037#\r
1038TOOLCHAIN = ${toolchain_tag}\r
1039TOOLCHAIN_TAG = ${toolchain_tag}\r
1040TARGET = ${build_target}\r
1041\r
1042#\r
1043# Build Directory Macro Definition\r
1044#\r
1045BUILD_DIR = ${platform_build_directory}\r
1046FV_DIR = ${platform_build_directory}${separator}FV\r
1047\r
1048#\r
1049# Shell Command Macro\r
1050#\r
1051${BEGIN}${shell_command_code} = ${shell_command}\r
1052${END}\r
1053\r
1054MAKE = ${make_path}\r
1055MAKE_FILE = ${makefile_path}\r
1056\r
1057#\r
1058# Default target\r
1059#\r
1060all: init build_libraries build_modules\r
1061\r
1062#\r
1063# Initialization target: print build information and create necessary directories\r
1064#\r
1065init:\r
1066\t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}]\r
1067\t${BEGIN}-@${create_directory_command}\r
1068\t${END}\r
1069#\r
1070# library build target\r
1071#\r
1072libraries: init build_libraries\r
1073\r
1074#\r
1075# module build target\r
1076#\r
1077modules: init build_libraries build_modules\r
1078\r
1079#\r
1080# Build all libraries:\r
1081#\r
1082build_libraries:\r
1083${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild\r
1084${END}\t@cd $(BUILD_DIR)\r
1085\r
1086#\r
1087# Build all modules:\r
1088#\r
1089build_modules:\r
1090${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild\r
1091${END}\t@cd $(BUILD_DIR)\r
1092\r
1093#\r
1094# Clean intermediate files\r
1095#\r
1096clean:\r
1097\t${BEGIN}-@${library_build_command} clean\r
1098\t${END}${BEGIN}-@${module_build_command} clean\r
1099\t${END}@cd $(BUILD_DIR)\r
1100\r
1101#\r
1102# Clean all generated files except to makefile\r
1103#\r
1104cleanall:\r
1105${BEGIN}\t${cleanall_command}\r
1106${END}\r
1107\r
1108#\r
1109# Clean all library files\r
1110#\r
1111cleanlib:\r
1112\t${BEGIN}-@${library_build_command} cleanall\r
1113\t${END}@cd $(BUILD_DIR)\n\r
1114''')\r
1115\r
1116 ## Constructor of PlatformMakefile\r
1117 #\r
1118 # @param ModuleAutoGen Object of PlatformAutoGen class\r
1119 #\r
1120 def __init__(self, PlatformAutoGen):\r
1121 BuildFile.__init__(self, PlatformAutoGen)\r
1122 self.ModuleBuildCommandList = []\r
1123 self.ModuleMakefileList = []\r
1124 self.IntermediateDirectoryList = []\r
1125 self.ModuleBuildDirectoryList = []\r
1126 self.LibraryBuildDirectoryList = []\r
03af2753 1127 self.LibraryMakeCommandList = []\r
f51461c8
LG
1128\r
1129 # Compose a dict object containing information used to do replacement in template\r
1130 def _CreateTemplateDict(self):\r
1131 Separator = self._SEP_[self._FileType]\r
1132\r
1133 PlatformInfo = self._AutoGenObject\r
1134 if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:\r
1135 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",\r
1136 ExtraData="[%s]" % str(self._AutoGenObject))\r
1137\r
1138 self.IntermediateDirectoryList = ["$(BUILD_DIR)"]\r
1139 self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()\r
1140 self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()\r
1141\r
1142 MakefileName = self._FILE_NAME_[self._FileType]\r
1143 LibraryMakefileList = []\r
1144 LibraryMakeCommandList = []\r
1145 for D in self.LibraryBuildDirectoryList:\r
1146 D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})\r
1147 Makefile = os.path.join(D, MakefileName)\r
1148 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}\r
1149 LibraryMakefileList.append(Makefile)\r
1150 LibraryMakeCommandList.append(Command)\r
03af2753 1151 self.LibraryMakeCommandList = LibraryMakeCommandList\r
f51461c8
LG
1152\r
1153 ModuleMakefileList = []\r
1154 ModuleMakeCommandList = []\r
1155 for D in self.ModuleBuildDirectoryList:\r
1156 D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir})\r
1157 Makefile = os.path.join(D, MakefileName)\r
1158 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}\r
1159 ModuleMakefileList.append(Makefile)\r
1160 ModuleMakeCommandList.append(Command)\r
1161\r
1162 MakefileTemplateDict = {\r
1163 "makefile_header" : self._FILE_HEADER_[self._FileType],\r
1164 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),\r
1165 "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"],\r
1166 "makefile_name" : MakefileName,\r
1167 "platform_name" : PlatformInfo.Name,\r
1168 "platform_guid" : PlatformInfo.Guid,\r
1169 "platform_version" : PlatformInfo.Version,\r
1170 "platform_file" : self._AutoGenObject.MetaFile,\r
1171 "platform_relative_directory": PlatformInfo.SourceDir,\r
1172 "platform_output_directory" : PlatformInfo.OutputDir,\r
1173 "platform_build_directory" : PlatformInfo.BuildDir,\r
1174\r
1175 "toolchain_tag" : PlatformInfo.ToolChain,\r
1176 "build_target" : PlatformInfo.BuildTarget,\r
1177 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),\r
1178 "shell_command" : self._SHELL_CMD_[self._FileType].values(),\r
1179 "build_architecture_list" : self._AutoGenObject.Arch,\r
1180 "architecture" : self._AutoGenObject.Arch,\r
1181 "separator" : Separator,\r
1182 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
1183 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),\r
1184 "library_makefile_list" : LibraryMakefileList,\r
1185 "module_makefile_list" : ModuleMakefileList,\r
1186 "library_build_command" : LibraryMakeCommandList,\r
1187 "module_build_command" : ModuleMakeCommandList,\r
1188 }\r
1189\r
1190 return MakefileTemplateDict\r
1191\r
1192 ## Get the root directory list for intermediate files of all modules build\r
1193 #\r
1194 # @retval list The list of directory\r
1195 #\r
1196 def GetModuleBuildDirectoryList(self):\r
1197 DirList = []\r
1198 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:\r
97fa0ee9
YL
1199 if not ModuleAutoGen.IsBinaryModule:\r
1200 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))\r
f51461c8
LG
1201 return DirList\r
1202\r
1203 ## Get the root directory list for intermediate files of all libraries build\r
1204 #\r
1205 # @retval list The list of directory\r
1206 #\r
1207 def GetLibraryBuildDirectoryList(self):\r
1208 DirList = []\r
1209 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:\r
97fa0ee9
YL
1210 if not LibraryAutoGen.IsBinaryModule:\r
1211 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))\r
f51461c8
LG
1212 return DirList\r
1213\r
1214 _TemplateDict = property(_CreateTemplateDict)\r
1215\r
1216## TopLevelMakefile class\r
1217#\r
1218# This class encapsules makefie and its generation for entrance makefile. It\r
1219# uses template to generate the content of makefile. The content of makefile\r
1220# will be got from WorkspaceAutoGen object.\r
1221#\r
1222class TopLevelMakefile(BuildFile):\r
1223 ## template used to generate toplevel makefile\r
97fa0ee9 1224 _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
1225\r
1226 ## Constructor of TopLevelMakefile\r
1227 #\r
1228 # @param Workspace Object of WorkspaceAutoGen class\r
1229 #\r
1230 def __init__(self, Workspace):\r
1231 BuildFile.__init__(self, Workspace)\r
1232 self.IntermediateDirectoryList = []\r
1233\r
1234 # Compose a dict object containing information used to do replacement in template\r
1235 def _CreateTemplateDict(self):\r
1236 Separator = self._SEP_[self._FileType]\r
1237\r
1238 # any platform autogen object is ok because we just need common information\r
1239 PlatformInfo = self._AutoGenObject\r
1240\r
1241 if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]:\r
1242 EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!",\r
1243 ExtraData="[%s]" % str(self._AutoGenObject))\r
1244\r
1245 for Arch in PlatformInfo.ArchList:\r
1246 self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch]))\r
1247 self.IntermediateDirectoryList.append("$(FV_DIR)")\r
1248\r
1249 # TRICK: for not generating GenFds call in makefile if no FDF file\r
1250 MacroList = []\r
1251 if PlatformInfo.FdfFile != None and PlatformInfo.FdfFile != "":\r
1252 FdfFileList = [PlatformInfo.FdfFile]\r
1253 # macros passed to GenFds\r
1254 MacroList.append('"%s=%s"' % ("EFI_SOURCE", GlobalData.gEfiSource.replace('\\', '\\\\')))\r
1255 MacroList.append('"%s=%s"' % ("EDK_SOURCE", GlobalData.gEdkSource.replace('\\', '\\\\')))\r
1256 MacroDict = {}\r
1257 MacroDict.update(GlobalData.gGlobalDefines)\r
1258 MacroDict.update(GlobalData.gCommandLineDefines)\r
1259 MacroDict.pop("EFI_SOURCE", "dummy")\r
1260 MacroDict.pop("EDK_SOURCE", "dummy")\r
1261 for MacroName in MacroDict:\r
1262 if MacroDict[MacroName] != "":\r
1263 MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))\r
1264 else:\r
1265 MacroList.append('"%s"' % MacroName)\r
1266 else:\r
1267 FdfFileList = []\r
1268\r
1269 # pass extra common options to external program called in makefile, currently GenFds.exe\r
1270 ExtraOption = ''\r
1271 LogLevel = EdkLogger.GetLevel()\r
1272 if LogLevel == EdkLogger.VERBOSE:\r
1273 ExtraOption += " -v"\r
1274 elif LogLevel <= EdkLogger.DEBUG_9:\r
1275 ExtraOption += " -d %d" % (LogLevel - 1)\r
1276 elif LogLevel == EdkLogger.QUIET:\r
1277 ExtraOption += " -q"\r
1278\r
1279 if GlobalData.gCaseInsensitive:\r
1280 ExtraOption += " -c"\r
1281\r
97fa0ee9
YL
1282 if GlobalData.gIgnoreSource:\r
1283 ExtraOption += " --ignore-sources"\r
1284\r
f51461c8
LG
1285 MakefileName = self._FILE_NAME_[self._FileType]\r
1286 SubBuildCommandList = []\r
1287 for A in PlatformInfo.ArchList:\r
1288 Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)}\r
1289 SubBuildCommandList.append(Command)\r
1290\r
1291 MakefileTemplateDict = {\r
1292 "makefile_header" : self._FILE_HEADER_[self._FileType],\r
1293 "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName),\r
1294 "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"],\r
1295 "platform_name" : PlatformInfo.Name,\r
1296 "platform_guid" : PlatformInfo.Guid,\r
1297 "platform_version" : PlatformInfo.Version,\r
1298 "platform_build_directory" : PlatformInfo.BuildDir,\r
97fa0ee9 1299 "conf_directory" : GlobalData.gConfDirectory,\r
f51461c8
LG
1300\r
1301 "toolchain_tag" : PlatformInfo.ToolChain,\r
1302 "build_target" : PlatformInfo.BuildTarget,\r
1303 "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(),\r
1304 "shell_command" : self._SHELL_CMD_[self._FileType].values(),\r
1305 'arch' : list(PlatformInfo.ArchList),\r
1306 "build_architecture_list" : ','.join(PlatformInfo.ArchList),\r
1307 "separator" : Separator,\r
1308 "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
1309 "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),\r
1310 "sub_build_command" : SubBuildCommandList,\r
1311 "fdf_file" : FdfFileList,\r
1312 "active_platform" : str(PlatformInfo),\r
1313 "fd" : PlatformInfo.FdTargetList,\r
1314 "fv" : PlatformInfo.FvTargetList,\r
1315 "cap" : PlatformInfo.CapTargetList,\r
1316 "extra_options" : ExtraOption,\r
1317 "macro" : MacroList,\r
1318 }\r
1319\r
1320 return MakefileTemplateDict\r
1321\r
1322 ## Get the root directory list for intermediate files of all modules build\r
1323 #\r
1324 # @retval list The list of directory\r
1325 #\r
1326 def GetModuleBuildDirectoryList(self):\r
1327 DirList = []\r
1328 for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:\r
97fa0ee9
YL
1329 if not ModuleAutoGen.IsBinaryModule:\r
1330 DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))\r
f51461c8
LG
1331 return DirList\r
1332\r
1333 ## Get the root directory list for intermediate files of all libraries build\r
1334 #\r
1335 # @retval list The list of directory\r
1336 #\r
1337 def GetLibraryBuildDirectoryList(self):\r
1338 DirList = []\r
1339 for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:\r
97fa0ee9
YL
1340 if not LibraryAutoGen.IsBinaryModule:\r
1341 DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))\r
f51461c8
LG
1342 return DirList\r
1343\r
1344 _TemplateDict = property(_CreateTemplateDict)\r
1345\r
1346# This acts like the main() function for the script, unless it is 'import'ed into another script.\r
1347if __name__ == '__main__':\r
1348 pass\r
1349\r