19ac70856e8c6eb474bcbdd8cd52134ea2e1b353
[people/mcb30/basetools.git] / Source / Python / AutoGen / GenMake.py
1 ## @file\r
2 # Create makefile for MS nmake and GNU make\r
3 #\r
4 # Copyright (c) 2007, Intel Corporation\r
5 # All rights reserved. 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
16 import os\r
17 import sys\r
18 import string\r
19 import re\r
20 import os.path as path\r
21 \r
22 from Common.EdkIIWorkspaceBuild import *\r
23 from Common.EdkIIWorkspace import *\r
24 from Common.BuildToolError import *\r
25 from Common.Misc import *\r
26 from BuildInfo import *\r
27 from BuildEngine import *\r
28 import Common.GlobalData as GlobalData\r
29 \r
30 ## Regular expression for finding header file inclusions\r
31 gIncludePattern = re.compile("^[ #]*include[ \t]+[\"<]*([^\"<>\n\r]+)[>\" ]*$", re.MULTILINE | re.UNICODE)\r
32 \r
33 ## Regular expression for matching macro used in header file inclusion\r
34 gMacroPattern = re.compile("([_A-Z][_A-Z0-9]*)[ \t]*\((.+)\)", re.UNICODE)\r
35 \r
36 ##\r
37 gProtocolDefinition = "Protocol/%(HeaderKey)s/%(HeaderKey)s.h"\r
38 gGuidDefinition = "Guid/%(HeaderKey)s/%(HeaderKey)s.h"\r
39 gArchProtocolDefinition = "ArchProtocol/%(HeaderKey)s/%(HeaderKey)s.h"\r
40 gPpiDefinition = "Ppi/%(HeaderKey)s/%(HeaderKey)s.h"\r
41 gIncludeMacroConversion = {\r
42   "EFI_PROTOCOL_DEFINITION"         :   gProtocolDefinition,\r
43   "EFI_GUID_DEFINITION"             :   gGuidDefinition,\r
44   "EFI_ARCH_PROTOCOL_DEFINITION"    :   gArchProtocolDefinition,\r
45   "EFI_PROTOCOL_PRODUCER"           :   gProtocolDefinition,\r
46   "EFI_PROTOCOL_CONSUMER"           :   gProtocolDefinition,\r
47   "EFI_PROTOCOL_DEPENDENCY"         :   gProtocolDefinition,\r
48   "EFI_ARCH_PROTOCOL_PRODUCER"      :   gArchProtocolDefinition,\r
49   "EFI_ARCH_PROTOCOL_CONSUMER"      :   gArchProtocolDefinition,\r
50   "EFI_ARCH_PROTOCOL_DEPENDENCY"    :   gArchProtocolDefinition,\r
51   "EFI_PPI_DEFINITION"              :   gPpiDefinition,\r
52   "EFI_PPI_PRODUCER"                :   gPpiDefinition,\r
53   "EFI_PPI_CONSUMER"                :   gPpiDefinition,\r
54   "EFI_PPI_DEPENDENCY"              :   gPpiDefinition,\r
55 }\r
56 \r
57 gMakeType = ""\r
58 if sys.platform == "win32":\r
59     gMakeType = "nmake"\r
60 else:\r
61     gMakeType = "gmake"\r
62 \r
63 \r
64 ## BuildFile class\r
65 #\r
66 #  This class encapsules makefie and its generation. It uses template to generate\r
67 #  the content of makefile. The content of makefile will be got from PlatformBuildInfo\r
68 #  or ModuleBuildInfo objects.\r
69 #\r
70 class BuildFile(object):\r
71     _TEMPLATE_ = ''\r
72     _FILE_NAME_ = {\r
73         "nmake" :   "Makefile",\r
74         "gmake" :   "GNUmakefile"\r
75     }\r
76 \r
77     _MAKEFILE_HEADER = '''#\r
78 # DO NOT EDIT\r
79 # This file is auto-generated by build utility\r
80 #\r
81 # Module Name:\r
82 #\r
83 #   %s\r
84 #\r
85 # Abstract:\r
86 #\r
87 #   Auto-generated makefile for building modules, libraries or platform\r
88 #\r
89     '''\r
90     \r
91     _FILE_HEADER_ = {\r
92         "nmake" :   _MAKEFILE_HEADER % _FILE_NAME_["nmake"],\r
93         "gmake" :   _MAKEFILE_HEADER % _FILE_NAME_["gmake"]\r
94     }\r
95 \r
96     #   \r
97     #   $(CP)     copy file command\r
98     #   $(MV)     move file command\r
99     #   $(RM)     remove file command\r
100     #   $(MD)     create dir command\r
101     #   $(RD)     remove dir command\r
102     #\r
103     _SHELL_CMD_ = {\r
104         "nmake" : {\r
105             "CP"    :   "copy /y",\r
106             "MV"    :   "move /y",\r
107             "RM"    :   "del /f /q",\r
108             "MD"    :   "mkdir",\r
109             "RD"    :   "rmdir /s /q",\r
110         },\r
111     \r
112         "gmake" : {\r
113             "CP"    :   "cp -f",\r
114             "MV"    :   "mv -f",\r
115             "RM"    :   "rm -f",\r
116             "MD"    :   "mkdir -p",\r
117             "RD"    :   "rm -r -f",\r
118         }\r
119     }\r
120 \r
121     _SEP_ = {\r
122         "nmake" :   "\\", \r
123         "gmake" :   "/"\r
124     }\r
125     \r
126     _MD_TEMPLATE_ = {\r
127         "nmake" :   'if not exist %(dir)s $(MD) %(dir)s',\r
128         "gmake" :   "test ! -e %(dir)s && $(MD) %(dir)s"\r
129     }\r
130 \r
131     _RD_TEMPLATE_ = {\r
132         "nmake" :   'if exist %(dir)s $(RD) %(dir)s',\r
133         "gmake" :   "test -e %(dir)s && $(RD) %(dir)s"\r
134     }\r
135     \r
136     _INC_FLAG_ = {"MSFT" : "/I", "GCC" : "-I", "INTEL" : "-I"}\r
137     \r
138     _LIB_GROUP_START_ = {"MSFT" : "", "GCC" : "-(", "INTEL" : ""}\r
139     _LIB_GROUP_END = {"MSFT" : "", "GCC" : "-)", "INTEL" : ""}\r
140     \r
141 \r
142     def __init__(self, AutoGenObject):\r
143         self._AutoGenObject = AutoGenObject\r
144         self._FileType = gMakeType\r
145 \r
146     def Generate(self, FileType=gMakeType):\r
147         self._FileType = FileType\r
148         FileContent = TemplateString()\r
149         FileContent.Append(self._TEMPLATE_, self._TemplateDict)\r
150 \r
151         FileName = self._FILE_NAME_[FileType]\r
152         return SaveFileOnChange(os.path.join(self._AutoGenObject.MakeFileDir, FileName), str(FileContent))\r
153 \r
154     ## Return a list of directory creation command string\r
155     #\r
156     #   @param      DirList     The list of directory to be created\r
157     #   @param      MakeType    GNU makefile or MS makefile\r
158     #\r
159     #   @retval     list        The directory creation command list\r
160     #\r
161     def GetCreateDirectoryCommand(self, DirList):\r
162         return [self._MD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]\r
163 \r
164     ## Return a list of directory removal command string\r
165     #\r
166     #   @param      DirList     The list of directory to be removed\r
167     #   @param      MakeType    GNU makefile or MS makefile\r
168     #\r
169     #   @retval     list        The directory removal command list\r
170     #\r
171     def GetRemoveDirectoryCommand(self, DirList):\r
172         return [self._RD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]\r
173 \r
174 \r
175 class ModuleMakefile(BuildFile):\r
176     _TEMPLATE_ = '''\\r
177 ${makefile_header}\r
178 \r
179 #\r
180 # Platform Macro Definition\r
181 #\r
182 PLATFORM_NAME = ${platform_name}\r
183 PLATFORM_GUID = ${platform_guid}\r
184 PLATFORM_VERSION = ${platform_version}\r
185 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}\r
186 PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}\r
187 PLATFORM_OUTPUT_DIR = ${platform_output_directory}\r
188 \r
189 #\r
190 # Module Macro Definition\r
191 #\r
192 MODULE_NAME = ${module_name}\r
193 MODULE_GUID = ${module_guid}\r
194 MODULE_VERSION = ${module_version}\r
195 MODULE_TYPE = ${module_type}\r
196 MODULE_FILE_BASE_NAME = ${module_file_base_name}\r
197 BASE_NAME = $(MODULE_NAME)\r
198 MODULE_RELATIVE_DIR = ${module_relative_directory}\r
199 MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory}\r
200 \r
201 #\r
202 # Build Configuration Macro Definition\r
203 #\r
204 ARCH = ${architecture}\r
205 TOOLCHAIN_TAG = ${toolchain_tag}\r
206 TARGET = ${build_target}\r
207 \r
208 #\r
209 # Build Directory Macro Definition\r
210 #\r
211 # PLATFORM_BUILD_DIR = ${platform_build_directory}\r
212 BUILD_DIR = ${platform_build_directory}\r
213 BIN_DIR = $(BUILD_DIR)${separator}${architecture}\r
214 LIB_DIR = $(BIN_DIR)\r
215 MODULE_BUILD_DIR = $(BUILD_DIR)${separator}${architecture}${separator}${module_relative_directory}${separator}${module_file_base_name}\r
216 OUTPUT_DIR = $(MODULE_BUILD_DIR)${separator}OUTPUT\r
217 DEBUG_DIR = $(MODULE_BUILD_DIR)${separator}DEBUG\r
218 DEST_DIR_OUTPUT = $(OUTPUT_DIR)\r
219 DEST_DIR_DEBUG = $(DEBUG_DIR)\r
220 \r
221 #\r
222 # Tools Flag Macro (from platform/module description file, tools_def.txt)\r
223 #\r
224 ${BEGIN}${tool_code}_FLAGS = ${module_tool_flags}\r
225 ${END}\r
226 \r
227 #\r
228 # Tools Path Macro\r
229 #\r
230 ${BEGIN}${tool_code} = ${tool_path}\r
231 ${END}\r
232 \r
233 MAKE_FILE = ${makefile_path}\r
234 \r
235 #\r
236 # Shell Command Macro\r
237 #\r
238 ${BEGIN}${shell_command_code} = ${shell_command}\r
239 ${END}\r
240 \r
241 #\r
242 # Build Macro\r
243 #\r
244 ${BEGIN}${source_file_macro}\r
245 ${END}\r
246 \r
247 ${BEGIN}${target_file_macro}\r
248 ${END}\r
249 \r
250 SOURCE_FILES = ${BEGIN}${source_file_macro_name} ${END}\r
251 \r
252 TARGET_FILES = ${BEGIN}${target_file_macro_name} ${END}\r
253 \r
254 INC = ${BEGIN}${include_path_prefix}${include_path} \\\r
255       ${END}\r
256 \r
257 #OBJECTS = ${BEGIN}$(OUTPUT_DIR)${separator}${object_file} \\\r
258 #          ${END}\r
259 \r
260 LIBS = ${BEGIN}${library_file} \\\r
261        ${END}${BEGIN}${system_library} \\\r
262        ${END} \\\r
263        $(LIB_LIST)\r
264 \r
265 COMMON_DEPS = ${BEGIN}${common_dependency_file} \\\r
266               ${END}\r
267 \r
268 IMAGE_ENTRY_POINT = ${module_entry_point}\r
269 ENTRYPOINT = ${module_entry_point}\r
270 \r
271 #\r
272 # Overridable Target Macro Definitions\r
273 #\r
274 INIT_TARGET = init\r
275 PCH_TARGET =\r
276 CODA_TARGET = ${BEGIN}${remaining_build_target} \\\r
277               ${END}\r
278 \r
279 #\r
280 # Default target, which will build dependent libraries in addition to source files\r
281 #\r
282 \r
283 all: mbuild\r
284 \r
285 \r
286 #\r
287 # Target used when called from platform makefile, which will bypass the build of dependent libraries\r
288 #\r
289 \r
290 pbuild: $(INIT_TARGET) $(PCH_TARGET) $(CODA_TARGET)\r
291 \r
292 #\r
293 # ModuleTarget\r
294 #\r
295 \r
296 mbuild: $(INIT_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET)\r
297 \r
298 \r
299 #\r
300 # Target to update the FD\r
301 #\r
302 \r
303 fds: mbuild gen_fds\r
304 \r
305 #\r
306 # Initialization target: print build information and create necessary directories\r
307 #\r
308 init:\r
309 \t-@echo Building ... $(MODULE_NAME) [$(ARCH)]\r
310 ${BEGIN}\t-@${create_directory_command}\n${END}\\r
311 ${BEGIN}\t-@${copy_autogen_h}\n${END}\r
312 \r
313 #\r
314 # GenLibsTarget\r
315 #\r
316 gen_libs:\r
317 \t${BEGIN}@cd ${dependent_library_build_directory} && "$(MAKE)" $(MAKE_FLAGS)\r
318 \t${END}@cd $(MODULE_BUILD_DIR)\r
319 \r
320 #\r
321 # Build Flash Device Image\r
322 #\r
323 gen_fds:\r
324 \t@cd $(BUILD_DIR) && "$(MAKE)" $(MAKE_FLAGS) fds\r
325 \t@cd $(MODULE_BUILD_DIR)\r
326 \r
327 #\r
328 # Individual Object Build Targets\r
329 #\r
330 ${BEGIN}${file_build_target}\r
331 ${END}\r
332 \r
333 \r
334 #\r
335 # clean all intermediate files\r
336 #\r
337 \r
338 clean:\r
339 \t${BEGIN}${clean_command}\r
340 \t${END}\r
341 \r
342 #\r
343 # clean all generated files\r
344 #\r
345 \r
346 cleanall:\r
347 ${BEGIN}\t${cleanall_command}\r
348 ${END}\t$(RM) *.pdb *.idb > NUL 2>&1\r
349 \t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi\r
350 \r
351 #\r
352 # clean pre-compiled header files\r
353 #\r
354 \r
355 cleanpch:\r
356 \t$(RM) $(OUTPUT_DIR)\*.pch > NUL 2>&1\r
357 \r
358 #\r
359 # clean all dependent libraries built\r
360 #\r
361 \r
362 cleanlib:\r
363 \t${BEGIN}@cd ${dependent_library_build_directory} && "$(MAKE)" $(MAKE_FLAGS) cleanall\r
364 \t${END}@cd $(MODULE_BUILD_DIR)\n'''\r
365     \r
366     def __init__(self, ModuleAutoGen):\r
367         BuildFile.__init__(self, ModuleAutoGen)\r
368         self.PlatformInfo = self._AutoGenObject.PlatformInfo\r
369 \r
370         self.ResultFileList = []\r
371         self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]\r
372     \r
373         self.SourceFileDatabase = {}  # {file type : file path}\r
374         self.DestFileDatabase = {}  # {file type : file path}\r
375         self.FileBuildTargetList = [] # [(src, target string)]\r
376         self.BuildTargetList = [] # [target string]\r
377         self.PendingBuildTargetList = [] # [FileBuildRule objects]\r
378         self.CommonFileDependency = []\r
379 \r
380         self.FileDependency = []\r
381         self.LibraryBuildCommandList = []\r
382         self.LibraryFileList = []\r
383         self.LibraryMakefileList = []\r
384         self.LibraryBuildDirectoryList = []\r
385         self.SystemLibraryList = []\r
386 \r
387     def _CreateTemplateDict(self):\r
388         if self._FileType not in self._SEP_:\r
389             EdkLogger.error("build", PARAMETER_INVALID, "Invalid Makefile type", ExtraData=self._FileType)\r
390         Separator = self._SEP_[self._FileType]\r
391 \r
392         # break build if no source files and binary files are found\r
393         if len(self._AutoGenObject.SourceFileList) == 0 and len(self._AutoGenObject.BinaryFileDict) == 0:\r
394             EdkLogger.error("build", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]"\r
395                             % (self._AutoGenObject.BuildTarget, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch),\r
396                             ExtraData=str(self._AutoGenObject))\r
397         # convert source files and binary files to build target\r
398         if len(self._AutoGenObject.SourceFileList) > 0:\r
399             self.ProcessSourceFileList()\r
400         if len(self._AutoGenObject.BinaryFileDict) > 0:\r
401             self.ProcessBinaryFileList()\r
402 \r
403         # convert dependent libaries to build command\r
404         self.ProcessDependentLibrary()\r
405         if self._AutoGenObject.Arch == "EBC":\r
406             # EBC compiler always use "EfiStart" as entry point\r
407             EntryPoint = "EfiStart"\r
408         elif self._AutoGenObject.AutoGenVersion < 0x00010005 and len(self._AutoGenObject.Module.ModuleEntryPointList) > 0:\r
409             # R8 modules use different entry point functions\r
410             EntryPoint = self._AutoGenObject.Module.ModuleEntryPointList[0]\r
411         else:\r
412             # R9 modules always use "_ModuleEntryPoint" as entry point\r
413             EntryPoint = "_ModuleEntryPoint"\r
414 \r
415         DefaultToolFlag = self.PlatformInfo.ToolOption.values()\r
416         # USER_DEFINED modules should take care of tools definitions by its own\r
417         if self._AutoGenObject.ModuleType == "USER_DEFINED":\r
418             DefaultToolFlag = ["" for p in DefaultToolFlag]\r
419 \r
420         if "CC" not in self.PlatformInfo.ToolChainFamily:\r
421             EdkLogger.error("AutoGen", AUTOGEN_ERROR, "Tool [CC] is not supported [%s, %s, %s]" % (self._AutoGenObject.BuildTarget,\r
422                                     self._AutoGenObject.ToolChain, self._AutoGenObject.Arch))\r
423         if  "DLINK" not in self.PlatformInfo.ToolChainFamily:\r
424             EdkLogger.error("AutoGen", AUTOGEN_ERROR, "Tool [DLINK] is not supported [%s, %s, %s]" % (self._AutoGenObject.BuildTarget,\r
425                                     self._AutoGenObject.ToolChain, self._AutoGenObject.Arch))\r
426 \r
427         if self._AutoGenObject.IsLibrary:\r
428             if "Static-Library-File" in self.DestFileDatabase:\r
429                 self.ResultFileList = self.DestFileDatabase["Static-Library-File"]\r
430         elif self._AutoGenObject.ModuleType == "USER_DEFINED":\r
431             if "Dynamic-Library-File" in self.DestFileDatabase:\r
432                 self.ResultFileList = self.DestFileDatabase["Dynamic-Library-File"]\r
433         if len(self.ResultFileList) == 0:\r
434             EdkLogger.error("AutoGen", AUTOGEN_ERROR, "Don't know how to end the module build")\r
435 \r
436         SourceFileMacroNameList = []\r
437         SourceFileMacroList = [] # macro name = file list\r
438         for FileType in self.SourceFileDatabase:\r
439             Macro = "%s_LIST" % FileType.replace("-", "_").upper()\r
440             SourceFileMacroNameList.append("$(%s)" % Macro)\r
441             Template = TemplateString()\r
442             Template.Append("%s = ${BEGIN}${source_file} \\\n\t${END}" % Macro,\r
443                             {"source_file" : self.SourceFileDatabase[FileType]})\r
444             SourceFileMacroList.append(str(Template))\r
445         TargetFileMacroList = []\r
446         TargetFileMacroNameList = []\r
447         for FileType in self.DestFileDatabase:\r
448             Macro = "%s_LIST" % FileType.replace("-", "_").upper()\r
449             TargetFileMacroNameList.append("$(%s)" % Macro)\r
450             Template = TemplateString()\r
451             Template.Append("%s = ${BEGIN}${target_file} \\\n\t${END}" % Macro,\r
452                             {"target_file" : self.DestFileDatabase[FileType]})\r
453             TargetFileMacroList.append(str(Template))\r
454 \r
455         # R8 modules need <BaseName>StrDefs.h for string ID\r
456         if self._AutoGenObject.AutoGenVersion < 0x00010005 and len(self._AutoGenObject.UnicodeFileList) > 0:\r
457             AutoGenHeaderFile = os.path.join("$(DEBUG_DIR)", "AutoGen.h")\r
458             StringHeaderFile = os.path.join("$(DEBUG_DIR)", "%sStrDefs.h" % self._AutoGenObject.Name)\r
459             CopyAutoGenHeaderFile = ["$(CP) %s %s" % (AutoGenHeaderFile, StringHeaderFile)]\r
460         else:\r
461             CopyAutoGenHeaderFile = []\r
462 \r
463         MakefileName = self._FILE_NAME_[self._FileType]\r
464         MakefileTemplateDict = {\r
465             "makefile_header"           : self._FILE_HEADER_[self._FileType],\r
466             "makefile_path"             : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),\r
467             "platform_name"             : self.PlatformInfo.Name,\r
468             "platform_guid"             : self.PlatformInfo.Guid,\r
469             "platform_version"          : self.PlatformInfo.Version,\r
470             "platform_relative_directory": self.PlatformInfo.SourceDir,\r
471             "platform_output_directory" : self.PlatformInfo.OutputDir,\r
472 \r
473             "module_name"               : self._AutoGenObject.Name,\r
474             "module_guid"               : self._AutoGenObject.Guid,\r
475             "module_version"            : self._AutoGenObject.Version,\r
476             "module_type"               : self._AutoGenObject.ModuleType,\r
477             "module_file_base_name"     : self._AutoGenObject.FileBase,\r
478             "module_relative_directory" : self._AutoGenObject.SourceDir,\r
479 \r
480             "architecture"              : self._AutoGenObject.Arch,\r
481             "toolchain_tag"             : self._AutoGenObject.ToolChain,\r
482             "build_target"              : self._AutoGenObject.BuildTarget,\r
483 \r
484             "platform_build_directory"  : self.PlatformInfo.BuildDir,\r
485 \r
486             "separator"                 : Separator,\r
487             "module_tool_flags"         : [self._AutoGenObject.BuildOption[tool] for tool in self.PlatformInfo.ToolPath],\r
488 \r
489             "tool_code"                 : self.PlatformInfo.ToolPath.keys(),\r
490             "tool_path"                 : self.PlatformInfo.ToolPath.values(),\r
491 \r
492             "shell_command_code"        : self._SHELL_CMD_[self._FileType].keys(),\r
493             "shell_command"             : self._SHELL_CMD_[self._FileType].values(),\r
494 \r
495             "module_entry_point"        : EntryPoint,\r
496             "include_path_prefix"       : self._INC_FLAG_[self.PlatformInfo.ToolChainFamily["CC"]],\r
497             "dlink_output_flag"         : self.PlatformInfo.OutputFlag["DLINK"],\r
498             "slink_output_flag"         : self.PlatformInfo.OutputFlag["SLINK"],\r
499             "start_group_flag"          : self._LIB_GROUP_START_[self.PlatformInfo.ToolChainFamily["DLINK"]],\r
500             "end_group_flag"            : self._LIB_GROUP_END[self.PlatformInfo.ToolChainFamily["DLINK"]],\r
501             "include_path"              : self._AutoGenObject.IncludePathList,\r
502             "library_file"              : self.LibraryFileList,\r
503             "remaining_build_target"    : self.ResultFileList,\r
504             "system_library"            : self.SystemLibraryList,\r
505             "common_dependency_file"    : self.CommonFileDependency,\r
506             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
507             "clean_command"             : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]),\r
508             "cleanall_command"          : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]),\r
509             "dependent_library_build_directory" : self.LibraryBuildDirectoryList,\r
510             "source_file_macro"         : SourceFileMacroList,\r
511             "target_file_macro"         : TargetFileMacroList,\r
512             "source_file_macro_name"    : SourceFileMacroNameList,\r
513             "target_file_macro_name"    : TargetFileMacroNameList,\r
514             "file_build_target"         : self.BuildTargetList,\r
515             "copy_autogen_h"            : CopyAutoGenHeaderFile,\r
516         }\r
517 \r
518         return MakefileTemplateDict\r
519 \r
520     ## Process source files to generate makefile targets and dependencies\r
521     #\r
522     #  The intermediate and final targets and dependencies are controlled by\r
523     #  build rules in $(WORKSPACE)/Conf/build_rule.txt. The dependencies of source\r
524     #  file are figured out by search included files in the source file.\r
525     #\r
526     #   @param      MakeType    GNU makefile or MS makefile\r
527     #\r
528     def ProcessSourceFileList(self):\r
529         Separator = self._SEP_[self._FileType]\r
530 \r
531         ForceIncludedFile = []\r
532         SourceFileList = []\r
533 \r
534         if "CC" not in self.PlatformInfo.ToolChainFamily:\r
535             EdkLogger.error("AutoGen", AUTOGEN_ERROR, "No CC tool found",\r
536                             ExtraData=str(self._AutoGenObject.Module))\r
537         Family = self.PlatformInfo.ToolChainFamily["CC"]\r
538         BuildRule = self.PlatformInfo.BuildRule\r
539 \r
540         CCodeFlag = False\r
541         FileList = self._AutoGenObject.SourceFileList\r
542         SourceDir = os.path.join(self._AutoGenObject.WorkspaceDir, self._AutoGenObject.SourceDir)\r
543         for FileInfo in FileList:\r
544             F, SrcFileType, SrcFileBuildRule = FileInfo\r
545             # no rule, no build\r
546             if SrcFileBuildRule == None:\r
547                 continue\r
548             if SrcFileType == "C-Code-File":\r
549                 CCodeFlag = True\r
550             SrcFileName = path.basename(F)\r
551             SrcFileBase, SrcFileExt = path.splitext(SrcFileName)\r
552             SrcFileDir = path.dirname(F)\r
553             if SrcFileDir == "":\r
554                 SrcFileDir = "."\r
555             else:\r
556                 P = "$(OUTPUT_DIR)" + Separator + SrcFileDir\r
557                 if P not in self.IntermediateDirectoryList:\r
558                     self.IntermediateDirectoryList.append(P)\r
559             SrcFileRelativePath = os.path.join(SourceDir, F)\r
560 \r
561             SrcFile, ExtraSrcFileList, DstFile, CommandList = SrcFileBuildRule.Apply(F, SourceDir, Separator)\r
562             if SrcFileType not in self.SourceFileDatabase:\r
563                 self.SourceFileDatabase[SrcFileType] = []\r
564             self.SourceFileDatabase[SrcFileType].append(SrcFile)\r
565             SourceFileList.append(SrcFileRelativePath)\r
566 \r
567             BuildTargetTemplate = "${BEGIN}%s : ${deps}\n"\\r
568                                   "${END}\t%s\n" % (DstFile, "\n\t".join(CommandList))\r
569             self.FileBuildTargetList.append((SrcFileRelativePath, BuildTargetTemplate))\r
570 \r
571             while True:\r
572                 # next target\r
573                 DstFileType, DstFileBuildRule = BuildRule.Get(SrcFileBuildRule.DestFileExt, Family)\r
574                 if DstFileType == None:\r
575                     DstFileType = "Unknown-Type-File"\r
576 \r
577                 if DstFileType  in self.SourceFileDatabase:\r
578                     self.SourceFileDatabase[DstFileType].append(DstFile)\r
579                 else:\r
580                     if DstFileType not in self.DestFileDatabase:\r
581                         self.DestFileDatabase[DstFileType] = []\r
582                     self.DestFileDatabase[DstFileType].append(DstFile)\r
583 \r
584                 if DstFileBuildRule != None and DstFileBuildRule.IsMultipleInput:\r
585                     if DstFileBuildRule not in self.PendingBuildTargetList:\r
586                         self.PendingBuildTargetList.append(DstFileBuildRule)\r
587                     break\r
588                 elif DstFileBuildRule == None or DstFileBuildRule.CommandList == []:\r
589                     self.ResultFileList.append(DstFile)\r
590                     break\r
591 \r
592                 SrcFile, ExtraSrcFileList, DstFile, CommandList = DstFileBuildRule.Apply(DstFile, None, Separator)\r
593                 BuildTargetString = "%s : %s %s\n"\\r
594                                     "\t%s\n" % (DstFile, SrcFile, " ".join(ExtraSrcFileList), "\n\t".join(CommandList))\r
595                 self.FileBuildTargetList.append((SrcFile, BuildTargetString))\r
596                 SrcFileBuildRule = DstFileBuildRule\r
597 \r
598         # handle pending targets\r
599         TempBuildTargetList = []\r
600         while True:\r
601             while len(self.PendingBuildTargetList) > 0:\r
602                 SrcFileBuildRule = self.PendingBuildTargetList.pop()\r
603                 SrcFileList = []\r
604                 for FileType in SrcFileBuildRule.SourceFileType:\r
605                     if FileType not in self.SourceFileDatabase:\r
606                         if FileType not in self.DestFileDatabase:\r
607                             continue\r
608                         else:\r
609                             SrcFileList.extend(self.DestFileDatabase[FileType])\r
610                     else:\r
611                         SrcFileList.extend(self.SourceFileDatabase[FileType])\r
612                 SrcFile, ExtraSrcFileList, DstFile, CommandList = SrcFileBuildRule.Apply(SrcFileList, None, Separator)\r
613                 BuildTargetString = "%s : %s %s\n"\\r
614                                     "\t%s\n" % (DstFile, SrcFile, " ".join(ExtraSrcFileList), "\n\t".join(CommandList))\r
615                 self.FileBuildTargetList.append((SrcFile, BuildTargetString))\r
616 \r
617                 # try to find next target\r
618                 while True:\r
619                     DstFileType, DstFileBuildRule = BuildRule.Get(SrcFileBuildRule.DestFileExt, Family)\r
620                     if DstFileType == None:\r
621                         DstFileType = "Unknown-Type-File"\r
622 \r
623                     if DstFileType  in self.SourceFileDatabase:\r
624                         self.SourceFileDatabase[DstFileType].append(DstFile)\r
625                     else:\r
626                         if DstFileType not in self.DestFileDatabase:\r
627                             self.DestFileDatabase[DstFileType] = []\r
628                         self.DestFileDatabase[DstFileType].append(DstFile)\r
629 \r
630                     if DstFileBuildRule != None and DstFileBuildRule.IsMultipleInput:\r
631                         TempBuildTargetList.append(DstFileBuildRule)\r
632                         break\r
633                     elif DstFileBuildRule == None or DstFileBuildRule.CommandList == []:\r
634                         self.ResultFileList.append(DstFile)\r
635                         break\r
636 \r
637                     SrcFile, ExtraSrcFileList, DstFile, CommandList = DstFileBuildRule.Apply(DstFile, None, Separator)\r
638                     BuildTargetString = "%s : %s %s\n"\\r
639                                         "\t%s\n" % (DstFile, SrcFile, " ".join(ExtraSrcFileList), "\n\t".join(CommandList))\r
640                     self.FileBuildTargetList.append((SrcFile, BuildTargetString))\r
641                     SrcFileBuildRule = DstFileBuildRule\r
642             if len(TempBuildTargetList) == 0:\r
643                 break\r
644             self.PendingBuildTargetList = TempBuildTargetList\r
645 \r
646         # Build AutoGen files only if we have C source files\r
647         if CCodeFlag == True:\r
648             for F in self._AutoGenObject.AutoGenFileList:\r
649                 SrcFileName = path.basename(F)\r
650                 SrcFileBase, SrcFileExt = path.splitext(SrcFileName)\r
651                 SrcFileDir = path.dirname(F)\r
652                 if SrcFileDir == "":\r
653                     SrcFileDir = "."\r
654                 else:\r
655                     P = "$(DEBUG_DIR)" + Separator + SrcFileDir\r
656                     if P not in self.IntermediateDirectoryList:\r
657                         self.IntermediateDirectoryList.append(P)\r
658 \r
659                 SrcFileRelativePath = os.path.join(self._AutoGenObject.DebugDir, F)\r
660 \r
661                 SrcFileType, SrcFileBuildRule = BuildRule.Get(SrcFileExt, Family)\r
662                 if SrcFileType != None and SrcFileType == "C-Header-File":\r
663                     ForceIncludedFile.append(SrcFileRelativePath)\r
664                 if SrcFileBuildRule == None or SrcFileBuildRule.CommandList == []:\r
665                     continue\r
666 \r
667                 SrcFile, ExtraSrcFileList, DstFile, CommandList = SrcFileBuildRule.Apply(F, self._AutoGenObject.DebugDir, Separator)\r
668 \r
669                 if SrcFileType not in self.SourceFileDatabase:\r
670                     self.SourceFileDatabase[SrcFileType] = []\r
671                 self.SourceFileDatabase[SrcFileType].append(SrcFile)\r
672                 SourceFileList.append(SrcFileRelativePath)\r
673 \r
674                 BuildTargetTemplate = "${BEGIN}%s : ${deps}\n"\\r
675                                       "${END}\t%s\n" % (DstFile, "\n\t".join(CommandList))\r
676                 self.FileBuildTargetList.append((SrcFileRelativePath, BuildTargetTemplate))\r
677 \r
678                 while True:\r
679                     # next target\r
680                     DstFileType, DstFileBuildRule = BuildRule.Get(SrcFileBuildRule.DestFileExt, Family)\r
681                     if DstFileType == None:\r
682                         DstFileType = "Unknown-Type-File"\r
683 \r
684                     if DstFileType  in self.SourceFileDatabase:\r
685                         self.SourceFileDatabase[DstFileType].append(DstFile)\r
686                     else:\r
687                         if DstFileType not in self.DestFileDatabase:\r
688                             self.DestFileDatabase[DstFileType] = []\r
689                         self.DestFileDatabase[DstFileType].append(DstFile)\r
690 \r
691                     if DstFileBuildRule != None and DstFileBuildRule.IsMultipleInput:\r
692                         if DstFileBuildRule not in self.PendingBuildTargetList:\r
693                             self.PendingBuildTargetList.append(DstFileBuildRule)\r
694                         break\r
695                     elif DstFileBuildRule == None or DstFileBuildRule.CommandList == []:\r
696                         self.ResultFileList.append(DstFile)\r
697                         break\r
698 \r
699                     SrcFile, ExtraSrcFileList, DstFile, CommandList = DstFileBuildRule.Apply(DstFile, None, Separator)\r
700                     BuildTargetString = "%s : %s %s\n"\\r
701                                         "\t%s\n" % (DstFile, SrcFile, " ".join(ExtraSrcFileList), "\n\t".join(CommandList))\r
702                     self.FileBuildTargetList.append((SrcFile, BuildTargetString))\r
703                     SrcFileBuildRule = DstFileBuildRule\r
704 \r
705         #\r
706         # Search dependency file list for each source file\r
707         #\r
708         self.FileDependency = self.GetFileDependency(SourceFileList, ForceIncludedFile, self._AutoGenObject.IncludePathList)\r
709         DepSet = None\r
710         for File in self.FileDependency:\r
711             # skip non-C files\r
712             if (not File.endswith(".c") and not File.endswith(".C")) or File.endswith("AutoGen.c"):\r
713                 continue\r
714             elif DepSet == None:\r
715                 DepSet = set(self.FileDependency[File])\r
716             else:\r
717                 DepSet &= set(self.FileDependency[File])\r
718         # in case nothing in SourceFileList\r
719         if DepSet == None:\r
720             DepSet = set()\r
721         #\r
722         # Extract comman files list in the dependency files\r
723         #\r
724         self.CommonFileDependency = list(DepSet)\r
725         for File in self.FileDependency:\r
726             # skip non-C files\r
727             if (not File.endswith(".c") and not File.endswith(".C")) or File.endswith("AutoGen.c"):\r
728                 continue\r
729             NewDepSet = set(self.FileDependency[File])\r
730             NewDepSet -= DepSet\r
731             self.FileDependency[File] = ["$(COMMON_DEPS)"] + list(NewDepSet)\r
732 \r
733         for File, TargetTemplate in self.FileBuildTargetList:\r
734             if File not in self.FileDependency:\r
735                 self.BuildTargetList.append(TargetTemplate)\r
736                 continue\r
737             Template = TemplateString()\r
738             Template.Append(TargetTemplate, {"deps" : self.FileDependency[File]})\r
739             self.BuildTargetList.append(str(Template))\r
740 \r
741 \r
742     ## Process binary files to generate makefile targets and dependencies\r
743     #\r
744     # All binary files are just copied to $(OUTPUT_DIR)\r
745     # \r
746     #   @param      MakeType    GNU makefile or MS makefile\r
747     #\r
748     def ProcessBinaryFileList(self):\r
749         BinaryFiles = self._AutoGenObject.BinaryFileDict\r
750         BuildTargetString = "%(dst)s : %(src)s\n"\\r
751                             "\t$(CP) %(src)s %(dst)s\n"\r
752         for FileType in BinaryFiles:\r
753             if FileType not in self.DestFileDatabase:\r
754                 self.DestFileDatabase[FileType] = []\r
755             for F in BinaryFiles[FileType]:\r
756                 Src = os.path.join("$(MODULE_DIR)", F)\r
757                 FileName = os.path.basename(F)\r
758                 Dst = os.path.join("$(OUTPUT_DIR)", FileName)\r
759                 self.DestFileDatabase[FileType].append(Dst)\r
760                 self.ResultFileList.append(Dst)\r
761                 self.BuildTargetList.append(BuildTargetString % {"dst":Dst, "src":Src})\r
762 \r
763     ## For creating makefile targets for dependent libraries\r
764     #\r
765     #   @param      MakeType    GNU makefile or MS makefile\r
766     #\r
767     def ProcessDependentLibrary(self):\r
768         for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:\r
769             self.LibraryBuildDirectoryList.append(LibraryAutoGen.BuildDir)\r
770             self.LibraryFileList.append(os.path.join(LibraryAutoGen.OutputDir, LibraryAutoGen.Name + ".lib"))\r
771 \r
772     ## Return a list containing source file's dependencies\r
773     #\r
774     #   @param      FileList        The list of source files\r
775     #   @param      ForceInculeList The list of files which will be included forcely\r
776     #   @param      SearchPathList  The list of search path\r
777     #\r
778     #   @retval     dict            The mapping between source file path and its dependencies\r
779     #\r
780     def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):\r
781         Dependency = {}\r
782         for F in FileList:\r
783             Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)\r
784         return Dependency\r
785     \r
786     ## Find dependencies for one source file\r
787     #\r
788     #  By searching recursively "#include" directive in file, find out all the\r
789     #  files needed by given source file. The dependecies will be only searched\r
790     #  in given search path list.\r
791     #\r
792     #   @param      File            The source file\r
793     #   @param      ForceInculeList The list of files which will be included forcely\r
794     #   @param      SearchPathList  The list of search path\r
795     #\r
796     #   @retval     list            The list of files the given source file depends on\r
797     #\r
798     def GetDependencyList(self, File, ForceList, SearchPathList):\r
799         EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File)\r
800         EdkLogger.debug(EdkLogger.DEBUG_0, "Including %s" % " ".join(ForceList))\r
801         FileStack = [File] + ForceList\r
802         DependencySet = set()\r
803         MacroUsedByIncludedFile = False\r
804     \r
805         if self._AutoGenObject.Arch not in gDependencyDatabase:\r
806             gDependencyDatabase[self._AutoGenObject.Arch] = {}\r
807         DepDb = gDependencyDatabase[self._AutoGenObject.Arch]\r
808         while len(FileStack) > 0:\r
809             EdkLogger.debug(EdkLogger.DEBUG_0, "Stack %s" % "\n\t".join(FileStack))\r
810             F = FileStack.pop()\r
811     \r
812             CurrentFileDependencyList = []\r
813             if F in DepDb and not IsChanged(F):\r
814                 CurrentFileDependencyList = DepDb[F]\r
815                 for Dep in CurrentFileDependencyList:\r
816                     if Dep not in FileStack and Dep not in DependencySet:\r
817                         FileStack.append(Dep)\r
818             else:\r
819                 try:\r
820                     Fd = open(F, 'r')\r
821                 except:\r
822                     EdkLogger.error("AutoGen", FILE_OPEN_FAILURE, ExtraData=F)\r
823     \r
824                 FileContent = Fd.read()\r
825                 Fd.close()\r
826                 if len(FileContent) == 0:\r
827                     continue\r
828     \r
829                 if FileContent[0] == 0xff or FileContent[0] == 0xfe:\r
830                     FileContent = unicode(FileContent, "utf-16")\r
831                 IncludedFileList = gIncludePattern.findall(FileContent)\r
832     \r
833                 CurrentFilePath = os.path.dirname(F)\r
834                 for Inc in IncludedFileList:\r
835                     # if there's macro used to reference header file, expand it\r
836                     HeaderList = gMacroPattern.findall(Inc)\r
837                     if len(HeaderList) == 1 and len(HeaderList[0]) == 2:\r
838                         HeaderType = HeaderList[0][0]\r
839                         HeaderKey = HeaderList[0][1]\r
840                         if HeaderType in gIncludeMacroConversion:\r
841                             Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey}\r
842                         else:\r
843                             # not known macro used in #include\r
844                             MacroUsedByIncludedFile = True\r
845                             continue\r
846                     Inc = os.path.normpath(Inc)\r
847                     for SearchPath in [CurrentFilePath] + SearchPathList:\r
848                         FilePath = os.path.join(SearchPath, Inc)\r
849                         if not os.path.exists(FilePath) or FilePath in CurrentFileDependencyList:\r
850                             continue\r
851                         CurrentFileDependencyList.append(FilePath)\r
852                         if FilePath not in FileStack and FilePath not in DependencySet:\r
853                             FileStack.append(FilePath)\r
854                         break\r
855                     else:\r
856                         EdkLogger.verbose("%s included by %s was not found in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList)))\r
857     \r
858                 if not MacroUsedByIncludedFile:\r
859                     if F == File:\r
860                         CurrentFileDependencyList += ForceList\r
861                     #\r
862                     # Don't keep the file in cache if it uses macro in included file.\r
863                     # So it will be scanned again if another file includes this file.\r
864                     #\r
865                     DepDb[F] = CurrentFileDependencyList\r
866             DependencySet.update(CurrentFileDependencyList)\r
867     \r
868         #\r
869         # If there's macro used in included file, always build the file by\r
870         # returning a empty dependency\r
871         #\r
872         if MacroUsedByIncludedFile:\r
873             DependencyList = [""]\r
874         else:\r
875             DependencyList = list(DependencySet)  # remove duplicate ones\r
876             DependencyList.append(File)\r
877     \r
878         return DependencyList        \r
879 \r
880     _TemplateDict = property(_CreateTemplateDict)\r
881 \r
882 class CustomMakefile(BuildFile):\r
883     _TEMPLATE_ = '''\\r
884 ${makefile_header}\r
885 \r
886 #\r
887 # Platform Macro Definition\r
888 #\r
889 PLATFORM_NAME = ${platform_name}\r
890 PLATFORM_GUID = ${platform_guid}\r
891 PLATFORM_VERSION = ${platform_version}\r
892 PLATFORM_RELATIVE_DIR = ${platform_relative_directory}\r
893 PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}\r
894 PLATFORM_OUTPUT_DIR = ${platform_output_directory}\r
895 \r
896 #\r
897 # Module Macro Definition\r
898 #\r
899 MODULE_NAME = ${module_name}\r
900 MODULE_GUID = ${module_guid}\r
901 MODULE_VERSION = ${module_version}\r
902 MODULE_TYPE = ${module_type}\r
903 MODULE_FILE_BASE_NAME = ${module_file_base_name}\r
904 BASE_NAME = $(MODULE_NAME)\r
905 MODULE_RELATIVE_DIR = ${module_relative_directory}\r
906 MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory}\r
907 \r
908 #\r
909 # Build Configuration Macro Definition\r
910 #\r
911 ARCH = ${architecture}\r
912 TOOLCHAIN_TAG = ${toolchain_tag}\r
913 TARGET = ${build_target}\r
914 \r
915 #\r
916 # Build Directory Macro Definition\r
917 #\r
918 # PLATFORM_BUILD_DIR = ${platform_build_directory}\r
919 BUILD_DIR = ${platform_build_directory}\r
920 BIN_DIR = $(BUILD_DIR)${separator}${architecture}\r
921 LIB_DIR = $(BIN_DIR)\r
922 MODULE_BUILD_DIR = $(BUILD_DIR)${separator}${architecture}${separator}${module_relative_directory}${separator}${module_file_base_name}\r
923 OUTPUT_DIR = $(MODULE_BUILD_DIR)${separator}OUTPUT\r
924 DEBUG_DIR = $(MODULE_BUILD_DIR)${separator}DEBUG\r
925 DEST_DIR_OUTPUT = $(OUTPUT_DIR)\r
926 DEST_DIR_DEBUG = $(DEBUG_DIR)\r
927 \r
928 #\r
929 # Tools Flag Macro (from platform/module description file, tools_def.txt)\r
930 #\r
931 ${BEGIN}${tool_code}_FLAGS = ${module_tool_flags}\r
932 ${END}\r
933 \r
934 #\r
935 # Tools Path Macro\r
936 #\r
937 ${BEGIN}${tool_code} = ${tool_path}\r
938 ${END}\r
939 \r
940 MAKE_FILE = ${makefile_path}\r
941 \r
942 #\r
943 # Shell Command Macro\r
944 #\r
945 ${BEGIN}${shell_command_code} = ${shell_command}\r
946 ${END}\r
947 \r
948 ${custom_makefile_content}\r
949 \r
950 #\r
951 # Target used when called from platform makefile, which will bypass the build of dependent libraries\r
952 #\r
953 \r
954 pbuild: init all\r
955 \r
956 \r
957 #\r
958 # ModuleTarget\r
959 #\r
960 \r
961 mbuild: init all\r
962 \r
963 \r
964 #\r
965 # Initialization target: print build information and create necessary directories\r
966 #\r
967 init:\r
968 \t-@echo Building ... $(MODULE_NAME) [$(ARCH)]\r
969 ${BEGIN}\t-@${create_directory_command}\n${END}\\r
970 \r
971 '''\r
972     def __init__(self, ModuleAutoGen):\r
973         BuildFile.__init__(self, ModuleAutoGen)\r
974         self.PlatformInfo = self._AutoGenObject.PlatformInfo\r
975         self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]\r
976 \r
977     ## Create customized makefile for a module\r
978     #\r
979     #   @param      File        The path of the makefile\r
980     #   @param      MakeType    GNU makefile or MS makefile\r
981     #\r
982     #   @retval     True        If the file is changed or doesn't exist\r
983     #   @retval     False       If the file exists and its content is not changed\r
984     #                           since last time\r
985     #\r
986     def _CreateTemplateDict(self):\r
987         Separator = self._SEP_[self._FileType]\r
988         try:\r
989             CustomMakefile = open(\r
990                                 os.path.join(\r
991                                             self._AutoGenObject.WorkspaceDir, \r
992                                             self._AutoGenObject.CustomMakefile[self._FileType]\r
993                                             ),\r
994                                 'r').read()\r
995         except:\r
996             EdkLogger.error('build', FILE_OPEN_FAILURE, ExtraData=self._AutoGenObject.CustomMakefile[self._FileType])\r
997 \r
998         MakefileName = self._FILE_NAME_[self._FileType]\r
999         MakefileTemplateDict = {\r
1000             "makefile_header"           : self._FILE_HEADER_[self._FileType],\r
1001             "makefile_path"             : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),\r
1002             "platform_name"             : self.PlatformInfo.Name,\r
1003             "platform_guid"             : self.PlatformInfo.Guid,\r
1004             "platform_version"          : self.PlatformInfo.Version,\r
1005             "platform_relative_directory": self.PlatformInfo.SourceDir,\r
1006             "platform_output_directory" : self.PlatformInfo.OutputDir,\r
1007 \r
1008             "module_name"               : self._AutoGenObject.Name,\r
1009             "module_guid"               : self._AutoGenObject.Guid,\r
1010             "module_version"            : self._AutoGenObject.Version,\r
1011             "module_type"               : self._AutoGenObject.ModuleType,\r
1012             "module_file_base_name"     : self._AutoGenObject.FileBase,\r
1013             "module_relative_directory" : self._AutoGenObject.SourceDir,\r
1014 \r
1015             "architecture"              : self._AutoGenObject.Arch,\r
1016             "toolchain_tag"             : self._AutoGenObject.ToolChain,\r
1017             "build_target"              : self._AutoGenObject.BuildTarget,\r
1018 \r
1019             "platform_build_directory"  : self.PlatformInfo.BuildDir,\r
1020 \r
1021             "separator"                 : Separator,\r
1022             "module_tool_flags"         : [self._AutoGenObject.BuildOption[tool] for tool in self.PlatformInfo.ToolPath],\r
1023 \r
1024             "shell_command_code"        : self._SHELL_CMD_[self._FileType].keys(),\r
1025             "shell_command"             : self._SHELL_CMD_[self._FileType].values(),\r
1026 \r
1027             "tool_code"                 : self.PlatformInfo.ToolPath.keys(),\r
1028             "tool_path"                 : self.PlatformInfo.ToolPath.values(),\r
1029 \r
1030             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
1031             "custom_makefile_content"   : CustomMakefile\r
1032         }\r
1033 \r
1034         return MakefileTemplateDict\r
1035 \r
1036     _TemplateDict = property(_CreateTemplateDict)\r
1037 \r
1038 class PlatformMakefile(BuildFile):\r
1039     _TEMPLATE_ = '''\\r
1040 ${makefile_header}\r
1041 \r
1042 #\r
1043 # Platform Macro Definition\r
1044 #\r
1045 PLATFORM_NAME = ${platform_name}\r
1046 PLATFORM_GUID = ${platform_guid}\r
1047 PLATFORM_VERSION = ${platform_version}\r
1048 PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}\r
1049 PLATFORM_OUTPUT_DIR = ${platform_output_directory}\r
1050 \r
1051 #\r
1052 # Build Configuration Macro Definition\r
1053 #\r
1054 TOOLCHAIN_TAG = ${toolchain_tag}\r
1055 TARGET = ${build_target}\r
1056 \r
1057 #\r
1058 # Build Directory Macro Definition\r
1059 #\r
1060 BUILD_DIR = ${platform_build_directory}\r
1061 FV_DIR = ${platform_build_directory}${separator}FV\r
1062 \r
1063 #\r
1064 # Shell Command Macro\r
1065 #\r
1066 ${BEGIN}${shell_command_code} = ${shell_command}\r
1067 ${END}\r
1068 \r
1069 MAKE = ${make_path}\r
1070 MAKE_FLAGS = ${make_flag}\r
1071 MAKE_FILE = ${makefile_path}\r
1072 \r
1073 #\r
1074 # Default target\r
1075 #\r
1076 all: init build_libraries build_modules\r
1077 \r
1078 #\r
1079 # Initialization target: print build information and create necessary directories\r
1080 #\r
1081 init:\r
1082 \t-@echo Building ... $(PLATFORM_NAME) [${build_architecture_list}]\r
1083 \t${BEGIN}-@${create_directory_command}\r
1084 \t${END}\r
1085 #\r
1086 # library build target\r
1087 #\r
1088 libraries: init build_libraries\r
1089 \r
1090 #\r
1091 # module build target\r
1092 #\r
1093 modules: init build_libraries build_modules\r
1094 \r
1095 #\r
1096 # Build all libraries:\r
1097 #\r
1098 build_libraries:\r
1099 ${BEGIN}\t@cd ${library_build_directory} && "$(MAKE)" $(MAKE_FLAGS) pbuild\r
1100 ${END}\t@cd $(BUILD_DIR)\r
1101 \r
1102 #\r
1103 # Build all modules:\r
1104 #\r
1105 build_modules:\r
1106 ${BEGIN}\t@cd ${module_build_directory} && "$(MAKE)" $(MAKE_FLAGS) pbuild\r
1107 ${END}\t@cd $(BUILD_DIR)\r
1108 \r
1109 #\r
1110 # Clean intermediate files\r
1111 #\r
1112 clean:\r
1113 \t${BEGIN}@cd ${library_build_directory} && "$(MAKE)" $(MAKE_FLAGS) clean\r
1114 \t${END}${BEGIN}@cd ${module_build_directory} && "$(MAKE)" $(MAKE_FLAGS) clean\r
1115 \t${END}@cd $(BUILD_DIR)\r
1116 \r
1117 #\r
1118 # Clean all generated files except to makefile\r
1119 #\r
1120 cleanall:\r
1121 ${BEGIN}\t${cleanall_command}\r
1122 ${END}\r
1123 \r
1124 #\r
1125 # Clean all library files\r
1126 #\r
1127 cleanlib:\r
1128 \t${BEGIN}@cd ${library_build_directory} && "$(MAKE)" $(MAKE_FLAGS) cleanall\r
1129 \t${END}@cd $(BUILD_DIR)\n\r
1130 '''\r
1131 \r
1132     def __init__(self, PlatformAutoGen):\r
1133         BuildFile.__init__(self, PlatformAutoGen)\r
1134         self.ModuleBuildCommandList = []\r
1135         self.ModuleMakefileList = []\r
1136         self.IntermediateDirectoryList = []\r
1137         self.ModuleBuildDirectoryList = []\r
1138         self.LibraryBuildDirectoryList = []\r
1139 \r
1140     ## Create makefile of platform\r
1141     #\r
1142     #   @param      File        The path of the makefile\r
1143     #   @param      MakeType    GNU makefile or MS makefile\r
1144     #\r
1145     #   @retval     True        If the file is changed or doesn't exist\r
1146     #   @retval     False       If the file exists and its content is not changed\r
1147     #                           since last time\r
1148     #\r
1149     def _CreateTemplateDict(self):\r
1150         Separator = self._SEP_[self._FileType]\r
1151 \r
1152         PlatformInfo = self._AutoGenObject\r
1153         if "MAKE" not in PlatformInfo.ToolPath:\r
1154             EdkLogger.error("GenMake", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!")\r
1155 \r
1156         self.IntermediateDirectoryList = ["$(BUILD_DIR)"]\r
1157         self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()\r
1158         self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()\r
1159 \r
1160         MakefileName = self._FILE_NAME_[self._FileType]\r
1161         MakefileTemplateDict = {\r
1162             "makefile_header"           : self._FILE_HEADER_[self._FileType],\r
1163             "makefile_path"             : os.path.join("$(BUILD_DIR)", MakefileName),\r
1164             "platform_name"             : PlatformInfo.Name,\r
1165             "platform_guid"             : PlatformInfo.Guid,\r
1166             "platform_version"          : PlatformInfo.Version,\r
1167             "platform_relative_directory": PlatformInfo.SourceDir,\r
1168             "platform_output_directory" : PlatformInfo.OutputDir,\r
1169             "platform_build_directory"  : PlatformInfo.BuildDir,\r
1170 \r
1171             "toolchain_tag"             : PlatformInfo.ToolChain,\r
1172             "build_target"              : PlatformInfo.BuildTarget,\r
1173             "make_path"                 : PlatformInfo.ToolPath["MAKE"],\r
1174             "make_flag"                 : PlatformInfo.ToolOption["MAKE"],\r
1175             "shell_command_code"        : self._SHELL_CMD_[self._FileType].keys(),\r
1176             "shell_command"             : self._SHELL_CMD_[self._FileType].values(),\r
1177             "build_architecture_list"   : self._AutoGenObject.Arch,\r
1178             "architecture"              : self._AutoGenObject.Arch,\r
1179             "separator"                 : Separator,\r
1180             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
1181             "cleanall_command"          : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),\r
1182             "library_build_directory"   : self.LibraryBuildDirectoryList,\r
1183             "module_build_directory"    : self.ModuleBuildDirectoryList,\r
1184             "active_platform"           : PlatformInfo.WorkspaceDir + Separator + str(PlatformInfo),\r
1185         }\r
1186 \r
1187         return MakefileTemplateDict\r
1188 \r
1189     ## Get the root directory list for intermediate files of all modules build\r
1190     #\r
1191     #   @retval     list    The list of directory\r
1192     #\r
1193     def GetModuleBuildDirectoryList(self):\r
1194         DirList = []\r
1195         for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:\r
1196             DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))\r
1197         return DirList\r
1198 \r
1199     ## Get the root directory list for intermediate files of all libraries build\r
1200     #\r
1201     #   @retval     list    The list of directory\r
1202     #\r
1203     def GetLibraryBuildDirectoryList(self):\r
1204         DirList = []\r
1205         for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:\r
1206             DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))\r
1207         return DirList\r
1208 \r
1209     _TemplateDict = property(_CreateTemplateDict)\r
1210 \r
1211 class TopLevelMakefile(BuildFile):\r
1212     _TEMPLATE_ = '''\\r
1213 ${makefile_header}\r
1214 \r
1215 #\r
1216 # Platform Macro Definition\r
1217 #\r
1218 PLATFORM_NAME = ${platform_name}\r
1219 PLATFORM_GUID = ${platform_guid}\r
1220 PLATFORM_VERSION = ${platform_version}\r
1221 \r
1222 #\r
1223 # Build Configuration Macro Definition\r
1224 #\r
1225 TOOLCHAIN_TAG = ${toolchain_tag}\r
1226 TARGET = ${build_target}\r
1227 \r
1228 #\r
1229 # Build Directory Macro Definition\r
1230 #\r
1231 BUILD_DIR = ${platform_build_directory}\r
1232 FV_DIR = ${platform_build_directory}${separator}FV\r
1233 \r
1234 #\r
1235 # Shell Command Macro\r
1236 #\r
1237 ${BEGIN}${shell_command_code} = ${shell_command}\r
1238 ${END}\r
1239 \r
1240 MAKE = ${make_path}\r
1241 MAKE_FLAGS = ${make_flag}\r
1242 MAKE_FILE = ${makefile_path}\r
1243 \r
1244 #\r
1245 # Default target\r
1246 #\r
1247 all: modules fds\r
1248 \r
1249 #\r
1250 # Initialization target: print build information and create necessary directories\r
1251 #\r
1252 init:\r
1253 \t-@echo Building ... $(PLATFORM_NAME) [${build_architecture_list}]\r
1254 \t${BEGIN}-@${create_directory_command}\r
1255 \t${END}\r
1256 #\r
1257 # library build target\r
1258 #\r
1259 libraries: init\r
1260 ${BEGIN}\t@cd $(BUILD_DIR)${separator}${arch} && "$(MAKE)" $(MAKE_FLAGS) libraries\r
1261 ${END}\t@cd $(BUILD_DIR)\r
1262 \r
1263 #\r
1264 # module build target\r
1265 #\r
1266 modules: init\r
1267 ${BEGIN}\t@cd $(BUILD_DIR)${separator}${arch} && "$(MAKE)" $(MAKE_FLAGS) modules\r
1268 ${END}\t@cd $(BUILD_DIR)\r
1269 \r
1270 #\r
1271 # Flash Device Image Target\r
1272 #\r
1273 fds: init\r
1274 \t-@cd $(FV_DIR)\r
1275 ${BEGIN}\tGenFds -f ${fdf_file} -o $(BUILD_DIR) -t $(TOOLCHAIN_TAG) -b $(TARGET) -p ${active_platform} -a ${build_architecture_list} ${log_level}${END}${BEGIN} -r ${fd} ${END}${BEGIN} -i ${fv} ${END}${BEGIN} -y ${macro} ${END}\r
1276 \r
1277 #\r
1278 # run command for emulator platform only\r
1279 #\r
1280 run:\r
1281 \tcd $(BUILD_DIR)${separator}IA32\r
1282 \tSecMain\r
1283 \tcd $(BUILD_DIR)\r
1284 \r
1285 #\r
1286 # Clean intermediate files\r
1287 #\r
1288 clean:\r
1289 ${BEGIN}\t@cd $(BUILD_DIR)${separator}${arch} && "$(MAKE)" $(MAKE_FLAGS) clean\r
1290 ${END}\t@cd $(BUILD_DIR)\r
1291 \r
1292 #\r
1293 # Clean all generated files except to makefile\r
1294 #\r
1295 cleanall:\r
1296 ${BEGIN}\t${cleanall_command}\r
1297 ${END}\r
1298 \r
1299 #\r
1300 # Clean all library files\r
1301 #\r
1302 cleanlib:\r
1303 ${BEGIN}\t@cd $(BUILD_DIR)${separator}${arch} && "$(MAKE)" $(MAKE_FLAGS) cleanlib\r
1304 ${END}\t@cd $(BUILD_DIR)\n\r
1305 '''\r
1306 \r
1307     def __init__(self, Workspace):\r
1308         BuildFile.__init__(self, Workspace)\r
1309         self.IntermediateDirectoryList = []\r
1310 \r
1311     ## Create makefile of platform\r
1312     #\r
1313     #   @param      File        The path of the makefile\r
1314     #   @param      MakeType    GNU makefile or MS makefile\r
1315     #\r
1316     #   @retval     True        If the file is changed or doesn't exist\r
1317     #   @retval     False       If the file exists and its content is not changed\r
1318     #                           since last time\r
1319     #\r
1320     def _CreateTemplateDict(self):\r
1321         Separator = self._SEP_[self._FileType]\r
1322 \r
1323         # any platform autogen object is ok because we just need common information\r
1324         PlatformInfo = self._AutoGenObject\r
1325 \r
1326         if "MAKE" not in PlatformInfo.ToolPath:\r
1327             EdkLogger.error("GenMake", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!")\r
1328 \r
1329         for Arch in PlatformInfo.ArchList:\r
1330             self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch]))\r
1331         self.IntermediateDirectoryList.append("$(FV_DIR)")\r
1332 \r
1333         # TRICK: for not generating GenFds call in makefile if no FDF file\r
1334         MacroList = []\r
1335         if PlatformInfo.FdfFile != None and PlatformInfo.FdfFile != "":\r
1336             FdfFileList = [PlatformInfo.FdfFile]\r
1337             # macros passed to GenFds\r
1338             for MacroName in GlobalData.gGlobalDefines:\r
1339                 MacroList.append('"%s=%s"' % (MacroName, GlobalData.gGlobalDefines[MacroName]))    \r
1340         else:\r
1341             FdfFileList = []\r
1342 \r
1343         # pass log level to external program called in makefile, currently GenFds.exe\r
1344         LogLevel = EdkLogger.GetLevel()\r
1345         if LogLevel == EdkLogger.VERBOSE:\r
1346             LogOption = "-v"\r
1347         elif LogLevel <= EdkLogger.DEBUG_9:\r
1348             LogOption = "-d %d" % (LogLevel - 1)\r
1349         elif LogLevel == EdkLogger.QUIET:\r
1350             LogOption = "-q"\r
1351         else:\r
1352             LogOption = ""\r
1353 \r
1354         MakefileName = self._FILE_NAME_[self._FileType]\r
1355         MakefileTemplateDict = {\r
1356             "makefile_header"           : self._FILE_HEADER_[self._FileType],\r
1357             "makefile_path"             : os.path.join("$(BUILD_DIR)", MakefileName),\r
1358             "platform_name"             : PlatformInfo.Name,\r
1359             "platform_guid"             : PlatformInfo.Guid,\r
1360             "platform_version"          : PlatformInfo.Version,\r
1361             "platform_build_directory"  : PlatformInfo.BuildDir,\r
1362 \r
1363             "toolchain_tag"             : PlatformInfo.ToolChain,\r
1364             "build_target"              : PlatformInfo.BuildTarget,\r
1365             "make_path"                 : PlatformInfo.ToolPath["MAKE"],\r
1366             "make_flag"                 : PlatformInfo.ToolOption["MAKE"],\r
1367             "shell_command_code"        : self._SHELL_CMD_[self._FileType].keys(),\r
1368             "shell_command"             : self._SHELL_CMD_[self._FileType].values(),\r
1369             'arch'                      : list(PlatformInfo.ArchList),\r
1370             "build_architecture_list"   : ','.join(PlatformInfo.ArchList),\r
1371             "separator"                 : Separator,\r
1372             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),\r
1373             "cleanall_command"          : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList),\r
1374             "fdf_file"                  : FdfFileList,\r
1375             "active_platform"           : PlatformInfo.WorkspaceDir + Separator + str(PlatformInfo),\r
1376             "fd"                        : PlatformInfo.FdTargetList,\r
1377             "fv"                        : PlatformInfo.FvTargetList,\r
1378             "log_level"                 : LogOption,\r
1379             "macro"                     : MacroList,\r
1380         }\r
1381 \r
1382         return MakefileTemplateDict\r
1383 \r
1384     ## Get the root directory list for intermediate files of all modules build\r
1385     #\r
1386     #   @retval     list    The list of directory\r
1387     #\r
1388     def GetModuleBuildDirectoryList(self):\r
1389         DirList = []\r
1390         for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList:\r
1391             DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir))\r
1392         return DirList\r
1393 \r
1394     ## Get the root directory list for intermediate files of all libraries build\r
1395     #\r
1396     #   @retval     list    The list of directory\r
1397     #\r
1398     def GetLibraryBuildDirectoryList(self):\r
1399         DirList = []\r
1400         for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList:\r
1401             DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir))\r
1402         return DirList\r
1403 \r
1404     _TemplateDict = property(_CreateTemplateDict)\r
1405 \r
1406 \r
1407 # This acts like the main() function for the script, unless it is 'import'ed into another script.\r
1408 if __name__ == '__main__':\r
1409     pass\r