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