77cb9983189d7af461a86603e6a485cf48056fd9
[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.BuildFileList = []\r
574             self.TargetFileList = []\r
575             self.ObjectFileList = []\r
576             self.ObjectBuildTargetList = []\r
577 \r
578             self.FileDependency = []\r
579             self.LibraryBuildCommandList = []\r
580             self.LibraryFileList = []\r
581             self.LibraryMakefileList = []\r
582             self.LibraryBuildDirectoryList = []\r
583             self.SystemLibraryList = []\r
584         elif type(Info) == type({}):    # and isinstance(info, PlatformBuildInfo):\r
585             if len(Info) <= 0:\r
586                 EdkLogger.error("AutoGen", AUTOGEN_ERROR, "No buildable platform found! Please check your build configuration!\n")\r
587             self.PlatformInfo = Info\r
588             self.ModuleBuild = False\r
589             self.ModuleBuildCommandList = []\r
590             self.ModuleMakefileList = []\r
591             self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()\r
592             self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()\r
593         else:\r
594             EdkLogger.error("AutoGen", AUTOGEN_ERROR, "Non-buildable item:%s" % str(Info))\r
595 \r
596         self.IntermediateDirectoryList = []\r
597 \r
598     ## Create necessary directory for makefile generation\r
599     def PrepareDirectory(self):\r
600         if self.ModuleBuild:\r
601             CreateDirectory(path.join(self.ModuleInfo.WorkspaceDir, self.PlatformInfo.BuildDir))\r
602             CreateDirectory(path.join(self.ModuleInfo.WorkspaceDir, self.ModuleInfo.BuildDir))\r
603             CreateDirectory(path.join(self.ModuleInfo.WorkspaceDir, self.ModuleInfo.DebugDir))\r
604 \r
605     ## Create the makefile\r
606     #\r
607     #   @param      File        The path of the makefile\r
608     #   @param      MakeType    GNU makefile or MS makefile\r
609     #\r
610     #   @retval     True        If the file is changed or doesn't exist\r
611     #   @retval     False       If the file exists and its content is not changed\r
612     #                           since last time\r
613     #\r
614     def Generate(self, File=None, MakeType=gMakeType):\r
615         if self.ModuleBuild:\r
616             return self.GenerateModuleMakefile(File, MakeType)\r
617         else:\r
618             return self.GeneratePlatformMakefile(File, MakeType)\r
619 \r
620     ## Create makefile of platform\r
621     #\r
622     #   @param      File        The path of the makefile\r
623     #   @param      MakeType    GNU makefile or MS makefile\r
624     #\r
625     #   @retval     True        If the file is changed or doesn't exist\r
626     #   @retval     False       If the file exists and its content is not changed\r
627     #                           since last time\r
628     #\r
629     def GeneratePlatformMakefile(self, File=None, MakeType=gMakeType):\r
630         Separator = gDirectorySeparator[MakeType]\r
631 \r
632         ArchList = self.PlatformInfo.keys()\r
633         PlatformInfo = self.PlatformInfo.values()[0]\r
634         ActivePlatform = PlatformInfo.Platform\r
635 \r
636         if "MAKE" not in PlatformInfo.ToolPath:\r
637             EdkLogger.error("GenMake", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!")\r
638 \r
639         OutputDir = PlatformInfo.OutputDir\r
640         if os.path.isabs(OutputDir):\r
641             self.PlatformBuildDirectory = OutputDir\r
642             CreateDirectory(self.PlatformBuildDirectory)\r
643         else:\r
644             self.PlatformBuildDirectory = "$(WORKSPACE)" + Separator + OutputDir\r
645             CreateDirectory(os.path.join(PlatformInfo.WorkspaceDir, OutputDir))\r
646 \r
647 \r
648         self.IntermediateDirectoryList = ["$(BUILD_DIR)%s%s" % (Separator, Arch) for Arch in self.PlatformInfo]\r
649         self.IntermediateDirectoryList.append("$(FV_DIR)")\r
650 \r
651         # TRICK: for not generating GenFds call in makefile if no FDF file\r
652         MacroList = []\r
653         if PlatformInfo.FdfFile != None and PlatformInfo.FdfFile != "":\r
654             FdfFileList = [PlatformInfo.FdfFile]\r
655             for MacroName in GlobalData.gGlobalDefines:\r
656                 MacroList.append('"%s=%s"' % (MacroName, GlobalData.gGlobalDefines[MacroName]))    \r
657         else:\r
658             FdfFileList = []\r
659 \r
660         # pass log level to external program called in makefile, currently GenFds.exe\r
661         LogLevel = EdkLogger.GetLevel()\r
662         if LogLevel == EdkLogger.VERBOSE:\r
663             LogOption = "-v"\r
664         elif LogLevel <= EdkLogger.DEBUG_9:\r
665             LogOption = "-d %d" % (LogLevel - 1)\r
666         elif LogLevel == EdkLogger.QUIET:\r
667             LogOption = "-q"\r
668         else:\r
669             LogOption = ""\r
670 \r
671         MakefileName = gMakefileName[MakeType]\r
672         MakefileTemplateDict = {\r
673             "makefile_header"           : gMakefileHeader % MakefileName,\r
674             "makefile_path"             : os.path.join("$(BUILD_DIR)", MakefileName),\r
675             "platform_name"             : PlatformInfo.Name,\r
676             "platform_guid"             : PlatformInfo.Guid,\r
677             "platform_version"          : PlatformInfo.Version,\r
678             "platform_relative_directory": PlatformInfo.SourceDir,\r
679             "platform_output_directory" : PlatformInfo.OutputDir,\r
680             "platform_build_directory"  : self.PlatformBuildDirectory,\r
681 \r
682             "toolchain_tag"             : PlatformInfo.ToolChain,\r
683             "build_target"              : PlatformInfo.BuildTarget,\r
684             "make_path"                 : PlatformInfo.ToolPath["MAKE"],\r
685             "make_flag"                 : PlatformInfo.ToolOption["MAKE"],\r
686             "build_architecture_list"   : ",".join(ArchList),\r
687             "architecture"              : self.PlatformInfo.keys(),\r
688             "separator"                 : Separator,\r
689             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList, MakeType),\r
690             "remove_directory_command"  : gRemoveDirectoryCommand[MakeType],\r
691             "remove_file_command"       : gRemoveFileCommand[MakeType],\r
692             "cleanall_command"          : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList, MakeType),\r
693             "library_build_directory"   : self.LibraryBuildDirectoryList,\r
694             "module_build_directory"    : self.ModuleBuildDirectoryList,\r
695             "fdf_file"                  : FdfFileList,\r
696             "active_platform"           : PlatformInfo.WorkspaceDir + Separator + ActivePlatform.DescFilePath,\r
697             "fd"                        : PlatformInfo.FdTargetList,\r
698             "fv"                        : PlatformInfo.FvTargetList,\r
699             "log_level"                 : LogOption,\r
700             "macro"                     : MacroList,\r
701         }\r
702 \r
703         self.PrepareDirectory()\r
704 \r
705         AutoGenMakefile = TemplateString()\r
706         AutoGenMakefile.Append(gPlatformMakefileTemplate, MakefileTemplateDict)\r
707 \r
708         FilePath = ""\r
709         if File == None:\r
710             FilePath = path.join(PlatformInfo.WorkspaceDir, PlatformInfo.MakeFileDir, MakefileName)\r
711         else:\r
712             FilePath = File\r
713 \r
714         return SaveFileOnChange(FilePath, str(AutoGenMakefile))\r
715 \r
716     ## Create makefile of a module\r
717     #\r
718     #   @param      File        The path of the makefile\r
719     #   @param      MakeType    GNU makefile or MS makefile\r
720     #\r
721     #   @retval     True        If the file is changed or doesn't exist\r
722     #   @retval     False       If the file exists and its content is not changed\r
723     #                           since last time\r
724     #\r
725     def GenerateModuleMakefile(self, File=None, MakeType=gMakeType):\r
726         if MakeType in self.ModuleInfo.CustomMakefile and self.ModuleInfo.CustomMakefile[MakeType] != "":\r
727             return self.GenerateCustomBuildMakefile(File, MakeType)\r
728 \r
729         Separator = gDirectorySeparator[MakeType]\r
730         PlatformInfo = self.PlatformInfo\r
731 \r
732         if os.path.isabs(PlatformInfo.OutputDir):\r
733             self.PlatformBuildDirectory = PlatformInfo.OutputDir\r
734         else:\r
735             self.PlatformBuildDirectory = "$(WORKSPACE)" + Separator + PlatformInfo.OutputDir\r
736 \r
737         self.ProcessSourceFileList(MakeType)\r
738         self.ProcessDependentLibrary(MakeType)\r
739 \r
740         if "DLINK" in PlatformInfo.ToolStaticLib:\r
741             EdkLogger.debug(EdkLogger.DEBUG_5, "Static library: " + PlatformInfo.ToolStaticLib["DLINK"])\r
742             self.SystemLibraryList.append(PlatformInfo.ToolStaticLib["DLINK"])\r
743 \r
744         if self.ModuleInfo.Arch == "EBC":\r
745             # EBC compiler always use "EfiStart" as entry point\r
746             EntryPoint = "EfiStart"\r
747         elif self.ModuleInfo.AutoGenVersion < 0x00010005 and len(self.ModuleInfo.Module.ModuleEntryPointList) > 0:\r
748             # R8 modules use different entry point functions\r
749             EntryPoint = self.ModuleInfo.Module.ModuleEntryPointList[0]\r
750         else:\r
751             # R9 modules always use "_ModuleEntryPoint" as entry point\r
752             EntryPoint = "_ModuleEntryPoint"\r
753 \r
754         DefaultToolFlag = PlatformInfo.ToolOption.values()\r
755         if self.ModuleInfo.ModuleType == "USER_DEFINED":\r
756             DefaultToolFlag = ["" for p in DefaultToolFlag]\r
757 \r
758         if "CC" not in PlatformInfo.ToolChainFamily:\r
759             EdkLogger.error("AutoGen", AUTOGEN_ERROR, "Tool [CC] is not supported [%s, %s, %s]" % (self.ModuleInfo.BuildTarget,\r
760                                     self.ModuleInfo.ToolChain, self.ModuleInfo.Arch))\r
761         if  "DLINK" not in PlatformInfo.ToolChainFamily:\r
762             EdkLogger.error("AutoGen", AUTOGEN_ERROR, "Tool [DLINK] is not supported [%s, %s, %s]" % (self.ModuleInfo.BuildTarget,\r
763                                     self.ModuleInfo.ToolChain, self.ModuleInfo.Arch))\r
764 \r
765         if self.ModuleInfo.IsLibrary:\r
766             self.ResultFileList = self.DestFileDatabase["Static-Library-File"]\r
767         elif self.ModuleInfo.ModuleType == "USER_DEFINED":\r
768             self.ResultFileList = self.DestFileDatabase["Dynamic-Library-File"]\r
769 \r
770         SourceFileMacroNameList = []\r
771         SourceFileMacroList = [] # macro name = file list\r
772         for FileType in self.SourceFileDatabase:\r
773             Macro = "%s_LIST" % FileType.replace("-", "_").upper()\r
774             SourceFileMacroNameList.append("$(%s)" % Macro)\r
775             Template = TemplateString()\r
776             Template.Append("%s = ${BEGIN}${source_file} \\\n\t${END}" % Macro,\r
777                             {"source_file" : self.SourceFileDatabase[FileType]})\r
778             SourceFileMacroList.append(str(Template))\r
779         TargetFileMacroList = []\r
780         TargetFileMacroNameList = []\r
781         for FileType in self.DestFileDatabase:\r
782             Macro = "%s_LIST" % FileType.replace("-", "_").upper()\r
783             TargetFileMacroNameList.append("$(%s)" % Macro)\r
784             Template = TemplateString()\r
785             Template.Append("%s = ${BEGIN}${target_file} \\\n\t${END}" % Macro,\r
786                             {"target_file" : self.DestFileDatabase[FileType]})\r
787             TargetFileMacroList.append(str(Template))\r
788 \r
789         # R8 modules need <BaseName>StrDefs.h for string ID\r
790         if self.ModuleInfo.AutoGenVersion < 0x00010005 and len(self.ModuleInfo.UnicodeFileList) > 0:\r
791             AutoGenHeaderFile = os.path.join("$(DEBUG_DIR)", "AutoGen.h")\r
792             StringHeaderFile = os.path.join("$(DEBUG_DIR)", "%sStrDefs.h" % self.ModuleInfo.BaseName)\r
793             CopyAutoGenHeaderFile = ["$(CP) %s %s" % (AutoGenHeaderFile, StringHeaderFile)]\r
794         else:\r
795             CopyAutoGenHeaderFile = []\r
796 \r
797         MakefileName = gMakefileName[MakeType]\r
798         MakefileTemplateDict = {\r
799             "makefile_header"           : gMakefileHeader % MakefileName,\r
800             "makefile_path"             : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),\r
801             "platform_name"             : PlatformInfo.Name,\r
802             "platform_guid"             : PlatformInfo.Guid,\r
803             "platform_version"          : PlatformInfo.Version,\r
804             "platform_relative_directory": PlatformInfo.SourceDir,\r
805             "platform_output_directory" : PlatformInfo.OutputDir,\r
806 \r
807             "module_name"               : self.ModuleInfo.Name,\r
808             "module_guid"               : self.ModuleInfo.Guid,\r
809             "module_version"            : self.ModuleInfo.Version,\r
810             "module_type"               : self.ModuleInfo.ModuleType,\r
811             "module_file_base_name"     : self.ModuleInfo.FileBase,\r
812             "module_relative_directory" : self.ModuleInfo.SourceDir,\r
813 \r
814             "architecture"              : self.ModuleInfo.Arch,\r
815             "toolchain_tag"             : self.ModuleInfo.ToolChain,\r
816             "build_target"              : self.ModuleInfo.BuildTarget,\r
817 \r
818             "platform_build_directory"  : self.PlatformBuildDirectory,\r
819 \r
820             "separator"                 : Separator,\r
821             "default_tool_flags"        : DefaultToolFlag,\r
822             "platform_tool_flags"       : [PlatformInfo.BuildOption[tool] for tool in PlatformInfo.ToolPath],\r
823             "module_tool_flags"         : [self.ModuleInfo.BuildOption[tool] for tool in PlatformInfo.ToolPath],\r
824 \r
825             "tool_code"                 : PlatformInfo.ToolPath.keys(),\r
826             "tool_path"                 : PlatformInfo.ToolPath.values(),\r
827 \r
828             "shell_command_code"        : gShellCommand[MakeType].keys(),\r
829             "shell_command"             : gShellCommand[MakeType].values(),\r
830 \r
831             "module_entry_point"        : EntryPoint,\r
832             "include_path_prefix"       : gIncludeFlag[PlatformInfo.ToolChainFamily["CC"]],\r
833             "dlink_output_flag"         : PlatformInfo.OutputFlag["DLINK"],\r
834             "slink_output_flag"         : PlatformInfo.OutputFlag["SLINK"],\r
835             "start_group_flag"          : gStartGroupFlag[PlatformInfo.ToolChainFamily["DLINK"]],\r
836             "end_group_flag"            : gEndGroupFlag[PlatformInfo.ToolChainFamily["DLINK"]],\r
837             "include_path"              : self.ModuleInfo.IncludePathList,\r
838             "target_file"               : self.TargetFileList,\r
839             "object_file"               : self.ObjectFileList,\r
840             "library_file"              : self.LibraryFileList,\r
841             "remaining_build_target"    : self.ResultFileList,\r
842             "system_library"            : self.SystemLibraryList,\r
843             "common_dependency_file"    : self.CommonFileDependency,\r
844             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList, MakeType),\r
845             "remove_directory_command"  : gRemoveDirectoryCommand[MakeType],\r
846             "remove_file_command"       : gRemoveFileCommand[MakeType],\r
847             "copy_file_command"         : gCopyFileCommand[MakeType],\r
848             "clean_command"             : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"], MakeType),\r
849             "cleanall_command"          : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"], MakeType),\r
850             "dependent_library_build_directory" : self.LibraryBuildDirectoryList,\r
851             "build_type"                        : self.BuildType,\r
852             "source_file_macro"         : SourceFileMacroList,\r
853             "target_file_macro"         : TargetFileMacroList,\r
854             "source_file_macro_name"    : SourceFileMacroNameList,\r
855             "target_file_macro_name"    : TargetFileMacroNameList,\r
856             "file_build_target"         : self.BuildTargetList,\r
857             "copy_autogen_h"            : CopyAutoGenHeaderFile,\r
858         }\r
859 \r
860         self.PrepareDirectory()\r
861 \r
862         AutoGenMakefile = TemplateString()\r
863         AutoGenMakefile.Append(gModuleMakefileTemplate, MakefileTemplateDict)\r
864 \r
865         FilePath = ""\r
866         if File == None:\r
867             FilePath = path.join(self.ModuleInfo.WorkspaceDir, self.ModuleInfo.MakeFileDir, MakefileName)\r
868         else:\r
869             FilePath = File\r
870 \r
871         return SaveFileOnChange(FilePath, str(AutoGenMakefile))\r
872 \r
873     ## Create customized makefile for a module\r
874     #\r
875     #   @param      File        The path of the makefile\r
876     #   @param      MakeType    GNU makefile or MS makefile\r
877     #\r
878     #   @retval     True        If the file is changed or doesn't exist\r
879     #   @retval     False       If the file exists and its content is not changed\r
880     #                           since last time\r
881     #\r
882     def GenerateCustomBuildMakefile(self, File=None, MakeType=gMakeType):\r
883         Separator = gDirectorySeparator[MakeType]\r
884 \r
885         if os.path.isabs(self.PlatformInfo.OutputDir):\r
886             self.PlatformBuildDirectory = self.PlatformInfo.OutputDir\r
887         else:\r
888             self.PlatformBuildDirectory = "$(WORKSPACE)" + Separator + self.PlatformInfo.OutputDir\r
889 \r
890         CustomMakefile = open(os.path.join(self.ModuleInfo.WorkspaceDir, self .ModuleInfo.CustomMakefile[MakeType]), 'r').read()\r
891 \r
892         MakefileName = gMakefileName[MakeType]\r
893         MakefileTemplateDict = {\r
894             "makefile_header"           : gMakefileHeader % MakefileName,\r
895             "platform_name"             : self.PlatformInfo.Name,\r
896             "platform_guid"             : self.PlatformInfo.Guid,\r
897             "platform_version"          : self.PlatformInfo.Version,\r
898             "platform_relative_directory": self.PlatformInfo.SourceDir,\r
899             "platform_output_directory" : self.PlatformInfo.OutputDir,\r
900 \r
901             "module_name"               : self.ModuleInfo.Name,\r
902             "module_guid"               : self.ModuleInfo.Guid,\r
903             "module_version"            : self.ModuleInfo.Version,\r
904             "module_type"               : self.ModuleInfo.ModuleType,\r
905             "module_file_base_name"     : self.ModuleInfo.FileBase,\r
906             "module_relative_directory" : self.ModuleInfo.SourceDir,\r
907 \r
908             "architecture"              : self.ModuleInfo.Arch,\r
909             "toolchain_tag"             : self.ModuleInfo.ToolChain,\r
910             "build_target"              : self.ModuleInfo.BuildTarget,\r
911 \r
912             "platform_build_directory"  : self.PlatformBuildDirectory,\r
913 \r
914             "separator"                 : Separator,\r
915             "default_tool_flags"        : self.PlatformInfo.ToolOption.values(),\r
916             "platform_tool_flags"       : self.PlatformInfo.BuildOption.values(),\r
917             "module_tool_flags"         : self.ModuleInfo.BuildOption.values(),\r
918 \r
919             "tool_code"                 : self.PlatformInfo.ToolPath.keys(),\r
920             "tool_path"                 : self.PlatformInfo.ToolPath.values(),\r
921 \r
922             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList, MakeType),\r
923             "directory_to_be_created"   : self.IntermediateDirectoryList,\r
924             "dependent_library_build_directory" : self.LibraryBuildDirectoryList,\r
925             "custom_makefile_content"   : CustomMakefile\r
926         }\r
927 \r
928         self.PrepareDirectory()\r
929 \r
930         AutoGenMakefile = TemplateString()\r
931         AutoGenMakefile.Append(gCustomMakefileTemplate, MakefileTemplateDict)\r
932 \r
933         FilePath = ""\r
934         if File == None:\r
935             FilePath = path.join(self.ModuleInfo.WorkspaceDir, self.ModuleInfo.MakeFileDir, MakefileName)\r
936         else:\r
937             FilePath = File\r
938 \r
939         return SaveFileOnChange(FilePath, str(AutoGenMakefile))\r
940 \r
941     ## Process source files to generate makefile targets and dependencies\r
942     #\r
943     #  The intermediate and final targets and dependencies are controlled by\r
944     #  build rules in $(WORKSPACE)/Conf/build_rule.txt. The dependencies of source\r
945     #  file are figured out by search included files in the source file.\r
946     #\r
947     #   @param      MakeType    GNU makefile or MS makefile\r
948     #\r
949     def ProcessSourceFileList(self, MakeType=gMakeType):\r
950         Separator = gDirectorySeparator[MakeType]\r
951 \r
952         Family = self.PlatformInfo.ToolChainFamily["CC"]\r
953         BuildRule = self.PlatformInfo.BuildRule\r
954 \r
955         self.ResultFileList = []\r
956         self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]\r
957 \r
958         self.SourceFileDatabase = {}  # {file type : file path}\r
959         self.DestFileDatabase = {}  # {file type : file path}\r
960         self.FileBuildTargetList = [] # [(src, target string)]\r
961         self.BuildTargetList = [] # [target string]\r
962         self.PendingBuildTargetList = [] # [FileBuildRule objects]\r
963 \r
964         ForceIncludedFile = []\r
965         SourceFileList = []\r
966 \r
967         FileList = self.ModuleInfo.SourceFileList\r
968         if len(FileList) == 0:\r
969             EdkLogger.error("AutoGen", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]"\r
970                             % (self.ModuleInfo.BuildTarget, self.ModuleInfo.ToolChain, self.ModuleInfo.Arch),\r
971                             ExtraData=str(self.ModuleInfo.Module))\r
972 \r
973         CCodeFlag = False\r
974         for FileInfo in FileList:\r
975             F, SrcFileType, SrcFileBuildRule = FileInfo\r
976             if SrcFileType == "C-Code-File":\r
977                 CCodeFlag = True\r
978             SrcFileName = path.basename(F)\r
979             SrcFileBase, SrcFileExt = path.splitext(SrcFileName)\r
980             SrcFileDir = path.dirname(F)\r
981             if SrcFileDir == "":\r
982                 SrcFileDir = "."\r
983             else:\r
984                 P = "$(OUTPUT_DIR)" + Separator + SrcFileDir\r
985                 if P not in self.IntermediateDirectoryList:\r
986                     self.IntermediateDirectoryList.append(P)\r
987             SrcFileRelativePath = os.path.join(self.ModuleInfo.SourceDir, F)\r
988 \r
989             SrcFile, ExtraSrcFileList, DstFile, CommandList = SrcFileBuildRule.Apply(F, self.ModuleInfo.SourceDir, Separator)\r
990 \r
991             if SrcFileType not in self.SourceFileDatabase:\r
992                 self.SourceFileDatabase[SrcFileType] = []\r
993             self.SourceFileDatabase[SrcFileType].append(SrcFile)\r
994             SourceFileList.append(SrcFileRelativePath)\r
995 \r
996             BuildTargetTemplate = "${BEGIN}%s : ${deps}\n"\\r
997                                   "${END}\t%s\n" % (DstFile, "\n\t".join(CommandList))\r
998             self.FileBuildTargetList.append((SrcFileRelativePath, BuildTargetTemplate))\r
999 \r
1000             while True:\r
1001                 # next target\r
1002                 DstFileType, DstFileBuildRule = BuildRule.Get(SrcFileBuildRule.DestFileExt, Family)\r
1003                 if DstFileType == None:\r
1004                     DstFileType = "Unknown-Type-File"\r
1005 \r
1006                 if DstFileType  in self.SourceFileDatabase:\r
1007                     self.SourceFileDatabase[DstFileType].append(DstFile)\r
1008                 else:\r
1009                     if DstFileType not in self.DestFileDatabase:\r
1010                         self.DestFileDatabase[DstFileType] = []\r
1011                     self.DestFileDatabase[DstFileType].append(DstFile)\r
1012 \r
1013                 if DstFileBuildRule != None and DstFileBuildRule.IsMultipleInput:\r
1014                     if DstFileBuildRule not in self.PendingBuildTargetList:\r
1015                         self.PendingBuildTargetList.append(DstFileBuildRule)\r
1016                     break\r
1017                 elif DstFileBuildRule == None or DstFileBuildRule.CommandList == []:\r
1018                     self.ResultFileList.append(DstFile)\r
1019                     break\r
1020 \r
1021                 SrcFile, ExtraSrcFileList, DstFile, CommandList = DstFileBuildRule.Apply(DstFile, None, Separator)\r
1022                 BuildTargetString = "%s : %s %s\n"\\r
1023                                     "\t%s\n" % (DstFile, SrcFile, " ".join(ExtraSrcFileList), "\n\t".join(CommandList))\r
1024                 self.FileBuildTargetList.append((SrcFile, BuildTargetString))\r
1025                 SrcFileBuildRule = DstFileBuildRule\r
1026 \r
1027         # handle pending targets\r
1028         TempBuildTargetList = []\r
1029         while True:\r
1030             while len(self.PendingBuildTargetList) > 0:\r
1031                 SrcFileBuildRule = self.PendingBuildTargetList.pop()\r
1032                 SrcFileList = []\r
1033                 for FileType in SrcFileBuildRule.SourceFileType:\r
1034                     if FileType not in self.SourceFileDatabase:\r
1035                         if FileType not in self.DestFileDatabase:\r
1036                             continue\r
1037                         else:\r
1038                             SrcFileList.extend(self.DestFileDatabase[FileType])\r
1039                     else:\r
1040                         SrcFileList.extend(self.SourceFileDatabase[FileType])\r
1041                 SrcFile, ExtraSrcFileList, DstFile, CommandList = SrcFileBuildRule.Apply(SrcFileList, None, Separator)\r
1042                 BuildTargetString = "%s : %s %s\n"\\r
1043                                     "\t%s\n" % (DstFile, SrcFile, " ".join(ExtraSrcFileList), "\n\t".join(CommandList))\r
1044                 self.FileBuildTargetList.append((SrcFile, BuildTargetString))\r
1045 \r
1046                 # try to find next target\r
1047                 while True:\r
1048                     DstFileType, DstFileBuildRule = BuildRule.Get(SrcFileBuildRule.DestFileExt, Family)\r
1049                     if DstFileType == None:\r
1050                         DstFileType = "Unknown-Type-File"\r
1051 \r
1052                     if DstFileType  in self.SourceFileDatabase:\r
1053                         self.SourceFileDatabase[DstFileType].append(DstFile)\r
1054                     else:\r
1055                         if DstFileType not in self.DestFileDatabase:\r
1056                             self.DestFileDatabase[DstFileType] = []\r
1057                         self.DestFileDatabase[DstFileType].append(DstFile)\r
1058 \r
1059                     if DstFileBuildRule != None and DstFileBuildRule.IsMultipleInput:\r
1060                         TempBuildTargetList.append(DstFileBuildRule)\r
1061                         break\r
1062                     elif DstFileBuildRule == None or DstFileBuildRule.CommandList == []:\r
1063                         self.ResultFileList.append(DstFile)\r
1064                         break\r
1065 \r
1066                     SrcFile, ExtraSrcFileList, DstFile, CommandList = DstFileBuildRule.Apply(DstFile, None, Separator)\r
1067                     BuildTargetString = "%s : %s %s\n"\\r
1068                                         "\t%s\n" % (DstFile, SrcFile, " ".join(ExtraSrcFileList), "\n\t".join(CommandList))\r
1069                     self.FileBuildTargetList.append((SrcFile, BuildTargetString))\r
1070                     SrcFileBuildRule = DstFileBuildRule\r
1071             if len(TempBuildTargetList) == 0:\r
1072                 break\r
1073             self.PendingBuildTargetList = TempBuildTargetList\r
1074 \r
1075         if CCodeFlag == True:\r
1076             for F in self.ModuleInfo.AutoGenFileList:\r
1077                 SrcFileName = path.basename(F)\r
1078                 SrcFileBase, SrcFileExt = path.splitext(SrcFileName)\r
1079                 SrcFileDir = path.dirname(F)\r
1080                 if SrcFileDir == "":\r
1081                     SrcFileDir = "."\r
1082                 else:\r
1083                     P = "$(DEBUG_DIR)" + Separator + SrcFileDir\r
1084                     if P not in self.IntermediateDirectoryList:\r
1085                         self.IntermediateDirectoryList.append(P)\r
1086 \r
1087                 SrcFileRelativePath = os.path.join(self.ModuleInfo.DebugDir, F)\r
1088 \r
1089                 SrcFileType, SrcFileBuildRule = BuildRule.Get(SrcFileExt, Family)\r
1090                 if SrcFileType != None and SrcFileType == "C-Header-File":\r
1091                     ForceIncludedFile.append(SrcFileRelativePath)\r
1092                 if SrcFileBuildRule == None or SrcFileBuildRule.CommandList == []:\r
1093                     continue\r
1094 \r
1095                 SrcFile, ExtraSrcFileList, DstFile, CommandList = SrcFileBuildRule.Apply(F, self.ModuleInfo.DebugDir, Separator)\r
1096 \r
1097                 if SrcFileType not in self.SourceFileDatabase:\r
1098                     self.SourceFileDatabase[SrcFileType] = []\r
1099                 self.SourceFileDatabase[SrcFileType].append(SrcFile)\r
1100                 SourceFileList.append(SrcFileRelativePath)\r
1101 \r
1102                 BuildTargetTemplate = "${BEGIN}%s : ${deps}\n"\\r
1103                                       "${END}\t%s\n" % (DstFile, "\n\t".join(CommandList))\r
1104                 self.FileBuildTargetList.append((SrcFileRelativePath, BuildTargetTemplate))\r
1105 \r
1106                 while True:\r
1107                     # next target\r
1108                     DstFileType, DstFileBuildRule = BuildRule.Get(SrcFileBuildRule.DestFileExt, Family)\r
1109                     if DstFileType == None:\r
1110                         DstFileType = "Unknown-Type-File"\r
1111 \r
1112                     if DstFileType  in self.SourceFileDatabase:\r
1113                         self.SourceFileDatabase[DstFileType].append(DstFile)\r
1114                     else:\r
1115                         if DstFileType not in self.DestFileDatabase:\r
1116                             self.DestFileDatabase[DstFileType] = []\r
1117                         self.DestFileDatabase[DstFileType].append(DstFile)\r
1118 \r
1119                     if DstFileBuildRule != None and DstFileBuildRule.IsMultipleInput:\r
1120                         if DstFileBuildRule not in self.PendingBuildTargetList:\r
1121                             self.PendingBuildTargetList.append(DstFileBuildRule)\r
1122                         break\r
1123                     elif DstFileBuildRule == None or DstFileBuildRule.CommandList == []:\r
1124                         self.ResultFileList.append(DstFile)\r
1125                         break\r
1126 \r
1127                     SrcFile, ExtraSrcFileList, DstFile, CommandList = DstFileBuildRule.Apply(DstFile, None, Separator)\r
1128                     BuildTargetString = "%s : %s %s\n"\\r
1129                                         "\t%s\n" % (DstFile, SrcFile, " ".join(ExtraSrcFileList), "\n\t".join(CommandList))\r
1130                     self.FileBuildTargetList.append((SrcFile, BuildTargetString))\r
1131                     SrcFileBuildRule = DstFileBuildRule\r
1132 \r
1133         #\r
1134         # Search dependency file list for each source file\r
1135         #\r
1136         self.FileDependency = self.GetFileDependency(SourceFileList, ForceIncludedFile, self.ModuleInfo.IncludePathList)\r
1137         DepSet = None\r
1138         for File in self.FileDependency:\r
1139             # skip AutoGen.c\r
1140             if File.endswith("AutoGen.c") or not File.endswith(".c"):\r
1141                 continue\r
1142             elif DepSet == None:\r
1143                 DepSet = set(self.FileDependency[File])\r
1144             else:\r
1145                 DepSet &= set(self.FileDependency[File])\r
1146         # in case nothing in SourceFileList\r
1147         if DepSet == None:\r
1148             DepSet = set()\r
1149         #\r
1150         # Extract comman files list in the dependency files\r
1151         #\r
1152         self.CommonFileDependency = list(DepSet)\r
1153         for F in self.FileDependency:\r
1154             NewDepSet = set(self.FileDependency[F])\r
1155             NewDepSet -= DepSet\r
1156             if F.endswith("AutoGen.c") or not F.endswith(".c"):\r
1157                 self.FileDependency[F] = [Separator.join(["$(WORKSPACE)", dep]) for dep in self.FileDependency[F]]\r
1158             else:\r
1159                 self.FileDependency[F] = ["$(COMMON_DEPS)"] + [Separator.join(["$(WORKSPACE)", dep]) for dep in NewDepSet]\r
1160 \r
1161         for File, TargetTemplate in self.FileBuildTargetList:\r
1162             if File not in self.FileDependency:\r
1163                 self.BuildTargetList.append(TargetTemplate)\r
1164                 continue\r
1165             Template = TemplateString()\r
1166             Template.Append(TargetTemplate, {"deps" : self.FileDependency[File]})\r
1167             self.BuildTargetList.append(str(Template))\r
1168 \r
1169     ## For creating makefile targets for dependent libraries\r
1170     #\r
1171     #   @param      MakeType    GNU makefile or MS makefile\r
1172     #\r
1173     def ProcessDependentLibrary(self, MakeType=gMakeType):\r
1174         for LibraryModule in self.ModuleInfo.DependentLibraryList:\r
1175             LibraryFile = str(LibraryModule)\r
1176             FileBase = path.basename(LibraryFile).split(".")[0]\r
1177             LibraryBuildPath = path.dirname(LibraryFile) + gDirectorySeparator[MakeType] + FileBase\r
1178             self.LibraryBuildDirectoryList.append(LibraryBuildPath)\r
1179             self.LibraryFileList.append(gDirectorySeparator[MakeType].join([LibraryBuildPath, "OUTPUT", LibraryModule.BaseName + ".lib"]))\r
1180 \r
1181     ## Determine the root directory for a platform build\r
1182     def GetPlatformBuildDirectory(self):\r
1183         if os.path.isabs(self.PlatformInfo.OutputDir):\r
1184             return self.PlatformInfo.OutputDir\r
1185         else:\r
1186             return os.path.join("$(WORKSPACE)", self.PlatformInfo.OutputDir)\r
1187 \r
1188     ## Return a list containing source file's dependencies\r
1189     #\r
1190     #   @param      FileList        The list of source files\r
1191     #   @param      ForceInculeList The list of files which will be included forcely\r
1192     #   @param      SearchPathList  The list of search path\r
1193     #\r
1194     #   @retval     dict            The mapping between source file path and its dependencies\r
1195     #\r
1196     def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):\r
1197         WorkingDir = os.getcwd()\r
1198         os.chdir(self.ModuleInfo.WorkspaceDir)\r
1199         Dependency = {}\r
1200         for F in FileList:\r
1201             Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)\r
1202         os.chdir(WorkingDir)\r
1203         return Dependency\r
1204 \r
1205     ## Find dependencies for one source file\r
1206     #\r
1207     #  By searching recursively "#include" directive in file, find out all the\r
1208     #  files needed by given source file. The dependecies will be only searched\r
1209     #  in given search path list.\r
1210     #\r
1211     #   @param      File            The source file\r
1212     #   @param      ForceInculeList The list of files which will be included forcely\r
1213     #   @param      SearchPathList  The list of search path\r
1214     #\r
1215     #   @retval     list            The list of files the given source file depends on\r
1216     #\r
1217     def GetDependencyList(self, File, ForceList, SearchPathList):\r
1218         WorkingDir = os.getcwd()\r
1219         os.chdir(self.ModuleInfo.WorkspaceDir)\r
1220 \r
1221         EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File)\r
1222         EdkLogger.debug(EdkLogger.DEBUG_0, "Including %s" % " ".join(ForceList))\r
1223         FileStack = [File] + ForceList\r
1224         DependencySet = set()\r
1225         MacroUsedByIncludedFile = False\r
1226 \r
1227         if self.ModuleInfo.Arch not in gDependencyDatabase:\r
1228             gDependencyDatabase[self.ModuleInfo.Arch] = {}\r
1229         DepDb = gDependencyDatabase[self.ModuleInfo.Arch]\r
1230         while len(FileStack) > 0:\r
1231             EdkLogger.debug(EdkLogger.DEBUG_0, "Stack %s" % "\n\t".join(FileStack))\r
1232             F = FileStack.pop()\r
1233 \r
1234             CurrentFileDependencyList = []\r
1235             if F in DepDb and not IsChanged(F):\r
1236                 CurrentFileDependencyList = DepDb[F]\r
1237                 for Dep in CurrentFileDependencyList:\r
1238                     if Dep not in FileStack and Dep not in DependencySet:\r
1239                         FileStack.append(Dep)\r
1240             else:\r
1241                 try:\r
1242                     Fd = open(F, 'r')\r
1243                 except:\r
1244                     EdkLogger.error("AutoGen", FILE_OPEN_FAILURE, ExtraData=F)\r
1245 \r
1246                 FileContent = Fd.read()\r
1247                 Fd.close()\r
1248                 if len(FileContent) == 0:\r
1249                     continue\r
1250 \r
1251                 if FileContent[0] == 0xff or FileContent[0] == 0xfe:\r
1252                     FileContent = unicode(FileContent, "utf-16")\r
1253                 IncludedFileList = gIncludePattern.findall(FileContent)\r
1254 \r
1255                 CurrentFilePath = os.path.dirname(F)\r
1256                 for Inc in IncludedFileList:\r
1257                     # if there's macro used to reference header file, expand it\r
1258                     HeaderList = gMacroPattern.findall(Inc)\r
1259                     if len(HeaderList) == 1 and len(HeaderList[0]) == 2:\r
1260                         HeaderType = HeaderList[0][0]\r
1261                         HeaderKey = HeaderList[0][1]\r
1262                         if HeaderType in gIncludeMacroConversion:\r
1263                             Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey}\r
1264                         else:\r
1265                             # not known macro used in #include\r
1266                             MacroUsedByIncludedFile = True\r
1267                             continue\r
1268                     Inc = os.path.normpath(Inc)\r
1269                     for SearchPath in [CurrentFilePath] + SearchPathList:\r
1270                         FilePath = os.path.join(SearchPath, Inc)\r
1271                         if not os.path.exists(FilePath) or FilePath in CurrentFileDependencyList:\r
1272                             continue\r
1273                         CurrentFileDependencyList.append(FilePath)\r
1274                         if FilePath not in FileStack and FilePath not in DependencySet:\r
1275                             FileStack.append(FilePath)\r
1276                         break\r
1277                     else:\r
1278                         EdkLogger.verbose("%s included by %s was not found in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList)))\r
1279 \r
1280                 if not MacroUsedByIncludedFile:\r
1281                     if F == File:\r
1282                         CurrentFileDependencyList += ForceList\r
1283                     #\r
1284                     # Don't keep the file in cache if it uses macro in included file.\r
1285                     # So it will be scanned again if another file includes this file.\r
1286                     #\r
1287                     DepDb[F] = CurrentFileDependencyList\r
1288             DependencySet.update(CurrentFileDependencyList)\r
1289 \r
1290         #\r
1291         # If there's macro used in included file, always build the file by\r
1292         # returning a empty dependency\r
1293         #\r
1294         if MacroUsedByIncludedFile:\r
1295             DependencyList = [""]\r
1296         else:\r
1297             DependencyList = list(DependencySet)  # remove duplicate ones\r
1298             DependencyList.append(File)\r
1299 \r
1300         os.chdir(WorkingDir)\r
1301         return DependencyList\r
1302 \r
1303     ## Get the root directory list for intermediate files of all modules build\r
1304     #\r
1305     #   @retval     list    The list of directory\r
1306     #\r
1307     def GetModuleBuildDirectoryList(self):\r
1308         DirList = []\r
1309         for Arch in self.PlatformInfo:\r
1310             for ModuleAutoGen in self.PlatformInfo[Arch].ModuleAutoGenList:\r
1311                 DirList.append(ModuleAutoGen.BuildInfo.BuildDir)\r
1312         return DirList\r
1313 \r
1314     ## Get the root directory list for intermediate files of all libraries build\r
1315     #\r
1316     #   @retval     list    The list of directory\r
1317     #\r
1318     def GetLibraryBuildDirectoryList(self):\r
1319         DirList = []\r
1320         for Arch in self.PlatformInfo:\r
1321             for LibraryAutoGen in self.PlatformInfo[Arch].LibraryAutoGenList:\r
1322                 DirList.append(LibraryAutoGen.BuildInfo.BuildDir)\r
1323         return DirList\r
1324 \r
1325     ## Return a list of directory creation command string\r
1326     #\r
1327     #   @param      DirList     The list of directory to be created\r
1328     #   @param      MakeType    GNU makefile or MS makefile\r
1329     #\r
1330     #   @retval     list        The directory creation command list\r
1331     #\r
1332     def GetCreateDirectoryCommand(self, DirList, MakeType=gMakeType):\r
1333         return [gCreateDirectoryCommandTemplate[MakeType] % {'dir':Dir} for Dir in DirList]\r
1334 \r
1335     ## Return a list of directory removal command string\r
1336     #\r
1337     #   @param      DirList     The list of directory to be removed\r
1338     #   @param      MakeType    GNU makefile or MS makefile\r
1339     #\r
1340     #   @retval     list        The directory removal command list\r
1341     #\r
1342     def GetRemoveDirectoryCommand(self, DirList, MakeType=gMakeType):\r
1343         return [gRemoveDirectoryCommandTemplate[MakeType] % {'dir':Dir} for Dir in DirList]\r
1344 \r
1345 # This acts like the main() function for the script, unless it is 'import'ed into another script.\r
1346 if __name__ == '__main__':\r
1347     pass\r