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