Removed the test of a key of tdict since it doesn't support this operation and will...
[people/mcb30/basetools.git] / Source / Python / AutoGen / AutoGen.py
1 ## @file
2 # Generate AutoGen.h, AutoGen.c and *.depex files
3 #
4 # Copyright (c) 2007, Intel Corporation
5 # All rights reserved. This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution.  The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
9 #
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 #
13
14 ## Import Modules
15 #
16 import sys
17 import os
18 import re
19 import os.path as path
20 import imp
21 import copy
22 from optparse import OptionParser
23 from optparse import make_option
24
25 import Common.EdkLogger
26 import GenC
27 import GenMake
28 import GenDepex
29
30 from StrGather import *
31 from BuildEngine import *
32
33 from Common.BuildToolError import *
34 from Common.EdkIIWorkspaceBuild import *
35 from Common.EdkIIWorkspace import *
36 from Common.DataType import *
37 from Common.Misc import *
38 from Common.String import *
39 import Common.GlobalData as GlobalData
40 from GenFds.FdfParser import *
41
42 ## Regular expression for splitting Dependency Expression stirng into tokens
43 gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")
44
45 ## Mapping Makefile type
46 gMakeTypeMap = {"MSFT":"nmake", "GCC":"gmake"}
47
48 ## Default output flag for all tools
49 gDefaultOutputFlag = "-o "
50
51 ## Output flags for specific tools
52 gOutputFlag = {
53     ("MSFT", "CC", "OUTPUT")      :   "/Fo",
54     ("MSFT", "SLINK", "OUTPUT")   :   "/OUT:",
55     ("MSFT", "DLINK", "OUTPUT")   :   "/OUT:",
56     ("MSFT", "ASMLINK", "OUTPUT") :   "/OUT:",
57     ("MSFT", "PCH", "OUTPUT")     :   "/Fp",
58     ("MSFT", "ASM", "OUTPUT")     :   "/Fo",
59
60     ("INTEL", "CC", "OUTPUT")          :   "/Fo",
61     ("INTEL", "SLINK", "OUTPUT")       :   "/OUT:",
62     ("INTEL", "DLINK", "OUTPUT")       :   "/OUT:",
63     ("INTEL", "ASMLINK", "OUTPUT")     :   "/OUT:",
64     ("INTEL", "PCH", "OUTPUT")         :   "/Fp",
65     ("INTEL", "ASM", "OUTPUT")         :   "/Fo",
66
67     ("GCC", "CC", "OUTPUT")        :   "-o ",
68     ("GCC", "SLINK", "OUTPUT")     :   "-cr ",
69     ("GCC", "DLINK", "OUTPUT")     :   "-o ",
70     ("GCC", "ASMLINK", "OUTPUT")   :   "-o ",
71     ("GCC", "PCH", "OUTPUT")       :   "-o ",
72     ("GCC", "ASM", "OUTPUT")       :   "-o ",
73 }
74
75 ## Flag for include file search path
76 gIncludeFlag = {"MSFT" : "/I", "GCC" : "-I", "INTEL" : "-I"}
77
78 ## Build rule configuration file
79 gBuildRuleFile = 'Conf/build_rule.txt'
80
81 ## default file name for AutoGen
82 gAutoGenCodeFileName = "AutoGen.c"
83 gAutoGenHeaderFileName = "AutoGen.h"
84 gAutoGenDepexFileName = "%(module_name)s.depex"
85
86 ## Base class for AutoGen
87 #
88 #   This class just implements the cache mechanism of AutoGen objects.
89 #
90 class AutoGen(object):
91     # database to maintain the objects of xxxAutoGen
92     _CACHE_ = {}    # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
93
94     ## Factory method
95     #
96     #   @param  Class           class object of real AutoGen class
97     #                           (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
98     #   @param  Workspace       Workspace directory or WorkspaceAutoGen object
99     #   @param  MetaFile        The path of meta file
100     #   @param  Target          Build target
101     #   @param  Toolchain       Tool chain name
102     #   @param  Arch            Target arch
103     #   @param  *args           The specific class related parameters
104     #   @param  **kwargs        The specific class related dict parameters
105     #
106     def __new__(Class, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
107         # check if the object has been created
108         Key = (Target, Toolchain)
109         if Key not in Class._CACHE_ or Arch not in Class._CACHE_[Key] \
110            or MetaFile not in Class._CACHE_[Key][Arch]:
111             AutoGenObject = super(AutoGen, Class).__new__(Class)
112             # call real constructor
113             if not AutoGenObject._Init(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
114                 return None
115             if Key not in Class._CACHE_:
116                 Class._CACHE_[Key] = {}
117             if Arch not in Class._CACHE_[Key]:
118                 Class._CACHE_[Key][Arch] = {}
119             Class._CACHE_[Key][Arch][MetaFile] = AutoGenObject
120         else:
121             AutoGenObject = Class._CACHE_[Key][Arch][MetaFile]
122
123         return AutoGenObject
124
125     ## hash() operator
126     #
127     #  The file path of platform file will be used to represent hash value of this object
128     #
129     #   @retval int     Hash value of the file path of platform file
130     #
131     def __hash__(self):
132         return hash(self._MetaFile)
133
134     ## str() operator
135     #
136     #  The file path of platform file will be used to represent this object
137     #
138     #   @retval string  String of platform file path
139     #
140     def __str__(self):
141         return self._MetaFile
142
143     ## "==" operator
144     def __eq__(self, Other):
145         return Other != None and self._MetaFile == str(Other)
146
147 ## Workspace AutoGen class
148 #
149 #   This class is used mainly to control the whole platform build for different
150 # architecture. This class will generate top level makefile.
151 #
152 class WorkspaceAutoGen(AutoGen):
153     ## Real constructor of WorkspaceAutoGen
154     #
155     # This method behaves the same as __init__ except that it needs explict invoke
156     # (in super class's __new__ method)
157     #
158     #   @param  WorkspaceDir            Root directory of workspace
159     #   @param  ActivePlatform          Meta-file of active platform
160     #   @param  Target                  Build target
161     #   @param  Toolchain               Tool chain name
162     #   @param  ArchList                List of architecture of current build
163     #   @param  MetaFileDb              Database containing meta-files
164     #   @param  BuildConfig             Configuration of build
165     #   @param  ToolDefinition          Tool chain definitions
166     #   @param  FlashDefinitionFile     File of flash definition
167     #   @param  Fds                     FD list to be generated
168     #   @param  Fvs                     FV list to be generated
169     #   @param  SkuId                   SKU id from command line
170     #
171     def _Init(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb,
172               BuildConfig, ToolDefinition, FlashDefinitionFile='', Fds=[], Fvs=[], SkuId=''):
173         self._MetaFile      = str(ActivePlatform)
174         self.WorkspaceDir   = WorkspaceDir
175         self.Platform       = ActivePlatform
176         self.BuildTarget    = Target
177         self.ToolChain      = Toolchain
178         self.ArchList       = ArchList
179         self.SkuId          = SkuId
180
181         self.BuildDatabase  = MetaFileDb
182         self.TargetTxt      = BuildConfig
183         self.ToolDef        = ToolDefinition
184         self.FdfFile        = FlashDefinitionFile
185         self.FdTargetList   = Fds
186         self.FvTargetList   = Fvs
187         self.AutoGenObjectList = []
188
189         # there's many relative directory operations, so ...
190         os.chdir(self.WorkspaceDir)
191
192         # parse FDF file to get PCDs in it, if any
193         if self.FdfFile != None and self.FdfFile != '':
194             Fdf = FdfParser(os.path.join(self.WorkspaceDir, self.FdfFile))
195             Fdf.ParseFile()
196             PcdSet = Fdf.Profile.PcdDict
197             ModuleList = Fdf.Profile.InfList
198         else:
199             PcdSet = {}
200             ModuleList = []
201
202         # apply SKU and inject PCDs from Flash Definition file
203         for Arch in self.ArchList:
204             Platform = self.BuildDatabase[self._MetaFile, Arch]
205             Platform.SkuName = self.SkuId
206             for Name, Guid in PcdSet:
207                 Platform.AddPcd(Name, Guid, PcdSet[Name, Guid])
208
209             Pa = PlatformAutoGen(self, self._MetaFile, Target, Toolchain, Arch)
210             self.AutoGenObjectList.append(Pa)
211
212         self._BuildDir = None
213         self._FvDir = None
214         self._MakeFileDir = None
215         self._BuildCommand = None
216
217         return True
218
219     ## Return the directory to store FV files
220     def _GetFvDir(self):
221         if self._FvDir == None:
222             self._FvDir = path.join(self.BuildDir, 'FV')
223         return self._FvDir
224
225     ## Return the directory to store all intermediate and final files built
226     def _GetBuildDir(self):
227         return self.AutoGenObjectList[0].BuildDir
228
229     ## Return the build output directory platform specifies
230     def _GetOutputDir(self):
231         return self.Platform.OutputDirectory
232
233     ## Return platform name
234     def _GetName(self):
235         return self.Platform.PlatformName
236
237     ## Return meta-file GUID
238     def _GetGuid(self):
239         return self.Platform.Guid
240
241     ## Return platform version
242     def _GetVersion(self):
243         return self.Platform.Version
244
245     ## Return paths of tools
246     def _GetToolPaths(self):
247         return self.AutoGenObjectList[0].ToolPath
248
249     ## Return options of tools
250     def _GetToolOptions(self):
251         return self.AutoGenObjectList[0].ToolOption
252
253     ## Return directory of platform makefile
254     #
255     #   @retval     string  Makefile directory
256     #
257     def _GetMakeFileDir(self):
258         if self._MakeFileDir == None:
259             self._MakeFileDir = self.BuildDir
260         return self._MakeFileDir
261
262     ## Return build command string
263     #
264     #   @retval     string  Build command string
265     #
266     def _GetBuildCommand(self):
267         if self._BuildCommand == None:
268             # BuildCommand should be all the same. So just get one from platform AutoGen
269             self._BuildCommand = self.AutoGenObjectList[0].BuildCommand
270         return self._BuildCommand
271
272     ## Create makefile for the platform and mdoules in it
273     #
274     #   @param      CreateDepsMakeFile      Flag indicating if the makefile for
275     #                                       modules will be created as well
276     #
277     def CreateMakeFile(self, CreateDepsMakeFile=False):
278         # create makefile for platform
279         Makefile = GenMake.TopLevelMakefile(self)
280         if Makefile.Generate():
281             EdkLogger.verbose("Generated makefile for platform [%s] %s\n" %
282                            (self._MetaFile, self.ArchList))
283         else:
284             EdkLogger.verbose("Skipped the generation of makefile for platform [%s] %s\n" %
285                            (self._MetaFile, self.ArchList))
286
287         if CreateDepsMakeFile:
288             for Pa in self.AutoGenObjectList:
289                 Pa.CreateMakeFile(CreateDepsMakeFile)
290
291     ## Create autogen code for platform and modules
292     #
293     #  Since there's no autogen code for platform, this method will do nothing
294     #  if CreateModuleCodeFile is set to False.
295     #
296     #   @param      CreateDepsCodeFile      Flag indicating if creating module's
297     #                                       autogen code file or not
298     #
299     def CreateCodeFile(self, CreateDepsCodeFile=False):
300         if not CreateDepsCodeFile:
301             return
302         for Pa in self.AutoGenObjectList:
303             Pa.CreateCodeFile(CreateDepsCodeFile)
304
305     Name                = property(_GetName)
306     Guid                = property(_GetGuid)
307     Version             = property(_GetVersion)
308     OutputDir           = property(_GetOutputDir)
309
310     ToolPath            = property(_GetToolPaths)       # toolcode : tool path
311     ToolOption          = property(_GetToolOptions)     # toolcode : tool option string
312
313     BuildDir            = property(_GetBuildDir)
314     FvDir               = property(_GetFvDir)
315     MakeFileDir         = property(_GetMakeFileDir)
316     BuildCommand        = property(_GetBuildCommand)
317
318 ## AutoGen class for platform
319 #
320 #  PlatformAutoGen class will process the original information in platform
321 #  file in order to generate makefile for platform.
322 #
323 class PlatformAutoGen(AutoGen):
324     ## The real constructor of PlatformAutoGen
325     #
326     #  This method is not supposed to be called by users of PlatformAutoGen. It's
327     #  only used by factory method __new__() to do real initialization work for an
328     #  object of PlatformAutoGen
329     #
330     #   @param      Workspace       EdkIIWorkspaceBuild object
331     #   @param      PlatformFile    Platform file (DSC file)
332     #   @param      Target          Build target (DEBUG, RELEASE)
333     #   @param      Toolchain       Name of tool chain
334     #   @param      Arch            arch of the platform supports
335     #
336     def _Init(self, Workspace, PlatformFile, Target, Toolchain, Arch):
337         EdkLogger.verbose("\nAutoGen platform [%s] [%s]" % (PlatformFile, Arch))
338         GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)
339
340         self._MetaFile = str(PlatformFile)
341         self.Workspace = Workspace
342         self.WorkspaceDir = Workspace.WorkspaceDir
343         self.ToolChain = Toolchain
344         self.BuildTarget = Target
345         self.Arch = Arch
346         self.SourceDir = path.dirname(PlatformFile)
347         self.FdTargetList = self.Workspace.FdTargetList
348         self.FvTargetList = self.Workspace.FvTargetList
349
350         # flag indicating if the makefile/C-code file has been created or not
351         self.IsMakeFileCreated  = False
352         self.IsCodeFileCreated  = False
353
354         self._Platform   = None
355         self._Name       = None
356         self._Guid       = None
357         self._Version    = None
358
359         self._BuildRule = None
360         self._SourceDir = None
361         self._BuildDir = None
362         self._OutputDir = None
363         self._FvDir = None
364         self._MakeFileDir = None
365         self._FdfFile = None
366
367         self._PcdTokenNumber = None    # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
368         self._DynamicPcdList = None    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
369         self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
370
371         self._ToolPath = None          # toolcode : tool path
372         self._ToolDllPath = None       # toolcode : lib path
373         self._ToolStaticLib = None     # toolcode : lib path
374         self._ToolChainFamily = None   # toolcode : tool chain family
375         self._BuildOption = None       # toolcode : option
376         self._OutputFlag = None        # toolcode : output flag
377         self._IncludeFlag = None       # toolcode : include flag
378         self._ToolOption = None        # toolcode : tool option string
379         self._PackageList = None
380         self._ModuleAutoGenList  = None
381         self._LibraryAutoGenList = None
382         self._BuildCommand = None
383
384         # get the original module/package/platform objects
385         self.BuildDatabase = Workspace.BuildDatabase
386         return True
387
388     ## Create autogen code for platform and modules
389     #
390     #  Since there's no autogen code for platform, this method will do nothing
391     #  if CreateModuleCodeFile is set to False.
392     #
393     #   @param      CreateModuleCodeFile    Flag indicating if creating module's
394     #                                       autogen code file or not
395     #
396     def CreateCodeFile(self, CreateModuleCodeFile=False):
397         # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
398         if self.IsCodeFileCreated or not CreateModuleCodeFile:
399             return
400
401         for Ma in self.ModuleAutoGenList:
402             Ma.CreateCodeFile(True)
403
404         # don't do this twice
405         self.IsCodeFileCreated = True
406
407     ## Create makefile for the platform and mdoules in it
408     #
409     #   @param      CreateModuleMakeFile    Flag indicating if the makefile for
410     #                                       modules will be created as well
411     #
412     def CreateMakeFile(self, CreateModuleMakeFile=False):
413         if CreateModuleMakeFile:
414             for ModuleFile in self.Platform.Modules:
415                 Ma = ModuleAutoGen(self.Workspace, ModuleFile,
416                                               self.BuildTarget, self.ToolChain,
417                                               self.Arch, self._MetaFile)
418                 Ma.CreateMakeFile(True)
419
420         # no need to create makefile for the platform more than once
421         if self.IsMakeFileCreated:
422             return
423
424         # create makefile for platform
425         Makefile = GenMake.PlatformMakefile(self)
426         if Makefile.Generate():
427             EdkLogger.verbose("Generated makefile for platform [%s] [%s]\n" %
428                            (self._MetaFile, self.Arch))
429         else:
430             EdkLogger.verbose("Skipped the generation of makefile for platform [%s] [%s]\n" %
431                            (self._MetaFile, self.Arch))
432         self.IsMakeFileCreated = True
433
434     ## Return the platform build data object
435     def _GetPlatform(self):
436         if self._Platform == None:
437             self._Platform = self.BuildDatabase[self._MetaFile, self.Arch]
438         return self._Platform
439
440     ## Return platform name
441     def _GetName(self):
442         return self.Platform.PlatformName
443
444     ## Return the meta file GUID
445     def _GetGuid(self):
446         return self.Platform.Guid
447
448     ## Return the platform version
449     def _GetVersion(self):
450         return self.Platform.Version
451
452     ## Return the FDF file name
453     def _GetFdfFile(self):
454         if self._FdfFile == None:
455             if self.Workspace.FdfFile != "":
456                 self._FdfFile= path.join(self.WorkspaceDir, self.Workspace.FdfFile)
457             else:
458                 self._FdfFile = ''
459         return self._FdfFile
460
461     ## Return the build output directory platform specifies
462     def _GetOutputDir(self):
463         return self.Platform.OutputDirectory
464
465     ## Return the directory to store all intermediate and final files built
466     def _GetBuildDir(self):
467         if self._BuildDir == None:
468             if os.path.isabs(self.OutputDir):
469                 self._BuildDir = path.join(
470                                             path.abspath(self.OutputDir),
471                                             self.BuildTarget + "_" + self.ToolChain,
472                                             )
473             else:
474                 self._BuildDir = path.join(
475                                             self.WorkspaceDir,
476                                             self.OutputDir,
477                                             self.BuildTarget + "_" + self.ToolChain,
478                                             )
479         return self._BuildDir
480
481     ## Return directory of platform makefile
482     #
483     #   @retval     string  Makefile directory
484     #
485     def _GetMakeFileDir(self):
486         if self._MakeFileDir == None:
487             self._MakeFileDir = path.join(self.BuildDir, self.Arch)
488         return self._MakeFileDir
489
490     ## Return build command string
491     #
492     #   @retval     string  Build command string
493     #
494     def _GetBuildCommand(self):
495         if self._BuildCommand == None:
496             self._BuildCommand = tuple()
497             if "MAKE" in self.ToolPath:
498                 self._BuildCommand += (self.ToolPath["MAKE"],)
499                 if "MAKE" in self.ToolOption:
500                     NewOption = self.ToolOption["MAKE"].strip()
501                     if NewOption != '':
502                       self._BuildCommand += (NewOption,)
503         return self._BuildCommand
504
505     ## Get tool chain definition
506     #
507     #  Get each tool defition for given tool chain from tools_def.txt and platform
508     #
509     def _GetToolDefinition(self):
510         ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
511         if "COMMAND_TYPE" not in self.Workspace.ToolDef.ToolsDefTxtDatabase:
512             EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",
513                             ExtraData="[%s]" % self._MetaFile)
514         ToolCodeList = self.Workspace.ToolDef.ToolsDefTxtDatabase["COMMAND_TYPE"]
515         self._ToolPath = {}
516         self._ToolDllPath = {}
517         self._ToolChainFamily = {}
518         self._ToolOption = {}
519         self._OutputFlag = {}
520         self._IncludeFlag = {}
521         for Tool in ToolCodeList:
522             KeyBaseString = "%s_%s_%s_%s" % (self.BuildTarget, self.ToolChain, self.Arch, Tool)
523
524             Key = "%s_PATH" % KeyBaseString
525             if Key not in ToolDefinition:
526                 continue
527             Path = ToolDefinition[Key]
528
529             Key = "%s_FAMILY" % KeyBaseString
530             if Key in ToolDefinition:
531                 Family = ToolDefinition[Key]
532             else:
533                 Family = ""
534
535             Key = "%s_FLAGS" % KeyBaseString
536             if Key in ToolDefinition:
537                 Option = ToolDefinition[Key]
538             else:
539                 Option = ""
540
541             Key = "%s_DLL" % KeyBaseString
542             if Key in ToolDefinition:
543                 Dll = ToolDefinition[Key]
544                 # set the DLL path in system's PATH environment
545                 os.environ["PATH"] = Dll + os.pathsep + os.environ["PATH"]
546             else:
547                 Dll = ""
548
549             Key = KeyBaseString + "_OUTPUT"
550             if Key in ToolDefinition:
551                 OutputFlag = ToolDefinition[Key]
552             elif (Family, Tool, "OUTPUT") in gOutputFlag:
553                 OutputFlag = gOutputFlag[Family, Tool, "OUTPUT"]
554                 if OutputFlag[0] == '"' and OutputFlag[-1] == '"':
555                     OutputFlag = OutputFlag[1:-1]
556             else:
557                 OutputFlag = gDefaultOutputFlag
558
559             if Family in gIncludeFlag:
560                 InputFlag = gIncludeFlag[Family]
561             else:
562                 InputFlag = '-I'
563
564             self._ToolPath[Tool] = Path
565             self._ToolDllPath[Tool] = Dll
566             self._ToolChainFamily[Tool] = Family
567             self._ToolOption[Tool] = Option
568             self._OutputFlag[Tool] = OutputFlag
569             self._IncludeFlag[Tool] = InputFlag
570
571     ## Return the paths of tools
572     def _GetToolPaths(self):
573         if self._ToolPath == None:
574             self._GetToolDefinition()
575         return self._ToolPath
576
577     ## Return the dll paths of tools
578     def _GetToolDllPaths(self):
579         if self._ToolDllPath == None:
580             self._GetToolDefinition()
581         return self._ToolDllPath
582
583     ## Return the static libraries of tools
584     def _GetToolStaticLibs(self):
585         if self._ToolStaticLib == None:
586             self._GetToolDefinition()
587         return self._ToolStaticLib
588
589     ## Return the families of tools
590     def _GetToolChainFamilies(self):
591         if self._ToolChainFamily == None:
592             self._GetToolDefinition()
593         return self._ToolChainFamily
594
595     ## Return the build options specific to this platform
596     def _GetBuildOptions(self):
597         if self._BuildOption == None:
598             self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)
599         return self._BuildOption
600
601     ## Return the output flag of tools
602     def _GetOuputFlags(self):
603         if self._OutputFlag == None:
604             self._GetToolDefinition()
605         return self._OutputFlag
606
607     ## Return the include flags of tools
608     def _GetIncludeFlags(self):
609         if self._IncludeFlag == None:
610             self._GetToolDefinition()
611         return self._IncludeFlag
612
613     ## Return the default options of tools
614     def _GetToolOptions(self):
615         if self._ToolOption == None:
616             self._GetToolDefinition()
617         return self._ToolOption
618
619     ## Parse build_rule.txt in $(WORKSPACE)/Conf/build_rule.txt
620     #
621     #   @retval     BuildRule object
622     #
623     def _GetBuildRule(self):
624         if self._BuildRule == None:
625             BuildRuleFile = None
626             if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:
627                 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
628             if BuildRuleFile in [None, '']:
629                 BuildRuleFile = gBuildRuleFile
630             self._BuildRule = BuildRule(BuildRuleFile)
631         return self._BuildRule
632
633     ## Summarize the packages used by modules in this platform
634     def _GetPackageList(self):
635         if self._PackageList == None:
636             self._PackageList = set()
637             for La in self.LibraryAutoGenList:
638                 self._PackageList.update(La.DependentPackageList)
639             for Ma in self.ModuleAutoGenList:
640                 self._PackageList.update(Ma.DependentPackageList)
641         return self._PackageList
642
643     ## Collect dynamic PCDs
644     #
645     #  Gather dynamic PCDs list from each module and their settings from platform
646     #
647     def _GetPcdList(self):
648         self._NonDynamicPcdList = []
649         self._DynamicPcdList = []
650
651         # for gathering error information
652         NotFoundPcdList = set()
653         NoDatumTypePcdList = set()
654
655         self._GuidValue = {}
656         for F in self.Platform.Modules:
657             M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self._MetaFile)
658             #GuidValue.update(M.Guids)
659             for PcdFromModule in M.PcdList:
660                 # check if the setting of the PCD is found in platform
661                 #if not PcdFromModule.IsOverrided:
662                 #    NotFoundPcdList.add("%s [%s]" % (" | ".join(Key), F))
663                 #    continue
664
665                 # make sure that the "VOID*" kind of datum has MaxDatumSize set
666                 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize == None:
667                     NoDatumTypePcdList.add("%s [%s]" % (" | ".join(Key), F))
668
669                 if PcdFromModule.Type in GenC.gDynamicPcd or PcdFromModule.Type in GenC.gDynamicExPcd:
670                     # for autogen code purpose
671                     if M.ModuleType in ["PEIM", "PEI_CORE"]:
672                         PcdFromModule.Phase = "PEI"
673                     if PcdFromModule not in self._DynamicPcdList:
674                         self._DynamicPcdList.append(PcdFromModule)
675                 elif PcdFromModule not in self._NonDynamicPcdList:
676                     self._NonDynamicPcdList.append(PcdFromModule)
677
678         # print out error information and break the build, if error found
679         if len(NoDatumTypePcdList) > 0:
680             NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)
681             EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
682                             File=self._MetaFile,
683                             ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
684                                       % NoDatumTypePcdListString)
685
686     ## Get list of non-dynamic PCDs
687     def _GetNonDynamicPcdList(self):
688         if self._NonDynamicPcdList == None:
689             self._GetPcdList()
690         return self._NonDynamicPcdList
691
692     ## Get list of dynamic PCDs
693     def _GetDynamicPcdList(self):
694         if self._DynamicPcdList == None:
695             self._GetPcdList()
696         return self._DynamicPcdList
697
698     ## Generate Token Number for all PCD
699     def _GetPcdTokenNumbers(self):
700         if self._PcdTokenNumber == None:
701             self._PcdTokenNumber = sdict()
702             TokenNumber = 1
703             for Pcd in self.DynamicPcdList:
704                 if Pcd.Phase == "PEI":
705                     EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
706                     self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
707                     TokenNumber += 1
708
709             for Pcd in self.DynamicPcdList:
710                 if Pcd.Phase == "DXE":
711                     EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
712                     self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
713                     TokenNumber += 1
714
715             for Pcd in self.NonDynamicPcdList:
716                 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
717                 TokenNumber += 1
718         return self._PcdTokenNumber
719
720     ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
721     def _GetAutoGenObjectList(self):
722         self._ModuleAutoGenList = []
723         self._LibraryAutoGenList = []
724         for ModuleFile in self.Platform.Modules:
725             Ma = ModuleAutoGen(
726                     self.Workspace,
727                     ModuleFile,
728                     self.BuildTarget,
729                     self.ToolChain,
730                     self.Arch,
731                     self._MetaFile
732                     )
733             if Ma not in self._ModuleAutoGenList:
734                 self._ModuleAutoGenList.append(Ma)
735             for La in Ma.LibraryAutoGenList:
736                 if La not in self._LibraryAutoGenList:
737                     self._LibraryAutoGenList.append(La)
738
739     ## Summarize ModuleAutoGen objects of all modules to be built for this platform
740     def _GetModuleAutoGenList(self):
741         if self._ModuleAutoGenList == None:
742             self._GetAutoGenObjectList()
743         return self._ModuleAutoGenList
744
745     ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
746     def _GetLibraryAutoGenList(self):
747         if self._LibraryAutoGenList == None:
748             self._GetAutoGenObjectList()
749         return self._LibraryAutoGenList
750
751     ## Test if a module is supported by the platform
752     #
753     #  An error will be raised directly if the module or its arch is not supported
754     #  by the platform or current configuration
755     #
756     def ValidModule(self, Module):
757         return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances
758
759     ## Resolve the library classes in a module to library instances
760     #
761     # This method will not only resolve library classes but also sort the library
762     # instances according to the dependency-ship.
763     #
764     #   @param  Module      The module from which the library classes will be resolved
765     #
766     #   @retval library_list    List of library instances sorted
767     #
768     def ApplyLibraryInstance(self, Module):
769         ModuleType = Module.ModuleType
770
771         # for overridding library instances with module specific setting
772         PlatformModule = self.Platform.Modules[str(Module)]
773
774         # add forced library instance
775         for LibraryClass in PlatformModule.LibraryClasses:
776             if LibraryClass.startswith("NULL"):
777                 Module.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]
778
779         # R9 module
780         LibraryConsumerList = [Module]
781         Constructor         = []
782         ConsumedByList      = sdict()
783         LibraryInstance     = sdict()
784
785         EdkLogger.verbose("")
786         EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
787         while len(LibraryConsumerList) > 0:
788             M = LibraryConsumerList.pop()
789             for LibraryClassName in M.LibraryClasses:
790                 if LibraryClassName not in LibraryInstance:
791                     # override library instance for this module
792                     if LibraryClassName in PlatformModule.LibraryClasses:
793                         LibraryPath = PlatformModule.LibraryClasses[LibraryClassName]
794                     else:
795                         LibraryPath = self.Platform.LibraryClasses[LibraryClassName, ModuleType]
796                     if LibraryPath == None or LibraryPath == "":
797                         LibraryPath = M.LibraryClasses[LibraryClassName]
798                         if LibraryPath == None or LibraryPath == "":
799                             EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,
800                                             "Instance of library class [%s] is not found" % LibraryClassName,
801                                             File=self._MetaFile,
802                                             ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), self.Arch, str(Module)))
803
804                     LibraryModule = self.BuildDatabase[LibraryPath, self.Arch]
805                     # for those forced library instance (NULL library), add a fake library class
806                     if LibraryClassName.startswith("NULL"):
807                         LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType]))
808                     elif LibraryModule.LibraryClass == None or len(LibraryModule.LibraryClass) == 0 \
809                          or ModuleType not in LibraryModule.LibraryClass[0].SupModList:
810                         EdkLogger.error("build", OPTION_MISSING,
811                                         "Module type [%s] is not supported by library instance [%s]" \
812                                         % (ModuleType, LibraryPath), File=self._MetaFile,
813                                         ExtraData="consumed by [%s]" % str(Module))
814
815                     LibraryInstance[LibraryClassName] = LibraryModule
816                     LibraryConsumerList.append(LibraryModule)
817                     EdkLogger.verbose("\t" + str(LibraryClassName) + " : " + str(LibraryModule))
818                 else:
819                     LibraryModule = LibraryInstance[LibraryClassName]
820
821                 if LibraryModule == None:
822                     continue
823
824                 if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor:
825                     Constructor.append(LibraryModule)
826
827                 if LibraryModule not in ConsumedByList:
828                     ConsumedByList[LibraryModule] = []
829                 # don't add current module itself to consumer list
830                 if M != Module:
831                     if M in ConsumedByList[LibraryModule]:
832                         continue
833                     ConsumedByList[LibraryModule].append(M)
834         #
835         # Initialize the sorted output list to the empty set
836         #
837         SortedLibraryList = []
838         #
839         # Q <- Set of all nodes with no incoming edges
840         #
841         LibraryList = [] #LibraryInstance.values()
842         Q = []
843         for LibraryClassName in LibraryInstance:
844             M = LibraryInstance[LibraryClassName]
845             LibraryList.append(M)
846             if ConsumedByList[M] == []:
847                 Q.insert(0, M)
848
849         #
850         # start the  DAG algorithm
851         #
852         while True:
853             EdgeRemoved = True
854             while Q == [] and EdgeRemoved:
855                 EdgeRemoved = False
856                 # for each node Item with a Constructor
857                 for Item in LibraryList:
858                     if Item not in Constructor:
859                         continue
860                     # for each Node without a constructor with an edge e from Item to Node
861                     for Node in ConsumedByList[Item]:
862                         if Node in Constructor:
863                             continue
864                         # remove edge e from the graph if Node has no constructor
865                         ConsumedByList[Item].remove(Node)
866                         EdgeRemoved = True
867                         if ConsumedByList[Item] == []:
868                             # insert Item into Q
869                             Q.insert(0, Item)
870                             break
871                     if Q != []:
872                         break
873             # DAG is done if there's no more incoming edge for all nodes
874             if Q == []:
875                 break
876
877             # remove node from Q
878             Node = Q.pop()
879             # output Node
880             SortedLibraryList.append(Node)
881
882             # for each node Item with an edge e from Node to Item do
883             for Item in LibraryList:
884                 if Node not in ConsumedByList[Item]:
885                     continue
886                 # remove edge e from the graph
887                 ConsumedByList[Item].remove(Node)
888
889                 if ConsumedByList[Item] != []:
890                     continue
891                 # insert Item into Q, if Item has no other incoming edges
892                 Q.insert(0, Item)
893
894         #
895         # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
896         #
897         for Item in LibraryList:
898             if ConsumedByList[Item] != [] and Item in Constructor and len(Constructor) > 1:
899                 ErrorMessage = "\tconsumed by " + "\n\tconsumed by ".join([str(L) for L in ConsumedByList[Item]])
900                 EdkLogger.error("build", BUILD_ERROR, 'Library [%s] with constructors has a cycle' % str(Item),
901                                 ExtraData=ErrorMessage, File=self._MetaFile)
902             if Item not in SortedLibraryList:
903                 SortedLibraryList.append(Item)
904
905         #
906         # Build the list of constructor and destructir names
907         # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
908         #
909         SortedLibraryList.reverse()
910         return SortedLibraryList
911
912
913     ## Override PCD setting (type, value, ...)
914     #
915     #   @param  ToPcd       The PCD to be overrided
916     #   @param  FromPcd     The PCD overrideing from
917     #
918     def _OverridePcd(self, ToPcd, FromPcd, Module=""):
919         #
920         # in case there's PCDs coming from FDF file, which have no type given.
921         # at this point, ToPcd.Type has the type found from dependent
922         # package
923         #
924         if FromPcd != None:
925             if ToPcd.Pending and FromPcd.Type not in [None, '']:
926                 ToPcd.Type = FromPcd.Type
927             elif ToPcd.Type not in [None, ''] and FromPcd.Type not in [None, ''] \
928                 and ToPcd.Type != FromPcd.Type:
929                 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",
930                                 ExtraData="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
931                                           % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName,
932                                              ToPcd.Type, Module, FromPcd.Type),
933                                           File=self._MetaFile)
934
935             if FromPcd.MaxDatumSize not in [None, '']:
936                 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
937             if FromPcd.DefaultValue not in [None, '']:
938                 ToPcd.DefaultValue = FromPcd.DefaultValue
939             if FromPcd.TokenValue not in [None, '']:
940                 ToPcd.TokenValue = FromPcd.TokenValue
941             if FromPcd.MaxDatumSize not in [None, '']:
942                 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
943             if FromPcd.DatumType not in [None, '']:
944                 ToPcd.DatumType = FromPcd.DatumType
945             if FromPcd.SkuInfoList not in [None, '', []]:
946                 ToPcd.SkuInfoList = FromPcd.SkuInfoList
947
948         if ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]:
949             EdkLogger.verbose("No MaxDatumSize specified for PCD %s.%s" \
950                               % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))
951             Value = ToPcd.DefaultValue
952             if Value in [None, '']:
953                 ToPcd.MaxDatumSize = 1
954             elif Value[0] == 'L':
955                 ToPcd.MaxDatumSize = str(len(Value) * 2)
956             elif Value[0] == '{':
957                 ToPcd.MaxDatumSize = str(len(Value.split(',')))
958             else:
959                 ToPcd.MaxDatumSize = str(len(Value))
960
961         # apply default SKU for dynamic PCDS if specified one is not available
962         if (ToPcd.Type in PCD_DYNAMIC_TYPE_LIST or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_LIST) \
963             and ToPcd.SkuInfoList in [None, {}, '']:
964             if self.Platform.SkuName in self.Platform.SkuIds:
965                 SkuName = self.Platform.SkuName
966             else:
967                 SkuName = 'DEFAULT'
968             ToPcd.SkuInfoList = {
969                 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName], '', '', '', '', '', ToPcd.DefaultValue)
970             }
971
972     ## Apply PCD setting defined platform to a module
973     #
974     #   @param  Module  The module from which the PCD setting will be overrided
975     #
976     #   @retval PCD_list    The list PCDs with settings from platform
977     #
978     def ApplyPcdSetting(self, Module):
979         # for each PCD in module
980         for Name,Guid in Module.Pcds:
981             PcdInModule = Module.Pcds[Name,Guid]
982             # find out the PCD setting in platform
983             if (Name,Guid) in self.Platform.Pcds:
984                 PcdInPlatform = self.Platform.Pcds[Name,Guid]
985             else:
986                 PcdInPlatform = None
987             # then override the settings if any
988             self._OverridePcd(PcdInModule, PcdInPlatform, Module)
989             # resolve the VariableGuid value
990             for SkuId in PcdInModule.SkuInfoList:
991                 Sku = PcdInModule.SkuInfoList[SkuId]
992                 if Sku.VariableGuid == '': continue
993                 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList)
994                 if Sku.VariableGuidValue == None:
995                     PackageList = '\t' + "\n\t".join([str(P) for P in Module.Packages])
996                     EdkLogger.error(
997                                 'build',
998                                 RESOURCE_NOT_AVAILABLE,
999                                 "Value of GUID [%s] is not found in" % Sku.VariableGuid,
1000                                 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \
1001                                                         % (Guid, Name, str(Module)),
1002                                 File=self._MetaFile
1003                                 )
1004
1005         # override PCD settings with module specific setting
1006         if Module in self.Platform.Modules:
1007             PlatformModule = self.Platform.Modules[str(Module)]
1008             for Key  in PlatformModule.Pcds:
1009                 if Key in Module.Pcds:
1010                     self._OverridePcd(Module.Pcds[Key], PlatformModule.Pcds[Key], Module)
1011         return Module.Pcds.values()
1012
1013     ## Resolve library names to library modules
1014     #
1015     # (for R8.x modules)
1016     #
1017     #   @param  Module  The module from which the library names will be resolved
1018     #
1019     #   @retval library_list    The list of library modules
1020     #
1021     def ResolveLibraryReference(self, Module):
1022         EdkLogger.verbose("")
1023         EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
1024         LibraryConsumerList = [Module]
1025
1026         # "CompilerStub" is a must for R8 modules
1027         Module.Libraries.append("CompilerStub")
1028         LibraryList = []
1029         while len(LibraryConsumerList) > 0:
1030             M = LibraryConsumerList.pop()
1031             for LibraryName in M.Libraries:
1032                 Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']
1033                 if Library == None:
1034                     EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),
1035                                     ExtraData="\t%s [%s]" % (str(Module), self.Arch))
1036                     continue
1037
1038                 if Library not in LibraryList:
1039                     LibraryList.append(Library)
1040                     LibraryConsumerList.append(Library)
1041                     EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))
1042         return LibraryList
1043
1044     ## Expand * in build option key
1045     #
1046     #   @param  Options     Options to be expanded
1047     #
1048     #   @retval options     Options expanded
1049     #
1050     def _ExpandBuildOption(self, Options):
1051         BuildOptions = {}
1052         for Key in Options:
1053             Family = Key[0]
1054             Target, Tag, Arch, Tool, Attr = Key[1].split("_")
1055             # if no tool defined for the option, skip it
1056             if Tool not in self.ToolPath:
1057                 continue
1058             # if tool chain family doesn't match, skip it
1059             if Family != None and Family != "" and Family != self.ToolChainFamily[Tool]:
1060                 continue
1061             # expand any wildcard
1062             if Target == "*" or Target == self.BuildTarget:
1063                 if Tag == "*" or Tag == self.ToolChain:
1064                     if Arch == "*" or Arch == self.Arch:
1065                         if Tool not in BuildOptions:
1066                             BuildOptions[Tool] = Options[Key]
1067                         else:
1068                             # append options for the same tool
1069                             BuildOptions[Tool] += " " + Options[Key]
1070         return BuildOptions
1071
1072     ## Append build options in platform to a module
1073     #
1074     #   @param  Module  The module to which the build options will be appened
1075     #
1076     #   @retval options     The options appended with build options in platform
1077     #
1078     def ApplyBuildOption(self, Module):
1079         PlatformOptions = self.BuildOption
1080         ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)
1081         if Module in self.Platform.Modules:
1082             PlatformModule = self.Platform.Modules[str(Module)]
1083             PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
1084         else:
1085             PlatformModuleOptions = {}
1086
1087         BuildOptions = {}
1088         # for those tools that have no option in module file, give it a empty string
1089         for Tool in self.Workspace.ToolPath:
1090             if Tool in self.ToolOption and Module.ModuleType != 'USER_DEFINED':
1091                 BuildOptions[Tool] = self.ToolOption[Tool]
1092             else:
1093                 BuildOptions[Tool] = ''
1094             if Tool in ModuleOptions:
1095                 BuildOptions[Tool] += " " + ModuleOptions[Tool]
1096             if Tool in PlatformOptions:
1097                 BuildOptions[Tool] += " " + PlatformOptions[Tool]
1098             if Tool in PlatformModuleOptions:
1099                 BuildOptions[Tool] += " " + PlatformModuleOptions[Tool]
1100         return BuildOptions
1101
1102     Platform            = property(_GetPlatform)
1103     Name                = property(_GetName)
1104     Guid                = property(_GetGuid)
1105     Version             = property(_GetVersion)
1106
1107     OutputDir           = property(_GetOutputDir)
1108     BuildDir            = property(_GetBuildDir)
1109     MakeFileDir         = property(_GetMakeFileDir)
1110     FdfFile             = property(_GetFdfFile)
1111
1112     PcdTokenNumber      = property(_GetPcdTokenNumbers)    # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1113     DynamicPcdList      = property(_GetDynamicPcdList)    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1114     NonDynamicPcdList   = property(_GetNonDynamicPcdList)    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1115     PackageList         = property(_GetPackageList)
1116
1117     ToolPath            = property(_GetToolPaths)    # toolcode : tool path
1118     ToolDllPath         = property(_GetToolDllPaths)    # toolcode : lib path
1119     ToolStaticLib       = property(_GetToolStaticLibs)    # toolcode : lib path
1120     ToolChainFamily     = property(_GetToolChainFamilies)    # toolcode : tool chain family
1121     BuildOption         = property(_GetBuildOptions)    # toolcode : option
1122     OutputFlag          = property(_GetOuputFlags)    # toolcode : output flag
1123     IncludeFlag         = property(_GetIncludeFlags)    # toolcode : include flag
1124     ToolOption          = property(_GetToolOptions)    # toolcode : tool option string
1125
1126     BuildCommand        = property(_GetBuildCommand)
1127     BuildRule           = property(_GetBuildRule)
1128     ModuleAutoGenList   = property(_GetModuleAutoGenList)
1129     LibraryAutoGenList  = property(_GetLibraryAutoGenList)
1130
1131 ## ModuleAutoGen class
1132 #
1133 # This class encapsules the AutoGen behaviors for the build tools. In addition to
1134 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
1135 # to the [depex] section in module's inf file.
1136 #
1137 class ModuleAutoGen(AutoGen):
1138     ## The real constructor of ModuleAutoGen
1139     #
1140     #  This method is not supposed to be called by users of ModuleAutoGen. It's
1141     #  only used by factory method __new__() to do real initialization work for an
1142     #  object of ModuleAutoGen
1143     #
1144     #   @param      Workspace           EdkIIWorkspaceBuild object
1145     #   @param      ModuleFile          The path of module file
1146     #   @param      Target              Build target (DEBUG, RELEASE)
1147     #   @param      Toolchain           Name of tool chain
1148     #   @param      Arch                The arch the module supports
1149     #   @param      PlatformFile        Platform meta-file
1150     #
1151     def _Init(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):
1152         EdkLogger.verbose("\nAutoGen module [%s] [%s]" % (ModuleFile, Arch))
1153         GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)
1154
1155         self.Workspace = Workspace
1156         self.WorkspaceDir = Workspace.WorkspaceDir
1157
1158         self._MetaFile = str(ModuleFile)
1159         self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)
1160         # check if this module is employed by active platform
1161         if not self.PlatformInfo.ValidModule(self._MetaFile):
1162             EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \
1163                               % (self._MetaFile, Arch))
1164             return False
1165
1166         self.SourceDir = path.dirname(self._MetaFile)
1167         self.FileBase, self.FileExt = path.splitext(path.basename(self._MetaFile))
1168
1169         self.ToolChain = Toolchain
1170         self.ToolChainFamily = "MSFT"
1171         self.BuildTarget = Target
1172         self.Arch = Arch
1173
1174         self.IsMakeFileCreated = False
1175         self.IsCodeFileCreated = False
1176
1177         self.BuildDatabase = self.Workspace.BuildDatabase
1178
1179         self._Module          = None
1180         self._Name            = None
1181         self._Guid            = None
1182         self._Version         = None
1183         self._ModuleType      = None
1184         self._ComponentType   = None
1185         self._PcdIsDriver     = None
1186         self._AutoGenVersion  = None
1187         self._LibraryFlag     = None
1188         self._CustomMakefile  = None
1189         self._Macro           = None
1190
1191         self._BuildDir        = None
1192         self._OutputDir       = None
1193         self._DebugDir        = None
1194         self._MakeFileDir     = None
1195
1196         self._IncludePathList = None
1197         self._AutoGenFileList = None
1198         self._UnicodeFileList = None
1199         self._SourceFileList  = None
1200         self._ObjectFileList  = None
1201         self._BinaryFileDict  = None
1202
1203         self._DependentPackageList    = None
1204         self._DependentLibraryList    = None
1205         self._LibraryAutoGenList      = None
1206         self._DerivedPackageList      = None
1207         self._PcdList                 = None
1208         self._GuidList                = None
1209         self._ProtocolList            = None
1210         self._PpiList                 = None
1211         self._DepexList               = None
1212         self._BuildOption             = None
1213
1214         return True
1215
1216
1217     ## Return the module build data object
1218     def _GetModule(self):
1219         if self._Module == None:
1220             self._Module = self.Workspace.BuildDatabase[self._MetaFile, self.Arch]
1221         return self._Module
1222
1223     ## Return the module name
1224     def _GetBaseName(self):
1225         return self.Module.BaseName
1226
1227     ## Return the module meta-file GUID
1228     def _GetGuid(self):
1229         return self.Module.Guid
1230
1231     ## Return the module version
1232     def _GetVersion(self):
1233         return self.Module.Version
1234
1235     ## Return the module type
1236     def _GetModuleType(self):
1237         return self.Module.ModuleType
1238
1239     ## Return the component type (for R8.x style of module)
1240     def _GetComponentType(self):
1241         return self.Module.ComponentType
1242
1243     ## Return the PCD_IS_DRIVER setting
1244     def _GetPcdIsDriver(self):
1245         return self.Module.PcdIsDriver
1246
1247     ## Return the autogen version, i.e. module meta-file version
1248     def _GetAutoGenVersion(self):
1249         return self.Module.AutoGenVersion
1250
1251     ## Check if the module is library or not
1252     def _IsLibrary(self):
1253         if self._LibraryFlag == None:
1254             if self.Module.LibraryClass != None and self.Module.LibraryClass != []:
1255                 self._LibraryFlag = True
1256             else:
1257                 self._LibraryFlag = False
1258         return self._LibraryFlag
1259
1260     ## Return the directory to store intermediate files of the module
1261     def _GetBuildDir(self):
1262         if self._BuildDir == None:
1263             self._BuildDir = path.join(
1264                                     self.PlatformInfo.BuildDir,
1265                                     self.Arch,
1266                                     self.SourceDir,
1267                                     self.FileBase
1268                                     )
1269         return self._BuildDir
1270
1271     ## Return the directory to store the intermediate object files of the mdoule
1272     def _GetOutputDir(self):
1273         if self._OutputDir == None:
1274             self._OutputDir = path.join(self.BuildDir, "OUTPUT")
1275         return self._OutputDir
1276
1277     ## Return the directory to store auto-gened source files of the mdoule
1278     def _GetDebugDir(self):
1279         if self._DebugDir == None:
1280             self._DebugDir = path.join(self.BuildDir, "DEBUG")
1281         return self._DebugDir
1282
1283     ## Return the path of custom file
1284     def _GetCustomMakefile(self):
1285         if self._CustomMakefile == None:
1286             self._CustomMakefile = {}
1287             for Type in self.Module.CustomMakefile:
1288                 if Type in gMakeTypeMap:
1289                     MakeType = gMakeTypeMap[Type]
1290                 else:
1291                     MakeType = 'nmake'
1292                 self._CustomMakefile[MakeType] = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
1293         return self._CustomMakefile
1294
1295     ## Return the directory of the makefile
1296     #
1297     #   @retval     string  The directory string of module's makefile
1298     #
1299     def _GetMakeFileDir(self):
1300         return self.BuildDir
1301
1302     ## Return build command string
1303     #
1304     #   @retval     string  Build command string
1305     #
1306     def _GetBuildCommand(self):
1307         return self.PlatformInfo.BuildCommand
1308
1309     ## Get object list of all packages the module and its dependent libraries belong to
1310     #
1311     #   @retval     list    The list of package object
1312     #
1313     def _GetDerivedPackageList(self):
1314         PackageList = []
1315         for M in [self.Module] + self.DependentLibraryList:
1316             for Package in M.Packages:
1317                 if Package in PackageList:
1318                     continue
1319                 PackageList.append(Package)
1320         return PackageList
1321
1322     ## Merge dependency expression
1323     #
1324     #   @retval     list    The token list of the dependency expression after parsed
1325     #
1326     def _GetDepexTokenList(self):
1327         if self._DepexList == None:
1328             self._DepexList = self.Module.Depex
1329             EdkLogger.verbose("DEPEX = %s" % self._DepexList)
1330             #
1331             # Append depex from dependent libraries
1332             #
1333             for Lib in self.DependentLibraryList:
1334                 if Lib.Depex != None and Lib.Depex != []:
1335                     if self._DepexList != []:
1336                         self._DepexList.append('AND')
1337                     self._DepexList.append('(')
1338                     self._DepexList.extend(Lib.Depex)
1339                     self._DepexList.append(')')
1340                     EdkLogger.verbose("DEPEX (+%s) = %s" % (Lib.BaseName, self._DepexList))
1341
1342             for I in range(0, len(self._DepexList)):
1343                 Token = self._DepexList[I]
1344                 if Token.endswith(".inf"):  # module file name
1345                     ModuleFile = os.path.normpath(Token)
1346                     self._DepexList[I] = self.BuildDatabase[ModuleFile].Guid
1347         return self._DepexList
1348
1349     ## Return the list of macro in module
1350     #
1351     #   @retval     list    The list of macro defined in module file
1352     #
1353     def _GetMacroList(self):
1354         return self.Module.Specification
1355
1356     ## Tool option for the module build
1357     #
1358     #   @param      PlatformInfo    The object of PlatformBuildInfo
1359     #   @retval     dict            The dict containing valid options
1360     #
1361     def _GetModuleBuildOption(self):
1362         if self._BuildOption == None:
1363             self._BuildOption = self.PlatformInfo.ApplyBuildOption(self.Module)
1364         return self._BuildOption
1365
1366     ## Return a list of files which can be built from source
1367     #
1368     #  What kind of files can be built is determined by build rules in
1369     #  $(WORKSPACE)/Conf/build_rule.txt and toolchain family.
1370     #
1371     def _GetSourceFileList(self):
1372         if self._SourceFileList != None:
1373             return self._SourceFileList
1374
1375         self._SourceFileList = []
1376         self._UnicodeFileList = []
1377         # use toolchain family of CC as the primary toolchain family
1378         if "CC" not in self.PlatformInfo.ToolChainFamily:
1379             EdkLogger.error("build", AUTOGEN_ERROR, "Tool [CC] is not defined for %s [%s, %s]" \
1380                              % (self.ToolChain, self.BuildTarget, self.Arch),
1381                             ExtraData="[%s]" % self._MetaFile)
1382         ToolChainFamily = self.PlatformInfo.ToolChainFamily["CC"]
1383         BuildRule = self.PlatformInfo.BuildRule
1384         for F in self.Module.Sources:
1385             SourceFile = F.SourceFile
1386             # match tool chain
1387             if F.TagName != "" and F.TagName != self.ToolChain:
1388                 EdkLogger.verbose("The toolchain [%s] for processing file [%s] is found, "
1389                                   "but [%s] is needed" % (F.TagName, F.SourceFile, self.ToolChain))
1390                 continue
1391             # match tool chain family
1392             if F.ToolChainFamily != "" and F.ToolChainFamily != ToolChainFamily:
1393                 EdkLogger.debug(EdkLogger.DEBUG_0, "The file [%s] must be built by tools of [%s], "
1394                                 "but current toolchain family is [%s]" % (SourceFile, F.ToolChainFamily, ToolChainFamily))
1395                 continue
1396
1397             # add the file path into search path list for file including
1398             Dir = path.dirname(SourceFile)
1399             if Dir != "":
1400                 Dir = path.join(self.WorkspaceDir, self.SourceDir, Dir)
1401                 if Dir not in self.IncludePathList:
1402                     self.IncludePathList.insert(0, Dir)
1403
1404             # skip unknown file
1405             Base, Ext = path.splitext(SourceFile)
1406
1407             # skip file which needs a tool having no matching toolchain family
1408             FileType, RuleObject = BuildRule.Get(Ext, ToolChainFamily)
1409             # unicode must be processed by AutoGen
1410             if FileType == "Unicode-Text-File":
1411                 self._UnicodeFileList.append(os.path.join(self.WorkspaceDir, self.SourceDir, SourceFile))
1412
1413             # if there's dxs file, don't use content in [depex] section to generate .depex file
1414             if FileType == "Dependency-Expression-File":
1415                 self._DepexList = []
1416
1417             # no command, no build
1418             if RuleObject != None and RuleObject.CommandList == []:
1419                 RuleObject = None
1420             if [SourceFile, FileType, RuleObject] not in self._SourceFileList:
1421                 self._SourceFileList.append([SourceFile, FileType, RuleObject])
1422
1423         return self._SourceFileList
1424
1425     ## Return the list of unicode files
1426     def _GetUnicodeFileList(self):
1427         if self._UnicodeFileList == None:
1428             self._GetSourceFileList()
1429         return self._UnicodeFileList
1430
1431     ## Return a list of files which can be built from binary
1432     #
1433     #  "Build" binary files are just to copy them to build directory.
1434     #
1435     #   @retval     list            The list of files which can be built later
1436     #
1437     def _GetBinaryFiles(self):
1438         if self._BinaryFileDict == None:
1439             self._BinaryFileDict = sdict()
1440             for F in self.Module.Binaries:
1441                 if F.Target != '*' and F.Target != self.BuildTarget:
1442                     continue
1443                 if F.FileType not in self._BinaryFileDict:
1444                     self._BinaryFileDict[F.FileType] = []
1445                 self._BinaryFileDict[F.FileType].append(F.BinaryFile)
1446         return self._BinaryFileDict
1447
1448     ## Get the list of package object the module depends on
1449     #
1450     #   @retval     list    The package object list
1451     #
1452     def _GetDependentPackageList(self):
1453         return self.Module.Packages
1454
1455     ## Return the list of auto-generated code file
1456     #
1457     #   @retval     list        The list of auto-generated file
1458     #
1459     def _GetAutoGenFileList(self):
1460         if self._AutoGenFileList == None:
1461             self._AutoGenFileList = {}
1462             AutoGenC = TemplateString()
1463             AutoGenH = TemplateString()
1464             GenC.CreateCode(self, AutoGenC, AutoGenH)
1465             if str(AutoGenC) != "":
1466                 self._AutoGenFileList[gAutoGenCodeFileName] = AutoGenC
1467             if str(AutoGenH) != "":
1468                 self._AutoGenFileList[gAutoGenHeaderFileName] = AutoGenH
1469         return self._AutoGenFileList
1470
1471     ## Return the list of library modules explicitly or implicityly used by this module
1472     def _GetLibraryList(self):
1473         if self._DependentLibraryList == None:
1474             # only merge library classes and PCD for non-library module
1475             if self.IsLibrary:
1476                 self._DependentLibraryList = []
1477             else:
1478                 if self.AutoGenVersion < 0x00010005:
1479                     self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)
1480                 else:
1481                     self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)
1482         return self._DependentLibraryList
1483
1484     ## Get the list of PCD
1485     #
1486     #   @retval     list                    The list of PCD
1487     #
1488     def _GetPcdList(self):
1489         if self._PcdList == None:
1490             if not self.IsLibrary:
1491                 # derive PCDs from libraries first
1492                 for Library in self.DependentLibraryList:
1493                     for Key in Library.Pcds:
1494                         if Key in self.Module.Pcds:
1495                             continue
1496                         self.Module.Pcds[Key] = copy.copy(Library.Pcds[Key])
1497                 # apply PCD settings from platform
1498             self._PcdList = self.PlatformInfo.ApplyPcdSetting(self.Module)
1499         return self._PcdList
1500
1501     ## Get the GUID value mapping
1502     #
1503     #   @retval     dict    The mapping between GUID cname and its value
1504     #
1505     def _GetGuidList(self):
1506         if self._GuidList == None:
1507             self._GuidList = self.Module.Guids
1508             for Library in self.DependentLibraryList:
1509                 self._GuidList.update(Library.Guids)
1510         return self._GuidList
1511
1512     ## Get the protocol value mapping
1513     #
1514     #   @retval     dict    The mapping between protocol cname and its value
1515     #
1516     def _GetProtocolList(self):
1517         if self._ProtocolList == None:
1518             self._ProtocolList = self.Module.Protocols
1519             for Library in self.DependentLibraryList:
1520                 self._ProtocolList.update(Library.Protocols)
1521         return self._ProtocolList
1522
1523     ## Get the PPI value mapping
1524     #
1525     #   @retval     dict    The mapping between PPI cname and its value
1526     #
1527     def _GetPpiList(self):
1528         if self._PpiList == None:
1529             self._PpiList = self.Module.Ppis
1530             for Library in self.DependentLibraryList:
1531                 self._PpiList.update(Library.Ppis)
1532         return self._PpiList
1533
1534     ## Get the list of include search path
1535     #
1536     #   @retval     list                    The list path
1537     #
1538     def _GetIncludePathList(self):
1539         if self._IncludePathList == None:
1540             self._IncludePathList = []
1541             if self.AutoGenVersion < 0x00010005:
1542                 for Inc in self.Module.Includes:
1543                     # '.' means "relative to module directory".
1544                     if Inc[0] == ".":
1545                         Inc = path.join(self.WorkspaceDir, self.SourceDir, Inc)
1546                     else:
1547                         Inc = path.join(self.WorkspaceDir, Inc)
1548                     if Inc in self._IncludePathList:
1549                         continue
1550                     self._IncludePathList.append(Inc)
1551                     # for r8 modules
1552                     self._IncludePathList.append(path.join(Inc, self.Arch.capitalize()))
1553                 # r8 module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
1554                 self._IncludePathList.append(self.DebugDir)
1555             else:
1556                 self._IncludePathList.append(os.path.join(self.WorkspaceDir, self.SourceDir))
1557                 self._IncludePathList.append(self.DebugDir)
1558
1559             for Package in self.Module.Packages:
1560                 PackageDir = path.join(self.WorkspaceDir, path.dirname(str(Package)))
1561                 if PackageDir not in self._IncludePathList:
1562                     self._IncludePathList.append(PackageDir)
1563                 for Inc in Package.Includes:
1564                     Inc = path.join(PackageDir, Inc)
1565                     if Inc not in self._IncludePathList:
1566                         self._IncludePathList.append(Inc)
1567         return self._IncludePathList
1568
1569     ## Create makefile for the module and its dependent libraries
1570     #
1571     #   @param      CreateLibraryMakeFile   Flag indicating if or not the makefiles of
1572     #                                       dependent libraries will be created
1573     #
1574     def CreateMakeFile(self, CreateLibraryMakeFile=True):
1575         if self.IsMakeFileCreated:
1576             return
1577
1578         PlatformInfo = self.PlatformInfo
1579         if not self.IsLibrary and CreateLibraryMakeFile:
1580             for LibraryAutoGen in self.LibraryAutoGenList:
1581                 LibraryAutoGen.CreateMakeFile()
1582
1583         if len(self.CustomMakefile) == 0:
1584             Makefile = GenMake.ModuleMakefile(self)
1585         else:
1586             Makefile = GenMake.CustomMakefile(self)
1587         if Makefile.Generate():
1588             EdkLogger.verbose("Generated makefile for module %s [%s]" %
1589                            (self.Name, self.Arch))
1590         else:
1591             EdkLogger.verbose("Skipped the generation of makefile for module %s [%s]" %
1592                               (self.Name, self.Arch))
1593
1594         self.IsMakeFileCreated = True
1595
1596     ## Create autogen code for the module and its dependent libraries
1597     #
1598     #   @param      CreateLibraryCodeFile   Flag indicating if or not the code of
1599     #                                       dependent libraries will be created
1600     #
1601     def CreateCodeFile(self, CreateLibraryCodeFile=True):
1602         if self.IsCodeFileCreated:
1603             return
1604
1605         PlatformInfo = self.PlatformInfo
1606         if not self.IsLibrary and CreateLibraryCodeFile:
1607             for LibraryAutoGen in self.LibraryAutoGenList:
1608                 LibraryAutoGen.CreateCodeFile()
1609
1610         AutoGenList = []
1611         IgoredAutoGenList = []
1612         for File in self.AutoGenFileList:
1613             if GenC.Generate(path.join(self.DebugDir, File), str(self.AutoGenFileList[File])):
1614                 AutoGenList.append(File)
1615             else:
1616                 IgoredAutoGenList.append(File)
1617
1618         if self.DepexList != []:
1619             Dpx = GenDepex.DependencyExpression(self.DepexList, self.ModuleType, True)
1620             DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
1621
1622             if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
1623                 AutoGenList.append(DpxFile)
1624             else:
1625                 IgoredAutoGenList.append(DpxFile)
1626
1627         if IgoredAutoGenList == []:
1628             EdkLogger.verbose("Generated [%s] files for module %s [%s]" %
1629                            (" ".join(AutoGenList), self.Name, self.Arch))
1630         elif AutoGenList == []:
1631             EdkLogger.verbose("Skipped the generation of [%s] files for module %s [%s]" %
1632                            (" ".join(IgoredAutoGenList), self.Name, self.Arch))
1633         else:
1634             EdkLogger.verbose("Generated [%s] (skipped %s) files for module %s [%s]" %
1635                            (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
1636
1637         self.IsCodeFileCreated = True
1638         return AutoGenList
1639
1640     ## Summarize the ModuleAutoGen objects of all libraries used by this module
1641     def _GetLibraryAutoGenList(self):
1642         if self._LibraryAutoGenList == None:
1643             self._LibraryAutoGenList = []
1644             for Library in self.DependentLibraryList:
1645                 La = ModuleAutoGen(
1646                         self.Workspace,
1647                         str(Library),
1648                         self.BuildTarget,
1649                         self.ToolChain,
1650                         self.Arch,
1651                         str(self.PlatformInfo)
1652                         )
1653                 if La not in self._LibraryAutoGenList:
1654                     self._LibraryAutoGenList.append(La)
1655         return self._LibraryAutoGenList
1656
1657     ## Return build command string
1658     #
1659     #   @retval     string  Build command string
1660     #
1661     def _GetBuildCommand(self):
1662         return self.PlatformInfo.BuildCommand
1663
1664
1665     Module          = property(_GetModule)
1666     Name            = property(_GetBaseName)
1667     Guid            = property(_GetGuid)
1668     Version         = property(_GetVersion)
1669     ModuleType      = property(_GetModuleType)
1670     ComponentType   = property(_GetComponentType)
1671     PcdIsDriver     = property(_GetPcdIsDriver)
1672     AutoGenVersion  = property(_GetAutoGenVersion)
1673     Macro           = property(_GetMacroList)
1674
1675     IsLibrary       = property(_IsLibrary)
1676
1677     BuildDir        = property(_GetBuildDir)
1678     OutputDir       = property(_GetOutputDir)
1679     DebugDir        = property(_GetDebugDir)
1680     MakeFileDir     = property(_GetMakeFileDir)
1681     CustomMakefile  = property(_GetCustomMakefile)
1682
1683     IncludePathList = property(_GetIncludePathList)
1684     AutoGenFileList = property(_GetAutoGenFileList)
1685     UnicodeFileList = property(_GetUnicodeFileList)
1686     SourceFileList  = property(_GetSourceFileList)
1687     BinaryFileDict  = property(_GetBinaryFiles) # FileType : [File List]
1688
1689     DependentPackageList    = property(_GetDependentPackageList)
1690     DependentLibraryList    = property(_GetLibraryList)
1691     LibraryAutoGenList      = property(_GetLibraryAutoGenList)
1692     DerivedPackageList      = property(_GetDerivedPackageList)
1693
1694     PcdList                 = property(_GetPcdList)
1695     GuidList                = property(_GetGuidList)
1696     ProtocolList            = property(_GetProtocolList)
1697     PpiList                 = property(_GetPpiList)
1698     DepexList               = property(_GetDepexTokenList)
1699     BuildOption             = property(_GetModuleBuildOption)
1700     BuildCommand            = property(_GetBuildCommand)
1701
1702 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1703 if __name__ == '__main__':
1704     pass
1705