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