Removed "-u" option of 'CP' command because Mac doesn't support it
[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 -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}\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}\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}${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        $(LIB_LIST)\r
340 \r
341 COMMON_DEPS = ${BEGIN}${common_dependency_file} \\\r
342               ${END}\r
343 \r
344 IMAGE_ENTRY_POINT = ${module_entry_point}\r
345 ENTRYPOINT = ${module_entry_point}\r
346 \r
347 #\r
348 # Overridable Target Macro Definitions\r
349 #\r
350 INIT_TARGET = init\r
351 PCH_TARGET =\r
352 CODA_TARGET = ${BEGIN}${remaining_build_target} \\\r
353               ${END}\r
354 \r
355 #\r
356 # Default target, which will build dependent libraries in addition to source files\r
357 #\r
358 \r
359 all: ${build_type}\r
360 \r
361 \r
362 #\r
363 # Target used when called from platform makefile, which will bypass the build of dependent libraries\r
364 #\r
365 \r
366 pbuild: $(INIT_TARGET) $(PCH_TARGET) $(CODA_TARGET)\r
367 \r
368 #\r
369 # ModuleTarget\r
370 #\r
371 \r
372 mbuild: $(INIT_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET)\r
373 \r
374 \r
375 #\r
376 # Target to update the FD\r
377 #\r
378 \r
379 fds: mbuild gen_fds\r
380 \r
381 #\r
382 # Initialization target: print build information and create necessary directories\r
383 #\r
384 init:\r
385 \t-@echo Building ... $(MODULE_NAME) $(MODULE_VERSION) [$(ARCH)] in platform $(PLATFORM_NAME) $(PLATFORM_VERSION)\r
386 ${BEGIN}\t-@${create_directory_command}\n${END}\\r
387 ${BEGIN}\t-@${copy_autogen_h}\n${END}\r
388 \r
389 #\r
390 # GenLibsTarget\r
391 #\r
392 gen_libs:\r
393 \t${BEGIN}cd $(BUILD_DIR)${separator}$(ARCH)${separator}${dependent_library_build_directory} && "$(MAKE)" $(MAKE_FLAGS)\r
394 \t${END}cd $(MODULE_BUILD_DIR)\r
395 \r
396 #\r
397 # Build Flash Device Image\r
398 #\r
399 gen_fds:\r
400 \tcd $(BUILD_DIR) && "$(MAKE)" $(MAKE_FLAGS) fds\r
401 \tcd $(MODULE_BUILD_DIR)\r
402 \r
403 #\r
404 # Individual Object Build Targets\r
405 #\r
406 ${BEGIN}${file_build_target}\r
407 ${END}\r
408 \r
409 \r
410 #\r
411 # clean all intermediate files\r
412 #\r
413 \r
414 clean:\r
415 \t${BEGIN}${clean_command}\r
416 \t${END}\r
417 \r
418 #\r
419 # clean all generated files\r
420 #\r
421 \r
422 cleanall:\r
423 ${BEGIN}\t${cleanall_command}\r
424 ${END}\t$(RM) *.pdb *.idb > NUL 2>&1\r
425 \t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi\r
426 \r
427 #\r
428 # clean pre-compiled header files\r
429 #\r
430 \r
431 cleanpch:\r
432 \t$(RM) $(OUTPUT_DIR)\*.pch > NUL 2>&1\r
433 \r
434 #\r
435 # clean all dependent libraries built\r
436 #\r
437 \r
438 cleanlib:\r
439 \t${BEGIN}cd $(BUILD_DIR)${separator}$(ARCH)${separator}${dependent_library_build_directory} && "$(MAKE)" $(MAKE_FLAGS) cleanall\r
440 \t${END}cd $(MODULE_BUILD_DIR)\r
441 \r
442 '''\r
443 \r
444 gPlatformMakefileTemplate = '''\\r
445 ${makefile_header}\r
446 \r
447 #\r
448 # Platform Macro Definition\r
449 #\r
450 PLATFORM_NAME = ${platform_name}\r
451 PLATFORM_GUID = ${platform_guid}\r
452 PLATFORM_VERSION = ${platform_version}\r
453 PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory}\r
454 PLATFORM_OUTPUT_DIR = ${platform_output_directory}\r
455 \r
456 #\r
457 # Build Configuration Macro Definition\r
458 #\r
459 TOOLCHAIN_TAG = ${toolchain_tag}\r
460 TARGET = ${build_target}\r
461 \r
462 #\r
463 # Build Directory Macro Definition\r
464 #\r
465 BUILD_DIR = ${platform_build_directory}\r
466 FV_DIR = ${platform_build_directory}${separator}FV\r
467 \r
468 #\r
469 # Shell Command Macro\r
470 #\r
471 ${BEGIN}${shell_command_code} = ${shell_command}\r
472 ${END}\r
473 \r
474 MAKE = ${make_path}\r
475 MAKE_FLAGS = ${make_flag}\r
476 MAKE_FILE = ${makefile_path}\r
477 \r
478 #\r
479 # Default target\r
480 #\r
481 all: init build_libraries build_modules build_fds\r
482 \r
483 #\r
484 # Initialization target: print build information and create necessary directories\r
485 #\r
486 init:\r
487 \t-@echo Building ... $(PLATFORM_NAME) $(PLATFORM_VERSION) [${build_architecture_list}]\r
488 \t${BEGIN}-@${create_directory_command}\r
489 \t${END}\r
490 #\r
491 # library build target\r
492 #\r
493 libraries: init build_libraries\r
494 \r
495 #\r
496 # module build target\r
497 #\r
498 modules: init build_libraries build_modules\r
499 \r
500 #\r
501 # Flash Device Image Target\r
502 #\r
503 fds: init build_fds\r
504 \r
505 #\r
506 # Build all libraries:\r
507 #\r
508 build_libraries:\r
509 ${BEGIN}\tcd ${library_build_directory} && "$(MAKE)" $(MAKE_FLAGS) pbuild\r
510 ${END}\tcd $(BUILD_DIR)\r
511 \r
512 #\r
513 # Build all modules:\r
514 #\r
515 build_modules:\r
516 ${BEGIN}\tcd ${module_build_directory} && "$(MAKE)" $(MAKE_FLAGS) pbuild\r
517 ${END}\tcd $(BUILD_DIR)\r
518 \r
519 #\r
520 # Build Flash Device Image\r
521 #\r
522 build_fds:\r
523 \t-@cd $(FV_DIR)\r
524 ${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
525 \r
526 #\r
527 # run command for emulator platform only\r
528 #\r
529 run:\r
530 \tcd $(BUILD_DIR)${separator}IA32\r
531 \tSecMain\r
532 \tcd $(BUILD_DIR)\r
533 \r
534 #\r
535 # Clean intermediate files\r
536 #\r
537 clean:\r
538 \t${BEGIN}cd ${library_build_directory} && "$(MAKE)" $(MAKE_FLAGS) clean\r
539 \t${END}${BEGIN}cd ${module_build_directory} && "$(MAKE)" $(MAKE_FLAGS) clean\r
540 \t${END}cd $(BUILD_DIR)\r
541 \r
542 #\r
543 # Clean all generated files except to makefile\r
544 #\r
545 cleanall:\r
546 ${BEGIN}\t${cleanall_command}\r
547 ${END}\r
548 \r
549 #\r
550 # Clean all library files\r
551 #\r
552 cleanlib:\r
553 \t${BEGIN}cd ${library_build_directory} && "$(MAKE)" $(MAKE_FLAGS) cleanall\r
554 \t${END}cd $(BUILD_DIR)\r
555 \r
556 '''\r
557 \r
558 ## Makefile class\r
559 #\r
560 #  This class encapsules makefie and its generation. It uses template to generate\r
561 #  the content of makefile. The content of makefile will be got from PlatformBuildInfo\r
562 #  or ModuleBuildInfo objects.\r
563 #\r
564 class Makefile(object):\r
565     ## Constructor\r
566     #\r
567     #  Intitialize the data member simply\r
568     #\r
569     #   @param      Info    PlatformBuildInfo or ModuleBuildInfo object\r
570     #   @param      Option  Option for the makefile generation (not used)\r
571     #\r
572     def __init__(self, Info, Option=None):\r
573         if isinstance(Info, ModuleBuildInfo):\r
574             if Info == None or Info == "":\r
575                 EdkLogger.error("AutoGen", AUTOGEN_ERROR, "No valid module found! Please check your build configuration!\n")\r
576             self.ModuleInfo = Info\r
577             self.PlatformInfo = Info.PlatformInfo\r
578             self.ModuleBuild = True\r
579 \r
580             self.BuildType = "mbuild"\r
581             self.TargetFileList = []\r
582             self.ObjectFileList = []\r
583 \r
584             self.ResultFileList = []\r
585             self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]\r
586         \r
587             self.SourceFileDatabase = {}  # {file type : file path}\r
588             self.DestFileDatabase = {}  # {file type : file path}\r
589             self.FileBuildTargetList = [] # [(src, target string)]\r
590             self.BuildTargetList = [] # [target string]\r
591             self.PendingBuildTargetList = [] # [FileBuildRule objects]\r
592             self.CommonFileDependency = []\r
593 \r
594             self.FileDependency = []\r
595             self.LibraryBuildCommandList = []\r
596             self.LibraryFileList = []\r
597             self.LibraryMakefileList = []\r
598             self.LibraryBuildDirectoryList = []\r
599             self.SystemLibraryList = []\r
600         elif type(Info) == type({}):    # and isinstance(info, PlatformBuildInfo):\r
601             if len(Info) <= 0:\r
602                 EdkLogger.error("AutoGen", AUTOGEN_ERROR, "No buildable platform found! Please check your build configuration!\n")\r
603             self.PlatformInfo = Info\r
604             self.ModuleBuild = False\r
605             self.ModuleBuildCommandList = []\r
606             self.ModuleMakefileList = []\r
607             self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()\r
608             self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()\r
609         else:\r
610             EdkLogger.error("AutoGen", AUTOGEN_ERROR, "Non-buildable item:%s" % str(Info))\r
611 \r
612         self.IntermediateDirectoryList = []\r
613 \r
614     ## Create necessary directory for makefile generation\r
615     def PrepareDirectory(self):\r
616         if self.ModuleBuild:\r
617             CreateDirectory(self.PlatformInfo.BuildDir)\r
618             CreateDirectory(self.ModuleInfo.BuildDir)\r
619             CreateDirectory(self.ModuleInfo.DebugDir)\r
620 \r
621     ## Create the makefile\r
622     #\r
623     #   @param      File        The path of the makefile\r
624     #   @param      MakeType    GNU makefile or MS makefile\r
625     #\r
626     #   @retval     True        If the file is changed or doesn't exist\r
627     #   @retval     False       If the file exists and its content is not changed\r
628     #                           since last time\r
629     #\r
630     def Generate(self, File=None, MakeType=gMakeType):\r
631         if self.ModuleBuild:\r
632             return self.GenerateModuleMakefile(File, MakeType)\r
633         else:\r
634             return self.GeneratePlatformMakefile(File, MakeType)\r
635 \r
636     ## Create makefile of platform\r
637     #\r
638     #   @param      File        The path of the makefile\r
639     #   @param      MakeType    GNU makefile or MS makefile\r
640     #\r
641     #   @retval     True        If the file is changed or doesn't exist\r
642     #   @retval     False       If the file exists and its content is not changed\r
643     #                           since last time\r
644     #\r
645     def GeneratePlatformMakefile(self, File=None, MakeType=gMakeType):\r
646         Separator = gDirectorySeparator[MakeType]\r
647 \r
648         ArchList = self.PlatformInfo.keys()\r
649         PlatformInfo = self.PlatformInfo.values()[0]\r
650         ActivePlatform = PlatformInfo.Platform\r
651 \r
652         if "MAKE" not in PlatformInfo.ToolPath:\r
653             EdkLogger.error("GenMake", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!")\r
654 \r
655         self.IntermediateDirectoryList = ["$(BUILD_DIR)%s%s" % (Separator, Arch) for Arch in self.PlatformInfo]\r
656         self.IntermediateDirectoryList.append("$(FV_DIR)")\r
657 \r
658         # TRICK: for not generating GenFds call in makefile if no FDF file\r
659         MacroList = []\r
660         if PlatformInfo.FdfFile != None and PlatformInfo.FdfFile != "":\r
661             FdfFileList = [PlatformInfo.FdfFile]\r
662             for MacroName in GlobalData.gGlobalDefines:\r
663                 MacroList.append('"%s=%s"' % (MacroName, GlobalData.gGlobalDefines[MacroName]))    \r
664         else:\r
665             FdfFileList = []\r
666 \r
667         # pass log level to external program called in makefile, currently GenFds.exe\r
668         LogLevel = EdkLogger.GetLevel()\r
669         if LogLevel == EdkLogger.VERBOSE:\r
670             LogOption = "-v"\r
671         elif LogLevel <= EdkLogger.DEBUG_9:\r
672             LogOption = "-d %d" % (LogLevel - 1)\r
673         elif LogLevel == EdkLogger.QUIET:\r
674             LogOption = "-q"\r
675         else:\r
676             LogOption = ""\r
677 \r
678         MakefileName = gMakefileName[MakeType]\r
679         MakefileTemplateDict = {\r
680             "makefile_header"           : gMakefileHeader % MakefileName,\r
681             "makefile_path"             : os.path.join("$(BUILD_DIR)", MakefileName),\r
682             "platform_name"             : PlatformInfo.Name,\r
683             "platform_guid"             : PlatformInfo.Guid,\r
684             "platform_version"          : PlatformInfo.Version,\r
685             "platform_relative_directory": PlatformInfo.SourceDir,\r
686             "platform_output_directory" : PlatformInfo.OutputDir,\r
687             "platform_build_directory"  : PlatformInfo.BuildDir,\r
688 \r
689             "toolchain_tag"             : PlatformInfo.ToolChain,\r
690             "build_target"              : PlatformInfo.BuildTarget,\r
691             "make_path"                 : PlatformInfo.ToolPath["MAKE"],\r
692             "make_flag"                 : PlatformInfo.ToolOption["MAKE"],\r
693             "shell_command_code"        : gShellCommand[MakeType].keys(),\r
694             "shell_command"             : gShellCommand[MakeType].values(),\r
695             "build_architecture_list"   : ",".join(ArchList),\r
696             "architecture"              : self.PlatformInfo.keys(),\r
697             "separator"                 : Separator,\r
698             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList, MakeType),\r
699             "remove_directory_command"  : gRemoveDirectoryCommand[MakeType],\r
700             "remove_file_command"       : gRemoveFileCommand[MakeType],\r
701             "cleanall_command"          : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList, MakeType),\r
702             "library_build_directory"   : self.LibraryBuildDirectoryList,\r
703             "module_build_directory"    : self.ModuleBuildDirectoryList,\r
704             "fdf_file"                  : FdfFileList,\r
705             "active_platform"           : PlatformInfo.WorkspaceDir + Separator + ActivePlatform.DescFilePath,\r
706             "fd"                        : PlatformInfo.FdTargetList,\r
707             "fv"                        : PlatformInfo.FvTargetList,\r
708             "log_level"                 : LogOption,\r
709             "macro"                     : MacroList,\r
710         }\r
711 \r
712         self.PrepareDirectory()\r
713 \r
714         AutoGenMakefile = TemplateString()\r
715         AutoGenMakefile.Append(gPlatformMakefileTemplate, MakefileTemplateDict)\r
716 \r
717         FilePath = ""\r
718         if File == None:\r
719             os.chdir(PlatformInfo.MakeFileDir)\r
720             FilePath = MakefileName\r
721         else:\r
722             FilePath = File\r
723 \r
724         Result = SaveFileOnChange(FilePath, str(AutoGenMakefile))\r
725         os.chdir(PlatformInfo.WorkspaceDir)\r
726         return Result\r
727 \r
728     ## Create makefile of a module\r
729     #\r
730     #   @param      File        The path of the makefile\r
731     #   @param      MakeType    GNU makefile or MS makefile\r
732     #\r
733     #   @retval     True        If the file is changed or doesn't exist\r
734     #   @retval     False       If the file exists and its content is not changed\r
735     #                           since last time\r
736     #\r
737     def GenerateModuleMakefile(self, File=None, MakeType=gMakeType):\r
738         if MakeType in self.ModuleInfo.CustomMakefile and self.ModuleInfo.CustomMakefile[MakeType] != "":\r
739             return self.GenerateCustomBuildMakefile(File, MakeType)\r
740 \r
741         Separator = gDirectorySeparator[MakeType]\r
742         PlatformInfo = self.PlatformInfo\r
743 \r
744         # break build if no source files and binary files are found\r
745         if len(self.ModuleInfo.SourceFileList) == 0 and len(self.ModuleInfo.BinaryFileDict) == 0:\r
746             EdkLogger.error("AutoGen", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]"\r
747                             % (self.ModuleInfo.BuildTarget, self.ModuleInfo.ToolChain, self.ModuleInfo.Arch),\r
748                             ExtraData=str(self.ModuleInfo.Module))\r
749         # convert source files and binary files to build target\r
750         if len(self.ModuleInfo.SourceFileList) > 0:\r
751             self.ProcessSourceFileList(MakeType)\r
752         if len(self.ModuleInfo.BinaryFileDict) > 0:\r
753             self.ProcessBinaryFileList(MakeType)\r
754         # convert dependent libaries to build command\r
755         self.ProcessDependentLibrary(MakeType)\r
756 \r
757         if "DLINK" in PlatformInfo.ToolStaticLib:\r
758             EdkLogger.debug(EdkLogger.DEBUG_5, "Static library: " + PlatformInfo.ToolStaticLib["DLINK"])\r
759             self.SystemLibraryList.append(PlatformInfo.ToolStaticLib["DLINK"])\r
760 \r
761         if self.ModuleInfo.Arch == "EBC":\r
762             # EBC compiler always use "EfiStart" as entry point\r
763             EntryPoint = "EfiStart"\r
764         elif self.ModuleInfo.AutoGenVersion < 0x00010005 and len(self.ModuleInfo.Module.ModuleEntryPointList) > 0:\r
765             # R8 modules use different entry point functions\r
766             EntryPoint = self.ModuleInfo.Module.ModuleEntryPointList[0]\r
767         else:\r
768             # R9 modules always use "_ModuleEntryPoint" as entry point\r
769             EntryPoint = "_ModuleEntryPoint"\r
770 \r
771         DefaultToolFlag = PlatformInfo.ToolOption.values()\r
772         if self.ModuleInfo.ModuleType == "USER_DEFINED":\r
773             DefaultToolFlag = ["" for p in DefaultToolFlag]\r
774 \r
775         if "CC" not in PlatformInfo.ToolChainFamily:\r
776             EdkLogger.error("AutoGen", AUTOGEN_ERROR, "Tool [CC] is not supported [%s, %s, %s]" % (self.ModuleInfo.BuildTarget,\r
777                                     self.ModuleInfo.ToolChain, self.ModuleInfo.Arch))\r
778         if  "DLINK" not in PlatformInfo.ToolChainFamily:\r
779             EdkLogger.error("AutoGen", AUTOGEN_ERROR, "Tool [DLINK] is not supported [%s, %s, %s]" % (self.ModuleInfo.BuildTarget,\r
780                                     self.ModuleInfo.ToolChain, self.ModuleInfo.Arch))\r
781 \r
782         if self.ModuleInfo.IsLibrary:\r
783             if "Static-Library-File" in self.DestFileDatabase:\r
784                 self.ResultFileList = self.DestFileDatabase["Static-Library-File"]\r
785         elif self.ModuleInfo.ModuleType == "USER_DEFINED":\r
786             if "Dynamic-Library-File" in self.DestFileDatabase:\r
787                 self.ResultFileList = self.DestFileDatabase["Dynamic-Library-File"]\r
788         if len(self.ResultFileList) == 0:\r
789             EdkLogger.error("AutoGen", AUTOGEN_ERROR, "Don't know how to end the module build")\r
790 \r
791         SourceFileMacroNameList = []\r
792         SourceFileMacroList = [] # macro name = file list\r
793         for FileType in self.SourceFileDatabase:\r
794             Macro = "%s_LIST" % FileType.replace("-", "_").upper()\r
795             SourceFileMacroNameList.append("$(%s)" % Macro)\r
796             Template = TemplateString()\r
797             Template.Append("%s = ${BEGIN}${source_file} \\\n\t${END}" % Macro,\r
798                             {"source_file" : self.SourceFileDatabase[FileType]})\r
799             SourceFileMacroList.append(str(Template))\r
800         TargetFileMacroList = []\r
801         TargetFileMacroNameList = []\r
802         for FileType in self.DestFileDatabase:\r
803             Macro = "%s_LIST" % FileType.replace("-", "_").upper()\r
804             TargetFileMacroNameList.append("$(%s)" % Macro)\r
805             Template = TemplateString()\r
806             Template.Append("%s = ${BEGIN}${target_file} \\\n\t${END}" % Macro,\r
807                             {"target_file" : self.DestFileDatabase[FileType]})\r
808             TargetFileMacroList.append(str(Template))\r
809 \r
810         # R8 modules need <BaseName>StrDefs.h for string ID\r
811         if self.ModuleInfo.AutoGenVersion < 0x00010005 and len(self.ModuleInfo.UnicodeFileList) > 0:\r
812             AutoGenHeaderFile = os.path.join("$(DEBUG_DIR)", "AutoGen.h")\r
813             StringHeaderFile = os.path.join("$(DEBUG_DIR)", "%sStrDefs.h" % self.ModuleInfo.BaseName)\r
814             CopyAutoGenHeaderFile = ["$(CP) %s %s" % (AutoGenHeaderFile, StringHeaderFile)]\r
815         else:\r
816             CopyAutoGenHeaderFile = []\r
817 \r
818         MakefileName = gMakefileName[MakeType]\r
819         MakefileTemplateDict = {\r
820             "makefile_header"           : gMakefileHeader % MakefileName,\r
821             "makefile_path"             : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),\r
822             "platform_name"             : PlatformInfo.Name,\r
823             "platform_guid"             : PlatformInfo.Guid,\r
824             "platform_version"          : PlatformInfo.Version,\r
825             "platform_relative_directory": PlatformInfo.SourceDir,\r
826             "platform_output_directory" : PlatformInfo.OutputDir,\r
827 \r
828             "module_name"               : self.ModuleInfo.Name,\r
829             "module_guid"               : self.ModuleInfo.Guid,\r
830             "module_version"            : self.ModuleInfo.Version,\r
831             "module_type"               : self.ModuleInfo.ModuleType,\r
832             "module_file_base_name"     : self.ModuleInfo.FileBase,\r
833             "module_relative_directory" : self.ModuleInfo.SourceDir,\r
834 \r
835             "architecture"              : self.ModuleInfo.Arch,\r
836             "toolchain_tag"             : self.ModuleInfo.ToolChain,\r
837             "build_target"              : self.ModuleInfo.BuildTarget,\r
838 \r
839             "platform_build_directory"  : PlatformInfo.BuildDir,\r
840 \r
841             "separator"                 : Separator,\r
842             "default_tool_flags"        : DefaultToolFlag,\r
843             "platform_tool_flags"       : [PlatformInfo.BuildOption[tool] for tool in PlatformInfo.ToolPath],\r
844             "module_tool_flags"         : [self.ModuleInfo.BuildOption[tool] for tool in PlatformInfo.ToolPath],\r
845 \r
846             "tool_code"                 : PlatformInfo.ToolPath.keys(),\r
847             "tool_path"                 : PlatformInfo.ToolPath.values(),\r
848 \r
849             "shell_command_code"        : gShellCommand[MakeType].keys(),\r
850             "shell_command"             : gShellCommand[MakeType].values(),\r
851 \r
852             "module_entry_point"        : EntryPoint,\r
853             "include_path_prefix"       : gIncludeFlag[PlatformInfo.ToolChainFamily["CC"]],\r
854             "dlink_output_flag"         : PlatformInfo.OutputFlag["DLINK"],\r
855             "slink_output_flag"         : PlatformInfo.OutputFlag["SLINK"],\r
856             "start_group_flag"          : gStartGroupFlag[PlatformInfo.ToolChainFamily["DLINK"]],\r
857             "end_group_flag"            : gEndGroupFlag[PlatformInfo.ToolChainFamily["DLINK"]],\r
858             "include_path"              : self.ModuleInfo.IncludePathList,\r
859             #"target_file"               : self.TargetFileList,\r
860             #"object_file"               : self.ObjectFileList,\r
861             "library_file"              : self.LibraryFileList,\r
862             "remaining_build_target"    : self.ResultFileList,\r
863             "system_library"            : self.SystemLibraryList,\r
864             "common_dependency_file"    : self.CommonFileDependency,\r
865             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList, MakeType),\r
866             "remove_directory_command"  : gRemoveDirectoryCommand[MakeType],\r
867             "remove_file_command"       : gRemoveFileCommand[MakeType],\r
868             "copy_file_command"         : gCopyFileCommand[MakeType],\r
869             "clean_command"             : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"], MakeType),\r
870             "cleanall_command"          : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"], MakeType),\r
871             "dependent_library_build_directory" : self.LibraryBuildDirectoryList,\r
872             "build_type"                        : self.BuildType,\r
873             "source_file_macro"         : SourceFileMacroList,\r
874             "target_file_macro"         : TargetFileMacroList,\r
875             "source_file_macro_name"    : SourceFileMacroNameList,\r
876             "target_file_macro_name"    : TargetFileMacroNameList,\r
877             "file_build_target"         : self.BuildTargetList,\r
878             "copy_autogen_h"            : CopyAutoGenHeaderFile,\r
879         }\r
880 \r
881         self.PrepareDirectory()\r
882 \r
883         AutoGenMakefile = TemplateString()\r
884         AutoGenMakefile.Append(gModuleMakefileTemplate, MakefileTemplateDict)\r
885 \r
886         FilePath = ""\r
887         if File == None:\r
888             os.chdir(self.ModuleInfo.PlatformInfo.BuildDir)\r
889             os.chdir(self.ModuleInfo.MakeFileDir)\r
890             FilePath = MakefileName\r
891         else:\r
892             FilePath = File\r
893 \r
894         Result = SaveFileOnChange(FilePath, str(AutoGenMakefile))\r
895         os.chdir(self.ModuleInfo.WorkspaceDir)\r
896         return Result\r
897 \r
898     ## Create customized makefile for a module\r
899     #\r
900     #   @param      File        The path of the makefile\r
901     #   @param      MakeType    GNU makefile or MS makefile\r
902     #\r
903     #   @retval     True        If the file is changed or doesn't exist\r
904     #   @retval     False       If the file exists and its content is not changed\r
905     #                           since last time\r
906     #\r
907     def GenerateCustomBuildMakefile(self, File=None, MakeType=gMakeType):\r
908         Separator = gDirectorySeparator[MakeType]\r
909         CustomMakefile = open(os.path.join(self.ModuleInfo.WorkspaceDir, self .ModuleInfo.CustomMakefile[MakeType]), 'r').read()\r
910 \r
911         MakefileName = gMakefileName[MakeType]\r
912         MakefileTemplateDict = {\r
913             "makefile_header"           : gMakefileHeader % MakefileName,\r
914             "platform_name"             : self.PlatformInfo.Name,\r
915             "platform_guid"             : self.PlatformInfo.Guid,\r
916             "platform_version"          : self.PlatformInfo.Version,\r
917             "platform_relative_directory": self.PlatformInfo.SourceDir,\r
918             "platform_output_directory" : self.PlatformInfo.OutputDir,\r
919 \r
920             "module_name"               : self.ModuleInfo.Name,\r
921             "module_guid"               : self.ModuleInfo.Guid,\r
922             "module_version"            : self.ModuleInfo.Version,\r
923             "module_type"               : self.ModuleInfo.ModuleType,\r
924             "module_file_base_name"     : self.ModuleInfo.FileBase,\r
925             "module_relative_directory" : self.ModuleInfo.SourceDir,\r
926 \r
927             "architecture"              : self.ModuleInfo.Arch,\r
928             "toolchain_tag"             : self.ModuleInfo.ToolChain,\r
929             "build_target"              : self.ModuleInfo.BuildTarget,\r
930 \r
931             "platform_build_directory"  : self.PlatformInfo.BuildDir,\r
932 \r
933             "separator"                 : Separator,\r
934             "default_tool_flags"        : self.PlatformInfo.ToolOption.values(),\r
935             "platform_tool_flags"       : self.PlatformInfo.BuildOption.values(),\r
936             "module_tool_flags"         : self.ModuleInfo.BuildOption.values(),\r
937 \r
938             "tool_code"                 : self.PlatformInfo.ToolPath.keys(),\r
939             "tool_path"                 : self.PlatformInfo.ToolPath.values(),\r
940 \r
941             "create_directory_command"  : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList, MakeType),\r
942             "directory_to_be_created"   : self.IntermediateDirectoryList,\r
943             "dependent_library_build_directory" : self.LibraryBuildDirectoryList,\r
944             "custom_makefile_content"   : CustomMakefile\r
945         }\r
946 \r
947         self.PrepareDirectory()\r
948 \r
949         AutoGenMakefile = TemplateString()\r
950         AutoGenMakefile.Append(gCustomMakefileTemplate, MakefileTemplateDict)\r
951 \r
952         FilePath = ""\r
953         if File == None:\r
954             FilePath = path.join(self.ModuleInfo.WorkspaceDir, self.ModuleInfo.MakeFileDir, MakefileName)\r
955         else:\r
956             FilePath = File\r
957 \r
958         return SaveFileOnChange(FilePath, str(AutoGenMakefile))\r
959 \r
960     ## Process source files to generate makefile targets and dependencies\r
961     #\r
962     #  The intermediate and final targets and dependencies are controlled by\r
963     #  build rules in $(WORKSPACE)/Conf/build_rule.txt. The dependencies of source\r
964     #  file are figured out by search included files in the source file.\r
965     #\r
966     #   @param      MakeType    GNU makefile or MS makefile\r
967     #\r
968     def ProcessSourceFileList(self, MakeType=gMakeType):\r
969         Separator = gDirectorySeparator[MakeType]\r
970 \r
971         ForceIncludedFile = []\r
972         SourceFileList = []\r
973 \r
974         if "CC" not in self.PlatformInfo.ToolChainFamily:\r
975             EdkLogger.error("AutoGen", AUTOGEN_ERROR, "No CC tool found",\r
976                             ExtraData=str(self.ModuleInfo.Module))\r
977         Family = self.PlatformInfo.ToolChainFamily["CC"]\r
978         BuildRule = self.PlatformInfo.BuildRule\r
979 \r
980         CCodeFlag = False\r
981         FileList = self.ModuleInfo.SourceFileList\r
982         SourceDir = os.path.join(self.ModuleInfo.WorkspaceDir, self.ModuleInfo.SourceDir)\r
983         for FileInfo in FileList:\r
984             F, SrcFileType, SrcFileBuildRule = FileInfo\r
985             if SrcFileType == "C-Code-File":\r
986                 CCodeFlag = True\r
987             SrcFileName = path.basename(F)\r
988             SrcFileBase, SrcFileExt = path.splitext(SrcFileName)\r
989             SrcFileDir = path.dirname(F)\r
990             if SrcFileDir == "":\r
991                 SrcFileDir = "."\r
992             else:\r
993                 P = "$(OUTPUT_DIR)" + Separator + SrcFileDir\r
994                 if P not in self.IntermediateDirectoryList:\r
995                     self.IntermediateDirectoryList.append(P)\r
996             SrcFileRelativePath = os.path.join(SourceDir, F)\r
997 \r
998             SrcFile, ExtraSrcFileList, DstFile, CommandList = SrcFileBuildRule.Apply(F, SourceDir, Separator)\r
999             if SrcFileType not in self.SourceFileDatabase:\r
1000                 self.SourceFileDatabase[SrcFileType] = []\r
1001             self.SourceFileDatabase[SrcFileType].append(SrcFile)\r
1002             SourceFileList.append(SrcFileRelativePath)\r
1003 \r
1004             BuildTargetTemplate = "${BEGIN}%s : ${deps}\n"\\r
1005                                   "${END}\t%s\n" % (DstFile, "\n\t".join(CommandList))\r
1006             self.FileBuildTargetList.append((SrcFileRelativePath, BuildTargetTemplate))\r
1007 \r
1008             while True:\r
1009                 # next target\r
1010                 DstFileType, DstFileBuildRule = BuildRule.Get(SrcFileBuildRule.DestFileExt, Family)\r
1011                 if DstFileType == None:\r
1012                     DstFileType = "Unknown-Type-File"\r
1013 \r
1014                 if DstFileType  in self.SourceFileDatabase:\r
1015                     self.SourceFileDatabase[DstFileType].append(DstFile)\r
1016                 else:\r
1017                     if DstFileType not in self.DestFileDatabase:\r
1018                         self.DestFileDatabase[DstFileType] = []\r
1019                     self.DestFileDatabase[DstFileType].append(DstFile)\r
1020 \r
1021                 if DstFileBuildRule != None and DstFileBuildRule.IsMultipleInput:\r
1022                     if DstFileBuildRule not in self.PendingBuildTargetList:\r
1023                         self.PendingBuildTargetList.append(DstFileBuildRule)\r
1024                     break\r
1025                 elif DstFileBuildRule == None or DstFileBuildRule.CommandList == []:\r
1026                     self.ResultFileList.append(DstFile)\r
1027                     break\r
1028 \r
1029                 SrcFile, ExtraSrcFileList, DstFile, CommandList = DstFileBuildRule.Apply(DstFile, None, Separator)\r
1030                 BuildTargetString = "%s : %s %s\n"\\r
1031                                     "\t%s\n" % (DstFile, SrcFile, " ".join(ExtraSrcFileList), "\n\t".join(CommandList))\r
1032                 self.FileBuildTargetList.append((SrcFile, BuildTargetString))\r
1033                 SrcFileBuildRule = DstFileBuildRule\r
1034 \r
1035         # handle pending targets\r
1036         TempBuildTargetList = []\r
1037         while True:\r
1038             while len(self.PendingBuildTargetList) > 0:\r
1039                 SrcFileBuildRule = self.PendingBuildTargetList.pop()\r
1040                 SrcFileList = []\r
1041                 for FileType in SrcFileBuildRule.SourceFileType:\r
1042                     if FileType not in self.SourceFileDatabase:\r
1043                         if FileType not in self.DestFileDatabase:\r
1044                             continue\r
1045                         else:\r
1046                             SrcFileList.extend(self.DestFileDatabase[FileType])\r
1047                     else:\r
1048                         SrcFileList.extend(self.SourceFileDatabase[FileType])\r
1049                 SrcFile, ExtraSrcFileList, DstFile, CommandList = SrcFileBuildRule.Apply(SrcFileList, None, Separator)\r
1050                 BuildTargetString = "%s : %s %s\n"\\r
1051                                     "\t%s\n" % (DstFile, SrcFile, " ".join(ExtraSrcFileList), "\n\t".join(CommandList))\r
1052                 self.FileBuildTargetList.append((SrcFile, BuildTargetString))\r
1053 \r
1054                 # try to find next target\r
1055                 while True:\r
1056                     DstFileType, DstFileBuildRule = BuildRule.Get(SrcFileBuildRule.DestFileExt, Family)\r
1057                     if DstFileType == None:\r
1058                         DstFileType = "Unknown-Type-File"\r
1059 \r
1060                     if DstFileType  in self.SourceFileDatabase:\r
1061                         self.SourceFileDatabase[DstFileType].append(DstFile)\r
1062                     else:\r
1063                         if DstFileType not in self.DestFileDatabase:\r
1064                             self.DestFileDatabase[DstFileType] = []\r
1065                         self.DestFileDatabase[DstFileType].append(DstFile)\r
1066 \r
1067                     if DstFileBuildRule != None and DstFileBuildRule.IsMultipleInput:\r
1068                         TempBuildTargetList.append(DstFileBuildRule)\r
1069                         break\r
1070                     elif DstFileBuildRule == None or DstFileBuildRule.CommandList == []:\r
1071                         self.ResultFileList.append(DstFile)\r
1072                         break\r
1073 \r
1074                     SrcFile, ExtraSrcFileList, DstFile, CommandList = DstFileBuildRule.Apply(DstFile, None, Separator)\r
1075                     BuildTargetString = "%s : %s %s\n"\\r
1076                                         "\t%s\n" % (DstFile, SrcFile, " ".join(ExtraSrcFileList), "\n\t".join(CommandList))\r
1077                     self.FileBuildTargetList.append((SrcFile, BuildTargetString))\r
1078                     SrcFileBuildRule = DstFileBuildRule\r
1079             if len(TempBuildTargetList) == 0:\r
1080                 break\r
1081             self.PendingBuildTargetList = TempBuildTargetList\r
1082 \r
1083         # Build AutoGen files only if we have C source files\r
1084         if CCodeFlag == True:\r
1085             for F in self.ModuleInfo.AutoGenFileList:\r
1086                 SrcFileName = path.basename(F)\r
1087                 SrcFileBase, SrcFileExt = path.splitext(SrcFileName)\r
1088                 SrcFileDir = path.dirname(F)\r
1089                 if SrcFileDir == "":\r
1090                     SrcFileDir = "."\r
1091                 else:\r
1092                     P = "$(DEBUG_DIR)" + Separator + SrcFileDir\r
1093                     if P not in self.IntermediateDirectoryList:\r
1094                         self.IntermediateDirectoryList.append(P)\r
1095 \r
1096                 SrcFileRelativePath = os.path.join(self.ModuleInfo.DebugDir, F)\r
1097 \r
1098                 SrcFileType, SrcFileBuildRule = BuildRule.Get(SrcFileExt, Family)\r
1099                 if SrcFileType != None and SrcFileType == "C-Header-File":\r
1100                     ForceIncludedFile.append(SrcFileRelativePath)\r
1101                 if SrcFileBuildRule == None or SrcFileBuildRule.CommandList == []:\r
1102                     continue\r
1103 \r
1104                 SrcFile, ExtraSrcFileList, DstFile, CommandList = SrcFileBuildRule.Apply(F, self.ModuleInfo.DebugDir, Separator)\r
1105 \r
1106                 if SrcFileType not in self.SourceFileDatabase:\r
1107                     self.SourceFileDatabase[SrcFileType] = []\r
1108                 self.SourceFileDatabase[SrcFileType].append(SrcFile)\r
1109                 SourceFileList.append(SrcFileRelativePath)\r
1110 \r
1111                 BuildTargetTemplate = "${BEGIN}%s : ${deps}\n"\\r
1112                                       "${END}\t%s\n" % (DstFile, "\n\t".join(CommandList))\r
1113                 self.FileBuildTargetList.append((SrcFileRelativePath, BuildTargetTemplate))\r
1114 \r
1115                 while True:\r
1116                     # next target\r
1117                     DstFileType, DstFileBuildRule = BuildRule.Get(SrcFileBuildRule.DestFileExt, Family)\r
1118                     if DstFileType == None:\r
1119                         DstFileType = "Unknown-Type-File"\r
1120 \r
1121                     if DstFileType  in self.SourceFileDatabase:\r
1122                         self.SourceFileDatabase[DstFileType].append(DstFile)\r
1123                     else:\r
1124                         if DstFileType not in self.DestFileDatabase:\r
1125                             self.DestFileDatabase[DstFileType] = []\r
1126                         self.DestFileDatabase[DstFileType].append(DstFile)\r
1127 \r
1128                     if DstFileBuildRule != None and DstFileBuildRule.IsMultipleInput:\r
1129                         if DstFileBuildRule not in self.PendingBuildTargetList:\r
1130                             self.PendingBuildTargetList.append(DstFileBuildRule)\r
1131                         break\r
1132                     elif DstFileBuildRule == None or DstFileBuildRule.CommandList == []:\r
1133                         self.ResultFileList.append(DstFile)\r
1134                         break\r
1135 \r
1136                     SrcFile, ExtraSrcFileList, DstFile, CommandList = DstFileBuildRule.Apply(DstFile, None, Separator)\r
1137                     BuildTargetString = "%s : %s %s\n"\\r
1138                                         "\t%s\n" % (DstFile, SrcFile, " ".join(ExtraSrcFileList), "\n\t".join(CommandList))\r
1139                     self.FileBuildTargetList.append((SrcFile, BuildTargetString))\r
1140                     SrcFileBuildRule = DstFileBuildRule\r
1141 \r
1142         #\r
1143         # Search dependency file list for each source file\r
1144         #\r
1145         self.FileDependency = self.GetFileDependency(SourceFileList, ForceIncludedFile, self.ModuleInfo.IncludePathList)\r
1146         DepSet = None\r
1147         for File in self.FileDependency:\r
1148             # skip non-C files\r
1149             if (not File.endswith(".c") and not File.endswith(".C")) or File.endswith("AutoGen.c"):\r
1150                 continue\r
1151             elif DepSet == None:\r
1152                 DepSet = set(self.FileDependency[File])\r
1153             else:\r
1154                 DepSet &= set(self.FileDependency[File])\r
1155         # in case nothing in SourceFileList\r
1156         if DepSet == None:\r
1157             DepSet = set()\r
1158         #\r
1159         # Extract comman files list in the dependency files\r
1160         #\r
1161         self.CommonFileDependency = list(DepSet)\r
1162         for F in self.FileDependency:\r
1163             NewDepSet = set(self.FileDependency[F])\r
1164             NewDepSet -= DepSet\r
1165             if File.endswith(".c") or File.endswith(".C") or not File.endswith("AutoGen.c"):\r
1166                 self.FileDependency[F] = ["$(COMMON_DEPS)"] + list(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         return self.PlatformInfo.BuildDir\r
1213 \r
1214     ## Return a list containing source file's dependencies\r
1215     #\r
1216     #   @param      FileList        The list of source files\r
1217     #   @param      ForceInculeList The list of files which will be included forcely\r
1218     #   @param      SearchPathList  The list of search path\r
1219     #\r
1220     #   @retval     dict            The mapping between source file path and its dependencies\r
1221     #\r
1222     def GetFileDependency(self, FileList, ForceInculeList, SearchPathList):\r
1223         Dependency = {}\r
1224         for F in FileList:\r
1225             Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList)\r
1226         return Dependency\r
1227 \r
1228     ## Find dependencies for one source file\r
1229     #\r
1230     #  By searching recursively "#include" directive in file, find out all the\r
1231     #  files needed by given source file. The dependecies will be only searched\r
1232     #  in given search path list.\r
1233     #\r
1234     #   @param      File            The source file\r
1235     #   @param      ForceInculeList The list of files which will be included forcely\r
1236     #   @param      SearchPathList  The list of search path\r
1237     #\r
1238     #   @retval     list            The list of files the given source file depends on\r
1239     #\r
1240     def GetDependencyList(self, File, ForceList, SearchPathList):\r
1241         EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File)\r
1242         EdkLogger.debug(EdkLogger.DEBUG_0, "Including %s" % " ".join(ForceList))\r
1243         FileStack = [File] + ForceList\r
1244         DependencySet = set()\r
1245         MacroUsedByIncludedFile = False\r
1246 \r
1247         if self.ModuleInfo.Arch not in gDependencyDatabase:\r
1248             gDependencyDatabase[self.ModuleInfo.Arch] = {}\r
1249         DepDb = gDependencyDatabase[self.ModuleInfo.Arch]\r
1250         while len(FileStack) > 0:\r
1251             EdkLogger.debug(EdkLogger.DEBUG_0, "Stack %s" % "\n\t".join(FileStack))\r
1252             F = FileStack.pop()\r
1253 \r
1254             CurrentFileDependencyList = []\r
1255             if F in DepDb and not IsChanged(F):\r
1256                 CurrentFileDependencyList = DepDb[F]\r
1257                 for Dep in CurrentFileDependencyList:\r
1258                     if Dep not in FileStack and Dep not in DependencySet:\r
1259                         FileStack.append(Dep)\r
1260             else:\r
1261                 try:\r
1262                     Fd = open(F, 'r')\r
1263                 except:\r
1264                     EdkLogger.error("AutoGen", FILE_OPEN_FAILURE, ExtraData=F)\r
1265 \r
1266                 FileContent = Fd.read()\r
1267                 Fd.close()\r
1268                 if len(FileContent) == 0:\r
1269                     continue\r
1270 \r
1271                 if FileContent[0] == 0xff or FileContent[0] == 0xfe:\r
1272                     FileContent = unicode(FileContent, "utf-16")\r
1273                 IncludedFileList = gIncludePattern.findall(FileContent)\r
1274 \r
1275                 CurrentFilePath = os.path.dirname(F)\r
1276                 for Inc in IncludedFileList:\r
1277                     # if there's macro used to reference header file, expand it\r
1278                     HeaderList = gMacroPattern.findall(Inc)\r
1279                     if len(HeaderList) == 1 and len(HeaderList[0]) == 2:\r
1280                         HeaderType = HeaderList[0][0]\r
1281                         HeaderKey = HeaderList[0][1]\r
1282                         if HeaderType in gIncludeMacroConversion:\r
1283                             Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey}\r
1284                         else:\r
1285                             # not known macro used in #include\r
1286                             MacroUsedByIncludedFile = True\r
1287                             continue\r
1288                     Inc = os.path.normpath(Inc)\r
1289                     for SearchPath in [CurrentFilePath] + SearchPathList:\r
1290                         FilePath = os.path.join(SearchPath, Inc)\r
1291                         if not os.path.exists(FilePath) or FilePath in CurrentFileDependencyList:\r
1292                             continue\r
1293                         CurrentFileDependencyList.append(FilePath)\r
1294                         if FilePath not in FileStack and FilePath not in DependencySet:\r
1295                             FileStack.append(FilePath)\r
1296                         break\r
1297                     else:\r
1298                         EdkLogger.verbose("%s included by %s was not found in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList)))\r
1299 \r
1300                 if not MacroUsedByIncludedFile:\r
1301                     if F == File:\r
1302                         CurrentFileDependencyList += ForceList\r
1303                     #\r
1304                     # Don't keep the file in cache if it uses macro in included file.\r
1305                     # So it will be scanned again if another file includes this file.\r
1306                     #\r
1307                     DepDb[F] = CurrentFileDependencyList\r
1308             DependencySet.update(CurrentFileDependencyList)\r
1309 \r
1310         #\r
1311         # If there's macro used in included file, always build the file by\r
1312         # returning a empty dependency\r
1313         #\r
1314         if MacroUsedByIncludedFile:\r
1315             DependencyList = [""]\r
1316         else:\r
1317             DependencyList = list(DependencySet)  # remove duplicate ones\r
1318             DependencyList.append(File)\r
1319 \r
1320         return DependencyList\r
1321 \r
1322     ## Get the root directory list for intermediate files of all modules build\r
1323     #\r
1324     #   @retval     list    The list of directory\r
1325     #\r
1326     def GetModuleBuildDirectoryList(self):\r
1327         DirList = []\r
1328         for Arch in self.PlatformInfo:\r
1329             for ModuleAutoGen in self.PlatformInfo[Arch].ModuleAutoGenList:\r
1330                 DirList.append(ModuleAutoGen.BuildInfo.BuildDir)\r
1331         return DirList\r
1332 \r
1333     ## Get the root directory list for intermediate files of all libraries build\r
1334     #\r
1335     #   @retval     list    The list of directory\r
1336     #\r
1337     def GetLibraryBuildDirectoryList(self):\r
1338         DirList = []\r
1339         for Arch in self.PlatformInfo:\r
1340             for LibraryAutoGen in self.PlatformInfo[Arch].LibraryAutoGenList:\r
1341                 DirList.append(LibraryAutoGen.BuildInfo.BuildDir)\r
1342         return DirList\r
1343 \r
1344     ## Return a list of directory creation command string\r
1345     #\r
1346     #   @param      DirList     The list of directory to be created\r
1347     #   @param      MakeType    GNU makefile or MS makefile\r
1348     #\r
1349     #   @retval     list        The directory creation command list\r
1350     #\r
1351     def GetCreateDirectoryCommand(self, DirList, MakeType=gMakeType):\r
1352         return [gCreateDirectoryCommandTemplate[MakeType] % {'dir':Dir} for Dir in DirList]\r
1353 \r
1354     ## Return a list of directory removal command string\r
1355     #\r
1356     #   @param      DirList     The list of directory to be removed\r
1357     #   @param      MakeType    GNU makefile or MS makefile\r
1358     #\r
1359     #   @retval     list        The directory removal command list\r
1360     #\r
1361     def GetRemoveDirectoryCommand(self, DirList, MakeType=gMakeType):\r
1362         return [gRemoveDirectoryCommandTemplate[MakeType] % {'dir':Dir} for Dir in DirList]\r
1363 \r
1364 # This acts like the main() function for the script, unless it is 'import'ed into another script.\r
1365 if __name__ == '__main__':\r
1366     pass\r