BUILDRULEFAMILY supports BuildOptions in INF and DSC.
[efi/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 os
17 import re
18 import os.path as path
19 import copy
20
21 import GenC
22 import GenMake
23 import GenDepex
24
25 from StrGather import *
26 from BuildEngine import BuildRule
27
28 from Common.BuildToolError import *
29 from Common.DataType import *
30 from Common.Misc import *
31 from Common.String import *
32 import Common.GlobalData as GlobalData
33 from GenFds.FdfParser import *
34 from CommonDataClass.CommonClass import SkuInfoClass
35 from Workspace.BuildClassObject import *
36
37 ## Regular expression for splitting Dependency Expression stirng into tokens
38 gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")
39
40 ## Mapping Makefile type
41 gMakeTypeMap = {"MSFT":"nmake", "GCC":"gmake"}
42
43
44 ## Build rule configuration file
45 gBuildRuleFile = 'Conf/build_rule.txt'
46
47 ## default file name for AutoGen
48 gAutoGenCodeFileName = "AutoGen.c"
49 gAutoGenHeaderFileName = "AutoGen.h"
50 gAutoGenStringFileName = "%(module_name)sStrDefs.h"
51 gAutoGenDepexFileName = "%(module_name)s.depex"
52 gAutoGenSmmDepexFileName = "%(module_name)s.smm"
53
54 ## Base class for AutoGen
55 #
56 #   This class just implements the cache mechanism of AutoGen objects.
57 #
58 class AutoGen(object):
59     # database to maintain the objects of xxxAutoGen
60     _CACHE_ = {}    # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
61
62     ## Factory method
63     #
64     #   @param  Class           class object of real AutoGen class
65     #                           (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
66     #   @param  Workspace       Workspace directory or WorkspaceAutoGen object
67     #   @param  MetaFile        The path of meta file
68     #   @param  Target          Build target
69     #   @param  Toolchain       Tool chain name
70     #   @param  Arch            Target arch
71     #   @param  *args           The specific class related parameters
72     #   @param  **kwargs        The specific class related dict parameters
73     #
74     def __new__(Class, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
75         # check if the object has been created
76         Key = (Target, Toolchain)
77         if Key not in Class._CACHE_ or Arch not in Class._CACHE_[Key] \
78            or MetaFile not in Class._CACHE_[Key][Arch]:
79             AutoGenObject = super(AutoGen, Class).__new__(Class)
80             # call real constructor
81             if not AutoGenObject._Init(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
82                 return None
83             if Key not in Class._CACHE_:
84                 Class._CACHE_[Key] = {}
85             if Arch not in Class._CACHE_[Key]:
86                 Class._CACHE_[Key][Arch] = {}
87             Class._CACHE_[Key][Arch][MetaFile] = AutoGenObject
88         else:
89             AutoGenObject = Class._CACHE_[Key][Arch][MetaFile]
90
91         return AutoGenObject
92
93     ## hash() operator
94     #
95     #  The file path of platform file will be used to represent hash value of this object
96     #
97     #   @retval int     Hash value of the file path of platform file
98     #
99     def __hash__(self):
100         return hash(self.MetaFile)
101
102     ## str() operator
103     #
104     #  The file path of platform file will be used to represent this object
105     #
106     #   @retval string  String of platform file path
107     #
108     def __str__(self):
109         return str(self.MetaFile)
110
111     ## "==" operator
112     def __eq__(self, Other):
113         return Other and self.MetaFile == Other
114
115 ## Workspace AutoGen class
116 #
117 #   This class is used mainly to control the whole platform build for different
118 # architecture. This class will generate top level makefile.
119 #
120 class WorkspaceAutoGen(AutoGen):
121     ## Real constructor of WorkspaceAutoGen
122     #
123     # This method behaves the same as __init__ except that it needs explict invoke
124     # (in super class's __new__ method)
125     #
126     #   @param  WorkspaceDir            Root directory of workspace
127     #   @param  ActivePlatform          Meta-file of active platform
128     #   @param  Target                  Build target
129     #   @param  Toolchain               Tool chain name
130     #   @param  ArchList                List of architecture of current build
131     #   @param  MetaFileDb              Database containing meta-files
132     #   @param  BuildConfig             Configuration of build
133     #   @param  ToolDefinition          Tool chain definitions
134     #   @param  FlashDefinitionFile     File of flash definition
135     #   @param  Fds                     FD list to be generated
136     #   @param  Fvs                     FV list to be generated
137     #   @param  SkuId                   SKU id from command line
138     #
139     def _Init(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb,
140               BuildConfig, ToolDefinition, FlashDefinitionFile='', Fds=[], Fvs=[], SkuId=''):
141         self.MetaFile       = ActivePlatform.MetaFile
142         self.WorkspaceDir   = WorkspaceDir
143         self.Platform       = ActivePlatform
144         self.BuildTarget    = Target
145         self.ToolChain      = Toolchain
146         self.ArchList       = ArchList
147         self.SkuId          = SkuId
148
149         self.BuildDatabase  = MetaFileDb
150         self.TargetTxt      = BuildConfig
151         self.ToolDef        = ToolDefinition
152         self.FdfFile        = FlashDefinitionFile
153         self.FdTargetList   = Fds
154         self.FvTargetList   = Fvs
155         self.AutoGenObjectList = []
156
157         # there's many relative directory operations, so ...
158         os.chdir(self.WorkspaceDir)
159
160         # parse FDF file to get PCDs in it, if any
161         if self.FdfFile != None and self.FdfFile != '':
162             Fdf = FdfParser(self.FdfFile.Path)
163             Fdf.ParseFile()
164             PcdSet = Fdf.Profile.PcdDict
165             ModuleList = Fdf.Profile.InfList
166         else:
167             PcdSet = {}
168             ModuleList = []
169
170         # apply SKU and inject PCDs from Flash Definition file
171         for Arch in self.ArchList:
172             Platform = self.BuildDatabase[self.MetaFile, Arch]
173             Platform.SkuName = self.SkuId
174             for Name, Guid in PcdSet:
175                 Platform.AddPcd(Name, Guid, PcdSet[Name, Guid])
176
177             Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)
178             #
179             # Explicitly collect platform's dynamic PCDs
180             #
181             Pa.CollectPlatformDynamicPcds()
182             self.AutoGenObjectList.append(Pa)
183
184         self._BuildDir = None
185         self._FvDir = None
186         self._MakeFileDir = None
187         self._BuildCommand = None
188
189         return True
190
191     def __repr__(self):
192         return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))
193
194     ## Return the directory to store FV files
195     def _GetFvDir(self):
196         if self._FvDir == None:
197             self._FvDir = path.join(self.BuildDir, 'FV')
198         return self._FvDir
199
200     ## Return the directory to store all intermediate and final files built
201     def _GetBuildDir(self):
202         return self.AutoGenObjectList[0].BuildDir
203
204     ## Return the build output directory platform specifies
205     def _GetOutputDir(self):
206         return self.Platform.OutputDirectory
207
208     ## Return platform name
209     def _GetName(self):
210         return self.Platform.PlatformName
211
212     ## Return meta-file GUID
213     def _GetGuid(self):
214         return self.Platform.Guid
215
216     ## Return platform version
217     def _GetVersion(self):
218         return self.Platform.Version
219
220     ## Return paths of tools
221     def _GetToolDefinition(self):
222         return self.AutoGenObjectList[0].ToolDefinition
223
224     ## Return directory of platform makefile
225     #
226     #   @retval     string  Makefile directory
227     #
228     def _GetMakeFileDir(self):
229         if self._MakeFileDir == None:
230             self._MakeFileDir = self.BuildDir
231         return self._MakeFileDir
232
233     ## Return build command string
234     #
235     #   @retval     string  Build command string
236     #
237     def _GetBuildCommand(self):
238         if self._BuildCommand == None:
239             # BuildCommand should be all the same. So just get one from platform AutoGen
240             self._BuildCommand = self.AutoGenObjectList[0].BuildCommand
241         return self._BuildCommand
242
243     ## Create makefile for the platform and mdoules in it
244     #
245     #   @param      CreateDepsMakeFile      Flag indicating if the makefile for
246     #                                       modules will be created as well
247     #
248     def CreateMakeFile(self, CreateDepsMakeFile=False):
249         # create makefile for platform
250         Makefile = GenMake.TopLevelMakefile(self)
251         if Makefile.Generate():
252             EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for platform [%s] %s\n" %
253                             (self.MetaFile, self.ArchList))
254         else:
255             EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for platform [%s] %s\n" %
256                             (self.MetaFile, self.ArchList))
257
258         if CreateDepsMakeFile:
259             for Pa in self.AutoGenObjectList:
260                 Pa.CreateMakeFile(CreateDepsMakeFile)
261
262     ## Create autogen code for platform and modules
263     #
264     #  Since there's no autogen code for platform, this method will do nothing
265     #  if CreateModuleCodeFile is set to False.
266     #
267     #   @param      CreateDepsCodeFile      Flag indicating if creating module's
268     #                                       autogen code file or not
269     #
270     def CreateCodeFile(self, CreateDepsCodeFile=False):
271         if not CreateDepsCodeFile:
272             return
273         for Pa in self.AutoGenObjectList:
274             Pa.CreateCodeFile(CreateDepsCodeFile)
275
276     Name                = property(_GetName)
277     Guid                = property(_GetGuid)
278     Version             = property(_GetVersion)
279     OutputDir           = property(_GetOutputDir)
280
281     ToolDefinition      = property(_GetToolDefinition)       # toolcode : tool path
282
283     BuildDir            = property(_GetBuildDir)
284     FvDir               = property(_GetFvDir)
285     MakeFileDir         = property(_GetMakeFileDir)
286     BuildCommand        = property(_GetBuildCommand)
287
288 ## AutoGen class for platform
289 #
290 #  PlatformAutoGen class will process the original information in platform
291 #  file in order to generate makefile for platform.
292 #
293 class PlatformAutoGen(AutoGen):
294     #
295     # Used to store all PCDs for both PEI and DXE phase, in order to generate 
296     # correct PCD database
297     # 
298     _DynaPcdList_ = []
299     _NonDynaPcdList_ = []
300
301     ## The real constructor of PlatformAutoGen
302     #
303     #  This method is not supposed to be called by users of PlatformAutoGen. It's
304     #  only used by factory method __new__() to do real initialization work for an
305     #  object of PlatformAutoGen
306     #
307     #   @param      Workspace       WorkspaceAutoGen object
308     #   @param      PlatformFile    Platform file (DSC file)
309     #   @param      Target          Build target (DEBUG, RELEASE)
310     #   @param      Toolchain       Name of tool chain
311     #   @param      Arch            arch of the platform supports
312     #
313     def _Init(self, Workspace, PlatformFile, Target, Toolchain, Arch):
314         EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))
315         GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)
316
317         self.MetaFile = PlatformFile
318         self.Workspace = Workspace
319         self.WorkspaceDir = Workspace.WorkspaceDir
320         self.ToolChain = Toolchain
321         self.BuildTarget = Target
322         self.Arch = Arch
323         self.SourceDir = PlatformFile.SubDir
324         self.SourceOverrideDir = None
325         self.FdTargetList = self.Workspace.FdTargetList
326         self.FvTargetList = self.Workspace.FvTargetList
327
328         # flag indicating if the makefile/C-code file has been created or not
329         self.IsMakeFileCreated  = False
330         self.IsCodeFileCreated  = False
331
332         self._Platform   = None
333         self._Name       = None
334         self._Guid       = None
335         self._Version    = None
336
337         self._BuildRule = None
338         self._SourceDir = None
339         self._BuildDir = None
340         self._OutputDir = None
341         self._FvDir = None
342         self._MakeFileDir = None
343         self._FdfFile = None
344
345         self._PcdTokenNumber = None    # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
346         self._DynamicPcdList = None    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
347         self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
348
349         self._ToolDefinitions = None
350         self._ToolDefFile = None          # toolcode : tool path
351         self._ToolChainFamily = None
352         self._BuildRuleFamily = None
353         self._BuildOption = None          # toolcode : option
354         self._PackageList = None
355         self._ModuleAutoGenList  = None
356         self._LibraryAutoGenList = None
357         self._BuildCommand = None
358
359         # get the original module/package/platform objects
360         self.BuildDatabase = Workspace.BuildDatabase
361         return True
362
363     def __repr__(self):
364         return "%s [%s]" % (self.MetaFile, self.Arch)
365
366     ## Create autogen code for platform and modules
367     #
368     #  Since there's no autogen code for platform, this method will do nothing
369     #  if CreateModuleCodeFile is set to False.
370     #
371     #   @param      CreateModuleCodeFile    Flag indicating if creating module's
372     #                                       autogen code file or not
373     #
374     def CreateCodeFile(self, CreateModuleCodeFile=False):
375         # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
376         if self.IsCodeFileCreated or not CreateModuleCodeFile:
377             return
378
379         for Ma in self.ModuleAutoGenList:
380             Ma.CreateCodeFile(True)
381
382         # don't do this twice
383         self.IsCodeFileCreated = True
384
385     ## Create makefile for the platform and mdoules in it
386     #
387     #   @param      CreateModuleMakeFile    Flag indicating if the makefile for
388     #                                       modules will be created as well
389     #
390     def CreateMakeFile(self, CreateModuleMakeFile=False):
391         if CreateModuleMakeFile:
392             for ModuleFile in self.Platform.Modules:
393                 Ma = ModuleAutoGen(self.Workspace, ModuleFile, self.BuildTarget,
394                                    self.ToolChain, self.Arch, self.MetaFile)
395                 Ma.CreateMakeFile(True)
396
397         # no need to create makefile for the platform more than once
398         if self.IsMakeFileCreated:
399             return
400
401         # create makefile for platform
402         Makefile = GenMake.PlatformMakefile(self)
403         if Makefile.Generate():
404             EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for platform [%s] [%s]\n" %
405                             (self.MetaFile, self.Arch))
406         else:
407             EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for platform [%s] [%s]\n" %
408                             (self.MetaFile, self.Arch))
409         self.IsMakeFileCreated = True
410
411     ## Collect dynamic PCDs
412     #
413     #  Gather dynamic PCDs list from each module and their settings from platform
414     #  This interface should be invoked explicitly when platform action is created.
415     #
416     def CollectPlatformDynamicPcds(self):
417         # for gathering error information
418         NoDatumTypePcdList = set()
419
420         self._GuidValue = {}
421         for F in self.Platform.Modules.keys():
422             M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self.MetaFile)
423             #GuidValue.update(M.Guids)
424             for PcdFromModule in M.ModulePcdList+M.LibraryPcdList:
425                 # make sure that the "VOID*" kind of datum has MaxDatumSize set
426                 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize == None:
427                     NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, F))
428
429                 if PcdFromModule.Type in GenC.gDynamicPcd or PcdFromModule.Type in GenC.gDynamicExPcd:
430                     #
431                     # If a dynamic PCD used by a PEM module/PEI module & DXE module,
432                     # it should be stored in Pcd PEI database, If a dynamic only
433                     # used by DXE module, it should be stored in DXE PCD database.
434                     # The default Phase is DXE
435                     #
436                     if M.ModuleType in ["PEIM", "PEI_CORE"]:
437                         PcdFromModule.Phase = "PEI"
438                     if PcdFromModule not in self._DynaPcdList_:
439                         self._DynaPcdList_.append(PcdFromModule)
440                     elif PcdFromModule.Phase == 'PEI':
441                         # overwrite any the same PCD existing, if Phase is PEI
442                         Index = self._DynaPcdList_.index(PcdFromModule)
443                         self._DynaPcdList_[Index] = PcdFromModule
444                 elif PcdFromModule not in self._NonDynaPcdList_:
445                     self._NonDynaPcdList_.append(PcdFromModule)
446
447         # print out error information and break the build, if error found
448         if len(NoDatumTypePcdList) > 0:
449             NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)
450             EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
451                             File=self.MetaFile,
452                             ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
453                                       % NoDatumTypePcdListString)
454         self._NonDynamicPcdList = self._NonDynaPcdList_
455         self._DynamicPcdList = self._DynaPcdList_
456         
457         #
458         # Sort dynamic PCD list to:
459         # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should 
460         #    try to be put header of dynamicd List
461         # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
462         #
463         # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
464         #
465         UnicodePcdArray = []
466         HiiPcdArray     = []
467         OtherPcdArray   = []
468         for Pcd in self._DynamicPcdList:
469             # just pick the a value to determine whether is unicode string type
470             Sku      = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]
471             PcdValue = Sku.DefaultValue
472             if Pcd.DatumType == 'VOID*' and PcdValue.startswith("L"):
473                 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
474                 UnicodePcdArray.append(Pcd)
475             elif len(Sku.VariableName) > 0:
476                 # if found HII type PCD then insert to right of UnicodeIndex
477                 HiiPcdArray.append(Pcd)
478             else:
479                 OtherPcdArray.append(Pcd)
480         del self._DynamicPcdList[:]
481         self._DynamicPcdList.extend(UnicodePcdArray)
482         self._DynamicPcdList.extend(HiiPcdArray)
483         self._DynamicPcdList.extend(OtherPcdArray)
484             
485         
486     ## Return the platform build data object
487     def _GetPlatform(self):
488         if self._Platform == None:
489             self._Platform = self.BuildDatabase[self.MetaFile, self.Arch]
490         return self._Platform
491
492     ## Return platform name
493     def _GetName(self):
494         return self.Platform.PlatformName
495
496     ## Return the meta file GUID
497     def _GetGuid(self):
498         return self.Platform.Guid
499
500     ## Return the platform version
501     def _GetVersion(self):
502         return self.Platform.Version
503
504     ## Return the FDF file name
505     def _GetFdfFile(self):
506         if self._FdfFile == None:
507             if self.Workspace.FdfFile != "":
508                 self._FdfFile= path.join(self.WorkspaceDir, self.Workspace.FdfFile)
509             else:
510                 self._FdfFile = ''
511         return self._FdfFile
512
513     ## Return the build output directory platform specifies
514     def _GetOutputDir(self):
515         return self.Platform.OutputDirectory
516
517     ## Return the directory to store all intermediate and final files built
518     def _GetBuildDir(self):
519         if self._BuildDir == None:
520             if os.path.isabs(self.OutputDir):
521                 self._BuildDir = path.join(
522                                             path.abspath(self.OutputDir),
523                                             self.BuildTarget + "_" + self.ToolChain,
524                                             )
525             else:
526                 self._BuildDir = path.join(
527                                             self.WorkspaceDir,
528                                             self.OutputDir,
529                                             self.BuildTarget + "_" + self.ToolChain,
530                                             )
531         return self._BuildDir
532
533     ## Return directory of platform makefile
534     #
535     #   @retval     string  Makefile directory
536     #
537     def _GetMakeFileDir(self):
538         if self._MakeFileDir == None:
539             self._MakeFileDir = path.join(self.BuildDir, self.Arch)
540         return self._MakeFileDir
541
542     ## Return build command string
543     #
544     #   @retval     string  Build command string
545     #
546     def _GetBuildCommand(self):
547         if self._BuildCommand == None:
548             self._BuildCommand = []
549             if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
550                 self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"])
551                 if "FLAGS" in self.ToolDefinition["MAKE"]:
552                     NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
553                     if NewOption != '':
554                       self._BuildCommand += SplitOption(NewOption)
555         return self._BuildCommand
556
557     ## Get tool chain definition
558     #
559     #  Get each tool defition for given tool chain from tools_def.txt and platform
560     #
561     def _GetToolDefinition(self):
562         if self._ToolDefinitions == None:
563             ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
564             if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:
565                 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",
566                                 ExtraData="[%s]" % self.MetaFile)
567             self._ToolDefinitions = {}
568             DllPathList = set()
569             for Def in ToolDefinition:
570                 Target, Tag, Arch, Tool, Attr = Def.split("_")
571                 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:
572                     continue
573
574                 Value = ToolDefinition[Def]
575                 # don't record the DLL
576                 if Attr == "DLL":
577                     DllPathList.add(Value)
578                     continue
579
580                 if Tool not in self._ToolDefinitions:
581                     self._ToolDefinitions[Tool] = {}
582                 self._ToolDefinitions[Tool][Attr] = Value
583
584             ToolsDef = ''
585             MakePath = ''
586             if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions:
587                 if "FLAGS" not in self._ToolDefinitions["MAKE"]:
588                     self._ToolDefinitions["MAKE"]["FLAGS"] = ""
589                 self._ToolDefinitions["MAKE"]["FLAGS"] += " -s"
590             MakeFlags = ''
591             for Tool in self._ToolDefinitions:
592                 for Attr in self._ToolDefinitions[Tool]:
593                     Value = self._ToolDefinitions[Tool][Attr]
594                     if Tool in self.BuildOption and Attr in self.BuildOption[Tool]:
595                         # check if override is indicated
596                         if self.BuildOption[Tool][Attr].startswith('='):
597                             Value = self.BuildOption[Tool][Attr][1:]
598                         else:
599                             Value += " " + self.BuildOption[Tool][Attr]
600
601                     if Attr == "PATH":
602                         # Don't put MAKE definition in the file
603                         if Tool == "MAKE":
604                             MakePath = Value
605                         else:
606                             ToolsDef += "%s = %s\n" % (Tool, Value)
607                     elif Attr != "DLL":
608                         # Don't put MAKE definition in the file
609                         if Tool == "MAKE":
610                             if Attr == "FLAGS":
611                                 MakeFlags = Value
612                         else:
613                             ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
614                 ToolsDef += "\n"
615
616             SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)
617             for DllPath in DllPathList:
618                 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]
619             os.environ["MAKE_FLAGS"] = MakeFlags
620
621         return self._ToolDefinitions
622
623     ## Return the paths of tools
624     def _GetToolDefFile(self):
625         if self._ToolDefFile == None:
626             self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
627         return self._ToolDefFile
628
629     ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
630     def _GetToolChainFamily(self):
631         if self._ToolChainFamily == None:
632             ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
633             if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
634                or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
635                or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:
636                 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
637                                    % self.ToolChain)
638                 self._ToolChainFamily = "MSFT"
639             else:
640                 self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]
641         return self._ToolChainFamily
642
643     def _GetBuildRuleFamily(self):
644         if self._BuildRuleFamily == None:
645             ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
646             if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
647                or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \
648                or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:
649                 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
650                                    % self.ToolChain)
651                 self._BuildRuleFamily = "MSFT"
652             else:
653                 self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]
654         return self._BuildRuleFamily
655
656     ## Return the build options specific to this platform
657     def _GetBuildOptions(self):
658         if self._BuildOption == None:
659             self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)
660         return self._BuildOption
661
662     ## Parse build_rule.txt in $(WORKSPACE)/Conf/build_rule.txt
663     #
664     #   @retval     BuildRule object
665     #
666     def _GetBuildRule(self):
667         if self._BuildRule == None:
668             BuildRuleFile = None
669             if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:
670                 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
671             if BuildRuleFile in [None, '']:
672                 BuildRuleFile = gBuildRuleFile
673             self._BuildRule = BuildRule(BuildRuleFile)
674         return self._BuildRule
675
676     ## Summarize the packages used by modules in this platform
677     def _GetPackageList(self):
678         if self._PackageList == None:
679             self._PackageList = set()
680             for La in self.LibraryAutoGenList:
681                 self._PackageList.update(La.DependentPackageList)
682             for Ma in self.ModuleAutoGenList:
683                 self._PackageList.update(Ma.DependentPackageList)
684             self._PackageList = list(self._PackageList)
685         return self._PackageList
686
687     ## Get list of non-dynamic PCDs
688     def _GetNonDynamicPcdList(self):
689         return self._NonDynamicPcdList
690
691     ## Get list of dynamic PCDs
692     def _GetDynamicPcdList(self):
693         return self._DynamicPcdList
694
695     ## Generate Token Number for all PCD
696     def _GetPcdTokenNumbers(self):
697         if self._PcdTokenNumber == None:
698             self._PcdTokenNumber = sdict()
699             TokenNumber = 1
700             for Pcd in self.DynamicPcdList:
701                 if Pcd.Phase == "PEI":
702                     EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
703                     self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
704                     TokenNumber += 1
705
706             for Pcd in self.DynamicPcdList:
707                 if Pcd.Phase == "DXE":
708                     EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
709                     self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
710                     TokenNumber += 1
711
712             for Pcd in self.NonDynamicPcdList:
713                 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
714                 TokenNumber += 1
715         return self._PcdTokenNumber
716
717     ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
718     def _GetAutoGenObjectList(self):
719         self._ModuleAutoGenList = []
720         self._LibraryAutoGenList = []
721         for ModuleFile in self.Platform.Modules:
722             Ma = ModuleAutoGen(
723                     self.Workspace,
724                     ModuleFile,
725                     self.BuildTarget,
726                     self.ToolChain,
727                     self.Arch,
728                     self.MetaFile
729                     )
730             if Ma not in self._ModuleAutoGenList:
731                 self._ModuleAutoGenList.append(Ma)
732             for La in Ma.LibraryAutoGenList:
733                 if La not in self._LibraryAutoGenList:
734                     self._LibraryAutoGenList.append(La)
735
736     ## Summarize ModuleAutoGen objects of all modules to be built for this platform
737     def _GetModuleAutoGenList(self):
738         if self._ModuleAutoGenList == None:
739             self._GetAutoGenObjectList()
740         return self._ModuleAutoGenList
741
742     ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
743     def _GetLibraryAutoGenList(self):
744         if self._LibraryAutoGenList == None:
745             self._GetAutoGenObjectList()
746         return self._LibraryAutoGenList
747
748     ## Test if a module is supported by the platform
749     #
750     #  An error will be raised directly if the module or its arch is not supported
751     #  by the platform or current configuration
752     #
753     def ValidModule(self, Module):
754         return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances
755
756     ## Resolve the library classes in a module to library instances
757     #
758     # This method will not only resolve library classes but also sort the library
759     # instances according to the dependency-ship.
760     #
761     #   @param  Module      The module from which the library classes will be resolved
762     #
763     #   @retval library_list    List of library instances sorted
764     #
765     def ApplyLibraryInstance(self, Module):
766         ModuleType = Module.ModuleType
767
768         # for overridding library instances with module specific setting
769         PlatformModule = self.Platform.Modules[str(Module)]
770
771         # add forced library instance
772         for LibraryClass in PlatformModule.LibraryClasses:
773             if LibraryClass.startswith("NULL"):
774                 Module.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]
775
776         # R9 module
777         LibraryConsumerList = [Module]
778         Constructor         = []
779         ConsumedByList      = sdict()
780         LibraryInstance     = sdict()
781
782         EdkLogger.verbose("")
783         EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
784         while len(LibraryConsumerList) > 0:
785             M = LibraryConsumerList.pop()
786             for LibraryClassName in M.LibraryClasses:
787                 if LibraryClassName not in LibraryInstance:
788                     # override library instance for this module
789                     if LibraryClassName in PlatformModule.LibraryClasses:
790                         LibraryPath = PlatformModule.LibraryClasses[LibraryClassName]
791                     else:
792                         LibraryPath = self.Platform.LibraryClasses[LibraryClassName, ModuleType]
793                     if LibraryPath == None or LibraryPath == "":
794                         LibraryPath = M.LibraryClasses[LibraryClassName]
795                         if LibraryPath == None or LibraryPath == "":
796                             EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,
797                                             "Instance of library class [%s] is not found" % LibraryClassName,
798                                             File=self.MetaFile,
799                                             ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), self.Arch, str(Module)))
800
801                     LibraryModule = self.BuildDatabase[LibraryPath, self.Arch]
802                     # for those forced library instance (NULL library), add a fake library class
803                     if LibraryClassName.startswith("NULL"):
804                         LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType]))
805                     elif LibraryModule.LibraryClass == None \
806                          or len(LibraryModule.LibraryClass) == 0 \
807                          or (ModuleType != 'USER_DEFINED'
808                              and ModuleType not in LibraryModule.LibraryClass[0].SupModList):
809                         # only USER_DEFINED can link against any library instance despite of its 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             # check the validation of datum
949             IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)
950             if not IsValid:
951                 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
952                                 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))
953
954         if ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]:
955             EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \
956                             % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))
957             Value = ToPcd.DefaultValue
958             if Value in [None, '']:
959                 ToPcd.MaxDatumSize = 1
960             elif Value[0] == 'L':
961                 ToPcd.MaxDatumSize = str(len(Value) * 2)
962             elif Value[0] == '{':
963                 ToPcd.MaxDatumSize = str(len(Value.split(',')))
964             else:
965                 ToPcd.MaxDatumSize = str(len(Value))
966
967         # apply default SKU for dynamic PCDS if specified one is not available
968         if (ToPcd.Type in PCD_DYNAMIC_TYPE_LIST or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_LIST) \
969             and ToPcd.SkuInfoList in [None, {}, '']:
970             if self.Platform.SkuName in self.Platform.SkuIds:
971                 SkuName = self.Platform.SkuName
972             else:
973                 SkuName = 'DEFAULT'
974             ToPcd.SkuInfoList = {
975                 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName], '', '', '', '', '', ToPcd.DefaultValue)
976             }
977
978     ## Apply PCD setting defined platform to a module
979     #
980     #   @param  Module  The module from which the PCD setting will be overrided
981     #
982     #   @retval PCD_list    The list PCDs with settings from platform
983     #
984     def ApplyPcdSetting(self, Module, Pcds):
985         # for each PCD in module
986         for Name,Guid in Pcds:
987             PcdInModule = Pcds[Name,Guid]
988             # find out the PCD setting in platform
989             if (Name,Guid) in self.Platform.Pcds:
990                 PcdInPlatform = self.Platform.Pcds[Name,Guid]
991             else:
992                 PcdInPlatform = None
993             # then override the settings if any
994             self._OverridePcd(PcdInModule, PcdInPlatform, Module)
995             # resolve the VariableGuid value
996             for SkuId in PcdInModule.SkuInfoList:
997                 Sku = PcdInModule.SkuInfoList[SkuId]
998                 if Sku.VariableGuid == '': continue
999                 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList)
1000                 if Sku.VariableGuidValue == None:
1001                     PackageList = "\n\t".join([str(P) for P in self.PackageList])
1002                     EdkLogger.error(
1003                                 'build',
1004                                 RESOURCE_NOT_AVAILABLE,
1005                                 "Value of GUID [%s] is not found in" % Sku.VariableGuid,
1006                                 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \
1007                                                         % (Guid, Name, str(Module)),
1008                                 File=self.MetaFile
1009                                 )
1010
1011         # override PCD settings with module specific setting
1012         if Module in self.Platform.Modules:
1013             PlatformModule = self.Platform.Modules[str(Module)]
1014             for Key  in PlatformModule.Pcds:
1015                 if Key in Pcds:
1016                     self._OverridePcd(Pcds[Key], PlatformModule.Pcds[Key], Module)
1017         return Pcds.values()
1018
1019     ## Resolve library names to library modules
1020     #
1021     # (for R8.x modules)
1022     #
1023     #   @param  Module  The module from which the library names will be resolved
1024     #
1025     #   @retval library_list    The list of library modules
1026     #
1027     def ResolveLibraryReference(self, Module):
1028         EdkLogger.verbose("")
1029         EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
1030         LibraryConsumerList = [Module]
1031
1032         # "CompilerStub" is a must for R8 modules
1033         if Module.Libraries:
1034             Module.Libraries.append("CompilerStub")
1035         LibraryList = []
1036         while len(LibraryConsumerList) > 0:
1037             M = LibraryConsumerList.pop()
1038             for LibraryName in M.Libraries:
1039                 Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']
1040                 if Library == None:
1041                     for Key in self.Platform.LibraryClasses.data.keys():
1042                         if LibraryName.upper() == Key.upper():
1043                             Library = self.Platform.LibraryClasses[Key, ':dummy:']
1044                             break
1045                     if Library == None:
1046                         EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),
1047                             ExtraData="\t%s [%s]" % (str(Module), self.Arch))
1048                         continue
1049
1050                 if Library not in LibraryList:
1051                     LibraryList.append(Library)
1052                     LibraryConsumerList.append(Library)
1053                     EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))
1054         return LibraryList
1055
1056     ## Expand * in build option key
1057     #
1058     #   @param  Options     Options to be expanded
1059     #
1060     #   @retval options     Options expanded
1061     #
1062     def _ExpandBuildOption(self, Options):
1063         BuildOptions = {}
1064         FamilyMatch  = False
1065         for Key in Options:
1066             Family = Key[0]
1067             Target, Tag, Arch, Tool, Attr = Key[1].split("_")
1068             if Tool not in self.ToolDefinition:
1069                 continue
1070             # if tool chain family doesn't match, skip it
1071             if Family != "":
1072                 FamilyIsNull = False
1073                 if self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY] != "":
1074                     if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
1075                         continue
1076                 elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
1077                     continue
1078                 FamilyMatch = True
1079             # expand any wildcard
1080             if Target == "*" or Target == self.BuildTarget:
1081                 if Tag == "*" or Tag == self.ToolChain:
1082                     if Arch == "*" or Arch == self.Arch:
1083                         if Tool not in BuildOptions:
1084                             BuildOptions[Tool] = {}
1085                         if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:
1086                             BuildOptions[Tool][Attr] = Options[Key]
1087                         else:
1088                             # append options for the same tool
1089                             BuildOptions[Tool][Attr] += " " + Options[Key]
1090         # Build Option Family has been checked, which need't to be checked again for family.
1091         if FamilyMatch or FamilyIsNull:
1092             return BuildOptions
1093         for Key in Options:
1094             Family = Key[0]
1095             Target, Tag, Arch, Tool, Attr = Key[1].split("_")
1096             # if tool chain family doesn't match, skip it
1097             if Tool not in self.ToolDefinition or Family =="":
1098                 continue
1099             # option has been added before
1100             if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
1101                 continue
1102
1103             # expand any wildcard
1104             if Target == "*" or Target == self.BuildTarget:
1105                 if Tag == "*" or Tag == self.ToolChain:
1106                     if Arch == "*" or Arch == self.Arch:
1107                         if Tool not in BuildOptions:
1108                             BuildOptions[Tool] = {}
1109                         if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:
1110                             BuildOptions[Tool][Attr] = Options[Key]
1111                         else:
1112                             # append options for the same tool
1113                             BuildOptions[Tool][Attr] += " " + Options[Key]
1114         return BuildOptions
1115
1116     ## Append build options in platform to a module
1117     #
1118     #   @param  Module  The module to which the build options will be appened
1119     #
1120     #   @retval options     The options appended with build options in platform
1121     #
1122     def ApplyBuildOption(self, Module):
1123         PlatformOptions = self.BuildOption
1124         ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)
1125         if Module in self.Platform.Modules:
1126             PlatformModule = self.Platform.Modules[str(Module)]
1127             PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
1128         else:
1129             PlatformModuleOptions = {}
1130
1131         AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() + PlatformModuleOptions.keys() + self.ToolDefinition.keys())
1132         BuildOptions = {}
1133         for Tool in AllTools:
1134             if Tool not in BuildOptions:
1135                 BuildOptions[Tool] = {}
1136
1137             for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, PlatformModuleOptions]:
1138                 if Tool not in Options:
1139                     continue
1140                 for Attr in Options[Tool]:
1141                     Value = Options[Tool][Attr]
1142                     if Attr not in BuildOptions[Tool]:
1143                         BuildOptions[Tool][Attr] = ""
1144                     # check if override is indicated
1145                     if Value.startswith('='):
1146                         BuildOptions[Tool][Attr] = Value[1:]
1147                     else:
1148                         BuildOptions[Tool][Attr] += " " + Value
1149         return BuildOptions
1150
1151     Platform            = property(_GetPlatform)
1152     Name                = property(_GetName)
1153     Guid                = property(_GetGuid)
1154     Version             = property(_GetVersion)
1155
1156     OutputDir           = property(_GetOutputDir)
1157     BuildDir            = property(_GetBuildDir)
1158     MakeFileDir         = property(_GetMakeFileDir)
1159     FdfFile             = property(_GetFdfFile)
1160
1161     PcdTokenNumber      = property(_GetPcdTokenNumbers)    # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1162     DynamicPcdList      = property(_GetDynamicPcdList)    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1163     NonDynamicPcdList   = property(_GetNonDynamicPcdList)    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1164     PackageList         = property(_GetPackageList)
1165
1166     ToolDefinition      = property(_GetToolDefinition)    # toolcode : tool path
1167     ToolDefinitionFile  = property(_GetToolDefFile)    # toolcode : lib path
1168     ToolChainFamily     = property(_GetToolChainFamily)
1169     BuildRuleFamily     = property(_GetBuildRuleFamily)
1170     BuildOption         = property(_GetBuildOptions)    # toolcode : option
1171
1172     BuildCommand        = property(_GetBuildCommand)
1173     BuildRule           = property(_GetBuildRule)
1174     ModuleAutoGenList   = property(_GetModuleAutoGenList)
1175     LibraryAutoGenList  = property(_GetLibraryAutoGenList)
1176
1177 ## ModuleAutoGen class
1178 #
1179 # This class encapsules the AutoGen behaviors for the build tools. In addition to
1180 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
1181 # to the [depex] section in module's inf file.
1182 #
1183 class ModuleAutoGen(AutoGen):
1184     ## The real constructor of ModuleAutoGen
1185     #
1186     #  This method is not supposed to be called by users of ModuleAutoGen. It's
1187     #  only used by factory method __new__() to do real initialization work for an
1188     #  object of ModuleAutoGen
1189     #
1190     #   @param      Workspace           EdkIIWorkspaceBuild object
1191     #   @param      ModuleFile          The path of module file
1192     #   @param      Target              Build target (DEBUG, RELEASE)
1193     #   @param      Toolchain           Name of tool chain
1194     #   @param      Arch                The arch the module supports
1195     #   @param      PlatformFile        Platform meta-file
1196     #
1197     def _Init(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):
1198         EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))
1199         GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)
1200
1201         self.Workspace = Workspace
1202         self.WorkspaceDir = Workspace.WorkspaceDir
1203
1204         self.MetaFile = ModuleFile
1205         self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)
1206         # check if this module is employed by active platform
1207         if not self.PlatformInfo.ValidModule(self.MetaFile):
1208             EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \
1209                               % (self.MetaFile, Arch))
1210             return False
1211
1212         self.SourceDir = self.MetaFile.SubDir
1213         self.SourceOverrideDir = None
1214         # use overrided path defined in DSC file
1215         if self.MetaFile.Key in GlobalData.gOverrideDir:
1216             self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]
1217
1218         self.ToolChain = Toolchain
1219         self.BuildTarget = Target
1220         self.Arch = Arch
1221         self.ToolChainFamily = self.PlatformInfo.ToolChainFamily
1222         self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily
1223
1224         self.IsMakeFileCreated = False
1225         self.IsCodeFileCreated = False
1226
1227         self.BuildDatabase = self.Workspace.BuildDatabase
1228
1229         self._Module          = None
1230         self._Name            = None
1231         self._Guid            = None
1232         self._Version         = None
1233         self._ModuleType      = None
1234         self._ComponentType   = None
1235         self._PcdIsDriver     = None
1236         self._AutoGenVersion  = None
1237         self._LibraryFlag     = None
1238         self._CustomMakefile  = None
1239         self._Macro           = None
1240
1241         self._BuildDir        = None
1242         self._OutputDir       = None
1243         self._DebugDir        = None
1244         self._MakeFileDir     = None
1245
1246         self._IncludePathList = None
1247         self._AutoGenFileList = None
1248         self._UnicodeFileList = None
1249         self._SourceFileList  = None
1250         self._ObjectFileList  = None
1251         self._BinaryFileList  = None
1252
1253         self._DependentPackageList    = None
1254         self._DependentLibraryList    = None
1255         self._LibraryAutoGenList      = None
1256         self._DerivedPackageList      = None
1257         self._ModulePcdList           = None
1258         self._LibraryPcdList          = None
1259         self._GuidList                = None
1260         self._ProtocolList            = None
1261         self._PpiList                 = None
1262         self._DepexList               = None
1263         self._BuildOption             = None
1264         self._BuildTargets            = None
1265         self._IntroBuildTargetList    = None
1266         self._FinalBuildTargetList    = None
1267         self._FileTypes               = None
1268         self._BuildRules              = None
1269
1270         return True
1271
1272     def __repr__(self):
1273         return "%s [%s]" % (self.MetaFile, self.Arch)
1274
1275     # Macros could be used in build_rule.txt (also Makefile)
1276     def _GetMacros(self):
1277         if self._Macro == None:
1278             self._Macro = sdict()
1279             self._Macro["WORKSPACE"             ] = self.WorkspaceDir
1280             self._Macro["MODULE_NAME"           ] = self.Name
1281             self._Macro["MODULE_GUID"           ] = self.Guid
1282             self._Macro["MODULE_VERSION"        ] = self.Version
1283             self._Macro["MODULE_TYPE"           ] = self.ModuleType
1284             self._Macro["MODULE_FILE"           ] = str(self.MetaFile)
1285             self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName
1286             self._Macro["MODULE_RELATIVE_DIR"   ] = self.SourceDir
1287             self._Macro["MODULE_DIR"            ] = self.SourceDir
1288
1289             self._Macro["BASE_NAME"             ] = self.Name
1290
1291             self._Macro["ARCH"                  ] = self.Arch
1292             self._Macro["TOOLCHAIN"             ] = self.ToolChain
1293             self._Macro["TOOLCHAIN_TAG"         ] = self.ToolChain
1294             self._Macro["TARGET"                ] = self.BuildTarget
1295
1296             self._Macro["BUILD_DIR"             ] = self.PlatformInfo.BuildDir
1297             self._Macro["BIN_DIR"               ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
1298             self._Macro["LIB_DIR"               ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
1299             self._Macro["MODULE_BUILD_DIR"      ] = self.BuildDir
1300             self._Macro["OUTPUT_DIR"            ] = self.OutputDir
1301             self._Macro["DEBUG_DIR"             ] = self.DebugDir
1302         return self._Macro
1303
1304     ## Return the module build data object
1305     def _GetModule(self):
1306         if self._Module == None:
1307             self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch]
1308         return self._Module
1309
1310     ## Return the module name
1311     def _GetBaseName(self):
1312         return self.Module.BaseName
1313
1314     ## Return the module SourceOverridePath
1315     def _GetSourceOverridePath(self):
1316         return self.Module.SourceOverridePath
1317
1318     ## Return the module meta-file GUID
1319     def _GetGuid(self):
1320         return self.Module.Guid
1321
1322     ## Return the module version
1323     def _GetVersion(self):
1324         return self.Module.Version
1325
1326     ## Return the module type
1327     def _GetModuleType(self):
1328         return self.Module.ModuleType
1329
1330     ## Return the component type (for R8.x style of module)
1331     def _GetComponentType(self):
1332         return self.Module.ComponentType
1333
1334     ## Return the build type
1335     def _GetBuildType(self):
1336         return self.Module.BuildType
1337
1338     ## Return the PCD_IS_DRIVER setting
1339     def _GetPcdIsDriver(self):
1340         return self.Module.PcdIsDriver
1341
1342     ## Return the autogen version, i.e. module meta-file version
1343     def _GetAutoGenVersion(self):
1344         return self.Module.AutoGenVersion
1345
1346     ## Check if the module is library or not
1347     def _IsLibrary(self):
1348         if self._LibraryFlag == None:
1349             if self.Module.LibraryClass != None and self.Module.LibraryClass != []:
1350                 self._LibraryFlag = True
1351             else:
1352                 self._LibraryFlag = False
1353         return self._LibraryFlag
1354
1355     ## Return the directory to store intermediate files of the module
1356     def _GetBuildDir(self):
1357         if self._BuildDir == None:
1358             self._BuildDir = path.join(
1359                                     self.PlatformInfo.BuildDir,
1360                                     self.Arch,
1361                                     self.SourceDir,
1362                                     self.MetaFile.BaseName
1363                                     )
1364             CreateDirectory(self._BuildDir)
1365         return self._BuildDir
1366
1367     ## Return the directory to store the intermediate object files of the mdoule
1368     def _GetOutputDir(self):
1369         if self._OutputDir == None:
1370             self._OutputDir = path.join(self.BuildDir, "OUTPUT")
1371             CreateDirectory(self._OutputDir)
1372         return self._OutputDir
1373
1374     ## Return the directory to store auto-gened source files of the mdoule
1375     def _GetDebugDir(self):
1376         if self._DebugDir == None:
1377             self._DebugDir = path.join(self.BuildDir, "DEBUG")
1378             CreateDirectory(self._DebugDir)
1379         return self._DebugDir
1380
1381     ## Return the path of custom file
1382     def _GetCustomMakefile(self):
1383         if self._CustomMakefile == None:
1384             self._CustomMakefile = {}
1385             for Type in self.Module.CustomMakefile:
1386                 if Type in gMakeTypeMap:
1387                     MakeType = gMakeTypeMap[Type]
1388                 else:
1389                     MakeType = 'nmake'
1390                 if self.SourceOverrideDir != None:
1391                     File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])
1392                     if not os.path.exists(File):
1393                         File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
1394                 else:
1395                     File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
1396                 self._CustomMakefile[MakeType] = File
1397         return self._CustomMakefile
1398
1399     ## Return the directory of the makefile
1400     #
1401     #   @retval     string  The directory string of module's makefile
1402     #
1403     def _GetMakeFileDir(self):
1404         return self.BuildDir
1405
1406     ## Return build command string
1407     #
1408     #   @retval     string  Build command string
1409     #
1410     def _GetBuildCommand(self):
1411         return self.PlatformInfo.BuildCommand
1412
1413     ## Get object list of all packages the module and its dependent libraries belong to
1414     #
1415     #   @retval     list    The list of package object
1416     #
1417     def _GetDerivedPackageList(self):
1418         PackageList = []
1419         for M in [self.Module] + self.DependentLibraryList:
1420             for Package in M.Packages:
1421                 if Package in PackageList:
1422                     continue
1423                 PackageList.append(Package)
1424         return PackageList
1425
1426     ## Merge dependency expression
1427     #
1428     #   @retval     list    The token list of the dependency expression after parsed
1429     #
1430     def _GetDepexTokenList(self):
1431         if self._DepexList == None:
1432             self._DepexList = {}
1433             if self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
1434                 return self._DepexList
1435
1436             if self.ModuleType == "DXE_SMM_DRIVER":
1437                 self._DepexList["DXE_DRIVER"] = []
1438                 self._DepexList["SMM_DRIVER"] = []
1439             else:
1440                 self._DepexList[self.ModuleType] = []
1441
1442             for ModuleType in self._DepexList:
1443                 DepexList = self._DepexList[ModuleType]
1444                 #
1445                 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
1446                 #
1447                 for M in [self.Module] + self.DependentLibraryList:
1448                     Inherited = False
1449                     for D in M.Depex[self.Arch, ModuleType]:
1450                         if DepexList != []:
1451                             DepexList.append('AND')
1452                         DepexList.append('(')
1453                         DepexList.extend(D)
1454                         if DepexList[-1] == 'END':  # no need of a END at this time
1455                             DepexList.pop()
1456                         DepexList.append(')')
1457                         Inherited = True
1458                     if Inherited:
1459                         EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))
1460                     if 'BEFORE' in DepexList or 'AFTER' in DepexList:
1461                         break
1462                 if len(DepexList) > 0:
1463                     EdkLogger.verbose('')
1464         return self._DepexList
1465
1466     ## Return the list of specification version required for the module
1467     #
1468     #   @retval     list    The list of specification defined in module file
1469     #
1470     def _GetSpecification(self):
1471         return self.Module.Specification
1472
1473     ## Tool option for the module build
1474     #
1475     #   @param      PlatformInfo    The object of PlatformBuildInfo
1476     #   @retval     dict            The dict containing valid options
1477     #
1478     def _GetModuleBuildOption(self):
1479         if self._BuildOption == None:
1480             self._BuildOption = self.PlatformInfo.ApplyBuildOption(self.Module)
1481         return self._BuildOption
1482
1483     ## Return a list of files which can be built from source
1484     #
1485     #  What kind of files can be built is determined by build rules in
1486     #  $(WORKSPACE)/Conf/build_rule.txt and toolchain family.
1487     #
1488     def _GetSourceFileList(self):
1489         if self._SourceFileList == None:
1490             self._SourceFileList = []
1491             for F in self.Module.Sources:
1492                 # match tool chain
1493                 if F.TagName != "" and F.TagName != self.ToolChain:
1494                     EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "
1495                                     "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))
1496                     continue
1497                 # match tool chain family
1498                 if F.ToolChainFamily != "" and F.ToolChainFamily != self.ToolChainFamily:
1499                     EdkLogger.debug(
1500                                 EdkLogger.DEBUG_0,
1501                                 "The file [%s] must be built by tools of [%s], " \
1502                                 "but current toolchain family is [%s]" \
1503                                     % (str(F), F.ToolChainFamily, self.ToolChainFamily))
1504                     continue
1505
1506                 # add the file path into search path list for file including
1507                 if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:
1508                     self.IncludePathList.insert(0, F.Dir)
1509                 self._SourceFileList.append(F)
1510                 self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)
1511         return self._SourceFileList
1512
1513     ## Return the list of unicode files
1514     def _GetUnicodeFileList(self):
1515         if self._UnicodeFileList == None:
1516             if TAB_UNICODE_FILE in self.FileTypes:
1517                 self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]
1518             else:
1519                 self._UnicodeFileList = []
1520         return self._UnicodeFileList
1521
1522     ## Return a list of files which can be built from binary
1523     #
1524     #  "Build" binary files are just to copy them to build directory.
1525     #
1526     #   @retval     list            The list of files which can be built later
1527     #
1528     def _GetBinaryFiles(self):
1529         if self._BinaryFileList == None:
1530             self._BinaryFileList = []
1531             for F in self.Module.Binaries:
1532                 if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:
1533                     continue
1534                 self._BinaryFileList.append(F)
1535                 self._ApplyBuildRule(F, F.Type)
1536         return self._BinaryFileList
1537
1538     def _GetBuildRules(self):
1539         if self._BuildRules == None:
1540             BuildRules = {}
1541             BuildRuleDatabase = self.PlatformInfo.BuildRule
1542             for Type in BuildRuleDatabase.FileTypeList:
1543                 #first try getting build rule by BuildRuleFamily
1544                 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]
1545                 if not RuleObject:
1546                     # build type is always module type, but ...
1547                     if self.ModuleType != self.BuildType:
1548                         RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]
1549                 #second try getting build rule by ToolChainFamily
1550                 if not RuleObject:
1551                     RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]
1552                     if not RuleObject:
1553                         # build type is always module type, but ...
1554                         if self.ModuleType != self.BuildType:
1555                             RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]
1556                 if not RuleObject:
1557                     continue
1558                 RuleObject = RuleObject.Instantiate(self.Macros)
1559                 BuildRules[Type] = RuleObject
1560                 for Ext in RuleObject.SourceFileExtList:
1561                     BuildRules[Ext] = RuleObject
1562             self._BuildRules = BuildRules
1563         return self._BuildRules
1564
1565     def _ApplyBuildRule(self, File, FileType):
1566         if self._BuildTargets == None:
1567             self._IntroBuildTargetList = set()
1568             self._FinalBuildTargetList = set()
1569             self._BuildTargets = {}
1570             self._FileTypes = {}
1571
1572         LastTarget = None
1573         RuleChain = []
1574         SourceList = [File]
1575         Index = 0
1576         while Index < len(SourceList):
1577             Source = SourceList[Index]
1578             Index = Index + 1
1579
1580             if Source != File:
1581                 CreateDirectory(Source.Dir)
1582
1583             if FileType in self.BuildRules:
1584                 RuleObject = self.BuildRules[FileType]
1585             elif Source.Ext in self.BuildRules:
1586                 RuleObject = self.BuildRules[Source.Ext]
1587             elif File.IsBinary and File == Source:
1588                 RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]
1589             else:
1590                 # stop at no more rules
1591                 if LastTarget:
1592                     self._FinalBuildTargetList.add(LastTarget)
1593                 break
1594
1595             FileType = RuleObject.SourceFileType
1596             if FileType not in self._FileTypes:
1597                 self._FileTypes[FileType] = set()
1598             self._FileTypes[FileType].add(Source)
1599
1600             # stop at STATIC_LIBRARY for library
1601             if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
1602                 self._FinalBuildTargetList.add(LastTarget)
1603                 break
1604
1605             Target = RuleObject.Apply(Source)
1606             if not Target:
1607                 if LastTarget:
1608                     self._FinalBuildTargetList.add(LastTarget)
1609                 break
1610             elif not Target.Outputs:
1611                 # Only do build for target with outputs
1612                 self._FinalBuildTargetList.add(Target)
1613
1614             if FileType not in self._BuildTargets:
1615                 self._BuildTargets[FileType] = set()
1616             self._BuildTargets[FileType].add(Target)
1617
1618             if not Source.IsBinary and Source == File:
1619                 self._IntroBuildTargetList.add(Target)
1620
1621             # to avoid cyclic rule
1622             if FileType in RuleChain:
1623                 break
1624
1625             RuleChain.append(FileType)
1626             SourceList.extend(Target.Outputs)
1627             LastTarget = Target
1628             FileType = TAB_UNKNOWN_FILE
1629
1630     def _GetTargets(self):
1631         if self._BuildTargets == None:
1632             self._IntroBuildTargetList = set()
1633             self._FinalBuildTargetList = set()
1634             self._BuildTargets = {}
1635             self._FileTypes = {}
1636
1637         #TRICK: call _GetSourceFileList to apply build rule for binary files
1638         if self.SourceFileList:
1639             pass
1640
1641         #TRICK: call _GetBinaryFileList to apply build rule for binary files
1642         if self.BinaryFileList:
1643             pass
1644
1645         return self._BuildTargets
1646
1647     def _GetIntroTargetList(self):
1648         self._GetTargets()
1649         return self._IntroBuildTargetList
1650
1651     def _GetFinalTargetList(self):
1652         self._GetTargets()
1653         return self._FinalBuildTargetList
1654
1655     def _GetFileTypes(self):
1656         self._GetTargets()
1657         return self._FileTypes
1658
1659     ## Get the list of package object the module depends on
1660     #
1661     #   @retval     list    The package object list
1662     #
1663     def _GetDependentPackageList(self):
1664         return self.Module.Packages
1665
1666     ## Return the list of auto-generated code file
1667     #
1668     #   @retval     list        The list of auto-generated file
1669     #
1670     def _GetAutoGenFileList(self):
1671         if self._AutoGenFileList == None:
1672             self._AutoGenFileList = {}
1673             AutoGenC = TemplateString()
1674             AutoGenH = TemplateString()
1675             StringH = TemplateString()
1676             GenC.CreateCode(self, AutoGenC, AutoGenH, StringH)
1677             if str(AutoGenC) != "" and TAB_C_CODE_FILE in self.FileTypes:
1678                 AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)
1679                 self._AutoGenFileList[AutoFile] = str(AutoGenC)
1680                 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
1681             if str(AutoGenH) != "":
1682                 AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)
1683                 self._AutoGenFileList[AutoFile] = str(AutoGenH)
1684                 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
1685             if str(StringH) != "":
1686                 AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)
1687                 self._AutoGenFileList[AutoFile] = str(StringH)
1688                 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
1689         return self._AutoGenFileList
1690
1691     ## Return the list of library modules explicitly or implicityly used by this module
1692     def _GetLibraryList(self):
1693         if self._DependentLibraryList == None:
1694             # only merge library classes and PCD for non-library module
1695             if self.IsLibrary:
1696                 self._DependentLibraryList = []
1697             else:
1698                 if self.AutoGenVersion < 0x00010005:
1699                     self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)
1700                 else:
1701                     self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)
1702         return self._DependentLibraryList
1703
1704     ## Get the list of PCDs from current module
1705     #
1706     #   @retval     list                    The list of PCD
1707     #
1708     def _GetModulePcdList(self):
1709         if self._ModulePcdList == None:
1710             # apply PCD settings from platform
1711             self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)
1712         return self._ModulePcdList
1713
1714     ## Get the list of PCDs from dependent libraries
1715     #
1716     #   @retval     list                    The list of PCD
1717     #
1718     def _GetLibraryPcdList(self):
1719         if self._LibraryPcdList == None:
1720             Pcds = {}
1721             if not self.IsLibrary:
1722                 # get PCDs from dependent libraries
1723                 for Library in self.DependentLibraryList:
1724                     for Key in Library.Pcds:
1725                         # skip duplicated PCDs
1726                         if Key in self.Module.Pcds or Key in Pcds:
1727                             continue
1728                         Pcds[Key] = copy.copy(Library.Pcds[Key])
1729                 # apply PCD settings from platform
1730                 self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)
1731             else:
1732                 self._LibraryPcdList = []
1733         return self._LibraryPcdList
1734
1735     ## Get the GUID value mapping
1736     #
1737     #   @retval     dict    The mapping between GUID cname and its value
1738     #
1739     def _GetGuidList(self):
1740         if self._GuidList == None:
1741             self._GuidList = self.Module.Guids
1742             for Library in self.DependentLibraryList:
1743                 self._GuidList.update(Library.Guids)
1744         return self._GuidList
1745
1746     ## Get the protocol value mapping
1747     #
1748     #   @retval     dict    The mapping between protocol cname and its value
1749     #
1750     def _GetProtocolList(self):
1751         if self._ProtocolList == None:
1752             self._ProtocolList = self.Module.Protocols
1753             for Library in self.DependentLibraryList:
1754                 self._ProtocolList.update(Library.Protocols)
1755         return self._ProtocolList
1756
1757     ## Get the PPI value mapping
1758     #
1759     #   @retval     dict    The mapping between PPI cname and its value
1760     #
1761     def _GetPpiList(self):
1762         if self._PpiList == None:
1763             self._PpiList = self.Module.Ppis
1764             for Library in self.DependentLibraryList:
1765                 self._PpiList.update(Library.Ppis)
1766         return self._PpiList
1767
1768     ## Get the list of include search path
1769     #
1770     #   @retval     list                    The list path
1771     #
1772     def _GetIncludePathList(self):
1773         if self._IncludePathList == None:
1774             self._IncludePathList = []
1775             if self.AutoGenVersion < 0x00010005:
1776                 for Inc in self.Module.Includes:
1777                     if Inc not in self._IncludePathList:
1778                         self._IncludePathList.append(Inc)
1779                     # for r8 modules
1780                     Inc = path.join(Inc, self.Arch.capitalize())
1781                     if os.path.exists(Inc) and Inc not in self._IncludePathList:
1782                         self._IncludePathList.append(Inc)
1783                 # r8 module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
1784                 self._IncludePathList.append(self.DebugDir)
1785             else:
1786                 self._IncludePathList.append(self.MetaFile.Dir)
1787                 self._IncludePathList.append(self.DebugDir)
1788
1789             for Package in self.Module.Packages:
1790                 PackageDir = path.join(self.WorkspaceDir, Package.MetaFile.Dir)
1791                 if PackageDir not in self._IncludePathList:
1792                     self._IncludePathList.append(PackageDir)
1793                 for Inc in Package.Includes:
1794                     if Inc not in self._IncludePathList:
1795                         self._IncludePathList.append(str(Inc))
1796         return self._IncludePathList
1797
1798     ## Create makefile for the module and its dependent libraries
1799     #
1800     #   @param      CreateLibraryMakeFile   Flag indicating if or not the makefiles of
1801     #                                       dependent libraries will be created
1802     #
1803     def CreateMakeFile(self, CreateLibraryMakeFile=True):
1804         if self.IsMakeFileCreated:
1805             return
1806
1807         if not self.IsLibrary and CreateLibraryMakeFile:
1808             for LibraryAutoGen in self.LibraryAutoGenList:
1809                 LibraryAutoGen.CreateMakeFile()
1810
1811         if len(self.CustomMakefile) == 0:
1812             Makefile = GenMake.ModuleMakefile(self)
1813         else:
1814             Makefile = GenMake.CustomMakefile(self)
1815         if Makefile.Generate():
1816             EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %
1817                             (self.Name, self.Arch))
1818         else:
1819             EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %
1820                             (self.Name, self.Arch))
1821
1822         self.IsMakeFileCreated = True
1823
1824     ## Create autogen code for the module and its dependent libraries
1825     #
1826     #   @param      CreateLibraryCodeFile   Flag indicating if or not the code of
1827     #                                       dependent libraries will be created
1828     #
1829     def CreateCodeFile(self, CreateLibraryCodeFile=True):
1830         if self.IsCodeFileCreated:
1831             return
1832
1833         if not self.IsLibrary and CreateLibraryCodeFile:
1834             for LibraryAutoGen in self.LibraryAutoGenList:
1835                 LibraryAutoGen.CreateCodeFile()
1836
1837         AutoGenList = []
1838         IgoredAutoGenList = []
1839
1840         for File in self.AutoGenFileList:
1841             if GenC.Generate(File.Path, self.AutoGenFileList[File]):
1842                 #Ignore R8 AutoGen.c
1843                 if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':
1844                         continue
1845
1846                 AutoGenList.append(str(File))
1847             else:
1848                 IgoredAutoGenList.append(str(File))
1849
1850         for ModuleType in self.DepexList:
1851             if len(self.DepexList[ModuleType]) == 0:
1852                 continue
1853             Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
1854             if ModuleType == 'SMM_DRIVER':
1855                 DpxFile = gAutoGenSmmDepexFileName % {"module_name" : self.Name}
1856             else:
1857                 DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
1858
1859             if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
1860                 AutoGenList.append(str(DpxFile))
1861             else:
1862                 IgoredAutoGenList.append(str(DpxFile))
1863
1864         if IgoredAutoGenList == []:
1865             EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %
1866                             (" ".join(AutoGenList), self.Name, self.Arch))
1867         elif AutoGenList == []:
1868             EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %
1869                             (" ".join(IgoredAutoGenList), self.Name, self.Arch))
1870         else:
1871             EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %
1872                             (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
1873
1874         self.IsCodeFileCreated = True
1875         return AutoGenList
1876
1877     ## Summarize the ModuleAutoGen objects of all libraries used by this module
1878     def _GetLibraryAutoGenList(self):
1879         if self._LibraryAutoGenList == None:
1880             self._LibraryAutoGenList = []
1881             for Library in self.DependentLibraryList:
1882                 La = ModuleAutoGen(
1883                         self.Workspace,
1884                         Library.MetaFile,
1885                         self.BuildTarget,
1886                         self.ToolChain,
1887                         self.Arch,
1888                         self.PlatformInfo.MetaFile
1889                         )
1890                 if La not in self._LibraryAutoGenList:
1891                     self._LibraryAutoGenList.append(La)
1892                     for Lib in La.CodaTargetList:
1893                         self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)
1894         return self._LibraryAutoGenList
1895
1896     ## Return build command string
1897     #
1898     #   @retval     string  Build command string
1899     #
1900     def _GetBuildCommand(self):
1901         return self.PlatformInfo.BuildCommand
1902
1903
1904     Module          = property(_GetModule)
1905     Name            = property(_GetBaseName)
1906     Guid            = property(_GetGuid)
1907     Version         = property(_GetVersion)
1908     ModuleType      = property(_GetModuleType)
1909     ComponentType   = property(_GetComponentType)
1910     BuildType       = property(_GetBuildType)
1911     PcdIsDriver     = property(_GetPcdIsDriver)
1912     AutoGenVersion  = property(_GetAutoGenVersion)
1913     Macros          = property(_GetMacros)
1914     Specification   = property(_GetSpecification)
1915
1916     IsLibrary       = property(_IsLibrary)
1917
1918     BuildDir        = property(_GetBuildDir)
1919     OutputDir       = property(_GetOutputDir)
1920     DebugDir        = property(_GetDebugDir)
1921     MakeFileDir     = property(_GetMakeFileDir)
1922     CustomMakefile  = property(_GetCustomMakefile)
1923
1924     IncludePathList = property(_GetIncludePathList)
1925     AutoGenFileList = property(_GetAutoGenFileList)
1926     UnicodeFileList = property(_GetUnicodeFileList)
1927     SourceFileList  = property(_GetSourceFileList)
1928     BinaryFileList  = property(_GetBinaryFiles) # FileType : [File List]
1929     Targets         = property(_GetTargets)
1930     IntroTargetList = property(_GetIntroTargetList)
1931     CodaTargetList  = property(_GetFinalTargetList)
1932     FileTypes       = property(_GetFileTypes)
1933     BuildRules      = property(_GetBuildRules)
1934
1935     DependentPackageList    = property(_GetDependentPackageList)
1936     DependentLibraryList    = property(_GetLibraryList)
1937     LibraryAutoGenList      = property(_GetLibraryAutoGenList)
1938     DerivedPackageList      = property(_GetDerivedPackageList)
1939
1940     ModulePcdList           = property(_GetModulePcdList)
1941     LibraryPcdList          = property(_GetLibraryPcdList)
1942     GuidList                = property(_GetGuidList)
1943     ProtocolList            = property(_GetProtocolList)
1944     PpiList                 = property(_GetPpiList)
1945     DepexList               = property(_GetDepexTokenList)
1946     BuildOption             = property(_GetModuleBuildOption)
1947     BuildCommand            = property(_GetBuildCommand)
1948
1949 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1950 if __name__ == '__main__':
1951     pass
1952