1## @file
2# Generate AutoGen.h, AutoGen.c and *.depex files
3#
4# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
5# 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#
16import Common.LongFilePathOs as os
17import re
18import os.path as path
19import copy
20import uuid
21
22import GenC
23import GenMake
24import GenDepex
25from StringIO import StringIO
26
27from StrGather import *
28from BuildEngine import BuildRule
29
30from Common.LongFilePathSupport import CopyLongFilePath
31from Common.BuildToolError import *
32from Common.DataType import *
33from Common.Misc import *
34from Common.String import *
35import Common.GlobalData as GlobalData
36from GenFds.FdfParser import *
37from CommonDataClass.CommonClass import SkuInfoClass
38from Workspace.BuildClassObject import *
39from GenPatchPcdTable.GenPatchPcdTable import parsePcdInfoFromMapFile
40import Common.VpdInfoFile as VpdInfoFile
41from GenPcdDb import CreatePcdDatabaseCode
42from Workspace.MetaFileCommentParser import UsageList
43from Common.MultipleWorkspace import MultipleWorkspace as mws
44import InfSectionParser
45
46## Regular expression for splitting Dependency Expression string into tokens
47gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")
48
49#
50# Match name = variable
51#
52gEfiVarStoreNamePattern = re.compile("\s*name\s*=\s*(\w+)")
53#
54# The format of guid in efivarstore statement likes following and must be correct:
55# guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
56#
57gEfiVarStoreGuidPattern = re.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
58
59## Mapping Makefile type
60gMakeTypeMap = {"MSFT":"nmake", "GCC":"gmake"}
61
62
63## Build rule configuration file
64gDefaultBuildRuleFile = 'Conf/build_rule.txt'
65
66## Build rule default version
67AutoGenReqBuildRuleVerNum = "0.1"
68
69## default file name for AutoGen
70gAutoGenCodeFileName = "AutoGen.c"
71gAutoGenHeaderFileName = "AutoGen.h"
72gAutoGenStringFileName = "%(module_name)sStrDefs.h"
73gAutoGenStringFormFileName = "%(module_name)sStrDefs.hpk"
74gAutoGenDepexFileName = "%(module_name)s.depex"
75
76gInfSpecVersion = "0x00010017"
77
78#
79# Template string to generic AsBuilt INF
80#
81gAsBuiltInfHeaderString = TemplateString("""${header_comments}
82
83# DO NOT EDIT
84# FILE auto-generated
85
86[Defines]
87  INF_VERSION                = ${module_inf_version}
88  BASE_NAME                  = ${module_name}
89  FILE_GUID                  = ${module_guid}
90  MODULE_TYPE                = ${module_module_type}${BEGIN}
91  VERSION_STRING             = ${module_version_string}${END}${BEGIN}
92  PCD_IS_DRIVER              = ${pcd_is_driver_string}${END}${BEGIN}
93  UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
94  PI_SPECIFICATION_VERSION   = ${module_pi_specification_version}${END}${BEGIN}
95  ENTRY_POINT                = ${module_entry_point}${END}${BEGIN}
96  UNLOAD_IMAGE               = ${module_unload_image}${END}${BEGIN}
97  CONSTRUCTOR                = ${module_constructor}${END}${BEGIN}
98  DESTRUCTOR                 = ${module_destructor}${END}${BEGIN}
99  SHADOW                     = ${module_shadow}${END}${BEGIN}
100  PCI_VENDOR_ID              = ${module_pci_vendor_id}${END}${BEGIN}
101  PCI_DEVICE_ID              = ${module_pci_device_id}${END}${BEGIN}
102  PCI_CLASS_CODE             = ${module_pci_class_code}${END}${BEGIN}
103  PCI_REVISION               = ${module_pci_revision}${END}${BEGIN}
104  BUILD_NUMBER               = ${module_build_number}${END}${BEGIN}
105  SPEC                       = ${module_spec}${END}${BEGIN}
106  UEFI_HII_RESOURCE_SECTION  = ${module_uefi_hii_resource_section}${END}${BEGIN}
107  MODULE_UNI_FILE            = ${module_uni_file}${END}
108
109[Packages.${module_arch}]${BEGIN}
110  ${package_item}${END}
111
112[Binaries.${module_arch}]${BEGIN}
113  ${binary_item}${END}
114
115[PatchPcd.${module_arch}]${BEGIN}
116  ${patchablepcd_item}
117${END}
118
119[Protocols.${module_arch}]${BEGIN}
120  ${protocol_item}
121${END}
122
123[Ppis.${module_arch}]${BEGIN}
124  ${ppi_item}
125${END}
126
127[Guids.${module_arch}]${BEGIN}
128  ${guid_item}
129${END}
130
131[PcdEx.${module_arch}]${BEGIN}
132  ${pcd_item}
133${END}
134
135[LibraryClasses.${module_arch}]
136## @LIB_INSTANCES${BEGIN}
137#  ${libraryclasses_item}${END}
138
139${depexsection_item}
140
141${tail_comments}
142
143[BuildOptions.${module_arch}]
144## @AsBuilt${BEGIN}
145##   ${flags_item}${END}
146""")
147
148## Base class for AutoGen
149#
150#   This class just implements the cache mechanism of AutoGen objects.
151#
152class AutoGen(object):
153    # database to maintain the objects of xxxAutoGen
154    _CACHE_ = {}    # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
155
156    ## Factory method
157    #
158    #   @param  Class           class object of real AutoGen class
159    #                           (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
160    #   @param  Workspace       Workspace directory or WorkspaceAutoGen object
161    #   @param  MetaFile        The path of meta file
162    #   @param  Target          Build target
163    #   @param  Toolchain       Tool chain name
164    #   @param  Arch            Target arch
165    #   @param  *args           The specific class related parameters
166    #   @param  **kwargs        The specific class related dict parameters
167    #
168    def __new__(Class, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
169        # check if the object has been created
170        Key = (Target, Toolchain)
171        if Key not in Class._CACHE_ or Arch not in Class._CACHE_[Key] \
172           or MetaFile not in Class._CACHE_[Key][Arch]:
173            AutoGenObject = super(AutoGen, Class).__new__(Class)
174            # call real constructor
175            if not AutoGenObject._Init(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
176                return None
177            if Key not in Class._CACHE_:
178                Class._CACHE_[Key] = {}
179            if Arch not in Class._CACHE_[Key]:
180                Class._CACHE_[Key][Arch] = {}
181            Class._CACHE_[Key][Arch][MetaFile] = AutoGenObject
182        else:
183            AutoGenObject = Class._CACHE_[Key][Arch][MetaFile]
184
185        return AutoGenObject
186
187    ## hash() operator
188    #
189    #  The file path of platform file will be used to represent hash value of this object
190    #
191    #   @retval int     Hash value of the file path of platform file
192    #
193    def __hash__(self):
194        return hash(self.MetaFile)
195
196    ## str() operator
197    #
198    #  The file path of platform file will be used to represent this object
199    #
200    #   @retval string  String of platform file path
201    #
202    def __str__(self):
203        return str(self.MetaFile)
204
205    ## "==" operator
206    def __eq__(self, Other):
207        return Other and self.MetaFile == Other
208
209## Workspace AutoGen class
210#
211#   This class is used mainly to control the whole platform build for different
212# architecture. This class will generate top level makefile.
213#
214class WorkspaceAutoGen(AutoGen):
215    ## Real constructor of WorkspaceAutoGen
216    #
217    # This method behaves the same as __init__ except that it needs explicit invoke
218    # (in super class's __new__ method)
219    #
220    #   @param  WorkspaceDir            Root directory of workspace
221    #   @param  ActivePlatform          Meta-file of active platform
222    #   @param  Target                  Build target
223    #   @param  Toolchain               Tool chain name
224    #   @param  ArchList                List of architecture of current build
225    #   @param  MetaFileDb              Database containing meta-files
226    #   @param  BuildConfig             Configuration of build
227    #   @param  ToolDefinition          Tool chain definitions
228    #   @param  FlashDefinitionFile     File of flash definition
229    #   @param  Fds                     FD list to be generated
230    #   @param  Fvs                     FV list to be generated
231    #   @param  Caps                    Capsule list to be generated
232    #   @param  SkuId                   SKU id from command line
233    #
234    def _Init(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb,
235              BuildConfig, ToolDefinition, FlashDefinitionFile='', Fds=None, Fvs=None, Caps=None, SkuId='', UniFlag=None,
236              Progress=None, BuildModule=None):
237        if Fds is None:
238            Fds = []
239        if Fvs is None:
240            Fvs = []
241        if Caps is None:
242            Caps = []
243        self.BuildDatabase  = MetaFileDb
244        self.MetaFile       = ActivePlatform
245        self.WorkspaceDir   = WorkspaceDir
246        self.Platform       = self.BuildDatabase[self.MetaFile, 'COMMON', Target, Toolchain]
247        GlobalData.gActivePlatform = self.Platform
248        self.BuildTarget    = Target
249        self.ToolChain      = Toolchain
250        self.ArchList       = ArchList
251        self.SkuId          = SkuId
252        self.UniFlag        = UniFlag
253
254        self.TargetTxt      = BuildConfig
255        self.ToolDef        = ToolDefinition
256        self.FdfFile        = FlashDefinitionFile
257        self.FdTargetList   = Fds
258        self.FvTargetList   = Fvs
259        self.CapTargetList  = Caps
260        self.AutoGenObjectList = []
261
262        # there's many relative directory operations, so ...
263        os.chdir(self.WorkspaceDir)
264
265        #
266        # Merge Arch
267        #
268        if not self.ArchList:
269            ArchList = set(self.Platform.SupArchList)
270        else:
271            ArchList = set(self.ArchList) & set(self.Platform.SupArchList)
272        if not ArchList:
273            EdkLogger.error("build", PARAMETER_INVALID,
274                            ExtraData = "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self.Platform.SupArchList)))
275        elif self.ArchList and len(ArchList) != len(self.ArchList):
276            SkippedArchList = set(self.ArchList).symmetric_difference(set(self.Platform.SupArchList))
277            EdkLogger.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
278                              % (" ".join(SkippedArchList), " ".join(self.Platform.SupArchList)))
279        self.ArchList = tuple(ArchList)
280
281        # Validate build target
282        if self.BuildTarget not in self.Platform.BuildTargets:
283            EdkLogger.error("build", PARAMETER_INVALID,
284                            ExtraData="Build target [%s] is not supported by the platform. [Valid target: %s]"
285                                      % (self.BuildTarget, " ".join(self.Platform.BuildTargets)))
286
287
288        # parse FDF file to get PCDs in it, if any
289        if not self.FdfFile:
290            self.FdfFile = self.Platform.FlashDefinition
291
292        EdkLogger.info("")
293        if self.ArchList:
294            EdkLogger.info('%-16s = %s' % ("Architecture(s)", ' '.join(self.ArchList)))
295        EdkLogger.info('%-16s = %s' % ("Build target", self.BuildTarget))
296        EdkLogger.info('%-16s = %s' % ("Toolchain", self.ToolChain))
297
298        EdkLogger.info('\n%-24s = %s' % ("Active Platform", self.Platform))
299        if BuildModule:
300            EdkLogger.info('%-24s = %s' % ("Active Module", BuildModule))
301
302        if self.FdfFile:
303            EdkLogger.info('%-24s = %s' % ("Flash Image Definition", self.FdfFile))
304
305        EdkLogger.verbose("\nFLASH_DEFINITION = %s" % self.FdfFile)
306
307        if Progress:
308            Progress.Start("\nProcessing meta-data")
309
310        if self.FdfFile:
311            #
312            # Mark now build in AutoGen Phase
313            #
314            GlobalData.gAutoGenPhase = True
315            Fdf = FdfParser(self.FdfFile.Path)
316            Fdf.ParseFile()
317            GlobalData.gFdfParser = Fdf
318            GlobalData.gAutoGenPhase = False
319            PcdSet = Fdf.Profile.PcdDict
320            ModuleList = Fdf.Profile.InfList
321            self.FdfProfile = Fdf.Profile
322            for fvname in self.FvTargetList:
323                if fvname.upper() not in self.FdfProfile.FvDict:
324                    EdkLogger.error("build", OPTION_VALUE_INVALID,
325                                    "No such an FV in FDF file: %s" % fvname)
326        else:
327            PcdSet = {}
328            ModuleList = []
329            self.FdfProfile = None
330            if self.FdTargetList:
331                EdkLogger.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self.FdTargetList))
332                self.FdTargetList = []
333            if self.FvTargetList:
334                EdkLogger.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self.FvTargetList))
335                self.FvTargetList = []
336            if self.CapTargetList:
337                EdkLogger.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self.CapTargetList))
338                self.CapTargetList = []
339
340        # apply SKU and inject PCDs from Flash Definition file
341        for Arch in self.ArchList:
342            Platform = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]
343
344            DecPcds = {}
345            DecPcdsKey = set()
346            PGen = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)
347            #Collect package set information from INF of FDF
348            PkgSet = set()
349            for Inf in ModuleList:
350                ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)
351                if ModuleFile in Platform.Modules:
352                    continue
353                ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]
354                PkgSet.update(ModuleData.Packages)
355            Pkgs = list(PkgSet) + list(PGen.PackageList)
356            for Pkg in Pkgs:
357                for Pcd in Pkg.Pcds:
358                    DecPcds[Pcd[0], Pcd[1]] = Pkg.Pcds[Pcd]
359                    DecPcdsKey.add((Pcd[0], Pcd[1], Pcd[2]))
360
361            Platform.SkuName = self.SkuId
362            for Name, Guid in PcdSet:
363                if (Name, Guid) not in DecPcds:
364                    EdkLogger.error(
365                        'build',
366                        PARSER_ERROR,
367                        "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid, Name),
368                        File = self.FdfProfile.PcdFileLineDict[Name, Guid][0],
369                        Line = self.FdfProfile.PcdFileLineDict[Name, Guid][1]
370                    )
371                else:
372                    # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
373                    if (Name, Guid, TAB_PCDS_FIXED_AT_BUILD) in DecPcdsKey \
374                        or (Name, Guid, TAB_PCDS_PATCHABLE_IN_MODULE) in DecPcdsKey \
375                        or (Name, Guid, TAB_PCDS_FEATURE_FLAG) in DecPcdsKey:
376                        Platform.AddPcd(Name, Guid, PcdSet[Name, Guid])
377                        continue
378                    elif (Name, Guid, TAB_PCDS_DYNAMIC) in DecPcdsKey or (Name, Guid, TAB_PCDS_DYNAMIC_EX) in DecPcdsKey:
379                        EdkLogger.error(
380                                'build',
381                                PARSER_ERROR,
382                                "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid, Name),
383                                File = self.FdfProfile.PcdFileLineDict[Name, Guid][0],
384                                Line = self.FdfProfile.PcdFileLineDict[Name, Guid][1]
385                        )
386
387            Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)
388            #
389            # Explicitly collect platform's dynamic PCDs
390            #
391            Pa.CollectPlatformDynamicPcds()
392            Pa.CollectFixedAtBuildPcds()
393            self.AutoGenObjectList.append(Pa)
394
395        #
396        # Check PCDs token value conflict in each DEC file.
397        #
398        self._CheckAllPcdsTokenValueConflict()
399
400        #
401        # Check PCD type and definition between DSC and DEC
402        #
403        self._CheckPcdDefineAndType()
404
405#         if self.FdfFile:
406#             self._CheckDuplicateInFV(Fdf)
407
408        self._BuildDir = None
409        self._FvDir = None
410        self._MakeFileDir = None
411        self._BuildCommand = None
412
413        return True
414
415    ## _CheckDuplicateInFV() method
416    #
417    # Check whether there is duplicate modules/files exist in FV section.
418    # The check base on the file GUID;
419    #
420    def _CheckDuplicateInFV(self, Fdf):
421        for Fv in Fdf.Profile.FvDict:
422            _GuidDict = {}
423            for FfsFile in Fdf.Profile.FvDict[Fv].FfsList:
424                if FfsFile.InfFileName and FfsFile.NameGuid == None:
425                    #
426                    # Get INF file GUID
427                    #
428                    InfFoundFlag = False
429                    for Pa in self.AutoGenObjectList:
430                        if InfFoundFlag:
431                            break
432                        for Module in Pa.ModuleAutoGenList:
433                            if path.normpath(Module.MetaFile.File) == path.normpath(FfsFile.InfFileName):
434                                InfFoundFlag = True
435                                if not Module.Guid.upper() in _GuidDict.keys():
436                                    _GuidDict[Module.Guid.upper()] = FfsFile
437                                    break
438                                else:
439                                    EdkLogger.error("build",
440                                                    FORMAT_INVALID,
441                                                    "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,
442                                                                                                                                   FfsFile.CurrentLineContent,
443                                                                                                                                   _GuidDict[Module.Guid.upper()].CurrentLineNum,
444                                                                                                                                   _GuidDict[Module.Guid.upper()].CurrentLineContent,
445                                                                                                                                   Module.Guid.upper()),
446                                                    ExtraData=self.FdfFile)
447                    #
448                    # Some INF files not have entity in DSC file.
449                    #
450                    if not InfFoundFlag:
451                        if FfsFile.InfFileName.find('$') == -1:
452                            InfPath = NormPath(FfsFile.InfFileName)
453                            if not os.path.exists(InfPath):
454                                EdkLogger.error('build', GENFDS_ERROR, "Non-existant Module %s !" % (FfsFile.InfFileName))
455
456                            PathClassObj = PathClass(FfsFile.InfFileName, self.WorkspaceDir)
457                            #
458                            # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use
459                            # BuildObject from one of AutoGenObjectList is enough.
460                            #
461                            InfObj = self.AutoGenObjectList[0].BuildDatabase.WorkspaceDb.BuildObject[PathClassObj, 'COMMON', self.BuildTarget, self.ToolChain]
462                            if not InfObj.Guid.upper() in _GuidDict.keys():
463                                _GuidDict[InfObj.Guid.upper()] = FfsFile
464                            else:
465                                EdkLogger.error("build",
466                                                FORMAT_INVALID,
467                                                "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,
468                                                                                                                               FfsFile.CurrentLineContent,
469                                                                                                                               _GuidDict[InfObj.Guid.upper()].CurrentLineNum,
470                                                                                                                               _GuidDict[InfObj.Guid.upper()].CurrentLineContent,
471                                                                                                                               InfObj.Guid.upper()),
472                                                ExtraData=self.FdfFile)
473                        InfFoundFlag = False
474
475                if FfsFile.NameGuid != None:
476                    _CheckPCDAsGuidPattern = re.compile("^PCD\(.+\..+\)$")
477
478                    #
479                    # If the NameGuid reference a PCD name.
480                    # The style must match: PCD(xxxx.yyy)
481                    #
482                    if _CheckPCDAsGuidPattern.match(FfsFile.NameGuid):
483                        #
484                        # Replace the PCD value.
485                        #
486                        _PcdName = FfsFile.NameGuid.lstrip("PCD(").rstrip(")")
487                        PcdFoundFlag = False
488                        for Pa in self.AutoGenObjectList:
489                            if not PcdFoundFlag:
490                                for PcdItem in Pa.AllPcdList:
491                                    if (PcdItem.TokenSpaceGuidCName + "." + PcdItem.TokenCName) == _PcdName:
492                                        #
493                                        # First convert from CFormatGuid to GUID string
494                                        #
495                                        _PcdGuidString = GuidStructureStringToGuidString(PcdItem.DefaultValue)
496
497                                        if not _PcdGuidString:
498                                            #
499                                            # Then try Byte array.
500                                            #
501                                            _PcdGuidString = GuidStructureByteArrayToGuidString(PcdItem.DefaultValue)
502
503                                        if not _PcdGuidString:
504                                            #
505                                            # Not Byte array or CFormat GUID, raise error.
506                                            #
507                                            EdkLogger.error("build",
508                                                            FORMAT_INVALID,
509                                                            "The format of PCD value is incorrect. PCD: %s , Value: %s\n" % (_PcdName, PcdItem.DefaultValue),
510                                                            ExtraData=self.FdfFile)
511
512                                        if not _PcdGuidString.upper() in _GuidDict.keys():
513                                            _GuidDict[_PcdGuidString.upper()] = FfsFile
514                                            PcdFoundFlag = True
515                                            break
516                                        else:
517                                            EdkLogger.error("build",
518                                                            FORMAT_INVALID,
519                                                            "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,
520                                                                                                                                           FfsFile.CurrentLineContent,
521                                                                                                                                           _GuidDict[_PcdGuidString.upper()].CurrentLineNum,
522                                                                                                                                           _GuidDict[_PcdGuidString.upper()].CurrentLineContent,
523                                                                                                                                           FfsFile.NameGuid.upper()),
524                                                            ExtraData=self.FdfFile)
525
526                    if not FfsFile.NameGuid.upper() in _GuidDict.keys():
527                        _GuidDict[FfsFile.NameGuid.upper()] = FfsFile
528                    else:
529                        #
530                        # Two raw file GUID conflict.
531                        #
532                        EdkLogger.error("build",
533                                        FORMAT_INVALID,
534                                        "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,
535                                                                                                                       FfsFile.CurrentLineContent,
536                                                                                                                       _GuidDict[FfsFile.NameGuid.upper()].CurrentLineNum,
537                                                                                                                       _GuidDict[FfsFile.NameGuid.upper()].CurrentLineContent,
538                                                                                                                       FfsFile.NameGuid.upper()),
539                                        ExtraData=self.FdfFile)
540
541
542    def _CheckPcdDefineAndType(self):
543        PcdTypeList = [
544            "FixedAtBuild", "PatchableInModule", "FeatureFlag",
545            "Dynamic", #"DynamicHii", "DynamicVpd",
546            "DynamicEx", # "DynamicExHii", "DynamicExVpd"
547        ]
548
549        # This dict store PCDs which are not used by any modules with specified arches
550        UnusedPcd = sdict()
551        for Pa in self.AutoGenObjectList:
552            # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
553            for Pcd in Pa.Platform.Pcds:
554                PcdType = Pa.Platform.Pcds[Pcd].Type
555
556                # If no PCD type, this PCD comes from FDF
557                if not PcdType:
558                    continue
559
560                # Try to remove Hii and Vpd suffix
561                if PcdType.startswith("DynamicEx"):
562                    PcdType = "DynamicEx"
563                elif PcdType.startswith("Dynamic"):
564                    PcdType = "Dynamic"
565
566                for Package in Pa.PackageList:
567                    # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
568                    if (Pcd[0], Pcd[1], PcdType) in Package.Pcds:
569                        break
570                    for Type in PcdTypeList:
571                        if (Pcd[0], Pcd[1], Type) in Package.Pcds:
572                            EdkLogger.error(
573                                'build',
574                                FORMAT_INVALID,
575                                "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
576                                % (Pa.Platform.Pcds[Pcd].Type, Pcd[1], Pcd[0], Type),
577                                ExtraData=None
578                            )
579                            return
580                else:
581                    UnusedPcd.setdefault(Pcd, []).append(Pa.Arch)
582
583        for Pcd in UnusedPcd:
584            EdkLogger.warn(
585                'build',
586                "The PCD was not specified by any INF module in the platform for the given architecture.\n"
587                "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
588                % (Pcd[1], Pcd[0], os.path.basename(str(self.MetaFile)), str(UnusedPcd[Pcd])),
589                ExtraData=None
590            )
591
592    def __repr__(self):
593        return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))
594
595    ## Return the directory to store FV files
596    def _GetFvDir(self):
597        if self._FvDir == None:
598            self._FvDir = path.join(self.BuildDir, 'FV')
599        return self._FvDir
600
601    ## Return the directory to store all intermediate and final files built
602    def _GetBuildDir(self):
603        return self.AutoGenObjectList[0].BuildDir
604
605    ## Return the build output directory platform specifies
606    def _GetOutputDir(self):
607        return self.Platform.OutputDirectory
608
609    ## Return platform name
610    def _GetName(self):
611        return self.Platform.PlatformName
612
613    ## Return meta-file GUID
614    def _GetGuid(self):
615        return self.Platform.Guid
616
617    ## Return platform version
618    def _GetVersion(self):
619        return self.Platform.Version
620
621    ## Return paths of tools
622    def _GetToolDefinition(self):
623        return self.AutoGenObjectList[0].ToolDefinition
624
625    ## Return directory of platform makefile
626    #
627    #   @retval     string  Makefile directory
628    #
629    def _GetMakeFileDir(self):
630        if self._MakeFileDir == None:
631            self._MakeFileDir = self.BuildDir
632        return self._MakeFileDir
633
634    ## Return build command string
635    #
636    #   @retval     string  Build command string
637    #
638    def _GetBuildCommand(self):
639        if self._BuildCommand == None:
640            # BuildCommand should be all the same. So just get one from platform AutoGen
641            self._BuildCommand = self.AutoGenObjectList[0].BuildCommand
642        return self._BuildCommand
643
644    ## Check the PCDs token value conflict in each DEC file.
645    #
646    # Will cause build break and raise error message while two PCDs conflict.
647    #
648    # @return  None
649    #
650    def _CheckAllPcdsTokenValueConflict(self):
651        for Pa in self.AutoGenObjectList:
652            for Package in Pa.PackageList:
653                PcdList = Package.Pcds.values()
654                PcdList.sort(lambda x, y: cmp(int(x.TokenValue, 0), int(y.TokenValue, 0)))
655                Count = 0
656                while (Count < len(PcdList) - 1) :
657                    Item = PcdList[Count]
658                    ItemNext = PcdList[Count + 1]
659                    #
660                    # Make sure in the same token space the TokenValue should be unique
661                    #
662                    if (int(Item.TokenValue, 0) == int(ItemNext.TokenValue, 0)):
663                        SameTokenValuePcdList = []
664                        SameTokenValuePcdList.append(Item)
665                        SameTokenValuePcdList.append(ItemNext)
666                        RemainPcdListLength = len(PcdList) - Count - 2
667                        for ValueSameCount in range(RemainPcdListLength):
668                            if int(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount].TokenValue, 0) == int(Item.TokenValue, 0):
669                                SameTokenValuePcdList.append(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount])
670                            else:
671                                break;
672                        #
673                        # Sort same token value PCD list with TokenGuid and TokenCName
674                        #
675                        SameTokenValuePcdList.sort(lambda x, y: cmp("%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName), "%s.%s" % (y.TokenSpaceGuidCName, y.TokenCName)))
676                        SameTokenValuePcdListCount = 0
677                        while (SameTokenValuePcdListCount < len(SameTokenValuePcdList) - 1):
678                            TemListItem = SameTokenValuePcdList[SameTokenValuePcdListCount]
679                            TemListItemNext = SameTokenValuePcdList[SameTokenValuePcdListCount + 1]
680
681                            if (TemListItem.TokenSpaceGuidCName == TemListItemNext.TokenSpaceGuidCName) and (TemListItem.TokenCName != TemListItemNext.TokenCName):
682                                EdkLogger.error(
683                                            'build',
684                                            FORMAT_INVALID,
685                                            "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
686                                            % (TemListItem.TokenValue, TemListItem.TokenSpaceGuidCName, TemListItem.TokenCName, TemListItemNext.TokenSpaceGuidCName, TemListItemNext.TokenCName, Package),
687                                            ExtraData=None
688                                            )
689                            SameTokenValuePcdListCount += 1
690                        Count += SameTokenValuePcdListCount
691                    Count += 1
692
693                PcdList = Package.Pcds.values()
694                PcdList.sort(lambda x, y: cmp("%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName), "%s.%s" % (y.TokenSpaceGuidCName, y.TokenCName)))
695                Count = 0
696                while (Count < len(PcdList) - 1) :
697                    Item = PcdList[Count]
698                    ItemNext = PcdList[Count + 1]
699                    #
700                    # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
701                    #
702                    if (Item.TokenSpaceGuidCName == ItemNext.TokenSpaceGuidCName) and (Item.TokenCName == ItemNext.TokenCName) and (int(Item.TokenValue, 0) != int(ItemNext.TokenValue, 0)):
703                        EdkLogger.error(
704                                    'build',
705                                    FORMAT_INVALID,
706                                    "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
707                                    % (Item.TokenValue, Item.TokenSpaceGuidCName, Item.TokenCName, Package),
708                                    ExtraData=None
709                                    )
710                    Count += 1
711    ## Generate fds command
712    def _GenFdsCommand(self):
713        return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()
714
715    ## Create makefile for the platform and modules in it
716    #
717    #   @param      CreateDepsMakeFile      Flag indicating if the makefile for
718    #                                       modules will be created as well
719    #
720    def CreateMakeFile(self, CreateDepsMakeFile=False):
721        if CreateDepsMakeFile:
722            for Pa in self.AutoGenObjectList:
723                Pa.CreateMakeFile(CreateDepsMakeFile)
724
725    ## Create autogen code for platform and modules
726    #
727    #  Since there's no autogen code for platform, this method will do nothing
728    #  if CreateModuleCodeFile is set to False.
729    #
730    #   @param      CreateDepsCodeFile      Flag indicating if creating module's
731    #                                       autogen code file or not
732    #
733    def CreateCodeFile(self, CreateDepsCodeFile=False):
734        if not CreateDepsCodeFile:
735            return
736        for Pa in self.AutoGenObjectList:
737            Pa.CreateCodeFile(CreateDepsCodeFile)
738
739    ## Create AsBuilt INF file the platform
740    #
741    def CreateAsBuiltInf(self):
742        return
743
744    Name                = property(_GetName)
745    Guid                = property(_GetGuid)
746    Version             = property(_GetVersion)
747    OutputDir           = property(_GetOutputDir)
748
749    ToolDefinition      = property(_GetToolDefinition)       # toolcode : tool path
750
751    BuildDir            = property(_GetBuildDir)
752    FvDir               = property(_GetFvDir)
753    MakeFileDir         = property(_GetMakeFileDir)
754    BuildCommand        = property(_GetBuildCommand)
755    GenFdsCommand       = property(_GenFdsCommand)
756
757## AutoGen class for platform
758#
759#  PlatformAutoGen class will process the original information in platform
760#  file in order to generate makefile for platform.
761#
762class PlatformAutoGen(AutoGen):
763    #
764    # Used to store all PCDs for both PEI and DXE phase, in order to generate
765    # correct PCD database
766    #
767    _DynaPcdList_ = []
768    _NonDynaPcdList_ = []
769
770    #
771    # The priority list while override build option
772    #
773    PrioList = {"0x11111"  : 16,     #  TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
774                "0x01111"  : 15,     #  ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
775                "0x10111"  : 14,     #  TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
776                "0x00111"  : 13,     #  ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
777                "0x11011"  : 12,     #  TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
778                "0x01011"  : 11,     #  ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
779                "0x10011"  : 10,     #  TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
780                "0x00011"  : 9,      #  ******_*********_****_COMMANDTYPE_ATTRIBUTE
781                "0x11101"  : 8,      #  TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
782                "0x01101"  : 7,      #  ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
783                "0x10101"  : 6,      #  TARGET_*********_ARCH_***********_ATTRIBUTE
784                "0x00101"  : 5,      #  ******_*********_ARCH_***********_ATTRIBUTE
785                "0x11001"  : 4,      #  TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
786                "0x01001"  : 3,      #  ******_TOOLCHAIN_****_***********_ATTRIBUTE
787                "0x10001"  : 2,      #  TARGET_*********_****_***********_ATTRIBUTE
788                "0x00001"  : 1}      #  ******_*********_****_***********_ATTRIBUTE (Lowest)
789
790    ## The real constructor of PlatformAutoGen
791    #
792    #  This method is not supposed to be called by users of PlatformAutoGen. It's
793    #  only used by factory method __new__() to do real initialization work for an
794    #  object of PlatformAutoGen
795    #
796    #   @param      Workspace       WorkspaceAutoGen object
797    #   @param      PlatformFile    Platform file (DSC file)
798    #   @param      Target          Build target (DEBUG, RELEASE)
799    #   @param      Toolchain       Name of tool chain
800    #   @param      Arch            arch of the platform supports
801    #
802    def _Init(self, Workspace, PlatformFile, Target, Toolchain, Arch):
803        EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))
804        GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)
805
806        self.MetaFile = PlatformFile
807        self.Workspace = Workspace
808        self.WorkspaceDir = Workspace.WorkspaceDir
809        self.ToolChain = Toolchain
810        self.BuildTarget = Target
811        self.Arch = Arch
812        self.SourceDir = PlatformFile.SubDir
813        self.SourceOverrideDir = None
814        self.FdTargetList = self.Workspace.FdTargetList
815        self.FvTargetList = self.Workspace.FvTargetList
816        self.AllPcdList = []
817        # get the original module/package/platform objects
818        self.BuildDatabase = Workspace.BuildDatabase
819
820        # flag indicating if the makefile/C-code file has been created or not
821        self.IsMakeFileCreated  = False
822        self.IsCodeFileCreated  = False
823
824        self._Platform   = None
825        self._Name       = None
826        self._Guid       = None
827        self._Version    = None
828
829        self._BuildRule = None
830        self._SourceDir = None
831        self._BuildDir = None
832        self._OutputDir = None
833        self._FvDir = None
834        self._MakeFileDir = None
835        self._FdfFile = None
836
837        self._PcdTokenNumber = None    # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
838        self._DynamicPcdList = None    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
839        self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
840        self._NonDynamicPcdDict = {}
841
842        self._ToolDefinitions = None
843        self._ToolDefFile = None          # toolcode : tool path
844        self._ToolChainFamily = None
845        self._BuildRuleFamily = None
846        self._BuildOption = None          # toolcode : option
847        self._EdkBuildOption = None       # edktoolcode : option
848        self._EdkIIBuildOption = None     # edkiitoolcode : option
849        self._PackageList = None
850        self._ModuleAutoGenList  = None
851        self._LibraryAutoGenList = None
852        self._BuildCommand = None
853        self._AsBuildInfList = []
854        self._AsBuildModuleList = []
855        if GlobalData.gFdfParser != None:
856            self._AsBuildInfList = GlobalData.gFdfParser.Profile.InfList
857            for Inf in self._AsBuildInfList:
858                InfClass = PathClass(NormPath(Inf), GlobalData.gWorkspace, self.Arch)
859                M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]
860                if not M.IsSupportedArch:
861                    continue
862                self._AsBuildModuleList.append(InfClass)
863        # get library/modules for build
864        self.LibraryBuildDirectoryList = []
865        self.ModuleBuildDirectoryList = []
866        return True
867
868    def __repr__(self):
869        return "%s [%s]" % (self.MetaFile, self.Arch)
870
871    ## Create autogen code for platform and modules
872    #
873    #  Since there's no autogen code for platform, this method will do nothing
874    #  if CreateModuleCodeFile is set to False.
875    #
876    #   @param      CreateModuleCodeFile    Flag indicating if creating module's
877    #                                       autogen code file or not
878    #
879    def CreateCodeFile(self, CreateModuleCodeFile=False):
880        # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
881        if self.IsCodeFileCreated or not CreateModuleCodeFile:
882            return
883
884        for Ma in self.ModuleAutoGenList:
885            Ma.CreateCodeFile(True)
886
887        # don't do this twice
888        self.IsCodeFileCreated = True
889
890    ## Generate Fds Command
891    def _GenFdsCommand(self):
892        return self.Workspace.GenFdsCommand
893
894    ## Create makefile for the platform and mdoules in it
895    #
896    #   @param      CreateModuleMakeFile    Flag indicating if the makefile for
897    #                                       modules will be created as well
898    #
899    def CreateMakeFile(self, CreateModuleMakeFile=False):
900        if CreateModuleMakeFile:
901            for ModuleFile in self.Platform.Modules:
902                Ma = ModuleAutoGen(self.Workspace, ModuleFile, self.BuildTarget,
903                                   self.ToolChain, self.Arch, self.MetaFile)
904                Ma.CreateMakeFile(True)
905                #Ma.CreateAsBuiltInf()
906
907        # no need to create makefile for the platform more than once
908        if self.IsMakeFileCreated:
909            return
910
911        # create library/module build dirs for platform
912        Makefile = GenMake.PlatformMakefile(self)
913        self.LibraryBuildDirectoryList = Makefile.GetLibraryBuildDirectoryList()
914        self.ModuleBuildDirectoryList = Makefile.GetModuleBuildDirectoryList()
915
916        self.IsMakeFileCreated = True
917
918    ## Deal with Shared FixedAtBuild Pcds
919    #
920    def CollectFixedAtBuildPcds(self):
921        for LibAuto in self.LibraryAutoGenList:
922            FixedAtBuildPcds = {}
923            ShareFixedAtBuildPcdsSameValue = {}
924            for Module in LibAuto._ReferenceModules:
925                for Pcd in Module.FixedAtBuildPcds + LibAuto.FixedAtBuildPcds:
926                    key = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName))
927                    if key not in FixedAtBuildPcds:
928                        ShareFixedAtBuildPcdsSameValue[key] = True
929                        FixedAtBuildPcds[key] = Pcd.DefaultValue
930                    else:
931                        if FixedAtBuildPcds[key] != Pcd.DefaultValue:
932                            ShareFixedAtBuildPcdsSameValue[key] = False
933            for Pcd in LibAuto.FixedAtBuildPcds:
934                key = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName))
935                if (Pcd.TokenCName,Pcd.TokenSpaceGuidCName) not in self.NonDynamicPcdDict:
936                    continue
937                else:
938                    DscPcd = self.NonDynamicPcdDict[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName)]
939                    if DscPcd.Type != "FixedAtBuild":
940                        continue
941                if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]:
942                    LibAuto.ConstPcd[key] = Pcd.DefaultValue
943
944    ## Collect dynamic PCDs
945    #
946    #  Gather dynamic PCDs list from each module and their settings from platform
947    #  This interface should be invoked explicitly when platform action is created.
948    #
949    def CollectPlatformDynamicPcds(self):
950        # for gathering error information
951        NoDatumTypePcdList = set()
952        PcdNotInDb = []
953        self._GuidValue = {}
954        FdfModuleList = []
955        for InfName in self._AsBuildInfList:
956            InfName = mws.join(self.WorkspaceDir, InfName)
957            FdfModuleList.append(os.path.normpath(InfName))
958        for F in self.Platform.Modules.keys():
959            M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self.MetaFile)
960            #GuidValue.update(M.Guids)
961
962            self.Platform.Modules[F].M = M
963
964            for PcdFromModule in M.ModulePcdList + M.LibraryPcdList:
965                # make sure that the "VOID*" kind of datum has MaxDatumSize set
966                if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize in [None, '']:
967                    NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, F))
968
969                # Check the PCD from Binary INF or Source INF
970                if M.IsBinaryModule == True:
971                    PcdFromModule.IsFromBinaryInf = True
972
973                # Check the PCD from DSC or not
974                if (PcdFromModule.TokenCName, PcdFromModule.TokenSpaceGuidCName) in self.Platform.Pcds.keys():
975                    PcdFromModule.IsFromDsc = True
976                else:
977                    PcdFromModule.IsFromDsc = False
978                if PcdFromModule.Type in GenC.gDynamicPcd or PcdFromModule.Type in GenC.gDynamicExPcd:
979                    if F.Path not in FdfModuleList:
980                        # If one of the Source built modules listed in the DSC is not listed
981                        # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
982                        # access method (it is only listed in the DEC file that declares the
983                        # PCD as PcdsDynamic), then build tool will report warning message
984                        # notify the PI that they are attempting to build a module that must
985                        # be included in a flash image in order to be functional. These Dynamic
986                        # PCD will not be added into the Database unless it is used by other
987                        # modules that are included in the FDF file.
988                        if PcdFromModule.Type in GenC.gDynamicPcd and \
989                            PcdFromModule.IsFromBinaryInf == False:
990                            # Print warning message to let the developer make a determine.
991                            if PcdFromModule not in PcdNotInDb:
992                                PcdNotInDb.append(PcdFromModule)
993                            continue
994                        # If one of the Source built modules listed in the DSC is not listed in
995                        # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
996                        # access method (it is only listed in the DEC file that declares the
997                        # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
998                        # PCD to the Platform's PCD Database.
999                        if PcdFromModule.Type in GenC.gDynamicExPcd:
1000                            if PcdFromModule not in PcdNotInDb:
1001                                PcdNotInDb.append(PcdFromModule)
1002                            continue
1003                    #
1004                    # If a dynamic PCD used by a PEM module/PEI module & DXE module,
1005                    # it should be stored in Pcd PEI database, If a dynamic only
1006                    # used by DXE module, it should be stored in DXE PCD database.
1007                    # The default Phase is DXE
1008                    #
1009                    if M.ModuleType in ["PEIM", "PEI_CORE"]:
1010                        PcdFromModule.Phase = "PEI"
1011                    if PcdFromModule not in self._DynaPcdList_:
1012                        self._DynaPcdList_.append(PcdFromModule)
1013                    elif PcdFromModule.Phase == 'PEI':
1014                        # overwrite any the same PCD existing, if Phase is PEI
1015                        Index = self._DynaPcdList_.index(PcdFromModule)
1016                        self._DynaPcdList_[Index] = PcdFromModule
1017                elif PcdFromModule not in self._NonDynaPcdList_:
1018                    self._NonDynaPcdList_.append(PcdFromModule)
1019                elif PcdFromModule in self._NonDynaPcdList_ and PcdFromModule.IsFromBinaryInf == True:
1020                    Index = self._NonDynaPcdList_.index(PcdFromModule)
1021                    if self._NonDynaPcdList_[Index].IsFromBinaryInf == False:
1022                        #The PCD from Binary INF will override the same one from source INF
1023                        self._NonDynaPcdList_.remove (self._NonDynaPcdList_[Index])
1024                        PcdFromModule.Pending = False
1025                        self._NonDynaPcdList_.append (PcdFromModule)
1026        # Parse the DynamicEx PCD from the AsBuild INF module list of FDF.
1027        DscModuleList = []
1028        for ModuleInf in self.Platform.Modules.keys():
1029            DscModuleList.append (os.path.normpath(ModuleInf.Path))
1030        # add the PCD from modules that listed in FDF but not in DSC to Database
1031        for InfName in FdfModuleList:
1032            if InfName not in DscModuleList:
1033                InfClass = PathClass(InfName)
1034                M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]
1035                # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
1036                # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
1037                # For binary module, if in current arch, we need to list the PCDs into database.
1038                if not M.IsSupportedArch:
1039                    continue
1040                # Override the module PCD setting by platform setting
1041                ModulePcdList = self.ApplyPcdSetting(M, M.Pcds)
1042                for PcdFromModule in ModulePcdList:
1043                    PcdFromModule.IsFromBinaryInf = True
1044                    PcdFromModule.IsFromDsc = False
1045                    # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1046                    if PcdFromModule.Type not in GenC.gDynamicExPcd and PcdFromModule.Type not in TAB_PCDS_PATCHABLE_IN_MODULE:
1047                        EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
1048                                        File=self.MetaFile,
1049                                        ExtraData="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1050                                        % (PcdFromModule.Type, PcdFromModule.TokenCName, InfName))
1051                    # make sure that the "VOID*" kind of datum has MaxDatumSize set
1052                    if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize in [None, '']:
1053                        NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, InfName))
1054                    if M.ModuleType in ["PEIM", "PEI_CORE"]:
1055                        PcdFromModule.Phase = "PEI"
1056                    if PcdFromModule not in self._DynaPcdList_ and PcdFromModule.Type in GenC.gDynamicExPcd:
1057                        self._DynaPcdList_.append(PcdFromModule)
1058                    elif PcdFromModule not in self._NonDynaPcdList_ and PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE:
1059                        self._NonDynaPcdList_.append(PcdFromModule)
1060                    if PcdFromModule in self._DynaPcdList_ and PcdFromModule.Phase == 'PEI' and PcdFromModule.Type in GenC.gDynamicExPcd:
1061                        # Overwrite the phase of any the same PCD existing, if Phase is PEI.
1062                        # It is to solve the case that a dynamic PCD used by a PEM module/PEI
1063                        # module & DXE module at a same time.
1064                        # Overwrite the type of the PCDs in source INF by the type of AsBuild
1065                        # INF file as DynamicEx.
1066                        Index = self._DynaPcdList_.index(PcdFromModule)
1067                        self._DynaPcdList_[Index].Phase = PcdFromModule.Phase
1068                        self._DynaPcdList_[Index].Type = PcdFromModule.Type
1069        for PcdFromModule in self._NonDynaPcdList_:
1070            # If a PCD is not listed in the DSC file, but binary INF files used by
1071            # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1072            # section, AND all source INF files used by this platform the build
1073            # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1074            # section, then the tools must NOT add the PCD to the Platform's PCD
1075            # Database; the build must assign the access method for this PCD as
1076            # PcdsPatchableInModule.
1077            if PcdFromModule not in self._DynaPcdList_:
1078                continue
1079            Index = self._DynaPcdList_.index(PcdFromModule)
1080            if PcdFromModule.IsFromDsc == False and \
1081                PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE and \
1082                PcdFromModule.IsFromBinaryInf == True and \
1083                self._DynaPcdList_[Index].IsFromBinaryInf == False:
1084                Index = self._DynaPcdList_.index(PcdFromModule)
1085                self._DynaPcdList_.remove (self._DynaPcdList_[Index])
1086
1087        # print out error information and break the build, if error found
1088        if len(NoDatumTypePcdList) > 0:
1089            NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)
1090            EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
1091                            File=self.MetaFile,
1092                            ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1093                                      % NoDatumTypePcdListString)
1094        self._NonDynamicPcdList = self._NonDynaPcdList_
1095        self._DynamicPcdList = self._DynaPcdList_
1096        #
1097        # Sort dynamic PCD list to:
1098        # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1099        #    try to be put header of dynamicd List
1100        # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1101        #
1102        # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1103        #
1104        UnicodePcdArray = []
1105        HiiPcdArray     = []
1106        OtherPcdArray   = []
1107        VpdPcdDict      = {}
1108        VpdFile               = VpdInfoFile.VpdInfoFile()
1109        NeedProcessVpdMapFile = False
1110
1111        if (self.Workspace.ArchList[-1] == self.Arch):
1112            for Pcd in self._DynamicPcdList:
1113                # just pick the a value to determine whether is unicode string type
1114                Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]
1115                Sku.VpdOffset = Sku.VpdOffset.strip()
1116
1117                PcdValue = Sku.DefaultValue
1118                if Pcd.DatumType == 'VOID*' and PcdValue.startswith("L"):
1119                    # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1120                    UnicodePcdArray.append(Pcd)
1121                elif len(Sku.VariableName) > 0:
1122                    # if found HII type PCD then insert to right of UnicodeIndex
1123                    HiiPcdArray.append(Pcd)
1124                else:
1125                    OtherPcdArray.append(Pcd)
1126                if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
1127                    VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd
1128
1129            PlatformPcds = self.Platform.Pcds.keys()
1130            PlatformPcds.sort()
1131            #
1132            # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1133            #
1134            for PcdKey in PlatformPcds:
1135                Pcd = self.Platform.Pcds[PcdKey]
1136                if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD] and \
1137                   PcdKey in VpdPcdDict:
1138                    Pcd = VpdPcdDict[PcdKey]
1139                    for (SkuName,Sku) in Pcd.SkuInfoList.items():
1140                        Sku.VpdOffset = Sku.VpdOffset.strip()
1141                        VpdFile.Add(Pcd, Sku.VpdOffset)
1142                        # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1143                        if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":
1144                            NeedProcessVpdMapFile = True
1145                            if self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == '':
1146                                EdkLogger.error("Build", FILE_NOT_FOUND, \
1147                                                "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")
1148
1149
1150            #
1151            # Fix the PCDs define in VPD PCD section that never referenced by module.
1152            # An example is PCD for signature usage.
1153            #
1154            for DscPcd in PlatformPcds:
1155                DscPcdEntry = self.Platform.Pcds[DscPcd]
1156                if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
1157                    if not (self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == ''):
1158                        FoundFlag = False
1159                        for VpdPcd in VpdFile._VpdArray.keys():
1160                            # This PCD has been referenced by module
1161                            if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
1162                               (VpdPcd.TokenCName == DscPcdEntry.TokenCName):
1163                                    FoundFlag = True
1164
1165                        # Not found, it should be signature
1166                        if not FoundFlag :
1167                            # just pick the a value to determine whether is unicode string type
1168                            for (SkuName,Sku) in DscPcdEntry.SkuInfoList.items():
1169                                Sku.VpdOffset = Sku.VpdOffset.strip()
1170
1171                                # Need to iterate DEC pcd information to get the value & datumtype
1172                                for eachDec in self.PackageList:
1173                                    for DecPcd in eachDec.Pcds:
1174                                        DecPcdEntry = eachDec.Pcds[DecPcd]
1175                                        if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
1176                                           (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):
1177                                            # Print warning message to let the developer make a determine.
1178                                            EdkLogger.warn("build", "Unreferenced vpd pcd used!",
1179                                                            File=self.MetaFile, \
1180                                                            ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \
1181                                                            %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path))
1182
1183                                            DscPcdEntry.DatumType    = DecPcdEntry.DatumType
1184                                            DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue
1185                                            DscPcdEntry.TokenValue = DecPcdEntry.TokenValue
1186                                            DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName]
1187                                            # Only fix the value while no value provided in DSC file.
1188                                            if (Sku.DefaultValue == "" or Sku.DefaultValue==None):
1189                                                DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]].DefaultValue = DecPcdEntry.DefaultValue
1190
1191                                if DscPcdEntry not in self._DynamicPcdList:
1192                                    self._DynamicPcdList.append(DscPcdEntry)
1193#                                Sku = DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]]
1194                                Sku.VpdOffset = Sku.VpdOffset.strip()
1195                                PcdValue = Sku.DefaultValue
1196                                VpdFile.Add(DscPcdEntry, Sku.VpdOffset)
1197                                if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":
1198                                    NeedProcessVpdMapFile = True
1199                            if DscPcdEntry.DatumType == 'VOID*' and PcdValue.startswith("L"):
1200                                UnicodePcdArray.append(DscPcdEntry)
1201                            elif len(Sku.VariableName) > 0:
1202                                HiiPcdArray.append(DscPcdEntry)
1203                            else:
1204                                OtherPcdArray.append(DscPcdEntry)
1205
1206                                # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1207
1208
1209
1210            if (self.Platform.FlashDefinition == None or self.Platform.FlashDefinition == '') and \
1211               VpdFile.GetCount() != 0:
1212                EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
1213                                "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))
1214
1215            if VpdFile.GetCount() != 0:
1216                DscTimeStamp = self.Platform.MetaFile.TimeStamp
1217                FvPath = os.path.join(self.BuildDir, "FV")
1218                if not os.path.exists(FvPath):
1219                    try:
1220                        os.makedirs(FvPath)
1221                    except:
1222                        EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)
1223
1224
1225                VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)
1226
1227
1228                if not os.path.exists(VpdFilePath) or os.path.getmtime(VpdFilePath) < DscTimeStamp:
1229                    VpdFile.Write(VpdFilePath)
1230
1231                    # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1232                    BPDGToolName = None
1233                    for ToolDef in self.ToolDefinition.values():
1234                        if ToolDef.has_key("GUID") and ToolDef["GUID"] == self.Platform.VpdToolGuid:
1235                            if not ToolDef.has_key("PATH"):
1236                                EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)
1237                            BPDGToolName = ToolDef["PATH"]
1238                            break
1239                    # Call third party GUID BPDG tool.
1240                    if BPDGToolName != None:
1241                        VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)
1242                    else:
1243                        EdkLogger.error("Build", FILE_NOT_FOUND, "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")
1244
1245                # Process VPD map file generated by third party BPDG tool
1246                if NeedProcessVpdMapFile:
1247                    VpdMapFilePath = os.path.join(self.BuildDir, "FV", "%s.map" % self.Platform.VpdToolGuid)
1248                    if os.path.exists(VpdMapFilePath):
1249                        VpdFile.Read(VpdMapFilePath)
1250
1251                        # Fixup "*" offset
1252                        for Pcd in self._DynamicPcdList:
1253                            # just pick the a value to determine whether is unicode string type
1254                            i = 0
1255                            for (SkuName,Sku) in Pcd.SkuInfoList.items():
1256                                if Sku.VpdOffset == "*":
1257                                    Sku.VpdOffset = VpdFile.GetOffset(Pcd)[i].strip()
1258                                i += 1
1259                    else:
1260                        EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)
1261
1262            # Delete the DynamicPcdList At the last time enter into this function
1263            del self._DynamicPcdList[:]
1264        self._DynamicPcdList.extend(UnicodePcdArray)
1265        self._DynamicPcdList.extend(HiiPcdArray)
1266        self._DynamicPcdList.extend(OtherPcdArray)
1267        self.AllPcdList = self._NonDynamicPcdList + self._DynamicPcdList
1268
1269    ## Return the platform build data object
1270    def _GetPlatform(self):
1271        if self._Platform == None:
1272            self._Platform = self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
1273        return self._Platform
1274
1275    ## Return platform name
1276    def _GetName(self):
1277        return self.Platform.PlatformName
1278
1279    ## Return the meta file GUID
1280    def _GetGuid(self):
1281        return self.Platform.Guid
1282
1283    ## Return the platform version
1284    def _GetVersion(self):
1285        return self.Platform.Version
1286
1287    ## Return the FDF file name
1288    def _GetFdfFile(self):
1289        if self._FdfFile == None:
1290            if self.Workspace.FdfFile != "":
1291                self._FdfFile= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)
1292            else:
1293                self._FdfFile = ''
1294        return self._FdfFile
1295
1296    ## Return the build output directory platform specifies
1297    def _GetOutputDir(self):
1298        return self.Platform.OutputDirectory
1299
1300    ## Return the directory to store all intermediate and final files built
1301    def _GetBuildDir(self):
1302        if self._BuildDir == None:
1303            if os.path.isabs(self.OutputDir):
1304                self._BuildDir = path.join(
1305                                            path.abspath(self.OutputDir),
1306                                            self.BuildTarget + "_" + self.ToolChain,
1307                                            )
1308            else:
1309                self._BuildDir = path.join(
1310                                            self.WorkspaceDir,
1311                                            self.OutputDir,
1312                                            self.BuildTarget + "_" + self.ToolChain,
1313                                            )
1314        return self._BuildDir
1315
1316    ## Return directory of platform makefile
1317    #
1318    #   @retval     string  Makefile directory
1319    #
1320    def _GetMakeFileDir(self):
1321        if self._MakeFileDir == None:
1322            self._MakeFileDir = path.join(self.BuildDir, self.Arch)
1323        return self._MakeFileDir
1324
1325    ## Return build command string
1326    #
1327    #   @retval     string  Build command string
1328    #
1329    def _GetBuildCommand(self):
1330        if self._BuildCommand == None:
1331            self._BuildCommand = []
1332            if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
1333                self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"])
1334                if "FLAGS" in self.ToolDefinition["MAKE"]:
1335                    NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
1336                    if NewOption != '':
1337                        self._BuildCommand += SplitOption(NewOption)
1338        return self._BuildCommand
1339
1340    ## Get tool chain definition
1341    #
1342    #  Get each tool defition for given tool chain from tools_def.txt and platform
1343    #
1344    def _GetToolDefinition(self):
1345        if self._ToolDefinitions == None:
1346            ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
1347            if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:
1348                EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",
1349                                ExtraData="[%s]" % self.MetaFile)
1350            self._ToolDefinitions = {}
1351            DllPathList = set()
1352            for Def in ToolDefinition:
1353                Target, Tag, Arch, Tool, Attr = Def.split("_")
1354                if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:
1355                    continue
1356
1357                Value = ToolDefinition[Def]
1358                # don't record the DLL
1359                if Attr == "DLL":
1360                    DllPathList.add(Value)
1361                    continue
1362
1363                if Tool not in self._ToolDefinitions:
1364                    self._ToolDefinitions[Tool] = {}
1365                self._ToolDefinitions[Tool][Attr] = Value
1366
1367            ToolsDef = ''
1368            MakePath = ''
1369            if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions:
1370                if "FLAGS" not in self._ToolDefinitions["MAKE"]:
1371                    self._ToolDefinitions["MAKE"]["FLAGS"] = ""
1372                self._ToolDefinitions["MAKE"]["FLAGS"] += " -s"
1373            MakeFlags = ''
1374            for Tool in self._ToolDefinitions:
1375                for Attr in self._ToolDefinitions[Tool]:
1376                    Value = self._ToolDefinitions[Tool][Attr]
1377                    if Tool in self.BuildOption and Attr in self.BuildOption[Tool]:
1378                        # check if override is indicated
1379                        if self.BuildOption[Tool][Attr].startswith('='):
1380                            Value = self.BuildOption[Tool][Attr][1:]
1381                        else:
1382                            Value += " " + self.BuildOption[Tool][Attr]
1383
1384                    if Attr == "PATH":
1385                        # Don't put MAKE definition in the file
1386                        if Tool == "MAKE":
1387                            MakePath = Value
1388                        else:
1389                            ToolsDef += "%s = %s\n" % (Tool, Value)
1390                    elif Attr != "DLL":
1391                        # Don't put MAKE definition in the file
1392                        if Tool == "MAKE":
1393                            if Attr == "FLAGS":
1394                                MakeFlags = Value
1395                        else:
1396                            ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
1397                ToolsDef += "\n"
1398
1399            SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)
1400            for DllPath in DllPathList:
1401                os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]
1402            os.environ["MAKE_FLAGS"] = MakeFlags
1403
1404        return self._ToolDefinitions
1405
1406    ## Return the paths of tools
1407    def _GetToolDefFile(self):
1408        if self._ToolDefFile == None:
1409            self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
1410        return self._ToolDefFile
1411
1412    ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1413    def _GetToolChainFamily(self):
1414        if self._ToolChainFamily == None:
1415            ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
1416            if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
1417               or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
1418               or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:
1419                EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1420                                   % self.ToolChain)
1421                self._ToolChainFamily = "MSFT"
1422            else:
1423                self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]
1424        return self._ToolChainFamily
1425
1426    def _GetBuildRuleFamily(self):
1427        if self._BuildRuleFamily == None:
1428            ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
1429            if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
1430               or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \
1431               or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:
1432                EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1433                                   % self.ToolChain)
1434                self._BuildRuleFamily = "MSFT"
1435            else:
1436                self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]
1437        return self._BuildRuleFamily
1438
1439    ## Return the build options specific for all modules in this platform
1440    def _GetBuildOptions(self):
1441        if self._BuildOption == None:
1442            self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)
1443        return self._BuildOption
1444
1445    ## Return the build options specific for EDK modules in this platform
1446    def _GetEdkBuildOptions(self):
1447        if self._EdkBuildOption == None:
1448            self._EdkBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)
1449        return self._EdkBuildOption
1450
1451    ## Return the build options specific for EDKII modules in this platform
1452    def _GetEdkIIBuildOptions(self):
1453        if self._EdkIIBuildOption == None:
1454            self._EdkIIBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)
1455        return self._EdkIIBuildOption
1456
1457    ## Parse build_rule.txt in Conf Directory.
1458    #
1459    #   @retval     BuildRule object
1460    #
1461    def _GetBuildRule(self):
1462        if self._BuildRule == None:
1463            BuildRuleFile = None
1464            if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:
1465                BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
1466            if BuildRuleFile in [None, '']:
1467                BuildRuleFile = gDefaultBuildRuleFile
1468            self._BuildRule = BuildRule(BuildRuleFile)
1469            if self._BuildRule._FileVersion == "":
1470                self._BuildRule._FileVersion = AutoGenReqBuildRuleVerNum
1471            else:
1472                if self._BuildRule._FileVersion < AutoGenReqBuildRuleVerNum :
1473                    # If Build Rule's version is less than the version number required by the tools, halting the build.
1474                    EdkLogger.error("build", AUTOGEN_ERROR,
1475                                    ExtraData="The version number [%s] of build_rule.txt is less than the version number required by the AutoGen.(the minimum required version number is [%s])"\
1476                                     % (self._BuildRule._FileVersion, AutoGenReqBuildRuleVerNum))
1477
1478        return self._BuildRule
1479
1480    ## Summarize the packages used by modules in this platform
1481    def _GetPackageList(self):
1482        if self._PackageList == None:
1483            self._PackageList = set()
1484            for La in self.LibraryAutoGenList:
1485                self._PackageList.update(La.DependentPackageList)
1486            for Ma in self.ModuleAutoGenList:
1487                self._PackageList.update(Ma.DependentPackageList)
1488            #Collect package set information from INF of FDF
1489            PkgSet = set()
1490            for ModuleFile in self._AsBuildModuleList:
1491                if ModuleFile in self.Platform.Modules:
1492                    continue
1493                ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]
1494                PkgSet.update(ModuleData.Packages)
1495            self._PackageList = list(self._PackageList) + list (PkgSet)
1496        return self._PackageList
1497
1498    def _GetNonDynamicPcdDict(self):
1499        if self._NonDynamicPcdDict:
1500            return self._NonDynamicPcdDict
1501        for Pcd in self.NonDynamicPcdList:
1502            self._NonDynamicPcdDict[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName)] = Pcd
1503        return self._NonDynamicPcdDict
1504
1505    ## Get list of non-dynamic PCDs
1506    def _GetNonDynamicPcdList(self):
1507        if self._NonDynamicPcdList == None:
1508            self.CollectPlatformDynamicPcds()
1509        return self._NonDynamicPcdList
1510
1511    ## Get list of dynamic PCDs
1512    def _GetDynamicPcdList(self):
1513        if self._DynamicPcdList == None:
1514            self.CollectPlatformDynamicPcds()
1515        return self._DynamicPcdList
1516
1517    ## Generate Token Number for all PCD
1518    def _GetPcdTokenNumbers(self):
1519        if self._PcdTokenNumber == None:
1520            self._PcdTokenNumber = sdict()
1521            TokenNumber = 1
1522            #
1523            # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
1524            # Such as:
1525            #
1526            # Dynamic PCD:
1527            # TokenNumber 0 ~ 10
1528            # DynamicEx PCD:
1529            # TokeNumber 11 ~ 20
1530            #
1531            for Pcd in self.DynamicPcdList:
1532                if Pcd.Phase == "PEI":
1533                    if Pcd.Type in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
1534                        EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
1535                        self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1536                        TokenNumber += 1
1537
1538            for Pcd in self.DynamicPcdList:
1539                if Pcd.Phase == "PEI":
1540                    if Pcd.Type in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
1541                        EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
1542                        self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1543                        TokenNumber += 1
1544
1545            for Pcd in self.DynamicPcdList:
1546                if Pcd.Phase == "DXE":
1547                    if Pcd.Type in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
1548                        EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
1549                        self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1550                        TokenNumber += 1
1551
1552            for Pcd in self.DynamicPcdList:
1553                if Pcd.Phase == "DXE":
1554                    if Pcd.Type in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
1555                        EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
1556                        self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1557                        TokenNumber += 1
1558
1559            for Pcd in self.NonDynamicPcdList:
1560                self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1561                TokenNumber += 1
1562        return self._PcdTokenNumber
1563
1564    ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
1565    def _GetAutoGenObjectList(self):
1566        self._ModuleAutoGenList = []
1567        self._LibraryAutoGenList = []
1568        for ModuleFile in self.Platform.Modules:
1569            Ma = ModuleAutoGen(
1570                    self.Workspace,
1571                    ModuleFile,
1572                    self.BuildTarget,
1573                    self.ToolChain,
1574                    self.Arch,
1575                    self.MetaFile
1576                    )
1577            if Ma not in self._ModuleAutoGenList:
1578                self._ModuleAutoGenList.append(Ma)
1579            for La in Ma.LibraryAutoGenList:
1580                if La not in self._LibraryAutoGenList:
1581                    self._LibraryAutoGenList.append(La)
1582                if Ma not in La._ReferenceModules:
1583                    La._ReferenceModules.append(Ma)
1584
1585    ## Summarize ModuleAutoGen objects of all modules to be built for this platform
1586    def _GetModuleAutoGenList(self):
1587        if self._ModuleAutoGenList == None:
1588            self._GetAutoGenObjectList()
1589        return self._ModuleAutoGenList
1590
1591    ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
1592    def _GetLibraryAutoGenList(self):
1593        if self._LibraryAutoGenList == None:
1594            self._GetAutoGenObjectList()
1595        return self._LibraryAutoGenList
1596
1597    ## Test if a module is supported by the platform
1598    #
1599    #  An error will be raised directly if the module or its arch is not supported
1600    #  by the platform or current configuration
1601    #
1602    def ValidModule(self, Module):
1603        return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \
1604            or Module in self._AsBuildModuleList
1605
1606    ## Resolve the library classes in a module to library instances
1607    #
1608    # This method will not only resolve library classes but also sort the library
1609    # instances according to the dependency-ship.
1610    #
1611    #   @param  Module      The module from which the library classes will be resolved
1612    #
1613    #   @retval library_list    List of library instances sorted
1614    #
1615    def ApplyLibraryInstance(self, Module):
1616        ModuleType = Module.ModuleType
1617
1618        # for overridding library instances with module specific setting
1619        PlatformModule = self.Platform.Modules[str(Module)]
1620
1621        # add forced library instances (specified under LibraryClasses sections)
1622        #
1623        # If a module has a MODULE_TYPE of USER_DEFINED,
1624        # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
1625        #
1626        if Module.ModuleType != SUP_MODULE_USER_DEFINED:
1627            for LibraryClass in self.Platform.LibraryClasses.GetKeys():
1628                if LibraryClass.startswith("NULL") and self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]:
1629                    Module.LibraryClasses[LibraryClass] = self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]
1630
1631        # add forced library instances (specified in module overrides)
1632        for LibraryClass in PlatformModule.LibraryClasses:
1633            if LibraryClass.startswith("NULL"):
1634                Module.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]
1635
1636        # EdkII module
1637        LibraryConsumerList = [Module]
1638        Constructor         = []
1639        ConsumedByList      = sdict()
1640        LibraryInstance     = sdict()
1641
1642        EdkLogger.verbose("")
1643        EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
1644        while len(LibraryConsumerList) > 0:
1645            M = LibraryConsumerList.pop()
1646            for LibraryClassName in M.LibraryClasses:
1647                if LibraryClassName not in LibraryInstance:
1648                    # override library instance for this module
1649                    if LibraryClassName in PlatformModule.LibraryClasses:
1650                        LibraryPath = PlatformModule.LibraryClasses[LibraryClassName]
1651                    else:
1652                        LibraryPath = self.Platform.LibraryClasses[LibraryClassName, ModuleType]
1653                    if LibraryPath == None or LibraryPath == "":
1654                        LibraryPath = M.LibraryClasses[LibraryClassName]
1655                        if LibraryPath == None or LibraryPath == "":
1656                            EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,
1657                                            "Instance of library class [%s] is not found" % LibraryClassName,
1658                                            File=self.MetaFile,
1659                                            ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), self.Arch, str(Module)))
1660
1661                    LibraryModule = self.BuildDatabase[LibraryPath, self.Arch, self.BuildTarget, self.ToolChain]
1662                    # for those forced library instance (NULL library), add a fake library class
1663                    if LibraryClassName.startswith("NULL"):
1664                        LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType]))
1665                    elif LibraryModule.LibraryClass == None \
1666                         or len(LibraryModule.LibraryClass) == 0 \
1667                         or (ModuleType != 'USER_DEFINED'
1668                             and ModuleType not in LibraryModule.LibraryClass[0].SupModList):
1669                        # only USER_DEFINED can link against any library instance despite of its SupModList
1670                        EdkLogger.error("build", OPTION_MISSING,
1671                                        "Module type [%s] is not supported by library instance [%s]" \
1672                                        % (ModuleType, LibraryPath), File=self.MetaFile,
1673                                        ExtraData="consumed by [%s]" % str(Module))
1674
1675                    LibraryInstance[LibraryClassName] = LibraryModule
1676                    LibraryConsumerList.append(LibraryModule)
1677                    EdkLogger.verbose("\t" + str(LibraryClassName) + " : " + str(LibraryModule))
1678                else:
1679                    LibraryModule = LibraryInstance[LibraryClassName]
1680
1681                if LibraryModule == None:
1682                    continue
1683
1684                if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor:
1685                    Constructor.append(LibraryModule)
1686
1687                if LibraryModule not in ConsumedByList:
1688                    ConsumedByList[LibraryModule] = []
1689                # don't add current module itself to consumer list
1690                if M != Module:
1691                    if M in ConsumedByList[LibraryModule]:
1692                        continue
1693                    ConsumedByList[LibraryModule].append(M)
1694        #
1695        # Initialize the sorted output list to the empty set
1696        #
1697        SortedLibraryList = []
1698        #
1699        # Q <- Set of all nodes with no incoming edges
1700        #
1701        LibraryList = [] #LibraryInstance.values()
1702        Q = []
1703        for LibraryClassName in LibraryInstance:
1704            M = LibraryInstance[LibraryClassName]
1705            LibraryList.append(M)
1706            if ConsumedByList[M] == []:
1707                Q.append(M)
1708
1709        #
1710        # start the  DAG algorithm
1711        #
1712        while True:
1713            EdgeRemoved = True
1714            while Q == [] and EdgeRemoved:
1715                EdgeRemoved = False
1716                # for each node Item with a Constructor
1717                for Item in LibraryList:
1718                    if Item not in Constructor:
1719                        continue
1720                    # for each Node without a constructor with an edge e from Item to Node
1721                    for Node in ConsumedByList[Item]:
1722                        if Node in Constructor:
1723                            continue
1724                        # remove edge e from the graph if Node has no constructor
1725                        ConsumedByList[Item].remove(Node)
1726                        EdgeRemoved = True
1727                        if ConsumedByList[Item] == []:
1728                            # insert Item into Q
1729                            Q.insert(0, Item)
1730                            break
1731                    if Q != []:
1732                        break
1733            # DAG is done if there's no more incoming edge for all nodes
1734            if Q == []:
1735                break
1736
1737            # remove node from Q
1738            Node = Q.pop()
1739            # output Node
1740            SortedLibraryList.append(Node)
1741
1742            # for each node Item with an edge e from Node to Item do
1743            for Item in LibraryList:
1744                if Node not in ConsumedByList[Item]:
1745                    continue
1746                # remove edge e from the graph
1747                ConsumedByList[Item].remove(Node)
1748
1749                if ConsumedByList[Item] != []:
1750                    continue
1751                # insert Item into Q, if Item has no other incoming edges
1752                Q.insert(0, Item)
1753
1754        #
1755        # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
1756        #
1757        for Item in LibraryList:
1758            if ConsumedByList[Item] != [] and Item in Constructor and len(Constructor) > 1:
1759                ErrorMessage = "\tconsumed by " + "\n\tconsumed by ".join([str(L) for L in ConsumedByList[Item]])
1760                EdkLogger.error("build", BUILD_ERROR, 'Library [%s] with constructors has a cycle' % str(Item),
1761                                ExtraData=ErrorMessage, File=self.MetaFile)
1762            if Item not in SortedLibraryList:
1763                SortedLibraryList.append(Item)
1764
1765        #
1766        # Build the list of constructor and destructir names
1767        # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
1768        #
1769        SortedLibraryList.reverse()
1770        return SortedLibraryList
1771
1772
1773    ## Override PCD setting (type, value, ...)
1774    #
1775    #   @param  ToPcd       The PCD to be overrided
1776    #   @param  FromPcd     The PCD overrideing from
1777    #
1778    def _OverridePcd(self, ToPcd, FromPcd, Module=""):
1779        #
1780        # in case there's PCDs coming from FDF file, which have no type given.
1781        # at this point, ToPcd.Type has the type found from dependent
1782        # package
1783        #
1784        if FromPcd != None:
1785            if ToPcd.Pending and FromPcd.Type not in [None, '']:
1786                ToPcd.Type = FromPcd.Type
1787            elif (ToPcd.Type not in [None, '']) and (FromPcd.Type not in [None, ''])\
1788                and (ToPcd.Type != FromPcd.Type) and (ToPcd.Type in FromPcd.Type):
1789                if ToPcd.Type.strip() == "DynamicEx":
1790                    ToPcd.Type = FromPcd.Type
1791            elif ToPcd.Type not in [None, ''] and FromPcd.Type not in [None, ''] \
1792                and ToPcd.Type != FromPcd.Type:
1793                EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",
1794                                ExtraData="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
1795                                          % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName,
1796                                             ToPcd.Type, Module, FromPcd.Type),
1797                                          File=self.MetaFile)
1798
1799            if FromPcd.MaxDatumSize not in [None, '']:
1800                ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
1801            if FromPcd.DefaultValue not in [None, '']:
1802                ToPcd.DefaultValue = FromPcd.DefaultValue
1803            if FromPcd.TokenValue not in [None, '']:
1804                ToPcd.TokenValue = FromPcd.TokenValue
1805            if FromPcd.MaxDatumSize not in [None, '']:
1806                ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
1807            if FromPcd.DatumType not in [None, '']:
1808                ToPcd.DatumType = FromPcd.DatumType
1809            if FromPcd.SkuInfoList not in [None, '', []]:
1810                ToPcd.SkuInfoList = FromPcd.SkuInfoList
1811
1812            # check the validation of datum
1813            IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)
1814            if not IsValid:
1815                EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
1816                                ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))
1817            ToPcd.validateranges = FromPcd.validateranges
1818            ToPcd.validlists = FromPcd.validlists
1819            ToPcd.expressions = FromPcd.expressions
1820
1821        if ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]:
1822            EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \
1823                            % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))
1824            Value = ToPcd.DefaultValue
1825            if Value in [None, '']:
1826                ToPcd.MaxDatumSize = '1'
1827            elif Value[0] == 'L':
1828                ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)
1829            elif Value[0] == '{':
1830                ToPcd.MaxDatumSize = str(len(Value.split(',')))
1831            else:
1832                ToPcd.MaxDatumSize = str(len(Value) - 1)
1833
1834        # apply default SKU for dynamic PCDS if specified one is not available
1835        if (ToPcd.Type in PCD_DYNAMIC_TYPE_LIST or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_LIST) \
1836            and ToPcd.SkuInfoList in [None, {}, '']:
1837            if self.Platform.SkuName in self.Platform.SkuIds:
1838                SkuName = self.Platform.SkuName
1839            else:
1840                SkuName = 'DEFAULT'
1841            ToPcd.SkuInfoList = {
1842                SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName], '', '', '', '', '', ToPcd.DefaultValue)
1843            }
1844
1845    ## Apply PCD setting defined platform to a module
1846    #
1847    #   @param  Module  The module from which the PCD setting will be overrided
1848    #
1849    #   @retval PCD_list    The list PCDs with settings from platform
1850    #
1851    def ApplyPcdSetting(self, Module, Pcds):
1852        # for each PCD in module
1853        for Name, Guid in Pcds:
1854            PcdInModule = Pcds[Name, Guid]
1855            # find out the PCD setting in platform
1856            if (Name, Guid) in self.Platform.Pcds:
1857                PcdInPlatform = self.Platform.Pcds[Name, Guid]
1858            else:
1859                PcdInPlatform = None
1860            # then override the settings if any
1861            self._OverridePcd(PcdInModule, PcdInPlatform, Module)
1862            # resolve the VariableGuid value
1863            for SkuId in PcdInModule.SkuInfoList:
1864                Sku = PcdInModule.SkuInfoList[SkuId]
1865                if Sku.VariableGuid == '': continue
1866                Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList)
1867                if Sku.VariableGuidValue == None:
1868                    PackageList = "\n\t".join([str(P) for P in self.PackageList])
1869                    EdkLogger.error(
1870                                'build',
1871                                RESOURCE_NOT_AVAILABLE,
1872                                "Value of GUID [%s] is not found in" % Sku.VariableGuid,
1873                                ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \
1874                                                        % (Guid, Name, str(Module)),
1875                                File=self.MetaFile
1876                                )
1877
1878        # override PCD settings with module specific setting
1879        if Module in self.Platform.Modules:
1880            PlatformModule = self.Platform.Modules[str(Module)]
1881            for Key  in PlatformModule.Pcds:
1882                if Key in Pcds:
1883                    self._OverridePcd(Pcds[Key], PlatformModule.Pcds[Key], Module)
1884        return Pcds.values()
1885
1886    ## Resolve library names to library modules
1887    #
1888    # (for Edk.x modules)
1889    #
1890    #   @param  Module  The module from which the library names will be resolved
1891    #
1892    #   @retval library_list    The list of library modules
1893    #
1894    def ResolveLibraryReference(self, Module):
1895        EdkLogger.verbose("")
1896        EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
1897        LibraryConsumerList = [Module]
1898
1899        # "CompilerStub" is a must for Edk modules
1900        if Module.Libraries:
1901            Module.Libraries.append("CompilerStub")
1902        LibraryList = []
1903        while len(LibraryConsumerList) > 0:
1904            M = LibraryConsumerList.pop()
1905            for LibraryName in M.Libraries:
1906                Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']
1907                if Library == None:
1908                    for Key in self.Platform.LibraryClasses.data.keys():
1909                        if LibraryName.upper() == Key.upper():
1910                            Library = self.Platform.LibraryClasses[Key, ':dummy:']
1911                            break
1912                    if Library == None:
1913                        EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),
1914                            ExtraData="\t%s [%s]" % (str(Module), self.Arch))
1915                        continue
1916
1917                if Library not in LibraryList:
1918                    LibraryList.append(Library)
1919                    LibraryConsumerList.append(Library)
1920                    EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))
1921        return LibraryList
1922
1923    ## Calculate the priority value of the build option
1924    #
1925    # @param    Key    Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1926    #
1927    # @retval   Value  Priority value based on the priority list.
1928    #
1929    def CalculatePriorityValue(self, Key):
1930        Target, ToolChain, Arch, CommandType, Attr = Key.split('_')
1931        PriorityValue = 0x11111
1932        if Target == "*":
1933            PriorityValue &= 0x01111
1934        if ToolChain == "*":
1935            PriorityValue &= 0x10111
1936        if Arch == "*":
1937            PriorityValue &= 0x11011
1938        if CommandType == "*":
1939            PriorityValue &= 0x11101
1940        if Attr == "*":
1941            PriorityValue &= 0x11110
1942
1943        return self.PrioList["0x%0.5x" % PriorityValue]
1944
1945
1946    ## Expand * in build option key
1947    #
1948    #   @param  Options     Options to be expanded
1949    #
1950    #   @retval options     Options expanded
1951    #
1952    def _ExpandBuildOption(self, Options, ModuleStyle=None):
1953        BuildOptions = {}
1954        FamilyMatch  = False
1955        FamilyIsNull = True
1956
1957        OverrideList = {}
1958        #
1959        # Construct a list contain the build options which need override.
1960        #
1961        for Key in Options:
1962            #
1963            # Key[0] -- tool family
1964            # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1965            #
1966            if (Key[0] == self.BuildRuleFamily and
1967                (ModuleStyle == None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):
1968                Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')
1969                if Target == self.BuildTarget or Target == "*":
1970                    if ToolChain == self.ToolChain or ToolChain == "*":
1971                        if Arch == self.Arch or Arch == "*":
1972                            if Options[Key].startswith("="):
1973                                if OverrideList.get(Key[1]) != None:
1974                                    OverrideList.pop(Key[1])
1975                                OverrideList[Key[1]] = Options[Key]
1976
1977        #
1978        # Use the highest priority value.
1979        #
1980        if (len(OverrideList) >= 2):
1981            KeyList = OverrideList.keys()
1982            for Index in range(len(KeyList)):
1983                NowKey = KeyList[Index]
1984                Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")
1985                for Index1 in range(len(KeyList) - Index - 1):
1986                    NextKey = KeyList[Index1 + Index + 1]
1987                    #
1988                    # Compare two Key, if one is included by another, choose the higher priority one
1989                    #
1990                    Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")
1991                    if Target1 == Target2 or Target1 == "*" or Target2 == "*":
1992                        if ToolChain1 == ToolChain2 or ToolChain1 == "*" or ToolChain2 == "*":
1993                            if Arch1 == Arch2 or Arch1 == "*" or Arch2 == "*":
1994                                if CommandType1 == CommandType2 or CommandType1 == "*" or CommandType2 == "*":
1995                                    if Attr1 == Attr2 or Attr1 == "*" or Attr2 == "*":
1996                                        if self.CalculatePriorityValue(NowKey) > self.CalculatePriorityValue(NextKey):
1997                                            if Options.get((self.BuildRuleFamily, NextKey)) != None:
1998                                                Options.pop((self.BuildRuleFamily, NextKey))
1999                                        else:
2000                                            if Options.get((self.BuildRuleFamily, NowKey)) != None:
2001                                                Options.pop((self.BuildRuleFamily, NowKey))
2002
2003        for Key in Options:
2004            if ModuleStyle != None and len (Key) > 2:
2005                # Check Module style is EDK or EDKII.
2006                # Only append build option for the matched style module.
2007                if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
2008                    continue
2009                elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
2010                    continue
2011            Family = Key[0]
2012            Target, Tag, Arch, Tool, Attr = Key[1].split("_")
2013            # if tool chain family doesn't match, skip it
2014            if Tool in self.ToolDefinition and Family != "":
2015                FamilyIsNull = False
2016                if self.ToolDefinition[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
2017                    if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
2018                        continue
2019                elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
2020                    continue
2021                FamilyMatch = True
2022            # expand any wildcard
2023            if Target == "*" or Target == self.BuildTarget:
2024                if Tag == "*" or Tag == self.ToolChain:
2025                    if Arch == "*" or Arch == self.Arch:
2026                        if Tool not in BuildOptions:
2027                            BuildOptions[Tool] = {}
2028                        if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
2029                            BuildOptions[Tool][Attr] = Options[Key]
2030                        else:
2031                            # append options for the same tool
2032                            BuildOptions[Tool][Attr] += " " + Options[Key]
2033        # Build Option Family has been checked, which need't to be checked again for family.
2034        if FamilyMatch or FamilyIsNull:
2035            return BuildOptions
2036
2037        for Key in Options:
2038            if ModuleStyle != None and len (Key) > 2:
2039                # Check Module style is EDK or EDKII.
2040                # Only append build option for the matched style module.
2041                if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
2042                    continue
2043                elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
2044                    continue
2045            Family = Key[0]
2046            Target, Tag, Arch, Tool, Attr = Key[1].split("_")
2047            # if tool chain family doesn't match, skip it
2048            if Tool not in self.ToolDefinition or Family == "":
2049                continue
2050            # option has been added before
2051            if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
2052                continue
2053
2054            # expand any wildcard
2055            if Target == "*" or Target == self.BuildTarget:
2056                if Tag == "*" or Tag == self.ToolChain:
2057                    if Arch == "*" or Arch == self.Arch:
2058                        if Tool not in BuildOptions:
2059                            BuildOptions[Tool] = {}
2060                        if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
2061                            BuildOptions[Tool][Attr] = Options[Key]
2062                        else:
2063                            # append options for the same tool
2064                            BuildOptions[Tool][Attr] += " " + Options[Key]
2065        return BuildOptions
2066
2067    ## Append build options in platform to a module
2068    #
2069    #   @param  Module  The module to which the build options will be appened
2070    #
2071    #   @retval options     The options appended with build options in platform
2072    #
2073    def ApplyBuildOption(self, Module):
2074        # Get the different options for the different style module
2075        if Module.AutoGenVersion < 0x00010005:
2076            PlatformOptions = self.EdkBuildOption
2077            ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDK_NAME, Module.ModuleType)
2078        else:
2079            PlatformOptions = self.EdkIIBuildOption
2080            ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)
2081        ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)
2082        ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)
2083        if Module in self.Platform.Modules:
2084            PlatformModule = self.Platform.Modules[str(Module)]
2085            PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
2086        else:
2087            PlatformModuleOptions = {}
2088
2089        BuildRuleOrder = None
2090        for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
2091            for Tool in Options:
2092                for Attr in Options[Tool]:
2093                    if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
2094                        BuildRuleOrder = Options[Tool][Attr]
2095
2096        AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() +
2097                       PlatformModuleOptions.keys() + ModuleTypeOptions.keys() +
2098                       self.ToolDefinition.keys())
2099        BuildOptions = {}
2100        for Tool in AllTools:
2101            if Tool not in BuildOptions:
2102                BuildOptions[Tool] = {}
2103
2104            for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
2105                if Tool not in Options:
2106                    continue
2107                for Attr in Options[Tool]:
2108                    Value = Options[Tool][Attr]
2109                    #
2110                    # Do not generate it in Makefile
2111                    #
2112                    if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
2113                        continue
2114                    if Attr not in BuildOptions[Tool]:
2115                        BuildOptions[Tool][Attr] = ""
2116                    # check if override is indicated
2117                    if Value.startswith('='):
2118                        ToolPath = Value[1:]
2119                        ToolPath = mws.handleWsMacro(ToolPath)
2120                        BuildOptions[Tool][Attr] = ToolPath
2121                    else:
2122                        Value = mws.handleWsMacro(Value)
2123                        BuildOptions[Tool][Attr] += " " + Value
2124        if Module.AutoGenVersion < 0x00010005 and self.Workspace.UniFlag != None:
2125            #
2126            # Override UNI flag only for EDK module.
2127            #
2128            if 'BUILD' not in BuildOptions:
2129                BuildOptions['BUILD'] = {}
2130            BuildOptions['BUILD']['FLAGS'] = self.Workspace.UniFlag
2131        return BuildOptions, BuildRuleOrder
2132
2133    Platform            = property(_GetPlatform)
2134    Name                = property(_GetName)
2135    Guid                = property(_GetGuid)
2136    Version             = property(_GetVersion)
2137
2138    OutputDir           = property(_GetOutputDir)
2139    BuildDir            = property(_GetBuildDir)
2140    MakeFileDir         = property(_GetMakeFileDir)
2141    FdfFile             = property(_GetFdfFile)
2142
2143    PcdTokenNumber      = property(_GetPcdTokenNumbers)    # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
2144    DynamicPcdList      = property(_GetDynamicPcdList)    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2145    NonDynamicPcdList   = property(_GetNonDynamicPcdList)    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2146    NonDynamicPcdDict   = property(_GetNonDynamicPcdDict)
2147    PackageList         = property(_GetPackageList)
2148
2149    ToolDefinition      = property(_GetToolDefinition)    # toolcode : tool path
2150    ToolDefinitionFile  = property(_GetToolDefFile)    # toolcode : lib path
2151    ToolChainFamily     = property(_GetToolChainFamily)
2152    BuildRuleFamily     = property(_GetBuildRuleFamily)
2153    BuildOption         = property(_GetBuildOptions)    # toolcode : option
2154    EdkBuildOption      = property(_GetEdkBuildOptions)   # edktoolcode : option
2155    EdkIIBuildOption    = property(_GetEdkIIBuildOptions) # edkiitoolcode : option
2156
2157    BuildCommand        = property(_GetBuildCommand)
2158    BuildRule           = property(_GetBuildRule)
2159    ModuleAutoGenList   = property(_GetModuleAutoGenList)
2160    LibraryAutoGenList  = property(_GetLibraryAutoGenList)
2161    GenFdsCommand       = property(_GenFdsCommand)
2162
2163## ModuleAutoGen class
2164#
2165# This class encapsules the AutoGen behaviors for the build tools. In addition to
2166# the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2167# to the [depex] section in module's inf file.
2168#
2169class ModuleAutoGen(AutoGen):
2170    ## The real constructor of ModuleAutoGen
2171    #
2172    #  This method is not supposed to be called by users of ModuleAutoGen. It's
2173    #  only used by factory method __new__() to do real initialization work for an
2174    #  object of ModuleAutoGen
2175    #
2176    #   @param      Workspace           EdkIIWorkspaceBuild object
2177    #   @param      ModuleFile          The path of module file
2178    #   @param      Target              Build target (DEBUG, RELEASE)
2179    #   @param      Toolchain           Name of tool chain
2180    #   @param      Arch                The arch the module supports
2181    #   @param      PlatformFile        Platform meta-file
2182    #
2183    def _Init(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):
2184        EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))
2185        GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)
2186
2187        self.Workspace = Workspace
2188        self.WorkspaceDir = Workspace.WorkspaceDir
2189
2190        self.MetaFile = ModuleFile
2191        self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)
2192        # check if this module is employed by active platform
2193        if not self.PlatformInfo.ValidModule(self.MetaFile):
2194            EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2195                              % (self.MetaFile, Arch))
2196            return False
2197
2198        self.SourceDir = self.MetaFile.SubDir
2199        self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir)
2200
2201        self.SourceOverrideDir = None
2202        # use overrided path defined in DSC file
2203        if self.MetaFile.Key in GlobalData.gOverrideDir:
2204            self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]
2205
2206        self.ToolChain = Toolchain
2207        self.BuildTarget = Target
2208        self.Arch = Arch
2209        self.ToolChainFamily = self.PlatformInfo.ToolChainFamily
2210        self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily
2211
2212        self.IsMakeFileCreated = False
2213        self.IsCodeFileCreated = False
2214        self.IsAsBuiltInfCreated = False
2215        self.DepexGenerated = False
2216
2217        self.BuildDatabase = self.Workspace.BuildDatabase
2218        self.BuildRuleOrder = None
2219
2220        self._Module          = None
2221        self._Name            = None
2222        self._Guid            = None
2223        self._Version         = None
2224        self._ModuleType      = None
2225        self._ComponentType   = None
2226        self._PcdIsDriver     = None
2227        self._AutoGenVersion  = None
2228        self._LibraryFlag     = None
2229        self._CustomMakefile  = None
2230        self._Macro           = None
2231
2232        self._BuildDir        = None
2233        self._OutputDir       = None
2234        self._DebugDir        = None
2235        self._MakeFileDir     = None
2236
2237        self._IncludePathList = None
2238        self._AutoGenFileList = None
2239        self._UnicodeFileList = None
2240        self._SourceFileList  = None
2241        self._ObjectFileList  = None
2242        self._BinaryFileList  = None
2243
2244        self._DependentPackageList    = None
2245        self._DependentLibraryList    = None
2246        self._LibraryAutoGenList      = None
2247        self._DerivedPackageList      = None
2248        self._ModulePcdList           = None
2249        self._LibraryPcdList          = None
2250        self._PcdComments = sdict()
2251        self._GuidList                = None
2252        self._GuidsUsedByPcd = None
2253        self._GuidComments = sdict()
2254        self._ProtocolList            = None
2255        self._ProtocolComments = sdict()
2256        self._PpiList                 = None
2257        self._PpiComments = sdict()
2258        self._DepexList               = None
2259        self._DepexExpressionList     = None
2260        self._BuildOption             = None
2261        self._BuildOptionIncPathList  = None
2262        self._BuildTargets            = None
2263        self._IntroBuildTargetList    = None
2264        self._FinalBuildTargetList    = None
2265        self._FileTypes               = None
2266        self._BuildRules              = None
2267
2268        ## The Modules referenced to this Library
2269        #  Only Library has this attribute
2270        self._ReferenceModules        = []
2271
2272        ## Store the FixedAtBuild Pcds
2273        #
2274        self._FixedAtBuildPcds         = []
2275        self.ConstPcd                  = {}
2276        return True
2277
2278    def __repr__(self):
2279        return "%s [%s]" % (self.MetaFile, self.Arch)
2280
2281    # Get FixedAtBuild Pcds of this Module
2282    def _GetFixedAtBuildPcds(self):
2283        if self._FixedAtBuildPcds:
2284            return self._FixedAtBuildPcds
2285        for Pcd in self.ModulePcdList:
2286            if self.IsLibrary:
2287                if not (Pcd.Pending == False and Pcd.Type == "FixedAtBuild"):
2288                    continue
2289            elif Pcd.Type != "FixedAtBuild":
2290                continue
2291            if Pcd not in self._FixedAtBuildPcds:
2292                self._FixedAtBuildPcds.append(Pcd)
2293
2294        return self._FixedAtBuildPcds
2295
2296    def _GetUniqueBaseName(self):
2297        BaseName = self.Name
2298        for Module in self.PlatformInfo.ModuleAutoGenList:
2299            if Module.MetaFile == self.MetaFile:
2300                continue
2301            if Module.Name == self.Name:
2302                if uuid.UUID(Module.Guid) == uuid.UUID(self.Guid):
2303                    EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'
2304                                    '  %s\n  %s' % (Module.MetaFile, self.MetaFile))
2305                BaseName = '%s_%s' % (self.Name, self.Guid)
2306        return BaseName
2307
2308    # Macros could be used in build_rule.txt (also Makefile)
2309    def _GetMacros(self):
2310        if self._Macro == None:
2311            self._Macro = sdict()
2312            self._Macro["WORKSPACE"             ] = self.WorkspaceDir
2313            self._Macro["MODULE_NAME"           ] = self.Name
2314            self._Macro["MODULE_NAME_GUID"      ] = self._GetUniqueBaseName()
2315            self._Macro["MODULE_GUID"           ] = self.Guid
2316            self._Macro["MODULE_VERSION"        ] = self.Version
2317            self._Macro["MODULE_TYPE"           ] = self.ModuleType
2318            self._Macro["MODULE_FILE"           ] = str(self.MetaFile)
2319            self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName
2320            self._Macro["MODULE_RELATIVE_DIR"   ] = self.SourceDir
2321            self._Macro["MODULE_DIR"            ] = self.SourceDir
2322
2323            self._Macro["BASE_NAME"             ] = self.Name
2324
2325            self._Macro["ARCH"                  ] = self.Arch
2326            self._Macro["TOOLCHAIN"             ] = self.ToolChain
2327            self._Macro["TOOLCHAIN_TAG"         ] = self.ToolChain
2328            self._Macro["TOOL_CHAIN_TAG"        ] = self.ToolChain
2329            self._Macro["TARGET"                ] = self.BuildTarget
2330
2331            self._Macro["BUILD_DIR"             ] = self.PlatformInfo.BuildDir
2332            self._Macro["BIN_DIR"               ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
2333            self._Macro["LIB_DIR"               ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
2334            self._Macro["MODULE_BUILD_DIR"      ] = self.BuildDir
2335            self._Macro["OUTPUT_DIR"            ] = self.OutputDir
2336            self._Macro["DEBUG_DIR"             ] = self.DebugDir
2337        return self._Macro
2338
2339    ## Return the module build data object
2340    def _GetModule(self):
2341        if self._Module == None:
2342            self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
2343        return self._Module
2344
2345    ## Return the module name
2346    def _GetBaseName(self):
2347        return self.Module.BaseName
2348
2349    ## Return the module DxsFile if exist
2350    def _GetDxsFile(self):
2351        return self.Module.DxsFile
2352
2353    ## Return the module SourceOverridePath
2354    def _GetSourceOverridePath(self):
2355        return self.Module.SourceOverridePath
2356
2357    ## Return the module meta-file GUID
2358    def _GetGuid(self):
2359        #
2360        # To build same module more than once, the module path with FILE_GUID overridden has
2361        # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
2362        # in DSC. The overridden GUID can be retrieved from file name
2363        #
2364        if os.path.basename(self.MetaFile.File) != os.path.basename(self.MetaFile.Path):
2365            #
2366            # Length of GUID is 36
2367            #
2368            return os.path.basename(self.MetaFile.Path)[:36]
2369        return self.Module.Guid
2370
2371    ## Return the module version
2372    def _GetVersion(self):
2373        return self.Module.Version
2374
2375    ## Return the module type
2376    def _GetModuleType(self):
2377        return self.Module.ModuleType
2378
2379    ## Return the component type (for Edk.x style of module)
2380    def _GetComponentType(self):
2381        return self.Module.ComponentType
2382
2383    ## Return the build type
2384    def _GetBuildType(self):
2385        return self.Module.BuildType
2386
2387    ## Return the PCD_IS_DRIVER setting
2388    def _GetPcdIsDriver(self):
2389        return self.Module.PcdIsDriver
2390
2391    ## Return the autogen version, i.e. module meta-file version
2392    def _GetAutoGenVersion(self):
2393        return self.Module.AutoGenVersion
2394
2395    ## Check if the module is library or not
2396    def _IsLibrary(self):
2397        if self._LibraryFlag == None:
2398            if self.Module.LibraryClass != None and self.Module.LibraryClass != []:
2399                self._LibraryFlag = True
2400            else:
2401                self._LibraryFlag = False
2402        return self._LibraryFlag
2403
2404    ## Check if the module is binary module or not
2405    def _IsBinaryModule(self):
2406        return self.Module.IsBinaryModule
2407
2408    ## Return the directory to store intermediate files of the module
2409    def _GetBuildDir(self):
2410        if self._BuildDir == None:
2411            self._BuildDir = path.join(
2412                                    self.PlatformInfo.BuildDir,
2413                                    self.Arch,
2414                                    self.SourceDir,
2415                                    self.MetaFile.BaseName
2416                                    )
2417            CreateDirectory(self._BuildDir)
2418        return self._BuildDir
2419
2420    ## Return the directory to store the intermediate object files of the mdoule
2421    def _GetOutputDir(self):
2422        if self._OutputDir == None:
2423            self._OutputDir = path.join(self.BuildDir, "OUTPUT")
2424            CreateDirectory(self._OutputDir)
2425        return self._OutputDir
2426
2427    ## Return the directory to store auto-gened source files of the mdoule
2428    def _GetDebugDir(self):
2429        if self._DebugDir == None:
2430            self._DebugDir = path.join(self.BuildDir, "DEBUG")
2431            CreateDirectory(self._DebugDir)
2432        return self._DebugDir
2433
2434    ## Return the path of custom file
2435    def _GetCustomMakefile(self):
2436        if self._CustomMakefile == None:
2437            self._CustomMakefile = {}
2438            for Type in self.Module.CustomMakefile:
2439                if Type in gMakeTypeMap:
2440                    MakeType = gMakeTypeMap[Type]
2441                else:
2442                    MakeType = 'nmake'
2443                if self.SourceOverrideDir != None:
2444                    File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])
2445                    if not os.path.exists(File):
2446                        File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
2447                else:
2448                    File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
2449                self._CustomMakefile[MakeType] = File
2450        return self._CustomMakefile
2451
2452    ## Return the directory of the makefile
2453    #
2454    #   @retval     string  The directory string of module's makefile
2455    #
2456    def _GetMakeFileDir(self):
2457        return self.BuildDir
2458
2459    ## Return build command string
2460    #
2461    #   @retval     string  Build command string
2462    #
2463    def _GetBuildCommand(self):
2464        return self.PlatformInfo.BuildCommand
2465
2466    ## Get object list of all packages the module and its dependent libraries belong to
2467    #
2468    #   @retval     list    The list of package object
2469    #
2470    def _GetDerivedPackageList(self):
2471        PackageList = []
2472        for M in [self.Module] + self.DependentLibraryList:
2473            for Package in M.Packages:
2474                if Package in PackageList:
2475                    continue
2476                PackageList.append(Package)
2477        return PackageList
2478
2479    ## Get the depex string
2480    #
2481    # @return : a string contain all depex expresion.
2482    def _GetDepexExpresionString(self):
2483        DepexStr = ''
2484        DepexList = []
2485        ## DPX_SOURCE IN Define section.
2486        if self.Module.DxsFile:
2487            return DepexStr
2488        for M in [self.Module] + self.DependentLibraryList:
2489            Filename = M.MetaFile.Path
2490            InfObj = InfSectionParser.InfSectionParser(Filename)
2491            DepexExpresionList = InfObj.GetDepexExpresionList()
2492            for DepexExpresion in DepexExpresionList:
2493                for key in DepexExpresion.keys():
2494                    Arch, ModuleType = key
2495                    # the type of build module is USER_DEFINED.
2496                    # All different DEPEX section tags would be copied into the As Built INF file
2497                    # and there would be separate DEPEX section tags
2498                    if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:
2499                        if (Arch.upper() == self.Arch.upper()) and (ModuleType.upper() != TAB_ARCH_COMMON):
2500                            DepexList.append({(Arch, ModuleType): DepexExpresion[key][:]})
2501                    else:
2502                        if Arch.upper() == TAB_ARCH_COMMON or \
2503                          (Arch.upper() == self.Arch.upper() and \
2504                          ModuleType.upper() in [TAB_ARCH_COMMON, self.ModuleType.upper()]):
2505                            DepexList.append({(Arch, ModuleType): DepexExpresion[key][:]})
2506
2507        #the type of build module is USER_DEFINED.
2508        if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:
2509            for Depex in DepexList:
2510                for key in Depex.keys():
2511                    DepexStr += '[Depex.%s.%s]\n' % key
2512                    DepexStr += '\n'.join(['# '+ val for val in Depex[key]])
2513                    DepexStr += '\n\n'
2514            if not DepexStr:
2515                return '[Depex.%s]\n' % self.Arch
2516            return DepexStr
2517
2518        #the type of build module not is USER_DEFINED.
2519        Count = 0
2520        for Depex in DepexList:
2521            Count += 1
2522            if DepexStr != '':
2523                DepexStr += ' AND '
2524            DepexStr += '('
2525            for D in Depex.values():
2526                DepexStr += ' '.join([val for val in D])
2527            Index = DepexStr.find('END')
2528            if Index > -1 and Index == len(DepexStr) - 3:
2529                DepexStr = DepexStr[:-3]
2530            DepexStr = DepexStr.strip()
2531            DepexStr += ')'
2532        if Count == 1:
2533            DepexStr = DepexStr.lstrip('(').rstrip(')').strip()
2534        if not DepexStr:
2535            return '[Depex.%s]\n' % self.Arch
2536        return '[Depex.%s]\n#  ' % self.Arch + DepexStr
2537
2538    ## Merge dependency expression
2539    #
2540    #   @retval     list    The token list of the dependency expression after parsed
2541    #
2542    def _GetDepexTokenList(self):
2543        if self._DepexList == None:
2544            self._DepexList = {}
2545            if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
2546                return self._DepexList
2547
2548            self._DepexList[self.ModuleType] = []
2549
2550            for ModuleType in self._DepexList:
2551                DepexList = self._DepexList[ModuleType]
2552                #
2553                # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2554                #
2555                for M in [self.Module] + self.DependentLibraryList:
2556                    Inherited = False
2557                    for D in M.Depex[self.Arch, ModuleType]:
2558                        if DepexList != []:
2559                            DepexList.append('AND')
2560                        DepexList.append('(')
2561                        DepexList.extend(D)
2562                        if DepexList[-1] == 'END':  # no need of a END at this time
2563                            DepexList.pop()
2564                        DepexList.append(')')
2565                        Inherited = True
2566                    if Inherited:
2567                        EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))
2568                    if 'BEFORE' in DepexList or 'AFTER' in DepexList:
2569                        break
2570                if len(DepexList) > 0:
2571                    EdkLogger.verbose('')
2572        return self._DepexList
2573
2574    ## Merge dependency expression
2575    #
2576    #   @retval     list    The token list of the dependency expression after parsed
2577    #
2578    def _GetDepexExpressionTokenList(self):
2579        if self._DepexExpressionList == None:
2580            self._DepexExpressionList = {}
2581            if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
2582                return self._DepexExpressionList
2583
2584            self._DepexExpressionList[self.ModuleType] = ''
2585
2586            for ModuleType in self._DepexExpressionList:
2587                DepexExpressionList = self._DepexExpressionList[ModuleType]
2588                #
2589                # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2590                #
2591                for M in [self.Module] + self.DependentLibraryList:
2592                    Inherited = False
2593                    for D in M.DepexExpression[self.Arch, ModuleType]:
2594                        if DepexExpressionList != '':
2595                            DepexExpressionList += ' AND '
2596                        DepexExpressionList += '('
2597                        DepexExpressionList += D
2598                        DepexExpressionList = DepexExpressionList.rstrip('END').strip()
2599                        DepexExpressionList += ')'
2600                        Inherited = True
2601                    if Inherited:
2602                        EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionList))
2603                    if 'BEFORE' in DepexExpressionList or 'AFTER' in DepexExpressionList:
2604                        break
2605                if len(DepexExpressionList) > 0:
2606                    EdkLogger.verbose('')
2607                self._DepexExpressionList[ModuleType] = DepexExpressionList
2608        return self._DepexExpressionList
2609
2610    ## Return the list of specification version required for the module
2611    #
2612    #   @retval     list    The list of specification defined in module file
2613    #
2614    def _GetSpecification(self):
2615        return self.Module.Specification
2616
2617    ## Tool option for the module build
2618    #
2619    #   @param      PlatformInfo    The object of PlatformBuildInfo
2620    #   @retval     dict            The dict containing valid options
2621    #
2622    def _GetModuleBuildOption(self):
2623        if self._BuildOption == None:
2624            self._BuildOption, self.BuildRuleOrder = self.PlatformInfo.ApplyBuildOption(self.Module)
2625            if self.BuildRuleOrder:
2626                self.BuildRuleOrder = ['.%s' % Ext for Ext in self.BuildRuleOrder.split()]
2627        return self._BuildOption
2628
2629    ## Get include path list from tool option for the module build
2630    #
2631    #   @retval     list            The include path list
2632    #
2633    def _GetBuildOptionIncPathList(self):
2634        if self._BuildOptionIncPathList == None:
2635            #
2636            # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
2637            # is the former use /I , the Latter used -I to specify include directories
2638            #
2639            if self.PlatformInfo.ToolChainFamily in ('MSFT'):
2640                gBuildOptIncludePattern = re.compile(r"(?:.*?)/I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)
2641            elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):
2642                gBuildOptIncludePattern = re.compile(r"(?:.*?)-I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)
2643            else:
2644                #
2645                # New ToolChainFamily, don't known whether there is option to specify include directories
2646                #
2647                self._BuildOptionIncPathList = []
2648                return self._BuildOptionIncPathList
2649
2650            BuildOptionIncPathList = []
2651            for Tool in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
2652                Attr = 'FLAGS'
2653                try:
2654                    FlagOption = self.BuildOption[Tool][Attr]
2655                except KeyError:
2656                    FlagOption = ''
2657
2658                if self.PlatformInfo.ToolChainFamily != 'RVCT':
2659                    IncPathList = [NormPath(Path, self.Macros) for Path in gBuildOptIncludePattern.findall(FlagOption)]
2660                else:
2661                    #
2662                    # RVCT may specify a list of directory seperated by commas
2663                    #
2664                    IncPathList = []
2665                    for Path in gBuildOptIncludePattern.findall(FlagOption):
2666                        PathList = GetSplitList(Path, TAB_COMMA_SPLIT)
2667                        IncPathList += [NormPath(PathEntry, self.Macros) for PathEntry in PathList]
2668
2669                #
2670                # EDK II modules must not reference header files outside of the packages they depend on or
2671                # within the module's directory tree. Report error if violation.
2672                #
2673                if self.AutoGenVersion >= 0x00010005 and len(IncPathList) > 0:
2674                    for Path in IncPathList:
2675                        if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir):
2676                            ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption)
2677                            EdkLogger.error("build",
2678                                            PARAMETER_INVALID,
2679                                            ExtraData=ErrMsg,
2680                                            File=str(self.MetaFile))
2681
2682
2683                BuildOptionIncPathList += IncPathList
2684
2685            self._BuildOptionIncPathList = BuildOptionIncPathList
2686
2687        return self._BuildOptionIncPathList
2688
2689    ## Return a list of files which can be built from source
2690    #
2691    #  What kind of files can be built is determined by build rules in
2692    #  $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
2693    #
2694    def _GetSourceFileList(self):
2695        if self._SourceFileList == None:
2696            self._SourceFileList = []
2697            for F in self.Module.Sources:
2698                # match tool chain
2699                if F.TagName not in ("", "*", self.ToolChain):
2700                    EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "
2701                                    "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))
2702                    continue
2703                # match tool chain family
2704                if F.ToolChainFamily not in ("", "*", self.ToolChainFamily):
2705                    EdkLogger.debug(
2706                                EdkLogger.DEBUG_0,
2707                                "The file [%s] must be built by tools of [%s], " \
2708                                "but current toolchain family is [%s]" \
2709                                    % (str(F), F.ToolChainFamily, self.ToolChainFamily))
2710                    continue
2711
2712                # add the file path into search path list for file including
2713                if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:
2714                    self.IncludePathList.insert(0, F.Dir)
2715                self._SourceFileList.append(F)
2716                self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)
2717        return self._SourceFileList
2718
2719    ## Return the list of unicode files
2720    def _GetUnicodeFileList(self):
2721        if self._UnicodeFileList == None:
2722            if TAB_UNICODE_FILE in self.FileTypes:
2723                self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]
2724            else:
2725                self._UnicodeFileList = []
2726        return self._UnicodeFileList
2727
2728    ## Return a list of files which can be built from binary
2729    #
2730    #  "Build" binary files are just to copy them to build directory.
2731    #
2732    #   @retval     list            The list of files which can be built later
2733    #
2734    def _GetBinaryFiles(self):
2735        if self._BinaryFileList == None:
2736            self._BinaryFileList = []
2737            for F in self.Module.Binaries:
2738                if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:
2739                    continue
2740                self._BinaryFileList.append(F)
2741                self._ApplyBuildRule(F, F.Type)
2742        return self._BinaryFileList
2743
2744    def _GetBuildRules(self):
2745        if self._BuildRules == None:
2746            BuildRules = {}
2747            BuildRuleDatabase = self.PlatformInfo.BuildRule
2748            for Type in BuildRuleDatabase.FileTypeList:
2749                #first try getting build rule by BuildRuleFamily
2750                RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]
2751                if not RuleObject:
2752                    # build type is always module type, but ...
2753                    if self.ModuleType != self.BuildType:
2754                        RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]
2755                #second try getting build rule by ToolChainFamily
2756                if not RuleObject:
2757                    RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]
2758                    if not RuleObject:
2759                        # build type is always module type, but ...
2760                        if self.ModuleType != self.BuildType:
2761                            RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]
2762                if not RuleObject:
2763                    continue
2764                RuleObject = RuleObject.Instantiate(self.Macros)
2765                BuildRules[Type] = RuleObject
2766                for Ext in RuleObject.SourceFileExtList:
2767                    BuildRules[Ext] = RuleObject
2768            self._BuildRules = BuildRules
2769        return self._BuildRules
2770
2771    def _ApplyBuildRule(self, File, FileType):
2772        if self._BuildTargets == None:
2773            self._IntroBuildTargetList = set()
2774            self._FinalBuildTargetList = set()
2775            self._BuildTargets = {}
2776            self._FileTypes = {}
2777
2778        SubDirectory = os.path.join(self.OutputDir, File.SubDir)
2779        if not os.path.exists(SubDirectory):
2780            CreateDirectory(SubDirectory)
2781        LastTarget = None
2782        RuleChain = []
2783        SourceList = [File]
2784        Index = 0
2785        #
2786        # Make sure to get build rule order value
2787        #
2788        self._GetModuleBuildOption()
2789
2790        while Index < len(SourceList):
2791            Source = SourceList[Index]
2792            Index = Index + 1
2793
2794            if Source != File:
2795                CreateDirectory(Source.Dir)
2796
2797            if File.IsBinary and File == Source and self._BinaryFileList != None and File in self._BinaryFileList:
2798                # Skip all files that are not binary libraries
2799                if not self.IsLibrary:
2800                    continue
2801                RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]
2802            elif FileType in self.BuildRules:
2803                RuleObject = self.BuildRules[FileType]
2804            elif Source.Ext in self.BuildRules:
2805                RuleObject = self.BuildRules[Source.Ext]
2806            else:
2807                # stop at no more rules
2808                if LastTarget:
2809                    self._FinalBuildTargetList.add(LastTarget)
2810                break
2811
2812            FileType = RuleObject.SourceFileType
2813            if FileType not in self._FileTypes:
2814                self._FileTypes[FileType] = set()
2815            self._FileTypes[FileType].add(Source)
2816
2817            # stop at STATIC_LIBRARY for library
2818            if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
2819                if LastTarget:
2820                    self._FinalBuildTargetList.add(LastTarget)
2821                break
2822
2823            Target = RuleObject.Apply(Source, self.BuildRuleOrder)
2824            if not Target:
2825                if LastTarget:
2826                    self._FinalBuildTargetList.add(LastTarget)
2827                break
2828            elif not Target.Outputs:
2829                # Only do build for target with outputs
2830                self._FinalBuildTargetList.add(Target)
2831
2832            if FileType not in self._BuildTargets:
2833                self._BuildTargets[FileType] = set()
2834            self._BuildTargets[FileType].add(Target)
2835
2836            if not Source.IsBinary and Source == File:
2837                self._IntroBuildTargetList.add(Target)
2838
2839            # to avoid cyclic rule
2840            if FileType in RuleChain:
2841                break
2842
2843            RuleChain.append(FileType)
2844            SourceList.extend(Target.Outputs)
2845            LastTarget = Target
2846            FileType = TAB_UNKNOWN_FILE
2847
2848    def _GetTargets(self):
2849        if self._BuildTargets == None:
2850            self._IntroBuildTargetList = set()
2851            self._FinalBuildTargetList = set()
2852            self._BuildTargets = {}
2853            self._FileTypes = {}
2854
2855        #TRICK: call _GetSourceFileList to apply build rule for source files
2856        if self.SourceFileList:
2857            pass
2858
2859        #TRICK: call _GetBinaryFileList to apply build rule for binary files
2860        if self.BinaryFileList:
2861            pass
2862
2863        return self._BuildTargets
2864
2865    def _GetIntroTargetList(self):
2866        self._GetTargets()
2867        return self._IntroBuildTargetList
2868
2869    def _GetFinalTargetList(self):
2870        self._GetTargets()
2871        return self._FinalBuildTargetList
2872
2873    def _GetFileTypes(self):
2874        self._GetTargets()
2875        return self._FileTypes
2876
2877    ## Get the list of package object the module depends on
2878    #
2879    #   @retval     list    The package object list
2880    #
2881    def _GetDependentPackageList(self):
2882        return self.Module.Packages
2883
2884    ## Return the list of auto-generated code file
2885    #
2886    #   @retval     list        The list of auto-generated file
2887    #
2888    def _GetAutoGenFileList(self):
2889        UniStringAutoGenC = True
2890        UniStringBinBuffer = StringIO()
2891        if self.BuildType == 'UEFI_HII':
2892            UniStringAutoGenC = False
2893        if self._AutoGenFileList == None:
2894            self._AutoGenFileList = {}
2895            AutoGenC = TemplateString()
2896            AutoGenH = TemplateString()
2897            StringH = TemplateString()
2898            GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, UniStringAutoGenC, UniStringBinBuffer)
2899            #
2900            # AutoGen.c is generated if there are library classes in inf, or there are object files
2901            #
2902            if str(AutoGenC) != "" and (len(self.Module.LibraryClasses) > 0
2903                                        or TAB_OBJECT_FILE in self.FileTypes):
2904                AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)
2905                self._AutoGenFileList[AutoFile] = str(AutoGenC)
2906                self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2907            if str(AutoGenH) != "":
2908                AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)
2909                self._AutoGenFileList[AutoFile] = str(AutoGenH)
2910                self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2911            if str(StringH) != "":
2912                AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)
2913                self._AutoGenFileList[AutoFile] = str(StringH)
2914                self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2915            if UniStringBinBuffer != None and UniStringBinBuffer.getvalue() != "":
2916                AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)
2917                self._AutoGenFileList[AutoFile] = UniStringBinBuffer.getvalue()
2918                AutoFile.IsBinary = True
2919                self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2920            if UniStringBinBuffer != None:
2921                UniStringBinBuffer.close()
2922        return self._AutoGenFileList
2923
2924    ## Return the list of library modules explicitly or implicityly used by this module
2925    def _GetLibraryList(self):
2926        if self._DependentLibraryList == None:
2927            # only merge library classes and PCD for non-library module
2928            if self.IsLibrary:
2929                self._DependentLibraryList = []
2930            else:
2931                if self.AutoGenVersion < 0x00010005:
2932                    self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)
2933                else:
2934                    self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)
2935        return self._DependentLibraryList
2936
2937    @staticmethod
2938    def UpdateComments(Recver, Src):
2939        for Key in Src:
2940            if Key not in Recver:
2941                Recver[Key] = []
2942            Recver[Key].extend(Src[Key])
2943    ## Get the list of PCDs from current module
2944    #
2945    #   @retval     list                    The list of PCD
2946    #
2947    def _GetModulePcdList(self):
2948        if self._ModulePcdList == None:
2949            # apply PCD settings from platform
2950            self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)
2951            self.UpdateComments(self._PcdComments, self.Module.PcdComments)
2952        return self._ModulePcdList
2953
2954    ## Get the list of PCDs from dependent libraries
2955    #
2956    #   @retval     list                    The list of PCD
2957    #
2958    def _GetLibraryPcdList(self):
2959        if self._LibraryPcdList == None:
2960            Pcds = sdict()
2961            if not self.IsLibrary:
2962                # get PCDs from dependent libraries
2963                for Library in self.DependentLibraryList:
2964                    self.UpdateComments(self._PcdComments, Library.PcdComments)
2965                    for Key in Library.Pcds:
2966                        # skip duplicated PCDs
2967                        if Key in self.Module.Pcds or Key in Pcds:
2968                            continue
2969                        Pcds[Key] = copy.copy(Library.Pcds[Key])
2970                # apply PCD settings from platform
2971                self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)
2972            else:
2973                self._LibraryPcdList = []
2974        return self._LibraryPcdList
2975
2976    ## Get the GUID value mapping
2977    #
2978    #   @retval     dict    The mapping between GUID cname and its value
2979    #
2980    def _GetGuidList(self):
2981        if self._GuidList == None:
2982            self._GuidList = sdict()
2983            self._GuidList.update(self.Module.Guids)
2984            for Library in self.DependentLibraryList:
2985                self._GuidList.update(Library.Guids)
2986                self.UpdateComments(self._GuidComments, Library.GuidComments)
2987            self.UpdateComments(self._GuidComments, self.Module.GuidComments)
2988        return self._GuidList
2989
2990    def GetGuidsUsedByPcd(self):
2991        if self._GuidsUsedByPcd == None:
2992            self._GuidsUsedByPcd = sdict()
2993            self._GuidsUsedByPcd.update(self.Module.GetGuidsUsedByPcd())
2994            for Library in self.DependentLibraryList:
2995                self._GuidsUsedByPcd.update(Library.GetGuidsUsedByPcd())
2996        return self._GuidsUsedByPcd
2997    ## Get the protocol value mapping
2998    #
2999    #   @retval     dict    The mapping between protocol cname and its value
3000    #
3001    def _GetProtocolList(self):
3002        if self._ProtocolList == None:
3003            self._ProtocolList = sdict()
3004            self._ProtocolList.update(self.Module.Protocols)
3005            for Library in self.DependentLibraryList:
3006                self._ProtocolList.update(Library.Protocols)
3007                self.UpdateComments(self._ProtocolComments, Library.ProtocolComments)
3008            self.UpdateComments(self._ProtocolComments, self.Module.ProtocolComments)
3009        return self._ProtocolList
3010
3011    ## Get the PPI value mapping
3012    #
3013    #   @retval     dict    The mapping between PPI cname and its value
3014    #
3015    def _GetPpiList(self):
3016        if self._PpiList == None:
3017            self._PpiList = sdict()
3018            self._PpiList.update(self.Module.Ppis)
3019            for Library in self.DependentLibraryList:
3020                self._PpiList.update(Library.Ppis)
3021                self.UpdateComments(self._PpiComments, Library.PpiComments)
3022            self.UpdateComments(self._PpiComments, self.Module.PpiComments)
3023        return self._PpiList
3024
3025    ## Get the list of include search path
3026    #
3027    #   @retval     list                    The list path
3028    #
3029    def _GetIncludePathList(self):
3030        if self._IncludePathList == None:
3031            self._IncludePathList = []
3032            if self.AutoGenVersion < 0x00010005:
3033                for Inc in self.Module.Includes:
3034                    if Inc not in self._IncludePathList:
3035                        self._IncludePathList.append(Inc)
3036                    # for Edk modules
3037                    Inc = path.join(Inc, self.Arch.capitalize())
3038                    if os.path.exists(Inc) and Inc not in self._IncludePathList:
3039                        self._IncludePathList.append(Inc)
3040                # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
3041                self._IncludePathList.append(self.DebugDir)
3042            else:
3043                self._IncludePathList.append(self.MetaFile.Dir)
3044                self._IncludePathList.append(self.DebugDir)
3045
3046            for Package in self.Module.Packages:
3047                PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir)
3048                if PackageDir not in self._IncludePathList:
3049                    self._IncludePathList.append(PackageDir)
3050                for Inc in Package.Includes:
3051                    if Inc not in self._IncludePathList:
3052                        self._IncludePathList.append(str(Inc))
3053        return self._IncludePathList
3054
3055    ## Get HII EX PCDs which maybe used by VFR
3056    #
3057    #  efivarstore used by VFR may relate with HII EX PCDs
3058    #  Get the variable name and GUID from efivarstore and HII EX PCD
3059    #  List the HII EX PCDs in As Built INF if both name and GUID match.
3060    #
3061    #  @retval    list    HII EX PCDs
3062    #
3063    def _GetPcdsMaybeUsedByVfr(self):
3064        if not self.SourceFileList:
3065            return []
3066
3067        NameGuids = []
3068        for SrcFile in self.SourceFileList:
3069            if SrcFile.Ext.lower() != '.vfr':
3070                continue
3071            Vfri = os.path.join(self.OutputDir, SrcFile.BaseName + '.i')
3072            if not os.path.exists(Vfri):
3073                continue
3074            VfriFile = open(Vfri, 'r')
3075            Content = VfriFile.read()
3076            VfriFile.close()
3077            Pos = Content.find('efivarstore')
3078            while Pos != -1:
3079                #
3080                # Make sure 'efivarstore' is the start of efivarstore statement
3081                # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3082                #
3083                Index = Pos - 1
3084                while Index >= 0 and Content[Index] in ' \t\r\n':
3085                    Index -= 1
3086                if Index >= 0 and Content[Index] != ';':
3087                    Pos = Content.find('efivarstore', Pos + len('efivarstore'))
3088                    continue
3089                #
3090                # 'efivarstore' must be followed by name and guid
3091                #
3092                Name = gEfiVarStoreNamePattern.search(Content, Pos)
3093                if not Name:
3094                    break
3095                Guid = gEfiVarStoreGuidPattern.search(Content, Pos)
3096                if not Guid:
3097                    break
3098                NameArray = ConvertStringToByteArray('L"' + Name.group(1) + '"')
3099                NameGuids.append((NameArray, GuidStructureStringToGuidString(Guid.group(1))))
3100                Pos = Content.find('efivarstore', Name.end())
3101        if not NameGuids:
3102            return []
3103        HiiExPcds = []
3104        for Pcd in self.PlatformInfo.Platform.Pcds.values():
3105            if Pcd.Type != TAB_PCDS_DYNAMIC_EX_HII:
3106                continue
3107            for SkuName in Pcd.SkuInfoList:
3108                SkuInfo = Pcd.SkuInfoList[SkuName]
3109                Name = ConvertStringToByteArray(SkuInfo.VariableName)
3110                Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList)
3111                if not Value:
3112                    continue
3113                Guid = GuidStructureStringToGuidString(Value)
3114                if (Name, Guid) in NameGuids and Pcd not in HiiExPcds:
3115                    HiiExPcds.append(Pcd)
3116                    break
3117
3118        return HiiExPcds
3119
3120    def _GenOffsetBin(self):
3121        VfrUniBaseName = {}
3122        for SourceFile in self.Module.Sources:
3123            if SourceFile.Type.upper() == ".VFR" :
3124                #
3125                # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3126                #
3127                VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")
3128            if SourceFile.Type.upper() == ".UNI" :
3129                #
3130                # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3131                #
3132                VfrUniBaseName["UniOffsetName"] = (self.Name + "Strings")
3133
3134        if len(VfrUniBaseName) == 0:
3135            return None
3136        MapFileName = os.path.join(self.OutputDir, self.Name + ".map")
3137        EfiFileName = os.path.join(self.OutputDir, self.Name + ".efi")
3138        VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, VfrUniBaseName.values())
3139        if not VfrUniOffsetList:
3140            return None
3141
3142        OutputName = '%sOffset.bin' % self.Name
3143        UniVfrOffsetFileName    =  os.path.join( self.OutputDir, OutputName)
3144
3145        try:
3146            fInputfile = open(UniVfrOffsetFileName, "wb+", 0)
3147        except:
3148            EdkLogger.error("build", FILE_OPEN_FAILURE, "File open failed for %s" % UniVfrOffsetFileName,None)
3149
3150        # Use a instance of StringIO to cache data
3151        fStringIO = StringIO('')
3152
3153        for Item in VfrUniOffsetList:
3154            if (Item[0].find("Strings") != -1):
3155                #
3156                # UNI offset in image.
3157                # GUID + Offset
3158                # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3159                #
3160                UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3161                UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]
3162                fStringIO.write(''.join(UniGuid))
3163                UniValue = pack ('Q', int (Item[1], 16))
3164                fStringIO.write (UniValue)
3165            else:
3166                #
3167                # VFR binary offset in image.
3168                # GUID + Offset
3169                # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3170                #
3171                VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3172                VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]
3173                fStringIO.write(''.join(VfrGuid))
3174                type (Item[1])
3175                VfrValue = pack ('Q', int (Item[1], 16))
3176                fStringIO.write (VfrValue)
3177        #
3178        # write data into file.
3179        #
3180        try :
3181            fInputfile.write (fStringIO.getvalue())
3182        except:
3183            EdkLogger.error("build", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the "
3184                            "file been locked or using by other applications." %UniVfrOffsetFileName,None)
3185
3186        fStringIO.close ()
3187        fInputfile.close ()
3188        return OutputName
3189
3190    ## Create AsBuilt INF file the module
3191    #
3192    def CreateAsBuiltInf(self):
3193        if self.IsAsBuiltInfCreated:
3194            return
3195
3196        # Skip the following code for EDK I inf
3197        if self.AutoGenVersion < 0x00010005:
3198            return
3199
3200        # Skip the following code for libraries
3201        if self.IsLibrary:
3202            return
3203
3204        # Skip the following code for modules with no source files
3205        if self.SourceFileList == None or self.SourceFileList == []:
3206            return
3207
3208        # Skip the following code for modules without any binary files
3209        if self.BinaryFileList <> None and self.BinaryFileList <> []:
3210            return
3211
3212        ### TODO: How to handles mixed source and binary modules
3213
3214        # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3215        # Also find all packages that the DynamicEx PCDs depend on
3216        Pcds = []
3217        PatchablePcds = {}
3218        Packages = []
3219        PcdCheckList = []
3220        PcdTokenSpaceList = []
3221        for Pcd in self.ModulePcdList + self.LibraryPcdList:
3222            if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE:
3223                PatchablePcds[Pcd.TokenCName] = Pcd
3224                PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'PatchableInModule'))
3225            elif Pcd.Type in GenC.gDynamicExPcd:
3226                if Pcd not in Pcds:
3227                    Pcds += [Pcd]
3228                    PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'DynamicEx'))
3229                    PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'Dynamic'))
3230                    PcdTokenSpaceList.append(Pcd.TokenSpaceGuidCName)
3231        GuidList = sdict()
3232        GuidList.update(self.GuidList)
3233        for TokenSpace in self.GetGuidsUsedByPcd():
3234            # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3235            # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3236            if TokenSpace not in PcdTokenSpaceList and TokenSpace in GuidList:
3237                GuidList.pop(TokenSpace)
3238        CheckList = (GuidList, self.PpiList, self.ProtocolList, PcdCheckList)
3239        for Package in self.DerivedPackageList:
3240            if Package in Packages:
3241                continue
3242            BeChecked = (Package.Guids, Package.Ppis, Package.Protocols, Package.Pcds)
3243            Found = False
3244            for Index in range(len(BeChecked)):
3245                for Item in CheckList[Index]:
3246                    if Item in BeChecked[Index]:
3247                        Packages += [Package]
3248                        Found = True
3249                        break
3250                if Found: break
3251
3252        VfrPcds = self._GetPcdsMaybeUsedByVfr()
3253        for Pkg in self.PlatformInfo.PackageList:
3254            if Pkg in Packages:
3255                continue
3256            for VfrPcd in VfrPcds:
3257                if ((VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, 'DynamicEx') in Pkg.Pcds or
3258                    (VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, 'Dynamic') in Pkg.Pcds):
3259                    Packages += [Pkg]
3260                    break
3261
3262        ModuleType = self.ModuleType
3263        if ModuleType == 'UEFI_DRIVER' and self.DepexGenerated:
3264            ModuleType = 'DXE_DRIVER'
3265
3266        DriverType = ''
3267        if self.PcdIsDriver != '':
3268            DriverType = self.PcdIsDriver
3269
3270        Guid = self.Guid
3271        MDefs = self.Module.Defines
3272
3273        AsBuiltInfDict = {
3274          'module_name'                       : self.Name,
3275          'module_guid'                       : Guid,
3276          'module_module_type'                : ModuleType,
3277          'module_version_string'             : [MDefs['VERSION_STRING']] if 'VERSION_STRING' in MDefs else [],
3278          'pcd_is_driver_string'              : [],
3279          'module_uefi_specification_version' : [],
3280          'module_pi_specification_version'   : [],
3281          'module_entry_point'                : self.Module.ModuleEntryPointList,
3282          'module_unload_image'               : self.Module.ModuleUnloadImageList,
3283          'module_constructor'                : self.Module.ConstructorList,
3284          'module_destructor'                 : self.Module.DestructorList,
3285          'module_shadow'                     : [MDefs['SHADOW']] if 'SHADOW' in MDefs else [],
3286          'module_pci_vendor_id'              : [MDefs['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs else [],
3287          'module_pci_device_id'              : [MDefs['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs else [],
3288          'module_pci_class_code'             : [MDefs['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs else [],
3289          'module_pci_revision'               : [MDefs['PCI_REVISION']] if 'PCI_REVISION' in MDefs else [],
3290          'module_build_number'               : [MDefs['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs else [],
3291          'module_spec'                       : [MDefs['SPEC']] if 'SPEC' in MDefs else [],
3292          'module_uefi_hii_resource_section'  : [MDefs['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs else [],
3293          'module_uni_file'                   : [MDefs['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs else [],
3294          'module_arch'                       : self.Arch,
3295          'package_item'                      : ['%s' % (Package.MetaFile.File.replace('\\', '/')) for Package in Packages],
3296          'binary_item'                       : [],
3297          'patchablepcd_item'                 : [],
3298          'pcd_item'                          : [],
3299          'protocol_item'                     : [],
3300          'ppi_item'                          : [],
3301          'guid_item'                         : [],
3302          'flags_item'                        : [],
3303          'libraryclasses_item'               : []
3304        }
3305
3306        if self.AutoGenVersion > int(gInfSpecVersion, 0):
3307            AsBuiltInfDict['module_inf_version'] = '0x%08x' % self.AutoGenVersion
3308        else:
3309            AsBuiltInfDict['module_inf_version'] = gInfSpecVersion
3310
3311        if DriverType:
3312            AsBuiltInfDict['pcd_is_driver_string'] += [DriverType]
3313
3314        if 'UEFI_SPECIFICATION_VERSION' in self.Specification:
3315          AsBuiltInfDict['module_uefi_specification_version'] += [self.Specification['UEFI_SPECIFICATION_VERSION']]
3316        if 'PI_SPECIFICATION_VERSION' in self.Specification:
3317          AsBuiltInfDict['module_pi_specification_version'] += [self.Specification['PI_SPECIFICATION_VERSION']]
3318
3319        OutputDir = self.OutputDir.replace('\\', '/').strip('/')
3320        if self.ModuleType in ['BASE', 'USER_DEFINED']:
3321          for Item in self.CodaTargetList:
3322            File = Item.Target.Path.replace('\\', '/').strip('/').replace(OutputDir, '').strip('/')
3323            if Item.Target.Ext.lower() == '.aml':
3324              AsBuiltInfDict['binary_item'] += ['ASL|' + File]
3325            elif Item.Target.Ext.lower() == '.acpi':
3326              AsBuiltInfDict['binary_item'] += ['ACPI|' + File]
3327            else:
3328              AsBuiltInfDict['binary_item'] += ['BIN|' + File]
3329        else:
3330          for Item in self.CodaTargetList:
3331            File = Item.Target.Path.replace('\\', '/').strip('/').replace(OutputDir, '').strip('/')
3332            if Item.Target.Ext.lower() == '.efi':
3333              AsBuiltInfDict['binary_item'] += ['PE32|' + self.Name + '.efi']
3334            else:
3335              AsBuiltInfDict['binary_item'] += ['BIN|' + File]
3336          if self.DepexGenerated:
3337            if self.ModuleType in ['PEIM']:
3338              AsBuiltInfDict['binary_item'] += ['PEI_DEPEX|' + self.Name + '.depex']
3339            if self.ModuleType in ['DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'UEFI_DRIVER']:
3340              AsBuiltInfDict['binary_item'] += ['DXE_DEPEX|' + self.Name + '.depex']
3341            if self.ModuleType in ['DXE_SMM_DRIVER']:
3342              AsBuiltInfDict['binary_item'] += ['SMM_DEPEX|' + self.Name + '.depex']
3343
3344        Bin = self._GenOffsetBin()
3345        if Bin:
3346            AsBuiltInfDict['binary_item'] += ['BIN|%s' % Bin]
3347
3348        for Root, Dirs, Files in os.walk(OutputDir):
3349            for File in Files:
3350                if File.lower().endswith('.pdb'):
3351                    AsBuiltInfDict['binary_item'] += ['DISPOSABLE|' + File]
3352        HeaderComments = self.Module.HeaderComments
3353        StartPos = 0
3354        for Index in range(len(HeaderComments)):
3355            if HeaderComments[Index].find('@BinaryHeader') != -1:
3356                HeaderComments[Index] = HeaderComments[Index].replace('@BinaryHeader', '@file')
3357                StartPos = Index
3358                break
3359        AsBuiltInfDict['header_comments'] = '\n'.join(HeaderComments[StartPos:]).replace(':#', '://')
3360        AsBuiltInfDict['tail_comments'] = '\n'.join(self.Module.TailComments)
3361
3362        GenList = [
3363            (self.ProtocolList, self._ProtocolComments, 'protocol_item'),
3364            (self.PpiList, self._PpiComments, 'ppi_item'),
3365            (GuidList, self._GuidComments, 'guid_item')
3366        ]
3367        for Item in GenList:
3368            for CName in Item[0]:
3369                Comments = ''
3370                if CName in Item[1]:
3371                    Comments = '\n  '.join(Item[1][CName])
3372                Entry = CName
3373                if Comments:
3374                    Entry = Comments + '\n  ' + CName
3375                AsBuiltInfDict[Item[2]].append(Entry)
3376        PatchList = parsePcdInfoFromMapFile(
3377                            os.path.join(self.OutputDir, self.Name + '.map'),
3378                            os.path.join(self.OutputDir, self.Name + '.efi')
3379                        )
3380        if PatchList:
3381            for PatchPcd in PatchList:
3382                if PatchPcd[0] not in PatchablePcds:
3383                    continue
3384                Pcd = PatchablePcds[PatchPcd[0]]
3385                PcdValue = ''
3386                if Pcd.DatumType != 'VOID*':
3387                    HexFormat = '0x%02x'
3388                    if Pcd.DatumType == 'UINT16':
3389                        HexFormat = '0x%04x'
3390                    elif Pcd.DatumType == 'UINT32':
3391                        HexFormat = '0x%08x'
3392                    elif Pcd.DatumType == 'UINT64':
3393                        HexFormat = '0x%016x'
3394                    PcdValue = HexFormat % int(Pcd.DefaultValue, 0)
3395                else:
3396                    if Pcd.MaxDatumSize == None or Pcd.MaxDatumSize == '':
3397                        EdkLogger.error("build", AUTOGEN_ERROR,
3398                                        "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
3399                                        )
3400                    ArraySize = int(Pcd.MaxDatumSize, 0)
3401                    PcdValue = Pcd.DefaultValue
3402                    if PcdValue[0] != '{':
3403                        Unicode = False
3404                        if PcdValue[0] == 'L':
3405                            Unicode = True
3406                        PcdValue = PcdValue.lstrip('L')
3407                        PcdValue = eval(PcdValue)
3408                        NewValue = '{'
3409                        for Index in range(0, len(PcdValue)):
3410                            if Unicode:
3411                                CharVal = ord(PcdValue[Index])
3412                                NewValue = NewValue + '0x%02x' % (CharVal & 0x00FF) + ', ' \
3413                                        + '0x%02x' % (CharVal >> 8) + ', '
3414                            else:
3415                                NewValue = NewValue + '0x%02x' % (ord(PcdValue[Index]) % 0x100) + ', '
3416                        Padding = '0x00, '
3417                        if Unicode:
3418                            Padding = Padding * 2
3419                            ArraySize = ArraySize / 2
3420                        if ArraySize < (len(PcdValue) + 1):
3421                            EdkLogger.error("build", AUTOGEN_ERROR,
3422                                            "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
3423                                            )
3424                        if ArraySize > len(PcdValue) + 1:
3425                            NewValue = NewValue + Padding * (ArraySize - len(PcdValue) - 1)
3426                        PcdValue = NewValue + Padding.strip().rstrip(',') + '}'
3427                    elif len(PcdValue.split(',')) <= ArraySize:
3428                        PcdValue = PcdValue.rstrip('}') + ', 0x00' * (ArraySize - len(PcdValue.split(',')))
3429                        PcdValue += '}'
3430                    else:
3431                        EdkLogger.error("build", AUTOGEN_ERROR,
3432                                        "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
3433                                        )
3434                PcdItem = '%s.%s|%s|0x%X' % \
3435                    (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, PcdValue, PatchPcd[1])
3436                PcdComments = ''
3437                if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
3438                    PcdComments = '\n  '.join(self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName])
3439                if PcdComments:
3440                    PcdItem = PcdComments + '\n  ' + PcdItem
3441                AsBuiltInfDict['patchablepcd_item'].append(PcdItem)
3442
3443        HiiPcds = []
3444        for Pcd in Pcds + VfrPcds:
3445            PcdComments = ''
3446            PcdCommentList = []
3447            HiiInfo = ''
3448            SkuId = ''
3449            if Pcd.Type == TAB_PCDS_DYNAMIC_EX_HII:
3450                for SkuName in Pcd.SkuInfoList:
3451                    SkuInfo = Pcd.SkuInfoList[SkuName]
3452                    SkuId = SkuInfo.SkuId
3453                    HiiInfo = '## %s|%s|%s' % (SkuInfo.VariableName, SkuInfo.VariableGuid, SkuInfo.VariableOffset)
3454                    break
3455            if SkuId:
3456                #
3457                # Don't generate duplicated HII PCD
3458                #
3459                if (SkuId, Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in HiiPcds:
3460                    continue
3461                else:
3462                    HiiPcds.append((SkuId, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
3463            if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
3464                PcdCommentList = self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName][:]
3465            if HiiInfo:
3466                UsageIndex = -1
3467                UsageStr = ''
3468                for Index, Comment in enumerate(PcdCommentList):
3469                    for Usage in UsageList:
3470                        if Comment.find(Usage) != -1:
3471                            UsageStr = Usage
3472                            UsageIndex = Index
3473                            break
3474                if UsageIndex != -1:
3475                    PcdCommentList[UsageIndex] = '## %s %s %s' % (UsageStr, HiiInfo, PcdCommentList[UsageIndex].replace(UsageStr, ''))
3476                else:
3477                    PcdCommentList.append('## UNDEFINED ' + HiiInfo)
3478            PcdComments = '\n  '.join(PcdCommentList)
3479            PcdEntry = Pcd.TokenSpaceGuidCName + '.' + Pcd.TokenCName
3480            if PcdComments:
3481                PcdEntry = PcdComments + '\n  ' + PcdEntry
3482            AsBuiltInfDict['pcd_item'] += [PcdEntry]
3483        for Item in self.BuildOption:
3484          if 'FLAGS' in self.BuildOption[Item]:
3485            AsBuiltInfDict['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self.ToolChainFamily, self.BuildTarget, self.ToolChain, self.Arch, Item, self.BuildOption[Item]['FLAGS'].strip())]
3486
3487        # Generated LibraryClasses section in comments.
3488        for Library in self.LibraryAutoGenList:
3489            AsBuiltInfDict['libraryclasses_item'] += [Library.MetaFile.File.replace('\\', '/')]
3490
3491        # Generated depex expression section in comments.
3492        AsBuiltInfDict['depexsection_item'] = ''
3493        DepexExpresion = self._GetDepexExpresionString()
3494        if DepexExpresion:
3495            AsBuiltInfDict['depexsection_item'] = DepexExpresion
3496
3497        AsBuiltInf = TemplateString()
3498        AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))
3499
3500        SaveFileOnChange(os.path.join(self.OutputDir, self.Name + '.inf'), str(AsBuiltInf), False)
3501
3502        self.IsAsBuiltInfCreated = True
3503
3504    ## Create makefile for the module and its dependent libraries
3505    #
3506    #   @param      CreateLibraryMakeFile   Flag indicating if or not the makefiles of
3507    #                                       dependent libraries will be created
3508    #
3509    def CreateMakeFile(self, CreateLibraryMakeFile=True):
3510        # Ignore generating makefile when it is a binary module
3511        if self.IsBinaryModule:
3512            return
3513
3514        if self.IsMakeFileCreated:
3515            return
3516
3517        if not self.IsLibrary and CreateLibraryMakeFile:
3518            for LibraryAutoGen in self.LibraryAutoGenList:
3519                LibraryAutoGen.CreateMakeFile()
3520
3521        if len(self.CustomMakefile) == 0:
3522            Makefile = GenMake.ModuleMakefile(self)
3523        else:
3524            Makefile = GenMake.CustomMakefile(self)
3525        if Makefile.Generate():
3526            EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %
3527                            (self.Name, self.Arch))
3528        else:
3529            EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %
3530                            (self.Name, self.Arch))
3531
3532        self.IsMakeFileCreated = True
3533
3534    def CopyBinaryFiles(self):
3535        for File in self.Module.Binaries:
3536            SrcPath = File.Path
3537            DstPath = os.path.join(self.OutputDir , os.path.basename(SrcPath))
3538            CopyLongFilePath(SrcPath, DstPath)
3539    ## Create autogen code for the module and its dependent libraries
3540    #
3541    #   @param      CreateLibraryCodeFile   Flag indicating if or not the code of
3542    #                                       dependent libraries will be created
3543    #
3544    def CreateCodeFile(self, CreateLibraryCodeFile=True):
3545        if self.IsCodeFileCreated:
3546            return
3547
3548        # Need to generate PcdDatabase even PcdDriver is binarymodule
3549        if self.IsBinaryModule and self.PcdIsDriver != '':
3550            CreatePcdDatabaseCode(self, TemplateString(), TemplateString())
3551            return
3552        if self.IsBinaryModule:
3553            if self.IsLibrary:
3554                self.CopyBinaryFiles()
3555            return
3556
3557        if not self.IsLibrary and CreateLibraryCodeFile:
3558            for LibraryAutoGen in self.LibraryAutoGenList:
3559                LibraryAutoGen.CreateCodeFile()
3560
3561        AutoGenList = []
3562        IgoredAutoGenList = []
3563
3564        for File in self.AutoGenFileList:
3565            if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):
3566                #Ignore Edk AutoGen.c
3567                if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':
3568                        continue
3569
3570                AutoGenList.append(str(File))
3571            else:
3572                IgoredAutoGenList.append(str(File))
3573
3574        # Skip the following code for EDK I inf
3575        if self.AutoGenVersion < 0x00010005:
3576            return
3577
3578        for ModuleType in self.DepexList:
3579            # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
3580            if len(self.DepexList[ModuleType]) == 0 or ModuleType == "USER_DEFINED":
3581                continue
3582
3583            Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
3584            DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
3585
3586            if len(Dpx.PostfixNotation) <> 0:
3587                self.DepexGenerated = True
3588
3589            if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
3590                AutoGenList.append(str(DpxFile))
3591            else:
3592                IgoredAutoGenList.append(str(DpxFile))
3593
3594        if IgoredAutoGenList == []:
3595            EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %
3596                            (" ".join(AutoGenList), self.Name, self.Arch))
3597        elif AutoGenList == []:
3598            EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %
3599                            (" ".join(IgoredAutoGenList), self.Name, self.Arch))
3600        else:
3601            EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %
3602                            (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
3603
3604        self.IsCodeFileCreated = True
3605        return AutoGenList
3606
3607    ## Summarize the ModuleAutoGen objects of all libraries used by this module
3608    def _GetLibraryAutoGenList(self):
3609        if self._LibraryAutoGenList == None:
3610            self._LibraryAutoGenList = []
3611            for Library in self.DependentLibraryList:
3612                La = ModuleAutoGen(
3613                        self.Workspace,
3614                        Library.MetaFile,
3615                        self.BuildTarget,
3616                        self.ToolChain,
3617                        self.Arch,
3618                        self.PlatformInfo.MetaFile
3619                        )
3620                if La not in self._LibraryAutoGenList:
3621                    self._LibraryAutoGenList.append(La)
3622                    for Lib in La.CodaTargetList:
3623                        self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)
3624        return self._LibraryAutoGenList
3625
3626    Module          = property(_GetModule)
3627    Name            = property(_GetBaseName)
3628    Guid            = property(_GetGuid)
3629    Version         = property(_GetVersion)
3630    ModuleType      = property(_GetModuleType)
3631    ComponentType   = property(_GetComponentType)
3632    BuildType       = property(_GetBuildType)
3633    PcdIsDriver     = property(_GetPcdIsDriver)
3634    AutoGenVersion  = property(_GetAutoGenVersion)
3635    Macros          = property(_GetMacros)
3636    Specification   = property(_GetSpecification)
3637
3638    IsLibrary       = property(_IsLibrary)
3639    IsBinaryModule  = property(_IsBinaryModule)
3640    BuildDir        = property(_GetBuildDir)
3641    OutputDir       = property(_GetOutputDir)
3642    DebugDir        = property(_GetDebugDir)
3643    MakeFileDir     = property(_GetMakeFileDir)
3644    CustomMakefile  = property(_GetCustomMakefile)
3645
3646    IncludePathList = property(_GetIncludePathList)
3647    AutoGenFileList = property(_GetAutoGenFileList)
3648    UnicodeFileList = property(_GetUnicodeFileList)
3649    SourceFileList  = property(_GetSourceFileList)
3650    BinaryFileList  = property(_GetBinaryFiles) # FileType : [File List]
3651    Targets         = property(_GetTargets)
3652    IntroTargetList = property(_GetIntroTargetList)
3653    CodaTargetList  = property(_GetFinalTargetList)
3654    FileTypes       = property(_GetFileTypes)
3655    BuildRules      = property(_GetBuildRules)
3656
3657    DependentPackageList    = property(_GetDependentPackageList)
3658    DependentLibraryList    = property(_GetLibraryList)
3659    LibraryAutoGenList      = property(_GetLibraryAutoGenList)
3660    DerivedPackageList      = property(_GetDerivedPackageList)
3661
3662    ModulePcdList           = property(_GetModulePcdList)
3663    LibraryPcdList          = property(_GetLibraryPcdList)
3664    GuidList                = property(_GetGuidList)
3665    ProtocolList            = property(_GetProtocolList)
3666    PpiList                 = property(_GetPpiList)
3667    DepexList               = property(_GetDepexTokenList)
3668    DxsFile                 = property(_GetDxsFile)
3669    DepexExpressionList     = property(_GetDepexExpressionTokenList)
3670    BuildOption             = property(_GetModuleBuildOption)
3671    BuildOptionIncPathList  = property(_GetBuildOptionIncPathList)
3672    BuildCommand            = property(_GetBuildCommand)
3673
3674    FixedAtBuildPcds         = property(_GetFixedAtBuildPcds)
3675
3676# This acts like the main() function for the script, unless it is 'import'ed into another script.
3677if __name__ == '__main__':
3678    pass
3679
3680