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