[edk2-devel] [Patch 04/10 V8] BaseTools: Decouple AutoGen Objects

Gary Lin glin at suse.com
Thu Aug 22 08:26:43 UTC 2019


On Thu, Aug 22, 2019 at 08:15:03AM +0000,  Feng, Bob C  wrote:
> Hi Gary,
> 
> https://edk2.groups.io/g/devel/message/46196
> 
> This patch is under review and it can fix this regression issue.
> 
Oh, thanks!
Will try the patch.

Gary Lin

> Thanks,
> Bob 
> 
> -----Original Message-----
> From: devel at edk2.groups.io [mailto:devel at edk2.groups.io] On Behalf Of Gary Lin
> Sent: Thursday, August 22, 2019 4:05 PM
> To: devel at edk2.groups.io; Feng, Bob C <bob.c.feng at intel.com>
> Cc: Gao, Liming <liming.gao at intel.com>; Shi, Steven <steven.shi at intel.com>
> Subject: Re: [edk2-devel] [Patch 04/10 V8] BaseTools: Decouple AutoGen Objects
> 
> On Wed, Aug 07, 2019 at 12:25:31PM +0800,  Bob Feng  wrote:
> > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1875
> > 
> > 1. Separate the AutoGen.py into 3 small py files.
> > One is for AutoGen base class, one is for WorkspaceAutoGen class
> > and PlatformAutoGen class, and the one for ModuleAutoGen class.
> > 2. Create a new class DataPipe to store the Platform scope settings.
> > Create a new class PlatformInfo to provide the same interface
> > as PlatformAutoGen. PlatformInfo class is initialized by
> > DataPipe instance.
> > Create a new class WorkspaceInfo to provide the same interface
> > as WorkspaceAutoGen. WorkspaceInfo class is initialized by
> > DataPipe instance.
> > 3. Change ModuleAutoGen to depends on DataPipe, PlatformInfo and
> > WorkspaceInfo. Remove the dependency of ModuleAutoGen to PlatformAutoGen.
> > 
> I found a regression of the dependency check.
> 
> When adding a driver, e.g. OpalPasswordPei, to OVMF without setting the
> library dependencies correctly, before this patch, 'build' would show the
> missing library and stop immediately. Now, 'build' doesn't complain anything
> and just starts compiling the code. It ends up in some strange errors due
> to the missing libraries.
> 
> It's easy to reproduce the bug with the following patch:
> 
> diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
> index 68073ef55b4d..7d67706612d1 100644
> --- a/OvmfPkg/OvmfPkgX64.dsc
> +++ b/OvmfPkg/OvmfPkgX64.dsc
> @@ -636,6 +636,7 @@ [Components]
>        NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf
>        NULL|SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.inf
>    }
> +  SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
>  !if $(TPM2_CONFIG_ENABLE) == TRUE
>    SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf
>  !endif
> 
> Gary Lin
> 
> > Cc: Liming Gao <liming.gao at intel.com>
> > Cc: Steven Shi <steven.shi at intel.com>
> > Signed-off-by: Bob Feng <bob.c.feng at intel.com>
> > ---
> >  BaseTools/Source/Python/AutoGen/AutoGen.py    | 4264 +----------------
> >  BaseTools/Source/Python/AutoGen/DataPipe.py   |  147 +
> >  BaseTools/Source/Python/AutoGen/GenC.py       |    2 +-
> >  .../Source/Python/AutoGen/ModuleAutoGen.py    | 1908 ++++++++
> >  .../Python/AutoGen/ModuleAutoGenHelper.py     |  619 +++
> >  .../Source/Python/AutoGen/PlatformAutoGen.py  | 1505 ++++++
> >  .../Source/Python/AutoGen/WorkspaceAutoGen.py |  904 ++++
> >  BaseTools/Source/Python/Common/Misc.py        |    1 -
> >  .../Python/PatchPcdValue/PatchPcdValue.py     |    1 -
> >  .../Source/Python/Workspace/DscBuildData.py   |   10 +-
> >  .../Source/Python/Workspace/InfBuildData.py   |   29 +
> >  .../Python/Workspace/WorkspaceCommon.py       |    4 +
> >  .../Python/Workspace/WorkspaceDatabase.py     |    3 +
> >  BaseTools/Source/Python/build/BuildReport.py  |    4 +-
> >  BaseTools/Source/Python/build/build.py        |   51 +-
> >  15 files changed, 5204 insertions(+), 4248 deletions(-)
> >  create mode 100644 BaseTools/Source/Python/AutoGen/DataPipe.py
> >  create mode 100644 BaseTools/Source/Python/AutoGen/ModuleAutoGen.py
> >  create mode 100644 BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py
> >  create mode 100644 BaseTools/Source/Python/AutoGen/PlatformAutoGen.py
> >  create mode 100644 BaseTools/Source/Python/AutoGen/WorkspaceAutoGen.py
> > 
> > diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py b/BaseTools/Source/Python/AutoGen/AutoGen.py
> > index bb0da46d74a9..d9ee699d8f30 100644
> > --- a/BaseTools/Source/Python/AutoGen/AutoGen.py
> > +++ b/BaseTools/Source/Python/AutoGen/AutoGen.py
> > @@ -10,226 +10,11 @@
> >
> >  ## Import Modules
> >  #
> >  from __future__ import print_function
> >  from __future__ import absolute_import
> > -import Common.LongFilePathOs as os
> > -import re
> > -import os.path as path
> > -import copy
> > -import uuid
> > -
> > -from . import GenC
> > -from . import GenMake
> > -from . import GenDepex
> > -from io import BytesIO
> > -
> > -from .StrGather import *
> > -from .BuildEngine import BuildRuleObj as BuildRule
> > -from .BuildEngine import gDefaultBuildRuleFile,AutoGenReqBuildRuleVerNum
> > -import shutil
> > -from Common.LongFilePathSupport import CopyLongFilePath
> > -from Common.BuildToolError import *
> > -from Common.DataType import *
> > -from Common.Misc import *
> > -from Common.StringUtils import *
> > -import Common.GlobalData as GlobalData
> > -from GenFds.FdfParser import *
> > -from CommonDataClass.CommonClass import SkuInfoClass
> > -from GenPatchPcdTable.GenPatchPcdTable import parsePcdInfoFromMapFile
> > -import Common.VpdInfoFile as VpdInfoFile
> > -from .GenPcdDb import CreatePcdDatabaseCode
> > -from Workspace.MetaFileCommentParser import UsageList
> > -from Workspace.WorkspaceCommon import GetModuleLibInstances
> > -from Common.MultipleWorkspace import MultipleWorkspace as mws
> > -from . import InfSectionParser
> > -import datetime
> > -import hashlib
> > -from .GenVar import VariableMgr, var_info
> > -from collections import OrderedDict
> > -from collections import defaultdict
> > -from Workspace.WorkspaceCommon import OrderedListDict
> > -from Common.ToolDefClassObject import gDefaultToolsDefFile
> > -
> > -from Common.caching import cached_property, cached_class_function
> > -
> > -## Regular expression for splitting Dependency Expression string into tokens
> > -gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")
> > -
> > -## Regular expression for match: PCD(xxxx.yyy)
> > -gPCDAsGuidPattern = re.compile(r"^PCD\(.+\..+\)$")
> > -
> > -#
> > -# Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
> > -# is the former use /I , the Latter used -I to specify include directories
> > -#
> > -gBuildOptIncludePatternMsft = re.compile(r"(?:.*?)/I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)
> > -gBuildOptIncludePatternOther = re.compile(r"(?:.*?)-I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)
> > -
> > -#
> > -# Match name = variable
> > -#
> > -gEfiVarStoreNamePattern = re.compile("\s*name\s*=\s*(\w+)")
> > -#
> > -# The format of guid in efivarstore statement likes following and must be correct:
> > -# guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
> > -#
> > -gEfiVarStoreGuidPattern = re.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
> > -
> > -## Mapping Makefile type
> > -gMakeTypeMap = {TAB_COMPILER_MSFT:"nmake", "GCC":"gmake"}
> > -
> > -
> > -## default file name for AutoGen
> > -gAutoGenCodeFileName = "AutoGen.c"
> > -gAutoGenHeaderFileName = "AutoGen.h"
> > -gAutoGenStringFileName = "%(module_name)sStrDefs.h"
> > -gAutoGenStringFormFileName = "%(module_name)sStrDefs.hpk"
> > -gAutoGenDepexFileName = "%(module_name)s.depex"
> > -gAutoGenImageDefFileName = "%(module_name)sImgDefs.h"
> > -gAutoGenIdfFileName = "%(module_name)sIdf.hpk"
> > -gInfSpecVersion = "0x00010017"
> > -
> > -#
> > -# Template string to generic AsBuilt INF
> > -#
> > -gAsBuiltInfHeaderString = TemplateString("""${header_comments}
> > -
> > -# DO NOT EDIT
> > -# FILE auto-generated
> > -
> > -[Defines]
> > -  INF_VERSION                = ${module_inf_version}
> > -  BASE_NAME                  = ${module_name}
> > -  FILE_GUID                  = ${module_guid}
> > -  MODULE_TYPE                = ${module_module_type}${BEGIN}
> > -  VERSION_STRING             = ${module_version_string}${END}${BEGIN}
> > -  PCD_IS_DRIVER              = ${pcd_is_driver_string}${END}${BEGIN}
> > -  UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
> > -  PI_SPECIFICATION_VERSION   = ${module_pi_specification_version}${END}${BEGIN}
> > -  ENTRY_POINT                = ${module_entry_point}${END}${BEGIN}
> > -  UNLOAD_IMAGE               = ${module_unload_image}${END}${BEGIN}
> > -  CONSTRUCTOR                = ${module_constructor}${END}${BEGIN}
> > -  DESTRUCTOR                 = ${module_destructor}${END}${BEGIN}
> > -  SHADOW                     = ${module_shadow}${END}${BEGIN}
> > -  PCI_VENDOR_ID              = ${module_pci_vendor_id}${END}${BEGIN}
> > -  PCI_DEVICE_ID              = ${module_pci_device_id}${END}${BEGIN}
> > -  PCI_CLASS_CODE             = ${module_pci_class_code}${END}${BEGIN}
> > -  PCI_REVISION               = ${module_pci_revision}${END}${BEGIN}
> > -  BUILD_NUMBER               = ${module_build_number}${END}${BEGIN}
> > -  SPEC                       = ${module_spec}${END}${BEGIN}
> > -  UEFI_HII_RESOURCE_SECTION  = ${module_uefi_hii_resource_section}${END}${BEGIN}
> > -  MODULE_UNI_FILE            = ${module_uni_file}${END}
> > -
> > -[Packages.${module_arch}]${BEGIN}
> > -  ${package_item}${END}
> > -
> > -[Binaries.${module_arch}]${BEGIN}
> > -  ${binary_item}${END}
> > -
> > -[PatchPcd.${module_arch}]${BEGIN}
> > -  ${patchablepcd_item}
> > -${END}
> > -
> > -[Protocols.${module_arch}]${BEGIN}
> > -  ${protocol_item}
> > -${END}
> > -
> > -[Ppis.${module_arch}]${BEGIN}
> > -  ${ppi_item}
> > -${END}
> > -
> > -[Guids.${module_arch}]${BEGIN}
> > -  ${guid_item}
> > -${END}
> > -
> > -[PcdEx.${module_arch}]${BEGIN}
> > -  ${pcd_item}
> > -${END}
> > -
> > -[LibraryClasses.${module_arch}]
> > -## @LIB_INSTANCES${BEGIN}
> > -#  ${libraryclasses_item}${END}
> > -
> > -${depexsection_item}
> > -
> > -${userextension_tianocore_item}
> > -
> > -${tail_comments}
> > -
> > -[BuildOptions.${module_arch}]
> > -## @AsBuilt${BEGIN}
> > -##   ${flags_item}${END}
> > -""")
> > -## Split command line option string to list
> > -#
> > -# subprocess.Popen needs the args to be a sequence. Otherwise there's problem
> > -# in non-windows platform to launch command
> > -#
> > -def _SplitOption(OptionString):
> > -    OptionList = []
> > -    LastChar = " "
> > -    OptionStart = 0
> > -    QuotationMark = ""
> > -    for Index in range(0, len(OptionString)):
> > -        CurrentChar = OptionString[Index]
> > -        if CurrentChar in ['"', "'"]:
> > -            if QuotationMark == CurrentChar:
> > -                QuotationMark = ""
> > -            elif QuotationMark == "":
> > -                QuotationMark = CurrentChar
> > -            continue
> > -        elif QuotationMark:
> > -            continue
> > -
> > -        if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]:
> > -            if Index > OptionStart:
> > -                OptionList.append(OptionString[OptionStart:Index - 1])
> > -            OptionStart = Index
> > -        LastChar = CurrentChar
> > -    OptionList.append(OptionString[OptionStart:])
> > -    return OptionList
> > -
> > -#
> > -# Convert string to C format array
> > -#
> > -def _ConvertStringToByteArray(Value):
> > -    Value = Value.strip()
> > -    if not Value:
> > -        return None
> > -    if Value[0] == '{':
> > -        if not Value.endswith('}'):
> > -            return None
> > -        Value = Value.replace(' ', '').replace('{', '').replace('}', '')
> > -        ValFields = Value.split(',')
> > -        try:
> > -            for Index in range(len(ValFields)):
> > -                ValFields[Index] = str(int(ValFields[Index], 0))
> > -        except ValueError:
> > -            return None
> > -        Value = '{' + ','.join(ValFields) + '}'
> > -        return Value
> > -
> > -    Unicode = False
> > -    if Value.startswith('L"'):
> > -        if not Value.endswith('"'):
> > -            return None
> > -        Value = Value[1:]
> > -        Unicode = True
> > -    elif not Value.startswith('"') or not Value.endswith('"'):
> > -        return None
> > -
> > -    Value = eval(Value)         # translate escape character
> > -    NewValue = '{'
> > -    for Index in range(0, len(Value)):
> > -        if Unicode:
> > -            NewValue = NewValue + str(ord(Value[Index]) % 0x10000) + ','
> > -        else:
> > -            NewValue = NewValue + str(ord(Value[Index]) % 0x100) + ','
> > -    Value = NewValue + '0}'
> > -    return Value
> > -
> > +from Common.DataType import TAB_STAR
> >  ## Base class for AutoGen
> >  #
> >  #   This class just implements the cache mechanism of AutoGen objects.
> >  #
> >  class AutoGen(object):
> > @@ -246,10 +31,11 @@ class AutoGen(object):
> >      #   @param  Toolchain       Tool chain name
> >      #   @param  Arch            Target arch
> >      #   @param  *args           The specific class related parameters
> >      #   @param  **kwargs        The specific class related dict parameters
> >      #
> > +
> >      def __new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
> >          # check if the object has been created
> >          Key = (Target, Toolchain, Arch, MetaFile)
> >          if Key in cls.__ObjectCache:
> >              # if it exists, just return it directly
> > @@ -279,4007 +65,49 @@ class AutoGen(object):
> >
> >      ## "==" operator
> >      def __eq__(self, Other):
> >          return Other and self.MetaFile == Other
> >
> > -## Workspace AutoGen class
> > -#
> > -#   This class is used mainly to control the whole platform build for different
> > -# architecture. This class will generate top level makefile.
> > -#
> > -class WorkspaceAutoGen(AutoGen):
> > -    # call super().__init__ then call the worker function with different parameter count
> > -    def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
> > -        if not hasattr(self, "_Init"):
> > -            self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)
> > -            self._Init = True
> > -
> > -    ## Initialize WorkspaceAutoGen
> > -    #
> > -    #   @param  WorkspaceDir            Root directory of workspace
> > -    #   @param  ActivePlatform          Meta-file of active platform
> > -    #   @param  Target                  Build target
> > -    #   @param  Toolchain               Tool chain name
> > -    #   @param  ArchList                List of architecture of current build
> > -    #   @param  MetaFileDb              Database containing meta-files
> > -    #   @param  BuildConfig             Configuration of build
> > -    #   @param  ToolDefinition          Tool chain definitions
> > -    #   @param  FlashDefinitionFile     File of flash definition
> > -    #   @param  Fds                     FD list to be generated
> > -    #   @param  Fvs                     FV list to be generated
> > -    #   @param  Caps                    Capsule list to be generated
> > -    #   @param  SkuId                   SKU id from command line
> > -    #
> > -    def _InitWorker(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb,
> > -              BuildConfig, ToolDefinition, FlashDefinitionFile='', Fds=None, Fvs=None, Caps=None, SkuId='', UniFlag=None,
> > -              Progress=None, BuildModule=None):
> > -        self.BuildDatabase  = MetaFileDb
> > -        self.MetaFile       = ActivePlatform
> > -        self.WorkspaceDir   = WorkspaceDir
> > -        self.Platform       = self.BuildDatabase[self.MetaFile, TAB_ARCH_COMMON, Target, Toolchain]
> > -        GlobalData.gActivePlatform = self.Platform
> > -        self.BuildTarget    = Target
> > -        self.ToolChain      = Toolchain
> > -        self.ArchList       = ArchList
> > -        self.SkuId          = SkuId
> > -        self.UniFlag        = UniFlag
> > -
> > -        self.TargetTxt      = BuildConfig
> > -        self.ToolDef        = ToolDefinition
> > -        self.FdfFile        = FlashDefinitionFile
> > -        self.FdTargetList   = Fds if Fds else []
> > -        self.FvTargetList   = Fvs if Fvs else []
> > -        self.CapTargetList  = Caps if Caps else []
> > -        self.AutoGenObjectList = []
> > -        self._GuidDict = {}
> > -
> > -        # there's many relative directory operations, so ...
> > -        os.chdir(self.WorkspaceDir)
> > -
> > -        self.MergeArch()
> > -        self.ValidateBuildTarget()
> > -
> > -        EdkLogger.info("")
> > -        if self.ArchList:
> > -            EdkLogger.info('%-16s = %s' % ("Architecture(s)", ' '.join(self.ArchList)))
> > -        EdkLogger.info('%-16s = %s' % ("Build target", self.BuildTarget))
> > -        EdkLogger.info('%-16s = %s' % ("Toolchain", self.ToolChain))
> > -
> > -        EdkLogger.info('\n%-24s = %s' % ("Active Platform", self.Platform))
> > -        if BuildModule:
> > -            EdkLogger.info('%-24s = %s' % ("Active Module", BuildModule))
> > -
> > -        if self.FdfFile:
> > -            EdkLogger.info('%-24s = %s' % ("Flash Image Definition", self.FdfFile))
> > -
> > -        EdkLogger.verbose("\nFLASH_DEFINITION = %s" % self.FdfFile)
> > -
> > -        if Progress:
> > -            Progress.Start("\nProcessing meta-data")
> > -        #
> > -        # Mark now build in AutoGen Phase
> > -        #
> > -        GlobalData.gAutoGenPhase = True
> > -        self.ProcessModuleFromPdf()
> > -        self.ProcessPcdType()
> > -        self.ProcessMixedPcd()
> > -        self.GetPcdsFromFDF()
> > -        self.CollectAllPcds()
> > -        self.GeneratePkgLevelHash()
> > -        #
> > -        # Check PCDs token value conflict in each DEC file.
> > -        #
> > -        self._CheckAllPcdsTokenValueConflict()
> > -        #
> > -        # Check PCD type and definition between DSC and DEC
> > -        #
> > -        self._CheckPcdDefineAndType()
> > -
> > -        self.CreateBuildOptionsFile()
> > -        self.CreatePcdTokenNumberFile()
> > -        self.CreateModuleHashInfo()
> > -        GlobalData.gAutoGenPhase = False
> > -
> > -    #
> > -    # Merge Arch
> > -    #
> > -    def MergeArch(self):
> > -        if not self.ArchList:
> > -            ArchList = set(self.Platform.SupArchList)
> > -        else:
> > -            ArchList = set(self.ArchList) & set(self.Platform.SupArchList)
> > -        if not ArchList:
> > -            EdkLogger.error("build", PARAMETER_INVALID,
> > -                            ExtraData = "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self.Platform.SupArchList)))
> > -        elif self.ArchList and len(ArchList) != len(self.ArchList):
> > -            SkippedArchList = set(self.ArchList).symmetric_difference(set(self.Platform.SupArchList))
> > -            EdkLogger.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
> > -                              % (" ".join(SkippedArchList), " ".join(self.Platform.SupArchList)))
> > -        self.ArchList = tuple(ArchList)
> > -
> > -    # Validate build target
> > -    def ValidateBuildTarget(self):
> > -        if self.BuildTarget not in self.Platform.BuildTargets:
> > -            EdkLogger.error("build", PARAMETER_INVALID,
> > -                            ExtraData="Build target [%s] is not supported by the platform. [Valid target: %s]"
> > -                                      % (self.BuildTarget, " ".join(self.Platform.BuildTargets)))
> > -    @cached_property
> > -    def FdfProfile(self):
> > -        if not self.FdfFile:
> > -            self.FdfFile = self.Platform.FlashDefinition
> > -
> > -        FdfProfile = None
> > -        if self.FdfFile:
> > -            Fdf = FdfParser(self.FdfFile.Path)
> > -            Fdf.ParseFile()
> > -            GlobalData.gFdfParser = Fdf
> > -            if Fdf.CurrentFdName and Fdf.CurrentFdName in Fdf.Profile.FdDict:
> > -                FdDict = Fdf.Profile.FdDict[Fdf.CurrentFdName]
> > -                for FdRegion in FdDict.RegionList:
> > -                    if str(FdRegion.RegionType) is 'FILE' and self.Platform.VpdToolGuid in str(FdRegion.RegionDataList):
> > -                        if int(FdRegion.Offset) % 8 != 0:
> > -                            EdkLogger.error("build", FORMAT_INVALID, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion.Offset))
> > -            FdfProfile = Fdf.Profile
> > -        else:
> > -            if self.FdTargetList:
> > -                EdkLogger.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self.FdTargetList))
> > -                self.FdTargetList = []
> > -            if self.FvTargetList:
> > -                EdkLogger.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self.FvTargetList))
> > -                self.FvTargetList = []
> > -            if self.CapTargetList:
> > -                EdkLogger.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self.CapTargetList))
> > -                self.CapTargetList = []
> > -
> > -        return FdfProfile
> > -
> > -    def ProcessModuleFromPdf(self):
> > -
> > -        if self.FdfProfile:
> > -            for fvname in self.FvTargetList:
> > -                if fvname.upper() not in self.FdfProfile.FvDict:
> > -                    EdkLogger.error("build", OPTION_VALUE_INVALID,
> > -                                    "No such an FV in FDF file: %s" % fvname)
> > -
> > -            # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
> > -            # but the path (self.MetaFile.Path) is the real path
> > -            for key in self.FdfProfile.InfDict:
> > -                if key == 'ArchTBD':
> > -                    MetaFile_cache = defaultdict(set)
> > -                    for Arch in self.ArchList:
> > -                        Current_Platform_cache = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]
> > -                        for Pkey in Current_Platform_cache.Modules:
> > -                            MetaFile_cache[Arch].add(Current_Platform_cache.Modules[Pkey].MetaFile)
> > -                    for Inf in self.FdfProfile.InfDict[key]:
> > -                        ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)
> > -                        for Arch in self.ArchList:
> > -                            if ModuleFile in MetaFile_cache[Arch]:
> > -                                break
> > -                        else:
> > -                            ModuleData = self.BuildDatabase[ModuleFile, Arch, self.BuildTarget, self.ToolChain]
> > -                            if not ModuleData.IsBinaryModule:
> > -                                EdkLogger.error('build', PARSER_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile)
> > -
> > -                else:
> > -                    for Arch in self.ArchList:
> > -                        if Arch == key:
> > -                            Platform = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]
> > -                            MetaFileList = set()
> > -                            for Pkey in Platform.Modules:
> > -                                MetaFileList.add(Platform.Modules[Pkey].MetaFile)
> > -                            for Inf in self.FdfProfile.InfDict[key]:
> > -                                ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)
> > -                                if ModuleFile in MetaFileList:
> > -                                    continue
> > -                                ModuleData = self.BuildDatabase[ModuleFile, Arch, self.BuildTarget, self.ToolChain]
> > -                                if not ModuleData.IsBinaryModule:
> > -                                    EdkLogger.error('build', PARSER_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile)
> > -
> > -
> > -
> > -    # parse FDF file to get PCDs in it, if any
> > -    def GetPcdsFromFDF(self):
> > -
> > -        if self.FdfProfile:
> > -            PcdSet = self.FdfProfile.PcdDict
> > -            # handle the mixed pcd in FDF file
> > -            for key in PcdSet:
> > -                if key in GlobalData.MixedPcd:
> > -                    Value = PcdSet[key]
> > -                    del PcdSet[key]
> > -                    for item in GlobalData.MixedPcd[key]:
> > -                        PcdSet[item] = Value
> > -            self.VerifyPcdDeclearation(PcdSet)
> > -
> > -    def ProcessPcdType(self):
> > -        for Arch in self.ArchList:
> > -            Platform = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]
> > -            Platform.Pcds
> > -            # generate the SourcePcdDict and BinaryPcdDict
> > -            PGen = PlatformAutoGen(self, self.MetaFile, self.BuildTarget, self.ToolChain, Arch)
> > -            for BuildData in list(PGen.BuildDatabase._CACHE_.values()):
> > -                if BuildData.Arch != Arch:
> > -                    continue
> > -                if BuildData.MetaFile.Ext == '.inf':
> > -                    for key in BuildData.Pcds:
> > -                        if BuildData.Pcds[key].Pending:
> > -                            if key in Platform.Pcds:
> > -                                PcdInPlatform = Platform.Pcds[key]
> > -                                if PcdInPlatform.Type:
> > -                                    BuildData.Pcds[key].Type = PcdInPlatform.Type
> > -                                    BuildData.Pcds[key].Pending = False
> > -
> > -                            if BuildData.MetaFile in Platform.Modules:
> > -                                PlatformModule = Platform.Modules[str(BuildData.MetaFile)]
> > -                                if key in PlatformModule.Pcds:
> > -                                    PcdInPlatform = PlatformModule.Pcds[key]
> > -                                    if PcdInPlatform.Type:
> > -                                        BuildData.Pcds[key].Type = PcdInPlatform.Type
> > -                                        BuildData.Pcds[key].Pending = False
> > -                            else:
> > -                                #Pcd used in Library, Pcd Type from reference module if Pcd Type is Pending
> > -                                if BuildData.Pcds[key].Pending:
> > -                                    MGen = ModuleAutoGen(self, BuildData.MetaFile, self.BuildTarget, self.ToolChain, Arch, self.MetaFile)
> > -                                    if MGen and MGen.IsLibrary:
> > -                                        if MGen in PGen.LibraryAutoGenList:
> > -                                            ReferenceModules = MGen.ReferenceModules
> > -                                            for ReferenceModule in ReferenceModules:
> > -                                                if ReferenceModule.MetaFile in Platform.Modules:
> > -                                                    RefPlatformModule = Platform.Modules[str(ReferenceModule.MetaFile)]
> > -                                                    if key in RefPlatformModule.Pcds:
> > -                                                        PcdInReferenceModule = RefPlatformModule.Pcds[key]
> > -                                                        if PcdInReferenceModule.Type:
> > -                                                            BuildData.Pcds[key].Type = PcdInReferenceModule.Type
> > -                                                            BuildData.Pcds[key].Pending = False
> > -                                                            break
> > -
> > -    def ProcessMixedPcd(self):
> > -        for Arch in self.ArchList:
> > -            SourcePcdDict = {TAB_PCDS_DYNAMIC_EX:set(), TAB_PCDS_PATCHABLE_IN_MODULE:set(),TAB_PCDS_DYNAMIC:set(),TAB_PCDS_FIXED_AT_BUILD:set()}
> > -            BinaryPcdDict = {TAB_PCDS_DYNAMIC_EX:set(), TAB_PCDS_PATCHABLE_IN_MODULE:set()}
> > -            SourcePcdDict_Keys = SourcePcdDict.keys()
> > -            BinaryPcdDict_Keys = BinaryPcdDict.keys()
> > -
> > -            # generate the SourcePcdDict and BinaryPcdDict
> > -            PGen = PlatformAutoGen(self, self.MetaFile, self.BuildTarget, self.ToolChain, Arch)
> > -            for BuildData in list(PGen.BuildDatabase._CACHE_.values()):
> > -                if BuildData.Arch != Arch:
> > -                    continue
> > -                if BuildData.MetaFile.Ext == '.inf':
> > -                    for key in BuildData.Pcds:
> > -                        if TAB_PCDS_DYNAMIC_EX in BuildData.Pcds[key].Type:
> > -                            if BuildData.IsBinaryModule:
> > -                                BinaryPcdDict[TAB_PCDS_DYNAMIC_EX].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
> > -                            else:
> > -                                SourcePcdDict[TAB_PCDS_DYNAMIC_EX].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
> > -
> > -                        elif TAB_PCDS_PATCHABLE_IN_MODULE in BuildData.Pcds[key].Type:
> > -                            if BuildData.MetaFile.Ext == '.inf':
> > -                                if BuildData.IsBinaryModule:
> > -                                    BinaryPcdDict[TAB_PCDS_PATCHABLE_IN_MODULE].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
> > -                                else:
> > -                                    SourcePcdDict[TAB_PCDS_PATCHABLE_IN_MODULE].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
> > -
> > -                        elif TAB_PCDS_DYNAMIC in BuildData.Pcds[key].Type:
> > -                            SourcePcdDict[TAB_PCDS_DYNAMIC].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
> > -                        elif TAB_PCDS_FIXED_AT_BUILD in BuildData.Pcds[key].Type:
> > -                            SourcePcdDict[TAB_PCDS_FIXED_AT_BUILD].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
> > -
> > -            #
> > -            # A PCD can only use one type for all source modules
> > -            #
> > -            for i in SourcePcdDict_Keys:
> > -                for j in SourcePcdDict_Keys:
> > -                    if i != j:
> > -                        Intersections = SourcePcdDict[i].intersection(SourcePcdDict[j])
> > -                        if len(Intersections) > 0:
> > -                            EdkLogger.error(
> > -                            'build',
> > -                            FORMAT_INVALID,
> > -                            "Building modules from source INFs, following PCD use %s and %s access method. It must be corrected to use only one access method." % (i, j),
> > -                            ExtraData='\n\t'.join(str(P[1]+'.'+P[0]) for P in Intersections)
> > -                            )
> > -
> > -            #
> > -            # intersection the BinaryPCD for Mixed PCD
> > -            #
> > -            for i in BinaryPcdDict_Keys:
> > -                for j in BinaryPcdDict_Keys:
> > -                    if i != j:
> > -                        Intersections = BinaryPcdDict[i].intersection(BinaryPcdDict[j])
> > -                        for item in Intersections:
> > -                            NewPcd1 = (item[0] + '_' + i, item[1])
> > -                            NewPcd2 = (item[0] + '_' + j, item[1])
> > -                            if item not in GlobalData.MixedPcd:
> > -                                GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]
> > -                            else:
> > -                                if NewPcd1 not in GlobalData.MixedPcd[item]:
> > -                                    GlobalData.MixedPcd[item].append(NewPcd1)
> > -                                if NewPcd2 not in GlobalData.MixedPcd[item]:
> > -                                    GlobalData.MixedPcd[item].append(NewPcd2)
> > -
> > -            #
> > -            # intersection the SourcePCD and BinaryPCD for Mixed PCD
> > -            #
> > -            for i in SourcePcdDict_Keys:
> > -                for j in BinaryPcdDict_Keys:
> > -                    if i != j:
> > -                        Intersections = SourcePcdDict[i].intersection(BinaryPcdDict[j])
> > -                        for item in Intersections:
> > -                            NewPcd1 = (item[0] + '_' + i, item[1])
> > -                            NewPcd2 = (item[0] + '_' + j, item[1])
> > -                            if item not in GlobalData.MixedPcd:
> > -                                GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]
> > -                            else:
> > -                                if NewPcd1 not in GlobalData.MixedPcd[item]:
> > -                                    GlobalData.MixedPcd[item].append(NewPcd1)
> > -                                if NewPcd2 not in GlobalData.MixedPcd[item]:
> > -                                    GlobalData.MixedPcd[item].append(NewPcd2)
> > -
> > -            for BuildData in list(PGen.BuildDatabase._CACHE_.values()):
> > -                if BuildData.Arch != Arch:
> > -                    continue
> > -                for key in BuildData.Pcds:
> > -                    for SinglePcd in GlobalData.MixedPcd:
> > -                        if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) == SinglePcd:
> > -                            for item in GlobalData.MixedPcd[SinglePcd]:
> > -                                Pcd_Type = item[0].split('_')[-1]
> > -                                if (Pcd_Type == BuildData.Pcds[key].Type) or (Pcd_Type == TAB_PCDS_DYNAMIC_EX and BuildData.Pcds[key].Type in PCD_DYNAMIC_EX_TYPE_SET) or \
> > -                                   (Pcd_Type == TAB_PCDS_DYNAMIC and BuildData.Pcds[key].Type in PCD_DYNAMIC_TYPE_SET):
> > -                                    Value = BuildData.Pcds[key]
> > -                                    Value.TokenCName = BuildData.Pcds[key].TokenCName + '_' + Pcd_Type
> > -                                    if len(key) == 2:
> > -                                        newkey = (Value.TokenCName, key[1])
> > -                                    elif len(key) == 3:
> > -                                        newkey = (Value.TokenCName, key[1], key[2])
> > -                                    del BuildData.Pcds[key]
> > -                                    BuildData.Pcds[newkey] = Value
> > -                                    break
> > -                            break
> > -
> > -    #Collect package set information from INF of FDF
> > -    @cached_property
> > -    def PkgSet(self):
> > -        if not self.FdfFile:
> > -            self.FdfFile = self.Platform.FlashDefinition
> > -
> > -        if self.FdfFile:
> > -            ModuleList = self.FdfProfile.InfList
> > -        else:
> > -            ModuleList = []
> > -        Pkgs = {}
> > -        for Arch in self.ArchList:
> > -            Platform = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]
> > -            PGen = PlatformAutoGen(self, self.MetaFile, self.BuildTarget, self.ToolChain, Arch)
> > -            PkgSet = set()
> > -            for Inf in ModuleList:
> > -                ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)
> > -                if ModuleFile in Platform.Modules:
> > -                    continue
> > -                ModuleData = self.BuildDatabase[ModuleFile, Arch, self.BuildTarget, self.ToolChain]
> > -                PkgSet.update(ModuleData.Packages)
> > -            Pkgs[Arch] = list(PkgSet) + list(PGen.PackageList)
> > -        return Pkgs
> > -
> > -    def VerifyPcdDeclearation(self,PcdSet):
> > -        for Arch in self.ArchList:
> > -            Platform = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]
> > -            Pkgs = self.PkgSet[Arch]
> > -            DecPcds = set()
> > -            DecPcdsKey = set()
> > -            for Pkg in Pkgs:
> > -                for Pcd in Pkg.Pcds:
> > -                    DecPcds.add((Pcd[0], Pcd[1]))
> > -                    DecPcdsKey.add((Pcd[0], Pcd[1], Pcd[2]))
> > -
> > -            Platform.SkuName = self.SkuId
> > -            for Name, Guid,Fileds in PcdSet:
> > -                if (Name, Guid) not in DecPcds:
> > -                    EdkLogger.error(
> > -                        'build',
> > -                        PARSER_ERROR,
> > -                        "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid, Name),
> > -                        File = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][0],
> > -                        Line = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][1]
> > -                    )
> > -                else:
> > -                    # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
> > -                    if (Name, Guid, TAB_PCDS_FIXED_AT_BUILD) in DecPcdsKey \
> > -                        or (Name, Guid, TAB_PCDS_PATCHABLE_IN_MODULE) in DecPcdsKey \
> > -                        or (Name, Guid, TAB_PCDS_FEATURE_FLAG) in DecPcdsKey:
> > -                        continue
> > -                    elif (Name, Guid, TAB_PCDS_DYNAMIC) in DecPcdsKey or (Name, Guid, TAB_PCDS_DYNAMIC_EX) in DecPcdsKey:
> > -                        EdkLogger.error(
> > -                                'build',
> > -                                PARSER_ERROR,
> > -                                "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid, Name),
> > -                                File = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][0],
> > -                                Line = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][1]
> > -                        )
> > -    def CollectAllPcds(self):
> > -
> > -        for Arch in self.ArchList:
> > -            Pa = PlatformAutoGen(self, self.MetaFile, self.BuildTarget, self.ToolChain, Arch)
> > -            #
> > -            # Explicitly collect platform's dynamic PCDs
> > -            #
> > -            Pa.CollectPlatformDynamicPcds()
> > -            Pa.CollectFixedAtBuildPcds()
> > -            self.AutoGenObjectList.append(Pa)
> > -
> > -    #
> > -    # Generate Package level hash value
> > -    #
> > -    def GeneratePkgLevelHash(self):
> > -        for Arch in self.ArchList:
> > -            GlobalData.gPackageHash = {}
> > -            if GlobalData.gUseHashCache:
> > -                for Pkg in self.PkgSet[Arch]:
> > -                    self._GenPkgLevelHash(Pkg)
> > -
> > -
> > -    def CreateBuildOptionsFile(self):
> > -        #
> > -        # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
> > -        #
> > -        content = 'gCommandLineDefines: '
> > -        content += str(GlobalData.gCommandLineDefines)
> > -        content += TAB_LINE_BREAK
> > -        content += 'BuildOptionPcd: '
> > -        content += str(GlobalData.BuildOptionPcd)
> > -        content += TAB_LINE_BREAK
> > -        content += 'Active Platform: '
> > -        content += str(self.Platform)
> > -        content += TAB_LINE_BREAK
> > -        if self.FdfFile:
> > -            content += 'Flash Image Definition: '
> > -            content += str(self.FdfFile)
> > -            content += TAB_LINE_BREAK
> > -        SaveFileOnChange(os.path.join(self.BuildDir, 'BuildOptions'), content, False)
> > -
> > -    def CreatePcdTokenNumberFile(self):
> > -        #
> > -        # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
> > -        #
> > -        PcdTokenNumber = 'PcdTokenNumber: '
> > -        Pa = self.AutoGenObjectList[0]
> > -        if Pa.PcdTokenNumber:
> > -            if Pa.DynamicPcdList:
> > -                for Pcd in Pa.DynamicPcdList:
> > -                    PcdTokenNumber += TAB_LINE_BREAK
> > -                    PcdTokenNumber += str((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))
> > -                    PcdTokenNumber += ' : '
> > -                    PcdTokenNumber += str(Pa.PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName])
> > -        SaveFileOnChange(os.path.join(self.BuildDir, 'PcdTokenNumber'), PcdTokenNumber, False)
> > -
> > -    def CreateModuleHashInfo(self):
> > -        #
> > -        # Get set of workspace metafiles
> > -        #
> > -        AllWorkSpaceMetaFiles = self._GetMetaFiles(self.BuildTarget, self.ToolChain)
> > -
> > -        #
> > -        # Retrieve latest modified time of all metafiles
> > -        #
> > -        SrcTimeStamp = 0
> > -        for f in AllWorkSpaceMetaFiles:
> > -            if os.stat(f)[8] > SrcTimeStamp:
> > -                SrcTimeStamp = os.stat(f)[8]
> > -        self._SrcTimeStamp = SrcTimeStamp
> > -
> > -        if GlobalData.gUseHashCache:
> > -            m = hashlib.md5()
> > -            for files in AllWorkSpaceMetaFiles:
> > -                if files.endswith('.dec'):
> > -                    continue
> > -                f = open(files, 'rb')
> > -                Content = f.read()
> > -                f.close()
> > -                m.update(Content)
> > -            SaveFileOnChange(os.path.join(self.BuildDir, 'AutoGen.hash'), m.hexdigest(), False)
> > -            GlobalData.gPlatformHash = m.hexdigest()
> > -
> > -        #
> > -        # Write metafile list to build directory
> > -        #
> > -        AutoGenFilePath = os.path.join(self.BuildDir, 'AutoGen')
> > -        if os.path.exists (AutoGenFilePath):
> > -            os.remove(AutoGenFilePath)
> > -        if not os.path.exists(self.BuildDir):
> > -            os.makedirs(self.BuildDir)
> > -        with open(os.path.join(self.BuildDir, 'AutoGen'), 'w+') as file:
> > -            for f in AllWorkSpaceMetaFiles:
> > -                print(f, file=file)
> > -        return True
> > -
> > -    def _GenPkgLevelHash(self, Pkg):
> > -        if Pkg.PackageName in GlobalData.gPackageHash:
> > -            return
> > -
> > -        PkgDir = os.path.join(self.BuildDir, Pkg.Arch, Pkg.PackageName)
> > -        CreateDirectory(PkgDir)
> > -        HashFile = os.path.join(PkgDir, Pkg.PackageName + '.hash')
> > -        m = hashlib.md5()
> > -        # Get .dec file's hash value
> > -        f = open(Pkg.MetaFile.Path, 'rb')
> > -        Content = f.read()
> > -        f.close()
> > -        m.update(Content)
> > -        # Get include files hash value
> > -        if Pkg.Includes:
> > -            for inc in sorted(Pkg.Includes, key=lambda x: str(x)):
> > -                for Root, Dirs, Files in os.walk(str(inc)):
> > -                    for File in sorted(Files):
> > -                        File_Path = os.path.join(Root, File)
> > -                        f = open(File_Path, 'rb')
> > -                        Content = f.read()
> > -                        f.close()
> > -                        m.update(Content)
> > -        SaveFileOnChange(HashFile, m.hexdigest(), False)
> > -        GlobalData.gPackageHash[Pkg.PackageName] = m.hexdigest()
> > -
> > -    def _GetMetaFiles(self, Target, Toolchain):
> > -        AllWorkSpaceMetaFiles = set()
> > -        #
> > -        # add fdf
> > -        #
> > -        if self.FdfFile:
> > -            AllWorkSpaceMetaFiles.add (self.FdfFile.Path)
> > -            for f in GlobalData.gFdfParser.GetAllIncludedFile():
> > -                AllWorkSpaceMetaFiles.add (f.FileName)
> > -        #
> > -        # add dsc
> > -        #
> > -        AllWorkSpaceMetaFiles.add(self.MetaFile.Path)
> > -
> > -        #
> > -        # add build_rule.txt & tools_def.txt
> > -        #
> > -        AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultBuildRuleFile))
> > -        AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultToolsDefFile))
> > -
> > -        # add BuildOption metafile
> > -        #
> > -        AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'BuildOptions'))
> > -
> > -        # add PcdToken Number file for Dynamic/DynamicEx Pcd
> > -        #
> > -        AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'PcdTokenNumber'))
> > -
> > -        for Pa in self.AutoGenObjectList:
> > -            AllWorkSpaceMetaFiles.add(Pa.ToolDefinitionFile)
> > -
> > -        for Arch in self.ArchList:
> > -            #
> > -            # add dec
> > -            #
> > -            for Package in PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch).PackageList:
> > -                AllWorkSpaceMetaFiles.add(Package.MetaFile.Path)
> > -
> > -            #
> > -            # add included dsc
> > -            #
> > -            for filePath in self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]._RawData.IncludedFiles:
> > -                AllWorkSpaceMetaFiles.add(filePath.Path)
> > -
> > -        return AllWorkSpaceMetaFiles
> > -
> > -    def _CheckPcdDefineAndType(self):
> > -        PcdTypeSet = {TAB_PCDS_FIXED_AT_BUILD,
> > -            TAB_PCDS_PATCHABLE_IN_MODULE,
> > -            TAB_PCDS_FEATURE_FLAG,
> > -            TAB_PCDS_DYNAMIC,
> > -            TAB_PCDS_DYNAMIC_EX}
> > -
> > -        # This dict store PCDs which are not used by any modules with specified arches
> > -        UnusedPcd = OrderedDict()
> > -        for Pa in self.AutoGenObjectList:
> > -            # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
> > -            for Pcd in Pa.Platform.Pcds:
> > -                PcdType = Pa.Platform.Pcds[Pcd].Type
> > -
> > -                # If no PCD type, this PCD comes from FDF
> > -                if not PcdType:
> > -                    continue
> > -
> > -                # Try to remove Hii and Vpd suffix
> > -                if PcdType.startswith(TAB_PCDS_DYNAMIC_EX):
> > -                    PcdType = TAB_PCDS_DYNAMIC_EX
> > -                elif PcdType.startswith(TAB_PCDS_DYNAMIC):
> > -                    PcdType = TAB_PCDS_DYNAMIC
> > -
> > -                for Package in Pa.PackageList:
> > -                    # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
> > -                    if (Pcd[0], Pcd[1], PcdType) in Package.Pcds:
> > -                        break
> > -                    for Type in PcdTypeSet:
> > -                        if (Pcd[0], Pcd[1], Type) in Package.Pcds:
> > -                            EdkLogger.error(
> > -                                'build',
> > -                                FORMAT_INVALID,
> > -                                "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
> > -                                % (Pa.Platform.Pcds[Pcd].Type, Pcd[1], Pcd[0], Type),
> > -                                ExtraData=None
> > -                            )
> > -                            return
> > -                else:
> > -                    UnusedPcd.setdefault(Pcd, []).append(Pa.Arch)
> > -
> > -        for Pcd in UnusedPcd:
> > -            EdkLogger.warn(
> > -                'build',
> > -                "The PCD was not specified by any INF module in the platform for the given architecture.\n"
> > -                "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
> > -                % (Pcd[1], Pcd[0], os.path.basename(str(self.MetaFile)), str(UnusedPcd[Pcd])),
> > -                ExtraData=None
> > -            )
> > -
> > -    def __repr__(self):
> > -        return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))
> > -
> > -    ## Return the directory to store FV files
> > -    @cached_property
> > -    def FvDir(self):
> > -        return path.join(self.BuildDir, TAB_FV_DIRECTORY)
> > -
> > -    ## Return the directory to store all intermediate and final files built
> > -    @cached_property
> > -    def BuildDir(self):
> > -        return self.AutoGenObjectList[0].BuildDir
> > -
> > -    ## Return the build output directory platform specifies
> > -    @cached_property
> > -    def OutputDir(self):
> > -        return self.Platform.OutputDirectory
> > -
> > -    ## Return platform name
> > -    @cached_property
> > -    def Name(self):
> > -        return self.Platform.PlatformName
> > -
> > -    ## Return meta-file GUID
> > -    @cached_property
> > -    def Guid(self):
> > -        return self.Platform.Guid
> > -
> > -    ## Return platform version
> > -    @cached_property
> > -    def Version(self):
> > -        return self.Platform.Version
> > -
> > -    ## Return paths of tools
> > -    @cached_property
> > -    def ToolDefinition(self):
> > -        return self.AutoGenObjectList[0].ToolDefinition
> > -
> > -    ## Return directory of platform makefile
> > -    #
> > -    #   @retval     string  Makefile directory
> > -    #
> > -    @cached_property
> > -    def MakeFileDir(self):
> > -        return self.BuildDir
> > -
> > -    ## Return build command string
> > -    #
> > -    #   @retval     string  Build command string
> > -    #
> > -    @cached_property
> > -    def BuildCommand(self):
> > -        # BuildCommand should be all the same. So just get one from platform AutoGen
> > -        return self.AutoGenObjectList[0].BuildCommand
> > -
> > -    ## Check the PCDs token value conflict in each DEC file.
> > -    #
> > -    # Will cause build break and raise error message while two PCDs conflict.
> > -    #
> > -    # @return  None
> > -    #
> > -    def _CheckAllPcdsTokenValueConflict(self):
> > -        for Pa in self.AutoGenObjectList:
> > -            for Package in Pa.PackageList:
> > -                PcdList = list(Package.Pcds.values())
> > -                PcdList.sort(key=lambda x: int(x.TokenValue, 0))
> > -                Count = 0
> > -                while (Count < len(PcdList) - 1) :
> > -                    Item = PcdList[Count]
> > -                    ItemNext = PcdList[Count + 1]
> > -                    #
> > -                    # Make sure in the same token space the TokenValue should be unique
> > -                    #
> > -                    if (int(Item.TokenValue, 0) == int(ItemNext.TokenValue, 0)):
> > -                        SameTokenValuePcdList = []
> > -                        SameTokenValuePcdList.append(Item)
> > -                        SameTokenValuePcdList.append(ItemNext)
> > -                        RemainPcdListLength = len(PcdList) - Count - 2
> > -                        for ValueSameCount in range(RemainPcdListLength):
> > -                            if int(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount].TokenValue, 0) == int(Item.TokenValue, 0):
> > -                                SameTokenValuePcdList.append(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount])
> > -                            else:
> > -                                break;
> > -                        #
> > -                        # Sort same token value PCD list with TokenGuid and TokenCName
> > -                        #
> > -                        SameTokenValuePcdList.sort(key=lambda x: "%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName))
> > -                        SameTokenValuePcdListCount = 0
> > -                        while (SameTokenValuePcdListCount < len(SameTokenValuePcdList) - 1):
> > -                            Flag = False
> > -                            TemListItem = SameTokenValuePcdList[SameTokenValuePcdListCount]
> > -                            TemListItemNext = SameTokenValuePcdList[SameTokenValuePcdListCount + 1]
> > -
> > -                            if (TemListItem.TokenSpaceGuidCName == TemListItemNext.TokenSpaceGuidCName) and (TemListItem.TokenCName != TemListItemNext.TokenCName):
> > -                                for PcdItem in GlobalData.MixedPcd:
> > -                                    if (TemListItem.TokenCName, TemListItem.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem] or \
> > -                                        (TemListItemNext.TokenCName, TemListItemNext.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
> > -                                        Flag = True
> > -                                if not Flag:
> > -                                    EdkLogger.error(
> > -                                                'build',
> > -                                                FORMAT_INVALID,
> > -                                                "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
> > -                                                % (TemListItem.TokenValue, TemListItem.TokenSpaceGuidCName, TemListItem.TokenCName, TemListItemNext.TokenSpaceGuidCName, TemListItemNext.TokenCName, Package),
> > -                                                ExtraData=None
> > -                                                )
> > -                            SameTokenValuePcdListCount += 1
> > -                        Count += SameTokenValuePcdListCount
> > -                    Count += 1
> > -
> > -                PcdList = list(Package.Pcds.values())
> > -                PcdList.sort(key=lambda x: "%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName))
> > -                Count = 0
> > -                while (Count < len(PcdList) - 1) :
> > -                    Item = PcdList[Count]
> > -                    ItemNext = PcdList[Count + 1]
> > -                    #
> > -                    # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
> > -                    #
> > -                    if (Item.TokenSpaceGuidCName == ItemNext.TokenSpaceGuidCName) and (Item.TokenCName == ItemNext.TokenCName) and (int(Item.TokenValue, 0) != int(ItemNext.TokenValue, 0)):
> > -                        EdkLogger.error(
> > -                                    'build',
> > -                                    FORMAT_INVALID,
> > -                                    "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
> > -                                    % (Item.TokenValue, Item.TokenSpaceGuidCName, Item.TokenCName, Package),
> > -                                    ExtraData=None
> > -                                    )
> > -                    Count += 1
> > -    ## Generate fds command
> > -    @property
> > -    def GenFdsCommand(self):
> > -        return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()
> > -
> > -    @property
> > -    def GenFdsCommandDict(self):
> > -        FdsCommandDict = {}
> > -        LogLevel = EdkLogger.GetLevel()
> > -        if LogLevel == EdkLogger.VERBOSE:
> > -            FdsCommandDict["verbose"] = True
> > -        elif LogLevel <= EdkLogger.DEBUG_9:
> > -            FdsCommandDict["debug"] = LogLevel - 1
> > -        elif LogLevel == EdkLogger.QUIET:
> > -            FdsCommandDict["quiet"] = True
> > -
> > -        if GlobalData.gEnableGenfdsMultiThread:
> > -            FdsCommandDict["GenfdsMultiThread"] = True
> > -        if GlobalData.gIgnoreSource:
> > -            FdsCommandDict["IgnoreSources"] = True
> > -
> > -        FdsCommandDict["OptionPcd"] = []
> > -        for pcd in GlobalData.BuildOptionPcd:
> > -            if pcd[2]:
> > -                pcdname = '.'.join(pcd[0:3])
> > -            else:
> > -                pcdname = '.'.join(pcd[0:2])
> > -            if pcd[3].startswith('{'):
> > -                FdsCommandDict["OptionPcd"].append(pcdname + '=' + 'H' + '"' + pcd[3] + '"')
> > -            else:
> > -                FdsCommandDict["OptionPcd"].append(pcdname + '=' + pcd[3])
> > -
> > -        MacroList = []
> > -        # macros passed to GenFds
> > -        MacroDict = {}
> > -        MacroDict.update(GlobalData.gGlobalDefines)
> > -        MacroDict.update(GlobalData.gCommandLineDefines)
> > -        for MacroName in MacroDict:
> > -            if MacroDict[MacroName] != "":
> > -                MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))
> > -            else:
> > -                MacroList.append('"%s"' % MacroName)
> > -        FdsCommandDict["macro"] = MacroList
> > -
> > -        FdsCommandDict["fdf_file"] = [self.FdfFile]
> > -        FdsCommandDict["build_target"] = self.BuildTarget
> > -        FdsCommandDict["toolchain_tag"] = self.ToolChain
> > -        FdsCommandDict["active_platform"] = str(self)
> > -
> > -        FdsCommandDict["conf_directory"] = GlobalData.gConfDirectory
> > -        FdsCommandDict["build_architecture_list"] = ','.join(self.ArchList)
> > -        FdsCommandDict["platform_build_directory"] = self.BuildDir
> > -
> > -        FdsCommandDict["fd"] = self.FdTargetList
> > -        FdsCommandDict["fv"] = self.FvTargetList
> > -        FdsCommandDict["cap"] = self.CapTargetList
> > -        return FdsCommandDict
> > -
> > -    ## Create makefile for the platform and modules in it
> > -    #
> > -    #   @param      CreateDepsMakeFile      Flag indicating if the makefile for
> > -    #                                       modules will be created as well
> > -    #
> > -    def CreateMakeFile(self, CreateDepsMakeFile=False):
> > -        if not CreateDepsMakeFile:
> > -            return
> > -        for Pa in self.AutoGenObjectList:
> > -            Pa.CreateMakeFile(True)
> > -
> > -    ## Create autogen code for platform and modules
> > -    #
> > -    #  Since there's no autogen code for platform, this method will do nothing
> > -    #  if CreateModuleCodeFile is set to False.
> > -    #
> > -    #   @param      CreateDepsCodeFile      Flag indicating if creating module's
> > -    #                                       autogen code file or not
> > -    #
> > -    def CreateCodeFile(self, CreateDepsCodeFile=False):
> > -        if not CreateDepsCodeFile:
> > -            return
> > -        for Pa in self.AutoGenObjectList:
> > -            Pa.CreateCodeFile(True)
> > -
> > -    ## Create AsBuilt INF file the platform
> > -    #
> > -    def CreateAsBuiltInf(self):
> > -        return
> > -
> > -
> > -## AutoGen class for platform
> > -#
> > -#  PlatformAutoGen class will process the original information in platform
> > -#  file in order to generate makefile for platform.
> > -#
> > -class PlatformAutoGen(AutoGen):
> > -    # call super().__init__ then call the worker function with different parameter count
> > -    def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
> > -        if not hasattr(self, "_Init"):
> > -            self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch)
> > -            self._Init = True
> > -    #
> > -    # Used to store all PCDs for both PEI and DXE phase, in order to generate
> > -    # correct PCD database
> > -    #
> > -    _DynaPcdList_ = []
> > -    _NonDynaPcdList_ = []
> > -    _PlatformPcds = {}
> > -
> > -    #
> > -    # The priority list while override build option
> > -    #
> > -    PrioList = {"0x11111"  : 16,     #  TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
> > -                "0x01111"  : 15,     #  ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
> > -                "0x10111"  : 14,     #  TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
> > -                "0x00111"  : 13,     #  ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
> > -                "0x11011"  : 12,     #  TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
> > -                "0x01011"  : 11,     #  ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
> > -                "0x10011"  : 10,     #  TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
> > -                "0x00011"  : 9,      #  ******_*********_****_COMMANDTYPE_ATTRIBUTE
> > -                "0x11101"  : 8,      #  TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
> > -                "0x01101"  : 7,      #  ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
> > -                "0x10101"  : 6,      #  TARGET_*********_ARCH_***********_ATTRIBUTE
> > -                "0x00101"  : 5,      #  ******_*********_ARCH_***********_ATTRIBUTE
> > -                "0x11001"  : 4,      #  TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
> > -                "0x01001"  : 3,      #  ******_TOOLCHAIN_****_***********_ATTRIBUTE
> > -                "0x10001"  : 2,      #  TARGET_*********_****_***********_ATTRIBUTE
> > -                "0x00001"  : 1}      #  ******_*********_****_***********_ATTRIBUTE (Lowest)
> > -
> > -    ## Initialize PlatformAutoGen
> > -    #
> > -    #
> > -    #   @param      Workspace       WorkspaceAutoGen object
> > -    #   @param      PlatformFile    Platform file (DSC file)
> > -    #   @param      Target          Build target (DEBUG, RELEASE)
> > -    #   @param      Toolchain       Name of tool chain
> > -    #   @param      Arch            arch of the platform supports
> > -    #
> > -    def _InitWorker(self, Workspace, PlatformFile, Target, Toolchain, Arch):
> > -        EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))
> > -        GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)
> > -
> > -        self.MetaFile = PlatformFile
> > -        self.Workspace = Workspace
> > -        self.WorkspaceDir = Workspace.WorkspaceDir
> > -        self.ToolChain = Toolchain
> > -        self.BuildTarget = Target
> > -        self.Arch = Arch
> > -        self.SourceDir = PlatformFile.SubDir
> > -        self.FdTargetList = self.Workspace.FdTargetList
> > -        self.FvTargetList = self.Workspace.FvTargetList
> > -        # get the original module/package/platform objects
> > -        self.BuildDatabase = Workspace.BuildDatabase
> > -        self.DscBuildDataObj = Workspace.Platform
> > -
> > -        # flag indicating if the makefile/C-code file has been created or not
> > -        self.IsMakeFileCreated  = False
> > -
> > -        self._DynamicPcdList = None    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
> > -        self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
> > -
> > -        self._AsBuildInfList = []
> > -        self._AsBuildModuleList = []
> > -
> > -        self.VariableInfo = None
> > -
> > -        if GlobalData.gFdfParser is not None:
> > -            self._AsBuildInfList = GlobalData.gFdfParser.Profile.InfList
> > -            for Inf in self._AsBuildInfList:
> > -                InfClass = PathClass(NormPath(Inf), GlobalData.gWorkspace, self.Arch)
> > -                M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]
> > -                if not M.IsBinaryModule:
> > -                    continue
> > -                self._AsBuildModuleList.append(InfClass)
> > -        # get library/modules for build
> > -        self.LibraryBuildDirectoryList = []
> > -        self.ModuleBuildDirectoryList = []
> > -
> > -        return True
> > -
> > -    ## hash() operator of PlatformAutoGen
> > -    #
> > -    #  The platform file path and arch string will be used to represent
> > -    #  hash value of this object
> > -    #
> > -    #   @retval   int Hash value of the platform file path and arch
> > -    #
> > -    @cached_class_function
> > -    def __hash__(self):
> > -        return hash((self.MetaFile, self.Arch))
> > -
> > -    @cached_class_function
> > -    def __repr__(self):
> > -        return "%s [%s]" % (self.MetaFile, self.Arch)
> > -
> > -    ## Create autogen code for platform and modules
> > -    #
> > -    #  Since there's no autogen code for platform, this method will do nothing
> > -    #  if CreateModuleCodeFile is set to False.
> > -    #
> > -    #   @param      CreateModuleCodeFile    Flag indicating if creating module's
> > -    #                                       autogen code file or not
> > -    #
> > -    @cached_class_function
> > -    def CreateCodeFile(self, CreateModuleCodeFile=False):
> > -        # only module has code to be created, so do nothing if CreateModuleCodeFile is False
> > -        if not CreateModuleCodeFile:
> > -            return
> > -
> > -        for Ma in self.ModuleAutoGenList:
> > -            Ma.CreateCodeFile(True)
> > -
> > -    ## Generate Fds Command
> > -    @cached_property
> > -    def GenFdsCommand(self):
> > -        return self.Workspace.GenFdsCommand
> > -
> > -    ## Create makefile for the platform and modules in it
> > -    #
> > -    #   @param      CreateModuleMakeFile    Flag indicating if the makefile for
> > -    #                                       modules will be created as well
> > -    #
> > -    def CreateMakeFile(self, CreateModuleMakeFile=False, FfsCommand = {}):
> > -        if CreateModuleMakeFile:
> > -            for Ma in self._MaList:
> > -                key = (Ma.MetaFile.File, self.Arch)
> > -                if key in FfsCommand:
> > -                    Ma.CreateMakeFile(True, FfsCommand[key])
> > -                else:
> > -                    Ma.CreateMakeFile(True)
> > -
> > -        # no need to create makefile for the platform more than once
> > -        if self.IsMakeFileCreated:
> > -            return
> > -
> > -        # create library/module build dirs for platform
> > -        Makefile = GenMake.PlatformMakefile(self)
> > -        self.LibraryBuildDirectoryList = Makefile.GetLibraryBuildDirectoryList()
> > -        self.ModuleBuildDirectoryList = Makefile.GetModuleBuildDirectoryList()
> > -
> > -        self.IsMakeFileCreated = True
> > -
> > -    @property
> > -    def AllPcdList(self):
> > -        return self.DynamicPcdList + self.NonDynamicPcdList
> > -    ## Deal with Shared FixedAtBuild Pcds
> > -    #
> > -    def CollectFixedAtBuildPcds(self):
> > -        for LibAuto in self.LibraryAutoGenList:
> > -            FixedAtBuildPcds = {}
> > -            ShareFixedAtBuildPcdsSameValue = {}
> > -            for Module in LibAuto.ReferenceModules:
> > -                for Pcd in set(Module.FixedAtBuildPcds + LibAuto.FixedAtBuildPcds):
> > -                    DefaultValue = Pcd.DefaultValue
> > -                    # Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib
> > -                    if Pcd in Module.LibraryPcdList:
> > -                        Index = Module.LibraryPcdList.index(Pcd)
> > -                        DefaultValue = Module.LibraryPcdList[Index].DefaultValue
> > -                    key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
> > -                    if key not in FixedAtBuildPcds:
> > -                        ShareFixedAtBuildPcdsSameValue[key] = True
> > -                        FixedAtBuildPcds[key] = DefaultValue
> > -                    else:
> > -                        if FixedAtBuildPcds[key] != DefaultValue:
> > -                            ShareFixedAtBuildPcdsSameValue[key] = False
> > -            for Pcd in LibAuto.FixedAtBuildPcds:
> > -                key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
> > -                if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) not in self.NonDynamicPcdDict:
> > -                    continue
> > -                else:
> > -                    DscPcd = self.NonDynamicPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)]
> > -                    if DscPcd.Type != TAB_PCDS_FIXED_AT_BUILD:
> > -                        continue
> > -                if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]:
> > -                    LibAuto.ConstPcd[key] = FixedAtBuildPcds[key]
> > -
> > -    def CollectVariables(self, DynamicPcdSet):
> > -        VpdRegionSize = 0
> > -        VpdRegionBase = 0
> > -        if self.Workspace.FdfFile:
> > -            FdDict = self.Workspace.FdfProfile.FdDict[GlobalData.gFdfParser.CurrentFdName]
> > -            for FdRegion in FdDict.RegionList:
> > -                for item in FdRegion.RegionDataList:
> > -                    if self.Platform.VpdToolGuid.strip() and self.Platform.VpdToolGuid in item:
> > -                        VpdRegionSize = FdRegion.Size
> > -                        VpdRegionBase = FdRegion.Offset
> > -                        break
> > -
> > -        VariableInfo = VariableMgr(self.DscBuildDataObj._GetDefaultStores(), self.DscBuildDataObj.SkuIds)
> > -        VariableInfo.SetVpdRegionMaxSize(VpdRegionSize)
> > -        VariableInfo.SetVpdRegionOffset(VpdRegionBase)
> > -        Index = 0
> > -        for Pcd in DynamicPcdSet:
> > -            pcdname = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
> > -            for SkuName in Pcd.SkuInfoList:
> > -                Sku = Pcd.SkuInfoList[SkuName]
> > -                SkuId = Sku.SkuId
> > -                if SkuId is None or SkuId == '':
> > -                    continue
> > -                if len(Sku.VariableName) > 0:
> > -                    if Sku.VariableAttribute and 'NV' not in Sku.VariableAttribute:
> > -                        continue
> > -                    VariableGuidStructure = Sku.VariableGuidValue
> > -                    VariableGuid = GuidStructureStringToGuidString(VariableGuidStructure)
> > -                    for StorageName in Sku.DefaultStoreDict:
> > -                        VariableInfo.append_variable(var_info(Index, pcdname, StorageName, SkuName, StringToArray(Sku.VariableName), VariableGuid, Sku.VariableOffset, Sku.VariableAttribute, Sku.HiiDefaultValue, Sku.DefaultStoreDict[StorageName] if Pcd.DatumType in TAB_PCD_NUMERIC_TYPES else StringToArray(Sku.DefaultStoreDict[StorageName]), Pcd.DatumType, Pcd.CustomAttribute['DscPosition'], Pcd.CustomAttribute.get('IsStru',False)))
> > -            Index += 1
> > -        return VariableInfo
> > -
> > -    def UpdateNVStoreMaxSize(self, OrgVpdFile):
> > -        if self.VariableInfo:
> > -            VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)
> > -            PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]
> > -
> > -            if PcdNvStoreDfBuffer:
> > -                if os.path.exists(VpdMapFilePath):
> > -                    OrgVpdFile.Read(VpdMapFilePath)
> > -                    PcdItems = OrgVpdFile.GetOffset(PcdNvStoreDfBuffer[0])
> > -                    NvStoreOffset = list(PcdItems.values())[0].strip() if PcdItems else '0'
> > -                else:
> > -                    EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)
> > -
> > -                NvStoreOffset = int(NvStoreOffset, 16) if NvStoreOffset.upper().startswith("0X") else int(NvStoreOffset)
> > -                default_skuobj = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT)
> > -                maxsize = self.VariableInfo.VpdRegionSize  - NvStoreOffset if self.VariableInfo.VpdRegionSize else len(default_skuobj.DefaultValue.split(","))
> > -                var_data = self.VariableInfo.PatchNVStoreDefaultMaxSize(maxsize)
> > -
> > -                if var_data and default_skuobj:
> > -                    default_skuobj.DefaultValue = var_data
> > -                    PcdNvStoreDfBuffer[0].DefaultValue = var_data
> > -                    PcdNvStoreDfBuffer[0].SkuInfoList.clear()
> > -                    PcdNvStoreDfBuffer[0].SkuInfoList[TAB_DEFAULT] = default_skuobj
> > -                    PcdNvStoreDfBuffer[0].MaxDatumSize = str(len(default_skuobj.DefaultValue.split(",")))
> > -
> > -        return OrgVpdFile
> > -
> > -    ## Collect dynamic PCDs
> > -    #
> > -    #  Gather dynamic PCDs list from each module and their settings from platform
> > -    #  This interface should be invoked explicitly when platform action is created.
> > -    #
> > -    def CollectPlatformDynamicPcds(self):
> > -        for key in self.Platform.Pcds:
> > -            for SinglePcd in GlobalData.MixedPcd:
> > -                if (self.Platform.Pcds[key].TokenCName, self.Platform.Pcds[key].TokenSpaceGuidCName) == SinglePcd:
> > -                    for item in GlobalData.MixedPcd[SinglePcd]:
> > -                        Pcd_Type = item[0].split('_')[-1]
> > -                        if (Pcd_Type == self.Platform.Pcds[key].Type) or (Pcd_Type == TAB_PCDS_DYNAMIC_EX and self.Platform.Pcds[key].Type in PCD_DYNAMIC_EX_TYPE_SET) or \
> > -                           (Pcd_Type == TAB_PCDS_DYNAMIC and self.Platform.Pcds[key].Type in PCD_DYNAMIC_TYPE_SET):
> > -                            Value = self.Platform.Pcds[key]
> > -                            Value.TokenCName = self.Platform.Pcds[key].TokenCName + '_' + Pcd_Type
> > -                            if len(key) == 2:
> > -                                newkey = (Value.TokenCName, key[1])
> > -                            elif len(key) == 3:
> > -                                newkey = (Value.TokenCName, key[1], key[2])
> > -                            del self.Platform.Pcds[key]
> > -                            self.Platform.Pcds[newkey] = Value
> > -                            break
> > -                    break
> > -
> > -        # for gathering error information
> > -        NoDatumTypePcdList = set()
> > -        FdfModuleList = []
> > -        for InfName in self._AsBuildInfList:
> > -            InfName = mws.join(self.WorkspaceDir, InfName)
> > -            FdfModuleList.append(os.path.normpath(InfName))
> > -        for M in self._MaList:
> > -#            F is the Module for which M is the module autogen
> > -            for PcdFromModule in M.ModulePcdList + M.LibraryPcdList:
> > -                # make sure that the "VOID*" kind of datum has MaxDatumSize set
> > -                if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:
> > -                    NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, M.MetaFile))
> > -
> > -                # Check the PCD from Binary INF or Source INF
> > -                if M.IsBinaryModule == True:
> > -                    PcdFromModule.IsFromBinaryInf = True
> > -
> > -                # Check the PCD from DSC or not
> > -                PcdFromModule.IsFromDsc = (PcdFromModule.TokenCName, PcdFromModule.TokenSpaceGuidCName) in self.Platform.Pcds
> > -
> > -                if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET or PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
> > -                    if M.MetaFile.Path not in FdfModuleList:
> > -                        # If one of the Source built modules listed in the DSC is not listed
> > -                        # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
> > -                        # access method (it is only listed in the DEC file that declares the
> > -                        # PCD as PcdsDynamic), then build tool will report warning message
> > -                        # notify the PI that they are attempting to build a module that must
> > -                        # be included in a flash image in order to be functional. These Dynamic
> > -                        # PCD will not be added into the Database unless it is used by other
> > -                        # modules that are included in the FDF file.
> > -                        if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET and \
> > -                            PcdFromModule.IsFromBinaryInf == False:
> > -                            # Print warning message to let the developer make a determine.
> > -                            continue
> > -                        # If one of the Source built modules listed in the DSC is not listed in
> > -                        # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
> > -                        # access method (it is only listed in the DEC file that declares the
> > -                        # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
> > -                        # PCD to the Platform's PCD Database.
> > -                        if PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
> > -                            continue
> > -                    #
> > -                    # If a dynamic PCD used by a PEM module/PEI module & DXE module,
> > -                    # it should be stored in Pcd PEI database, If a dynamic only
> > -                    # used by DXE module, it should be stored in DXE PCD database.
> > -                    # The default Phase is DXE
> > -                    #
> > -                    if M.ModuleType in SUP_MODULE_SET_PEI:
> > -                        PcdFromModule.Phase = "PEI"
> > -                    if PcdFromModule not in self._DynaPcdList_:
> > -                        self._DynaPcdList_.append(PcdFromModule)
> > -                    elif PcdFromModule.Phase == 'PEI':
> > -                        # overwrite any the same PCD existing, if Phase is PEI
> > -                        Index = self._DynaPcdList_.index(PcdFromModule)
> > -                        self._DynaPcdList_[Index] = PcdFromModule
> > -                elif PcdFromModule not in self._NonDynaPcdList_:
> > -                    self._NonDynaPcdList_.append(PcdFromModule)
> > -                elif PcdFromModule in self._NonDynaPcdList_ and PcdFromModule.IsFromBinaryInf == True:
> > -                    Index = self._NonDynaPcdList_.index(PcdFromModule)
> > -                    if self._NonDynaPcdList_[Index].IsFromBinaryInf == False:
> > -                        #The PCD from Binary INF will override the same one from source INF
> > -                        self._NonDynaPcdList_.remove (self._NonDynaPcdList_[Index])
> > -                        PcdFromModule.Pending = False
> > -                        self._NonDynaPcdList_.append (PcdFromModule)
> > -        DscModuleSet = {os.path.normpath(ModuleInf.Path) for ModuleInf in self.Platform.Modules}
> > -        # add the PCD from modules that listed in FDF but not in DSC to Database
> > -        for InfName in FdfModuleList:
> > -            if InfName not in DscModuleSet:
> > -                InfClass = PathClass(InfName)
> > -                M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]
> > -                # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
> > -                # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
> > -                # For binary module, if in current arch, we need to list the PCDs into database.
> > -                if not M.IsBinaryModule:
> > -                    continue
> > -                # Override the module PCD setting by platform setting
> > -                ModulePcdList = self.ApplyPcdSetting(M, M.Pcds)
> > -                for PcdFromModule in ModulePcdList:
> > -                    PcdFromModule.IsFromBinaryInf = True
> > -                    PcdFromModule.IsFromDsc = False
> > -                    # Only allow the DynamicEx and Patchable PCD in AsBuild INF
> > -                    if PcdFromModule.Type not in PCD_DYNAMIC_EX_TYPE_SET and PcdFromModule.Type not in TAB_PCDS_PATCHABLE_IN_MODULE:
> > -                        EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
> > -                                        File=self.MetaFile,
> > -                                        ExtraData="\n\tExisted %s PCD %s in:\n\t\t%s\n"
> > -                                        % (PcdFromModule.Type, PcdFromModule.TokenCName, InfName))
> > -                    # make sure that the "VOID*" kind of datum has MaxDatumSize set
> > -                    if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:
> > -                        NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, InfName))
> > -                    if M.ModuleType in SUP_MODULE_SET_PEI:
> > -                        PcdFromModule.Phase = "PEI"
> > -                    if PcdFromModule not in self._DynaPcdList_ and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
> > -                        self._DynaPcdList_.append(PcdFromModule)
> > -                    elif PcdFromModule not in self._NonDynaPcdList_ and PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE:
> > -                        self._NonDynaPcdList_.append(PcdFromModule)
> > -                    if PcdFromModule in self._DynaPcdList_ and PcdFromModule.Phase == 'PEI' and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
> > -                        # Overwrite the phase of any the same PCD existing, if Phase is PEI.
> > -                        # It is to solve the case that a dynamic PCD used by a PEM module/PEI
> > -                        # module & DXE module at a same time.
> > -                        # Overwrite the type of the PCDs in source INF by the type of AsBuild
> > -                        # INF file as DynamicEx.
> > -                        Index = self._DynaPcdList_.index(PcdFromModule)
> > -                        self._DynaPcdList_[Index].Phase = PcdFromModule.Phase
> > -                        self._DynaPcdList_[Index].Type = PcdFromModule.Type
> > -        for PcdFromModule in self._NonDynaPcdList_:
> > -            # If a PCD is not listed in the DSC file, but binary INF files used by
> > -            # this platform all (that use this PCD) list the PCD in a [PatchPcds]
> > -            # section, AND all source INF files used by this platform the build
> > -            # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
> > -            # section, then the tools must NOT add the PCD to the Platform's PCD
> > -            # Database; the build must assign the access method for this PCD as
> > -            # PcdsPatchableInModule.
> > -            if PcdFromModule not in self._DynaPcdList_:
> > -                continue
> > -            Index = self._DynaPcdList_.index(PcdFromModule)
> > -            if PcdFromModule.IsFromDsc == False and \
> > -                PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE and \
> > -                PcdFromModule.IsFromBinaryInf == True and \
> > -                self._DynaPcdList_[Index].IsFromBinaryInf == False:
> > -                Index = self._DynaPcdList_.index(PcdFromModule)
> > -                self._DynaPcdList_.remove (self._DynaPcdList_[Index])
> > -
> > -        # print out error information and break the build, if error found
> > -        if len(NoDatumTypePcdList) > 0:
> > -            NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)
> > -            EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
> > -                            File=self.MetaFile,
> > -                            ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
> > -                                      % NoDatumTypePcdListString)
> > -        self._NonDynamicPcdList = self._NonDynaPcdList_
> > -        self._DynamicPcdList = self._DynaPcdList_
> > -        #
> > -        # Sort dynamic PCD list to:
> > -        # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
> > -        #    try to be put header of dynamicd List
> > -        # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
> > -        #
> > -        # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
> > -        #
> > -        UnicodePcdArray = set()
> > -        HiiPcdArray     = set()
> > -        OtherPcdArray   = set()
> > -        VpdPcdDict      = {}
> > -        VpdFile               = VpdInfoFile.VpdInfoFile()
> > -        NeedProcessVpdMapFile = False
> > -
> > -        for pcd in self.Platform.Pcds:
> > -            if pcd not in self._PlatformPcds:
> > -                self._PlatformPcds[pcd] = self.Platform.Pcds[pcd]
> > -
> > -        for item in self._PlatformPcds:
> > -            if self._PlatformPcds[item].DatumType and self._PlatformPcds[item].DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
> > -                self._PlatformPcds[item].DatumType = TAB_VOID
> > -
> > -        if (self.Workspace.ArchList[-1] == self.Arch):
> > -            for Pcd in self._DynamicPcdList:
> > -                # just pick the a value to determine whether is unicode string type
> > -                Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)
> > -                Sku.VpdOffset = Sku.VpdOffset.strip()
> > -
> > -                if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
> > -                    Pcd.DatumType = TAB_VOID
> > -
> > -                    # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
> > -                    # if found HII type PCD then insert to right of UnicodeIndex
> > -                if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
> > -                    VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd
> > -
> > -            #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
> > -            PcdNvStoreDfBuffer = VpdPcdDict.get(("PcdNvStoreDefaultValueBuffer", "gEfiMdeModulePkgTokenSpaceGuid"))
> > -            if PcdNvStoreDfBuffer:
> > -                self.VariableInfo = self.CollectVariables(self._DynamicPcdList)
> > -                vardump = self.VariableInfo.dump()
> > -                if vardump:
> > -                    #
> > -                    #According to PCD_DATABASE_INIT in edk2\MdeModulePkg\Include\Guid\PcdDataBaseSignatureGuid.h,
> > -                    #the max size for string PCD should not exceed USHRT_MAX 65535(0xffff).
> > -                    #typedef UINT16 SIZE_INFO;
> > -                    #//SIZE_INFO  SizeTable[];
> > -                    if len(vardump.split(",")) > 0xffff:
> > -                        EdkLogger.error("build", RESOURCE_OVERFLOW, 'The current length of PCD %s value is %d, it exceeds to the max size of String PCD.' %(".".join([PcdNvStoreDfBuffer.TokenSpaceGuidCName,PcdNvStoreDfBuffer.TokenCName]) ,len(vardump.split(","))))
> > -                    PcdNvStoreDfBuffer.DefaultValue = vardump
> > -                    for skuname in PcdNvStoreDfBuffer.SkuInfoList:
> > -                        PcdNvStoreDfBuffer.SkuInfoList[skuname].DefaultValue = vardump
> > -                        PcdNvStoreDfBuffer.MaxDatumSize = str(len(vardump.split(",")))
> > -            else:
> > -                #If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd
> > -                if [Pcd for Pcd in self._DynamicPcdList if Pcd.UserDefinedDefaultStoresFlag]:
> > -                    EdkLogger.warn("build", "PcdNvStoreDefaultValueBuffer should be defined as PcdsDynamicExVpd in dsc file since the DefaultStores is enabled for this platform.\n%s" %self.Platform.MetaFile.Path)
> > -            PlatformPcds = sorted(self._PlatformPcds.keys())
> > -            #
> > -            # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
> > -            #
> > -            VpdSkuMap = {}
> > -            for PcdKey in PlatformPcds:
> > -                Pcd = self._PlatformPcds[PcdKey]
> > -                if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD] and \
> > -                   PcdKey in VpdPcdDict:
> > -                    Pcd = VpdPcdDict[PcdKey]
> > -                    SkuValueMap = {}
> > -                    DefaultSku = Pcd.SkuInfoList.get(TAB_DEFAULT)
> > -                    if DefaultSku:
> > -                        PcdValue = DefaultSku.DefaultValue
> > -                        if PcdValue not in SkuValueMap:
> > -                            SkuValueMap[PcdValue] = []
> > -                            VpdFile.Add(Pcd, TAB_DEFAULT, DefaultSku.VpdOffset)
> > -                        SkuValueMap[PcdValue].append(DefaultSku)
> > -
> > -                    for (SkuName, Sku) in Pcd.SkuInfoList.items():
> > -                        Sku.VpdOffset = Sku.VpdOffset.strip()
> > -                        PcdValue = Sku.DefaultValue
> > -                        if PcdValue == "":
> > -                            PcdValue  = Pcd.DefaultValue
> > -                        if Sku.VpdOffset != TAB_STAR:
> > -                            if PcdValue.startswith("{"):
> > -                                Alignment = 8
> > -                            elif PcdValue.startswith("L"):
> > -                                Alignment = 2
> > -                            else:
> > -                                Alignment = 1
> > -                            try:
> > -                                VpdOffset = int(Sku.VpdOffset)
> > -                            except:
> > -                                try:
> > -                                    VpdOffset = int(Sku.VpdOffset, 16)
> > -                                except:
> > -                                    EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
> > -                            if VpdOffset % Alignment != 0:
> > -                                if PcdValue.startswith("{"):
> > -                                    EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName), File=self.MetaFile)
> > -                                else:
> > -                                    EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Alignment))
> > -                        if PcdValue not in SkuValueMap:
> > -                            SkuValueMap[PcdValue] = []
> > -                            VpdFile.Add(Pcd, SkuName, Sku.VpdOffset)
> > -                        SkuValueMap[PcdValue].append(Sku)
> > -                        # if the offset of a VPD is *, then it need to be fixed up by third party tool.
> > -                        if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:
> > -                            NeedProcessVpdMapFile = True
> > -                            if self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == '':
> > -                                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.")
> > -
> > -                    VpdSkuMap[PcdKey] = SkuValueMap
> > -            #
> > -            # Fix the PCDs define in VPD PCD section that never referenced by module.
> > -            # An example is PCD for signature usage.
> > -            #
> > -            for DscPcd in PlatformPcds:
> > -                DscPcdEntry = self._PlatformPcds[DscPcd]
> > -                if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
> > -                    if not (self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == ''):
> > -                        FoundFlag = False
> > -                        for VpdPcd in VpdFile._VpdArray:
> > -                            # This PCD has been referenced by module
> > -                            if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
> > -                               (VpdPcd.TokenCName == DscPcdEntry.TokenCName):
> > -                                    FoundFlag = True
> > -
> > -                        # Not found, it should be signature
> > -                        if not FoundFlag :
> > -                            # just pick the a value to determine whether is unicode string type
> > -                            SkuValueMap = {}
> > -                            SkuObjList = list(DscPcdEntry.SkuInfoList.items())
> > -                            DefaultSku = DscPcdEntry.SkuInfoList.get(TAB_DEFAULT)
> > -                            if DefaultSku:
> > -                                defaultindex = SkuObjList.index((TAB_DEFAULT, DefaultSku))
> > -                                SkuObjList[0], SkuObjList[defaultindex] = SkuObjList[defaultindex], SkuObjList[0]
> > -                            for (SkuName, Sku) in SkuObjList:
> > -                                Sku.VpdOffset = Sku.VpdOffset.strip()
> > -
> > -                                # Need to iterate DEC pcd information to get the value & datumtype
> > -                                for eachDec in self.PackageList:
> > -                                    for DecPcd in eachDec.Pcds:
> > -                                        DecPcdEntry = eachDec.Pcds[DecPcd]
> > -                                        if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
> > -                                           (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):
> > -                                            # Print warning message to let the developer make a determine.
> > -                                            EdkLogger.warn("build", "Unreferenced vpd pcd used!",
> > -                                                            File=self.MetaFile, \
> > -                                                            ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \
> > -                                                            %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path))
> > -
> > -                                            DscPcdEntry.DatumType    = DecPcdEntry.DatumType
> > -                                            DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue
> > -                                            DscPcdEntry.TokenValue = DecPcdEntry.TokenValue
> > -                                            DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName]
> > -                                            # Only fix the value while no value provided in DSC file.
> > -                                            if not Sku.DefaultValue:
> > -                                                DscPcdEntry.SkuInfoList[list(DscPcdEntry.SkuInfoList.keys())[0]].DefaultValue = DecPcdEntry.DefaultValue
> > -
> > -                                if DscPcdEntry not in self._DynamicPcdList:
> > -                                    self._DynamicPcdList.append(DscPcdEntry)
> > -                                Sku.VpdOffset = Sku.VpdOffset.strip()
> > -                                PcdValue = Sku.DefaultValue
> > -                                if PcdValue == "":
> > -                                    PcdValue  = DscPcdEntry.DefaultValue
> > -                                if Sku.VpdOffset != TAB_STAR:
> > -                                    if PcdValue.startswith("{"):
> > -                                        Alignment = 8
> > -                                    elif PcdValue.startswith("L"):
> > -                                        Alignment = 2
> > -                                    else:
> > -                                        Alignment = 1
> > -                                    try:
> > -                                        VpdOffset = int(Sku.VpdOffset)
> > -                                    except:
> > -                                        try:
> > -                                            VpdOffset = int(Sku.VpdOffset, 16)
> > -                                        except:
> > -                                            EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName))
> > -                                    if VpdOffset % Alignment != 0:
> > -                                        if PcdValue.startswith("{"):
> > -                                            EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName), File=self.MetaFile)
> > -                                        else:
> > -                                            EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, Alignment))
> > -                                if PcdValue not in SkuValueMap:
> > -                                    SkuValueMap[PcdValue] = []
> > -                                    VpdFile.Add(DscPcdEntry, SkuName, Sku.VpdOffset)
> > -                                SkuValueMap[PcdValue].append(Sku)
> > -                                if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:
> > -                                    NeedProcessVpdMapFile = True
> > -                            if DscPcdEntry.DatumType == TAB_VOID and PcdValue.startswith("L"):
> > -                                UnicodePcdArray.add(DscPcdEntry)
> > -                            elif len(Sku.VariableName) > 0:
> > -                                HiiPcdArray.add(DscPcdEntry)
> > -                            else:
> > -                                OtherPcdArray.add(DscPcdEntry)
> > -
> > -                                # if the offset of a VPD is *, then it need to be fixed up by third party tool.
> > -                            VpdSkuMap[DscPcd] = SkuValueMap
> > -            if (self.Platform.FlashDefinition is None or self.Platform.FlashDefinition == '') and \
> > -               VpdFile.GetCount() != 0:
> > -                EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
> > -                                "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))
> > -
> > -            if VpdFile.GetCount() != 0:
> > -
> > -                self.FixVpdOffset(VpdFile)
> > -
> > -                self.FixVpdOffset(self.UpdateNVStoreMaxSize(VpdFile))
> > -                PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]
> > -                if PcdNvStoreDfBuffer:
> > -                    PcdName,PcdGuid = PcdNvStoreDfBuffer[0].TokenCName, PcdNvStoreDfBuffer[0].TokenSpaceGuidCName
> > -                    if (PcdName,PcdGuid) in VpdSkuMap:
> > -                        DefaultSku = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT)
> > -                        VpdSkuMap[(PcdName,PcdGuid)] = {DefaultSku.DefaultValue:[SkuObj for SkuObj in PcdNvStoreDfBuffer[0].SkuInfoList.values() ]}
> > -
> > -                # Process VPD map file generated by third party BPDG tool
> > -                if NeedProcessVpdMapFile:
> > -                    VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)
> > -                    if os.path.exists(VpdMapFilePath):
> > -                        VpdFile.Read(VpdMapFilePath)
> > -
> > -                        # Fixup TAB_STAR offset
> > -                        for pcd in VpdSkuMap:
> > -                            vpdinfo = VpdFile.GetVpdInfo(pcd)
> > -                            if vpdinfo is None:
> > -                            # just pick the a value to determine whether is unicode string type
> > -                                continue
> > -                            for pcdvalue in VpdSkuMap[pcd]:
> > -                                for sku in VpdSkuMap[pcd][pcdvalue]:
> > -                                    for item in vpdinfo:
> > -                                        if item[2] == pcdvalue:
> > -                                            sku.VpdOffset = item[1]
> > -                    else:
> > -                        EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)
> > -
> > -            # Delete the DynamicPcdList At the last time enter into this function
> > -            for Pcd in self._DynamicPcdList:
> > -                # just pick the a value to determine whether is unicode string type
> > -                Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)
> > -                Sku.VpdOffset = Sku.VpdOffset.strip()
> > -
> > -                if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
> > -                    Pcd.DatumType = TAB_VOID
> > -
> > -                PcdValue = Sku.DefaultValue
> > -                if Pcd.DatumType == TAB_VOID and PcdValue.startswith("L"):
> > -                    # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
> > -                    UnicodePcdArray.add(Pcd)
> > -                elif len(Sku.VariableName) > 0:
> > -                    # if found HII type PCD then insert to right of UnicodeIndex
> > -                    HiiPcdArray.add(Pcd)
> > -                else:
> > -                    OtherPcdArray.add(Pcd)
> > -            del self._DynamicPcdList[:]
> > -        self._DynamicPcdList.extend(list(UnicodePcdArray))
> > -        self._DynamicPcdList.extend(list(HiiPcdArray))
> > -        self._DynamicPcdList.extend(list(OtherPcdArray))
> > -        allskuset = [(SkuName, Sku.SkuId) for pcd in self._DynamicPcdList for (SkuName, Sku) in pcd.SkuInfoList.items()]
> > -        for pcd in self._DynamicPcdList:
> > -            if len(pcd.SkuInfoList) == 1:
> > -                for (SkuName, SkuId) in allskuset:
> > -                    if isinstance(SkuId, str) and eval(SkuId) == 0 or SkuId == 0:
> > -                        continue
> > -                    pcd.SkuInfoList[SkuName] = copy.deepcopy(pcd.SkuInfoList[TAB_DEFAULT])
> > -                    pcd.SkuInfoList[SkuName].SkuId = SkuId
> > -                    pcd.SkuInfoList[SkuName].SkuIdName = SkuName
> > -
> > -    def FixVpdOffset(self, VpdFile ):
> > -        FvPath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY)
> > -        if not os.path.exists(FvPath):
> > -            try:
> > -                os.makedirs(FvPath)
> > -            except:
> > -                EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)
> > -
> > -        VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)
> > -
> > -        if VpdFile.Write(VpdFilePath):
> > -            # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
> > -            BPDGToolName = None
> > -            for ToolDef in self.ToolDefinition.values():
> > -                if TAB_GUID in ToolDef and ToolDef[TAB_GUID] == self.Platform.VpdToolGuid:
> > -                    if "PATH" not in ToolDef:
> > -                        EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)
> > -                    BPDGToolName = ToolDef["PATH"]
> > -                    break
> > -            # Call third party GUID BPDG tool.
> > -            if BPDGToolName is not None:
> > -                VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)
> > -            else:
> > -                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.")
> > -
> > -    ## Return the platform build data object
> > -    @cached_property
> > -    def Platform(self):
> > -        return self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
> > -
> > -    ## Return platform name
> > -    @cached_property
> > -    def Name(self):
> > -        return self.Platform.PlatformName
> > -
> > -    ## Return the meta file GUID
> > -    @cached_property
> > -    def Guid(self):
> > -        return self.Platform.Guid
> > -
> > -    ## Return the platform version
> > -    @cached_property
> > -    def Version(self):
> > -        return self.Platform.Version
> > -
> > -    ## Return the FDF file name
> > -    @cached_property
> > -    def FdfFile(self):
> > -        if self.Workspace.FdfFile:
> > -            RetVal= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)
> > -        else:
> > -            RetVal = ''
> > -        return RetVal
> > -
> > -    ## Return the build output directory platform specifies
> > -    @cached_property
> > -    def OutputDir(self):
> > -        return self.Platform.OutputDirectory
> > -
> > -    ## Return the directory to store all intermediate and final files built
> > -    @cached_property
> > -    def BuildDir(self):
> > -        if os.path.isabs(self.OutputDir):
> > -            GlobalData.gBuildDirectory = RetVal = path.join(
> > -                                        path.abspath(self.OutputDir),
> > -                                        self.BuildTarget + "_" + self.ToolChain,
> > -                                        )
> > -        else:
> > -            GlobalData.gBuildDirectory = RetVal = path.join(
> > -                                        self.WorkspaceDir,
> > -                                        self.OutputDir,
> > -                                        self.BuildTarget + "_" + self.ToolChain,
> > -                                        )
> > -        return RetVal
> > -
> > -    ## Return directory of platform makefile
> > -    #
> > -    #   @retval     string  Makefile directory
> > -    #
> > -    @cached_property
> > -    def MakeFileDir(self):
> > -        return path.join(self.BuildDir, self.Arch)
> > -
> > -    ## Return build command string
> > -    #
> > -    #   @retval     string  Build command string
> > -    #
> > -    @cached_property
> > -    def BuildCommand(self):
> > -        RetVal = []
> > -        if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
> > -            RetVal += _SplitOption(self.ToolDefinition["MAKE"]["PATH"])
> > -            if "FLAGS" in self.ToolDefinition["MAKE"]:
> > -                NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
> > -                if NewOption != '':
> > -                    RetVal += _SplitOption(NewOption)
> > -            if "MAKE" in self.EdkIIBuildOption:
> > -                if "FLAGS" in self.EdkIIBuildOption["MAKE"]:
> > -                    Flags = self.EdkIIBuildOption["MAKE"]["FLAGS"]
> > -                    if Flags.startswith('='):
> > -                        RetVal = [RetVal[0]] + [Flags[1:]]
> > -                    else:
> > -                        RetVal.append(Flags)
> > -        return RetVal
> > -
> > -    ## Get tool chain definition
> > -    #
> > -    #  Get each tool definition for given tool chain from tools_def.txt and platform
> > -    #
> > -    @cached_property
> > -    def ToolDefinition(self):
> > -        ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
> > -        if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:
> > -            EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",
> > -                            ExtraData="[%s]" % self.MetaFile)
> > -        RetVal = OrderedDict()
> > -        DllPathList = set()
> > -        for Def in ToolDefinition:
> > -            Target, Tag, Arch, Tool, Attr = Def.split("_")
> > -            if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:
> > -                continue
> > -
> > -            Value = ToolDefinition[Def]
> > -            # don't record the DLL
> > -            if Attr == "DLL":
> > -                DllPathList.add(Value)
> > -                continue
> > -
> > -            if Tool not in RetVal:
> > -                RetVal[Tool] = OrderedDict()
> > -            RetVal[Tool][Attr] = Value
> > -
> > -        ToolsDef = ''
> > -        if GlobalData.gOptions.SilentMode and "MAKE" in RetVal:
> > -            if "FLAGS" not in RetVal["MAKE"]:
> > -                RetVal["MAKE"]["FLAGS"] = ""
> > -            RetVal["MAKE"]["FLAGS"] += " -s"
> > -        MakeFlags = ''
> > -        for Tool in RetVal:
> > -            for Attr in RetVal[Tool]:
> > -                Value = RetVal[Tool][Attr]
> > -                if Tool in self._BuildOptionWithToolDef(RetVal) and Attr in self._BuildOptionWithToolDef(RetVal)[Tool]:
> > -                    # check if override is indicated
> > -                    if self._BuildOptionWithToolDef(RetVal)[Tool][Attr].startswith('='):
> > -                        Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr][1:]
> > -                    else:
> > -                        if Attr != 'PATH':
> > -                            Value += " " + self._BuildOptionWithToolDef(RetVal)[Tool][Attr]
> > -                        else:
> > -                            Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr]
> > -
> > -                if Attr == "PATH":
> > -                    # Don't put MAKE definition in the file
> > -                    if Tool != "MAKE":
> > -                        ToolsDef += "%s = %s\n" % (Tool, Value)
> > -                elif Attr != "DLL":
> > -                    # Don't put MAKE definition in the file
> > -                    if Tool == "MAKE":
> > -                        if Attr == "FLAGS":
> > -                            MakeFlags = Value
> > -                    else:
> > -                        ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
> > -            ToolsDef += "\n"
> > -        tool_def_file = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
> > -        SaveFileOnChange(tool_def_file, ToolsDef, False)
> > -        for DllPath in DllPathList:
> > -            os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]
> > -        os.environ["MAKE_FLAGS"] = MakeFlags
> > -
> > -        return RetVal
> > -
> > -    ## Return the paths of tools
> > -    @cached_property
> > -    def ToolDefinitionFile(self):
> > -        tool_def_file = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
> > -        if not os.path.exists(tool_def_file):
> > -            self.ToolDefinition
> > -        return tool_def_file
> > -
> > -    ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
> > -    @cached_property
> > -    def ToolChainFamily(self):
> > -        ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
> > -        if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
> > -           or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
> > -           or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:
> > -            EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
> > -                               % self.ToolChain)
> > -            RetVal = TAB_COMPILER_MSFT
> > -        else:
> > -            RetVal = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]
> > -        return RetVal
> > -
> > -    @cached_property
> > -    def BuildRuleFamily(self):
> > -        ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
> > -        if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
> > -           or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \
> > -           or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:
> > -            EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
> > -                               % self.ToolChain)
> > -            return TAB_COMPILER_MSFT
> > -
> > -        return ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]
> > -
> > -    ## Return the build options specific for all modules in this platform
> > -    @cached_property
> > -    def BuildOption(self):
> > -        return self._ExpandBuildOption(self.Platform.BuildOptions)
> > -
> > -    def _BuildOptionWithToolDef(self, ToolDef):
> > -        return self._ExpandBuildOption(self.Platform.BuildOptions, ToolDef=ToolDef)
> > -
> > -    ## Return the build options specific for EDK modules in this platform
> > -    @cached_property
> > -    def EdkBuildOption(self):
> > -        return self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)
> > -
> > -    ## Return the build options specific for EDKII modules in this platform
> > -    @cached_property
> > -    def EdkIIBuildOption(self):
> > -        return self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)
> > -
> > -    ## Summarize the packages used by modules in this platform
> > -    @cached_property
> > -    def PackageList(self):
> > -        RetVal = set()
> > -        for La in self.LibraryAutoGenList:
> > -            RetVal.update(La.DependentPackageList)
> > -        for Ma in self.ModuleAutoGenList:
> > -            RetVal.update(Ma.DependentPackageList)
> > -        #Collect package set information from INF of FDF
> > -        for ModuleFile in self._AsBuildModuleList:
> > -            if ModuleFile in self.Platform.Modules:
> > -                continue
> > -            ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]
> > -            RetVal.update(ModuleData.Packages)
> > -        return list(RetVal)
> > -
> > -    @cached_property
> > -    def NonDynamicPcdDict(self):
> > -        return {(Pcd.TokenCName, Pcd.TokenSpaceGuidCName):Pcd for Pcd in self.NonDynamicPcdList}
> > -
> > -    ## Get list of non-dynamic PCDs
> > -    @property
> > -    def NonDynamicPcdList(self):
> > -        if not self._NonDynamicPcdList:
> > -            self.CollectPlatformDynamicPcds()
> > -        return self._NonDynamicPcdList
> > -
> > -    ## Get list of dynamic PCDs
> > -    @property
> > -    def DynamicPcdList(self):
> > -        if not self._DynamicPcdList:
> > -            self.CollectPlatformDynamicPcds()
> > -        return self._DynamicPcdList
> > -
> > -    ## Generate Token Number for all PCD
> > -    @cached_property
> > -    def PcdTokenNumber(self):
> > -        RetVal = OrderedDict()
> > -        TokenNumber = 1
> > -        #
> > -        # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
> > -        # Such as:
> > -        #
> > -        # Dynamic PCD:
> > -        # TokenNumber 0 ~ 10
> > -        # DynamicEx PCD:
> > -        # TokeNumber 11 ~ 20
> > -        #
> > -        for Pcd in self.DynamicPcdList:
> > -            if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:
> > -                EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
> > -                RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
> > -                TokenNumber += 1
> > -
> > -        for Pcd in self.DynamicPcdList:
> > -            if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
> > -                EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
> > -                RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
> > -                TokenNumber += 1
> > -
> > -        for Pcd in self.DynamicPcdList:
> > -            if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:
> > -                EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
> > -                RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
> > -                TokenNumber += 1
> > -
> > -        for Pcd in self.DynamicPcdList:
> > -            if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
> > -                EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
> > -                RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
> > -                TokenNumber += 1
> > -
> > -        for Pcd in self.NonDynamicPcdList:
> > -            RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
> > -            TokenNumber += 1
> > -        return RetVal
> > -
> > -    @cached_property
> > -    def _MaList(self):
> > -        for ModuleFile in self.Platform.Modules:
> > -            Ma = ModuleAutoGen(
> > -                  self.Workspace,
> > -                  ModuleFile,
> > -                  self.BuildTarget,
> > -                  self.ToolChain,
> > -                  self.Arch,
> > -                  self.MetaFile
> > -                  )
> > -            self.Platform.Modules[ModuleFile].M = Ma
> > -        return [x.M for x in self.Platform.Modules.values()]
> > -
> > -    ## Summarize ModuleAutoGen objects of all modules to be built for this platform
> > -    @cached_property
> > -    def ModuleAutoGenList(self):
> > -        RetVal = []
> > -        for Ma in self._MaList:
> > -            if Ma not in RetVal:
> > -                RetVal.append(Ma)
> > -        return RetVal
> > -
> > -    ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
> > -    @cached_property
> > -    def LibraryAutoGenList(self):
> > -        RetVal = []
> > -        for Ma in self._MaList:
> > -            for La in Ma.LibraryAutoGenList:
> > -                if La not in RetVal:
> > -                    RetVal.append(La)
> > -                if Ma not in La.ReferenceModules:
> > -                    La.ReferenceModules.append(Ma)
> > -        return RetVal
> > -
> > -    ## Test if a module is supported by the platform
> > -    #
> > -    #  An error will be raised directly if the module or its arch is not supported
> > -    #  by the platform or current configuration
> > -    #
> > -    def ValidModule(self, Module):
> > -        return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \
> > -            or Module in self._AsBuildModuleList
> > -
> > -    ## Resolve the library classes in a module to library instances
> > -    #
> > -    # This method will not only resolve library classes but also sort the library
> > -    # instances according to the dependency-ship.
> > -    #
> > -    #   @param  Module      The module from which the library classes will be resolved
> > -    #
> > -    #   @retval library_list    List of library instances sorted
> > -    #
> > -    def ApplyLibraryInstance(self, Module):
> > -        # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
> > -        if str(Module) not in self.Platform.Modules:
> > -            return []
> > -
> > -        return GetModuleLibInstances(Module,
> > -                                     self.Platform,
> > -                                     self.BuildDatabase,
> > -                                     self.Arch,
> > -                                     self.BuildTarget,
> > -                                     self.ToolChain,
> > -                                     self.MetaFile,
> > -                                     EdkLogger)
> > -
> > -    ## Override PCD setting (type, value, ...)
> > -    #
> > -    #   @param  ToPcd       The PCD to be overridden
> > -    #   @param  FromPcd     The PCD overriding from
> > -    #
> > -    def _OverridePcd(self, ToPcd, FromPcd, Module="", Msg="", Library=""):
> > -        #
> > -        # in case there's PCDs coming from FDF file, which have no type given.
> > -        # at this point, ToPcd.Type has the type found from dependent
> > -        # package
> > -        #
> > -        TokenCName = ToPcd.TokenCName
> > -        for PcdItem in GlobalData.MixedPcd:
> > -            if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
> > -                TokenCName = PcdItem[0]
> > -                break
> > -        if FromPcd is not None:
> > -            if ToPcd.Pending and FromPcd.Type:
> > -                ToPcd.Type = FromPcd.Type
> > -            elif ToPcd.Type and FromPcd.Type\
> > -                and ToPcd.Type != FromPcd.Type and ToPcd.Type in FromPcd.Type:
> > -                if ToPcd.Type.strip() == TAB_PCDS_DYNAMIC_EX:
> > -                    ToPcd.Type = FromPcd.Type
> > -            elif ToPcd.Type and FromPcd.Type \
> > -                and ToPcd.Type != FromPcd.Type:
> > -                if Library:
> > -                    Module = str(Module) + " 's library file (" + str(Library) + ")"
> > -                EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",
> > -                                ExtraData="%s.%s is used as [%s] in module %s, but as [%s] in %s."\
> > -                                          % (ToPcd.TokenSpaceGuidCName, TokenCName,
> > -                                             ToPcd.Type, Module, FromPcd.Type, Msg),
> > -                                          File=self.MetaFile)
> > -
> > -            if FromPcd.MaxDatumSize:
> > -                ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
> > -                ToPcd.MaxSizeUserSet = FromPcd.MaxDatumSize
> > -            if FromPcd.DefaultValue:
> > -                ToPcd.DefaultValue = FromPcd.DefaultValue
> > -            if FromPcd.TokenValue:
> > -                ToPcd.TokenValue = FromPcd.TokenValue
> > -            if FromPcd.DatumType:
> > -                ToPcd.DatumType = FromPcd.DatumType
> > -            if FromPcd.SkuInfoList:
> > -                ToPcd.SkuInfoList = FromPcd.SkuInfoList
> > -            if FromPcd.UserDefinedDefaultStoresFlag:
> > -                ToPcd.UserDefinedDefaultStoresFlag = FromPcd.UserDefinedDefaultStoresFlag
> > -            # Add Flexible PCD format parse
> > -            if ToPcd.DefaultValue:
> > -                try:
> > -                    ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self.Workspace._GuidDict)(True)
> > -                except BadExpression as Value:
> > -                    EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),
> > -                                        File=self.MetaFile)
> > -
> > -            # check the validation of datum
> > -            IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)
> > -            if not IsValid:
> > -                EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
> > -                                ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, TokenCName))
> > -            ToPcd.validateranges = FromPcd.validateranges
> > -            ToPcd.validlists = FromPcd.validlists
> > -            ToPcd.expressions = FromPcd.expressions
> > -            ToPcd.CustomAttribute = FromPcd.CustomAttribute
> > -
> > -        if FromPcd is not None and ToPcd.DatumType == TAB_VOID and not ToPcd.MaxDatumSize:
> > -            EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \
> > -                            % (ToPcd.TokenSpaceGuidCName, TokenCName))
> > -            Value = ToPcd.DefaultValue
> > -            if not Value:
> > -                ToPcd.MaxDatumSize = '1'
> > -            elif Value[0] == 'L':
> > -                ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)
> > -            elif Value[0] == '{':
> > -                ToPcd.MaxDatumSize = str(len(Value.split(',')))
> > -            else:
> > -                ToPcd.MaxDatumSize = str(len(Value) - 1)
> > -
> > -        # apply default SKU for dynamic PCDS if specified one is not available
> > -        if (ToPcd.Type in PCD_DYNAMIC_TYPE_SET or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_SET) \
> > -            and not ToPcd.SkuInfoList:
> > -            if self.Platform.SkuName in self.Platform.SkuIds:
> > -                SkuName = self.Platform.SkuName
> > -            else:
> > -                SkuName = TAB_DEFAULT
> > -            ToPcd.SkuInfoList = {
> > -                SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName][0], '', '', '', '', '', ToPcd.DefaultValue)
> > -            }
> > -
> > -    ## Apply PCD setting defined platform to a module
> > -    #
> > -    #   @param  Module  The module from which the PCD setting will be overridden
> > -    #
> > -    #   @retval PCD_list    The list PCDs with settings from platform
> > -    #
> > -    def ApplyPcdSetting(self, Module, Pcds, Library=""):
> > -        # for each PCD in module
> > -        for Name, Guid in Pcds:
> > -            PcdInModule = Pcds[Name, Guid]
> > -            # find out the PCD setting in platform
> > -            if (Name, Guid) in self.Platform.Pcds:
> > -                PcdInPlatform = self.Platform.Pcds[Name, Guid]
> > -            else:
> > -                PcdInPlatform = None
> > -            # then override the settings if any
> > -            self._OverridePcd(PcdInModule, PcdInPlatform, Module, Msg="DSC PCD sections", Library=Library)
> > -            # resolve the VariableGuid value
> > -            for SkuId in PcdInModule.SkuInfoList:
> > -                Sku = PcdInModule.SkuInfoList[SkuId]
> > -                if Sku.VariableGuid == '': continue
> > -                Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList, self.MetaFile.Path)
> > -                if Sku.VariableGuidValue is None:
> > -                    PackageList = "\n\t".join(str(P) for P in self.PackageList)
> > -                    EdkLogger.error(
> > -                                'build',
> > -                                RESOURCE_NOT_AVAILABLE,
> > -                                "Value of GUID [%s] is not found in" % Sku.VariableGuid,
> > -                                ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \
> > -                                                        % (Guid, Name, str(Module)),
> > -                                File=self.MetaFile
> > -                                )
> > -
> > -        # override PCD settings with module specific setting
> > -        if Module in self.Platform.Modules:
> > -            PlatformModule = self.Platform.Modules[str(Module)]
> > -            for Key  in PlatformModule.Pcds:
> > -                if GlobalData.BuildOptionPcd:
> > -                    for pcd in GlobalData.BuildOptionPcd:
> > -                        (TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue, _) = pcd
> > -                        if (TokenCName, TokenSpaceGuidCName) == Key and FieldName =="":
> > -                            PlatformModule.Pcds[Key].DefaultValue = pcdvalue
> > -                            PlatformModule.Pcds[Key].PcdValueFromComm = pcdvalue
> > -                            break
> > -                Flag = False
> > -                if Key in Pcds:
> > -                    ToPcd = Pcds[Key]
> > -                    Flag = True
> > -                elif Key in GlobalData.MixedPcd:
> > -                    for PcdItem in GlobalData.MixedPcd[Key]:
> > -                        if PcdItem in Pcds:
> > -                            ToPcd = Pcds[PcdItem]
> > -                            Flag = True
> > -                            break
> > -                if Flag:
> > -                    self._OverridePcd(ToPcd, PlatformModule.Pcds[Key], Module, Msg="DSC Components Module scoped PCD section", Library=Library)
> > -        # use PCD value to calculate the MaxDatumSize when it is not specified
> > -        for Name, Guid in Pcds:
> > -            Pcd = Pcds[Name, Guid]
> > -            if Pcd.DatumType == TAB_VOID and not Pcd.MaxDatumSize:
> > -                Pcd.MaxSizeUserSet = None
> > -                Value = Pcd.DefaultValue
> > -                if not Value:
> > -                    Pcd.MaxDatumSize = '1'
> > -                elif Value[0] == 'L':
> > -                    Pcd.MaxDatumSize = str((len(Value) - 2) * 2)
> > -                elif Value[0] == '{':
> > -                    Pcd.MaxDatumSize = str(len(Value.split(',')))
> > -                else:
> > -                    Pcd.MaxDatumSize = str(len(Value) - 1)
> > -        return list(Pcds.values())
> > -
> > -
> > -
> > -    ## Calculate the priority value of the build option
> > -    #
> > -    # @param    Key    Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
> > -    #
> > -    # @retval   Value  Priority value based on the priority list.
> > -    #
> > -    def CalculatePriorityValue(self, Key):
> > -        Target, ToolChain, Arch, CommandType, Attr = Key.split('_')
> > -        PriorityValue = 0x11111
> > -        if Target == TAB_STAR:
> > -            PriorityValue &= 0x01111
> > -        if ToolChain == TAB_STAR:
> > -            PriorityValue &= 0x10111
> > -        if Arch == TAB_STAR:
> > -            PriorityValue &= 0x11011
> > -        if CommandType == TAB_STAR:
> > -            PriorityValue &= 0x11101
> > -        if Attr == TAB_STAR:
> > -            PriorityValue &= 0x11110
> > -
> > -        return self.PrioList["0x%0.5x" % PriorityValue]
> > -
> > -
> > -    ## Expand * in build option key
> > -    #
> > -    #   @param  Options     Options to be expanded
> > -    #   @param  ToolDef     Use specified ToolDef instead of full version.
> > -    #                       This is needed during initialization to prevent
> > -    #                       infinite recursion betweeh BuildOptions,
> > -    #                       ToolDefinition, and this function.
> > -    #
> > -    #   @retval options     Options expanded
> > -    #
> > -    def _ExpandBuildOption(self, Options, ModuleStyle=None, ToolDef=None):
> > -        if not ToolDef:
> > -            ToolDef = self.ToolDefinition
> > -        BuildOptions = {}
> > -        FamilyMatch  = False
> > -        FamilyIsNull = True
> > -
> > -        OverrideList = {}
> > -        #
> > -        # Construct a list contain the build options which need override.
> > -        #
> > -        for Key in Options:
> > -            #
> > -            # Key[0] -- tool family
> > -            # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
> > -            #
> > -            if (Key[0] == self.BuildRuleFamily and
> > -                (ModuleStyle is None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):
> > -                Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')
> > -                if (Target == self.BuildTarget or Target == TAB_STAR) and\
> > -                    (ToolChain == self.ToolChain or ToolChain == TAB_STAR) and\
> > -                    (Arch == self.Arch or Arch == TAB_STAR) and\
> > -                    Options[Key].startswith("="):
> > -
> > -                    if OverrideList.get(Key[1]) is not None:
> > -                        OverrideList.pop(Key[1])
> > -                    OverrideList[Key[1]] = Options[Key]
> > -
> > -        #
> > -        # Use the highest priority value.
> > -        #
> > -        if (len(OverrideList) >= 2):
> > -            KeyList = list(OverrideList.keys())
> > -            for Index in range(len(KeyList)):
> > -                NowKey = KeyList[Index]
> > -                Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")
> > -                for Index1 in range(len(KeyList) - Index - 1):
> > -                    NextKey = KeyList[Index1 + Index + 1]
> > -                    #
> > -                    # Compare two Key, if one is included by another, choose the higher priority one
> > -                    #
> > -                    Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")
> > -                    if (Target1 == Target2 or Target1 == TAB_STAR or Target2 == TAB_STAR) and\
> > -                        (ToolChain1 == ToolChain2 or ToolChain1 == TAB_STAR or ToolChain2 == TAB_STAR) and\
> > -                        (Arch1 == Arch2 or Arch1 == TAB_STAR or Arch2 == TAB_STAR) and\
> > -                        (CommandType1 == CommandType2 or CommandType1 == TAB_STAR or CommandType2 == TAB_STAR) and\
> > -                        (Attr1 == Attr2 or Attr1 == TAB_STAR or Attr2 == TAB_STAR):
> > -
> > -                        if self.CalculatePriorityValue(NowKey) > self.CalculatePriorityValue(NextKey):
> > -                            if Options.get((self.BuildRuleFamily, NextKey)) is not None:
> > -                                Options.pop((self.BuildRuleFamily, NextKey))
> > -                        else:
> > -                            if Options.get((self.BuildRuleFamily, NowKey)) is not None:
> > -                                Options.pop((self.BuildRuleFamily, NowKey))
> > -
> > -        for Key in Options:
> > -            if ModuleStyle is not None and len (Key) > 2:
> > -                # Check Module style is EDK or EDKII.
> > -                # Only append build option for the matched style module.
> > -                if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
> > -                    continue
> > -                elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
> > -                    continue
> > -            Family = Key[0]
> > -            Target, Tag, Arch, Tool, Attr = Key[1].split("_")
> > -            # if tool chain family doesn't match, skip it
> > -            if Tool in ToolDef and Family != "":
> > -                FamilyIsNull = False
> > -                if ToolDef[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
> > -                    if Family != ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
> > -                        continue
> > -                elif Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
> > -                    continue
> > -                FamilyMatch = True
> > -            # expand any wildcard
> > -            if Target == TAB_STAR or Target == self.BuildTarget:
> > -                if Tag == TAB_STAR or Tag == self.ToolChain:
> > -                    if Arch == TAB_STAR or Arch == self.Arch:
> > -                        if Tool not in BuildOptions:
> > -                            BuildOptions[Tool] = {}
> > -                        if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
> > -                            BuildOptions[Tool][Attr] = Options[Key]
> > -                        else:
> > -                            # append options for the same tool except PATH
> > -                            if Attr != 'PATH':
> > -                                BuildOptions[Tool][Attr] += " " + Options[Key]
> > -                            else:
> > -                                BuildOptions[Tool][Attr] = Options[Key]
> > -        # Build Option Family has been checked, which need't to be checked again for family.
> > -        if FamilyMatch or FamilyIsNull:
> > -            return BuildOptions
> > -
> > -        for Key in Options:
> > -            if ModuleStyle is not None and len (Key) > 2:
> > -                # Check Module style is EDK or EDKII.
> > -                # Only append build option for the matched style module.
> > -                if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
> > -                    continue
> > -                elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
> > -                    continue
> > -            Family = Key[0]
> > -            Target, Tag, Arch, Tool, Attr = Key[1].split("_")
> > -            # if tool chain family doesn't match, skip it
> > -            if Tool not in ToolDef or Family == "":
> > -                continue
> > -            # option has been added before
> > -            if Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
> > -                continue
> > -
> > -            # expand any wildcard
> > -            if Target == TAB_STAR or Target == self.BuildTarget:
> > -                if Tag == TAB_STAR or Tag == self.ToolChain:
> > -                    if Arch == TAB_STAR or Arch == self.Arch:
> > -                        if Tool not in BuildOptions:
> > -                            BuildOptions[Tool] = {}
> > -                        if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
> > -                            BuildOptions[Tool][Attr] = Options[Key]
> > -                        else:
> > -                            # append options for the same tool except PATH
> > -                            if Attr != 'PATH':
> > -                                BuildOptions[Tool][Attr] += " " + Options[Key]
> > -                            else:
> > -                                BuildOptions[Tool][Attr] = Options[Key]
> > -        return BuildOptions
> > -    def GetGlobalBuildOptions(self,Module):
> > -        ModuleTypeOptions = self.Platform.GetBuildOptionsByPkg(Module, Module.ModuleType)
> > -        ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)
> > -        if Module in self.Platform.Modules:
> > -            PlatformModule = self.Platform.Modules[str(Module)]
> > -            PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
> > -        else:
> > -            PlatformModuleOptions = {}
> > -        return ModuleTypeOptions, PlatformModuleOptions
> > -    ## Append build options in platform to a module
> > -    #
> > -    #   @param  Module  The module to which the build options will be appended
> > -    #
> > -    #   @retval options     The options appended with build options in platform
> > -    #
> > -    def ApplyBuildOption(self, Module):
> > -        # Get the different options for the different style module
> > -        PlatformOptions = self.EdkIIBuildOption
> > -        ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)
> > -        ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)
> > -        ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)
> > -        if Module in self.Platform.Modules:
> > -            PlatformModule = self.Platform.Modules[str(Module)]
> > -            PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
> > -        else:
> > -            PlatformModuleOptions = {}
> > -
> > -        BuildRuleOrder = None
> > -        for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
> > -            for Tool in Options:
> > -                for Attr in Options[Tool]:
> > -                    if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
> > -                        BuildRuleOrder = Options[Tool][Attr]
> > -
> > -        AllTools = set(list(ModuleOptions.keys()) + list(PlatformOptions.keys()) +
> > -                       list(PlatformModuleOptions.keys()) + list(ModuleTypeOptions.keys()) +
> > -                       list(self.ToolDefinition.keys()))
> > -        BuildOptions = defaultdict(lambda: defaultdict(str))
> > -        for Tool in AllTools:
> > -            for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
> > -                if Tool not in Options:
> > -                    continue
> > -                for Attr in Options[Tool]:
> > -                    #
> > -                    # Do not generate it in Makefile
> > -                    #
> > -                    if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
> > -                        continue
> > -                    Value = Options[Tool][Attr]
> > -                    # check if override is indicated
> > -                    if Value.startswith('='):
> > -                        BuildOptions[Tool][Attr] = mws.handleWsMacro(Value[1:])
> > -                    else:
> > -                        if Attr != 'PATH':
> > -                            BuildOptions[Tool][Attr] += " " + mws.handleWsMacro(Value)
> > -                        else:
> > -                            BuildOptions[Tool][Attr] = mws.handleWsMacro(Value)
> > -
> > -        return BuildOptions, BuildRuleOrder
> > -
> > -#
> > -# extend lists contained in a dictionary with lists stored in another dictionary
> > -# if CopyToDict is not derived from DefaultDict(list) then this may raise exception
> > -#
> > -def ExtendCopyDictionaryLists(CopyToDict, CopyFromDict):
> > -    for Key in CopyFromDict:
> > -        CopyToDict[Key].extend(CopyFromDict[Key])
> > -
> > -# Create a directory specified by a set of path elements and return the full path
> > -def _MakeDir(PathList):
> > -    RetVal = path.join(*PathList)
> > -    CreateDirectory(RetVal)
> > -    return RetVal
> > -
> > -## ModuleAutoGen class
> > -#
> > -# This class encapsules the AutoGen behaviors for the build tools. In addition to
> > -# the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
> > -# to the [depex] section in module's inf file.
> > -#
> > -class ModuleAutoGen(AutoGen):
> > -    # call super().__init__ then call the worker function with different parameter count
> > -    def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
> > -        if not hasattr(self, "_Init"):
> > -            self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args)
> > -            self._Init = True
> > -
> > -    ## Cache the timestamps of metafiles of every module in a class attribute
> > -    #
> > -    TimeDict = {}
> > -
> > -    def __new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
> > -        # check if this module is employed by active platform
> > -        if not PlatformAutoGen(Workspace, args[0], Target, Toolchain, Arch).ValidModule(MetaFile):
> > -            EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \
> > -                              % (MetaFile, Arch))
> > -            return None
> > -        return super(ModuleAutoGen, cls).__new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)
> > -
> > -    ## Initialize ModuleAutoGen
> > -    #
> > -    #   @param      Workspace           EdkIIWorkspaceBuild object
> > -    #   @param      ModuleFile          The path of module file
> > -    #   @param      Target              Build target (DEBUG, RELEASE)
> > -    #   @param      Toolchain           Name of tool chain
> > -    #   @param      Arch                The arch the module supports
> > -    #   @param      PlatformFile        Platform meta-file
> > -    #
> > -    def _InitWorker(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):
> > -        EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))
> > -        GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)
> > -
> > -        self.Workspace = Workspace
> > -        self.WorkspaceDir = Workspace.WorkspaceDir
> > -        self.MetaFile = ModuleFile
> > -        self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)
> > -
> > -        self.SourceDir = self.MetaFile.SubDir
> > -        self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir)
> > -
> > -        self.ToolChain = Toolchain
> > -        self.BuildTarget = Target
> > -        self.Arch = Arch
> > -        self.ToolChainFamily = self.PlatformInfo.ToolChainFamily
> > -        self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily
> > -
> > -        self.IsCodeFileCreated = False
> > -        self.IsAsBuiltInfCreated = False
> > -        self.DepexGenerated = False
> > -
> > -        self.BuildDatabase = self.Workspace.BuildDatabase
> > -        self.BuildRuleOrder = None
> > -        self.BuildTime      = 0
> > -
> > -        self._PcdComments = OrderedListDict()
> > -        self._GuidComments = OrderedListDict()
> > -        self._ProtocolComments = OrderedListDict()
> > -        self._PpiComments = OrderedListDict()
> > -        self._BuildTargets            = None
> > -        self._IntroBuildTargetList    = None
> > -        self._FinalBuildTargetList    = None
> > -        self._FileTypes               = None
> > -
> > -        self.AutoGenDepSet = set()
> > -        self.ReferenceModules = []
> > -        self.ConstPcd                  = {}
> > -
> > -    ## hash() operator of ModuleAutoGen
> > -    #
> > -    #  The module file path and arch string will be used to represent
> > -    #  hash value of this object
> > -    #
> > -    #   @retval   int Hash value of the module file path and arch
> > -    #
> > -    @cached_class_function
> > -    def __hash__(self):
> > -        return hash((self.MetaFile, self.Arch))
> > -
> > -    def __repr__(self):
> > -        return "%s [%s]" % (self.MetaFile, self.Arch)
> > -
> > -    # Get FixedAtBuild Pcds of this Module
> > -    @cached_property
> > -    def FixedAtBuildPcds(self):
> > -        RetVal = []
> > -        for Pcd in self.ModulePcdList:
> > -            if Pcd.Type != TAB_PCDS_FIXED_AT_BUILD:
> > -                continue
> > -            if Pcd not in RetVal:
> > -                RetVal.append(Pcd)
> > -        return RetVal
> > -
> > -    @cached_property
> > -    def FixedVoidTypePcds(self):
> > -        RetVal = {}
> > -        for Pcd in self.FixedAtBuildPcds:
> > -            if Pcd.DatumType == TAB_VOID:
> > -                if '{}.{}'.format(Pcd.TokenSpaceGuidCName, Pcd.TokenCName) not in RetVal:
> > -                    RetVal['{}.{}'.format(Pcd.TokenSpaceGuidCName, Pcd.TokenCName)] = Pcd.DefaultValue
> > -        return RetVal
> > -
> > -    @property
> > -    def UniqueBaseName(self):
> > -        BaseName = self.Name
> > -        for Module in self.PlatformInfo.ModuleAutoGenList:
> > -            if Module.MetaFile == self.MetaFile:
> > -                continue
> > -            if Module.Name == self.Name:
> > -                if uuid.UUID(Module.Guid) == uuid.UUID(self.Guid):
> > -                    EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'
> > -                                    '  %s\n  %s' % (Module.MetaFile, self.MetaFile))
> > -                BaseName = '%s_%s' % (self.Name, self.Guid)
> > -        return BaseName
> > -
> > -    # Macros could be used in build_rule.txt (also Makefile)
> > -    @cached_property
> > -    def Macros(self):
> > -        return OrderedDict((
> > -            ("WORKSPACE" ,self.WorkspaceDir),
> > -            ("MODULE_NAME" ,self.Name),
> > -            ("MODULE_NAME_GUID" ,self.UniqueBaseName),
> > -            ("MODULE_GUID" ,self.Guid),
> > -            ("MODULE_VERSION" ,self.Version),
> > -            ("MODULE_TYPE" ,self.ModuleType),
> > -            ("MODULE_FILE" ,str(self.MetaFile)),
> > -            ("MODULE_FILE_BASE_NAME" ,self.MetaFile.BaseName),
> > -            ("MODULE_RELATIVE_DIR" ,self.SourceDir),
> > -            ("MODULE_DIR" ,self.SourceDir),
> > -            ("BASE_NAME" ,self.Name),
> > -            ("ARCH" ,self.Arch),
> > -            ("TOOLCHAIN" ,self.ToolChain),
> > -            ("TOOLCHAIN_TAG" ,self.ToolChain),
> > -            ("TOOL_CHAIN_TAG" ,self.ToolChain),
> > -            ("TARGET" ,self.BuildTarget),
> > -            ("BUILD_DIR" ,self.PlatformInfo.BuildDir),
> > -            ("BIN_DIR" ,os.path.join(self.PlatformInfo.BuildDir, self.Arch)),
> > -            ("LIB_DIR" ,os.path.join(self.PlatformInfo.BuildDir, self.Arch)),
> > -            ("MODULE_BUILD_DIR" ,self.BuildDir),
> > -            ("OUTPUT_DIR" ,self.OutputDir),
> > -            ("DEBUG_DIR" ,self.DebugDir),
> > -            ("DEST_DIR_OUTPUT" ,self.OutputDir),
> > -            ("DEST_DIR_DEBUG" ,self.DebugDir),
> > -            ("PLATFORM_NAME" ,self.PlatformInfo.Name),
> > -            ("PLATFORM_GUID" ,self.PlatformInfo.Guid),
> > -            ("PLATFORM_VERSION" ,self.PlatformInfo.Version),
> > -            ("PLATFORM_RELATIVE_DIR" ,self.PlatformInfo.SourceDir),
> > -            ("PLATFORM_DIR" ,mws.join(self.WorkspaceDir, self.PlatformInfo.SourceDir)),
> > -            ("PLATFORM_OUTPUT_DIR" ,self.PlatformInfo.OutputDir),
> > -            ("FFS_OUTPUT_DIR" ,self.FfsOutputDir)
> > -            ))
> > -
> > -    ## Return the module build data object
> > -    @cached_property
> > -    def Module(self):
> > -        return self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
> > -
> > -    ## Return the module name
> > -    @cached_property
> > -    def Name(self):
> > -        return self.Module.BaseName
> > -
> > -    ## Return the module DxsFile if exist
> > -    @cached_property
> > -    def DxsFile(self):
> > -        return self.Module.DxsFile
> > -
> > -    ## Return the module meta-file GUID
> > -    @cached_property
> > -    def Guid(self):
> > -        #
> > -        # To build same module more than once, the module path with FILE_GUID overridden has
> > -        # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the real path
> > -        # in DSC. The overridden GUID can be retrieved from file name
> > -        #
> > -        if os.path.basename(self.MetaFile.File) != os.path.basename(self.MetaFile.Path):
> > -            #
> > -            # Length of GUID is 36
> > -            #
> > -            return os.path.basename(self.MetaFile.Path)[:36]
> > -        return self.Module.Guid
> > -
> > -    ## Return the module version
> > -    @cached_property
> > -    def Version(self):
> > -        return self.Module.Version
> > -
> > -    ## Return the module type
> > -    @cached_property
> > -    def ModuleType(self):
> > -        return self.Module.ModuleType
> > -
> > -    ## Return the component type (for Edk.x style of module)
> > -    @cached_property
> > -    def ComponentType(self):
> > -        return self.Module.ComponentType
> > -
> > -    ## Return the build type
> > -    @cached_property
> > -    def BuildType(self):
> > -        return self.Module.BuildType
> > -
> > -    ## Return the PCD_IS_DRIVER setting
> > -    @cached_property
> > -    def PcdIsDriver(self):
> > -        return self.Module.PcdIsDriver
> > -
> > -    ## Return the autogen version, i.e. module meta-file version
> > -    @cached_property
> > -    def AutoGenVersion(self):
> > -        return self.Module.AutoGenVersion
> > -
> > -    ## Check if the module is library or not
> > -    @cached_property
> > -    def IsLibrary(self):
> > -        return bool(self.Module.LibraryClass)
> > -
> > -    ## Check if the module is binary module or not
> > -    @cached_property
> > -    def IsBinaryModule(self):
> > -        return self.Module.IsBinaryModule
> > -
> > -    ## Return the directory to store intermediate files of the module
> > -    @cached_property
> > -    def BuildDir(self):
> > -        return _MakeDir((
> > -                                    self.PlatformInfo.BuildDir,
> > -                                    self.Arch,
> > -                                    self.SourceDir,
> > -                                    self.MetaFile.BaseName
> > -            ))
> > -
> > -    ## Return the directory to store the intermediate object files of the module
> > -    @cached_property
> > -    def OutputDir(self):
> > -        return _MakeDir((self.BuildDir, "OUTPUT"))
> > -
> > -    ## Return the directory path to store ffs file
> > -    @cached_property
> > -    def FfsOutputDir(self):
> > -        if GlobalData.gFdfParser:
> > -            return path.join(self.PlatformInfo.BuildDir, TAB_FV_DIRECTORY, "Ffs", self.Guid + self.Name)
> > -        return ''
> > -
> > -    ## Return the directory to store auto-gened source files of the module
> > -    @cached_property
> > -    def DebugDir(self):
> > -        return _MakeDir((self.BuildDir, "DEBUG"))
> > -
> > -    ## Return the path of custom file
> > -    @cached_property
> > -    def CustomMakefile(self):
> > -        RetVal = {}
> > -        for Type in self.Module.CustomMakefile:
> > -            MakeType = gMakeTypeMap[Type] if Type in gMakeTypeMap else 'nmake'
> > -            File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
> > -            RetVal[MakeType] = File
> > -        return RetVal
> > -
> > -    ## Return the directory of the makefile
> > -    #
> > -    #   @retval     string  The directory string of module's makefile
> > -    #
> > -    @cached_property
> > -    def MakeFileDir(self):
> > -        return self.BuildDir
> > -
> > -    ## Return build command string
> > -    #
> > -    #   @retval     string  Build command string
> > -    #
> > -    @cached_property
> > -    def BuildCommand(self):
> > -        return self.PlatformInfo.BuildCommand
> > -
> > -    ## Get object list of all packages the module and its dependent libraries belong to
> > -    #
> > -    #   @retval     list    The list of package object
> > -    #
> > -    @cached_property
> > -    def DerivedPackageList(self):
> > -        PackageList = []
> > -        for M in [self.Module] + self.DependentLibraryList:
> > -            for Package in M.Packages:
> > -                if Package in PackageList:
> > -                    continue
> > -                PackageList.append(Package)
> > -        return PackageList
> > -
> > -    ## Get the depex string
> > -    #
> > -    # @return : a string contain all depex expression.
> > -    def _GetDepexExpresionString(self):
> > -        DepexStr = ''
> > -        DepexList = []
> > -        ## DPX_SOURCE IN Define section.
> > -        if self.Module.DxsFile:
> > -            return DepexStr
> > -        for M in [self.Module] + self.DependentLibraryList:
> > -            Filename = M.MetaFile.Path
> > -            InfObj = InfSectionParser.InfSectionParser(Filename)
> > -            DepexExpressionList = InfObj.GetDepexExpresionList()
> > -            for DepexExpression in DepexExpressionList:
> > -                for key in DepexExpression:
> > -                    Arch, ModuleType = key
> > -                    DepexExpr = [x for x in DepexExpression[key] if not str(x).startswith('#')]
> > -                    # the type of build module is USER_DEFINED.
> > -                    # All different DEPEX section tags would be copied into the As Built INF file
> > -                    # and there would be separate DEPEX section tags
> > -                    if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED or self.ModuleType.upper() == SUP_MODULE_HOST_APPLICATION:
> > -                        if (Arch.upper() == self.Arch.upper()) and (ModuleType.upper() != TAB_ARCH_COMMON):
> > -                            DepexList.append({(Arch, ModuleType): DepexExpr})
> > -                    else:
> > -                        if Arch.upper() == TAB_ARCH_COMMON or \
> > -                          (Arch.upper() == self.Arch.upper() and \
> > -                          ModuleType.upper() in [TAB_ARCH_COMMON, self.ModuleType.upper()]):
> > -                            DepexList.append({(Arch, ModuleType): DepexExpr})
> > -
> > -        #the type of build module is USER_DEFINED.
> > -        if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED or self.ModuleType.upper() == SUP_MODULE_HOST_APPLICATION:
> > -            for Depex in DepexList:
> > -                for key in Depex:
> > -                    DepexStr += '[Depex.%s.%s]\n' % key
> > -                    DepexStr += '\n'.join('# '+ val for val in Depex[key])
> > -                    DepexStr += '\n\n'
> > -            if not DepexStr:
> > -                return '[Depex.%s]\n' % self.Arch
> > -            return DepexStr
> > -
> > -        #the type of build module not is USER_DEFINED.
> > -        Count = 0
> > -        for Depex in DepexList:
> > -            Count += 1
> > -            if DepexStr != '':
> > -                DepexStr += ' AND '
> > -            DepexStr += '('
> > -            for D in Depex.values():
> > -                DepexStr += ' '.join(val for val in D)
> > -            Index = DepexStr.find('END')
> > -            if Index > -1 and Index == len(DepexStr) - 3:
> > -                DepexStr = DepexStr[:-3]
> > -            DepexStr = DepexStr.strip()
> > -            DepexStr += ')'
> > -        if Count == 1:
> > -            DepexStr = DepexStr.lstrip('(').rstrip(')').strip()
> > -        if not DepexStr:
> > -            return '[Depex.%s]\n' % self.Arch
> > -        return '[Depex.%s]\n#  ' % self.Arch + DepexStr
> > -
> > -    ## Merge dependency expression
> > -    #
> > -    #   @retval     list    The token list of the dependency expression after parsed
> > -    #
> > -    @cached_property
> > -    def DepexList(self):
> > -        if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
> > -            return {}
> > -
> > -        DepexList = []
> > -        #
> > -        # Append depex from dependent libraries, if not "BEFORE", "AFTER" expression
> > -        #
> > -        for M in [self.Module] + self.DependentLibraryList:
> > -            Inherited = False
> > -            for D in M.Depex[self.Arch, self.ModuleType]:
> > -                if DepexList != []:
> > -                    DepexList.append('AND')
> > -                DepexList.append('(')
> > -                #replace D with value if D is FixedAtBuild PCD
> > -                NewList = []
> > -                for item in D:
> > -                    if '.' not in item:
> > -                        NewList.append(item)
> > -                    else:
> > -                        FixedVoidTypePcds = {}
> > -                        if item in self.FixedVoidTypePcds:
> > -                            FixedVoidTypePcds = self.FixedVoidTypePcds
> > -                        elif M in self.PlatformInfo.LibraryAutoGenList:
> > -                            Index = self.PlatformInfo.LibraryAutoGenList.index(M)
> > -                            FixedVoidTypePcds = self.PlatformInfo.LibraryAutoGenList[Index].FixedVoidTypePcds
> > -                        if item not in FixedVoidTypePcds:
> > -                            EdkLogger.error("build", FORMAT_INVALID, "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type in the module.".format(item))
> > -                        else:
> > -                            Value = FixedVoidTypePcds[item]
> > -                            if len(Value.split(',')) != 16:
> > -                                EdkLogger.error("build", FORMAT_INVALID,
> > -                                                "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type and 16 bytes in the module.".format(item))
> > -                            NewList.append(Value)
> > -                DepexList.extend(NewList)
> > -                if DepexList[-1] == 'END':  # no need of a END at this time
> > -                    DepexList.pop()
> > -                DepexList.append(')')
> > -                Inherited = True
> > -            if Inherited:
> > -                EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))
> > -            if 'BEFORE' in DepexList or 'AFTER' in DepexList:
> > -                break
> > -            if len(DepexList) > 0:
> > -                EdkLogger.verbose('')
> > -        return {self.ModuleType:DepexList}
> > -
> > -    ## Merge dependency expression
> > -    #
> > -    #   @retval     list    The token list of the dependency expression after parsed
> > -    #
> > -    @cached_property
> > -    def DepexExpressionDict(self):
> > -        if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
> > -            return {}
> > -
> > -        DepexExpressionString = ''
> > -        #
> > -        # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
> > -        #
> > -        for M in [self.Module] + self.DependentLibraryList:
> > -            Inherited = False
> > -            for D in M.DepexExpression[self.Arch, self.ModuleType]:
> > -                if DepexExpressionString != '':
> > -                    DepexExpressionString += ' AND '
> > -                DepexExpressionString += '('
> > -                DepexExpressionString += D
> > -                DepexExpressionString = DepexExpressionString.rstrip('END').strip()
> > -                DepexExpressionString += ')'
> > -                Inherited = True
> > -            if Inherited:
> > -                EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionString))
> > -            if 'BEFORE' in DepexExpressionString or 'AFTER' in DepexExpressionString:
> > -                break
> > -        if len(DepexExpressionString) > 0:
> > -            EdkLogger.verbose('')
> > -
> > -        return {self.ModuleType:DepexExpressionString}
> > -
> > -    # Get the tiano core user extension, it is contain dependent library.
> > -    # @retval: a list contain tiano core userextension.
> > -    #
> > -    def _GetTianoCoreUserExtensionList(self):
> > -        TianoCoreUserExtentionList = []
> > -        for M in [self.Module] + self.DependentLibraryList:
> > -            Filename = M.MetaFile.Path
> > -            InfObj = InfSectionParser.InfSectionParser(Filename)
> > -            TianoCoreUserExtenList = InfObj.GetUserExtensionTianoCore()
> > -            for TianoCoreUserExtent in TianoCoreUserExtenList:
> > -                for Section in TianoCoreUserExtent:
> > -                    ItemList = Section.split(TAB_SPLIT)
> > -                    Arch = self.Arch
> > -                    if len(ItemList) == 4:
> > -                        Arch = ItemList[3]
> > -                    if Arch.upper() == TAB_ARCH_COMMON or Arch.upper() == self.Arch.upper():
> > -                        TianoCoreList = []
> > -                        TianoCoreList.extend([TAB_SECTION_START + Section + TAB_SECTION_END])
> > -                        TianoCoreList.extend(TianoCoreUserExtent[Section][:])
> > -                        TianoCoreList.append('\n')
> > -                        TianoCoreUserExtentionList.append(TianoCoreList)
> > -
> > -        return TianoCoreUserExtentionList
> > -
> > -    ## Return the list of specification version required for the module
> > -    #
> > -    #   @retval     list    The list of specification defined in module file
> > -    #
> > -    @cached_property
> > -    def Specification(self):
> > -        return self.Module.Specification
> > -
> > -    ## Tool option for the module build
> > -    #
> > -    #   @param      PlatformInfo    The object of PlatformBuildInfo
> > -    #   @retval     dict            The dict containing valid options
> > -    #
> > -    @cached_property
> > -    def BuildOption(self):
> > -        RetVal, self.BuildRuleOrder = self.PlatformInfo.ApplyBuildOption(self.Module)
> > -        if self.BuildRuleOrder:
> > -            self.BuildRuleOrder = ['.%s' % Ext for Ext in self.BuildRuleOrder.split()]
> > -        return RetVal
> > -
> > -    ## Get include path list from tool option for the module build
> > -    #
> > -    #   @retval     list            The include path list
> > -    #
> > -    @cached_property
> > -    def BuildOptionIncPathList(self):
> > -        #
> > -        # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
> > -        # is the former use /I , the Latter used -I to specify include directories
> > -        #
> > -        if self.PlatformInfo.ToolChainFamily in (TAB_COMPILER_MSFT):
> > -            BuildOptIncludeRegEx = gBuildOptIncludePatternMsft
> > -        elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):
> > -            BuildOptIncludeRegEx = gBuildOptIncludePatternOther
> > -        else:
> > -            #
> > -            # New ToolChainFamily, don't known whether there is option to specify include directories
> > -            #
> > -            return []
> > -
> > -        RetVal = []
> > -        for Tool in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
> > -            try:
> > -                FlagOption = self.BuildOption[Tool]['FLAGS']
> > -            except KeyError:
> > -                FlagOption = ''
> > -
> > -            if self.ToolChainFamily != 'RVCT':
> > -                IncPathList = [NormPath(Path, self.Macros) for Path in BuildOptIncludeRegEx.findall(FlagOption)]
> > -            else:
> > -                #
> > -                # RVCT may specify a list of directory separated by commas
> > -                #
> > -                IncPathList = []
> > -                for Path in BuildOptIncludeRegEx.findall(FlagOption):
> > -                    PathList = GetSplitList(Path, TAB_COMMA_SPLIT)
> > -                    IncPathList.extend(NormPath(PathEntry, self.Macros) for PathEntry in PathList)
> > -
> > -            #
> > -            # EDK II modules must not reference header files outside of the packages they depend on or
> > -            # within the module's directory tree. Report error if violation.
> > -            #
> > -            if GlobalData.gDisableIncludePathCheck == False:
> > -                for Path in IncPathList:
> > -                    if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir):
> > -                        ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption)
> > -                        EdkLogger.error("build",
> > -                                        PARAMETER_INVALID,
> > -                                        ExtraData=ErrMsg,
> > -                                        File=str(self.MetaFile))
> > -            RetVal += IncPathList
> > -        return RetVal
> > -
> > -    ## Return a list of files which can be built from source
> > -    #
> > -    #  What kind of files can be built is determined by build rules in
> > -    #  $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
> > -    #
> > -    @cached_property
> > -    def SourceFileList(self):
> > -        RetVal = []
> > -        ToolChainTagSet = {"", TAB_STAR, self.ToolChain}
> > -        ToolChainFamilySet = {"", TAB_STAR, self.ToolChainFamily, self.BuildRuleFamily}
> > -        for F in self.Module.Sources:
> > -            # match tool chain
> > -            if F.TagName not in ToolChainTagSet:
> > -                EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "
> > -                                "but [%s] is currently used" % (F.TagName, str(F), self.ToolChain))
> > -                continue
> > -            # match tool chain family or build rule family
> > -            if F.ToolChainFamily not in ToolChainFamilySet:
> > -                EdkLogger.debug(
> > -                            EdkLogger.DEBUG_0,
> > -                            "The file [%s] must be built by tools of [%s], " \
> > -                            "but current toolchain family is [%s], buildrule family is [%s]" \
> > -                                % (str(F), F.ToolChainFamily, self.ToolChainFamily, self.BuildRuleFamily))
> > -                continue
> > -
> > -            # add the file path into search path list for file including
> > -            if F.Dir not in self.IncludePathList:
> > -                self.IncludePathList.insert(0, F.Dir)
> > -            RetVal.append(F)
> > -
> > -        self._MatchBuildRuleOrder(RetVal)
> > -
> > -        for F in RetVal:
> > -            self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)
> > -        return RetVal
> > -
> > -    def _MatchBuildRuleOrder(self, FileList):
> > -        Order_Dict = {}
> > -        self.BuildOption
> > -        for SingleFile in FileList:
> > -            if self.BuildRuleOrder and SingleFile.Ext in self.BuildRuleOrder and SingleFile.Ext in self.BuildRules:
> > -                key = SingleFile.Path.rsplit(SingleFile.Ext,1)[0]
> > -                if key in Order_Dict:
> > -                    Order_Dict[key].append(SingleFile.Ext)
> > -                else:
> > -                    Order_Dict[key] = [SingleFile.Ext]
> > -
> > -        RemoveList = []
> > -        for F in Order_Dict:
> > -            if len(Order_Dict[F]) > 1:
> > -                Order_Dict[F].sort(key=lambda i: self.BuildRuleOrder.index(i))
> > -                for Ext in Order_Dict[F][1:]:
> > -                    RemoveList.append(F + Ext)
> > -
> > -        for item in RemoveList:
> > -            FileList.remove(item)
> > -
> > -        return FileList
> > -
> > -    ## Return the list of unicode files
> > -    @cached_property
> > -    def UnicodeFileList(self):
> > -        return self.FileTypes.get(TAB_UNICODE_FILE,[])
> > -
> > -    ## Return the list of vfr files
> > -    @cached_property
> > -    def VfrFileList(self):
> > -        return self.FileTypes.get(TAB_VFR_FILE, [])
> > -
> > -    ## Return the list of Image Definition files
> > -    @cached_property
> > -    def IdfFileList(self):
> > -        return self.FileTypes.get(TAB_IMAGE_FILE,[])
> > -
> > -    ## Return a list of files which can be built from binary
> > -    #
> > -    #  "Build" binary files are just to copy them to build directory.
> > -    #
> > -    #   @retval     list            The list of files which can be built later
> > -    #
> > -    @cached_property
> > -    def BinaryFileList(self):
> > -        RetVal = []
> > -        for F in self.Module.Binaries:
> > -            if F.Target not in [TAB_ARCH_COMMON, TAB_STAR] and F.Target != self.BuildTarget:
> > -                continue
> > -            RetVal.append(F)
> > -            self._ApplyBuildRule(F, F.Type, BinaryFileList=RetVal)
> > -        return RetVal
> > -
> > -    @cached_property
> > -    def BuildRules(self):
> > -        RetVal = {}
> > -        BuildRuleDatabase = BuildRule
> > -        for Type in BuildRuleDatabase.FileTypeList:
> > -            #first try getting build rule by BuildRuleFamily
> > -            RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]
> > -            if not RuleObject:
> > -                # build type is always module type, but ...
> > -                if self.ModuleType != self.BuildType:
> > -                    RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]
> > -            #second try getting build rule by ToolChainFamily
> > -            if not RuleObject:
> > -                RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]
> > -                if not RuleObject:
> > -                    # build type is always module type, but ...
> > -                    if self.ModuleType != self.BuildType:
> > -                        RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]
> > -            if not RuleObject:
> > -                continue
> > -            RuleObject = RuleObject.Instantiate(self.Macros)
> > -            RetVal[Type] = RuleObject
> > -            for Ext in RuleObject.SourceFileExtList:
> > -                RetVal[Ext] = RuleObject
> > -        return RetVal
> > -
> > -    def _ApplyBuildRule(self, File, FileType, BinaryFileList=None):
> > -        if self._BuildTargets is None:
> > -            self._IntroBuildTargetList = set()
> > -            self._FinalBuildTargetList = set()
> > -            self._BuildTargets = defaultdict(set)
> > -            self._FileTypes = defaultdict(set)
> > -
> > -        if not BinaryFileList:
> > -            BinaryFileList = self.BinaryFileList
> > -
> > -        SubDirectory = os.path.join(self.OutputDir, File.SubDir)
> > -        if not os.path.exists(SubDirectory):
> > -            CreateDirectory(SubDirectory)
> > -        LastTarget = None
> > -        RuleChain = set()
> > -        SourceList = [File]
> > -        Index = 0
> > -        #
> > -        # Make sure to get build rule order value
> > -        #
> > -        self.BuildOption
> > -
> > -        while Index < len(SourceList):
> > -            Source = SourceList[Index]
> > -            Index = Index + 1
> > -
> > -            if Source != File:
> > -                CreateDirectory(Source.Dir)
> > -
> > -            if File.IsBinary and File == Source and File in BinaryFileList:
> > -                # Skip all files that are not binary libraries
> > -                if not self.IsLibrary:
> > -                    continue
> > -                RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]
> > -            elif FileType in self.BuildRules:
> > -                RuleObject = self.BuildRules[FileType]
> > -            elif Source.Ext in self.BuildRules:
> > -                RuleObject = self.BuildRules[Source.Ext]
> > -            else:
> > -                # stop at no more rules
> > -                if LastTarget:
> > -                    self._FinalBuildTargetList.add(LastTarget)
> > -                break
> > -
> > -            FileType = RuleObject.SourceFileType
> > -            self._FileTypes[FileType].add(Source)
> > -
> > -            # stop at STATIC_LIBRARY for library
> > -            if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
> > -                if LastTarget:
> > -                    self._FinalBuildTargetList.add(LastTarget)
> > -                break
> > -
> > -            Target = RuleObject.Apply(Source, self.BuildRuleOrder)
> > -            if not Target:
> > -                if LastTarget:
> > -                    self._FinalBuildTargetList.add(LastTarget)
> > -                break
> > -            elif not Target.Outputs:
> > -                # Only do build for target with outputs
> > -                self._FinalBuildTargetList.add(Target)
> > -
> > -            self._BuildTargets[FileType].add(Target)
> > -
> > -            if not Source.IsBinary and Source == File:
> > -                self._IntroBuildTargetList.add(Target)
> > -
> > -            # to avoid cyclic rule
> > -            if FileType in RuleChain:
> > -                break
> > -
> > -            RuleChain.add(FileType)
> > -            SourceList.extend(Target.Outputs)
> > -            LastTarget = Target
> > -            FileType = TAB_UNKNOWN_FILE
> > -
> > -    @cached_property
> > -    def Targets(self):
> > -        if self._BuildTargets is None:
> > -            self._IntroBuildTargetList = set()
> > -            self._FinalBuildTargetList = set()
> > -            self._BuildTargets = defaultdict(set)
> > -            self._FileTypes = defaultdict(set)
> > -
> > -        #TRICK: call SourceFileList property to apply build rule for source files
> > -        self.SourceFileList
> > -
> > -        #TRICK: call _GetBinaryFileList to apply build rule for binary files
> > -        self.BinaryFileList
> > -
> > -        return self._BuildTargets
> > -
> > -    @cached_property
> > -    def IntroTargetList(self):
> > -        self.Targets
> > -        return self._IntroBuildTargetList
> > -
> > -    @cached_property
> > -    def CodaTargetList(self):
> > -        self.Targets
> > -        return self._FinalBuildTargetList
> > -
> > -    @cached_property
> > -    def FileTypes(self):
> > -        self.Targets
> > -        return self._FileTypes
> > -
> > -    ## Get the list of package object the module depends on
> > -    #
> > -    #   @retval     list    The package object list
> > -    #
> > -    @cached_property
> > -    def DependentPackageList(self):
> > -        return self.Module.Packages
> > -
> > -    ## Return the list of auto-generated code file
> > -    #
> > -    #   @retval     list        The list of auto-generated file
> > -    #
> > -    @cached_property
> > -    def AutoGenFileList(self):
> > -        AutoGenUniIdf = self.BuildType != 'UEFI_HII'
> > -        UniStringBinBuffer = BytesIO()
> > -        IdfGenBinBuffer = BytesIO()
> > -        RetVal = {}
> > -        AutoGenC = TemplateString()
> > -        AutoGenH = TemplateString()
> > -        StringH = TemplateString()
> > -        StringIdf = TemplateString()
> > -        GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, AutoGenUniIdf, UniStringBinBuffer, StringIdf, AutoGenUniIdf, IdfGenBinBuffer)
> > -        #
> > -        # AutoGen.c is generated if there are library classes in inf, or there are object files
> > -        #
> > -        if str(AutoGenC) != "" and (len(self.Module.LibraryClasses) > 0
> > -                                    or TAB_OBJECT_FILE in self.FileTypes):
> > -            AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)
> > -            RetVal[AutoFile] = str(AutoGenC)
> > -            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
> > -        if str(AutoGenH) != "":
> > -            AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)
> > -            RetVal[AutoFile] = str(AutoGenH)
> > -            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
> > -        if str(StringH) != "":
> > -            AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)
> > -            RetVal[AutoFile] = str(StringH)
> > -            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
> > -        if UniStringBinBuffer is not None and UniStringBinBuffer.getvalue() != b"":
> > -            AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)
> > -            RetVal[AutoFile] = UniStringBinBuffer.getvalue()
> > -            AutoFile.IsBinary = True
> > -            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
> > -        if UniStringBinBuffer is not None:
> > -            UniStringBinBuffer.close()
> > -        if str(StringIdf) != "":
> > -            AutoFile = PathClass(gAutoGenImageDefFileName % {"module_name":self.Name}, self.DebugDir)
> > -            RetVal[AutoFile] = str(StringIdf)
> > -            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
> > -        if IdfGenBinBuffer is not None and IdfGenBinBuffer.getvalue() != b"":
> > -            AutoFile = PathClass(gAutoGenIdfFileName % {"module_name":self.Name}, self.OutputDir)
> > -            RetVal[AutoFile] = IdfGenBinBuffer.getvalue()
> > -            AutoFile.IsBinary = True
> > -            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
> > -        if IdfGenBinBuffer is not None:
> > -            IdfGenBinBuffer.close()
> > -        return RetVal
> > -
> > -    ## Return the list of library modules explicitly or implicitly used by this module
> > -    @cached_property
> > -    def DependentLibraryList(self):
> > -        # only merge library classes and PCD for non-library module
> > -        if self.IsLibrary:
> > -            return []
> > -        return self.PlatformInfo.ApplyLibraryInstance(self.Module)
> > -
> > -    ## Get the list of PCDs from current module
> > -    #
> > -    #   @retval     list                    The list of PCD
> > -    #
> > -    @cached_property
> > -    def ModulePcdList(self):
> > -        # apply PCD settings from platform
> > -        RetVal = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)
> > -        ExtendCopyDictionaryLists(self._PcdComments, self.Module.PcdComments)
> > -        return RetVal
> > -
> > -    ## Get the list of PCDs from dependent libraries
> > -    #
> > -    #   @retval     list                    The list of PCD
> > -    #
> > -    @cached_property
> > -    def LibraryPcdList(self):
> > -        if self.IsLibrary:
> > -            return []
> > -        RetVal = []
> > -        Pcds = set()
> > -        # get PCDs from dependent libraries
> > -        for Library in self.DependentLibraryList:
> > -            PcdsInLibrary = OrderedDict()
> > -            ExtendCopyDictionaryLists(self._PcdComments, Library.PcdComments)
> > -            for Key in Library.Pcds:
> > -                # skip duplicated PCDs
> > -                if Key in self.Module.Pcds or Key in Pcds:
> > -                    continue
> > -                Pcds.add(Key)
> > -                PcdsInLibrary[Key] = copy.copy(Library.Pcds[Key])
> > -            RetVal.extend(self.PlatformInfo.ApplyPcdSetting(self.Module, PcdsInLibrary, Library=Library))
> > -        return RetVal
> > -
> > -    ## Get the GUID value mapping
> > -    #
> > -    #   @retval     dict    The mapping between GUID cname and its value
> > -    #
> > -    @cached_property
> > -    def GuidList(self):
> > -        RetVal = OrderedDict(self.Module.Guids)
> > -        for Library in self.DependentLibraryList:
> > -            RetVal.update(Library.Guids)
> > -            ExtendCopyDictionaryLists(self._GuidComments, Library.GuidComments)
> > -        ExtendCopyDictionaryLists(self._GuidComments, self.Module.GuidComments)
> > -        return RetVal
> > -
> > -    @cached_property
> > -    def GetGuidsUsedByPcd(self):
> > -        RetVal = OrderedDict(self.Module.GetGuidsUsedByPcd())
> > -        for Library in self.DependentLibraryList:
> > -            RetVal.update(Library.GetGuidsUsedByPcd())
> > -        return RetVal
> > -    ## Get the protocol value mapping
> > -    #
> > -    #   @retval     dict    The mapping between protocol cname and its value
> > -    #
> > -    @cached_property
> > -    def ProtocolList(self):
> > -        RetVal = OrderedDict(self.Module.Protocols)
> > -        for Library in self.DependentLibraryList:
> > -            RetVal.update(Library.Protocols)
> > -            ExtendCopyDictionaryLists(self._ProtocolComments, Library.ProtocolComments)
> > -        ExtendCopyDictionaryLists(self._ProtocolComments, self.Module.ProtocolComments)
> > -        return RetVal
> > -
> > -    ## Get the PPI value mapping
> > -    #
> > -    #   @retval     dict    The mapping between PPI cname and its value
> > -    #
> > -    @cached_property
> > -    def PpiList(self):
> > -        RetVal = OrderedDict(self.Module.Ppis)
> > -        for Library in self.DependentLibraryList:
> > -            RetVal.update(Library.Ppis)
> > -            ExtendCopyDictionaryLists(self._PpiComments, Library.PpiComments)
> > -        ExtendCopyDictionaryLists(self._PpiComments, self.Module.PpiComments)
> > -        return RetVal
> > -
> > -    ## Get the list of include search path
> > -    #
> > -    #   @retval     list                    The list path
> > -    #
> > -    @cached_property
> > -    def IncludePathList(self):
> > -        RetVal = []
> > -        RetVal.append(self.MetaFile.Dir)
> > -        RetVal.append(self.DebugDir)
> > -
> > -        for Package in self.Module.Packages:
> > -            PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir)
> > -            if PackageDir not in RetVal:
> > -                RetVal.append(PackageDir)
> > -            IncludesList = Package.Includes
> > -            if Package._PrivateIncludes:
> > -                if not self.MetaFile.OriginalPath.Path.startswith(PackageDir):
> > -                    IncludesList = list(set(Package.Includes).difference(set(Package._PrivateIncludes)))
> > -            for Inc in IncludesList:
> > -                if Inc not in RetVal:
> > -                    RetVal.append(str(Inc))
> > -        return RetVal
> > -
> > -    @cached_property
> > -    def IncludePathLength(self):
> > -        return sum(len(inc)+1 for inc in self.IncludePathList)
> > -
> > -    ## Get HII EX PCDs which maybe used by VFR
> > -    #
> > -    #  efivarstore used by VFR may relate with HII EX PCDs
> > -    #  Get the variable name and GUID from efivarstore and HII EX PCD
> > -    #  List the HII EX PCDs in As Built INF if both name and GUID match.
> > -    #
> > -    #  @retval    list    HII EX PCDs
> > -    #
> > -    def _GetPcdsMaybeUsedByVfr(self):
> > -        if not self.SourceFileList:
> > -            return []
> > -
> > -        NameGuids = set()
> > -        for SrcFile in self.SourceFileList:
> > -            if SrcFile.Ext.lower() != '.vfr':
> > -                continue
> > -            Vfri = os.path.join(self.OutputDir, SrcFile.BaseName + '.i')
> > -            if not os.path.exists(Vfri):
> > -                continue
> > -            VfriFile = open(Vfri, 'r')
> > -            Content = VfriFile.read()
> > -            VfriFile.close()
> > -            Pos = Content.find('efivarstore')
> > -            while Pos != -1:
> > -                #
> > -                # Make sure 'efivarstore' is the start of efivarstore statement
> > -                # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
> > -                #
> > -                Index = Pos - 1
> > -                while Index >= 0 and Content[Index] in ' \t\r\n':
> > -                    Index -= 1
> > -                if Index >= 0 and Content[Index] != ';':
> > -                    Pos = Content.find('efivarstore', Pos + len('efivarstore'))
> > -                    continue
> > -                #
> > -                # 'efivarstore' must be followed by name and guid
> > -                #
> > -                Name = gEfiVarStoreNamePattern.search(Content, Pos)
> > -                if not Name:
> > -                    break
> > -                Guid = gEfiVarStoreGuidPattern.search(Content, Pos)
> > -                if not Guid:
> > -                    break
> > -                NameArray = _ConvertStringToByteArray('L"' + Name.group(1) + '"')
> > -                NameGuids.add((NameArray, GuidStructureStringToGuidString(Guid.group(1))))
> > -                Pos = Content.find('efivarstore', Name.end())
> > -        if not NameGuids:
> > -            return []
> > -        HiiExPcds = []
> > -        for Pcd in self.PlatformInfo.Platform.Pcds.values():
> > -            if Pcd.Type != TAB_PCDS_DYNAMIC_EX_HII:
> > -                continue
> > -            for SkuInfo in Pcd.SkuInfoList.values():
> > -                Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList, self.MetaFile.Path)
> > -                if not Value:
> > -                    continue
> > -                Name = _ConvertStringToByteArray(SkuInfo.VariableName)
> > -                Guid = GuidStructureStringToGuidString(Value)
> > -                if (Name, Guid) in NameGuids and Pcd not in HiiExPcds:
> > -                    HiiExPcds.append(Pcd)
> > -                    break
> > -
> > -        return HiiExPcds
> > -
> > -    def _GenOffsetBin(self):
> > -        VfrUniBaseName = {}
> > -        for SourceFile in self.Module.Sources:
> > -            if SourceFile.Type.upper() == ".VFR" :
> > -                #
> > -                # search the .map file to find the offset of vfr binary in the PE32+/TE file.
> > -                #
> > -                VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")
> > -            elif SourceFile.Type.upper() == ".UNI" :
> > -                #
> > -                # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
> > -                #
> > -                VfrUniBaseName["UniOffsetName"] = (self.Name + "Strings")
> > -
> > -        if not VfrUniBaseName:
> > -            return None
> > -        MapFileName = os.path.join(self.OutputDir, self.Name + ".map")
> > -        EfiFileName = os.path.join(self.OutputDir, self.Name + ".efi")
> > -        VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, list(VfrUniBaseName.values()))
> > -        if not VfrUniOffsetList:
> > -            return None
> > -
> > -        OutputName = '%sOffset.bin' % self.Name
> > -        UniVfrOffsetFileName    =  os.path.join( self.OutputDir, OutputName)
> > -
> > -        try:
> > -            fInputfile = open(UniVfrOffsetFileName, "wb+", 0)
> > -        except:
> > -            EdkLogger.error("build", FILE_OPEN_FAILURE, "File open failed for %s" % UniVfrOffsetFileName, None)
> > -
> > -        # Use a instance of BytesIO to cache data
> > -        fStringIO = BytesIO()
> > -
> > -        for Item in VfrUniOffsetList:
> > -            if (Item[0].find("Strings") != -1):
> > -                #
> > -                # UNI offset in image.
> > -                # GUID + Offset
> > -                # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
> > -                #
> > -                UniGuid = b'\xe0\xc5\x13\x89\xf63\x86M\x9b\xf1C\xef\x89\xfc\x06f'
> > -                fStringIO.write(UniGuid)
> > -                UniValue = pack ('Q', int (Item[1], 16))
> > -                fStringIO.write (UniValue)
> > -            else:
> > -                #
> > -                # VFR binary offset in image.
> > -                # GUID + Offset
> > -                # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
> > -                #
> > -                VfrGuid = b'\xb4|\xbc\xd0Gj_I\xaa\x11q\x07F\xda\x06\xa2'
> > -                fStringIO.write(VfrGuid)
> > -                VfrValue = pack ('Q', int (Item[1], 16))
> > -                fStringIO.write (VfrValue)
> > -        #
> > -        # write data into file.
> > -        #
> > -        try :
> > -            fInputfile.write (fStringIO.getvalue())
> > -        except:
> > -            EdkLogger.error("build", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the "
> > -                            "file been locked or using by other applications." %UniVfrOffsetFileName, None)
> > -
> > -        fStringIO.close ()
> > -        fInputfile.close ()
> > -        return OutputName
> > -
> > -    @cached_property
> > -    def OutputFile(self):
> > -        retVal = set()
> > -        OutputDir = self.OutputDir.replace('\\', '/').strip('/')
> > -        DebugDir = self.DebugDir.replace('\\', '/').strip('/')
> > -        for Item in self.CodaTargetList:
> > -            File = Item.Target.Path.replace('\\', '/').strip('/').replace(DebugDir, '').replace(OutputDir, '').strip('/')
> > -            retVal.add(File)
> > -        if self.DepexGenerated:
> > -            retVal.add(self.Name + '.depex')
> > -
> > -        Bin = self._GenOffsetBin()
> > -        if Bin:
> > -            retVal.add(Bin)
> > -
> > -        for Root, Dirs, Files in os.walk(OutputDir):
> > -            for File in Files:
> > -                if File.lower().endswith('.pdb'):
> > -                    retVal.add(File)
> > -
> > -        return retVal
> > -
> > -    ## Create AsBuilt INF file the module
> > -    #
> > -    def CreateAsBuiltInf(self):
> > -
> > -        if self.IsAsBuiltInfCreated:
> > -            return
> > -
> > -        # Skip INF file generation for libraries
> > -        if self.IsLibrary:
> > -            return
> > -
> > -        # Skip the following code for modules with no source files
> > -        if not self.SourceFileList:
> > -            return
> > -
> > -        # Skip the following code for modules without any binary files
> > -        if self.BinaryFileList:
> > -            return
> > -
> > -        ### TODO: How to handles mixed source and binary modules
> > -
> > -        # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
> > -        # Also find all packages that the DynamicEx PCDs depend on
> > -        Pcds = []
> > -        PatchablePcds = []
> > -        Packages = []
> > -        PcdCheckList = []
> > -        PcdTokenSpaceList = []
> > -        for Pcd in self.ModulePcdList + self.LibraryPcdList:
> > -            if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE:
> > -                PatchablePcds.append(Pcd)
> > -                PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, TAB_PCDS_PATCHABLE_IN_MODULE))
> > -            elif Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
> > -                if Pcd not in Pcds:
> > -                    Pcds.append(Pcd)
> > -                    PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, TAB_PCDS_DYNAMIC_EX))
> > -                    PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, TAB_PCDS_DYNAMIC))
> > -                    PcdTokenSpaceList.append(Pcd.TokenSpaceGuidCName)
> > -        GuidList = OrderedDict(self.GuidList)
> > -        for TokenSpace in self.GetGuidsUsedByPcd:
> > -            # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
> > -            # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
> > -            if TokenSpace not in PcdTokenSpaceList and TokenSpace in GuidList:
> > -                GuidList.pop(TokenSpace)
> > -        CheckList = (GuidList, self.PpiList, self.ProtocolList, PcdCheckList)
> > -        for Package in self.DerivedPackageList:
> > -            if Package in Packages:
> > -                continue
> > -            BeChecked = (Package.Guids, Package.Ppis, Package.Protocols, Package.Pcds)
> > -            Found = False
> > -            for Index in range(len(BeChecked)):
> > -                for Item in CheckList[Index]:
> > -                    if Item in BeChecked[Index]:
> > -                        Packages.append(Package)
> > -                        Found = True
> > -                        break
> > -                if Found:
> > -                    break
> > -
> > -        VfrPcds = self._GetPcdsMaybeUsedByVfr()
> > -        for Pkg in self.PlatformInfo.PackageList:
> > -            if Pkg in Packages:
> > -                continue
> > -            for VfrPcd in VfrPcds:
> > -                if ((VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, TAB_PCDS_DYNAMIC_EX) in Pkg.Pcds or
> > -                    (VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, TAB_PCDS_DYNAMIC) in Pkg.Pcds):
> > -                    Packages.append(Pkg)
> > -                    break
> > -
> > -        ModuleType = SUP_MODULE_DXE_DRIVER if self.ModuleType == SUP_MODULE_UEFI_DRIVER and self.DepexGenerated else self.ModuleType
> > -        DriverType = self.PcdIsDriver if self.PcdIsDriver else ''
> > -        Guid = self.Guid
> > -        MDefs = self.Module.Defines
> > -
> > -        AsBuiltInfDict = {
> > -          'module_name'                       : self.Name,
> > -          'module_guid'                       : Guid,
> > -          'module_module_type'                : ModuleType,
> > -          'module_version_string'             : [MDefs['VERSION_STRING']] if 'VERSION_STRING' in MDefs else [],
> > -          'pcd_is_driver_string'              : [],
> > -          'module_uefi_specification_version' : [],
> > -          'module_pi_specification_version'   : [],
> > -          'module_entry_point'                : self.Module.ModuleEntryPointList,
> > -          'module_unload_image'               : self.Module.ModuleUnloadImageList,
> > -          'module_constructor'                : self.Module.ConstructorList,
> > -          'module_destructor'                 : self.Module.DestructorList,
> > -          'module_shadow'                     : [MDefs['SHADOW']] if 'SHADOW' in MDefs else [],
> > -          'module_pci_vendor_id'              : [MDefs['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs else [],
> > -          'module_pci_device_id'              : [MDefs['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs else [],
> > -          'module_pci_class_code'             : [MDefs['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs else [],
> > -          'module_pci_revision'               : [MDefs['PCI_REVISION']] if 'PCI_REVISION' in MDefs else [],
> > -          'module_build_number'               : [MDefs['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs else [],
> > -          'module_spec'                       : [MDefs['SPEC']] if 'SPEC' in MDefs else [],
> > -          'module_uefi_hii_resource_section'  : [MDefs['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs else [],
> > -          'module_uni_file'                   : [MDefs['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs else [],
> > -          'module_arch'                       : self.Arch,
> > -          'package_item'                      : [Package.MetaFile.File.replace('\\', '/') for Package in Packages],
> > -          'binary_item'                       : [],
> > -          'patchablepcd_item'                 : [],
> > -          'pcd_item'                          : [],
> > -          'protocol_item'                     : [],
> > -          'ppi_item'                          : [],
> > -          'guid_item'                         : [],
> > -          'flags_item'                        : [],
> > -          'libraryclasses_item'               : []
> > -        }
> > -
> > -        if 'MODULE_UNI_FILE' in MDefs:
> > -            UNIFile = os.path.join(self.MetaFile.Dir, MDefs['MODULE_UNI_FILE'])
> > -            if os.path.isfile(UNIFile):
> > -                shutil.copy2(UNIFile, self.OutputDir)
> > -
> > -        if self.AutoGenVersion > int(gInfSpecVersion, 0):
> > -            AsBuiltInfDict['module_inf_version'] = '0x%08x' % self.AutoGenVersion
> > -        else:
> > -            AsBuiltInfDict['module_inf_version'] = gInfSpecVersion
> > -
> > -        if DriverType:
> > -            AsBuiltInfDict['pcd_is_driver_string'].append(DriverType)
> > -
> > -        if 'UEFI_SPECIFICATION_VERSION' in self.Specification:
> > -            AsBuiltInfDict['module_uefi_specification_version'].append(self.Specification['UEFI_SPECIFICATION_VERSION'])
> > -        if 'PI_SPECIFICATION_VERSION' in self.Specification:
> > -            AsBuiltInfDict['module_pi_specification_version'].append(self.Specification['PI_SPECIFICATION_VERSION'])
> > -
> > -        OutputDir = self.OutputDir.replace('\\', '/').strip('/')
> > -        DebugDir = self.DebugDir.replace('\\', '/').strip('/')
> > -        for Item in self.CodaTargetList:
> > -            File = Item.Target.Path.replace('\\', '/').strip('/').replace(DebugDir, '').replace(OutputDir, '').strip('/')
> > -            if os.path.isabs(File):
> > -                File = File.replace('\\', '/').strip('/').replace(OutputDir, '').strip('/')
> > -            if Item.Target.Ext.lower() == '.aml':
> > -                AsBuiltInfDict['binary_item'].append('ASL|' + File)
> > -            elif Item.Target.Ext.lower() == '.acpi':
> > -                AsBuiltInfDict['binary_item'].append('ACPI|' + File)
> > -            elif Item.Target.Ext.lower() == '.efi':
> > -                AsBuiltInfDict['binary_item'].append('PE32|' + self.Name + '.efi')
> > -            else:
> > -                AsBuiltInfDict['binary_item'].append('BIN|' + File)
> > -        if not self.DepexGenerated:
> > -            DepexFile = os.path.join(self.OutputDir, self.Name + '.depex')
> > -            if os.path.exists(DepexFile):
> > -                self.DepexGenerated = True
> > -        if self.DepexGenerated:
> > -            if self.ModuleType in [SUP_MODULE_PEIM]:
> > -                AsBuiltInfDict['binary_item'].append('PEI_DEPEX|' + self.Name + '.depex')
> > -            elif self.ModuleType in [SUP_MODULE_DXE_DRIVER, SUP_MODULE_DXE_RUNTIME_DRIVER, SUP_MODULE_DXE_SAL_DRIVER, SUP_MODULE_UEFI_DRIVER]:
> > -                AsBuiltInfDict['binary_item'].append('DXE_DEPEX|' + self.Name + '.depex')
> > -            elif self.ModuleType in [SUP_MODULE_DXE_SMM_DRIVER]:
> > -                AsBuiltInfDict['binary_item'].append('SMM_DEPEX|' + self.Name + '.depex')
> > -
> > -        Bin = self._GenOffsetBin()
> > -        if Bin:
> > -            AsBuiltInfDict['binary_item'].append('BIN|%s' % Bin)
> > -
> > -        for Root, Dirs, Files in os.walk(OutputDir):
> > -            for File in Files:
> > -                if File.lower().endswith('.pdb'):
> > -                    AsBuiltInfDict['binary_item'].append('DISPOSABLE|' + File)
> > -        HeaderComments = self.Module.HeaderComments
> > -        StartPos = 0
> > -        for Index in range(len(HeaderComments)):
> > -            if HeaderComments[Index].find('@BinaryHeader') != -1:
> > -                HeaderComments[Index] = HeaderComments[Index].replace('@BinaryHeader', '@file')
> > -                StartPos = Index
> > -                break
> > -        AsBuiltInfDict['header_comments'] = '\n'.join(HeaderComments[StartPos:]).replace(':#', '://')
> > -        AsBuiltInfDict['tail_comments'] = '\n'.join(self.Module.TailComments)
> > -
> > -        GenList = [
> > -            (self.ProtocolList, self._ProtocolComments, 'protocol_item'),
> > -            (self.PpiList, self._PpiComments, 'ppi_item'),
> > -            (GuidList, self._GuidComments, 'guid_item')
> > -        ]
> > -        for Item in GenList:
> > -            for CName in Item[0]:
> > -                Comments = '\n  '.join(Item[1][CName]) if CName in Item[1] else ''
> > -                Entry = Comments + '\n  ' + CName if Comments else CName
> > -                AsBuiltInfDict[Item[2]].append(Entry)
> > -        PatchList = parsePcdInfoFromMapFile(
> > -                            os.path.join(self.OutputDir, self.Name + '.map'),
> > -                            os.path.join(self.OutputDir, self.Name + '.efi')
> > -                        )
> > -        if PatchList:
> > -            for Pcd in PatchablePcds:
> > -                TokenCName = Pcd.TokenCName
> > -                for PcdItem in GlobalData.MixedPcd:
> > -                    if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
> > -                        TokenCName = PcdItem[0]
> > -                        break
> > -                for PatchPcd in PatchList:
> > -                    if TokenCName == PatchPcd[0]:
> > -                        break
> > -                else:
> > -                    continue
> > -                PcdValue = ''
> > -                if Pcd.DatumType == 'BOOLEAN':
> > -                    BoolValue = Pcd.DefaultValue.upper()
> > -                    if BoolValue == 'TRUE':
> > -                        Pcd.DefaultValue = '1'
> > -                    elif BoolValue == 'FALSE':
> > -                        Pcd.DefaultValue = '0'
> > -
> > -                if Pcd.DatumType in TAB_PCD_NUMERIC_TYPES:
> > -                    HexFormat = '0x%02x'
> > -                    if Pcd.DatumType == TAB_UINT16:
> > -                        HexFormat = '0x%04x'
> > -                    elif Pcd.DatumType == TAB_UINT32:
> > -                        HexFormat = '0x%08x'
> > -                    elif Pcd.DatumType == TAB_UINT64:
> > -                        HexFormat = '0x%016x'
> > -                    PcdValue = HexFormat % int(Pcd.DefaultValue, 0)
> > -                else:
> > -                    if Pcd.MaxDatumSize is None or Pcd.MaxDatumSize == '':
> > -                        EdkLogger.error("build", AUTOGEN_ERROR,
> > -                                        "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd.TokenSpaceGuidCName, TokenCName)
> > -                                        )
> > -                    ArraySize = int(Pcd.MaxDatumSize, 0)
> > -                    PcdValue = Pcd.DefaultValue
> > -                    if PcdValue[0] != '{':
> > -                        Unicode = False
> > -                        if PcdValue[0] == 'L':
> > -                            Unicode = True
> > -                        PcdValue = PcdValue.lstrip('L')
> > -                        PcdValue = eval(PcdValue)
> > -                        NewValue = '{'
> > -                        for Index in range(0, len(PcdValue)):
> > -                            if Unicode:
> > -                                CharVal = ord(PcdValue[Index])
> > -                                NewValue = NewValue + '0x%02x' % (CharVal & 0x00FF) + ', ' \
> > -                                        + '0x%02x' % (CharVal >> 8) + ', '
> > -                            else:
> > -                                NewValue = NewValue + '0x%02x' % (ord(PcdValue[Index]) % 0x100) + ', '
> > -                        Padding = '0x00, '
> > -                        if Unicode:
> > -                            Padding = Padding * 2
> > -                            ArraySize = ArraySize // 2
> > -                        if ArraySize < (len(PcdValue) + 1):
> > -                            if Pcd.MaxSizeUserSet:
> > -                                EdkLogger.error("build", AUTOGEN_ERROR,
> > -                                            "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)
> > -                                            )
> > -                            else:
> > -                                ArraySize = len(PcdValue) + 1
> > -                        if ArraySize > len(PcdValue) + 1:
> > -                            NewValue = NewValue + Padding * (ArraySize - len(PcdValue) - 1)
> > -                        PcdValue = NewValue + Padding.strip().rstrip(',') + '}'
> > -                    elif len(PcdValue.split(',')) <= ArraySize:
> > -                        PcdValue = PcdValue.rstrip('}') + ', 0x00' * (ArraySize - len(PcdValue.split(',')))
> > -                        PcdValue += '}'
> > -                    else:
> > -                        if Pcd.MaxSizeUserSet:
> > -                            EdkLogger.error("build", AUTOGEN_ERROR,
> > -                                        "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)
> > -                                        )
> > -                        else:
> > -                            ArraySize = len(PcdValue) + 1
> > -                PcdItem = '%s.%s|%s|0x%X' % \
> > -                    (Pcd.TokenSpaceGuidCName, TokenCName, PcdValue, PatchPcd[1])
> > -                PcdComments = ''
> > -                if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
> > -                    PcdComments = '\n  '.join(self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName])
> > -                if PcdComments:
> > -                    PcdItem = PcdComments + '\n  ' + PcdItem
> > -                AsBuiltInfDict['patchablepcd_item'].append(PcdItem)
> > -
> > -        for Pcd in Pcds + VfrPcds:
> > -            PcdCommentList = []
> > -            HiiInfo = ''
> > -            TokenCName = Pcd.TokenCName
> > -            for PcdItem in GlobalData.MixedPcd:
> > -                if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
> > -                    TokenCName = PcdItem[0]
> > -                    break
> > -            if Pcd.Type == TAB_PCDS_DYNAMIC_EX_HII:
> > -                for SkuName in Pcd.SkuInfoList:
> > -                    SkuInfo = Pcd.SkuInfoList[SkuName]
> > -                    HiiInfo = '## %s|%s|%s' % (SkuInfo.VariableName, SkuInfo.VariableGuid, SkuInfo.VariableOffset)
> > -                    break
> > -            if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
> > -                PcdCommentList = self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName][:]
> > -            if HiiInfo:
> > -                UsageIndex = -1
> > -                UsageStr = ''
> > -                for Index, Comment in enumerate(PcdCommentList):
> > -                    for Usage in UsageList:
> > -                        if Comment.find(Usage) != -1:
> > -                            UsageStr = Usage
> > -                            UsageIndex = Index
> > -                            break
> > -                if UsageIndex != -1:
> > -                    PcdCommentList[UsageIndex] = '## %s %s %s' % (UsageStr, HiiInfo, PcdCommentList[UsageIndex].replace(UsageStr, ''))
> > -                else:
> > -                    PcdCommentList.append('## UNDEFINED ' + HiiInfo)
> > -            PcdComments = '\n  '.join(PcdCommentList)
> > -            PcdEntry = Pcd.TokenSpaceGuidCName + '.' + TokenCName
> > -            if PcdComments:
> > -                PcdEntry = PcdComments + '\n  ' + PcdEntry
> > -            AsBuiltInfDict['pcd_item'].append(PcdEntry)
> > -        for Item in self.BuildOption:
> > -            if 'FLAGS' in self.BuildOption[Item]:
> > -                AsBuiltInfDict['flags_item'].append('%s:%s_%s_%s_%s_FLAGS = %s' % (self.ToolChainFamily, self.BuildTarget, self.ToolChain, self.Arch, Item, self.BuildOption[Item]['FLAGS'].strip()))
> > -
> > -        # Generated LibraryClasses section in comments.
> > -        for Library in self.LibraryAutoGenList:
> > -            AsBuiltInfDict['libraryclasses_item'].append(Library.MetaFile.File.replace('\\', '/'))
> > -
> > -        # Generated UserExtensions TianoCore section.
> > -        # All tianocore user extensions are copied.
> > -        UserExtStr = ''
> > -        for TianoCore in self._GetTianoCoreUserExtensionList():
> > -            UserExtStr += '\n'.join(TianoCore)
> > -            ExtensionFile = os.path.join(self.MetaFile.Dir, TianoCore[1])
> > -            if os.path.isfile(ExtensionFile):
> > -                shutil.copy2(ExtensionFile, self.OutputDir)
> > -        AsBuiltInfDict['userextension_tianocore_item'] = UserExtStr
> > -
> > -        # Generated depex expression section in comments.
> > -        DepexExpression = self._GetDepexExpresionString()
> > -        AsBuiltInfDict['depexsection_item'] = DepexExpression if DepexExpression else ''
> > -
> > -        AsBuiltInf = TemplateString()
> > -        AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))
> > -
> > -        SaveFileOnChange(os.path.join(self.OutputDir, self.Name + '.inf'), str(AsBuiltInf), False)
> > -
> > -        self.IsAsBuiltInfCreated = True
> > -
> > -    def CopyModuleToCache(self):
> > -        FileDir = path.join(GlobalData.gBinCacheDest, self.PlatformInfo.OutputDir, self.BuildTarget + "_" + self.ToolChain, self.Arch, self.SourceDir, self.MetaFile.BaseName)
> > -        CreateDirectory (FileDir)
> > -        HashFile = path.join(self.BuildDir, self.Name + '.hash')
> > -        if os.path.exists(HashFile):
> > -            CopyFileOnChange(HashFile, FileDir)
> > -        ModuleFile = path.join(self.OutputDir, self.Name + '.inf')
> > -        if os.path.exists(ModuleFile):
> > -            CopyFileOnChange(ModuleFile, FileDir)
> > -
> > -        if not self.OutputFile:
> > -            Ma = self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
> > -            self.OutputFile = Ma.Binaries
> > -
> > -        for File in self.OutputFile:
> > -            File = str(File)
> > -            if not os.path.isabs(File):
> > -                File = os.path.join(self.OutputDir, File)
> > -            if os.path.exists(File):
> > -                sub_dir = os.path.relpath(File, self.OutputDir)
> > -                destination_file = os.path.join(FileDir, sub_dir)
> > -                destination_dir = os.path.dirname(destination_file)
> > -                CreateDirectory(destination_dir)
> > -                CopyFileOnChange(File, destination_dir)
> > -
> > -    def AttemptModuleCacheCopy(self):
> > -        # If library or Module is binary do not skip by hash
> > -        if self.IsBinaryModule:
> > -            return False
> > -        # .inc is contains binary information so do not skip by hash as well
> > -        for f_ext in self.SourceFileList:
> > -            if '.inc' in str(f_ext):
> > -                return False
> > -        FileDir = path.join(GlobalData.gBinCacheSource, self.PlatformInfo.OutputDir, self.BuildTarget + "_" + self.ToolChain, self.Arch, self.SourceDir, self.MetaFile.BaseName)
> > -        HashFile = path.join(FileDir, self.Name + '.hash')
> > -        if os.path.exists(HashFile):
> > -            f = open(HashFile, 'r')
> > -            CacheHash = f.read()
> > -            f.close()
> > -            self.GenModuleHash()
> > -            if GlobalData.gModuleHash[self.Arch][self.Name]:
> > -                if CacheHash == GlobalData.gModuleHash[self.Arch][self.Name]:
> > -                    for root, dir, files in os.walk(FileDir):
> > -                        for f in files:
> > -                            if self.Name + '.hash' in f:
> > -                                CopyFileOnChange(HashFile, self.BuildDir)
> > -                            else:
> > -                                File = path.join(root, f)
> > -                                sub_dir = os.path.relpath(File, FileDir)
> > -                                destination_file = os.path.join(self.OutputDir, sub_dir)
> > -                                destination_dir = os.path.dirname(destination_file)
> > -                                CreateDirectory(destination_dir)
> > -                                CopyFileOnChange(File, destination_dir)
> > -                    if self.Name == "PcdPeim" or self.Name == "PcdDxe":
> > -                        CreatePcdDatabaseCode(self, TemplateString(), TemplateString())
> > -                    return True
> > -        return False
> > -
> > -    ## Create makefile for the module and its dependent libraries
> > -    #
> > -    #   @param      CreateLibraryMakeFile   Flag indicating if or not the makefiles of
> > -    #                                       dependent libraries will be created
> > -    #
> > -    @cached_class_function
> > -    def CreateMakeFile(self, CreateLibraryMakeFile=True, GenFfsList = []):
> > -        # nest this function inside its only caller.
> > -        def CreateTimeStamp():
> > -            FileSet = {self.MetaFile.Path}
> > -
> > -            for SourceFile in self.Module.Sources:
> > -                FileSet.add (SourceFile.Path)
> > -
> > -            for Lib in self.DependentLibraryList:
> > -                FileSet.add (Lib.MetaFile.Path)
> > -
> > -            for f in self.AutoGenDepSet:
> > -                FileSet.add (f.Path)
> > -
> > -            if os.path.exists (self.TimeStampPath):
> > -                os.remove (self.TimeStampPath)
> > -            with open(self.TimeStampPath, 'w+') as file:
> > -                for f in FileSet:
> > -                    print(f, file=file)
> > -
> > -        # Ignore generating makefile when it is a binary module
> > -        if self.IsBinaryModule:
> > -            return
> > -
> > -        self.GenFfsList = GenFfsList
> > -        if not self.IsLibrary and CreateLibraryMakeFile:
> > -            for LibraryAutoGen in self.LibraryAutoGenList:
> > -                LibraryAutoGen.CreateMakeFile()
> > -
> > -        # Don't enable if hash feature enabled, CanSkip uses timestamps to determine build skipping
> > -        if not GlobalData.gUseHashCache and self.CanSkip():
> > -            return
> > -
> > -        if len(self.CustomMakefile) == 0:
> > -            Makefile = GenMake.ModuleMakefile(self)
> > -        else:
> > -            Makefile = GenMake.CustomMakefile(self)
> > -        if Makefile.Generate():
> > -            EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %
> > -                            (self.Name, self.Arch))
> > -        else:
> > -            EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %
> > -                            (self.Name, self.Arch))
> > -
> > -        CreateTimeStamp()
> > -
> > -    def CopyBinaryFiles(self):
> > -        for File in self.Module.Binaries:
> > -            SrcPath = File.Path
> > -            DstPath = os.path.join(self.OutputDir, os.path.basename(SrcPath))
> > -            CopyLongFilePath(SrcPath, DstPath)
> > -    ## Create autogen code for the module and its dependent libraries
> > -    #
> > -    #   @param      CreateLibraryCodeFile   Flag indicating if or not the code of
> > -    #                                       dependent libraries will be created
> > -    #
> > -    def CreateCodeFile(self, CreateLibraryCodeFile=True):
> > -        if self.IsCodeFileCreated:
> > -            return
> > -
> > -        # Need to generate PcdDatabase even PcdDriver is binarymodule
> > -        if self.IsBinaryModule and self.PcdIsDriver != '':
> > -            CreatePcdDatabaseCode(self, TemplateString(), TemplateString())
> > -            return
> > -        if self.IsBinaryModule:
> > -            if self.IsLibrary:
> > -                self.CopyBinaryFiles()
> > -            return
> > -
> > -        if not self.IsLibrary and CreateLibraryCodeFile:
> > -            for LibraryAutoGen in self.LibraryAutoGenList:
> > -                LibraryAutoGen.CreateCodeFile()
> > -
> > -        # Don't enable if hash feature enabled, CanSkip uses timestamps to determine build skipping
> > -        if not GlobalData.gUseHashCache and self.CanSkip():
> > -            return
> > -
> > -        AutoGenList = []
> > -        IgoredAutoGenList = []
> > -
> > -        for File in self.AutoGenFileList:
> > -            if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):
> > -                AutoGenList.append(str(File))
> > -            else:
> > -                IgoredAutoGenList.append(str(File))
> > -
> > -
> > -        for ModuleType in self.DepexList:
> > -            # Ignore empty [depex] section or [depex] section for SUP_MODULE_USER_DEFINED module
> > -            if len(self.DepexList[ModuleType]) == 0 or ModuleType == SUP_MODULE_USER_DEFINED or ModuleType == SUP_MODULE_HOST_APPLICATION:
> > -                continue
> > -
> > -            Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
> > -            DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
> > -
> > -            if len(Dpx.PostfixNotation) != 0:
> > -                self.DepexGenerated = True
> > -
> > -            if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
> > -                AutoGenList.append(str(DpxFile))
> > -            else:
> > -                IgoredAutoGenList.append(str(DpxFile))
> > -
> > -        if IgoredAutoGenList == []:
> > -            EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %
> > -                            (" ".join(AutoGenList), self.Name, self.Arch))
> > -        elif AutoGenList == []:
> > -            EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %
> > -                            (" ".join(IgoredAutoGenList), self.Name, self.Arch))
> > -        else:
> > -            EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %
> > -                            (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
> > -
> > -        self.IsCodeFileCreated = True
> > -        return AutoGenList
> > -
> > -    ## Summarize the ModuleAutoGen objects of all libraries used by this module
> > -    @cached_property
> > -    def LibraryAutoGenList(self):
> > -        RetVal = []
> > -        for Library in self.DependentLibraryList:
> > -            La = ModuleAutoGen(
> > -                        self.Workspace,
> > -                        Library.MetaFile,
> > -                        self.BuildTarget,
> > -                        self.ToolChain,
> > -                        self.Arch,
> > -                        self.PlatformInfo.MetaFile
> > -                        )
> > -            if La not in RetVal:
> > -                RetVal.append(La)
> > -                for Lib in La.CodaTargetList:
> > -                    self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)
> > -        return RetVal
> > -
> > -    def GenModuleHash(self):
> > -        # Initialize a dictionary for each arch type
> > -        if self.Arch not in GlobalData.gModuleHash:
> > -            GlobalData.gModuleHash[self.Arch] = {}
> > -
> > -        # Early exit if module or library has been hashed and is in memory
> > -        if self.Name in GlobalData.gModuleHash[self.Arch]:
> > -            return GlobalData.gModuleHash[self.Arch][self.Name].encode('utf-8')
> > -
> > -        # Initialze hash object
> > -        m = hashlib.md5()
> > -
> > -        # Add Platform level hash
> > -        m.update(GlobalData.gPlatformHash.encode('utf-8'))
> > -
> > -        # Add Package level hash
> > -        if self.DependentPackageList:
> > -            for Pkg in sorted(self.DependentPackageList, key=lambda x: x.PackageName):
> > -                if Pkg.PackageName in GlobalData.gPackageHash:
> > -                    m.update(GlobalData.gPackageHash[Pkg.PackageName].encode('utf-8'))
> > -
> > -        # Add Library hash
> > -        if self.LibraryAutoGenList:
> > -            for Lib in sorted(self.LibraryAutoGenList, key=lambda x: x.Name):
> > -                if Lib.Name not in GlobalData.gModuleHash[self.Arch]:
> > -                    Lib.GenModuleHash()
> > -                m.update(GlobalData.gModuleHash[self.Arch][Lib.Name].encode('utf-8'))
> > -
> > -        # Add Module self
> > -        f = open(str(self.MetaFile), 'rb')
> > -        Content = f.read()
> > -        f.close()
> > -        m.update(Content)
> > -
> > -        # Add Module's source files
> > -        if self.SourceFileList:
> > -            for File in sorted(self.SourceFileList, key=lambda x: str(x)):
> > -                f = open(str(File), 'rb')
> > -                Content = f.read()
> > -                f.close()
> > -                m.update(Content)
> > -
> > -        GlobalData.gModuleHash[self.Arch][self.Name] = m.hexdigest()
> > -
> > -        return GlobalData.gModuleHash[self.Arch][self.Name].encode('utf-8')
> > -
> > -    ## Decide whether we can skip the ModuleAutoGen process
> > -    def CanSkipbyHash(self):
> > -        # Hashing feature is off
> > -        if not GlobalData.gUseHashCache:
> > -            return False
> > -
> > -        # Initialize a dictionary for each arch type
> > -        if self.Arch not in GlobalData.gBuildHashSkipTracking:
> > -            GlobalData.gBuildHashSkipTracking[self.Arch] = dict()
> > -
> > -        # If library or Module is binary do not skip by hash
> > -        if self.IsBinaryModule:
> > -            return False
> > -
> > -        # .inc is contains binary information so do not skip by hash as well
> > -        for f_ext in self.SourceFileList:
> > -            if '.inc' in str(f_ext):
> > -                return False
> > -
> > -        # Use Cache, if exists and if Module has a copy in cache
> > -        if GlobalData.gBinCacheSource and self.AttemptModuleCacheCopy():
> > -            return True
> > -
> > -        # Early exit for libraries that haven't yet finished building
> > -        HashFile = path.join(self.BuildDir, self.Name + ".hash")
> > -        if self.IsLibrary and not os.path.exists(HashFile):
> > -            return False
> > -
> > -        # Return a Boolean based on if can skip by hash, either from memory or from IO.
> > -        if self.Name not in GlobalData.gBuildHashSkipTracking[self.Arch]:
> > -            # If hashes are the same, SaveFileOnChange() will return False.
> > -            GlobalData.gBuildHashSkipTracking[self.Arch][self.Name] = not SaveFileOnChange(HashFile, self.GenModuleHash(), True)
> > -            return GlobalData.gBuildHashSkipTracking[self.Arch][self.Name]
> > -        else:
> > -            return GlobalData.gBuildHashSkipTracking[self.Arch][self.Name]
> > -
> > -    ## Decide whether we can skip the ModuleAutoGen process
> > -    #  If any source file is newer than the module than we cannot skip
> > -    #
> > -    def CanSkip(self):
> > -        if self.MakeFileDir in GlobalData.gSikpAutoGenCache:
> > -            return True
> > -        if not os.path.exists(self.TimeStampPath):
> > -            return False
> > -        #last creation time of the module
> > -        DstTimeStamp = os.stat(self.TimeStampPath)[8]
> > -
> > -        SrcTimeStamp = self.Workspace._SrcTimeStamp
> > -        if SrcTimeStamp > DstTimeStamp:
> > -            return False
> > -
> > -        with open(self.TimeStampPath,'r') as f:
> > -            for source in f:
> > -                source = source.rstrip('\n')
> > -                if not os.path.exists(source):
> > -                    return False
> > -                if source not in ModuleAutoGen.TimeDict :
> > -                    ModuleAutoGen.TimeDict[source] = os.stat(source)[8]
> > -                if ModuleAutoGen.TimeDict[source] > DstTimeStamp:
> > -                    return False
> > -        GlobalData.gSikpAutoGenCache.add(self.MakeFileDir)
> > -        return True
> > -
> > -    @cached_property
> > -    def TimeStampPath(self):
> > -        return os.path.join(self.MakeFileDir, 'AutoGenTimeStamp')
> > +    @classmethod
> > +    def Cache(cls):
> > +        return cls.__ObjectCache
> > +
> > +#
> > +# The priority list while override build option
> > +#
> > +PrioList = {"0x11111"  : 16,     #  TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
> > +            "0x01111"  : 15,     #  ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
> > +            "0x10111"  : 14,     #  TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
> > +            "0x00111"  : 13,     #  ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
> > +            "0x11011"  : 12,     #  TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
> > +            "0x01011"  : 11,     #  ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
> > +            "0x10011"  : 10,     #  TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
> > +            "0x00011"  : 9,      #  ******_*********_****_COMMANDTYPE_ATTRIBUTE
> > +            "0x11101"  : 8,      #  TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
> > +            "0x01101"  : 7,      #  ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
> > +            "0x10101"  : 6,      #  TARGET_*********_ARCH_***********_ATTRIBUTE
> > +            "0x00101"  : 5,      #  ******_*********_ARCH_***********_ATTRIBUTE
> > +            "0x11001"  : 4,      #  TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
> > +            "0x01001"  : 3,      #  ******_TOOLCHAIN_****_***********_ATTRIBUTE
> > +            "0x10001"  : 2,      #  TARGET_*********_****_***********_ATTRIBUTE
> > +            "0x00001"  : 1}      #  ******_*********_****_***********_ATTRIBUTE (Lowest)
> > +## Calculate the priority value of the build option
> > +#
> > +# @param    Key    Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
> > +#
> > +# @retval   Value  Priority value based on the priority list.
> > +#
> > +def CalculatePriorityValue(Key):
> > +    Target, ToolChain, Arch, CommandType, Attr = Key.split('_')
> > +    PriorityValue = 0x11111
> > +    if Target == TAB_STAR:
> > +        PriorityValue &= 0x01111
> > +    if ToolChain == TAB_STAR:
> > +        PriorityValue &= 0x10111
> > +    if Arch == TAB_STAR:
> > +        PriorityValue &= 0x11011
> > +    if CommandType == TAB_STAR:
> > +        PriorityValue &= 0x11101
> > +    if Attr == TAB_STAR:
> > +        PriorityValue &= 0x11110
> > +
> > +    return PrioList["0x%0.5x" % PriorityValue]
> > diff --git a/BaseTools/Source/Python/AutoGen/DataPipe.py b/BaseTools/Source/Python/AutoGen/DataPipe.py
> > new file mode 100644
> > index 000000000000..5bcc39bd380d
> > --- /dev/null
> > +++ b/BaseTools/Source/Python/AutoGen/DataPipe.py
> > @@ -0,0 +1,147 @@
> > +## @file
> > +# Create makefile for MS nmake and GNU make
> > +#
> > +# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +from __future__ import absolute_import
> > +from Workspace.WorkspaceDatabase import BuildDB
> > +from Workspace.WorkspaceCommon import GetModuleLibInstances
> > +import Common.GlobalData as GlobalData
> > +import os
> > +import pickle
> > +from pickle import HIGHEST_PROTOCOL
> > +
> > +class PCD_DATA():
> > +    def __init__(self,TokenCName,TokenSpaceGuidCName,Type,DatumType,SkuInfoList,DefaultValue,
> > +                 MaxDatumSize,UserDefinedDefaultStoresFlag,validateranges,
> > +                 validlists,expressions,CustomAttribute,TokenValue):
> > +        self.TokenCName = TokenCName
> > +        self.TokenSpaceGuidCName = TokenSpaceGuidCName
> > +        self.Type = Type
> > +        self.DatumType = DatumType
> > +        self.SkuInfoList = SkuInfoList
> > +        self.DefaultValue = DefaultValue
> > +        self.MaxDatumSize = MaxDatumSize
> > +        self.UserDefinedDefaultStoresFlag = UserDefinedDefaultStoresFlag
> > +        self.validateranges = validateranges
> > +        self.validlists = validlists
> > +        self.expressions = expressions
> > +        self.CustomAttribute = CustomAttribute
> > +        self.TokenValue = TokenValue
> > +
> > +class DataPipe(object):
> > +    def __init__(self, BuildDir=None):
> > +        self.data_container = {}
> > +        self.BuildDir = BuildDir
> > +
> > +class MemoryDataPipe(DataPipe):
> > +
> > +    def Get(self,key):
> > +        return self.data_container.get(key)
> > +
> > +    def dump(self,file_path):
> > +        with open(file_path,'wb') as fd:
> > +            pickle.dump(self.data_container,fd,pickle.HIGHEST_PROTOCOL)
> > +
> > +    def load(self,file_path):
> > +        with open(file_path,'rb') as fd:
> > +            self.data_container = pickle.load(fd)
> > +
> > +    @property
> > +    def DataContainer(self):
> > +        return self.data_container
> > +    @DataContainer.setter
> > +    def DataContainer(self,data):
> > +        self.data_container.update(data)
> > +
> > +    def FillData(self,PlatformInfo):
> > +        #Platform Pcds
> > +        self.DataContainer = {
> > +            "PLA_PCD" : [PCD_DATA(
> > +            pcd.TokenCName,pcd.TokenSpaceGuidCName,pcd.Type,
> > +            pcd.DatumType,pcd.SkuInfoList,pcd.DefaultValue,
> > +            pcd.MaxDatumSize,pcd.UserDefinedDefaultStoresFlag,pcd.validateranges,
> > +                 pcd.validlists,pcd.expressions,pcd.CustomAttribute,pcd.TokenValue)
> > +            for pcd in PlatformInfo.Platform.Pcds.values()]
> > +            }
> > +
> > +        #Platform Module Pcds
> > +        ModulePcds = {}
> > +        for m in PlatformInfo.Platform.Modules:
> > +            m_pcds =  PlatformInfo.Platform.Modules[m].Pcds
> > +            if m_pcds:
> > +                ModulePcds[(m.File,m.Root)] = [PCD_DATA(
> > +            pcd.TokenCName,pcd.TokenSpaceGuidCName,pcd.Type,
> > +            pcd.DatumType,pcd.SkuInfoList,pcd.DefaultValue,
> > +            pcd.MaxDatumSize,pcd.UserDefinedDefaultStoresFlag,pcd.validateranges,
> > +                 pcd.validlists,pcd.expressions,pcd.CustomAttribute,pcd.TokenValue)
> > +            for pcd in PlatformInfo.Platform.Modules[m].Pcds.values()]
> > +
> > +
> > +        self.DataContainer = {"MOL_PCDS":ModulePcds}
> > +
> > +        #Module's Library Instance
> > +        ModuleLibs = {}
> > +        for m in PlatformInfo.Platform.Modules:
> > +            module_obj = BuildDB.BuildObject[m,PlatformInfo.Arch,PlatformInfo.BuildTarget,PlatformInfo.ToolChain]
> > +            Libs = GetModuleLibInstances(module_obj, PlatformInfo.Platform, BuildDB.BuildObject, PlatformInfo.Arch,PlatformInfo.BuildTarget,PlatformInfo.ToolChain)
> > +            ModuleLibs[(m.File,m.Root,module_obj.Arch)] = [(l.MetaFile.File,l.MetaFile.Root,l.Arch) for l in Libs]
> > +        self.DataContainer = {"DEPS":ModuleLibs}
> > +
> > +        #Platform BuildOptions
> > +
> > +        platform_build_opt =  PlatformInfo.EdkIIBuildOption
> > +
> > +        ToolDefinition = PlatformInfo.ToolDefinition
> > +        module_build_opt = {}
> > +        for m in PlatformInfo.Platform.Modules:
> > +            ModuleTypeOptions, PlatformModuleOptions = PlatformInfo.GetGlobalBuildOptions(BuildDB.BuildObject[m,PlatformInfo.Arch,PlatformInfo.BuildTarget,PlatformInfo.ToolChain])
> > +            if ModuleTypeOptions or PlatformModuleOptions:
> > +                module_build_opt.update({(m.File,m.Root): {"ModuleTypeOptions":ModuleTypeOptions, "PlatformModuleOptions":PlatformModuleOptions}})
> > +
> > +        self.DataContainer = {"PLA_BO":platform_build_opt,
> > +                              "TOOLDEF":ToolDefinition,
> > +                              "MOL_BO":module_build_opt
> > +                              }
> > +
> > +
> > +
> > +        #Platform Info
> > +        PInfo = {
> > +            "WorkspaceDir":PlatformInfo.Workspace.WorkspaceDir,
> > +            "Target":PlatformInfo.BuildTarget,
> > +            "ToolChain":PlatformInfo.Workspace.ToolChain,
> > +            "BuildRuleFile":PlatformInfo.BuildRule,
> > +            "Arch": PlatformInfo.Arch,
> > +            "ArchList":PlatformInfo.Workspace.ArchList,
> > +            "ActivePlatform":PlatformInfo.MetaFile
> > +            }
> > +        self.DataContainer = {'P_Info':PInfo}
> > +
> > +        self.DataContainer = {'M_Name':PlatformInfo.UniqueBaseName}
> > +
> > +        self.DataContainer = {"ToolChainFamily": PlatformInfo.ToolChainFamily}
> > +
> > +        self.DataContainer = {"BuildRuleFamily": PlatformInfo.BuildRuleFamily}
> > +
> > +        self.DataContainer = {"MixedPcd":GlobalData.MixedPcd}
> > +
> > +        self.DataContainer = {"BuildOptPcd":GlobalData.BuildOptionPcd}
> > +
> > +        self.DataContainer = {"BuildCommand": PlatformInfo.BuildCommand}
> > +
> > +        self.DataContainer = {"AsBuildModuleList": PlatformInfo._AsBuildModuleList}
> > +
> > +        self.DataContainer = {"G_defines": GlobalData.gGlobalDefines}
> > +
> > +        self.DataContainer = {"CL_defines": GlobalData.gCommandLineDefines}
> > +
> > +        self.DataContainer = {"Env_Var": {k:v for k, v in os.environ.items()}}
> > +
> > +        self.DataContainer = {"PackageList": [(dec.MetaFile,dec.Arch) for dec in PlatformInfo.PackageList]}
> > +
> > +        self.DataContainer = {"GuidDict": PlatformInfo.Platform._GuidDict}
> > +
> > +        self.DataContainer = {"FdfParser": True if GlobalData.gFdfParser else False}
> > +
> > diff --git a/BaseTools/Source/Python/AutoGen/GenC.py b/BaseTools/Source/Python/AutoGen/GenC.py
> > index 4cb776206e90..4c3f4e3e55ae 100644
> > --- a/BaseTools/Source/Python/AutoGen/GenC.py
> > +++ b/BaseTools/Source/Python/AutoGen/GenC.py
> > @@ -1627,11 +1627,11 @@ def CreatePcdCode(Info, AutoGenC, AutoGenH):
> >      TokenSpaceList = []
> >      for Pcd in Info.ModulePcdList:
> >          if Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET and Pcd.TokenSpaceGuidCName not in TokenSpaceList:
> >              TokenSpaceList.append(Pcd.TokenSpaceGuidCName)
> >
> > -    SkuMgr = Info.Workspace.Platform.SkuIdMgr
> > +    SkuMgr = Info.PlatformInfo.Platform.SkuIdMgr
> >      AutoGenH.Append("\n// Definition of SkuId Array\n")
> >      AutoGenH.Append("extern UINT64 _gPcd_SkuId_Array[];\n")
> >      # Add extern declarations to AutoGen.h if one or more Token Space GUIDs were found
> >      if TokenSpaceList:
> >          AutoGenH.Append("\n// Definition of PCD Token Space GUIDs used in this module\n\n")
> > diff --git a/BaseTools/Source/Python/AutoGen/ModuleAutoGen.py b/BaseTools/Source/Python/AutoGen/ModuleAutoGen.py
> > new file mode 100644
> > index 000000000000..d19c03862094
> > --- /dev/null
> > +++ b/BaseTools/Source/Python/AutoGen/ModuleAutoGen.py
> > @@ -0,0 +1,1908 @@
> > +## @file
> > +# Create makefile for MS nmake and GNU make
> > +#
> > +# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +from __future__ import absolute_import
> > +from AutoGen.AutoGen import AutoGen
> > +from Common.LongFilePathSupport import CopyLongFilePath
> > +from Common.BuildToolError import *
> > +from Common.DataType import *
> > +from Common.Misc import *
> > +from Common.StringUtils import NormPath,GetSplitList
> > +from collections import defaultdict
> > +from Workspace.WorkspaceCommon import OrderedListDict
> > +import os.path as path
> > +import copy
> > +import hashlib
> > +from . import InfSectionParser
> > +from . import GenC
> > +from . import GenMake
> > +from . import GenDepex
> > +from io import BytesIO
> > +from GenPatchPcdTable.GenPatchPcdTable import parsePcdInfoFromMapFile
> > +from Workspace.MetaFileCommentParser import UsageList
> > +from .GenPcdDb import CreatePcdDatabaseCode
> > +from Common.caching import cached_class_function
> > +from AutoGen.ModuleAutoGenHelper import PlatformInfo,WorkSpaceInfo
> > +
> > +## Mapping Makefile type
> > +gMakeTypeMap = {TAB_COMPILER_MSFT:"nmake", "GCC":"gmake"}
> > +#
> > +# Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
> > +# is the former use /I , the Latter used -I to specify include directories
> > +#
> > +gBuildOptIncludePatternMsft = re.compile(r"(?:.*?)/I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)
> > +gBuildOptIncludePatternOther = re.compile(r"(?:.*?)-I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)
> > +
> > +## default file name for AutoGen
> > +gAutoGenCodeFileName = "AutoGen.c"
> > +gAutoGenHeaderFileName = "AutoGen.h"
> > +gAutoGenStringFileName = "%(module_name)sStrDefs.h"
> > +gAutoGenStringFormFileName = "%(module_name)sStrDefs.hpk"
> > +gAutoGenDepexFileName = "%(module_name)s.depex"
> > +gAutoGenImageDefFileName = "%(module_name)sImgDefs.h"
> > +gAutoGenIdfFileName = "%(module_name)sIdf.hpk"
> > +gInfSpecVersion = "0x00010017"
> > +
> > +#
> > +# Match name = variable
> > +#
> > +gEfiVarStoreNamePattern = re.compile("\s*name\s*=\s*(\w+)")
> > +#
> > +# The format of guid in efivarstore statement likes following and must be correct:
> > +# guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
> > +#
> > +gEfiVarStoreGuidPattern = re.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
> > +
> > +#
> > +# Template string to generic AsBuilt INF
> > +#
> > +gAsBuiltInfHeaderString = TemplateString("""${header_comments}
> > +
> > +# DO NOT EDIT
> > +# FILE auto-generated
> > +
> > +[Defines]
> > +  INF_VERSION                = ${module_inf_version}
> > +  BASE_NAME                  = ${module_name}
> > +  FILE_GUID                  = ${module_guid}
> > +  MODULE_TYPE                = ${module_module_type}${BEGIN}
> > +  VERSION_STRING             = ${module_version_string}${END}${BEGIN}
> > +  PCD_IS_DRIVER              = ${pcd_is_driver_string}${END}${BEGIN}
> > +  UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
> > +  PI_SPECIFICATION_VERSION   = ${module_pi_specification_version}${END}${BEGIN}
> > +  ENTRY_POINT                = ${module_entry_point}${END}${BEGIN}
> > +  UNLOAD_IMAGE               = ${module_unload_image}${END}${BEGIN}
> > +  CONSTRUCTOR                = ${module_constructor}${END}${BEGIN}
> > +  DESTRUCTOR                 = ${module_destructor}${END}${BEGIN}
> > +  SHADOW                     = ${module_shadow}${END}${BEGIN}
> > +  PCI_VENDOR_ID              = ${module_pci_vendor_id}${END}${BEGIN}
> > +  PCI_DEVICE_ID              = ${module_pci_device_id}${END}${BEGIN}
> > +  PCI_CLASS_CODE             = ${module_pci_class_code}${END}${BEGIN}
> > +  PCI_REVISION               = ${module_pci_revision}${END}${BEGIN}
> > +  BUILD_NUMBER               = ${module_build_number}${END}${BEGIN}
> > +  SPEC                       = ${module_spec}${END}${BEGIN}
> > +  UEFI_HII_RESOURCE_SECTION  = ${module_uefi_hii_resource_section}${END}${BEGIN}
> > +  MODULE_UNI_FILE            = ${module_uni_file}${END}
> > +
> > +[Packages.${module_arch}]${BEGIN}
> > +  ${package_item}${END}
> > +
> > +[Binaries.${module_arch}]${BEGIN}
> > +  ${binary_item}${END}
> > +
> > +[PatchPcd.${module_arch}]${BEGIN}
> > +  ${patchablepcd_item}
> > +${END}
> > +
> > +[Protocols.${module_arch}]${BEGIN}
> > +  ${protocol_item}
> > +${END}
> > +
> > +[Ppis.${module_arch}]${BEGIN}
> > +  ${ppi_item}
> > +${END}
> > +
> > +[Guids.${module_arch}]${BEGIN}
> > +  ${guid_item}
> > +${END}
> > +
> > +[PcdEx.${module_arch}]${BEGIN}
> > +  ${pcd_item}
> > +${END}
> > +
> > +[LibraryClasses.${module_arch}]
> > +## @LIB_INSTANCES${BEGIN}
> > +#  ${libraryclasses_item}${END}
> > +
> > +${depexsection_item}
> > +
> > +${userextension_tianocore_item}
> > +
> > +${tail_comments}
> > +
> > +[BuildOptions.${module_arch}]
> > +## @AsBuilt${BEGIN}
> > +##   ${flags_item}${END}
> > +""")
> > +#
> > +# extend lists contained in a dictionary with lists stored in another dictionary
> > +# if CopyToDict is not derived from DefaultDict(list) then this may raise exception
> > +#
> > +def ExtendCopyDictionaryLists(CopyToDict, CopyFromDict):
> > +    for Key in CopyFromDict:
> > +        CopyToDict[Key].extend(CopyFromDict[Key])
> > +
> > +# Create a directory specified by a set of path elements and return the full path
> > +def _MakeDir(PathList):
> > +    RetVal = path.join(*PathList)
> > +    CreateDirectory(RetVal)
> > +    return RetVal
> > +
> > +#
> > +# Convert string to C format array
> > +#
> > +def _ConvertStringToByteArray(Value):
> > +    Value = Value.strip()
> > +    if not Value:
> > +        return None
> > +    if Value[0] == '{':
> > +        if not Value.endswith('}'):
> > +            return None
> > +        Value = Value.replace(' ', '').replace('{', '').replace('}', '')
> > +        ValFields = Value.split(',')
> > +        try:
> > +            for Index in range(len(ValFields)):
> > +                ValFields[Index] = str(int(ValFields[Index], 0))
> > +        except ValueError:
> > +            return None
> > +        Value = '{' + ','.join(ValFields) + '}'
> > +        return Value
> > +
> > +    Unicode = False
> > +    if Value.startswith('L"'):
> > +        if not Value.endswith('"'):
> > +            return None
> > +        Value = Value[1:]
> > +        Unicode = True
> > +    elif not Value.startswith('"') or not Value.endswith('"'):
> > +        return None
> > +
> > +    Value = eval(Value)         # translate escape character
> > +    NewValue = '{'
> > +    for Index in range(0, len(Value)):
> > +        if Unicode:
> > +            NewValue = NewValue + str(ord(Value[Index]) % 0x10000) + ','
> > +        else:
> > +            NewValue = NewValue + str(ord(Value[Index]) % 0x100) + ','
> > +    Value = NewValue + '0}'
> > +    return Value
> > +
> > +## ModuleAutoGen class
> > +#
> > +# This class encapsules the AutoGen behaviors for the build tools. In addition to
> > +# the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
> > +# to the [depex] section in module's inf file.
> > +#
> > +class ModuleAutoGen(AutoGen):
> > +    # call super().__init__ then call the worker function with different parameter count
> > +    def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
> > +        if not hasattr(self, "_Init"):
> > +            self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args)
> > +            self._Init = True
> > +
> > +    ## Cache the timestamps of metafiles of every module in a class attribute
> > +    #
> > +    TimeDict = {}
> > +
> > +    def __new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
> > +#         check if this module is employed by active platform
> > +        if not PlatformInfo(Workspace, args[0], Target, Toolchain, Arch,args[-1]).ValidModule(MetaFile):
> > +            EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \
> > +                              % (MetaFile, Arch))
> > +            return None
> > +        return super(ModuleAutoGen, cls).__new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)
> > +
> > +    ## Initialize ModuleAutoGen
> > +    #
> > +    #   @param      Workspace           EdkIIWorkspaceBuild object
> > +    #   @param      ModuleFile          The path of module file
> > +    #   @param      Target              Build target (DEBUG, RELEASE)
> > +    #   @param      Toolchain           Name of tool chain
> > +    #   @param      Arch                The arch the module supports
> > +    #   @param      PlatformFile        Platform meta-file
> > +    #
> > +    def _InitWorker(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile,DataPipe):
> > +        EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))
> > +        GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)
> > +
> > +        self.Workspace = None
> > +        self.WorkspaceDir = ""
> > +        self.PlatformInfo = None
> > +        self.DataPipe = DataPipe
> > +        self.__init_platform_info__()
> > +        self.MetaFile = ModuleFile
> > +        self.SourceDir = self.MetaFile.SubDir
> > +        self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir)
> > +
> > +        self.ToolChain = Toolchain
> > +        self.BuildTarget = Target
> > +        self.Arch = Arch
> > +        self.ToolChainFamily = self.PlatformInfo.ToolChainFamily
> > +        self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily
> > +
> > +        self.IsCodeFileCreated = False
> > +        self.IsAsBuiltInfCreated = False
> > +        self.DepexGenerated = False
> > +
> > +        self.BuildDatabase = self.Workspace.BuildDatabase
> > +        self.BuildRuleOrder = None
> > +        self.BuildTime      = 0
> > +
> > +        self._GuidComments = OrderedListDict()
> > +        self._ProtocolComments = OrderedListDict()
> > +        self._PpiComments = OrderedListDict()
> > +        self._BuildTargets            = None
> > +        self._IntroBuildTargetList    = None
> > +        self._FinalBuildTargetList    = None
> > +        self._FileTypes               = None
> > +
> > +        self.AutoGenDepSet = set()
> > +        self.ReferenceModules = []
> > +        self.ConstPcd                  = {}
> > +
> > +    def __init_platform_info__(self):
> > +        pinfo = self.DataPipe.Get("P_Info")
> > +        self.Workspace = WorkSpaceInfo(pinfo.get("WorkspaceDir"),pinfo.get("ActivePlatform"),pinfo.get("Target"),pinfo.get("ToolChain"),pinfo.get("ArchList"))
> > +        self.WorkspaceDir = pinfo.get("WorkspaceDir")
> > +        self.PlatformInfo = PlatformInfo(self.Workspace,pinfo.get("ActivePlatform"),pinfo.get("Target"),pinfo.get("ToolChain"),pinfo.get("Arch"),self.DataPipe)
> > +    ## hash() operator of ModuleAutoGen
> > +    #
> > +    #  The module file path and arch string will be used to represent
> > +    #  hash value of this object
> > +    #
> > +    #   @retval   int Hash value of the module file path and arch
> > +    #
> > +    @cached_class_function
> > +    def __hash__(self):
> > +        return hash((self.MetaFile, self.Arch))
> > +    def __repr__(self):
> > +        return "%s [%s]" % (self.MetaFile, self.Arch)
> > +
> > +    # Get FixedAtBuild Pcds of this Module
> > +    @cached_property
> > +    def FixedAtBuildPcds(self):
> > +        RetVal = []
> > +        for Pcd in self.ModulePcdList:
> > +            if Pcd.Type != TAB_PCDS_FIXED_AT_BUILD:
> > +                continue
> > +            if Pcd not in RetVal:
> > +                RetVal.append(Pcd)
> > +        return RetVal
> > +
> > +    @cached_property
> > +    def FixedVoidTypePcds(self):
> > +        RetVal = {}
> > +        for Pcd in self.FixedAtBuildPcds:
> > +            if Pcd.DatumType == TAB_VOID:
> > +                if '.'.join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName)) not in RetVal:
> > +                    RetVal['.'.join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))] = Pcd.DefaultValue
> > +        return RetVal
> > +
> > +    @property
> > +    def UniqueBaseName(self):
> > +        ModuleNames = self.DataPipe.Get("M_Name")
> > +        if not ModuleNames:
> > +            return self.Name
> > +        return ModuleNames.get(self.Name,self.Name)
> > +
> > +    # Macros could be used in build_rule.txt (also Makefile)
> > +    @cached_property
> > +    def Macros(self):
> > +        return OrderedDict((
> > +            ("WORKSPACE" ,self.WorkspaceDir),
> > +            ("MODULE_NAME" ,self.Name),
> > +            ("MODULE_NAME_GUID" ,self.UniqueBaseName),
> > +            ("MODULE_GUID" ,self.Guid),
> > +            ("MODULE_VERSION" ,self.Version),
> > +            ("MODULE_TYPE" ,self.ModuleType),
> > +            ("MODULE_FILE" ,str(self.MetaFile)),
> > +            ("MODULE_FILE_BASE_NAME" ,self.MetaFile.BaseName),
> > +            ("MODULE_RELATIVE_DIR" ,self.SourceDir),
> > +            ("MODULE_DIR" ,self.SourceDir),
> > +            ("BASE_NAME" ,self.Name),
> > +            ("ARCH" ,self.Arch),
> > +            ("TOOLCHAIN" ,self.ToolChain),
> > +            ("TOOLCHAIN_TAG" ,self.ToolChain),
> > +            ("TOOL_CHAIN_TAG" ,self.ToolChain),
> > +            ("TARGET" ,self.BuildTarget),
> > +            ("BUILD_DIR" ,self.PlatformInfo.BuildDir),
> > +            ("BIN_DIR" ,os.path.join(self.PlatformInfo.BuildDir, self.Arch)),
> > +            ("LIB_DIR" ,os.path.join(self.PlatformInfo.BuildDir, self.Arch)),
> > +            ("MODULE_BUILD_DIR" ,self.BuildDir),
> > +            ("OUTPUT_DIR" ,self.OutputDir),
> > +            ("DEBUG_DIR" ,self.DebugDir),
> > +            ("DEST_DIR_OUTPUT" ,self.OutputDir),
> > +            ("DEST_DIR_DEBUG" ,self.DebugDir),
> > +            ("PLATFORM_NAME" ,self.PlatformInfo.Name),
> > +            ("PLATFORM_GUID" ,self.PlatformInfo.Guid),
> > +            ("PLATFORM_VERSION" ,self.PlatformInfo.Version),
> > +            ("PLATFORM_RELATIVE_DIR" ,self.PlatformInfo.SourceDir),
> > +            ("PLATFORM_DIR" ,mws.join(self.WorkspaceDir, self.PlatformInfo.SourceDir)),
> > +            ("PLATFORM_OUTPUT_DIR" ,self.PlatformInfo.OutputDir),
> > +            ("FFS_OUTPUT_DIR" ,self.FfsOutputDir)
> > +            ))
> > +
> > +    ## Return the module build data object
> > +    @cached_property
> > +    def Module(self):
> > +        return self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
> > +
> > +    ## Return the module name
> > +    @cached_property
> > +    def Name(self):
> > +        return self.Module.BaseName
> > +
> > +    ## Return the module DxsFile if exist
> > +    @cached_property
> > +    def DxsFile(self):
> > +        return self.Module.DxsFile
> > +
> > +    ## Return the module meta-file GUID
> > +    @cached_property
> > +    def Guid(self):
> > +        #
> > +        # To build same module more than once, the module path with FILE_GUID overridden has
> > +        # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the real path
> > +        # in DSC. The overridden GUID can be retrieved from file name
> > +        #
> > +        if os.path.basename(self.MetaFile.File) != os.path.basename(self.MetaFile.Path):
> > +            #
> > +            # Length of GUID is 36
> > +            #
> > +            return os.path.basename(self.MetaFile.Path)[:36]
> > +        return self.Module.Guid
> > +
> > +    ## Return the module version
> > +    @cached_property
> > +    def Version(self):
> > +        return self.Module.Version
> > +
> > +    ## Return the module type
> > +    @cached_property
> > +    def ModuleType(self):
> > +        return self.Module.ModuleType
> > +
> > +    ## Return the component type (for Edk.x style of module)
> > +    @cached_property
> > +    def ComponentType(self):
> > +        return self.Module.ComponentType
> > +
> > +    ## Return the build type
> > +    @cached_property
> > +    def BuildType(self):
> > +        return self.Module.BuildType
> > +
> > +    ## Return the PCD_IS_DRIVER setting
> > +    @cached_property
> > +    def PcdIsDriver(self):
> > +        return self.Module.PcdIsDriver
> > +
> > +    ## Return the autogen version, i.e. module meta-file version
> > +    @cached_property
> > +    def AutoGenVersion(self):
> > +        return self.Module.AutoGenVersion
> > +
> > +    ## Check if the module is library or not
> > +    @cached_property
> > +    def IsLibrary(self):
> > +        return bool(self.Module.LibraryClass)
> > +
> > +    ## Check if the module is binary module or not
> > +    @cached_property
> > +    def IsBinaryModule(self):
> > +        return self.Module.IsBinaryModule
> > +
> > +    ## Return the directory to store intermediate files of the module
> > +    @cached_property
> > +    def BuildDir(self):
> > +        return _MakeDir((
> > +                                    self.PlatformInfo.BuildDir,
> > +                                    self.Arch,
> > +                                    self.SourceDir,
> > +                                    self.MetaFile.BaseName
> > +            ))
> > +
> > +    ## Return the directory to store the intermediate object files of the module
> > +    @cached_property
> > +    def OutputDir(self):
> > +        return _MakeDir((self.BuildDir, "OUTPUT"))
> > +
> > +    ## Return the directory path to store ffs file
> > +    @cached_property
> > +    def FfsOutputDir(self):
> > +        if GlobalData.gFdfParser:
> > +            return path.join(self.PlatformInfo.BuildDir, TAB_FV_DIRECTORY, "Ffs", self.Guid + self.Name)
> > +        return ''
> > +
> > +    ## Return the directory to store auto-gened source files of the module
> > +    @cached_property
> > +    def DebugDir(self):
> > +        return _MakeDir((self.BuildDir, "DEBUG"))
> > +
> > +    ## Return the path of custom file
> > +    @cached_property
> > +    def CustomMakefile(self):
> > +        RetVal = {}
> > +        for Type in self.Module.CustomMakefile:
> > +            MakeType = gMakeTypeMap[Type] if Type in gMakeTypeMap else 'nmake'
> > +            File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
> > +            RetVal[MakeType] = File
> > +        return RetVal
> > +
> > +    ## Return the directory of the makefile
> > +    #
> > +    #   @retval     string  The directory string of module's makefile
> > +    #
> > +    @cached_property
> > +    def MakeFileDir(self):
> > +        return self.BuildDir
> > +
> > +    ## Return build command string
> > +    #
> > +    #   @retval     string  Build command string
> > +    #
> > +    @cached_property
> > +    def BuildCommand(self):
> > +        return self.PlatformInfo.BuildCommand
> > +
> > +    ## Get object list of all packages the module and its dependent libraries belong to
> > +    #
> > +    #   @retval     list    The list of package object
> > +    #
> > +    @cached_property
> > +    def DerivedPackageList(self):
> > +        PackageList = []
> > +        for M in [self.Module] + self.DependentLibraryList:
> > +            for Package in M.Packages:
> > +                if Package in PackageList:
> > +                    continue
> > +                PackageList.append(Package)
> > +        return PackageList
> > +
> > +    ## Get the depex string
> > +    #
> > +    # @return : a string contain all depex expression.
> > +    def _GetDepexExpresionString(self):
> > +        DepexStr = ''
> > +        DepexList = []
> > +        ## DPX_SOURCE IN Define section.
> > +        if self.Module.DxsFile:
> > +            return DepexStr
> > +        for M in [self.Module] + self.DependentLibraryList:
> > +            Filename = M.MetaFile.Path
> > +            InfObj = InfSectionParser.InfSectionParser(Filename)
> > +            DepexExpressionList = InfObj.GetDepexExpresionList()
> > +            for DepexExpression in DepexExpressionList:
> > +                for key in DepexExpression:
> > +                    Arch, ModuleType = key
> > +                    DepexExpr = [x for x in DepexExpression[key] if not str(x).startswith('#')]
> > +                    # the type of build module is USER_DEFINED.
> > +                    # All different DEPEX section tags would be copied into the As Built INF file
> > +                    # and there would be separate DEPEX section tags
> > +                    if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED or self.ModuleType.upper() == SUP_MODULE_HOST_APPLICATION:
> > +                        if (Arch.upper() == self.Arch.upper()) and (ModuleType.upper() != TAB_ARCH_COMMON):
> > +                            DepexList.append({(Arch, ModuleType): DepexExpr})
> > +                    else:
> > +                        if Arch.upper() == TAB_ARCH_COMMON or \
> > +                          (Arch.upper() == self.Arch.upper() and \
> > +                          ModuleType.upper() in [TAB_ARCH_COMMON, self.ModuleType.upper()]):
> > +                            DepexList.append({(Arch, ModuleType): DepexExpr})
> > +
> > +        #the type of build module is USER_DEFINED.
> > +        if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED or self.ModuleType.upper() == SUP_MODULE_HOST_APPLICATION:
> > +            for Depex in DepexList:
> > +                for key in Depex:
> > +                    DepexStr += '[Depex.%s.%s]\n' % key
> > +                    DepexStr += '\n'.join('# '+ val for val in Depex[key])
> > +                    DepexStr += '\n\n'
> > +            if not DepexStr:
> > +                return '[Depex.%s]\n' % self.Arch
> > +            return DepexStr
> > +
> > +        #the type of build module not is USER_DEFINED.
> > +        Count = 0
> > +        for Depex in DepexList:
> > +            Count += 1
> > +            if DepexStr != '':
> > +                DepexStr += ' AND '
> > +            DepexStr += '('
> > +            for D in Depex.values():
> > +                DepexStr += ' '.join(val for val in D)
> > +            Index = DepexStr.find('END')
> > +            if Index > -1 and Index == len(DepexStr) - 3:
> > +                DepexStr = DepexStr[:-3]
> > +            DepexStr = DepexStr.strip()
> > +            DepexStr += ')'
> > +        if Count == 1:
> > +            DepexStr = DepexStr.lstrip('(').rstrip(')').strip()
> > +        if not DepexStr:
> > +            return '[Depex.%s]\n' % self.Arch
> > +        return '[Depex.%s]\n#  ' % self.Arch + DepexStr
> > +
> > +    ## Merge dependency expression
> > +    #
> > +    #   @retval     list    The token list of the dependency expression after parsed
> > +    #
> > +    @cached_property
> > +    def DepexList(self):
> > +        if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
> > +            return {}
> > +
> > +        DepexList = []
> > +        #
> > +        # Append depex from dependent libraries, if not "BEFORE", "AFTER" expression
> > +        #
> > +        FixedVoidTypePcds = {}
> > +        for M in [self] + self.LibraryAutoGenList:
> > +            FixedVoidTypePcds.update(M.FixedVoidTypePcds)
> > +        for M in [self] + self.LibraryAutoGenList:
> > +            Inherited = False
> > +            for D in M.Module.Depex[self.Arch, self.ModuleType]:
> > +                if DepexList != []:
> > +                    DepexList.append('AND')
> > +                DepexList.append('(')
> > +                #replace D with value if D is FixedAtBuild PCD
> > +                NewList = []
> > +                for item in D:
> > +                    if '.' not in item:
> > +                        NewList.append(item)
> > +                    else:
> > +                        try:
> > +                            Value = FixedVoidTypePcds[item]
> > +                            if len(Value.split(',')) != 16:
> > +                                EdkLogger.error("build", FORMAT_INVALID,
> > +                                                "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type and 16 bytes in the module.".format(item))
> > +                            NewList.append(Value)
> > +                        except:
> > +                            EdkLogger.error("build", FORMAT_INVALID, "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type in the module.".format(item))
> > +
> > +                DepexList.extend(NewList)
> > +                if DepexList[-1] == 'END':  # no need of a END at this time
> > +                    DepexList.pop()
> > +                DepexList.append(')')
> > +                Inherited = True
> > +            if Inherited:
> > +                EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.Module.BaseName, DepexList))
> > +            if 'BEFORE' in DepexList or 'AFTER' in DepexList:
> > +                break
> > +            if len(DepexList) > 0:
> > +                EdkLogger.verbose('')
> > +        return {self.ModuleType:DepexList}
> > +
> > +    ## Merge dependency expression
> > +    #
> > +    #   @retval     list    The token list of the dependency expression after parsed
> > +    #
> > +    @cached_property
> > +    def DepexExpressionDict(self):
> > +        if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
> > +            return {}
> > +
> > +        DepexExpressionString = ''
> > +        #
> > +        # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
> > +        #
> > +        for M in [self.Module] + self.DependentLibraryList:
> > +            Inherited = False
> > +            for D in M.DepexExpression[self.Arch, self.ModuleType]:
> > +                if DepexExpressionString != '':
> > +                    DepexExpressionString += ' AND '
> > +                DepexExpressionString += '('
> > +                DepexExpressionString += D
> > +                DepexExpressionString = DepexExpressionString.rstrip('END').strip()
> > +                DepexExpressionString += ')'
> > +                Inherited = True
> > +            if Inherited:
> > +                EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionString))
> > +            if 'BEFORE' in DepexExpressionString or 'AFTER' in DepexExpressionString:
> > +                break
> > +        if len(DepexExpressionString) > 0:
> > +            EdkLogger.verbose('')
> > +
> > +        return {self.ModuleType:DepexExpressionString}
> > +
> > +    # Get the tiano core user extension, it is contain dependent library.
> > +    # @retval: a list contain tiano core userextension.
> > +    #
> > +    def _GetTianoCoreUserExtensionList(self):
> > +        TianoCoreUserExtentionList = []
> > +        for M in [self.Module] + self.DependentLibraryList:
> > +            Filename = M.MetaFile.Path
> > +            InfObj = InfSectionParser.InfSectionParser(Filename)
> > +            TianoCoreUserExtenList = InfObj.GetUserExtensionTianoCore()
> > +            for TianoCoreUserExtent in TianoCoreUserExtenList:
> > +                for Section in TianoCoreUserExtent:
> > +                    ItemList = Section.split(TAB_SPLIT)
> > +                    Arch = self.Arch
> > +                    if len(ItemList) == 4:
> > +                        Arch = ItemList[3]
> > +                    if Arch.upper() == TAB_ARCH_COMMON or Arch.upper() == self.Arch.upper():
> > +                        TianoCoreList = []
> > +                        TianoCoreList.extend([TAB_SECTION_START + Section + TAB_SECTION_END])
> > +                        TianoCoreList.extend(TianoCoreUserExtent[Section][:])
> > +                        TianoCoreList.append('\n')
> > +                        TianoCoreUserExtentionList.append(TianoCoreList)
> > +
> > +        return TianoCoreUserExtentionList
> > +
> > +    ## Return the list of specification version required for the module
> > +    #
> > +    #   @retval     list    The list of specification defined in module file
> > +    #
> > +    @cached_property
> > +    def Specification(self):
> > +        return self.Module.Specification
> > +
> > +    ## Tool option for the module build
> > +    #
> > +    #   @param      PlatformInfo    The object of PlatformBuildInfo
> > +    #   @retval     dict            The dict containing valid options
> > +    #
> > +    @cached_property
> > +    def BuildOption(self):
> > +        RetVal, self.BuildRuleOrder = self.PlatformInfo.ApplyBuildOption(self.Module)
> > +        if self.BuildRuleOrder:
> > +            self.BuildRuleOrder = ['.%s' % Ext for Ext in self.BuildRuleOrder.split()]
> > +        return RetVal
> > +
> > +    ## Get include path list from tool option for the module build
> > +    #
> > +    #   @retval     list            The include path list
> > +    #
> > +    @cached_property
> > +    def BuildOptionIncPathList(self):
> > +        #
> > +        # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
> > +        # is the former use /I , the Latter used -I to specify include directories
> > +        #
> > +        if self.PlatformInfo.ToolChainFamily in (TAB_COMPILER_MSFT):
> > +            BuildOptIncludeRegEx = gBuildOptIncludePatternMsft
> > +        elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):
> > +            BuildOptIncludeRegEx = gBuildOptIncludePatternOther
> > +        else:
> > +            #
> > +            # New ToolChainFamily, don't known whether there is option to specify include directories
> > +            #
> > +            return []
> > +
> > +        RetVal = []
> > +        for Tool in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
> > +            try:
> > +                FlagOption = self.BuildOption[Tool]['FLAGS']
> > +            except KeyError:
> > +                FlagOption = ''
> > +
> > +            if self.ToolChainFamily != 'RVCT':
> > +                IncPathList = [NormPath(Path, self.Macros) for Path in BuildOptIncludeRegEx.findall(FlagOption)]
> > +            else:
> > +                #
> > +                # RVCT may specify a list of directory seperated by commas
> > +                #
> > +                IncPathList = []
> > +                for Path in BuildOptIncludeRegEx.findall(FlagOption):
> > +                    PathList = GetSplitList(Path, TAB_COMMA_SPLIT)
> > +                    IncPathList.extend(NormPath(PathEntry, self.Macros) for PathEntry in PathList)
> > +
> > +            #
> > +            # EDK II modules must not reference header files outside of the packages they depend on or
> > +            # within the module's directory tree. Report error if violation.
> > +            #
> > +            if GlobalData.gDisableIncludePathCheck == False:
> > +                for Path in IncPathList:
> > +                    if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir):
> > +                        ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption)
> > +                        EdkLogger.error("build",
> > +                                        PARAMETER_INVALID,
> > +                                        ExtraData=ErrMsg,
> > +                                        File=str(self.MetaFile))
> > +            RetVal += IncPathList
> > +        return RetVal
> > +
> > +    ## Return a list of files which can be built from source
> > +    #
> > +    #  What kind of files can be built is determined by build rules in
> > +    #  $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
> > +    #
> > +    @cached_property
> > +    def SourceFileList(self):
> > +        RetVal = []
> > +        ToolChainTagSet = {"", TAB_STAR, self.ToolChain}
> > +        ToolChainFamilySet = {"", TAB_STAR, self.ToolChainFamily, self.BuildRuleFamily}
> > +        for F in self.Module.Sources:
> > +            # match tool chain
> > +            if F.TagName not in ToolChainTagSet:
> > +                EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "
> > +                                "but [%s] is currently used" % (F.TagName, str(F), self.ToolChain))
> > +                continue
> > +            # match tool chain family or build rule family
> > +            if F.ToolChainFamily not in ToolChainFamilySet:
> > +                EdkLogger.debug(
> > +                            EdkLogger.DEBUG_0,
> > +                            "The file [%s] must be built by tools of [%s], " \
> > +                            "but current toolchain family is [%s], buildrule family is [%s]" \
> > +                                % (str(F), F.ToolChainFamily, self.ToolChainFamily, self.BuildRuleFamily))
> > +                continue
> > +
> > +            # add the file path into search path list for file including
> > +            if F.Dir not in self.IncludePathList:
> > +                self.IncludePathList.insert(0, F.Dir)
> > +            RetVal.append(F)
> > +
> > +        self._MatchBuildRuleOrder(RetVal)
> > +
> > +        for F in RetVal:
> > +            self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)
> > +        return RetVal
> > +
> > +    def _MatchBuildRuleOrder(self, FileList):
> > +        Order_Dict = {}
> > +        self.BuildOption
> > +        for SingleFile in FileList:
> > +            if self.BuildRuleOrder and SingleFile.Ext in self.BuildRuleOrder and SingleFile.Ext in self.BuildRules:
> > +                key = SingleFile.Path.rsplit(SingleFile.Ext,1)[0]
> > +                if key in Order_Dict:
> > +                    Order_Dict[key].append(SingleFile.Ext)
> > +                else:
> > +                    Order_Dict[key] = [SingleFile.Ext]
> > +
> > +        RemoveList = []
> > +        for F in Order_Dict:
> > +            if len(Order_Dict[F]) > 1:
> > +                Order_Dict[F].sort(key=lambda i: self.BuildRuleOrder.index(i))
> > +                for Ext in Order_Dict[F][1:]:
> > +                    RemoveList.append(F + Ext)
> > +
> > +        for item in RemoveList:
> > +            FileList.remove(item)
> > +
> > +        return FileList
> > +
> > +    ## Return the list of unicode files
> > +    @cached_property
> > +    def UnicodeFileList(self):
> > +        return self.FileTypes.get(TAB_UNICODE_FILE,[])
> > +
> > +    ## Return the list of vfr files
> > +    @cached_property
> > +    def VfrFileList(self):
> > +        return self.FileTypes.get(TAB_VFR_FILE, [])
> > +
> > +    ## Return the list of Image Definition files
> > +    @cached_property
> > +    def IdfFileList(self):
> > +        return self.FileTypes.get(TAB_IMAGE_FILE,[])
> > +
> > +    ## Return a list of files which can be built from binary
> > +    #
> > +    #  "Build" binary files are just to copy them to build directory.
> > +    #
> > +    #   @retval     list            The list of files which can be built later
> > +    #
> > +    @cached_property
> > +    def BinaryFileList(self):
> > +        RetVal = []
> > +        for F in self.Module.Binaries:
> > +            if F.Target not in [TAB_ARCH_COMMON, TAB_STAR] and F.Target != self.BuildTarget:
> > +                continue
> > +            RetVal.append(F)
> > +            self._ApplyBuildRule(F, F.Type, BinaryFileList=RetVal)
> > +        return RetVal
> > +
> > +    @cached_property
> > +    def BuildRules(self):
> > +        RetVal = {}
> > +        BuildRuleDatabase = self.PlatformInfo.BuildRule
> > +        for Type in BuildRuleDatabase.FileTypeList:
> > +            #first try getting build rule by BuildRuleFamily
> > +            RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]
> > +            if not RuleObject:
> > +                # build type is always module type, but ...
> > +                if self.ModuleType != self.BuildType:
> > +                    RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]
> > +            #second try getting build rule by ToolChainFamily
> > +            if not RuleObject:
> > +                RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]
> > +                if not RuleObject:
> > +                    # build type is always module type, but ...
> > +                    if self.ModuleType != self.BuildType:
> > +                        RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]
> > +            if not RuleObject:
> > +                continue
> > +            RuleObject = RuleObject.Instantiate(self.Macros)
> > +            RetVal[Type] = RuleObject
> > +            for Ext in RuleObject.SourceFileExtList:
> > +                RetVal[Ext] = RuleObject
> > +        return RetVal
> > +
> > +    def _ApplyBuildRule(self, File, FileType, BinaryFileList=None):
> > +        if self._BuildTargets is None:
> > +            self._IntroBuildTargetList = set()
> > +            self._FinalBuildTargetList = set()
> > +            self._BuildTargets = defaultdict(set)
> > +            self._FileTypes = defaultdict(set)
> > +
> > +        if not BinaryFileList:
> > +            BinaryFileList = self.BinaryFileList
> > +
> > +        SubDirectory = os.path.join(self.OutputDir, File.SubDir)
> > +        if not os.path.exists(SubDirectory):
> > +            CreateDirectory(SubDirectory)
> > +        LastTarget = None
> > +        RuleChain = set()
> > +        SourceList = [File]
> > +        Index = 0
> > +        #
> > +        # Make sure to get build rule order value
> > +        #
> > +        self.BuildOption
> > +
> > +        while Index < len(SourceList):
> > +            Source = SourceList[Index]
> > +            Index = Index + 1
> > +
> > +            if Source != File:
> > +                CreateDirectory(Source.Dir)
> > +
> > +            if File.IsBinary and File == Source and File in BinaryFileList:
> > +                # Skip all files that are not binary libraries
> > +                if not self.IsLibrary:
> > +                    continue
> > +                RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]
> > +            elif FileType in self.BuildRules:
> > +                RuleObject = self.BuildRules[FileType]
> > +            elif Source.Ext in self.BuildRules:
> > +                RuleObject = self.BuildRules[Source.Ext]
> > +            else:
> > +                # stop at no more rules
> > +                if LastTarget:
> > +                    self._FinalBuildTargetList.add(LastTarget)
> > +                break
> > +
> > +            FileType = RuleObject.SourceFileType
> > +            self._FileTypes[FileType].add(Source)
> > +
> > +            # stop at STATIC_LIBRARY for library
> > +            if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
> > +                if LastTarget:
> > +                    self._FinalBuildTargetList.add(LastTarget)
> > +                break
> > +
> > +            Target = RuleObject.Apply(Source, self.BuildRuleOrder)
> > +            if not Target:
> > +                if LastTarget:
> > +                    self._FinalBuildTargetList.add(LastTarget)
> > +                break
> > +            elif not Target.Outputs:
> > +                # Only do build for target with outputs
> > +                self._FinalBuildTargetList.add(Target)
> > +
> > +            self._BuildTargets[FileType].add(Target)
> > +
> > +            if not Source.IsBinary and Source == File:
> > +                self._IntroBuildTargetList.add(Target)
> > +
> > +            # to avoid cyclic rule
> > +            if FileType in RuleChain:
> > +                break
> > +
> > +            RuleChain.add(FileType)
> > +            SourceList.extend(Target.Outputs)
> > +            LastTarget = Target
> > +            FileType = TAB_UNKNOWN_FILE
> > +
> > +    @cached_property
> > +    def Targets(self):
> > +        if self._BuildTargets is None:
> > +            self._IntroBuildTargetList = set()
> > +            self._FinalBuildTargetList = set()
> > +            self._BuildTargets = defaultdict(set)
> > +            self._FileTypes = defaultdict(set)
> > +
> > +        #TRICK: call SourceFileList property to apply build rule for source files
> > +        self.SourceFileList
> > +
> > +        #TRICK: call _GetBinaryFileList to apply build rule for binary files
> > +        self.BinaryFileList
> > +
> > +        return self._BuildTargets
> > +
> > +    @cached_property
> > +    def IntroTargetList(self):
> > +        self.Targets
> > +        return self._IntroBuildTargetList
> > +
> > +    @cached_property
> > +    def CodaTargetList(self):
> > +        self.Targets
> > +        return self._FinalBuildTargetList
> > +
> > +    @cached_property
> > +    def FileTypes(self):
> > +        self.Targets
> > +        return self._FileTypes
> > +
> > +    ## Get the list of package object the module depends on
> > +    #
> > +    #   @retval     list    The package object list
> > +    #
> > +    @cached_property
> > +    def DependentPackageList(self):
> > +        return self.Module.Packages
> > +
> > +    ## Return the list of auto-generated code file
> > +    #
> > +    #   @retval     list        The list of auto-generated file
> > +    #
> > +    @cached_property
> > +    def AutoGenFileList(self):
> > +        AutoGenUniIdf = self.BuildType != 'UEFI_HII'
> > +        UniStringBinBuffer = BytesIO()
> > +        IdfGenBinBuffer = BytesIO()
> > +        RetVal = {}
> > +        AutoGenC = TemplateString()
> > +        AutoGenH = TemplateString()
> > +        StringH = TemplateString()
> > +        StringIdf = TemplateString()
> > +        GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, AutoGenUniIdf, UniStringBinBuffer, StringIdf, AutoGenUniIdf, IdfGenBinBuffer)
> > +        #
> > +        # AutoGen.c is generated if there are library classes in inf, or there are object files
> > +        #
> > +        if str(AutoGenC) != "" and (len(self.Module.LibraryClasses) > 0
> > +                                    or TAB_OBJECT_FILE in self.FileTypes):
> > +            AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)
> > +            RetVal[AutoFile] = str(AutoGenC)
> > +            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
> > +        if str(AutoGenH) != "":
> > +            AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)
> > +            RetVal[AutoFile] = str(AutoGenH)
> > +            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
> > +        if str(StringH) != "":
> > +            AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)
> > +            RetVal[AutoFile] = str(StringH)
> > +            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
> > +        if UniStringBinBuffer is not None and UniStringBinBuffer.getvalue() != b"":
> > +            AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)
> > +            RetVal[AutoFile] = UniStringBinBuffer.getvalue()
> > +            AutoFile.IsBinary = True
> > +            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
> > +        if UniStringBinBuffer is not None:
> > +            UniStringBinBuffer.close()
> > +        if str(StringIdf) != "":
> > +            AutoFile = PathClass(gAutoGenImageDefFileName % {"module_name":self.Name}, self.DebugDir)
> > +            RetVal[AutoFile] = str(StringIdf)
> > +            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
> > +        if IdfGenBinBuffer is not None and IdfGenBinBuffer.getvalue() != b"":
> > +            AutoFile = PathClass(gAutoGenIdfFileName % {"module_name":self.Name}, self.OutputDir)
> > +            RetVal[AutoFile] = IdfGenBinBuffer.getvalue()
> > +            AutoFile.IsBinary = True
> > +            self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
> > +        if IdfGenBinBuffer is not None:
> > +            IdfGenBinBuffer.close()
> > +        return RetVal
> > +
> > +    ## Return the list of library modules explicitly or implicitly used by this module
> > +    @cached_property
> > +    def DependentLibraryList(self):
> > +        # only merge library classes and PCD for non-library module
> > +        if self.IsLibrary:
> > +            return []
> > +        return self.PlatformInfo.ApplyLibraryInstance(self.Module)
> > +
> > +    ## Get the list of PCDs from current module
> > +    #
> > +    #   @retval     list                    The list of PCD
> > +    #
> > +    @cached_property
> > +    def ModulePcdList(self):
> > +        # apply PCD settings from platform
> > +        RetVal = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)
> > +
> > +        return RetVal
> > +    @cached_property
> > +    def _PcdComments(self):
> > +        ReVal = OrderedListDict()
> > +        ExtendCopyDictionaryLists(ReVal, self.Module.PcdComments)
> > +        if not self.IsLibrary:
> > +            for Library in self.DependentLibraryList:
> > +                ExtendCopyDictionaryLists(ReVal, Library.PcdComments)
> > +        return ReVal
> > +
> > +    ## Get the list of PCDs from dependent libraries
> > +    #
> > +    #   @retval     list                    The list of PCD
> > +    #
> > +    @cached_property
> > +    def LibraryPcdList(self):
> > +        if self.IsLibrary:
> > +            return []
> > +        RetVal = []
> > +        Pcds = set()
> > +        # get PCDs from dependent libraries
> > +        for Library in self.DependentLibraryList:
> > +            PcdsInLibrary = OrderedDict()
> > +            for Key in Library.Pcds:
> > +                # skip duplicated PCDs
> > +                if Key in self.Module.Pcds or Key in Pcds:
> > +                    continue
> > +                Pcds.add(Key)
> > +                PcdsInLibrary[Key] = copy.copy(Library.Pcds[Key])
> > +            RetVal.extend(self.PlatformInfo.ApplyPcdSetting(self.Module, PcdsInLibrary, Library=Library))
> > +        return RetVal
> > +
> > +    ## Get the GUID value mapping
> > +    #
> > +    #   @retval     dict    The mapping between GUID cname and its value
> > +    #
> > +    @cached_property
> > +    def GuidList(self):
> > +        RetVal = self.Module.Guids
> > +        for Library in self.DependentLibraryList:
> > +            RetVal.update(Library.Guids)
> > +            ExtendCopyDictionaryLists(self._GuidComments, Library.GuidComments)
> > +        ExtendCopyDictionaryLists(self._GuidComments, self.Module.GuidComments)
> > +        return RetVal
> > +
> > +    @cached_property
> > +    def GetGuidsUsedByPcd(self):
> > +        RetVal = OrderedDict(self.Module.GetGuidsUsedByPcd())
> > +        for Library in self.DependentLibraryList:
> > +            RetVal.update(Library.GetGuidsUsedByPcd())
> > +        return RetVal
> > +    ## Get the protocol value mapping
> > +    #
> > +    #   @retval     dict    The mapping between protocol cname and its value
> > +    #
> > +    @cached_property
> > +    def ProtocolList(self):
> > +        RetVal = OrderedDict(self.Module.Protocols)
> > +        for Library in self.DependentLibraryList:
> > +            RetVal.update(Library.Protocols)
> > +            ExtendCopyDictionaryLists(self._ProtocolComments, Library.ProtocolComments)
> > +        ExtendCopyDictionaryLists(self._ProtocolComments, self.Module.ProtocolComments)
> > +        return RetVal
> > +
> > +    ## Get the PPI value mapping
> > +    #
> > +    #   @retval     dict    The mapping between PPI cname and its value
> > +    #
> > +    @cached_property
> > +    def PpiList(self):
> > +        RetVal = OrderedDict(self.Module.Ppis)
> > +        for Library in self.DependentLibraryList:
> > +            RetVal.update(Library.Ppis)
> > +            ExtendCopyDictionaryLists(self._PpiComments, Library.PpiComments)
> > +        ExtendCopyDictionaryLists(self._PpiComments, self.Module.PpiComments)
> > +        return RetVal
> > +
> > +    ## Get the list of include search path
> > +    #
> > +    #   @retval     list                    The list path
> > +    #
> > +    @cached_property
> > +    def IncludePathList(self):
> > +        RetVal = []
> > +        RetVal.append(self.MetaFile.Dir)
> > +        RetVal.append(self.DebugDir)
> > +
> > +        for Package in self.Module.Packages:
> > +            PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir)
> > +            if PackageDir not in RetVal:
> > +                RetVal.append(PackageDir)
> > +            IncludesList = Package.Includes
> > +            if Package._PrivateIncludes:
> > +                if not self.MetaFile.OriginalPath.Path.startswith(PackageDir):
> > +                    IncludesList = list(set(Package.Includes).difference(set(Package._PrivateIncludes)))
> > +            for Inc in IncludesList:
> > +                if Inc not in RetVal:
> > +                    RetVal.append(str(Inc))
> > +        return RetVal
> > +
> > +    @cached_property
> > +    def IncludePathLength(self):
> > +        return sum(len(inc)+1 for inc in self.IncludePathList)
> > +
> > +    ## Get HII EX PCDs which maybe used by VFR
> > +    #
> > +    #  efivarstore used by VFR may relate with HII EX PCDs
> > +    #  Get the variable name and GUID from efivarstore and HII EX PCD
> > +    #  List the HII EX PCDs in As Built INF if both name and GUID match.
> > +    #
> > +    #  @retval    list    HII EX PCDs
> > +    #
> > +    def _GetPcdsMaybeUsedByVfr(self):
> > +        if not self.SourceFileList:
> > +            return []
> > +
> > +        NameGuids = set()
> > +        for SrcFile in self.SourceFileList:
> > +            if SrcFile.Ext.lower() != '.vfr':
> > +                continue
> > +            Vfri = os.path.join(self.OutputDir, SrcFile.BaseName + '.i')
> > +            if not os.path.exists(Vfri):
> > +                continue
> > +            VfriFile = open(Vfri, 'r')
> > +            Content = VfriFile.read()
> > +            VfriFile.close()
> > +            Pos = Content.find('efivarstore')
> > +            while Pos != -1:
> > +                #
> > +                # Make sure 'efivarstore' is the start of efivarstore statement
> > +                # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
> > +                #
> > +                Index = Pos - 1
> > +                while Index >= 0 and Content[Index] in ' \t\r\n':
> > +                    Index -= 1
> > +                if Index >= 0 and Content[Index] != ';':
> > +                    Pos = Content.find('efivarstore', Pos + len('efivarstore'))
> > +                    continue
> > +                #
> > +                # 'efivarstore' must be followed by name and guid
> > +                #
> > +                Name = gEfiVarStoreNamePattern.search(Content, Pos)
> > +                if not Name:
> > +                    break
> > +                Guid = gEfiVarStoreGuidPattern.search(Content, Pos)
> > +                if not Guid:
> > +                    break
> > +                NameArray = _ConvertStringToByteArray('L"' + Name.group(1) + '"')
> > +                NameGuids.add((NameArray, GuidStructureStringToGuidString(Guid.group(1))))
> > +                Pos = Content.find('efivarstore', Name.end())
> > +        if not NameGuids:
> > +            return []
> > +        HiiExPcds = []
> > +        for Pcd in self.PlatformInfo.Pcds.values():
> > +            if Pcd.Type != TAB_PCDS_DYNAMIC_EX_HII:
> > +                continue
> > +            for SkuInfo in Pcd.SkuInfoList.values():
> > +                Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList, self.MetaFile.Path)
> > +                if not Value:
> > +                    continue
> > +                Name = _ConvertStringToByteArray(SkuInfo.VariableName)
> > +                Guid = GuidStructureStringToGuidString(Value)
> > +                if (Name, Guid) in NameGuids and Pcd not in HiiExPcds:
> > +                    HiiExPcds.append(Pcd)
> > +                    break
> > +
> > +        return HiiExPcds
> > +
> > +    def _GenOffsetBin(self):
> > +        VfrUniBaseName = {}
> > +        for SourceFile in self.Module.Sources:
> > +            if SourceFile.Type.upper() == ".VFR" :
> > +                #
> > +                # search the .map file to find the offset of vfr binary in the PE32+/TE file.
> > +                #
> > +                VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")
> > +            elif SourceFile.Type.upper() == ".UNI" :
> > +                #
> > +                # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
> > +                #
> > +                VfrUniBaseName["UniOffsetName"] = (self.Name + "Strings")
> > +
> > +        if not VfrUniBaseName:
> > +            return None
> > +        MapFileName = os.path.join(self.OutputDir, self.Name + ".map")
> > +        EfiFileName = os.path.join(self.OutputDir, self.Name + ".efi")
> > +        VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, list(VfrUniBaseName.values()))
> > +        if not VfrUniOffsetList:
> > +            return None
> > +
> > +        OutputName = '%sOffset.bin' % self.Name
> > +        UniVfrOffsetFileName    =  os.path.join( self.OutputDir, OutputName)
> > +
> > +        try:
> > +            fInputfile = open(UniVfrOffsetFileName, "wb+", 0)
> > +        except:
> > +            EdkLogger.error("build", FILE_OPEN_FAILURE, "File open failed for %s" % UniVfrOffsetFileName, None)
> > +
> > +        # Use a instance of BytesIO to cache data
> > +        fStringIO = BytesIO()
> > +
> > +        for Item in VfrUniOffsetList:
> > +            if (Item[0].find("Strings") != -1):
> > +                #
> > +                # UNI offset in image.
> > +                # GUID + Offset
> > +                # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
> > +                #
> > +                UniGuid = b'\xe0\xc5\x13\x89\xf63\x86M\x9b\xf1C\xef\x89\xfc\x06f'
> > +                fStringIO.write(UniGuid)
> > +                UniValue = pack ('Q', int (Item[1], 16))
> > +                fStringIO.write (UniValue)
> > +            else:
> > +                #
> > +                # VFR binary offset in image.
> > +                # GUID + Offset
> > +                # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
> > +                #
> > +                VfrGuid = b'\xb4|\xbc\xd0Gj_I\xaa\x11q\x07F\xda\x06\xa2'
> > +                fStringIO.write(VfrGuid)
> > +                VfrValue = pack ('Q', int (Item[1], 16))
> > +                fStringIO.write (VfrValue)
> > +        #
> > +        # write data into file.
> > +        #
> > +        try :
> > +            fInputfile.write (fStringIO.getvalue())
> > +        except:
> > +            EdkLogger.error("build", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the "
> > +                            "file been locked or using by other applications." %UniVfrOffsetFileName, None)
> > +
> > +        fStringIO.close ()
> > +        fInputfile.close ()
> > +        return OutputName
> > +    @cached_property
> > +    def OutputFile(self):
> > +        retVal = set()
> > +        OutputDir = self.OutputDir.replace('\\', '/').strip('/')
> > +        DebugDir = self.DebugDir.replace('\\', '/').strip('/')
> > +        for Item in self.CodaTargetList:
> > +            File = Item.Target.Path.replace('\\', '/').strip('/').replace(DebugDir, '').replace(OutputDir, '').strip('/')
> > +            retVal.add(File)
> > +        if self.DepexGenerated:
> > +            retVal.add(self.Name + '.depex')
> > +
> > +        Bin = self._GenOffsetBin()
> > +        if Bin:
> > +            retVal.add(Bin)
> > +
> > +        for Root, Dirs, Files in os.walk(OutputDir):
> > +            for File in Files:
> > +                if File.lower().endswith('.pdb'):
> > +                    retVal.add(File)
> > +
> > +        return retVal
> > +
> > +    ## Create AsBuilt INF file the module
> > +    #
> > +    def CreateAsBuiltInf(self):
> > +
> > +        if self.IsAsBuiltInfCreated:
> > +            return
> > +
> > +        # Skip INF file generation for libraries
> > +        if self.IsLibrary:
> > +            return
> > +
> > +        # Skip the following code for modules with no source files
> > +        if not self.SourceFileList:
> > +            return
> > +
> > +        # Skip the following code for modules without any binary files
> > +        if self.BinaryFileList:
> > +            return
> > +
> > +        ### TODO: How to handles mixed source and binary modules
> > +
> > +        # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
> > +        # Also find all packages that the DynamicEx PCDs depend on
> > +        Pcds = []
> > +        PatchablePcds = []
> > +        Packages = []
> > +        PcdCheckList = []
> > +        PcdTokenSpaceList = []
> > +        for Pcd in self.ModulePcdList + self.LibraryPcdList:
> > +            if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE:
> > +                PatchablePcds.append(Pcd)
> > +                PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, TAB_PCDS_PATCHABLE_IN_MODULE))
> > +            elif Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
> > +                if Pcd not in Pcds:
> > +                    Pcds.append(Pcd)
> > +                    PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, TAB_PCDS_DYNAMIC_EX))
> > +                    PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, TAB_PCDS_DYNAMIC))
> > +                    PcdTokenSpaceList.append(Pcd.TokenSpaceGuidCName)
> > +        GuidList = OrderedDict(self.GuidList)
> > +        for TokenSpace in self.GetGuidsUsedByPcd:
> > +            # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
> > +            # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
> > +            if TokenSpace not in PcdTokenSpaceList and TokenSpace in GuidList:
> > +                GuidList.pop(TokenSpace)
> > +        CheckList = (GuidList, self.PpiList, self.ProtocolList, PcdCheckList)
> > +        for Package in self.DerivedPackageList:
> > +            if Package in Packages:
> > +                continue
> > +            BeChecked = (Package.Guids, Package.Ppis, Package.Protocols, Package.Pcds)
> > +            Found = False
> > +            for Index in range(len(BeChecked)):
> > +                for Item in CheckList[Index]:
> > +                    if Item in BeChecked[Index]:
> > +                        Packages.append(Package)
> > +                        Found = True
> > +                        break
> > +                if Found:
> > +                    break
> > +
> > +        VfrPcds = self._GetPcdsMaybeUsedByVfr()
> > +        for Pkg in self.PlatformInfo.PackageList:
> > +            if Pkg in Packages:
> > +                continue
> > +            for VfrPcd in VfrPcds:
> > +                if ((VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, TAB_PCDS_DYNAMIC_EX) in Pkg.Pcds or
> > +                    (VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, TAB_PCDS_DYNAMIC) in Pkg.Pcds):
> > +                    Packages.append(Pkg)
> > +                    break
> > +
> > +        ModuleType = SUP_MODULE_DXE_DRIVER if self.ModuleType == SUP_MODULE_UEFI_DRIVER and self.DepexGenerated else self.ModuleType
> > +        DriverType = self.PcdIsDriver if self.PcdIsDriver else ''
> > +        Guid = self.Guid
> > +        MDefs = self.Module.Defines
> > +
> > +        AsBuiltInfDict = {
> > +          'module_name'                       : self.Name,
> > +          'module_guid'                       : Guid,
> > +          'module_module_type'                : ModuleType,
> > +          'module_version_string'             : [MDefs['VERSION_STRING']] if 'VERSION_STRING' in MDefs else [],
> > +          'pcd_is_driver_string'              : [],
> > +          'module_uefi_specification_version' : [],
> > +          'module_pi_specification_version'   : [],
> > +          'module_entry_point'                : self.Module.ModuleEntryPointList,
> > +          'module_unload_image'               : self.Module.ModuleUnloadImageList,
> > +          'module_constructor'                : self.Module.ConstructorList,
> > +          'module_destructor'                 : self.Module.DestructorList,
> > +          'module_shadow'                     : [MDefs['SHADOW']] if 'SHADOW' in MDefs else [],
> > +          'module_pci_vendor_id'              : [MDefs['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs else [],
> > +          'module_pci_device_id'              : [MDefs['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs else [],
> > +          'module_pci_class_code'             : [MDefs['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs else [],
> > +          'module_pci_revision'               : [MDefs['PCI_REVISION']] if 'PCI_REVISION' in MDefs else [],
> > +          'module_build_number'               : [MDefs['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs else [],
> > +          'module_spec'                       : [MDefs['SPEC']] if 'SPEC' in MDefs else [],
> > +          'module_uefi_hii_resource_section'  : [MDefs['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs else [],
> > +          'module_uni_file'                   : [MDefs['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs else [],
> > +          'module_arch'                       : self.Arch,
> > +          'package_item'                      : [Package.MetaFile.File.replace('\\', '/') for Package in Packages],
> > +          'binary_item'                       : [],
> > +          'patchablepcd_item'                 : [],
> > +          'pcd_item'                          : [],
> > +          'protocol_item'                     : [],
> > +          'ppi_item'                          : [],
> > +          'guid_item'                         : [],
> > +          'flags_item'                        : [],
> > +          'libraryclasses_item'               : []
> > +        }
> > +
> > +        if 'MODULE_UNI_FILE' in MDefs:
> > +            UNIFile = os.path.join(self.MetaFile.Dir, MDefs['MODULE_UNI_FILE'])
> > +            if os.path.isfile(UNIFile):
> > +                shutil.copy2(UNIFile, self.OutputDir)
> > +
> > +        if self.AutoGenVersion > int(gInfSpecVersion, 0):
> > +            AsBuiltInfDict['module_inf_version'] = '0x%08x' % self.AutoGenVersion
> > +        else:
> > +            AsBuiltInfDict['module_inf_version'] = gInfSpecVersion
> > +
> > +        if DriverType:
> > +            AsBuiltInfDict['pcd_is_driver_string'].append(DriverType)
> > +
> > +        if 'UEFI_SPECIFICATION_VERSION' in self.Specification:
> > +            AsBuiltInfDict['module_uefi_specification_version'].append(self.Specification['UEFI_SPECIFICATION_VERSION'])
> > +        if 'PI_SPECIFICATION_VERSION' in self.Specification:
> > +            AsBuiltInfDict['module_pi_specification_version'].append(self.Specification['PI_SPECIFICATION_VERSION'])
> > +
> > +        OutputDir = self.OutputDir.replace('\\', '/').strip('/')
> > +        DebugDir = self.DebugDir.replace('\\', '/').strip('/')
> > +        for Item in self.CodaTargetList:
> > +            File = Item.Target.Path.replace('\\', '/').strip('/').replace(DebugDir, '').replace(OutputDir, '').strip('/')
> > +            if os.path.isabs(File):
> > +                File = File.replace('\\', '/').strip('/').replace(OutputDir, '').strip('/')
> > +            if Item.Target.Ext.lower() == '.aml':
> > +                AsBuiltInfDict['binary_item'].append('ASL|' + File)
> > +            elif Item.Target.Ext.lower() == '.acpi':
> > +                AsBuiltInfDict['binary_item'].append('ACPI|' + File)
> > +            elif Item.Target.Ext.lower() == '.efi':
> > +                AsBuiltInfDict['binary_item'].append('PE32|' + self.Name + '.efi')
> > +            else:
> > +                AsBuiltInfDict['binary_item'].append('BIN|' + File)
> > +        if not self.DepexGenerated:
> > +            DepexFile = os.path.join(self.OutputDir, self.Name + '.depex')
> > +            if os.path.exists(DepexFile):
> > +                self.DepexGenerated = True
> > +        if self.DepexGenerated:
> > +            if self.ModuleType in [SUP_MODULE_PEIM]:
> > +                AsBuiltInfDict['binary_item'].append('PEI_DEPEX|' + self.Name + '.depex')
> > +            elif self.ModuleType in [SUP_MODULE_DXE_DRIVER, SUP_MODULE_DXE_RUNTIME_DRIVER, SUP_MODULE_DXE_SAL_DRIVER, SUP_MODULE_UEFI_DRIVER]:
> > +                AsBuiltInfDict['binary_item'].append('DXE_DEPEX|' + self.Name + '.depex')
> > +            elif self.ModuleType in [SUP_MODULE_DXE_SMM_DRIVER]:
> > +                AsBuiltInfDict['binary_item'].append('SMM_DEPEX|' + self.Name + '.depex')
> > +
> > +        Bin = self._GenOffsetBin()
> > +        if Bin:
> > +            AsBuiltInfDict['binary_item'].append('BIN|%s' % Bin)
> > +
> > +        for Root, Dirs, Files in os.walk(OutputDir):
> > +            for File in Files:
> > +                if File.lower().endswith('.pdb'):
> > +                    AsBuiltInfDict['binary_item'].append('DISPOSABLE|' + File)
> > +        HeaderComments = self.Module.HeaderComments
> > +        StartPos = 0
> > +        for Index in range(len(HeaderComments)):
> > +            if HeaderComments[Index].find('@BinaryHeader') != -1:
> > +                HeaderComments[Index] = HeaderComments[Index].replace('@BinaryHeader', '@file')
> > +                StartPos = Index
> > +                break
> > +        AsBuiltInfDict['header_comments'] = '\n'.join(HeaderComments[StartPos:]).replace(':#', '://')
> > +        AsBuiltInfDict['tail_comments'] = '\n'.join(self.Module.TailComments)
> > +
> > +        GenList = [
> > +            (self.ProtocolList, self._ProtocolComments, 'protocol_item'),
> > +            (self.PpiList, self._PpiComments, 'ppi_item'),
> > +            (GuidList, self._GuidComments, 'guid_item')
> > +        ]
> > +        for Item in GenList:
> > +            for CName in Item[0]:
> > +                Comments = '\n  '.join(Item[1][CName]) if CName in Item[1] else ''
> > +                Entry = Comments + '\n  ' + CName if Comments else CName
> > +                AsBuiltInfDict[Item[2]].append(Entry)
> > +        PatchList = parsePcdInfoFromMapFile(
> > +                            os.path.join(self.OutputDir, self.Name + '.map'),
> > +                            os.path.join(self.OutputDir, self.Name + '.efi')
> > +                        )
> > +        if PatchList:
> > +            for Pcd in PatchablePcds:
> > +                TokenCName = Pcd.TokenCName
> > +                for PcdItem in GlobalData.MixedPcd:
> > +                    if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
> > +                        TokenCName = PcdItem[0]
> > +                        break
> > +                for PatchPcd in PatchList:
> > +                    if TokenCName == PatchPcd[0]:
> > +                        break
> > +                else:
> > +                    continue
> > +                PcdValue = ''
> > +                if Pcd.DatumType == 'BOOLEAN':
> > +                    BoolValue = Pcd.DefaultValue.upper()
> > +                    if BoolValue == 'TRUE':
> > +                        Pcd.DefaultValue = '1'
> > +                    elif BoolValue == 'FALSE':
> > +                        Pcd.DefaultValue = '0'
> > +
> > +                if Pcd.DatumType in TAB_PCD_NUMERIC_TYPES:
> > +                    HexFormat = '0x%02x'
> > +                    if Pcd.DatumType == TAB_UINT16:
> > +                        HexFormat = '0x%04x'
> > +                    elif Pcd.DatumType == TAB_UINT32:
> > +                        HexFormat = '0x%08x'
> > +                    elif Pcd.DatumType == TAB_UINT64:
> > +                        HexFormat = '0x%016x'
> > +                    PcdValue = HexFormat % int(Pcd.DefaultValue, 0)
> > +                else:
> > +                    if Pcd.MaxDatumSize is None or Pcd.MaxDatumSize == '':
> > +                        EdkLogger.error("build", AUTOGEN_ERROR,
> > +                                        "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd.TokenSpaceGuidCName, TokenCName)
> > +                                        )
> > +                    ArraySize = int(Pcd.MaxDatumSize, 0)
> > +                    PcdValue = Pcd.DefaultValue
> > +                    if PcdValue[0] != '{':
> > +                        Unicode = False
> > +                        if PcdValue[0] == 'L':
> > +                            Unicode = True
> > +                        PcdValue = PcdValue.lstrip('L')
> > +                        PcdValue = eval(PcdValue)
> > +                        NewValue = '{'
> > +                        for Index in range(0, len(PcdValue)):
> > +                            if Unicode:
> > +                                CharVal = ord(PcdValue[Index])
> > +                                NewValue = NewValue + '0x%02x' % (CharVal & 0x00FF) + ', ' \
> > +                                        + '0x%02x' % (CharVal >> 8) + ', '
> > +                            else:
> > +                                NewValue = NewValue + '0x%02x' % (ord(PcdValue[Index]) % 0x100) + ', '
> > +                        Padding = '0x00, '
> > +                        if Unicode:
> > +                            Padding = Padding * 2
> > +                            ArraySize = ArraySize // 2
> > +                        if ArraySize < (len(PcdValue) + 1):
> > +                            if Pcd.MaxSizeUserSet:
> > +                                EdkLogger.error("build", AUTOGEN_ERROR,
> > +                                            "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)
> > +                                            )
> > +                            else:
> > +                                ArraySize = len(PcdValue) + 1
> > +                        if ArraySize > len(PcdValue) + 1:
> > +                            NewValue = NewValue + Padding * (ArraySize - len(PcdValue) - 1)
> > +                        PcdValue = NewValue + Padding.strip().rstrip(',') + '}'
> > +                    elif len(PcdValue.split(',')) <= ArraySize:
> > +                        PcdValue = PcdValue.rstrip('}') + ', 0x00' * (ArraySize - len(PcdValue.split(',')))
> > +                        PcdValue += '}'
> > +                    else:
> > +                        if Pcd.MaxSizeUserSet:
> > +                            EdkLogger.error("build", AUTOGEN_ERROR,
> > +                                        "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)
> > +                                        )
> > +                        else:
> > +                            ArraySize = len(PcdValue) + 1
> > +                PcdItem = '%s.%s|%s|0x%X' % \
> > +                    (Pcd.TokenSpaceGuidCName, TokenCName, PcdValue, PatchPcd[1])
> > +                PcdComments = ''
> > +                if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
> > +                    PcdComments = '\n  '.join(self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName])
> > +                if PcdComments:
> > +                    PcdItem = PcdComments + '\n  ' + PcdItem
> > +                AsBuiltInfDict['patchablepcd_item'].append(PcdItem)
> > +
> > +        for Pcd in Pcds + VfrPcds:
> > +            PcdCommentList = []
> > +            HiiInfo = ''
> > +            TokenCName = Pcd.TokenCName
> > +            for PcdItem in GlobalData.MixedPcd:
> > +                if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
> > +                    TokenCName = PcdItem[0]
> > +                    break
> > +            if Pcd.Type == TAB_PCDS_DYNAMIC_EX_HII:
> > +                for SkuName in Pcd.SkuInfoList:
> > +                    SkuInfo = Pcd.SkuInfoList[SkuName]
> > +                    HiiInfo = '## %s|%s|%s' % (SkuInfo.VariableName, SkuInfo.VariableGuid, SkuInfo.VariableOffset)
> > +                    break
> > +            if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
> > +                PcdCommentList = self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName][:]
> > +            if HiiInfo:
> > +                UsageIndex = -1
> > +                UsageStr = ''
> > +                for Index, Comment in enumerate(PcdCommentList):
> > +                    for Usage in UsageList:
> > +                        if Comment.find(Usage) != -1:
> > +                            UsageStr = Usage
> > +                            UsageIndex = Index
> > +                            break
> > +                if UsageIndex != -1:
> > +                    PcdCommentList[UsageIndex] = '## %s %s %s' % (UsageStr, HiiInfo, PcdCommentList[UsageIndex].replace(UsageStr, ''))
> > +                else:
> > +                    PcdCommentList.append('## UNDEFINED ' + HiiInfo)
> > +            PcdComments = '\n  '.join(PcdCommentList)
> > +            PcdEntry = Pcd.TokenSpaceGuidCName + '.' + TokenCName
> > +            if PcdComments:
> > +                PcdEntry = PcdComments + '\n  ' + PcdEntry
> > +            AsBuiltInfDict['pcd_item'].append(PcdEntry)
> > +        for Item in self.BuildOption:
> > +            if 'FLAGS' in self.BuildOption[Item]:
> > +                AsBuiltInfDict['flags_item'].append('%s:%s_%s_%s_%s_FLAGS = %s' % (self.ToolChainFamily, self.BuildTarget, self.ToolChain, self.Arch, Item, self.BuildOption[Item]['FLAGS'].strip()))
> > +
> > +        # Generated LibraryClasses section in comments.
> > +        for Library in self.LibraryAutoGenList:
> > +            AsBuiltInfDict['libraryclasses_item'].append(Library.MetaFile.File.replace('\\', '/'))
> > +
> > +        # Generated UserExtensions TianoCore section.
> > +        # All tianocore user extensions are copied.
> > +        UserExtStr = ''
> > +        for TianoCore in self._GetTianoCoreUserExtensionList():
> > +            UserExtStr += '\n'.join(TianoCore)
> > +            ExtensionFile = os.path.join(self.MetaFile.Dir, TianoCore[1])
> > +            if os.path.isfile(ExtensionFile):
> > +                shutil.copy2(ExtensionFile, self.OutputDir)
> > +        AsBuiltInfDict['userextension_tianocore_item'] = UserExtStr
> > +
> > +        # Generated depex expression section in comments.
> > +        DepexExpression = self._GetDepexExpresionString()
> > +        AsBuiltInfDict['depexsection_item'] = DepexExpression if DepexExpression else ''
> > +
> > +        AsBuiltInf = TemplateString()
> > +        AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))
> > +
> > +        SaveFileOnChange(os.path.join(self.OutputDir, self.Name + '.inf'), str(AsBuiltInf), False)
> > +
> > +        self.IsAsBuiltInfCreated = True
> > +
> > +    def CopyModuleToCache(self):
> > +        FileDir = path.join(GlobalData.gBinCacheDest, self.PlatformInfo.Name, self.BuildTarget + "_" + self.ToolChain, self.Arch, self.SourceDir, self.MetaFile.BaseName)
> > +        CreateDirectory (FileDir)
> > +        HashFile = path.join(self.BuildDir, self.Name + '.hash')
> > +        if os.path.exists(HashFile):
> > +            CopyFileOnChange(HashFile, FileDir)
> > +        ModuleFile = path.join(self.OutputDir, self.Name + '.inf')
> > +        if os.path.exists(ModuleFile):
> > +            CopyFileOnChange(ModuleFile, FileDir)
> > +        if not self.OutputFile:
> > +            Ma = self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
> > +            self.OutputFile = Ma.Binaries
> > +        for File in self.OutputFile:
> > +            File = str(File)
> > +            if not os.path.isabs(File):
> > +                File = os.path.join(self.OutputDir, File)
> > +            if os.path.exists(File):
> > +                sub_dir = os.path.relpath(File, self.OutputDir)
> > +                destination_file = os.path.join(FileDir, sub_dir)
> > +                destination_dir = os.path.dirname(destination_file)
> > +                CreateDirectory(destination_dir)
> > +                CopyFileOnChange(File, destination_dir)
> > +
> > +    def AttemptModuleCacheCopy(self):
> > +        # If library or Module is binary do not skip by hash
> > +        if self.IsBinaryModule:
> > +            return False
> > +        # .inc is contains binary information so do not skip by hash as well
> > +        for f_ext in self.SourceFileList:
> > +            if '.inc' in str(f_ext):
> > +                return False
> > +        FileDir = path.join(GlobalData.gBinCacheSource, self.PlatformInfo.Name, self.BuildTarget + "_" + self.ToolChain, self.Arch, self.SourceDir, self.MetaFile.BaseName)
> > +        HashFile = path.join(FileDir, self.Name + '.hash')
> > +        if os.path.exists(HashFile):
> > +            f = open(HashFile, 'r')
> > +            CacheHash = f.read()
> > +            f.close()
> > +            self.GenModuleHash()
> > +            if GlobalData.gModuleHash[self.Arch][self.Name]:
> > +                if CacheHash == GlobalData.gModuleHash[self.Arch][self.Name]:
> > +                    for root, dir, files in os.walk(FileDir):
> > +                        for f in files:
> > +                            if self.Name + '.hash' in f:
> > +                                CopyFileOnChange(HashFile, self.BuildDir)
> > +                            else:
> > +                                File = path.join(root, f)
> > +                                sub_dir = os.path.relpath(File, FileDir)
> > +                                destination_file = os.path.join(self.OutputDir, sub_dir)
> > +                                destination_dir = os.path.dirname(destination_file)
> > +                                CreateDirectory(destination_dir)
> > +                                CopyFileOnChange(File, destination_dir)
> > +                    if self.Name == "PcdPeim" or self.Name == "PcdDxe":
> > +                        CreatePcdDatabaseCode(self, TemplateString(), TemplateString())
> > +                    return True
> > +        return False
> > +
> > +    ## Create makefile for the module and its dependent libraries
> > +    #
> > +    #   @param      CreateLibraryMakeFile   Flag indicating if or not the makefiles of
> > +    #                                       dependent libraries will be created
> > +    #
> > +    @cached_class_function
> > +    def CreateMakeFile(self, CreateLibraryMakeFile=True, GenFfsList = []):
> > +        # nest this function inside it's only caller.
> > +        def CreateTimeStamp():
> > +            FileSet = {self.MetaFile.Path}
> > +
> > +            for SourceFile in self.Module.Sources:
> > +                FileSet.add (SourceFile.Path)
> > +
> > +            for Lib in self.DependentLibraryList:
> > +                FileSet.add (Lib.MetaFile.Path)
> > +
> > +            for f in self.AutoGenDepSet:
> > +                FileSet.add (f.Path)
> > +
> > +            if os.path.exists (self.TimeStampPath):
> > +                os.remove (self.TimeStampPath)
> > +            with open(self.TimeStampPath, 'w+') as fd:
> > +                for f in FileSet:
> > +                    fd.write(f)
> > +                    fd.write("\n")
> > +
> > +        # Ignore generating makefile when it is a binary module
> > +        if self.IsBinaryModule:
> > +            return
> > +
> > +        self.GenFfsList = GenFfsList
> > +
> > +        if not self.IsLibrary and CreateLibraryMakeFile:
> > +            for LibraryAutoGen in self.LibraryAutoGenList:
> > +                LibraryAutoGen.CreateMakeFile()
> > +        # Don't enable if hash feature enabled, CanSkip uses timestamps to determine build skipping
> > +        if not GlobalData.gUseHashCache and self.CanSkip():
> > +            return
> > +
> > +        if len(self.CustomMakefile) == 0:
> > +            Makefile = GenMake.ModuleMakefile(self)
> > +        else:
> > +            Makefile = GenMake.CustomMakefile(self)
> > +        if Makefile.Generate():
> > +            EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %
> > +                            (self.Name, self.Arch))
> > +        else:
> > +            EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %
> > +                            (self.Name, self.Arch))
> > +
> > +        CreateTimeStamp()
> > +
> > +    def CopyBinaryFiles(self):
> > +        for File in self.Module.Binaries:
> > +            SrcPath = File.Path
> > +            DstPath = os.path.join(self.OutputDir, os.path.basename(SrcPath))
> > +            CopyLongFilePath(SrcPath, DstPath)
> > +    ## Create autogen code for the module and its dependent libraries
> > +    #
> > +    #   @param      CreateLibraryCodeFile   Flag indicating if or not the code of
> > +    #                                       dependent libraries will be created
> > +    #
> > +    def CreateCodeFile(self, CreateLibraryCodeFile=True):
> > +        if self.IsCodeFileCreated:
> > +            return
> > +
> > +        # Need to generate PcdDatabase even PcdDriver is binarymodule
> > +        if self.IsBinaryModule and self.PcdIsDriver != '':
> > +            CreatePcdDatabaseCode(self, TemplateString(), TemplateString())
> > +            return
> > +        if self.IsBinaryModule:
> > +            if self.IsLibrary:
> > +                self.CopyBinaryFiles()
> > +            return
> > +
> > +        if not self.IsLibrary and CreateLibraryCodeFile:
> > +            for LibraryAutoGen in self.LibraryAutoGenList:
> > +                LibraryAutoGen.CreateCodeFile()
> > +
> > +        # Don't enable if hash feature enabled, CanSkip uses timestamps to determine build skipping
> > +        if not GlobalData.gUseHashCache and self.CanSkip():
> > +            return
> > +
> > +        AutoGenList = []
> > +        IgoredAutoGenList = []
> > +
> > +        for File in self.AutoGenFileList:
> > +            if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):
> > +                AutoGenList.append(str(File))
> > +            else:
> > +                IgoredAutoGenList.append(str(File))
> > +
> > +
> > +        for ModuleType in self.DepexList:
> > +            # Ignore empty [depex] section or [depex] section for SUP_MODULE_USER_DEFINED module
> > +            if len(self.DepexList[ModuleType]) == 0 or ModuleType == SUP_MODULE_USER_DEFINED or ModuleType == SUP_MODULE_HOST_APPLICATION:
> > +                continue
> > +
> > +            Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
> > +            DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
> > +
> > +            if len(Dpx.PostfixNotation) != 0:
> > +                self.DepexGenerated = True
> > +
> > +            if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
> > +                AutoGenList.append(str(DpxFile))
> > +            else:
> > +                IgoredAutoGenList.append(str(DpxFile))
> > +
> > +        if IgoredAutoGenList == []:
> > +            EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %
> > +                            (" ".join(AutoGenList), self.Name, self.Arch))
> > +        elif AutoGenList == []:
> > +            EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %
> > +                            (" ".join(IgoredAutoGenList), self.Name, self.Arch))
> > +        else:
> > +            EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %
> > +                            (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
> > +
> > +        self.IsCodeFileCreated = True
> > +        return AutoGenList
> > +
> > +    ## Summarize the ModuleAutoGen objects of all libraries used by this module
> > +    @cached_property
> > +    def LibraryAutoGenList(self):
> > +        RetVal = []
> > +        for Library in self.DependentLibraryList:
> > +            La = ModuleAutoGen(
> > +                        self.Workspace,
> > +                        Library.MetaFile,
> > +                        self.BuildTarget,
> > +                        self.ToolChain,
> > +                        self.Arch,
> > +                        self.PlatformInfo.MetaFile,
> > +                        self.DataPipe
> > +                        )
> > +            La.IsLibrary = True
> > +            if La not in RetVal:
> > +                RetVal.append(La)
> > +                for Lib in La.CodaTargetList:
> > +                    self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)
> > +        return RetVal
> > +
> > +    def GenModuleHash(self):
> > +        # Initialize a dictionary for each arch type
> > +        if self.Arch not in GlobalData.gModuleHash:
> > +            GlobalData.gModuleHash[self.Arch] = {}
> > +
> > +        # Early exit if module or library has been hashed and is in memory
> > +        if self.Name in GlobalData.gModuleHash[self.Arch]:
> > +            return GlobalData.gModuleHash[self.Arch][self.Name].encode('utf-8')
> > +
> > +        # Initialze hash object
> > +        m = hashlib.md5()
> > +
> > +        # Add Platform level hash
> > +        m.update(GlobalData.gPlatformHash.encode('utf-8'))
> > +
> > +        # Add Package level hash
> > +        if self.DependentPackageList:
> > +            for Pkg in sorted(self.DependentPackageList, key=lambda x: x.PackageName):
> > +                if Pkg.PackageName in GlobalData.gPackageHash:
> > +                    m.update(GlobalData.gPackageHash[Pkg.PackageName].encode('utf-8'))
> > +
> > +        # Add Library hash
> > +        if self.LibraryAutoGenList:
> > +            for Lib in sorted(self.LibraryAutoGenList, key=lambda x: x.Name):
> > +                if Lib.Name not in GlobalData.gModuleHash[self.Arch]:
> > +                    Lib.GenModuleHash()
> > +                m.update(GlobalData.gModuleHash[self.Arch][Lib.Name].encode('utf-8'))
> > +
> > +        # Add Module self
> > +        f = open(str(self.MetaFile), 'rb')
> > +        Content = f.read()
> > +        f.close()
> > +        m.update(Content)
> > +
> > +        # Add Module's source files
> > +        if self.SourceFileList:
> > +            for File in sorted(self.SourceFileList, key=lambda x: str(x)):
> > +                f = open(str(File), 'rb')
> > +                Content = f.read()
> > +                f.close()
> > +                m.update(Content)
> > +
> > +        GlobalData.gModuleHash[self.Arch][self.Name] = m.hexdigest()
> > +
> > +        return GlobalData.gModuleHash[self.Arch][self.Name].encode('utf-8')
> > +
> > +    ## Decide whether we can skip the ModuleAutoGen process
> > +    def CanSkipbyHash(self):
> > +        # Hashing feature is off
> > +        if not GlobalData.gUseHashCache:
> > +            return False
> > +
> > +        # Initialize a dictionary for each arch type
> > +        if self.Arch not in GlobalData.gBuildHashSkipTracking:
> > +            GlobalData.gBuildHashSkipTracking[self.Arch] = dict()
> > +
> > +        # If library or Module is binary do not skip by hash
> > +        if self.IsBinaryModule:
> > +            return False
> > +
> > +        # .inc is contains binary information so do not skip by hash as well
> > +        for f_ext in self.SourceFileList:
> > +            if '.inc' in str(f_ext):
> > +                return False
> > +
> > +        # Use Cache, if exists and if Module has a copy in cache
> > +        if GlobalData.gBinCacheSource and self.AttemptModuleCacheCopy():
> > +            return True
> > +
> > +        # Early exit for libraries that haven't yet finished building
> > +        HashFile = path.join(self.BuildDir, self.Name + ".hash")
> > +        if self.IsLibrary and not os.path.exists(HashFile):
> > +            return False
> > +
> > +        # Return a Boolean based on if can skip by hash, either from memory or from IO.
> > +        if self.Name not in GlobalData.gBuildHashSkipTracking[self.Arch]:
> > +            # If hashes are the same, SaveFileOnChange() will return False.
> > +            GlobalData.gBuildHashSkipTracking[self.Arch][self.Name] = not SaveFileOnChange(HashFile, self.GenModuleHash(), True)
> > +            return GlobalData.gBuildHashSkipTracking[self.Arch][self.Name]
> > +        else:
> > +            return GlobalData.gBuildHashSkipTracking[self.Arch][self.Name]
> > +
> > +    ## Decide whether we can skip the ModuleAutoGen process
> > +    #  If any source file is newer than the module than we cannot skip
> > +    #
> > +    def CanSkip(self):
> > +        if self.MakeFileDir in GlobalData.gSikpAutoGenCache:
> > +            return True
> > +        if not os.path.exists(self.TimeStampPath):
> > +            return False
> > +        #last creation time of the module
> > +        DstTimeStamp = os.stat(self.TimeStampPath)[8]
> > +
> > +        SrcTimeStamp = self.Workspace._SrcTimeStamp
> > +        if SrcTimeStamp > DstTimeStamp:
> > +            return False
> > +
> > +        with open(self.TimeStampPath,'r') as f:
> > +            for source in f:
> > +                source = source.rstrip('\n')
> > +                if not os.path.exists(source):
> > +                    return False
> > +                if source not in ModuleAutoGen.TimeDict :
> > +                    ModuleAutoGen.TimeDict[source] = os.stat(source)[8]
> > +                if ModuleAutoGen.TimeDict[source] > DstTimeStamp:
> > +                    return False
> > +        GlobalData.gSikpAutoGenCache.add(self.MakeFileDir)
> > +        return True
> > +
> > +    @cached_property
> > +    def TimeStampPath(self):
> > +        return os.path.join(self.MakeFileDir, 'AutoGenTimeStamp')
> > diff --git a/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py b/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py
> > new file mode 100644
> > index 000000000000..c7591253debd
> > --- /dev/null
> > +++ b/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py
> > @@ -0,0 +1,619 @@
> > +## @file
> > +# Create makefile for MS nmake and GNU make
> > +#
> > +# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +from __future__ import absolute_import
> > +from Workspace.WorkspaceDatabase import WorkspaceDatabase,BuildDB
> > +from Common.caching import cached_property
> > +from AutoGen.BuildEngine import BuildRule,AutoGenReqBuildRuleVerNum
> > +from AutoGen.AutoGen import CalculatePriorityValue
> > +from Common.Misc import CheckPcdDatum,GuidValue
> > +from Common.Expression import ValueExpressionEx
> > +from Common.DataType import *
> > +from CommonDataClass.Exceptions import *
> > +from CommonDataClass.CommonClass import SkuInfoClass
> > +import Common.EdkLogger as EdkLogger
> > +from Common.BuildToolError import OPTION_CONFLICT,FORMAT_INVALID,RESOURCE_NOT_AVAILABLE
> > +from Common.MultipleWorkspace import MultipleWorkspace as mws
> > +from collections import defaultdict
> > +from Common.Misc import PathClass
> > +import os
> > +
> > +
> > +#
> > +# The priority list while override build option
> > +#
> > +PrioList = {"0x11111"  : 16,     #  TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
> > +            "0x01111"  : 15,     #  ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
> > +            "0x10111"  : 14,     #  TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
> > +            "0x00111"  : 13,     #  ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
> > +            "0x11011"  : 12,     #  TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
> > +            "0x01011"  : 11,     #  ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
> > +            "0x10011"  : 10,     #  TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
> > +            "0x00011"  : 9,      #  ******_*********_****_COMMANDTYPE_ATTRIBUTE
> > +            "0x11101"  : 8,      #  TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
> > +            "0x01101"  : 7,      #  ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
> > +            "0x10101"  : 6,      #  TARGET_*********_ARCH_***********_ATTRIBUTE
> > +            "0x00101"  : 5,      #  ******_*********_ARCH_***********_ATTRIBUTE
> > +            "0x11001"  : 4,      #  TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
> > +            "0x01001"  : 3,      #  ******_TOOLCHAIN_****_***********_ATTRIBUTE
> > +            "0x10001"  : 2,      #  TARGET_*********_****_***********_ATTRIBUTE
> > +            "0x00001"  : 1}      #  ******_*********_****_***********_ATTRIBUTE (Lowest)
> > +## Base class for AutoGen
> > +#
> > +#   This class just implements the cache mechanism of AutoGen objects.
> > +#
> > +class AutoGenInfo(object):
> > +    # database to maintain the objects in each child class
> > +    __ObjectCache = {}    # (BuildTarget, ToolChain, ARCH, platform file): AutoGen object
> > +
> > +    ## Factory method
> > +    #
> > +    #   @param  Class           class object of real AutoGen class
> > +    #                           (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
> > +    #   @param  Workspace       Workspace directory or WorkspaceAutoGen object
> > +    #   @param  MetaFile        The path of meta file
> > +    #   @param  Target          Build target
> > +    #   @param  Toolchain       Tool chain name
> > +    #   @param  Arch            Target arch
> > +    #   @param  *args           The specific class related parameters
> > +    #   @param  **kwargs        The specific class related dict parameters
> > +    #
> > +    @classmethod
> > +    def GetCache(cls):
> > +        return cls.__ObjectCache
> > +    def __new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
> > +        # check if the object has been created
> > +        Key = (Target, Toolchain, Arch, MetaFile)
> > +        if Key in cls.__ObjectCache:
> > +            # if it exists, just return it directly
> > +            return cls.__ObjectCache[Key]
> > +            # it didnt exist. create it, cache it, then return it
> > +        RetVal = cls.__ObjectCache[Key] = super(AutoGenInfo, cls).__new__(cls)
> > +        return RetVal
> > +
> > +
> > +    ## hash() operator
> > +    #
> > +    #  The file path of platform file will be used to represent hash value of this object
> > +    #
> > +    #   @retval int     Hash value of the file path of platform file
> > +    #
> > +    def __hash__(self):
> > +        return hash(self.MetaFile)
> > +
> > +    ## str() operator
> > +    #
> > +    #  The file path of platform file will be used to represent this object
> > +    #
> > +    #   @retval string  String of platform file path
> > +    #
> > +    def __str__(self):
> > +        return str(self.MetaFile)
> > +
> > +    ## "==" operator
> > +    def __eq__(self, Other):
> > +        return Other and self.MetaFile == Other
> > +
> > +    ## Expand * in build option key
> > +    #
> > +    #   @param  Options     Options to be expanded
> > +    #   @param  ToolDef     Use specified ToolDef instead of full version.
> > +    #                       This is needed during initialization to prevent
> > +    #                       infinite recursion betweeh BuildOptions,
> > +    #                       ToolDefinition, and this function.
> > +    #
> > +    #   @retval options     Options expanded
> > +    #
> > +    def _ExpandBuildOption(self, Options, ModuleStyle=None, ToolDef=None):
> > +        if not ToolDef:
> > +            ToolDef = self.ToolDefinition
> > +        BuildOptions = {}
> > +        FamilyMatch  = False
> > +        FamilyIsNull = True
> > +
> > +        OverrideList = {}
> > +        #
> > +        # Construct a list contain the build options which need override.
> > +        #
> > +        for Key in Options:
> > +            #
> > +            # Key[0] -- tool family
> > +            # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
> > +            #
> > +            if (Key[0] == self.BuildRuleFamily and
> > +                (ModuleStyle is None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):
> > +                Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')
> > +                if (Target == self.BuildTarget or Target == TAB_STAR) and\
> > +                    (ToolChain == self.ToolChain or ToolChain == TAB_STAR) and\
> > +                    (Arch == self.Arch or Arch == TAB_STAR) and\
> > +                    Options[Key].startswith("="):
> > +
> > +                    if OverrideList.get(Key[1]) is not None:
> > +                        OverrideList.pop(Key[1])
> > +                    OverrideList[Key[1]] = Options[Key]
> > +
> > +        #
> > +        # Use the highest priority value.
> > +        #
> > +        if (len(OverrideList) >= 2):
> > +            KeyList = list(OverrideList.keys())
> > +            for Index in range(len(KeyList)):
> > +                NowKey = KeyList[Index]
> > +                Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")
> > +                for Index1 in range(len(KeyList) - Index - 1):
> > +                    NextKey = KeyList[Index1 + Index + 1]
> > +                    #
> > +                    # Compare two Key, if one is included by another, choose the higher priority one
> > +                    #
> > +                    Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")
> > +                    if (Target1 == Target2 or Target1 == TAB_STAR or Target2 == TAB_STAR) and\
> > +                        (ToolChain1 == ToolChain2 or ToolChain1 == TAB_STAR or ToolChain2 == TAB_STAR) and\
> > +                        (Arch1 == Arch2 or Arch1 == TAB_STAR or Arch2 == TAB_STAR) and\
> > +                        (CommandType1 == CommandType2 or CommandType1 == TAB_STAR or CommandType2 == TAB_STAR) and\
> > +                        (Attr1 == Attr2 or Attr1 == TAB_STAR or Attr2 == TAB_STAR):
> > +
> > +                        if CalculatePriorityValue(NowKey) > CalculatePriorityValue(NextKey):
> > +                            if Options.get((self.BuildRuleFamily, NextKey)) is not None:
> > +                                Options.pop((self.BuildRuleFamily, NextKey))
> > +                        else:
> > +                            if Options.get((self.BuildRuleFamily, NowKey)) is not None:
> > +                                Options.pop((self.BuildRuleFamily, NowKey))
> > +
> > +        for Key in Options:
> > +            if ModuleStyle is not None and len (Key) > 2:
> > +                # Check Module style is EDK or EDKII.
> > +                # Only append build option for the matched style module.
> > +                if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
> > +                    continue
> > +                elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
> > +                    continue
> > +            Family = Key[0]
> > +            Target, Tag, Arch, Tool, Attr = Key[1].split("_")
> > +            # if tool chain family doesn't match, skip it
> > +            if Tool in ToolDef and Family != "":
> > +                FamilyIsNull = False
> > +                if ToolDef[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
> > +                    if Family != ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
> > +                        continue
> > +                elif Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
> > +                    continue
> > +                FamilyMatch = True
> > +            # expand any wildcard
> > +            if Target == TAB_STAR or Target == self.BuildTarget:
> > +                if Tag == TAB_STAR or Tag == self.ToolChain:
> > +                    if Arch == TAB_STAR or Arch == self.Arch:
> > +                        if Tool not in BuildOptions:
> > +                            BuildOptions[Tool] = {}
> > +                        if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
> > +                            BuildOptions[Tool][Attr] = Options[Key]
> > +                        else:
> > +                            # append options for the same tool except PATH
> > +                            if Attr != 'PATH':
> > +                                BuildOptions[Tool][Attr] += " " + Options[Key]
> > +                            else:
> > +                                BuildOptions[Tool][Attr] = Options[Key]
> > +        # Build Option Family has been checked, which need't to be checked again for family.
> > +        if FamilyMatch or FamilyIsNull:
> > +            return BuildOptions
> > +
> > +        for Key in Options:
> > +            if ModuleStyle is not None and len (Key) > 2:
> > +                # Check Module style is EDK or EDKII.
> > +                # Only append build option for the matched style module.
> > +                if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
> > +                    continue
> > +                elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
> > +                    continue
> > +            Family = Key[0]
> > +            Target, Tag, Arch, Tool, Attr = Key[1].split("_")
> > +            # if tool chain family doesn't match, skip it
> > +            if Tool not in ToolDef or Family == "":
> > +                continue
> > +            # option has been added before
> > +            if Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
> > +                continue
> > +
> > +            # expand any wildcard
> > +            if Target == TAB_STAR or Target == self.BuildTarget:
> > +                if Tag == TAB_STAR or Tag == self.ToolChain:
> > +                    if Arch == TAB_STAR or Arch == self.Arch:
> > +                        if Tool not in BuildOptions:
> > +                            BuildOptions[Tool] = {}
> > +                        if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
> > +                            BuildOptions[Tool][Attr] = Options[Key]
> > +                        else:
> > +                            # append options for the same tool except PATH
> > +                            if Attr != 'PATH':
> > +                                BuildOptions[Tool][Attr] += " " + Options[Key]
> > +                            else:
> > +                                BuildOptions[Tool][Attr] = Options[Key]
> > +        return BuildOptions
> > +#
> > +#This class is the pruned WorkSpaceAutoGen for ModuleAutoGen in multiple thread
> > +#
> > +class WorkSpaceInfo(AutoGenInfo):
> > +    def __init__(self,Workspace, MetaFile, Target, ToolChain, Arch):
> > +        self._SrcTimeStamp = 0
> > +        self.Db = BuildDB
> > +        self.BuildDatabase = self.Db.BuildObject
> > +        self.Target = Target
> > +        self.ToolChain = ToolChain
> > +        self.WorkspaceDir = Workspace
> > +        self.ActivePlatform = MetaFile
> > +        self.ArchList = Arch
> > +
> > +
> > +class PlatformInfo(AutoGenInfo):
> > +    def __init__(self, Workspace, MetaFile, Target, ToolChain, Arch,DataPipe):
> > +        self.Wa = Workspace
> > +        self.WorkspaceDir = self.Wa.WorkspaceDir
> > +        self.MetaFile = MetaFile
> > +        self.Arch = Arch
> > +        self.Target = Target
> > +        self.BuildTarget = Target
> > +        self.ToolChain = ToolChain
> > +        self.Platform = self.Wa.BuildDatabase[self.MetaFile, self.Arch, self.Target, self.ToolChain]
> > +
> > +        self.SourceDir = MetaFile.SubDir
> > +        self.DataPipe = DataPipe
> > +    @cached_property
> > +    def _AsBuildModuleList(self):
> > +        retVal = self.DataPipe.Get("AsBuildModuleList")
> > +        if retVal is None:
> > +            retVal = {}
> > +        return retVal
> > +
> > +    ## Test if a module is supported by the platform
> > +    #
> > +    #  An error will be raised directly if the module or its arch is not supported
> > +    #  by the platform or current configuration
> > +    #
> > +    def ValidModule(self, Module):
> > +        return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \
> > +            or Module in self._AsBuildModuleList
> > +
> > +    @cached_property
> > +    def ToolChainFamily(self):
> > +        retVal = self.DataPipe.Get("ToolChainFamily")
> > +        if retVal is None:
> > +            retVal = {}
> > +        return retVal
> > +
> > +    @cached_property
> > +    def BuildRuleFamily(self):
> > +        retVal = self.DataPipe.Get("BuildRuleFamily")
> > +        if retVal is None:
> > +            retVal = {}
> > +        return retVal
> > +
> > +    @cached_property
> > +    def _MbList(self):
> > +        return [self.Wa.BuildDatabase[m, self.Arch, self.BuildTarget, self.ToolChain] for m in self.Platform.Modules]
> > +
> > +    @cached_property
> > +    def PackageList(self):
> > +        RetVal = set()
> > +        for dec_file,Arch in self.DataPipe.Get("PackageList"):
> > +            RetVal.add(self.Wa.BuildDatabase[dec_file,Arch,self.BuildTarget, self.ToolChain])
> > +        return list(RetVal)
> > +
> > +    ## Return the directory to store all intermediate and final files built
> > +    @cached_property
> > +    def BuildDir(self):
> > +        if os.path.isabs(self.OutputDir):
> > +            RetVal = os.path.join(
> > +                                os.path.abspath(self.OutputDir),
> > +                                self.Target + "_" + self.ToolChain,
> > +                                )
> > +        else:
> > +            RetVal = os.path.join(
> > +                                self.WorkspaceDir,
> > +                                self.OutputDir,
> > +                                self.Target + "_" + self.ToolChain,
> > +                                )
> > +        return RetVal
> > +
> > +    ## Return the build output directory platform specifies
> > +    @cached_property
> > +    def OutputDir(self):
> > +        return self.Platform.OutputDirectory
> > +
> > +    ## Return platform name
> > +    @cached_property
> > +    def Name(self):
> > +        return self.Platform.PlatformName
> > +
> > +    ## Return meta-file GUID
> > +    @cached_property
> > +    def Guid(self):
> > +        return self.Platform.Guid
> > +
> > +    ## Return platform version
> > +    @cached_property
> > +    def Version(self):
> > +        return self.Platform.Version
> > +
> > +    ## Return paths of tools
> > +    @cached_property
> > +    def ToolDefinition(self):
> > +        retVal = self.DataPipe.Get("TOOLDEF")
> > +        if retVal is None:
> > +            retVal = {}
> > +        return retVal
> > +
> > +    ## Return build command string
> > +    #
> > +    #   @retval     string  Build command string
> > +    #
> > +    @cached_property
> > +    def BuildCommand(self):
> > +        retVal = self.DataPipe.Get("BuildCommand")
> > +        if retVal is None:
> > +            retVal = []
> > +        return retVal
> > +
> > +    @cached_property
> > +    def PcdTokenNumber(self):
> > +        retVal = self.DataPipe.Get("PCD_TNUM")
> > +        if retVal is None:
> > +            retVal = {}
> > +        return retVal
> > +
> > +    ## Override PCD setting (type, value, ...)
> > +    #
> > +    #   @param  ToPcd       The PCD to be overridden
> > +    #   @param  FromPcd     The PCD overriding from
> > +    #
> > +    def _OverridePcd(self, ToPcd, FromPcd, Module="", Msg="", Library=""):
> > +        #
> > +        # in case there's PCDs coming from FDF file, which have no type given.
> > +        # at this point, ToPcd.Type has the type found from dependent
> > +        # package
> > +        #
> > +        TokenCName = ToPcd.TokenCName
> > +        for PcdItem in self.MixedPcd:
> > +            if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in self.MixedPcd[PcdItem]:
> > +                TokenCName = PcdItem[0]
> > +                break
> > +        if FromPcd is not None:
> > +            if ToPcd.Pending and FromPcd.Type:
> > +                ToPcd.Type = FromPcd.Type
> > +            elif ToPcd.Type and FromPcd.Type\
> > +                and ToPcd.Type != FromPcd.Type and ToPcd.Type in FromPcd.Type:
> > +                if ToPcd.Type.strip() == TAB_PCDS_DYNAMIC_EX:
> > +                    ToPcd.Type = FromPcd.Type
> > +            elif ToPcd.Type and FromPcd.Type \
> > +                and ToPcd.Type != FromPcd.Type:
> > +                if Library:
> > +                    Module = str(Module) + " 's library file (" + str(Library) + ")"
> > +                EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",
> > +                                ExtraData="%s.%s is used as [%s] in module %s, but as [%s] in %s."\
> > +                                          % (ToPcd.TokenSpaceGuidCName, TokenCName,
> > +                                             ToPcd.Type, Module, FromPcd.Type, Msg),
> > +                                          File=self.MetaFile)
> > +
> > +            if FromPcd.MaxDatumSize:
> > +                ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
> > +                ToPcd.MaxSizeUserSet = FromPcd.MaxDatumSize
> > +            if FromPcd.DefaultValue:
> > +                ToPcd.DefaultValue = FromPcd.DefaultValue
> > +            if FromPcd.TokenValue:
> > +                ToPcd.TokenValue = FromPcd.TokenValue
> > +            if FromPcd.DatumType:
> > +                ToPcd.DatumType = FromPcd.DatumType
> > +            if FromPcd.SkuInfoList:
> > +                ToPcd.SkuInfoList = FromPcd.SkuInfoList
> > +            if FromPcd.UserDefinedDefaultStoresFlag:
> > +                ToPcd.UserDefinedDefaultStoresFlag = FromPcd.UserDefinedDefaultStoresFlag
> > +            # Add Flexible PCD format parse
> > +            if ToPcd.DefaultValue:
> > +                try:
> > +                    ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self._GuidDict)(True)
> > +                except BadExpression as Value:
> > +                    EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),
> > +                                        File=self.MetaFile)
> > +
> > +            # check the validation of datum
> > +            IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)
> > +            if not IsValid:
> > +                EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
> > +                                ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, TokenCName))
> > +            ToPcd.validateranges = FromPcd.validateranges
> > +            ToPcd.validlists = FromPcd.validlists
> > +            ToPcd.expressions = FromPcd.expressions
> > +            ToPcd.CustomAttribute = FromPcd.CustomAttribute
> > +
> > +        if FromPcd is not None and ToPcd.DatumType == TAB_VOID and not ToPcd.MaxDatumSize:
> > +            EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \
> > +                            % (ToPcd.TokenSpaceGuidCName, TokenCName))
> > +            Value = ToPcd.DefaultValue
> > +            if not Value:
> > +                ToPcd.MaxDatumSize = '1'
> > +            elif Value[0] == 'L':
> > +                ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)
> > +            elif Value[0] == '{':
> > +                ToPcd.MaxDatumSize = str(len(Value.split(',')))
> > +            else:
> > +                ToPcd.MaxDatumSize = str(len(Value) - 1)
> > +
> > +        # apply default SKU for dynamic PCDS if specified one is not available
> > +        if (ToPcd.Type in PCD_DYNAMIC_TYPE_SET or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_SET) \
> > +            and not ToPcd.SkuInfoList:
> > +            if self.Platform.SkuName in self.Platform.SkuIds:
> > +                SkuName = self.Platform.SkuName
> > +            else:
> > +                SkuName = TAB_DEFAULT
> > +            ToPcd.SkuInfoList = {
> > +                SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName][0], '', '', '', '', '', ToPcd.DefaultValue)
> > +            }
> > +
> > +    def ApplyPcdSetting(self, Module, Pcds, Library=""):
> > +        # for each PCD in module
> > +        for Name, Guid in Pcds:
> > +            PcdInModule = Pcds[Name, Guid]
> > +            # find out the PCD setting in platform
> > +            if (Name, Guid) in self.Pcds:
> > +                PcdInPlatform = self.Pcds[Name, Guid]
> > +            else:
> > +                PcdInPlatform = None
> > +            # then override the settings if any
> > +            self._OverridePcd(PcdInModule, PcdInPlatform, Module, Msg="DSC PCD sections", Library=Library)
> > +            # resolve the VariableGuid value
> > +            for SkuId in PcdInModule.SkuInfoList:
> > +                Sku = PcdInModule.SkuInfoList[SkuId]
> > +                if Sku.VariableGuid == '': continue
> > +                Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList, self.MetaFile.Path)
> > +                if Sku.VariableGuidValue is None:
> > +                    PackageList = "\n\t".join(str(P) for P in self.PackageList)
> > +                    EdkLogger.error(
> > +                                'build',
> > +                                RESOURCE_NOT_AVAILABLE,
> > +                                "Value of GUID [%s] is not found in" % Sku.VariableGuid,
> > +                                ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \
> > +                                                        % (Guid, Name, str(Module)),
> > +                                File=self.MetaFile
> > +                                )
> > +
> > +        # override PCD settings with module specific setting
> > +        if Module in self.Platform.Modules:
> > +            PlatformModule = self.Platform.Modules[str(Module)]
> > +            for Key  in PlatformModule.Pcds:
> > +                if self.BuildOptionPcd:
> > +                    for pcd in self.BuildOptionPcd:
> > +                        (TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue, _) = pcd
> > +                        if (TokenCName, TokenSpaceGuidCName) == Key and FieldName =="":
> > +                            PlatformModule.Pcds[Key].DefaultValue = pcdvalue
> > +                            PlatformModule.Pcds[Key].PcdValueFromComm = pcdvalue
> > +                            break
> > +                Flag = False
> > +                if Key in Pcds:
> > +                    ToPcd = Pcds[Key]
> > +                    Flag = True
> > +                elif Key in self.MixedPcd:
> > +                    for PcdItem in self.MixedPcd[Key]:
> > +                        if PcdItem in Pcds:
> > +                            ToPcd = Pcds[PcdItem]
> > +                            Flag = True
> > +                            break
> > +                if Flag:
> > +                    self._OverridePcd(ToPcd, PlatformModule.Pcds[Key], Module, Msg="DSC Components Module scoped PCD section", Library=Library)
> > +        # use PCD value to calculate the MaxDatumSize when it is not specified
> > +        for Name, Guid in Pcds:
> > +            Pcd = Pcds[Name, Guid]
> > +            if Pcd.DatumType == TAB_VOID and not Pcd.MaxDatumSize:
> > +                Pcd.MaxSizeUserSet = None
> > +                Value = Pcd.DefaultValue
> > +                if not Value:
> > +                    Pcd.MaxDatumSize = '1'
> > +                elif Value[0] == 'L':
> > +                    Pcd.MaxDatumSize = str((len(Value) - 2) * 2)
> > +                elif Value[0] == '{':
> > +                    Pcd.MaxDatumSize = str(len(Value.split(',')))
> > +                else:
> > +                    Pcd.MaxDatumSize = str(len(Value) - 1)
> > +        return list(Pcds.values())
> > +
> > +    @cached_property
> > +    def Pcds(self):
> > +        PlatformPcdData = self.DataPipe.Get("PLA_PCD")
> > +#         for pcd in PlatformPcdData:
> > +#             for skuid in pcd.SkuInfoList:
> > +#                 pcd.SkuInfoList[skuid] = self.CreateSkuInfoFromDict(pcd.SkuInfoList[skuid])
> > +        return {(pcddata.TokenCName,pcddata.TokenSpaceGuidCName):pcddata for pcddata in PlatformPcdData}
> > +
> > +    def CreateSkuInfoFromDict(self,SkuInfoDict):
> > +        return SkuInfoClass(
> > +            SkuInfoDict.get("SkuIdName"),
> > +            SkuInfoDict.get("SkuId"),
> > +            SkuInfoDict.get("VariableName"),
> > +            SkuInfoDict.get("VariableGuid"),
> > +            SkuInfoDict.get("VariableOffset"),
> > +            SkuInfoDict.get("HiiDefaultValue"),
> > +            SkuInfoDict.get("VpdOffset"),
> > +            SkuInfoDict.get("DefaultValue"),
> > +            SkuInfoDict.get("VariableGuidValue"),
> > +            SkuInfoDict.get("VariableAttribute",""),
> > +            SkuInfoDict.get("DefaultStore",None)
> > +            )
> > +    @cached_property
> > +    def MixedPcd(self):
> > +        return self.DataPipe.Get("MixedPcd")
> > +    @cached_property
> > +    def _GuidDict(self):
> > +        RetVal = self.DataPipe.Get("GuidDict")
> > +        if RetVal is None:
> > +            RetVal = {}
> > +        return RetVal
> > +    @cached_property
> > +    def BuildOptionPcd(self):
> > +        return self.DataPipe.Get("BuildOptPcd")
> > +    def ApplyBuildOption(self,module):
> > +        PlatformOptions = self.DataPipe.Get("PLA_BO")
> > +        ModuleBuildOptions = self.DataPipe.Get("MOL_BO")
> > +        ModuleOptionFromDsc = ModuleBuildOptions.get((module.MetaFile.File,module.MetaFile.Root))
> > +        if ModuleOptionFromDsc:
> > +            ModuleTypeOptions, PlatformModuleOptions = ModuleOptionFromDsc["ModuleTypeOptions"],ModuleOptionFromDsc["PlatformModuleOptions"]
> > +        else:
> > +            ModuleTypeOptions, PlatformModuleOptions = {}, {}
> > +        ToolDefinition = self.DataPipe.Get("TOOLDEF")
> > +        ModuleOptions = self._ExpandBuildOption(module.BuildOptions)
> > +        BuildRuleOrder = None
> > +        for Options in [ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
> > +            for Tool in Options:
> > +                for Attr in Options[Tool]:
> > +                    if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
> > +                        BuildRuleOrder = Options[Tool][Attr]
> > +
> > +        AllTools = set(list(ModuleOptions.keys()) + list(PlatformOptions.keys()) +
> > +                       list(PlatformModuleOptions.keys()) + list(ModuleTypeOptions.keys()) +
> > +                       list(ToolDefinition.keys()))
> > +        BuildOptions = defaultdict(lambda: defaultdict(str))
> > +        for Tool in AllTools:
> > +            for Options in [ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
> > +                if Tool not in Options:
> > +                    continue
> > +                for Attr in Options[Tool]:
> > +                    #
> > +                    # Do not generate it in Makefile
> > +                    #
> > +                    if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
> > +                        continue
> > +                    Value = Options[Tool][Attr]
> > +                    # check if override is indicated
> > +                    if Value.startswith('='):
> > +                        BuildOptions[Tool][Attr] = mws.handleWsMacro(Value[1:])
> > +                    else:
> > +                        if Attr != 'PATH':
> > +                            BuildOptions[Tool][Attr] += " " + mws.handleWsMacro(Value)
> > +                        else:
> > +                            BuildOptions[Tool][Attr] = mws.handleWsMacro(Value)
> > +
> > +        return BuildOptions, BuildRuleOrder
> > +
> > +    def ApplyLibraryInstance(self,module):
> > +        alldeps = self.DataPipe.Get("DEPS")
> > +        if alldeps is None:
> > +            alldeps = {}
> > +        mod_libs = alldeps.get((module.MetaFile.File,module.MetaFile.Root,module.Arch,module.MetaFile.Path),[])
> > +        retVal = []
> > +        for (file_path,root,arch,abs_path) in mod_libs:
> > +            libMetaFile = PathClass(file_path,root)
> > +            libMetaFile.OriginalPath = PathClass(file_path,root)
> > +            libMetaFile.Path = abs_path
> > +            retVal.append(self.Wa.BuildDatabase[libMetaFile, arch, self.Target,self.ToolChain])
> > +        return retVal
> > +
> > +    ## Parse build_rule.txt in Conf Directory.
> > +    #
> > +    #   @retval     BuildRule object
> > +    #
> > +    @cached_property
> > +    def BuildRule(self):
> > +        WInfo = self.DataPipe.Get("P_Info")
> > +        RetVal = WInfo.get("BuildRuleFile")
> > +        if RetVal._FileVersion == "":
> > +            RetVal._FileVersion = AutoGenReqBuildRuleVerNum
> > +        return RetVal
> > diff --git a/BaseTools/Source/Python/AutoGen/PlatformAutoGen.py b/BaseTools/Source/Python/AutoGen/PlatformAutoGen.py
> > new file mode 100644
> > index 000000000000..6c947eca2b57
> > --- /dev/null
> > +++ b/BaseTools/Source/Python/AutoGen/PlatformAutoGen.py
> > @@ -0,0 +1,1505 @@
> > +## @file
> > +# Create makefile for MS nmake and GNU make
> > +#
> > +# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +
> > +## Import Modules
> > +#
> > +from __future__ import print_function
> > +from __future__ import absolute_import
> > +import os.path as path
> > +import copy
> > +from collections import defaultdict
> > +
> > +from .BuildEngine import BuildRule,gDefaultBuildRuleFile,AutoGenReqBuildRuleVerNum
> > +from .GenVar import VariableMgr, var_info
> > +from . import GenMake
> > +from AutoGen.DataPipe import MemoryDataPipe
> > +from AutoGen.ModuleAutoGen import ModuleAutoGen
> > +from AutoGen.AutoGen import AutoGen
> > +from AutoGen.AutoGen import CalculatePriorityValue
> > +from Workspace.WorkspaceCommon import GetModuleLibInstances
> > +from CommonDataClass.CommonClass import SkuInfoClass
> > +from Common.caching import cached_class_function
> > +from Common.Expression import ValueExpressionEx
> > +from Common.StringUtils import StringToArray,NormPath
> > +from Common.BuildToolError import *
> > +from Common.DataType import *
> > +from Common.Misc import *
> > +import Common.VpdInfoFile as VpdInfoFile
> > +
> > +## Split command line option string to list
> > +#
> > +# subprocess.Popen needs the args to be a sequence. Otherwise there's problem
> > +# in non-windows platform to launch command
> > +#
> > +def _SplitOption(OptionString):
> > +    OptionList = []
> > +    LastChar = " "
> > +    OptionStart = 0
> > +    QuotationMark = ""
> > +    for Index in range(0, len(OptionString)):
> > +        CurrentChar = OptionString[Index]
> > +        if CurrentChar in ['"', "'"]:
> > +            if QuotationMark == CurrentChar:
> > +                QuotationMark = ""
> > +            elif QuotationMark == "":
> > +                QuotationMark = CurrentChar
> > +            continue
> > +        elif QuotationMark:
> > +            continue
> > +
> > +        if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]:
> > +            if Index > OptionStart:
> > +                OptionList.append(OptionString[OptionStart:Index - 1])
> > +            OptionStart = Index
> > +        LastChar = CurrentChar
> > +    OptionList.append(OptionString[OptionStart:])
> > +    return OptionList
> > +
> > +## AutoGen class for platform
> > +#
> > +#  PlatformAutoGen class will process the original information in platform
> > +#  file in order to generate makefile for platform.
> > +#
> > +class PlatformAutoGen(AutoGen):
> > +    # call super().__init__ then call the worker function with different parameter count
> > +    def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
> > +        if not hasattr(self, "_Init"):
> > +            self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch)
> > +            self._Init = True
> > +    #
> > +    # Used to store all PCDs for both PEI and DXE phase, in order to generate
> > +    # correct PCD database
> > +    #
> > +    _DynaPcdList_ = []
> > +    _NonDynaPcdList_ = []
> > +    _PlatformPcds = {}
> > +
> > +
> > +
> > +    ## Initialize PlatformAutoGen
> > +    #
> > +    #
> > +    #   @param      Workspace       WorkspaceAutoGen object
> > +    #   @param      PlatformFile    Platform file (DSC file)
> > +    #   @param      Target          Build target (DEBUG, RELEASE)
> > +    #   @param      Toolchain       Name of tool chain
> > +    #   @param      Arch            arch of the platform supports
> > +    #
> > +    def _InitWorker(self, Workspace, PlatformFile, Target, Toolchain, Arch):
> > +        EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))
> > +        GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)
> > +
> > +        self.MetaFile = PlatformFile
> > +        self.Workspace = Workspace
> > +        self.WorkspaceDir = Workspace.WorkspaceDir
> > +        self.ToolChain = Toolchain
> > +        self.BuildTarget = Target
> > +        self.Arch = Arch
> > +        self.SourceDir = PlatformFile.SubDir
> > +        self.FdTargetList = self.Workspace.FdTargetList
> > +        self.FvTargetList = self.Workspace.FvTargetList
> > +        # get the original module/package/platform objects
> > +        self.BuildDatabase = Workspace.BuildDatabase
> > +        self.DscBuildDataObj = Workspace.Platform
> > +
> > +        # flag indicating if the makefile/C-code file has been created or not
> > +        self.IsMakeFileCreated  = False
> > +
> > +        self._DynamicPcdList = None    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
> > +        self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
> > +
> > +        self._AsBuildInfList = []
> > +        self._AsBuildModuleList = []
> > +
> > +        self.VariableInfo = None
> > +
> > +        if GlobalData.gFdfParser is not None:
> > +            self._AsBuildInfList = GlobalData.gFdfParser.Profile.InfList
> > +            for Inf in self._AsBuildInfList:
> > +                InfClass = PathClass(NormPath(Inf), GlobalData.gWorkspace, self.Arch)
> > +                M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]
> > +                if not M.IsBinaryModule:
> > +                    continue
> > +                self._AsBuildModuleList.append(InfClass)
> > +        # get library/modules for build
> > +        self.LibraryBuildDirectoryList = []
> > +        self.ModuleBuildDirectoryList = []
> > +
> > +        self.DataPipe = MemoryDataPipe(self.BuildDir)
> > +        self.DataPipe.FillData(self)
> > +
> > +        return True
> > +    ## hash() operator of PlatformAutoGen
> > +    #
> > +    #  The platform file path and arch string will be used to represent
> > +    #  hash value of this object
> > +    #
> > +    #   @retval   int Hash value of the platform file path and arch
> > +    #
> > +    @cached_class_function
> > +    def __hash__(self):
> > +        return hash((self.MetaFile, self.Arch))
> > +    @cached_class_function
> > +    def __repr__(self):
> > +        return "%s [%s]" % (self.MetaFile, self.Arch)
> > +
> > +    ## Create autogen code for platform and modules
> > +    #
> > +    #  Since there's no autogen code for platform, this method will do nothing
> > +    #  if CreateModuleCodeFile is set to False.
> > +    #
> > +    #   @param      CreateModuleCodeFile    Flag indicating if creating module's
> > +    #                                       autogen code file or not
> > +    #
> > +    @cached_class_function
> > +    def CreateCodeFile(self, CreateModuleCodeFile=False):
> > +        # only module has code to be created, so do nothing if CreateModuleCodeFile is False
> > +        if not CreateModuleCodeFile:
> > +            return
> > +
> > +        for Ma in self.ModuleAutoGenList:
> > +            Ma.CreateCodeFile(True)
> > +
> > +    ## Generate Fds Command
> > +    @cached_property
> > +    def GenFdsCommand(self):
> > +        return self.Workspace.GenFdsCommand
> > +
> > +    ## Create makefile for the platform and modules in it
> > +    #
> > +    #   @param      CreateModuleMakeFile    Flag indicating if the makefile for
> > +    #                                       modules will be created as well
> > +    #
> > +    def CreateMakeFile(self, CreateModuleMakeFile=False, FfsCommand = {}):
> > +        if CreateModuleMakeFile:
> > +            for Ma in self._MaList:
> > +                key = (Ma.MetaFile.File, self.Arch)
> > +                if key in FfsCommand:
> > +                    Ma.CreateMakeFile(True, FfsCommand[key])
> > +                else:
> > +                    Ma.CreateMakeFile(True)
> > +
> > +        # no need to create makefile for the platform more than once
> > +        if self.IsMakeFileCreated:
> > +            return
> > +
> > +        # create library/module build dirs for platform
> > +        Makefile = GenMake.PlatformMakefile(self)
> > +        self.LibraryBuildDirectoryList = Makefile.GetLibraryBuildDirectoryList()
> > +        self.ModuleBuildDirectoryList = Makefile.GetModuleBuildDirectoryList()
> > +
> > +        self.IsMakeFileCreated = True
> > +
> > +    @property
> > +    def AllPcdList(self):
> > +        return self.DynamicPcdList + self.NonDynamicPcdList
> > +    ## Deal with Shared FixedAtBuild Pcds
> > +    #
> > +    def CollectFixedAtBuildPcds(self):
> > +        for LibAuto in self.LibraryAutoGenList:
> > +            FixedAtBuildPcds = {}
> > +            ShareFixedAtBuildPcdsSameValue = {}
> > +            for Module in LibAuto.ReferenceModules:
> > +                for Pcd in set(Module.FixedAtBuildPcds + LibAuto.FixedAtBuildPcds):
> > +                    DefaultValue = Pcd.DefaultValue
> > +                    # Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib
> > +                    if Pcd in Module.LibraryPcdList:
> > +                        Index = Module.LibraryPcdList.index(Pcd)
> > +                        DefaultValue = Module.LibraryPcdList[Index].DefaultValue
> > +                    key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
> > +                    if key not in FixedAtBuildPcds:
> > +                        ShareFixedAtBuildPcdsSameValue[key] = True
> > +                        FixedAtBuildPcds[key] = DefaultValue
> > +                    else:
> > +                        if FixedAtBuildPcds[key] != DefaultValue:
> > +                            ShareFixedAtBuildPcdsSameValue[key] = False
> > +            for Pcd in LibAuto.FixedAtBuildPcds:
> > +                key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
> > +                if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) not in self.NonDynamicPcdDict:
> > +                    continue
> > +                else:
> > +                    DscPcd = self.NonDynamicPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)]
> > +                    if DscPcd.Type != TAB_PCDS_FIXED_AT_BUILD:
> > +                        continue
> > +                if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]:
> > +                    LibAuto.ConstPcd[key] = FixedAtBuildPcds[key]
> > +
> > +    def CollectVariables(self, DynamicPcdSet):
> > +        VpdRegionSize = 0
> > +        VpdRegionBase = 0
> > +        if self.Workspace.FdfFile:
> > +            FdDict = self.Workspace.FdfProfile.FdDict[GlobalData.gFdfParser.CurrentFdName]
> > +            for FdRegion in FdDict.RegionList:
> > +                for item in FdRegion.RegionDataList:
> > +                    if self.Platform.VpdToolGuid.strip() and self.Platform.VpdToolGuid in item:
> > +                        VpdRegionSize = FdRegion.Size
> > +                        VpdRegionBase = FdRegion.Offset
> > +                        break
> > +
> > +        VariableInfo = VariableMgr(self.DscBuildDataObj._GetDefaultStores(), self.DscBuildDataObj.SkuIds)
> > +        VariableInfo.SetVpdRegionMaxSize(VpdRegionSize)
> > +        VariableInfo.SetVpdRegionOffset(VpdRegionBase)
> > +        Index = 0
> > +        for Pcd in DynamicPcdSet:
> > +            pcdname = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
> > +            for SkuName in Pcd.SkuInfoList:
> > +                Sku = Pcd.SkuInfoList[SkuName]
> > +                SkuId = Sku.SkuId
> > +                if SkuId is None or SkuId == '':
> > +                    continue
> > +                if len(Sku.VariableName) > 0:
> > +                    if Sku.VariableAttribute and 'NV' not in Sku.VariableAttribute:
> > +                        continue
> > +                    VariableGuidStructure = Sku.VariableGuidValue
> > +                    VariableGuid = GuidStructureStringToGuidString(VariableGuidStructure)
> > +                    for StorageName in Sku.DefaultStoreDict:
> > +                        VariableInfo.append_variable(var_info(Index, pcdname, StorageName, SkuName, StringToArray(Sku.VariableName), VariableGuid, Sku.VariableOffset, Sku.VariableAttribute, Sku.HiiDefaultValue, Sku.DefaultStoreDict[StorageName] if Pcd.DatumType in TAB_PCD_NUMERIC_TYPES else StringToArray(Sku.DefaultStoreDict[StorageName]), Pcd.DatumType, Pcd.CustomAttribute['DscPosition'], Pcd.CustomAttribute.get('IsStru',False)))
> > +            Index += 1
> > +        return VariableInfo
> > +
> > +    def UpdateNVStoreMaxSize(self, OrgVpdFile):
> > +        if self.VariableInfo:
> > +            VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)
> > +            PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]
> > +
> > +            if PcdNvStoreDfBuffer:
> > +                if os.path.exists(VpdMapFilePath):
> > +                    OrgVpdFile.Read(VpdMapFilePath)
> > +                    PcdItems = OrgVpdFile.GetOffset(PcdNvStoreDfBuffer[0])
> > +                    NvStoreOffset = list(PcdItems.values())[0].strip() if PcdItems else '0'
> > +                else:
> > +                    EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)
> > +
> > +                NvStoreOffset = int(NvStoreOffset, 16) if NvStoreOffset.upper().startswith("0X") else int(NvStoreOffset)
> > +                default_skuobj = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT)
> > +                maxsize = self.VariableInfo.VpdRegionSize  - NvStoreOffset if self.VariableInfo.VpdRegionSize else len(default_skuobj.DefaultValue.split(","))
> > +                var_data = self.VariableInfo.PatchNVStoreDefaultMaxSize(maxsize)
> > +
> > +                if var_data and default_skuobj:
> > +                    default_skuobj.DefaultValue = var_data
> > +                    PcdNvStoreDfBuffer[0].DefaultValue = var_data
> > +                    PcdNvStoreDfBuffer[0].SkuInfoList.clear()
> > +                    PcdNvStoreDfBuffer[0].SkuInfoList[TAB_DEFAULT] = default_skuobj
> > +                    PcdNvStoreDfBuffer[0].MaxDatumSize = str(len(default_skuobj.DefaultValue.split(",")))
> > +
> > +        return OrgVpdFile
> > +
> > +    ## Collect dynamic PCDs
> > +    #
> > +    #  Gather dynamic PCDs list from each module and their settings from platform
> > +    #  This interface should be invoked explicitly when platform action is created.
> > +    #
> > +    def CollectPlatformDynamicPcds(self):
> > +        self.CategoryPcds()
> > +        self.SortDynamicPcd()
> > +
> > +    def CategoryPcds(self):
> > +        # Category Pcds into DynamicPcds and NonDynamicPcds
> > +        # for gathering error information
> > +        NoDatumTypePcdList = set()
> > +        FdfModuleList = []
> > +        for InfName in self._AsBuildInfList:
> > +            InfName = mws.join(self.WorkspaceDir, InfName)
> > +            FdfModuleList.append(os.path.normpath(InfName))
> > +        for M in self._MbList:
> > +#            F is the Module for which M is the module autogen
> > +            ModPcdList = self.ApplyPcdSetting(M, M.ModulePcdList)
> > +            LibPcdList = []
> > +            for lib in M.LibraryPcdList:
> > +                LibPcdList.extend(self.ApplyPcdSetting(M, M.LibraryPcdList[lib], lib))
> > +            for PcdFromModule in ModPcdList + LibPcdList:
> > +
> > +                # make sure that the "VOID*" kind of datum has MaxDatumSize set
> > +                if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:
> > +                    NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, M.MetaFile))
> > +
> > +                # Check the PCD from Binary INF or Source INF
> > +                if M.IsBinaryModule == True:
> > +                    PcdFromModule.IsFromBinaryInf = True
> > +
> > +                # Check the PCD from DSC or not
> > +                PcdFromModule.IsFromDsc = (PcdFromModule.TokenCName, PcdFromModule.TokenSpaceGuidCName) in self.Platform.Pcds
> > +
> > +                if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET or PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
> > +                    if M.MetaFile.Path not in FdfModuleList:
> > +                        # If one of the Source built modules listed in the DSC is not listed
> > +                        # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
> > +                        # access method (it is only listed in the DEC file that declares the
> > +                        # PCD as PcdsDynamic), then build tool will report warning message
> > +                        # notify the PI that they are attempting to build a module that must
> > +                        # be included in a flash image in order to be functional. These Dynamic
> > +                        # PCD will not be added into the Database unless it is used by other
> > +                        # modules that are included in the FDF file.
> > +                        if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET and \
> > +                            PcdFromModule.IsFromBinaryInf == False:
> > +                            # Print warning message to let the developer make a determine.
> > +                            continue
> > +                        # If one of the Source built modules listed in the DSC is not listed in
> > +                        # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
> > +                        # access method (it is only listed in the DEC file that declares the
> > +                        # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
> > +                        # PCD to the Platform's PCD Database.
> > +                        if PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
> > +                            continue
> > +                    #
> > +                    # If a dynamic PCD used by a PEM module/PEI module & DXE module,
> > +                    # it should be stored in Pcd PEI database, If a dynamic only
> > +                    # used by DXE module, it should be stored in DXE PCD database.
> > +                    # The default Phase is DXE
> > +                    #
> > +                    if M.ModuleType in SUP_MODULE_SET_PEI:
> > +                        PcdFromModule.Phase = "PEI"
> > +                    if PcdFromModule not in self._DynaPcdList_:
> > +                        self._DynaPcdList_.append(PcdFromModule)
> > +                    elif PcdFromModule.Phase == 'PEI':
> > +                        # overwrite any the same PCD existing, if Phase is PEI
> > +                        Index = self._DynaPcdList_.index(PcdFromModule)
> > +                        self._DynaPcdList_[Index] = PcdFromModule
> > +                elif PcdFromModule not in self._NonDynaPcdList_:
> > +                    self._NonDynaPcdList_.append(PcdFromModule)
> > +                elif PcdFromModule in self._NonDynaPcdList_ and PcdFromModule.IsFromBinaryInf == True:
> > +                    Index = self._NonDynaPcdList_.index(PcdFromModule)
> > +                    if self._NonDynaPcdList_[Index].IsFromBinaryInf == False:
> > +                        #The PCD from Binary INF will override the same one from source INF
> > +                        self._NonDynaPcdList_.remove (self._NonDynaPcdList_[Index])
> > +                        PcdFromModule.Pending = False
> > +                        self._NonDynaPcdList_.append (PcdFromModule)
> > +        DscModuleSet = {os.path.normpath(ModuleInf.Path) for ModuleInf in self.Platform.Modules}
> > +        # add the PCD from modules that listed in FDF but not in DSC to Database
> > +        for InfName in FdfModuleList:
> > +            if InfName not in DscModuleSet:
> > +                InfClass = PathClass(InfName)
> > +                M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]
> > +                # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
> > +                # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
> > +                # For binary module, if in current arch, we need to list the PCDs into database.
> > +                if not M.IsBinaryModule:
> > +                    continue
> > +                # Override the module PCD setting by platform setting
> > +                ModulePcdList = self.ApplyPcdSetting(M, M.Pcds)
> > +                for PcdFromModule in ModulePcdList:
> > +                    PcdFromModule.IsFromBinaryInf = True
> > +                    PcdFromModule.IsFromDsc = False
> > +                    # Only allow the DynamicEx and Patchable PCD in AsBuild INF
> > +                    if PcdFromModule.Type not in PCD_DYNAMIC_EX_TYPE_SET and PcdFromModule.Type not in TAB_PCDS_PATCHABLE_IN_MODULE:
> > +                        EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
> > +                                        File=self.MetaFile,
> > +                                        ExtraData="\n\tExisted %s PCD %s in:\n\t\t%s\n"
> > +                                        % (PcdFromModule.Type, PcdFromModule.TokenCName, InfName))
> > +                    # make sure that the "VOID*" kind of datum has MaxDatumSize set
> > +                    if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:
> > +                        NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, InfName))
> > +                    if M.ModuleType in SUP_MODULE_SET_PEI:
> > +                        PcdFromModule.Phase = "PEI"
> > +                    if PcdFromModule not in self._DynaPcdList_ and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
> > +                        self._DynaPcdList_.append(PcdFromModule)
> > +                    elif PcdFromModule not in self._NonDynaPcdList_ and PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE:
> > +                        self._NonDynaPcdList_.append(PcdFromModule)
> > +                    if PcdFromModule in self._DynaPcdList_ and PcdFromModule.Phase == 'PEI' and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
> > +                        # Overwrite the phase of any the same PCD existing, if Phase is PEI.
> > +                        # It is to solve the case that a dynamic PCD used by a PEM module/PEI
> > +                        # module & DXE module at a same time.
> > +                        # Overwrite the type of the PCDs in source INF by the type of AsBuild
> > +                        # INF file as DynamicEx.
> > +                        Index = self._DynaPcdList_.index(PcdFromModule)
> > +                        self._DynaPcdList_[Index].Phase = PcdFromModule.Phase
> > +                        self._DynaPcdList_[Index].Type = PcdFromModule.Type
> > +        for PcdFromModule in self._NonDynaPcdList_:
> > +            # If a PCD is not listed in the DSC file, but binary INF files used by
> > +            # this platform all (that use this PCD) list the PCD in a [PatchPcds]
> > +            # section, AND all source INF files used by this platform the build
> > +            # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
> > +            # section, then the tools must NOT add the PCD to the Platform's PCD
> > +            # Database; the build must assign the access method for this PCD as
> > +            # PcdsPatchableInModule.
> > +            if PcdFromModule not in self._DynaPcdList_:
> > +                continue
> > +            Index = self._DynaPcdList_.index(PcdFromModule)
> > +            if PcdFromModule.IsFromDsc == False and \
> > +                PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE and \
> > +                PcdFromModule.IsFromBinaryInf == True and \
> > +                self._DynaPcdList_[Index].IsFromBinaryInf == False:
> > +                Index = self._DynaPcdList_.index(PcdFromModule)
> > +                self._DynaPcdList_.remove (self._DynaPcdList_[Index])
> > +
> > +        # print out error information and break the build, if error found
> > +        if len(NoDatumTypePcdList) > 0:
> > +            NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)
> > +            EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
> > +                            File=self.MetaFile,
> > +                            ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
> > +                                      % NoDatumTypePcdListString)
> > +        self._NonDynamicPcdList = self._NonDynaPcdList_
> > +        self._DynamicPcdList = self._DynaPcdList_
> > +
> > +    def SortDynamicPcd(self):
> > +        #
> > +        # Sort dynamic PCD list to:
> > +        # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
> > +        #    try to be put header of dynamicd List
> > +        # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
> > +        #
> > +        # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
> > +        #
> > +        UnicodePcdArray = set()
> > +        HiiPcdArray     = set()
> > +        OtherPcdArray   = set()
> > +        VpdPcdDict      = {}
> > +        VpdFile               = VpdInfoFile.VpdInfoFile()
> > +        NeedProcessVpdMapFile = False
> > +
> > +        for pcd in self.Platform.Pcds:
> > +            if pcd not in self._PlatformPcds:
> > +                self._PlatformPcds[pcd] = self.Platform.Pcds[pcd]
> > +
> > +        for item in self._PlatformPcds:
> > +            if self._PlatformPcds[item].DatumType and self._PlatformPcds[item].DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
> > +                self._PlatformPcds[item].DatumType = TAB_VOID
> > +
> > +        if (self.Workspace.ArchList[-1] == self.Arch):
> > +            for Pcd in self._DynamicPcdList:
> > +                # just pick the a value to determine whether is unicode string type
> > +                Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)
> > +                Sku.VpdOffset = Sku.VpdOffset.strip()
> > +
> > +                if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
> > +                    Pcd.DatumType = TAB_VOID
> > +
> > +                    # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
> > +                    # if found HII type PCD then insert to right of UnicodeIndex
> > +                if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
> > +                    VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd
> > +
> > +            #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
> > +            PcdNvStoreDfBuffer = VpdPcdDict.get(("PcdNvStoreDefaultValueBuffer", "gEfiMdeModulePkgTokenSpaceGuid"))
> > +            if PcdNvStoreDfBuffer:
> > +                self.VariableInfo = self.CollectVariables(self._DynamicPcdList)
> > +                vardump = self.VariableInfo.dump()
> > +                if vardump:
> > +                    #
> > +                    #According to PCD_DATABASE_INIT in edk2\MdeModulePkg\Include\Guid\PcdDataBaseSignatureGuid.h,
> > +                    #the max size for string PCD should not exceed USHRT_MAX 65535(0xffff).
> > +                    #typedef UINT16 SIZE_INFO;
> > +                    #//SIZE_INFO  SizeTable[];
> > +                    if len(vardump.split(",")) > 0xffff:
> > +                        EdkLogger.error("build", RESOURCE_OVERFLOW, 'The current length of PCD %s value is %d, it exceeds to the max size of String PCD.' %(".".join([PcdNvStoreDfBuffer.TokenSpaceGuidCName,PcdNvStoreDfBuffer.TokenCName]) ,len(vardump.split(","))))
> > +                    PcdNvStoreDfBuffer.DefaultValue = vardump
> > +                    for skuname in PcdNvStoreDfBuffer.SkuInfoList:
> > +                        PcdNvStoreDfBuffer.SkuInfoList[skuname].DefaultValue = vardump
> > +                        PcdNvStoreDfBuffer.MaxDatumSize = str(len(vardump.split(",")))
> > +            else:
> > +                #If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd
> > +                if [Pcd for Pcd in self._DynamicPcdList if Pcd.UserDefinedDefaultStoresFlag]:
> > +                    EdkLogger.warn("build", "PcdNvStoreDefaultValueBuffer should be defined as PcdsDynamicExVpd in dsc file since the DefaultStores is enabled for this platform.\n%s" %self.Platform.MetaFile.Path)
> > +            PlatformPcds = sorted(self._PlatformPcds.keys())
> > +            #
> > +            # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
> > +            #
> > +            VpdSkuMap = {}
> > +            for PcdKey in PlatformPcds:
> > +                Pcd = self._PlatformPcds[PcdKey]
> > +                if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD] and \
> > +                   PcdKey in VpdPcdDict:
> > +                    Pcd = VpdPcdDict[PcdKey]
> > +                    SkuValueMap = {}
> > +                    DefaultSku = Pcd.SkuInfoList.get(TAB_DEFAULT)
> > +                    if DefaultSku:
> > +                        PcdValue = DefaultSku.DefaultValue
> > +                        if PcdValue not in SkuValueMap:
> > +                            SkuValueMap[PcdValue] = []
> > +                            VpdFile.Add(Pcd, TAB_DEFAULT, DefaultSku.VpdOffset)
> > +                        SkuValueMap[PcdValue].append(DefaultSku)
> > +
> > +                    for (SkuName, Sku) in Pcd.SkuInfoList.items():
> > +                        Sku.VpdOffset = Sku.VpdOffset.strip()
> > +                        PcdValue = Sku.DefaultValue
> > +                        if PcdValue == "":
> > +                            PcdValue  = Pcd.DefaultValue
> > +                        if Sku.VpdOffset != TAB_STAR:
> > +                            if PcdValue.startswith("{"):
> > +                                Alignment = 8
> > +                            elif PcdValue.startswith("L"):
> > +                                Alignment = 2
> > +                            else:
> > +                                Alignment = 1
> > +                            try:
> > +                                VpdOffset = int(Sku.VpdOffset)
> > +                            except:
> > +                                try:
> > +                                    VpdOffset = int(Sku.VpdOffset, 16)
> > +                                except:
> > +                                    EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
> > +                            if VpdOffset % Alignment != 0:
> > +                                if PcdValue.startswith("{"):
> > +                                    EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName), File=self.MetaFile)
> > +                                else:
> > +                                    EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Alignment))
> > +                        if PcdValue not in SkuValueMap:
> > +                            SkuValueMap[PcdValue] = []
> > +                            VpdFile.Add(Pcd, SkuName, Sku.VpdOffset)
> > +                        SkuValueMap[PcdValue].append(Sku)
> > +                        # if the offset of a VPD is *, then it need to be fixed up by third party tool.
> > +                        if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:
> > +                            NeedProcessVpdMapFile = True
> > +                            if self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == '':
> > +                                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.")
> > +
> > +                    VpdSkuMap[PcdKey] = SkuValueMap
> > +            #
> > +            # Fix the PCDs define in VPD PCD section that never referenced by module.
> > +            # An example is PCD for signature usage.
> > +            #
> > +            for DscPcd in PlatformPcds:
> > +                DscPcdEntry = self._PlatformPcds[DscPcd]
> > +                if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
> > +                    if not (self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == ''):
> > +                        FoundFlag = False
> > +                        for VpdPcd in VpdFile._VpdArray:
> > +                            # This PCD has been referenced by module
> > +                            if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
> > +                               (VpdPcd.TokenCName == DscPcdEntry.TokenCName):
> > +                                    FoundFlag = True
> > +
> > +                        # Not found, it should be signature
> > +                        if not FoundFlag :
> > +                            # just pick the a value to determine whether is unicode string type
> > +                            SkuValueMap = {}
> > +                            SkuObjList = list(DscPcdEntry.SkuInfoList.items())
> > +                            DefaultSku = DscPcdEntry.SkuInfoList.get(TAB_DEFAULT)
> > +                            if DefaultSku:
> > +                                defaultindex = SkuObjList.index((TAB_DEFAULT, DefaultSku))
> > +                                SkuObjList[0], SkuObjList[defaultindex] = SkuObjList[defaultindex], SkuObjList[0]
> > +                            for (SkuName, Sku) in SkuObjList:
> > +                                Sku.VpdOffset = Sku.VpdOffset.strip()
> > +
> > +                                # Need to iterate DEC pcd information to get the value & datumtype
> > +                                for eachDec in self.PackageList:
> > +                                    for DecPcd in eachDec.Pcds:
> > +                                        DecPcdEntry = eachDec.Pcds[DecPcd]
> > +                                        if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
> > +                                           (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):
> > +                                            # Print warning message to let the developer make a determine.
> > +                                            EdkLogger.warn("build", "Unreferenced vpd pcd used!",
> > +                                                            File=self.MetaFile, \
> > +                                                            ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \
> > +                                                            %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path))
> > +
> > +                                            DscPcdEntry.DatumType    = DecPcdEntry.DatumType
> > +                                            DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue
> > +                                            DscPcdEntry.TokenValue = DecPcdEntry.TokenValue
> > +                                            DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName]
> > +                                            # Only fix the value while no value provided in DSC file.
> > +                                            if not Sku.DefaultValue:
> > +                                                DscPcdEntry.SkuInfoList[list(DscPcdEntry.SkuInfoList.keys())[0]].DefaultValue = DecPcdEntry.DefaultValue
> > +
> > +                                if DscPcdEntry not in self._DynamicPcdList:
> > +                                    self._DynamicPcdList.append(DscPcdEntry)
> > +                                Sku.VpdOffset = Sku.VpdOffset.strip()
> > +                                PcdValue = Sku.DefaultValue
> > +                                if PcdValue == "":
> > +                                    PcdValue  = DscPcdEntry.DefaultValue
> > +                                if Sku.VpdOffset != TAB_STAR:
> > +                                    if PcdValue.startswith("{"):
> > +                                        Alignment = 8
> > +                                    elif PcdValue.startswith("L"):
> > +                                        Alignment = 2
> > +                                    else:
> > +                                        Alignment = 1
> > +                                    try:
> > +                                        VpdOffset = int(Sku.VpdOffset)
> > +                                    except:
> > +                                        try:
> > +                                            VpdOffset = int(Sku.VpdOffset, 16)
> > +                                        except:
> > +                                            EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName))
> > +                                    if VpdOffset % Alignment != 0:
> > +                                        if PcdValue.startswith("{"):
> > +                                            EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName), File=self.MetaFile)
> > +                                        else:
> > +                                            EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, Alignment))
> > +                                if PcdValue not in SkuValueMap:
> > +                                    SkuValueMap[PcdValue] = []
> > +                                    VpdFile.Add(DscPcdEntry, SkuName, Sku.VpdOffset)
> > +                                SkuValueMap[PcdValue].append(Sku)
> > +                                if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:
> > +                                    NeedProcessVpdMapFile = True
> > +                            if DscPcdEntry.DatumType == TAB_VOID and PcdValue.startswith("L"):
> > +                                UnicodePcdArray.add(DscPcdEntry)
> > +                            elif len(Sku.VariableName) > 0:
> > +                                HiiPcdArray.add(DscPcdEntry)
> > +                            else:
> > +                                OtherPcdArray.add(DscPcdEntry)
> > +
> > +                                # if the offset of a VPD is *, then it need to be fixed up by third party tool.
> > +                            VpdSkuMap[DscPcd] = SkuValueMap
> > +            if (self.Platform.FlashDefinition is None or self.Platform.FlashDefinition == '') and \
> > +               VpdFile.GetCount() != 0:
> > +                EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
> > +                                "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))
> > +
> > +            if VpdFile.GetCount() != 0:
> > +
> > +                self.FixVpdOffset(VpdFile)
> > +
> > +                self.FixVpdOffset(self.UpdateNVStoreMaxSize(VpdFile))
> > +                PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]
> > +                if PcdNvStoreDfBuffer:
> > +                    PcdName,PcdGuid = PcdNvStoreDfBuffer[0].TokenCName, PcdNvStoreDfBuffer[0].TokenSpaceGuidCName
> > +                    if (PcdName,PcdGuid) in VpdSkuMap:
> > +                        DefaultSku = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT)
> > +                        VpdSkuMap[(PcdName,PcdGuid)] = {DefaultSku.DefaultValue:[SkuObj for SkuObj in PcdNvStoreDfBuffer[0].SkuInfoList.values() ]}
> > +
> > +                # Process VPD map file generated by third party BPDG tool
> > +                if NeedProcessVpdMapFile:
> > +                    VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)
> > +                    if os.path.exists(VpdMapFilePath):
> > +                        VpdFile.Read(VpdMapFilePath)
> > +
> > +                        # Fixup TAB_STAR offset
> > +                        for pcd in VpdSkuMap:
> > +                            vpdinfo = VpdFile.GetVpdInfo(pcd)
> > +                            if vpdinfo is None:
> > +                            # just pick the a value to determine whether is unicode string type
> > +                                continue
> > +                            for pcdvalue in VpdSkuMap[pcd]:
> > +                                for sku in VpdSkuMap[pcd][pcdvalue]:
> > +                                    for item in vpdinfo:
> > +                                        if item[2] == pcdvalue:
> > +                                            sku.VpdOffset = item[1]
> > +                    else:
> > +                        EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)
> > +
> > +            # Delete the DynamicPcdList At the last time enter into this function
> > +            for Pcd in self._DynamicPcdList:
> > +                # just pick the a value to determine whether is unicode string type
> > +                Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)
> > +                Sku.VpdOffset = Sku.VpdOffset.strip()
> > +
> > +                if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
> > +                    Pcd.DatumType = TAB_VOID
> > +
> > +                PcdValue = Sku.DefaultValue
> > +                if Pcd.DatumType == TAB_VOID and PcdValue.startswith("L"):
> > +                    # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
> > +                    UnicodePcdArray.add(Pcd)
> > +                elif len(Sku.VariableName) > 0:
> > +                    # if found HII type PCD then insert to right of UnicodeIndex
> > +                    HiiPcdArray.add(Pcd)
> > +                else:
> > +                    OtherPcdArray.add(Pcd)
> > +            del self._DynamicPcdList[:]
> > +        self._DynamicPcdList.extend(list(UnicodePcdArray))
> > +        self._DynamicPcdList.extend(list(HiiPcdArray))
> > +        self._DynamicPcdList.extend(list(OtherPcdArray))
> > +        allskuset = [(SkuName, Sku.SkuId) for pcd in self._DynamicPcdList for (SkuName, Sku) in pcd.SkuInfoList.items()]
> > +        for pcd in self._DynamicPcdList:
> > +            if len(pcd.SkuInfoList) == 1:
> > +                for (SkuName, SkuId) in allskuset:
> > +                    if isinstance(SkuId, str) and eval(SkuId) == 0 or SkuId == 0:
> > +                        continue
> > +                    pcd.SkuInfoList[SkuName] = copy.deepcopy(pcd.SkuInfoList[TAB_DEFAULT])
> > +                    pcd.SkuInfoList[SkuName].SkuId = SkuId
> > +                    pcd.SkuInfoList[SkuName].SkuIdName = SkuName
> > +
> > +    def FixVpdOffset(self, VpdFile ):
> > +        FvPath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY)
> > +        if not os.path.exists(FvPath):
> > +            try:
> > +                os.makedirs(FvPath)
> > +            except:
> > +                EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)
> > +
> > +        VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)
> > +
> > +        if VpdFile.Write(VpdFilePath):
> > +            # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
> > +            BPDGToolName = None
> > +            for ToolDef in self.ToolDefinition.values():
> > +                if TAB_GUID in ToolDef and ToolDef[TAB_GUID] == self.Platform.VpdToolGuid:
> > +                    if "PATH" not in ToolDef:
> > +                        EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)
> > +                    BPDGToolName = ToolDef["PATH"]
> > +                    break
> > +            # Call third party GUID BPDG tool.
> > +            if BPDGToolName is not None:
> > +                VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)
> > +            else:
> > +                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.")
> > +
> > +    ## Return the platform build data object
> > +    @cached_property
> > +    def Platform(self):
> > +        return self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
> > +
> > +    ## Return platform name
> > +    @cached_property
> > +    def Name(self):
> > +        return self.Platform.PlatformName
> > +
> > +    ## Return the meta file GUID
> > +    @cached_property
> > +    def Guid(self):
> > +        return self.Platform.Guid
> > +
> > +    ## Return the platform version
> > +    @cached_property
> > +    def Version(self):
> > +        return self.Platform.Version
> > +
> > +    ## Return the FDF file name
> > +    @cached_property
> > +    def FdfFile(self):
> > +        if self.Workspace.FdfFile:
> > +            RetVal= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)
> > +        else:
> > +            RetVal = ''
> > +        return RetVal
> > +
> > +    ## Return the build output directory platform specifies
> > +    @cached_property
> > +    def OutputDir(self):
> > +        return self.Platform.OutputDirectory
> > +
> > +    ## Return the directory to store all intermediate and final files built
> > +    @cached_property
> > +    def BuildDir(self):
> > +        if os.path.isabs(self.OutputDir):
> > +            GlobalData.gBuildDirectory = RetVal = path.join(
> > +                                        path.abspath(self.OutputDir),
> > +                                        self.BuildTarget + "_" + self.ToolChain,
> > +                                        )
> > +        else:
> > +            GlobalData.gBuildDirectory = RetVal = path.join(
> > +                                        self.WorkspaceDir,
> > +                                        self.OutputDir,
> > +                                        self.BuildTarget + "_" + self.ToolChain,
> > +                                        )
> > +        return RetVal
> > +
> > +    ## Return directory of platform makefile
> > +    #
> > +    #   @retval     string  Makefile directory
> > +    #
> > +    @cached_property
> > +    def MakeFileDir(self):
> > +        return path.join(self.BuildDir, self.Arch)
> > +
> > +    ## Return build command string
> > +    #
> > +    #   @retval     string  Build command string
> > +    #
> > +    @cached_property
> > +    def BuildCommand(self):
> > +        RetVal = []
> > +        if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
> > +            RetVal += _SplitOption(self.ToolDefinition["MAKE"]["PATH"])
> > +            if "FLAGS" in self.ToolDefinition["MAKE"]:
> > +                NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
> > +                if NewOption != '':
> > +                    RetVal += _SplitOption(NewOption)
> > +            if "MAKE" in self.EdkIIBuildOption:
> > +                if "FLAGS" in self.EdkIIBuildOption["MAKE"]:
> > +                    Flags = self.EdkIIBuildOption["MAKE"]["FLAGS"]
> > +                    if Flags.startswith('='):
> > +                        RetVal = [RetVal[0]] + [Flags[1:]]
> > +                    else:
> > +                        RetVal.append(Flags)
> > +        return RetVal
> > +
> > +    ## Get tool chain definition
> > +    #
> > +    #  Get each tool definition for given tool chain from tools_def.txt and platform
> > +    #
> > +    @cached_property
> > +    def ToolDefinition(self):
> > +        ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
> > +        if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:
> > +            EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",
> > +                            ExtraData="[%s]" % self.MetaFile)
> > +        RetVal = OrderedDict()
> > +        DllPathList = set()
> > +        for Def in ToolDefinition:
> > +            Target, Tag, Arch, Tool, Attr = Def.split("_")
> > +            if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:
> > +                continue
> > +
> > +            Value = ToolDefinition[Def]
> > +            # don't record the DLL
> > +            if Attr == "DLL":
> > +                DllPathList.add(Value)
> > +                continue
> > +
> > +            if Tool not in RetVal:
> > +                RetVal[Tool] = OrderedDict()
> > +            RetVal[Tool][Attr] = Value
> > +
> > +        ToolsDef = ''
> > +        if GlobalData.gOptions.SilentMode and "MAKE" in RetVal:
> > +            if "FLAGS" not in RetVal["MAKE"]:
> > +                RetVal["MAKE"]["FLAGS"] = ""
> > +            RetVal["MAKE"]["FLAGS"] += " -s"
> > +        MakeFlags = ''
> > +        for Tool in RetVal:
> > +            for Attr in RetVal[Tool]:
> > +                Value = RetVal[Tool][Attr]
> > +                if Tool in self._BuildOptionWithToolDef(RetVal) and Attr in self._BuildOptionWithToolDef(RetVal)[Tool]:
> > +                    # check if override is indicated
> > +                    if self._BuildOptionWithToolDef(RetVal)[Tool][Attr].startswith('='):
> > +                        Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr][1:]
> > +                    else:
> > +                        if Attr != 'PATH':
> > +                            Value += " " + self._BuildOptionWithToolDef(RetVal)[Tool][Attr]
> > +                        else:
> > +                            Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr]
> > +
> > +                if Attr == "PATH":
> > +                    # Don't put MAKE definition in the file
> > +                    if Tool != "MAKE":
> > +                        ToolsDef += "%s = %s\n" % (Tool, Value)
> > +                elif Attr != "DLL":
> > +                    # Don't put MAKE definition in the file
> > +                    if Tool == "MAKE":
> > +                        if Attr == "FLAGS":
> > +                            MakeFlags = Value
> > +                    else:
> > +                        ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
> > +            ToolsDef += "\n"
> > +
> > +        tool_def_file = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
> > +        SaveFileOnChange(tool_def_file, ToolsDef, False)
> > +        for DllPath in DllPathList:
> > +            os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]
> > +        os.environ["MAKE_FLAGS"] = MakeFlags
> > +
> > +        return RetVal
> > +
> > +    ## Return the paths of tools
> > +    @cached_property
> > +    def ToolDefinitionFile(self):
> > +        tool_def_file = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
> > +        if not os.path.exists(tool_def_file):
> > +            self.ToolDefinition
> > +        return tool_def_file
> > +
> > +    ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
> > +    @cached_property
> > +    def ToolChainFamily(self):
> > +        ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
> > +        if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
> > +           or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
> > +           or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:
> > +            EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
> > +                               % self.ToolChain)
> > +            RetVal = TAB_COMPILER_MSFT
> > +        else:
> > +            RetVal = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]
> > +        return RetVal
> > +
> > +    @cached_property
> > +    def BuildRuleFamily(self):
> > +        ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
> > +        if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
> > +           or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \
> > +           or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:
> > +            EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
> > +                               % self.ToolChain)
> > +            return TAB_COMPILER_MSFT
> > +
> > +        return ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]
> > +
> > +    ## Return the build options specific for all modules in this platform
> > +    @cached_property
> > +    def BuildOption(self):
> > +        return self._ExpandBuildOption(self.Platform.BuildOptions)
> > +
> > +    def _BuildOptionWithToolDef(self, ToolDef):
> > +        return self._ExpandBuildOption(self.Platform.BuildOptions, ToolDef=ToolDef)
> > +
> > +    ## Return the build options specific for EDK modules in this platform
> > +    @cached_property
> > +    def EdkBuildOption(self):
> > +        return self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)
> > +
> > +    ## Return the build options specific for EDKII modules in this platform
> > +    @cached_property
> > +    def EdkIIBuildOption(self):
> > +        return self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)
> > +
> > +    ## Parse build_rule.txt in Conf Directory.
> > +    #
> > +    #   @retval     BuildRule object
> > +    #
> > +    @cached_property
> > +    def BuildRule(self):
> > +        BuildRuleFile = None
> > +        if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:
> > +            BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
> > +        if not BuildRuleFile:
> > +            BuildRuleFile = gDefaultBuildRuleFile
> > +        RetVal = BuildRule(BuildRuleFile)
> > +        if RetVal._FileVersion == "":
> > +            RetVal._FileVersion = AutoGenReqBuildRuleVerNum
> > +        else:
> > +            if RetVal._FileVersion < AutoGenReqBuildRuleVerNum :
> > +                # If Build Rule's version is less than the version number required by the tools, halting the build.
> > +                EdkLogger.error("build", AUTOGEN_ERROR,
> > +                                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])"\
> > +                                 % (RetVal._FileVersion, AutoGenReqBuildRuleVerNum))
> > +        return RetVal
> > +
> > +    ## Summarize the packages used by modules in this platform
> > +    @cached_property
> > +    def PackageList(self):
> > +        RetVal = set()
> > +        for Mb in self._MbList:
> > +            RetVal.update(Mb.Packages)
> > +            for lb in Mb.LibInstances:
> > +                RetVal.update(lb.Packages)
> > +        #Collect package set information from INF of FDF
> > +        for ModuleFile in self._AsBuildModuleList:
> > +            if ModuleFile in self.Platform.Modules:
> > +                continue
> > +            ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]
> > +            RetVal.update(ModuleData.Packages)
> > +        return list(RetVal)
> > +
> > +    @cached_property
> > +    def NonDynamicPcdDict(self):
> > +        return {(Pcd.TokenCName, Pcd.TokenSpaceGuidCName):Pcd for Pcd in self.NonDynamicPcdList}
> > +
> > +    ## Get list of non-dynamic PCDs
> > +    @property
> > +    def NonDynamicPcdList(self):
> > +        if not self._NonDynamicPcdList:
> > +            self.CollectPlatformDynamicPcds()
> > +        return self._NonDynamicPcdList
> > +
> > +    ## Get list of dynamic PCDs
> > +    @property
> > +    def DynamicPcdList(self):
> > +        if not self._DynamicPcdList:
> > +            self.CollectPlatformDynamicPcds()
> > +        return self._DynamicPcdList
> > +
> > +    ## Generate Token Number for all PCD
> > +    @cached_property
> > +    def PcdTokenNumber(self):
> > +        RetVal = OrderedDict()
> > +        TokenNumber = 1
> > +        #
> > +        # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
> > +        # Such as:
> > +        #
> > +        # Dynamic PCD:
> > +        # TokenNumber 0 ~ 10
> > +        # DynamicEx PCD:
> > +        # TokeNumber 11 ~ 20
> > +        #
> > +        for Pcd in self.DynamicPcdList:
> > +            if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:
> > +                EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
> > +                RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
> > +                TokenNumber += 1
> > +
> > +        for Pcd in self.DynamicPcdList:
> > +            if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
> > +                EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
> > +                RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
> > +                TokenNumber += 1
> > +
> > +        for Pcd in self.DynamicPcdList:
> > +            if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:
> > +                EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
> > +                RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
> > +                TokenNumber += 1
> > +
> > +        for Pcd in self.DynamicPcdList:
> > +            if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
> > +                EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
> > +                RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
> > +                TokenNumber += 1
> > +
> > +        for Pcd in self.NonDynamicPcdList:
> > +            RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
> > +            TokenNumber += 1
> > +        return RetVal
> > +
> > +    @cached_property
> > +    def _MbList(self):
> > +        return [self.BuildDatabase[m, self.Arch, self.BuildTarget, self.ToolChain] for m in self.Platform.Modules]
> > +
> > +    @cached_property
> > +    def _MaList(self):
> > +        for ModuleFile in self.Platform.Modules:
> > +            Ma = ModuleAutoGen(
> > +                  self.Workspace,
> > +                  ModuleFile,
> > +                  self.BuildTarget,
> > +                  self.ToolChain,
> > +                  self.Arch,
> > +                  self.MetaFile,
> > +                  self.DataPipe
> > +                  )
> > +            self.Platform.Modules[ModuleFile].M = Ma
> > +        return [x.M for x in self.Platform.Modules.values()]
> > +
> > +    ## Summarize ModuleAutoGen objects of all modules to be built for this platform
> > +    @cached_property
> > +    def ModuleAutoGenList(self):
> > +        RetVal = []
> > +        for Ma in self._MaList:
> > +            if Ma not in RetVal:
> > +                RetVal.append(Ma)
> > +        return RetVal
> > +
> > +    ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
> > +    @cached_property
> > +    def LibraryAutoGenList(self):
> > +        RetVal = []
> > +        for Ma in self._MaList:
> > +            for La in Ma.LibraryAutoGenList:
> > +                if La not in RetVal:
> > +                    RetVal.append(La)
> > +                if Ma not in La.ReferenceModules:
> > +                    La.ReferenceModules.append(Ma)
> > +        return RetVal
> > +
> > +    ## Test if a module is supported by the platform
> > +    #
> > +    #  An error will be raised directly if the module or its arch is not supported
> > +    #  by the platform or current configuration
> > +    #
> > +    def ValidModule(self, Module):
> > +        return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \
> > +            or Module in self._AsBuildModuleList
> > +    @cached_property
> > +    def GetAllModuleInfo(self,WithoutPcd=True):
> > +        ModuleLibs = set()
> > +        for m in self.Platform.Modules:
> > +            module_obj = self.BuildDatabase[m,self.Arch,self.BuildTarget,self.ToolChain]
> > +            if not bool(module_obj.LibraryClass):
> > +                Libs = GetModuleLibInstances(module_obj, self.Platform, self.BuildDatabase, self.Arch,self.BuildTarget,self.ToolChain)
> > +            else:
> > +                Libs = []
> > +            ModuleLibs.update( set([(l.MetaFile.File,l.MetaFile.Root,l.Arch,True) for l in Libs]))
> > +            if WithoutPcd and module_obj.PcdIsDriver:
> > +                continue
> > +            ModuleLibs.add((m.File,m.Root,module_obj.Arch,False))
> > +
> > +        return ModuleLibs
> > +
> > +    ## Resolve the library classes in a module to library instances
> > +    #
> > +    # This method will not only resolve library classes but also sort the library
> > +    # instances according to the dependency-ship.
> > +    #
> > +    #   @param  Module      The module from which the library classes will be resolved
> > +    #
> > +    #   @retval library_list    List of library instances sorted
> > +    #
> > +    def ApplyLibraryInstance(self, Module):
> > +        # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
> > +        if str(Module) not in self.Platform.Modules:
> > +            return []
> > +
> > +        return GetModuleLibInstances(Module,
> > +                                     self.Platform,
> > +                                     self.BuildDatabase,
> > +                                     self.Arch,
> > +                                     self.BuildTarget,
> > +                                     self.ToolChain,
> > +                                     self.MetaFile,
> > +                                     EdkLogger)
> > +
> > +    ## Override PCD setting (type, value, ...)
> > +    #
> > +    #   @param  ToPcd       The PCD to be overridden
> > +    #   @param  FromPcd     The PCD overriding from
> > +    #
> > +    def _OverridePcd(self, ToPcd, FromPcd, Module="", Msg="", Library=""):
> > +        #
> > +        # in case there's PCDs coming from FDF file, which have no type given.
> > +        # at this point, ToPcd.Type has the type found from dependent
> > +        # package
> > +        #
> > +        TokenCName = ToPcd.TokenCName
> > +        for PcdItem in GlobalData.MixedPcd:
> > +            if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
> > +                TokenCName = PcdItem[0]
> > +                break
> > +        if FromPcd is not None:
> > +            if ToPcd.Pending and FromPcd.Type:
> > +                ToPcd.Type = FromPcd.Type
> > +            elif ToPcd.Type and FromPcd.Type\
> > +                and ToPcd.Type != FromPcd.Type and ToPcd.Type in FromPcd.Type:
> > +                if ToPcd.Type.strip() == TAB_PCDS_DYNAMIC_EX:
> > +                    ToPcd.Type = FromPcd.Type
> > +            elif ToPcd.Type and FromPcd.Type \
> > +                and ToPcd.Type != FromPcd.Type:
> > +                if Library:
> > +                    Module = str(Module) + " 's library file (" + str(Library) + ")"
> > +                EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",
> > +                                ExtraData="%s.%s is used as [%s] in module %s, but as [%s] in %s."\
> > +                                          % (ToPcd.TokenSpaceGuidCName, TokenCName,
> > +                                             ToPcd.Type, Module, FromPcd.Type, Msg),
> > +                                          File=self.MetaFile)
> > +
> > +            if FromPcd.MaxDatumSize:
> > +                ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
> > +                ToPcd.MaxSizeUserSet = FromPcd.MaxDatumSize
> > +            if FromPcd.DefaultValue:
> > +                ToPcd.DefaultValue = FromPcd.DefaultValue
> > +            if FromPcd.TokenValue:
> > +                ToPcd.TokenValue = FromPcd.TokenValue
> > +            if FromPcd.DatumType:
> > +                ToPcd.DatumType = FromPcd.DatumType
> > +            if FromPcd.SkuInfoList:
> > +                ToPcd.SkuInfoList = FromPcd.SkuInfoList
> > +            if FromPcd.UserDefinedDefaultStoresFlag:
> > +                ToPcd.UserDefinedDefaultStoresFlag = FromPcd.UserDefinedDefaultStoresFlag
> > +            # Add Flexible PCD format parse
> > +            if ToPcd.DefaultValue:
> > +                try:
> > +                    ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self.Platform._GuidDict)(True)
> > +                except BadExpression as Value:
> > +                    EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),
> > +                                        File=self.MetaFile)
> > +
> > +            # check the validation of datum
> > +            IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)
> > +            if not IsValid:
> > +                EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
> > +                                ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, TokenCName))
> > +            ToPcd.validateranges = FromPcd.validateranges
> > +            ToPcd.validlists = FromPcd.validlists
> > +            ToPcd.expressions = FromPcd.expressions
> > +            ToPcd.CustomAttribute = FromPcd.CustomAttribute
> > +
> > +        if FromPcd is not None and ToPcd.DatumType == TAB_VOID and not ToPcd.MaxDatumSize:
> > +            EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \
> > +                            % (ToPcd.TokenSpaceGuidCName, TokenCName))
> > +            Value = ToPcd.DefaultValue
> > +            if not Value:
> > +                ToPcd.MaxDatumSize = '1'
> > +            elif Value[0] == 'L':
> > +                ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)
> > +            elif Value[0] == '{':
> > +                ToPcd.MaxDatumSize = str(len(Value.split(',')))
> > +            else:
> > +                ToPcd.MaxDatumSize = str(len(Value) - 1)
> > +
> > +        # apply default SKU for dynamic PCDS if specified one is not available
> > +        if (ToPcd.Type in PCD_DYNAMIC_TYPE_SET or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_SET) \
> > +            and not ToPcd.SkuInfoList:
> > +            if self.Platform.SkuName in self.Platform.SkuIds:
> > +                SkuName = self.Platform.SkuName
> > +            else:
> > +                SkuName = TAB_DEFAULT
> > +            ToPcd.SkuInfoList = {
> > +                SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName][0], '', '', '', '', '', ToPcd.DefaultValue)
> > +            }
> > +
> > +    ## Apply PCD setting defined platform to a module
> > +    #
> > +    #   @param  Module  The module from which the PCD setting will be overridden
> > +    #
> > +    #   @retval PCD_list    The list PCDs with settings from platform
> > +    #
> > +    def ApplyPcdSetting(self, Module, Pcds, Library=""):
> > +        # for each PCD in module
> > +        for Name, Guid in Pcds:
> > +            PcdInModule = Pcds[Name, Guid]
> > +            # find out the PCD setting in platform
> > +            if (Name, Guid) in self.Platform.Pcds:
> > +                PcdInPlatform = self.Platform.Pcds[Name, Guid]
> > +            else:
> > +                PcdInPlatform = None
> > +            # then override the settings if any
> > +            self._OverridePcd(PcdInModule, PcdInPlatform, Module, Msg="DSC PCD sections", Library=Library)
> > +            # resolve the VariableGuid value
> > +            for SkuId in PcdInModule.SkuInfoList:
> > +                Sku = PcdInModule.SkuInfoList[SkuId]
> > +                if Sku.VariableGuid == '': continue
> > +                Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList, self.MetaFile.Path)
> > +                if Sku.VariableGuidValue is None:
> > +                    PackageList = "\n\t".join(str(P) for P in self.PackageList)
> > +                    EdkLogger.error(
> > +                                'build',
> > +                                RESOURCE_NOT_AVAILABLE,
> > +                                "Value of GUID [%s] is not found in" % Sku.VariableGuid,
> > +                                ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \
> > +                                                        % (Guid, Name, str(Module)),
> > +                                File=self.MetaFile
> > +                                )
> > +
> > +        # override PCD settings with module specific setting
> > +        if Module in self.Platform.Modules:
> > +            PlatformModule = self.Platform.Modules[str(Module)]
> > +            for Key  in PlatformModule.Pcds:
> > +                if GlobalData.BuildOptionPcd:
> > +                    for pcd in GlobalData.BuildOptionPcd:
> > +                        (TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue, _) = pcd
> > +                        if (TokenCName, TokenSpaceGuidCName) == Key and FieldName =="":
> > +                            PlatformModule.Pcds[Key].DefaultValue = pcdvalue
> > +                            PlatformModule.Pcds[Key].PcdValueFromComm = pcdvalue
> > +                            break
> > +                Flag = False
> > +                if Key in Pcds:
> > +                    ToPcd = Pcds[Key]
> > +                    Flag = True
> > +                elif Key in GlobalData.MixedPcd:
> > +                    for PcdItem in GlobalData.MixedPcd[Key]:
> > +                        if PcdItem in Pcds:
> > +                            ToPcd = Pcds[PcdItem]
> > +                            Flag = True
> > +                            break
> > +                if Flag:
> > +                    self._OverridePcd(ToPcd, PlatformModule.Pcds[Key], Module, Msg="DSC Components Module scoped PCD section", Library=Library)
> > +        # use PCD value to calculate the MaxDatumSize when it is not specified
> > +        for Name, Guid in Pcds:
> > +            Pcd = Pcds[Name, Guid]
> > +            if Pcd.DatumType == TAB_VOID and not Pcd.MaxDatumSize:
> > +                Pcd.MaxSizeUserSet = None
> > +                Value = Pcd.DefaultValue
> > +                if not Value:
> > +                    Pcd.MaxDatumSize = '1'
> > +                elif Value[0] == 'L':
> > +                    Pcd.MaxDatumSize = str((len(Value) - 2) * 2)
> > +                elif Value[0] == '{':
> > +                    Pcd.MaxDatumSize = str(len(Value.split(',')))
> > +                else:
> > +                    Pcd.MaxDatumSize = str(len(Value) - 1)
> > +        return list(Pcds.values())
> > +
> > +    ## Append build options in platform to a module
> > +    #
> > +    #   @param  Module  The module to which the build options will be appended
> > +    #
> > +    #   @retval options     The options appended with build options in platform
> > +    #
> > +    def ApplyBuildOption(self, Module):
> > +        # Get the different options for the different style module
> > +        PlatformOptions = self.EdkIIBuildOption
> > +        ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)
> > +        ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)
> > +        ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)
> > +        if Module in self.Platform.Modules:
> > +            PlatformModule = self.Platform.Modules[str(Module)]
> > +            PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
> > +        else:
> > +            PlatformModuleOptions = {}
> > +
> > +        BuildRuleOrder = None
> > +        for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
> > +            for Tool in Options:
> > +                for Attr in Options[Tool]:
> > +                    if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
> > +                        BuildRuleOrder = Options[Tool][Attr]
> > +
> > +        AllTools = set(list(ModuleOptions.keys()) + list(PlatformOptions.keys()) +
> > +                       list(PlatformModuleOptions.keys()) + list(ModuleTypeOptions.keys()) +
> > +                       list(self.ToolDefinition.keys()))
> > +        BuildOptions = defaultdict(lambda: defaultdict(str))
> > +        for Tool in AllTools:
> > +            for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
> > +                if Tool not in Options:
> > +                    continue
> > +                for Attr in Options[Tool]:
> > +                    #
> > +                    # Do not generate it in Makefile
> > +                    #
> > +                    if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
> > +                        continue
> > +                    Value = Options[Tool][Attr]
> > +                    # check if override is indicated
> > +                    if Value.startswith('='):
> > +                        BuildOptions[Tool][Attr] = mws.handleWsMacro(Value[1:])
> > +                    else:
> > +                        if Attr != 'PATH':
> > +                            BuildOptions[Tool][Attr] += " " + mws.handleWsMacro(Value)
> > +                        else:
> > +                            BuildOptions[Tool][Attr] = mws.handleWsMacro(Value)
> > +
> > +        return BuildOptions, BuildRuleOrder
> > +
> > +
> > +    def GetGlobalBuildOptions(self,Module):
> > +        ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)
> > +        ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)
> > +
> > +        if Module in self.Platform.Modules:
> > +            PlatformModule = self.Platform.Modules[str(Module)]
> > +            PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
> > +        else:
> > +            PlatformModuleOptions = {}
> > +
> > +        return ModuleTypeOptions,PlatformModuleOptions
> > +    def ModuleGuid(self,Module):
> > +        if os.path.basename(Module.MetaFile.File) != os.path.basename(Module.MetaFile.Path):
> > +            #
> > +            # Length of GUID is 36
> > +            #
> > +            return os.path.basename(Module.MetaFile.Path)[:36]
> > +        return Module.Guid
> > +    @cached_property
> > +    def UniqueBaseName(self):
> > +        retVal ={}
> > +        ModuleNameDict = {}
> > +        UniqueName = {}
> > +        for Module in self._MbList:
> > +            unique_base_name = '%s_%s' % (Module.BaseName,self.ModuleGuid(Module))
> > +            if unique_base_name not in ModuleNameDict:
> > +                ModuleNameDict[unique_base_name] = []
> > +            ModuleNameDict[unique_base_name].append(Module.MetaFile)
> > +            if Module.BaseName not in UniqueName:
> > +                UniqueName[Module.BaseName] = set()
> > +            UniqueName[Module.BaseName].add((self.ModuleGuid(Module),Module.MetaFile))
> > +        for module_paths in ModuleNameDict.values():
> > +            if len(module_paths) > 1 and len(set(module_paths))>1:
> > +                samemodules = list(set(module_paths))
> > +                EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'
> > +                                    '  %s\n  %s' % (samemodules[0], samemodules[1]))
> > +        for name in UniqueName:
> > +            Guid_Path = UniqueName[name]
> > +            if len(Guid_Path) > 1:
> > +                retVal[name] = '%s_%s' % (name,Guid_Path.pop()[0])
> > +        return retVal
> > +    ## Expand * in build option key
> > +    #
> > +    #   @param  Options     Options to be expanded
> > +    #   @param  ToolDef     Use specified ToolDef instead of full version.
> > +    #                       This is needed during initialization to prevent
> > +    #                       infinite recursion betweeh BuildOptions,
> > +    #                       ToolDefinition, and this function.
> > +    #
> > +    #   @retval options     Options expanded
> > +    #
> > +    def _ExpandBuildOption(self, Options, ModuleStyle=None, ToolDef=None):
> > +        if not ToolDef:
> > +            ToolDef = self.ToolDefinition
> > +        BuildOptions = {}
> > +        FamilyMatch  = False
> > +        FamilyIsNull = True
> > +
> > +        OverrideList = {}
> > +        #
> > +        # Construct a list contain the build options which need override.
> > +        #
> > +        for Key in Options:
> > +            #
> > +            # Key[0] -- tool family
> > +            # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
> > +            #
> > +            if (Key[0] == self.BuildRuleFamily and
> > +                (ModuleStyle is None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):
> > +                Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')
> > +                if (Target == self.BuildTarget or Target == TAB_STAR) and\
> > +                    (ToolChain == self.ToolChain or ToolChain == TAB_STAR) and\
> > +                    (Arch == self.Arch or Arch == TAB_STAR) and\
> > +                    Options[Key].startswith("="):
> > +
> > +                    if OverrideList.get(Key[1]) is not None:
> > +                        OverrideList.pop(Key[1])
> > +                    OverrideList[Key[1]] = Options[Key]
> > +
> > +        #
> > +        # Use the highest priority value.
> > +        #
> > +        if (len(OverrideList) >= 2):
> > +            KeyList = list(OverrideList.keys())
> > +            for Index in range(len(KeyList)):
> > +                NowKey = KeyList[Index]
> > +                Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")
> > +                for Index1 in range(len(KeyList) - Index - 1):
> > +                    NextKey = KeyList[Index1 + Index + 1]
> > +                    #
> > +                    # Compare two Key, if one is included by another, choose the higher priority one
> > +                    #
> > +                    Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")
> > +                    if (Target1 == Target2 or Target1 == TAB_STAR or Target2 == TAB_STAR) and\
> > +                        (ToolChain1 == ToolChain2 or ToolChain1 == TAB_STAR or ToolChain2 == TAB_STAR) and\
> > +                        (Arch1 == Arch2 or Arch1 == TAB_STAR or Arch2 == TAB_STAR) and\
> > +                        (CommandType1 == CommandType2 or CommandType1 == TAB_STAR or CommandType2 == TAB_STAR) and\
> > +                        (Attr1 == Attr2 or Attr1 == TAB_STAR or Attr2 == TAB_STAR):
> > +
> > +                        if CalculatePriorityValue(NowKey) > CalculatePriorityValue(NextKey):
> > +                            if Options.get((self.BuildRuleFamily, NextKey)) is not None:
> > +                                Options.pop((self.BuildRuleFamily, NextKey))
> > +                        else:
> > +                            if Options.get((self.BuildRuleFamily, NowKey)) is not None:
> > +                                Options.pop((self.BuildRuleFamily, NowKey))
> > +
> > +        for Key in Options:
> > +            if ModuleStyle is not None and len (Key) > 2:
> > +                # Check Module style is EDK or EDKII.
> > +                # Only append build option for the matched style module.
> > +                if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
> > +                    continue
> > +                elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
> > +                    continue
> > +            Family = Key[0]
> > +            Target, Tag, Arch, Tool, Attr = Key[1].split("_")
> > +            # if tool chain family doesn't match, skip it
> > +            if Tool in ToolDef and Family != "":
> > +                FamilyIsNull = False
> > +                if ToolDef[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
> > +                    if Family != ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
> > +                        continue
> > +                elif Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
> > +                    continue
> > +                FamilyMatch = True
> > +            # expand any wildcard
> > +            if Target == TAB_STAR or Target == self.BuildTarget:
> > +                if Tag == TAB_STAR or Tag == self.ToolChain:
> > +                    if Arch == TAB_STAR or Arch == self.Arch:
> > +                        if Tool not in BuildOptions:
> > +                            BuildOptions[Tool] = {}
> > +                        if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
> > +                            BuildOptions[Tool][Attr] = Options[Key]
> > +                        else:
> > +                            # append options for the same tool except PATH
> > +                            if Attr != 'PATH':
> > +                                BuildOptions[Tool][Attr] += " " + Options[Key]
> > +                            else:
> > +                                BuildOptions[Tool][Attr] = Options[Key]
> > +        # Build Option Family has been checked, which need't to be checked again for family.
> > +        if FamilyMatch or FamilyIsNull:
> > +            return BuildOptions
> > +
> > +        for Key in Options:
> > +            if ModuleStyle is not None and len (Key) > 2:
> > +                # Check Module style is EDK or EDKII.
> > +                # Only append build option for the matched style module.
> > +                if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
> > +                    continue
> > +                elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
> > +                    continue
> > +            Family = Key[0]
> > +            Target, Tag, Arch, Tool, Attr = Key[1].split("_")
> > +            # if tool chain family doesn't match, skip it
> > +            if Tool not in ToolDef or Family == "":
> > +                continue
> > +            # option has been added before
> > +            if Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
> > +                continue
> > +
> > +            # expand any wildcard
> > +            if Target == TAB_STAR or Target == self.BuildTarget:
> > +                if Tag == TAB_STAR or Tag == self.ToolChain:
> > +                    if Arch == TAB_STAR or Arch == self.Arch:
> > +                        if Tool not in BuildOptions:
> > +                            BuildOptions[Tool] = {}
> > +                        if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
> > +                            BuildOptions[Tool][Attr] = Options[Key]
> > +                        else:
> > +                            # append options for the same tool except PATH
> > +                            if Attr != 'PATH':
> > +                                BuildOptions[Tool][Attr] += " " + Options[Key]
> > +                            else:
> > +                                BuildOptions[Tool][Attr] = Options[Key]
> > +        return BuildOptions
> > diff --git a/BaseTools/Source/Python/AutoGen/WorkspaceAutoGen.py b/BaseTools/Source/Python/AutoGen/WorkspaceAutoGen.py
> > new file mode 100644
> > index 000000000000..22a7d996fd3b
> > --- /dev/null
> > +++ b/BaseTools/Source/Python/AutoGen/WorkspaceAutoGen.py
> > @@ -0,0 +1,904 @@
> > +## @file
> > +# Create makefile for MS nmake and GNU make
> > +#
> > +# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +
> > +## Import Modules
> > +#
> > +from __future__ import print_function
> > +from __future__ import absolute_import
> > +import os.path as path
> > +import hashlib
> > +from collections import defaultdict
> > +from GenFds.FdfParser import FdfParser
> > +from Workspace.WorkspaceCommon import GetModuleLibInstances
> > +from AutoGen import GenMake
> > +from AutoGen.AutoGen import AutoGen
> > +from AutoGen.PlatformAutoGen import PlatformAutoGen
> > +from AutoGen.BuildEngine import gDefaultBuildRuleFile
> > +from Common.ToolDefClassObject import gDefaultToolsDefFile
> > +from Common.StringUtils import NormPath
> > +from Common.BuildToolError import *
> > +from Common.DataType import *
> > +from Common.Misc import *
> > +
> > +## Regular expression for splitting Dependency Expression string into tokens
> > +gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")
> > +
> > +## Regular expression for match: PCD(xxxx.yyy)
> > +gPCDAsGuidPattern = re.compile(r"^PCD\(.+\..+\)$")
> > +
> > +## Workspace AutoGen class
> > +#
> > +#   This class is used mainly to control the whole platform build for different
> > +# architecture. This class will generate top level makefile.
> > +#
> > +class WorkspaceAutoGen(AutoGen):
> > +    # call super().__init__ then call the worker function with different parameter count
> > +    def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
> > +        if not hasattr(self, "_Init"):
> > +            self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)
> > +            self._Init = True
> > +
> > +    ## Initialize WorkspaceAutoGen
> > +    #
> > +    #   @param  WorkspaceDir            Root directory of workspace
> > +    #   @param  ActivePlatform          Meta-file of active platform
> > +    #   @param  Target                  Build target
> > +    #   @param  Toolchain               Tool chain name
> > +    #   @param  ArchList                List of architecture of current build
> > +    #   @param  MetaFileDb              Database containing meta-files
> > +    #   @param  BuildConfig             Configuration of build
> > +    #   @param  ToolDefinition          Tool chain definitions
> > +    #   @param  FlashDefinitionFile     File of flash definition
> > +    #   @param  Fds                     FD list to be generated
> > +    #   @param  Fvs                     FV list to be generated
> > +    #   @param  Caps                    Capsule list to be generated
> > +    #   @param  SkuId                   SKU id from command line
> > +    #
> > +    def _InitWorker(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb,
> > +              BuildConfig, ToolDefinition, FlashDefinitionFile='', Fds=None, Fvs=None, Caps=None, SkuId='', UniFlag=None,
> > +              Progress=None, BuildModule=None):
> > +        self.BuildDatabase  = MetaFileDb
> > +        self.MetaFile       = ActivePlatform
> > +        self.WorkspaceDir   = WorkspaceDir
> > +        self.Platform       = self.BuildDatabase[self.MetaFile, TAB_ARCH_COMMON, Target, Toolchain]
> > +        GlobalData.gActivePlatform = self.Platform
> > +        self.BuildTarget    = Target
> > +        self.ToolChain      = Toolchain
> > +        self.ArchList       = ArchList
> > +        self.SkuId          = SkuId
> > +        self.UniFlag        = UniFlag
> > +
> > +        self.TargetTxt      = BuildConfig
> > +        self.ToolDef        = ToolDefinition
> > +        self.FdfFile        = FlashDefinitionFile
> > +        self.FdTargetList   = Fds if Fds else []
> > +        self.FvTargetList   = Fvs if Fvs else []
> > +        self.CapTargetList  = Caps if Caps else []
> > +        self.AutoGenObjectList = []
> > +        self._GuidDict = {}
> > +
> > +        # there's many relative directory operations, so ...
> > +        os.chdir(self.WorkspaceDir)
> > +
> > +        self.MergeArch()
> > +        self.ValidateBuildTarget()
> > +
> > +        EdkLogger.info("")
> > +        if self.ArchList:
> > +            EdkLogger.info('%-16s = %s' % ("Architecture(s)", ' '.join(self.ArchList)))
> > +        EdkLogger.info('%-16s = %s' % ("Build target", self.BuildTarget))
> > +        EdkLogger.info('%-16s = %s' % ("Toolchain", self.ToolChain))
> > +
> > +        EdkLogger.info('\n%-24s = %s' % ("Active Platform", self.Platform))
> > +        if BuildModule:
> > +            EdkLogger.info('%-24s = %s' % ("Active Module", BuildModule))
> > +
> > +        if self.FdfFile:
> > +            EdkLogger.info('%-24s = %s' % ("Flash Image Definition", self.FdfFile))
> > +
> > +        EdkLogger.verbose("\nFLASH_DEFINITION = %s" % self.FdfFile)
> > +
> > +        if Progress:
> > +            Progress.Start("\nProcessing meta-data")
> > +        #
> > +        # Mark now build in AutoGen Phase
> > +        #
> > +        GlobalData.gAutoGenPhase = True
> > +        self.ProcessModuleFromPdf()
> > +        self.ProcessPcdType()
> > +        self.ProcessMixedPcd()
> > +        self.VerifyPcdsFromFDF()
> > +        self.CollectAllPcds()
> > +        self.GeneratePkgLevelHash()
> > +        #
> > +        # Check PCDs token value conflict in each DEC file.
> > +        #
> > +        self._CheckAllPcdsTokenValueConflict()
> > +        #
> > +        # Check PCD type and definition between DSC and DEC
> > +        #
> > +        self._CheckPcdDefineAndType()
> > +
> > +        self.CreateBuildOptionsFile()
> > +        self.CreatePcdTokenNumberFile()
> > +        self.CreateModuleHashInfo()
> > +        GlobalData.gAutoGenPhase = False
> > +
> > +    #
> > +    # Merge Arch
> > +    #
> > +    def MergeArch(self):
> > +        if not self.ArchList:
> > +            ArchList = set(self.Platform.SupArchList)
> > +        else:
> > +            ArchList = set(self.ArchList) & set(self.Platform.SupArchList)
> > +        if not ArchList:
> > +            EdkLogger.error("build", PARAMETER_INVALID,
> > +                            ExtraData = "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self.Platform.SupArchList)))
> > +        elif self.ArchList and len(ArchList) != len(self.ArchList):
> > +            SkippedArchList = set(self.ArchList).symmetric_difference(set(self.Platform.SupArchList))
> > +            EdkLogger.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
> > +                              % (" ".join(SkippedArchList), " ".join(self.Platform.SupArchList)))
> > +        self.ArchList = tuple(ArchList)
> > +
> > +    # Validate build target
> > +    def ValidateBuildTarget(self):
> > +        if self.BuildTarget not in self.Platform.BuildTargets:
> > +            EdkLogger.error("build", PARAMETER_INVALID,
> > +                            ExtraData="Build target [%s] is not supported by the platform. [Valid target: %s]"
> > +                                      % (self.BuildTarget, " ".join(self.Platform.BuildTargets)))
> > +    @cached_property
> > +    def FdfProfile(self):
> > +        if not self.FdfFile:
> > +            self.FdfFile = self.Platform.FlashDefinition
> > +
> > +        FdfProfile = None
> > +        if self.FdfFile:
> > +            Fdf = FdfParser(self.FdfFile.Path)
> > +            Fdf.ParseFile()
> > +            GlobalData.gFdfParser = Fdf
> > +            if Fdf.CurrentFdName and Fdf.CurrentFdName in Fdf.Profile.FdDict:
> > +                FdDict = Fdf.Profile.FdDict[Fdf.CurrentFdName]
> > +                for FdRegion in FdDict.RegionList:
> > +                    if str(FdRegion.RegionType) is 'FILE' and self.Platform.VpdToolGuid in str(FdRegion.RegionDataList):
> > +                        if int(FdRegion.Offset) % 8 != 0:
> > +                            EdkLogger.error("build", FORMAT_INVALID, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion.Offset))
> > +            FdfProfile = Fdf.Profile
> > +        else:
> > +            if self.FdTargetList:
> > +                EdkLogger.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self.FdTargetList))
> > +                self.FdTargetList = []
> > +            if self.FvTargetList:
> > +                EdkLogger.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self.FvTargetList))
> > +                self.FvTargetList = []
> > +            if self.CapTargetList:
> > +                EdkLogger.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self.CapTargetList))
> > +                self.CapTargetList = []
> > +
> > +        return FdfProfile
> > +
> > +    def ProcessModuleFromPdf(self):
> > +
> > +        if self.FdfProfile:
> > +            for fvname in self.FvTargetList:
> > +                if fvname.upper() not in self.FdfProfile.FvDict:
> > +                    EdkLogger.error("build", OPTION_VALUE_INVALID,
> > +                                    "No such an FV in FDF file: %s" % fvname)
> > +
> > +            # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
> > +            # but the path (self.MetaFile.Path) is the real path
> > +            for key in self.FdfProfile.InfDict:
> > +                if key == 'ArchTBD':
> > +                    MetaFile_cache = defaultdict(set)
> > +                    for Arch in self.ArchList:
> > +                        Current_Platform_cache = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]
> > +                        for Pkey in Current_Platform_cache.Modules:
> > +                            MetaFile_cache[Arch].add(Current_Platform_cache.Modules[Pkey].MetaFile)
> > +                    for Inf in self.FdfProfile.InfDict[key]:
> > +                        ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)
> > +                        for Arch in self.ArchList:
> > +                            if ModuleFile in MetaFile_cache[Arch]:
> > +                                break
> > +                        else:
> > +                            ModuleData = self.BuildDatabase[ModuleFile, Arch, self.BuildTarget, self.ToolChain]
> > +                            if not ModuleData.IsBinaryModule:
> > +                                EdkLogger.error('build', PARSER_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile)
> > +
> > +                else:
> > +                    for Arch in self.ArchList:
> > +                        if Arch == key:
> > +                            Platform = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]
> > +                            MetaFileList = set()
> > +                            for Pkey in Platform.Modules:
> > +                                MetaFileList.add(Platform.Modules[Pkey].MetaFile)
> > +                            for Inf in self.FdfProfile.InfDict[key]:
> > +                                ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)
> > +                                if ModuleFile in MetaFileList:
> > +                                    continue
> > +                                ModuleData = self.BuildDatabase[ModuleFile, Arch, self.BuildTarget, self.ToolChain]
> > +                                if not ModuleData.IsBinaryModule:
> > +                                    EdkLogger.error('build', PARSER_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile)
> > +
> > +
> > +
> > +    # parse FDF file to get PCDs in it, if any
> > +    def VerifyPcdsFromFDF(self):
> > +
> > +        if self.FdfProfile:
> > +            PcdSet = self.FdfProfile.PcdDict
> > +            self.VerifyPcdDeclearation(PcdSet)
> > +
> > +    def ProcessPcdType(self):
> > +        for Arch in self.ArchList:
> > +            Platform = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]
> > +            Platform.Pcds
> > +            # generate the SourcePcdDict and BinaryPcdDict
> > +            Libs = []
> > +            for BuildData in list(self.BuildDatabase._CACHE_.values()):
> > +                if BuildData.Arch != Arch:
> > +                    continue
> > +                if BuildData.MetaFile.Ext == '.inf' and str(BuildData) in Platform.Modules :
> > +                    Libs.extend(GetModuleLibInstances(BuildData, Platform,
> > +                                     self.BuildDatabase,
> > +                                     Arch,
> > +                                     self.BuildTarget,
> > +                                     self.ToolChain
> > +                                     ))
> > +            for BuildData in list(self.BuildDatabase._CACHE_.values()):
> > +                if BuildData.Arch != Arch:
> > +                    continue
> > +                if BuildData.MetaFile.Ext == '.inf':
> > +                    for key in BuildData.Pcds:
> > +                        if BuildData.Pcds[key].Pending:
> > +                            if key in Platform.Pcds:
> > +                                PcdInPlatform = Platform.Pcds[key]
> > +                                if PcdInPlatform.Type:
> > +                                    BuildData.Pcds[key].Type = PcdInPlatform.Type
> > +                                    BuildData.Pcds[key].Pending = False
> > +
> > +                            if BuildData.MetaFile in Platform.Modules:
> > +                                PlatformModule = Platform.Modules[str(BuildData.MetaFile)]
> > +                                if key in PlatformModule.Pcds:
> > +                                    PcdInPlatform = PlatformModule.Pcds[key]
> > +                                    if PcdInPlatform.Type:
> > +                                        BuildData.Pcds[key].Type = PcdInPlatform.Type
> > +                                        BuildData.Pcds[key].Pending = False
> > +                            else:
> > +                                #Pcd used in Library, Pcd Type from reference module if Pcd Type is Pending
> > +                                if BuildData.Pcds[key].Pending:
> > +                                    if bool(BuildData.LibraryClass):
> > +                                        if BuildData in set(Libs):
> > +                                            ReferenceModules = BuildData.ReferenceModules
> > +                                            for ReferenceModule in ReferenceModules:
> > +                                                if ReferenceModule.MetaFile in Platform.Modules:
> > +                                                    RefPlatformModule = Platform.Modules[str(ReferenceModule.MetaFile)]
> > +                                                    if key in RefPlatformModule.Pcds:
> > +                                                        PcdInReferenceModule = RefPlatformModule.Pcds[key]
> > +                                                        if PcdInReferenceModule.Type:
> > +                                                            BuildData.Pcds[key].Type = PcdInReferenceModule.Type
> > +                                                            BuildData.Pcds[key].Pending = False
> > +                                                            break
> > +
> > +    def ProcessMixedPcd(self):
> > +        for Arch in self.ArchList:
> > +            SourcePcdDict = {TAB_PCDS_DYNAMIC_EX:set(), TAB_PCDS_PATCHABLE_IN_MODULE:set(),TAB_PCDS_DYNAMIC:set(),TAB_PCDS_FIXED_AT_BUILD:set()}
> > +            BinaryPcdDict = {TAB_PCDS_DYNAMIC_EX:set(), TAB_PCDS_PATCHABLE_IN_MODULE:set()}
> > +            SourcePcdDict_Keys = SourcePcdDict.keys()
> > +            BinaryPcdDict_Keys = BinaryPcdDict.keys()
> > +
> > +            # generate the SourcePcdDict and BinaryPcdDict
> > +
> > +            for BuildData in list(self.BuildDatabase._CACHE_.values()):
> > +                if BuildData.Arch != Arch:
> > +                    continue
> > +                if BuildData.MetaFile.Ext == '.inf':
> > +                    for key in BuildData.Pcds:
> > +                        if TAB_PCDS_DYNAMIC_EX in BuildData.Pcds[key].Type:
> > +                            if BuildData.IsBinaryModule:
> > +                                BinaryPcdDict[TAB_PCDS_DYNAMIC_EX].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
> > +                            else:
> > +                                SourcePcdDict[TAB_PCDS_DYNAMIC_EX].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
> > +
> > +                        elif TAB_PCDS_PATCHABLE_IN_MODULE in BuildData.Pcds[key].Type:
> > +                            if BuildData.MetaFile.Ext == '.inf':
> > +                                if BuildData.IsBinaryModule:
> > +                                    BinaryPcdDict[TAB_PCDS_PATCHABLE_IN_MODULE].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
> > +                                else:
> > +                                    SourcePcdDict[TAB_PCDS_PATCHABLE_IN_MODULE].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
> > +
> > +                        elif TAB_PCDS_DYNAMIC in BuildData.Pcds[key].Type:
> > +                            SourcePcdDict[TAB_PCDS_DYNAMIC].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
> > +                        elif TAB_PCDS_FIXED_AT_BUILD in BuildData.Pcds[key].Type:
> > +                            SourcePcdDict[TAB_PCDS_FIXED_AT_BUILD].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
> > +
> > +            #
> > +            # A PCD can only use one type for all source modules
> > +            #
> > +            for i in SourcePcdDict_Keys:
> > +                for j in SourcePcdDict_Keys:
> > +                    if i != j:
> > +                        Intersections = SourcePcdDict[i].intersection(SourcePcdDict[j])
> > +                        if len(Intersections) > 0:
> > +                            EdkLogger.error(
> > +                            'build',
> > +                            FORMAT_INVALID,
> > +                            "Building modules from source INFs, following PCD use %s and %s access method. It must be corrected to use only one access method." % (i, j),
> > +                            ExtraData='\n\t'.join(str(P[1]+'.'+P[0]) for P in Intersections)
> > +                            )
> > +
> > +            #
> > +            # intersection the BinaryPCD for Mixed PCD
> > +            #
> > +            for i in BinaryPcdDict_Keys:
> > +                for j in BinaryPcdDict_Keys:
> > +                    if i != j:
> > +                        Intersections = BinaryPcdDict[i].intersection(BinaryPcdDict[j])
> > +                        for item in Intersections:
> > +                            NewPcd1 = (item[0] + '_' + i, item[1])
> > +                            NewPcd2 = (item[0] + '_' + j, item[1])
> > +                            if item not in GlobalData.MixedPcd:
> > +                                GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]
> > +                            else:
> > +                                if NewPcd1 not in GlobalData.MixedPcd[item]:
> > +                                    GlobalData.MixedPcd[item].append(NewPcd1)
> > +                                if NewPcd2 not in GlobalData.MixedPcd[item]:
> > +                                    GlobalData.MixedPcd[item].append(NewPcd2)
> > +
> > +            #
> > +            # intersection the SourcePCD and BinaryPCD for Mixed PCD
> > +            #
> > +            for i in SourcePcdDict_Keys:
> > +                for j in BinaryPcdDict_Keys:
> > +                    if i != j:
> > +                        Intersections = SourcePcdDict[i].intersection(BinaryPcdDict[j])
> > +                        for item in Intersections:
> > +                            NewPcd1 = (item[0] + '_' + i, item[1])
> > +                            NewPcd2 = (item[0] + '_' + j, item[1])
> > +                            if item not in GlobalData.MixedPcd:
> > +                                GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]
> > +                            else:
> > +                                if NewPcd1 not in GlobalData.MixedPcd[item]:
> > +                                    GlobalData.MixedPcd[item].append(NewPcd1)
> > +                                if NewPcd2 not in GlobalData.MixedPcd[item]:
> > +                                    GlobalData.MixedPcd[item].append(NewPcd2)
> > +
> > +            BuildData = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]
> > +            for key in BuildData.Pcds:
> > +                for SinglePcd in GlobalData.MixedPcd:
> > +                    if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) == SinglePcd:
> > +                        for item in GlobalData.MixedPcd[SinglePcd]:
> > +                            Pcd_Type = item[0].split('_')[-1]
> > +                            if (Pcd_Type == BuildData.Pcds[key].Type) or (Pcd_Type == TAB_PCDS_DYNAMIC_EX and BuildData.Pcds[key].Type in PCD_DYNAMIC_EX_TYPE_SET) or \
> > +                               (Pcd_Type == TAB_PCDS_DYNAMIC and BuildData.Pcds[key].Type in PCD_DYNAMIC_TYPE_SET):
> > +                                Value = BuildData.Pcds[key]
> > +                                Value.TokenCName = BuildData.Pcds[key].TokenCName + '_' + Pcd_Type
> > +                                if len(key) == 2:
> > +                                    newkey = (Value.TokenCName, key[1])
> > +                                elif len(key) == 3:
> > +                                    newkey = (Value.TokenCName, key[1], key[2])
> > +                                del BuildData.Pcds[key]
> > +                                BuildData.Pcds[newkey] = Value
> > +                                break
> > +                        break
> > +
> > +        if self.FdfProfile:
> > +            PcdSet = self.FdfProfile.PcdDict
> > +            # handle the mixed pcd in FDF file
> > +            for key in PcdSet:
> > +                if key in GlobalData.MixedPcd:
> > +                    Value = PcdSet[key]
> > +                    del PcdSet[key]
> > +                    for item in GlobalData.MixedPcd[key]:
> > +                        PcdSet[item] = Value
> > +
> > +    #Collect package set information from INF of FDF
> > +    @cached_property
> > +    def PkgSet(self):
> > +        if not self.FdfFile:
> > +            self.FdfFile = self.Platform.FlashDefinition
> > +
> > +        if self.FdfFile:
> > +            ModuleList = self.FdfProfile.InfList
> > +        else:
> > +            ModuleList = []
> > +        Pkgs = {}
> > +        for Arch in self.ArchList:
> > +            Platform = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]
> > +            PkgSet = set()
> > +            for mb in [self.BuildDatabase[m, Arch, self.BuildTarget, self.ToolChain] for m in Platform.Modules]:
> > +                PkgSet.update(mb.Packages)
> > +            for Inf in ModuleList:
> > +                ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)
> > +                if ModuleFile in Platform.Modules:
> > +                    continue
> > +                ModuleData = self.BuildDatabase[ModuleFile, Arch, self.BuildTarget, self.ToolChain]
> > +                PkgSet.update(ModuleData.Packages)
> > +            Pkgs[Arch] = list(PkgSet)
> > +        return Pkgs
> > +
> > +    def VerifyPcdDeclearation(self,PcdSet):
> > +        for Arch in self.ArchList:
> > +            Platform = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]
> > +            Pkgs = self.PkgSet[Arch]
> > +            DecPcds = set()
> > +            DecPcdsKey = set()
> > +            for Pkg in Pkgs:
> > +                for Pcd in Pkg.Pcds:
> > +                    DecPcds.add((Pcd[0], Pcd[1]))
> > +                    DecPcdsKey.add((Pcd[0], Pcd[1], Pcd[2]))
> > +
> > +            Platform.SkuName = self.SkuId
> > +            for Name, Guid,Fileds in PcdSet:
> > +                if (Name, Guid) not in DecPcds:
> > +                    EdkLogger.error(
> > +                        'build',
> > +                        PARSER_ERROR,
> > +                        "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid, Name),
> > +                        File = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][0],
> > +                        Line = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][1]
> > +                    )
> > +                else:
> > +                    # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
> > +                    if (Name, Guid, TAB_PCDS_FIXED_AT_BUILD) in DecPcdsKey \
> > +                        or (Name, Guid, TAB_PCDS_PATCHABLE_IN_MODULE) in DecPcdsKey \
> > +                        or (Name, Guid, TAB_PCDS_FEATURE_FLAG) in DecPcdsKey:
> > +                        continue
> > +                    elif (Name, Guid, TAB_PCDS_DYNAMIC) in DecPcdsKey or (Name, Guid, TAB_PCDS_DYNAMIC_EX) in DecPcdsKey:
> > +                        EdkLogger.error(
> > +                                'build',
> > +                                PARSER_ERROR,
> > +                                "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid, Name),
> > +                                File = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][0],
> > +                                Line = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][1]
> > +                        )
> > +    def CollectAllPcds(self):
> > +
> > +        for Arch in self.ArchList:
> > +            Pa = PlatformAutoGen(self, self.MetaFile, self.BuildTarget, self.ToolChain, Arch)
> > +            #
> > +            # Explicitly collect platform's dynamic PCDs
> > +            #
> > +            Pa.CollectPlatformDynamicPcds()
> > +            Pa.CollectFixedAtBuildPcds()
> > +            self.AutoGenObjectList.append(Pa)
> > +        # We need to calculate the PcdTokenNumber after all Arch Pcds are collected.
> > +        for Arch in self.ArchList:
> > +            #Pcd TokenNumber
> > +            Pa = PlatformAutoGen(self, self.MetaFile, self.BuildTarget, self.ToolChain, Arch)
> > +            self.UpdateModuleDataPipe(Arch,  {"PCD_TNUM":Pa.PcdTokenNumber})
> > +
> > +    def UpdateModuleDataPipe(self,arch, attr_dict):
> > +        for (Target, Toolchain, Arch, MetaFile) in AutoGen.Cache():
> > +            if Arch != arch:
> > +                continue
> > +            try:
> > +                AutoGen.Cache()[(Target, Toolchain, Arch, MetaFile)].DataPipe.DataContainer = attr_dict
> > +            except Exception:
> > +                pass
> > +    #
> > +    # Generate Package level hash value
> > +    #
> > +    def GeneratePkgLevelHash(self):
> > +        for Arch in self.ArchList:
> > +            GlobalData.gPackageHash = {}
> > +            if GlobalData.gUseHashCache:
> > +                for Pkg in self.PkgSet[Arch]:
> > +                    self._GenPkgLevelHash(Pkg)
> > +
> > +
> > +    def CreateBuildOptionsFile(self):
> > +        #
> > +        # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
> > +        #
> > +        content = 'gCommandLineDefines: '
> > +        content += str(GlobalData.gCommandLineDefines)
> > +        content += TAB_LINE_BREAK
> > +        content += 'BuildOptionPcd: '
> > +        content += str(GlobalData.BuildOptionPcd)
> > +        content += TAB_LINE_BREAK
> > +        content += 'Active Platform: '
> > +        content += str(self.Platform)
> > +        content += TAB_LINE_BREAK
> > +        if self.FdfFile:
> > +            content += 'Flash Image Definition: '
> > +            content += str(self.FdfFile)
> > +            content += TAB_LINE_BREAK
> > +        SaveFileOnChange(os.path.join(self.BuildDir, 'BuildOptions'), content, False)
> > +
> > +    def CreatePcdTokenNumberFile(self):
> > +        #
> > +        # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
> > +        #
> > +        PcdTokenNumber = 'PcdTokenNumber: '
> > +        Pa = self.AutoGenObjectList[0]
> > +        if Pa.PcdTokenNumber:
> > +            if Pa.DynamicPcdList:
> > +                for Pcd in Pa.DynamicPcdList:
> > +                    PcdTokenNumber += TAB_LINE_BREAK
> > +                    PcdTokenNumber += str((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))
> > +                    PcdTokenNumber += ' : '
> > +                    PcdTokenNumber += str(Pa.PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName])
> > +        SaveFileOnChange(os.path.join(self.BuildDir, 'PcdTokenNumber'), PcdTokenNumber, False)
> > +
> > +    def CreateModuleHashInfo(self):
> > +        #
> > +        # Get set of workspace metafiles
> > +        #
> > +        AllWorkSpaceMetaFiles = self._GetMetaFiles(self.BuildTarget, self.ToolChain)
> > +
> > +        #
> > +        # Retrieve latest modified time of all metafiles
> > +        #
> > +        SrcTimeStamp = 0
> > +        for f in AllWorkSpaceMetaFiles:
> > +            if os.stat(f)[8] > SrcTimeStamp:
> > +                SrcTimeStamp = os.stat(f)[8]
> > +        self._SrcTimeStamp = SrcTimeStamp
> > +
> > +        if GlobalData.gUseHashCache:
> > +            m = hashlib.md5()
> > +            for files in AllWorkSpaceMetaFiles:
> > +                if files.endswith('.dec'):
> > +                    continue
> > +                f = open(files, 'rb')
> > +                Content = f.read()
> > +                f.close()
> > +                m.update(Content)
> > +            SaveFileOnChange(os.path.join(self.BuildDir, 'AutoGen.hash'), m.hexdigest(), False)
> > +            GlobalData.gPlatformHash = m.hexdigest()
> > +
> > +        #
> > +        # Write metafile list to build directory
> > +        #
> > +        AutoGenFilePath = os.path.join(self.BuildDir, 'AutoGen')
> > +        if os.path.exists (AutoGenFilePath):
> > +            os.remove(AutoGenFilePath)
> > +        if not os.path.exists(self.BuildDir):
> > +            os.makedirs(self.BuildDir)
> > +        with open(os.path.join(self.BuildDir, 'AutoGen'), 'w+') as file:
> > +            for f in AllWorkSpaceMetaFiles:
> > +                print(f, file=file)
> > +        return True
> > +
> > +    def _GenPkgLevelHash(self, Pkg):
> > +        if Pkg.PackageName in GlobalData.gPackageHash:
> > +            return
> > +
> > +        PkgDir = os.path.join(self.BuildDir, Pkg.Arch, Pkg.PackageName)
> > +        CreateDirectory(PkgDir)
> > +        HashFile = os.path.join(PkgDir, Pkg.PackageName + '.hash')
> > +        m = hashlib.md5()
> > +        # Get .dec file's hash value
> > +        f = open(Pkg.MetaFile.Path, 'rb')
> > +        Content = f.read()
> > +        f.close()
> > +        m.update(Content)
> > +        # Get include files hash value
> > +        if Pkg.Includes:
> > +            for inc in sorted(Pkg.Includes, key=lambda x: str(x)):
> > +                for Root, Dirs, Files in os.walk(str(inc)):
> > +                    for File in sorted(Files):
> > +                        File_Path = os.path.join(Root, File)
> > +                        f = open(File_Path, 'rb')
> > +                        Content = f.read()
> > +                        f.close()
> > +                        m.update(Content)
> > +        SaveFileOnChange(HashFile, m.hexdigest(), False)
> > +        GlobalData.gPackageHash[Pkg.PackageName] = m.hexdigest()
> > +
> > +    def _GetMetaFiles(self, Target, Toolchain):
> > +        AllWorkSpaceMetaFiles = set()
> > +        #
> > +        # add fdf
> > +        #
> > +        if self.FdfFile:
> > +            AllWorkSpaceMetaFiles.add (self.FdfFile.Path)
> > +            for f in GlobalData.gFdfParser.GetAllIncludedFile():
> > +                AllWorkSpaceMetaFiles.add (f.FileName)
> > +        #
> > +        # add dsc
> > +        #
> > +        AllWorkSpaceMetaFiles.add(self.MetaFile.Path)
> > +
> > +        #
> > +        # add build_rule.txt & tools_def.txt
> > +        #
> > +        AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultBuildRuleFile))
> > +        AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultToolsDefFile))
> > +
> > +        # add BuildOption metafile
> > +        #
> > +        AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'BuildOptions'))
> > +
> > +        # add PcdToken Number file for Dynamic/DynamicEx Pcd
> > +        #
> > +        AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'PcdTokenNumber'))
> > +
> > +        for Pa in self.AutoGenObjectList:
> > +            AllWorkSpaceMetaFiles.add(Pa.ToolDefinitionFile)
> > +
> > +        for Arch in self.ArchList:
> > +            #
> > +            # add dec
> > +            #
> > +            for Package in PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch).PackageList:
> > +                AllWorkSpaceMetaFiles.add(Package.MetaFile.Path)
> > +
> > +            #
> > +            # add included dsc
> > +            #
> > +            for filePath in self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]._RawData.IncludedFiles:
> > +                AllWorkSpaceMetaFiles.add(filePath.Path)
> > +
> > +        return AllWorkSpaceMetaFiles
> > +
> > +    def _CheckPcdDefineAndType(self):
> > +        PcdTypeSet = {TAB_PCDS_FIXED_AT_BUILD,
> > +            TAB_PCDS_PATCHABLE_IN_MODULE,
> > +            TAB_PCDS_FEATURE_FLAG,
> > +            TAB_PCDS_DYNAMIC,
> > +            TAB_PCDS_DYNAMIC_EX}
> > +
> > +        # This dict store PCDs which are not used by any modules with specified arches
> > +        UnusedPcd = OrderedDict()
> > +        for Pa in self.AutoGenObjectList:
> > +            # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
> > +            for Pcd in Pa.Platform.Pcds:
> > +                PcdType = Pa.Platform.Pcds[Pcd].Type
> > +
> > +                # If no PCD type, this PCD comes from FDF
> > +                if not PcdType:
> > +                    continue
> > +
> > +                # Try to remove Hii and Vpd suffix
> > +                if PcdType.startswith(TAB_PCDS_DYNAMIC_EX):
> > +                    PcdType = TAB_PCDS_DYNAMIC_EX
> > +                elif PcdType.startswith(TAB_PCDS_DYNAMIC):
> > +                    PcdType = TAB_PCDS_DYNAMIC
> > +
> > +                for Package in Pa.PackageList:
> > +                    # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
> > +                    if (Pcd[0], Pcd[1], PcdType) in Package.Pcds:
> > +                        break
> > +                    for Type in PcdTypeSet:
> > +                        if (Pcd[0], Pcd[1], Type) in Package.Pcds:
> > +                            EdkLogger.error(
> > +                                'build',
> > +                                FORMAT_INVALID,
> > +                                "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
> > +                                % (Pa.Platform.Pcds[Pcd].Type, Pcd[1], Pcd[0], Type),
> > +                                ExtraData=None
> > +                            )
> > +                            return
> > +                else:
> > +                    UnusedPcd.setdefault(Pcd, []).append(Pa.Arch)
> > +
> > +        for Pcd in UnusedPcd:
> > +            EdkLogger.warn(
> > +                'build',
> > +                "The PCD was not specified by any INF module in the platform for the given architecture.\n"
> > +                "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
> > +                % (Pcd[1], Pcd[0], os.path.basename(str(self.MetaFile)), str(UnusedPcd[Pcd])),
> > +                ExtraData=None
> > +            )
> > +
> > +    def __repr__(self):
> > +        return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))
> > +
> > +    ## Return the directory to store FV files
> > +    @cached_property
> > +    def FvDir(self):
> > +        return path.join(self.BuildDir, TAB_FV_DIRECTORY)
> > +
> > +    ## Return the directory to store all intermediate and final files built
> > +    @cached_property
> > +    def BuildDir(self):
> > +        return self.AutoGenObjectList[0].BuildDir
> > +
> > +    ## Return the build output directory platform specifies
> > +    @cached_property
> > +    def OutputDir(self):
> > +        return self.Platform.OutputDirectory
> > +
> > +    ## Return platform name
> > +    @cached_property
> > +    def Name(self):
> > +        return self.Platform.PlatformName
> > +
> > +    ## Return meta-file GUID
> > +    @cached_property
> > +    def Guid(self):
> > +        return self.Platform.Guid
> > +
> > +    ## Return platform version
> > +    @cached_property
> > +    def Version(self):
> > +        return self.Platform.Version
> > +
> > +    ## Return paths of tools
> > +    @cached_property
> > +    def ToolDefinition(self):
> > +        return self.AutoGenObjectList[0].ToolDefinition
> > +
> > +    ## Return directory of platform makefile
> > +    #
> > +    #   @retval     string  Makefile directory
> > +    #
> > +    @cached_property
> > +    def MakeFileDir(self):
> > +        return self.BuildDir
> > +
> > +    ## Return build command string
> > +    #
> > +    #   @retval     string  Build command string
> > +    #
> > +    @cached_property
> > +    def BuildCommand(self):
> > +        # BuildCommand should be all the same. So just get one from platform AutoGen
> > +        return self.AutoGenObjectList[0].BuildCommand
> > +
> > +    ## Check the PCDs token value conflict in each DEC file.
> > +    #
> > +    # Will cause build break and raise error message while two PCDs conflict.
> > +    #
> > +    # @return  None
> > +    #
> > +    def _CheckAllPcdsTokenValueConflict(self):
> > +        for Pa in self.AutoGenObjectList:
> > +            for Package in Pa.PackageList:
> > +                PcdList = list(Package.Pcds.values())
> > +                PcdList.sort(key=lambda x: int(x.TokenValue, 0))
> > +                Count = 0
> > +                while (Count < len(PcdList) - 1) :
> > +                    Item = PcdList[Count]
> > +                    ItemNext = PcdList[Count + 1]
> > +                    #
> > +                    # Make sure in the same token space the TokenValue should be unique
> > +                    #
> > +                    if (int(Item.TokenValue, 0) == int(ItemNext.TokenValue, 0)):
> > +                        SameTokenValuePcdList = []
> > +                        SameTokenValuePcdList.append(Item)
> > +                        SameTokenValuePcdList.append(ItemNext)
> > +                        RemainPcdListLength = len(PcdList) - Count - 2
> > +                        for ValueSameCount in range(RemainPcdListLength):
> > +                            if int(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount].TokenValue, 0) == int(Item.TokenValue, 0):
> > +                                SameTokenValuePcdList.append(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount])
> > +                            else:
> > +                                break;
> > +                        #
> > +                        # Sort same token value PCD list with TokenGuid and TokenCName
> > +                        #
> > +                        SameTokenValuePcdList.sort(key=lambda x: "%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName))
> > +                        SameTokenValuePcdListCount = 0
> > +                        while (SameTokenValuePcdListCount < len(SameTokenValuePcdList) - 1):
> > +                            Flag = False
> > +                            TemListItem = SameTokenValuePcdList[SameTokenValuePcdListCount]
> > +                            TemListItemNext = SameTokenValuePcdList[SameTokenValuePcdListCount + 1]
> > +
> > +                            if (TemListItem.TokenSpaceGuidCName == TemListItemNext.TokenSpaceGuidCName) and (TemListItem.TokenCName != TemListItemNext.TokenCName):
> > +                                for PcdItem in GlobalData.MixedPcd:
> > +                                    if (TemListItem.TokenCName, TemListItem.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem] or \
> > +                                        (TemListItemNext.TokenCName, TemListItemNext.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
> > +                                        Flag = True
> > +                                if not Flag:
> > +                                    EdkLogger.error(
> > +                                                'build',
> > +                                                FORMAT_INVALID,
> > +                                                "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
> > +                                                % (TemListItem.TokenValue, TemListItem.TokenSpaceGuidCName, TemListItem.TokenCName, TemListItemNext.TokenSpaceGuidCName, TemListItemNext.TokenCName, Package),
> > +                                                ExtraData=None
> > +                                                )
> > +                            SameTokenValuePcdListCount += 1
> > +                        Count += SameTokenValuePcdListCount
> > +                    Count += 1
> > +
> > +                PcdList = list(Package.Pcds.values())
> > +                PcdList.sort(key=lambda x: "%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName))
> > +                Count = 0
> > +                while (Count < len(PcdList) - 1) :
> > +                    Item = PcdList[Count]
> > +                    ItemNext = PcdList[Count + 1]
> > +                    #
> > +                    # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
> > +                    #
> > +                    if (Item.TokenSpaceGuidCName == ItemNext.TokenSpaceGuidCName) and (Item.TokenCName == ItemNext.TokenCName) and (int(Item.TokenValue, 0) != int(ItemNext.TokenValue, 0)):
> > +                        EdkLogger.error(
> > +                                    'build',
> > +                                    FORMAT_INVALID,
> > +                                    "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
> > +                                    % (Item.TokenValue, Item.TokenSpaceGuidCName, Item.TokenCName, Package),
> > +                                    ExtraData=None
> > +                                    )
> > +                    Count += 1
> > +    ## Generate fds command
> > +    @property
> > +    def GenFdsCommand(self):
> > +        return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()
> > +
> > +    @property
> > +    def GenFdsCommandDict(self):
> > +        FdsCommandDict = {}
> > +        LogLevel = EdkLogger.GetLevel()
> > +        if LogLevel == EdkLogger.VERBOSE:
> > +            FdsCommandDict["verbose"] = True
> > +        elif LogLevel <= EdkLogger.DEBUG_9:
> > +            FdsCommandDict["debug"] = LogLevel - 1
> > +        elif LogLevel == EdkLogger.QUIET:
> > +            FdsCommandDict["quiet"] = True
> > +
> > +        if GlobalData.gEnableGenfdsMultiThread:
> > +            FdsCommandDict["GenfdsMultiThread"] = True
> > +        if GlobalData.gIgnoreSource:
> > +            FdsCommandDict["IgnoreSources"] = True
> > +
> > +        FdsCommandDict["OptionPcd"] = []
> > +        for pcd in GlobalData.BuildOptionPcd:
> > +            if pcd[2]:
> > +                pcdname = '.'.join(pcd[0:3])
> > +            else:
> > +                pcdname = '.'.join(pcd[0:2])
> > +            if pcd[3].startswith('{'):
> > +                FdsCommandDict["OptionPcd"].append(pcdname + '=' + 'H' + '"' + pcd[3] + '"')
> > +            else:
> > +                FdsCommandDict["OptionPcd"].append(pcdname + '=' + pcd[3])
> > +
> > +        MacroList = []
> > +        # macros passed to GenFds
> > +        MacroDict = {}
> > +        MacroDict.update(GlobalData.gGlobalDefines)
> > +        MacroDict.update(GlobalData.gCommandLineDefines)
> > +        for MacroName in MacroDict:
> > +            if MacroDict[MacroName] != "":
> > +                MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))
> > +            else:
> > +                MacroList.append('"%s"' % MacroName)
> > +        FdsCommandDict["macro"] = MacroList
> > +
> > +        FdsCommandDict["fdf_file"] = [self.FdfFile]
> > +        FdsCommandDict["build_target"] = self.BuildTarget
> > +        FdsCommandDict["toolchain_tag"] = self.ToolChain
> > +        FdsCommandDict["active_platform"] = str(self)
> > +
> > +        FdsCommandDict["conf_directory"] = GlobalData.gConfDirectory
> > +        FdsCommandDict["build_architecture_list"] = ','.join(self.ArchList)
> > +        FdsCommandDict["platform_build_directory"] = self.BuildDir
> > +
> > +        FdsCommandDict["fd"] = self.FdTargetList
> > +        FdsCommandDict["fv"] = self.FvTargetList
> > +        FdsCommandDict["cap"] = self.CapTargetList
> > +        return FdsCommandDict
> > +
> > +    ## Create makefile for the platform and modules in it
> > +    #
> > +    #   @param      CreateDepsMakeFile      Flag indicating if the makefile for
> > +    #                                       modules will be created as well
> > +    #
> > +    def CreateMakeFile(self, CreateDepsMakeFile=False):
> > +        if not CreateDepsMakeFile:
> > +            return
> > +        for Pa in self.AutoGenObjectList:
> > +            Pa.CreateMakeFile(True)
> > +
> > +    ## Create autogen code for platform and modules
> > +    #
> > +    #  Since there's no autogen code for platform, this method will do nothing
> > +    #  if CreateModuleCodeFile is set to False.
> > +    #
> > +    #   @param      CreateDepsCodeFile      Flag indicating if creating module's
> > +    #                                       autogen code file or not
> > +    #
> > +    def CreateCodeFile(self, CreateDepsCodeFile=False):
> > +        if not CreateDepsCodeFile:
> > +            return
> > +        for Pa in self.AutoGenObjectList:
> > +            Pa.CreateCodeFile(True)
> > +
> > +    ## Create AsBuilt INF file the platform
> > +    #
> > +    def CreateAsBuiltInf(self):
> > +        return
> > +
> > diff --git a/BaseTools/Source/Python/Common/Misc.py b/BaseTools/Source/Python/Common/Misc.py
> > index 1caa184eb923..26d149c27040 100644
> > --- a/BaseTools/Source/Python/Common/Misc.py
> > +++ b/BaseTools/Source/Python/Common/Misc.py
> > @@ -647,11 +647,10 @@ def GuidValue(CName, PackageList, Inffile = None):
> >              if not Inffile.startswith(P.MetaFile.Dir):
> >                  GuidKeys = [x for x in P.Guids if x not in P._PrivateGuids]
> >          if CName in GuidKeys:
> >              return P.Guids[CName]
> >      return None
> > -    return None
> >
> >  ## A string template class
> >  #
> >  #  This class implements a template for string replacement. A string template
> >  #  looks like following
> > diff --git a/BaseTools/Source/Python/PatchPcdValue/PatchPcdValue.py b/BaseTools/Source/Python/PatchPcdValue/PatchPcdValue.py
> > index 02735e165ca1..d35cd792704c 100644
> > --- a/BaseTools/Source/Python/PatchPcdValue/PatchPcdValue.py
> > +++ b/BaseTools/Source/Python/PatchPcdValue/PatchPcdValue.py
> > @@ -9,11 +9,10 @@
> >  # Import Modules
> >  #
> >  import Common.LongFilePathOs as os
> >  from Common.LongFilePathSupport import OpenLongFilePath as open
> >  import sys
> > -import re
> >
> >  from optparse import OptionParser
> >  from optparse import make_option
> >  from Common.BuildToolError import *
> >  import Common.EdkLogger as EdkLogger
> > diff --git a/BaseTools/Source/Python/Workspace/DscBuildData.py b/BaseTools/Source/Python/Workspace/DscBuildData.py
> > index fa41e57c4f45..383aeaaa15c3 100644
> > --- a/BaseTools/Source/Python/Workspace/DscBuildData.py
> > +++ b/BaseTools/Source/Python/Workspace/DscBuildData.py
> > @@ -1371,15 +1371,15 @@ class DscBuildData(PlatformBuildClassObject):
> >                      if PcdInDec.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
> >                                          self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE],
> >                                          self._PCD_TYPE_STRING_[MODEL_PCD_FEATURE_FLAG],
> >                                          self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC],
> >                                          self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX]]:
> > -                        self.Pcds[Name, Guid] = copy.deepcopy(PcdInDec)
> > -                        self.Pcds[Name, Guid].DefaultValue = NoFiledValues[( Guid, Name)][0]
> > +                        self._Pcds[Name, Guid] = copy.deepcopy(PcdInDec)
> > +                        self._Pcds[Name, Guid].DefaultValue = NoFiledValues[( Guid, Name)][0]
> >                      if PcdInDec.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC],
> >                                          self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX]]:
> > -                        self.Pcds[Name, Guid].SkuInfoList = {TAB_DEFAULT:SkuInfoClass(TAB_DEFAULT, self.SkuIds[TAB_DEFAULT][0], '', '', '', '', '', NoFiledValues[( Guid, Name)][0])}
> > +                        self._Pcds[Name, Guid].SkuInfoList = {TAB_DEFAULT:SkuInfoClass(TAB_DEFAULT, self.SkuIds[TAB_DEFAULT][0], '', '', '', '', '', NoFiledValues[( Guid, Name)][0])}
> >          return AllPcds
> >
> >      def OverrideByFdfOverAll(self,AllPcds):
> >
> >          if GlobalData.gFdfParser is None:
> > @@ -1417,12 +1417,12 @@ class DscBuildData(PlatformBuildClassObject):
> >                  if PcdInDec:
> >                      PcdInDec.PcdValueFromFdf = Value
> >                      if PcdInDec.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
> >                                          self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE],
> >                                          self._PCD_TYPE_STRING_[MODEL_PCD_FEATURE_FLAG]]:
> > -                        self.Pcds[Name, Guid] = copy.deepcopy(PcdInDec)
> > -                        self.Pcds[Name, Guid].DefaultValue = Value
> > +                        self._Pcds[Name, Guid] = copy.deepcopy(PcdInDec)
> > +                        self._Pcds[Name, Guid].DefaultValue = Value
> >          return AllPcds
> >
> >      def ParsePcdNameStruct(self,NamePart1,NamePart2):
> >          TokenSpaceCName = PcdCName = DimensionAttr = Field = ""
> >          if "." in NamePart1:
> > diff --git a/BaseTools/Source/Python/Workspace/InfBuildData.py b/BaseTools/Source/Python/Workspace/InfBuildData.py
> > index da35391d3aff..e63246b03b6e 100644
> > --- a/BaseTools/Source/Python/Workspace/InfBuildData.py
> > +++ b/BaseTools/Source/Python/Workspace/InfBuildData.py
> > @@ -152,10 +152,17 @@ class InfBuildData(ModuleBuildClassObject):
> >          self._GuidsUsedByPcd = OrderedDict()
> >          self._GuidComments = None
> >          self._PcdComments = None
> >          self._BuildOptions = None
> >          self._DependencyFileList = None
> > +        self.LibInstances = []
> > +        self.ReferenceModules = set()
> > +        self.Guids
> > +        self.Pcds
> > +    def SetReferenceModule(self,Module):
> > +        self.ReferenceModules.add(Module)
> > +        return self
> >
> >      ## XXX[key] = value
> >      def __setitem__(self, key, value):
> >          self.__dict__[self._PROPERTY_[key]] = value
> >
> > @@ -703,10 +710,29 @@ class InfBuildData(ModuleBuildClassObject):
> >          RetVal.update(self._GetPcd(MODEL_PCD_DYNAMIC))
> >          RetVal.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
> >          return RetVal
> >
> >      @cached_property
> > +    def ModulePcdList(self):
> > +        RetVal = self.Pcds
> > +        return RetVal
> > +    @cached_property
> > +    def LibraryPcdList(self):
> > +        if bool(self.LibraryClass):
> > +            return []
> > +        RetVal = {}
> > +        Pcds = set()
> > +        for Library in self.LibInstances:
> > +            PcdsInLibrary = OrderedDict()
> > +            for Key in Library.Pcds:
> > +                if Key in self.Pcds or Key in Pcds:
> > +                    continue
> > +                Pcds.add(Key)
> > +                PcdsInLibrary[Key] = copy.copy(Library.Pcds[Key])
> > +            RetVal[Library] = PcdsInLibrary
> > +        return RetVal
> > +    @cached_property
> >      def PcdsName(self):
> >          PcdsName = set()
> >          for Type in (MODEL_PCD_FIXED_AT_BUILD,MODEL_PCD_PATCHABLE_IN_MODULE,MODEL_PCD_FEATURE_FLAG,MODEL_PCD_DYNAMIC,MODEL_PCD_DYNAMIC_EX):
> >              RecordList = self._RawData[Type, self._Arch, self._Platform]
> >              for TokenSpaceGuid, PcdCName, _, _, _, _, _ in RecordList:
> > @@ -1028,5 +1054,8 @@ class InfBuildData(ModuleBuildClassObject):
> >      @property
> >      def IsBinaryModule(self):
> >          if (self.Binaries and not self.Sources) or GlobalData.gIgnoreSource:
> >              return True
> >          return False
> > +def ExtendCopyDictionaryLists(CopyToDict, CopyFromDict):
> > +    for Key in CopyFromDict:
> > +        CopyToDict[Key].extend(CopyFromDict[Key])
> > diff --git a/BaseTools/Source/Python/Workspace/WorkspaceCommon.py b/BaseTools/Source/Python/Workspace/WorkspaceCommon.py
> > index 41ae684d3ee9..76583f46e500 100644
> > --- a/BaseTools/Source/Python/Workspace/WorkspaceCommon.py
> > +++ b/BaseTools/Source/Python/Workspace/WorkspaceCommon.py
> > @@ -86,10 +86,12 @@ def GetDeclaredPcd(Platform, BuildDatabase, Arch, Target, Toolchain, additionalP
> >  #
> >  def GetLiabraryInstances(Module, Platform, BuildDatabase, Arch, Target, Toolchain):
> >      return GetModuleLibInstances(Module, Platform, BuildDatabase, Arch, Target, Toolchain)
> >
> >  def GetModuleLibInstances(Module, Platform, BuildDatabase, Arch, Target, Toolchain, FileName = '', EdkLogger = None):
> > +    if Module.LibInstances:
> > +        return Module.LibInstances
> >      ModuleType = Module.ModuleType
> >
> >      # add forced library instances (specified under LibraryClasses sections)
> >      #
> >      # If a module has a MODULE_TYPE of USER_DEFINED,
> > @@ -244,6 +246,8 @@ def GetModuleLibInstances(Module, Platform, BuildDatabase, Arch, Target, Toolcha
> >      #
> >      # Build the list of constructor and destructor names
> >      # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
> >      #
> >      SortedLibraryList.reverse()
> > +    Module.LibInstances = SortedLibraryList
> > +    SortedLibraryList = [lib.SetReferenceModule(Module) for lib in SortedLibraryList]
> >      return SortedLibraryList
> > diff --git a/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py b/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
> > index 28a975f54e51..ab7b4506c1c1 100644
> > --- a/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
> > +++ b/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
> > @@ -60,10 +60,12 @@ class WorkspaceDatabase(object):
> >              MODEL_FILE_DEC  :   DecBuildData,
> >              MODEL_FILE_DSC  :   DscBuildData,
> >          }
> >
> >          _CACHE_ = {}    # (FilePath, Arch)  : <object>
> > +        def GetCache(self):
> > +            return self._CACHE_
> >
> >          # constructor
> >          def __init__(self, WorkspaceDb):
> >              self.WorkspaceDb = WorkspaceDb
> >
> > @@ -201,10 +203,11 @@ class WorkspaceDatabase(object):
> >          Platform = self.BuildObject[PathClass(Dscfile), TAB_COMMON]
> >          if Platform is None:
> >              EdkLogger.error('build', PARSER_ERROR, "Failed to parser DSC file: %s" % Dscfile)
> >          return Platform
> >
> > +BuildDB = WorkspaceDatabase()
> >  ##
> >  #
> >  # This acts like the main() function for the script, unless it is 'import'ed into another
> >  # script.
> >  #
> > diff --git a/BaseTools/Source/Python/build/BuildReport.py b/BaseTools/Source/Python/build/BuildReport.py
> > index b4189240e127..9c12c01d2a2a 100644
> > --- a/BaseTools/Source/Python/build/BuildReport.py
> > +++ b/BaseTools/Source/Python/build/BuildReport.py
> > @@ -32,11 +32,11 @@ from Common.BuildToolError import CODE_ERROR
> >  from Common.BuildToolError import COMMAND_FAILURE
> >  from Common.BuildToolError import FORMAT_INVALID
> >  from Common.LongFilePathSupport import OpenLongFilePath as open
> >  from Common.MultipleWorkspace import MultipleWorkspace as mws
> >  import Common.GlobalData as GlobalData
> > -from AutoGen.AutoGen import ModuleAutoGen
> > +from AutoGen.ModuleAutoGen import ModuleAutoGen
> >  from Common.Misc import PathClass
> >  from Common.StringUtils import NormPath
> >  from Common.DataType import *
> >  import collections
> >  from Common.Expression import *
> > @@ -2140,11 +2140,11 @@ class PlatformReport(object):
> >                  if GlobalData.gFdfParser is not None:
> >                      if Pa.Arch in GlobalData.gFdfParser.Profile.InfDict:
> >                          INFList = GlobalData.gFdfParser.Profile.InfDict[Pa.Arch]
> >                          for InfName in INFList:
> >                              InfClass = PathClass(NormPath(InfName), Wa.WorkspaceDir, Pa.Arch)
> > -                            Ma = ModuleAutoGen(Wa, InfClass, Pa.BuildTarget, Pa.ToolChain, Pa.Arch, Wa.MetaFile)
> > +                            Ma = ModuleAutoGen(Wa, InfClass, Pa.BuildTarget, Pa.ToolChain, Pa.Arch, Wa.MetaFile,Pa.DataPile)
> >                              if Ma is None:
> >                                  continue
> >                              if Ma not in ModuleAutoGenList:
> >                                  ModuleAutoGenList.append(Ma)
> >                  for MGen in ModuleAutoGenList:
> > diff --git a/BaseTools/Source/Python/build/build.py b/BaseTools/Source/Python/build/build.py
> > index 07693b97359e..3d083f4eaade 100644
> > --- a/BaseTools/Source/Python/build/build.py
> > +++ b/BaseTools/Source/Python/build/build.py
> > @@ -10,46 +10,49 @@
> >
> >  ##
> >  # Import Modules
> >  #
> >  from __future__ import print_function
> > -import Common.LongFilePathOs as os
> > -import re
> > +from __future__ import absolute_import
> > +import os.path as path
> >  import sys
> > +import os
> > +import re
> >  import glob
> >  import time
> >  import platform
> >  import traceback
> > -import encodings.ascii
> >  import multiprocessing
> > -
> > -from struct import *
> > -from threading import *
> > +from threading import Thread,Event,BoundedSemaphore
> >  import threading
> > +from subprocess import Popen,PIPE
> > +from collections import OrderedDict, defaultdict
> >  from optparse import OptionParser
> > -from subprocess import *
> > +from AutoGen.PlatformAutoGen import PlatformAutoGen
> > +from AutoGen.ModuleAutoGen import ModuleAutoGen
> > +from AutoGen.WorkspaceAutoGen import WorkspaceAutoGen
> > +from AutoGen import GenMake
> >  from Common import Misc as Utils
> >
> > -from Common.LongFilePathSupport import OpenLongFilePath as open
> >  from Common.TargetTxtClassObject import TargetTxt
> >  from Common.ToolDefClassObject import ToolDef
> > +from Common.Misc import PathClass,SaveFileOnChange,RemoveDirectory
> > +from Common.StringUtils import NormPath
> > +from Common.MultipleWorkspace import MultipleWorkspace as mws
> > +from Common.BuildToolError import *
> >  from Common.DataType import *
> > +import Common.EdkLogger as EdkLogger
> >  from Common.BuildVersion import gBUILD_VERSION
> > -from AutoGen.AutoGen import *
> > -from Common.BuildToolError import *
> > -from Workspace.WorkspaceDatabase import WorkspaceDatabase
> > -from Common.MultipleWorkspace import MultipleWorkspace as mws
> > +from Workspace.WorkspaceDatabase import BuildDB
> >
> >  from BuildReport import BuildReport
> > -from GenPatchPcdTable.GenPatchPcdTable import *
> > -from PatchPcdValue.PatchPcdValue import *
> > +from GenPatchPcdTable.GenPatchPcdTable import PeImageClass,parsePcdInfoFromMapFile
> > +from PatchPcdValue.PatchPcdValue import PatchBinaryFile
> >
> > -import Common.EdkLogger
> >  import Common.GlobalData as GlobalData
> >  from GenFds.GenFds import GenFds, GenFdsApi
> >
> > -from collections import OrderedDict, defaultdict
> >
> >  # Version and Copyright
> >  VersionNumber = "0.60" + ' ' + gBUILD_VERSION
> >  __version__ = "%prog Version " + VersionNumber
> >  __copyright__ = "Copyright (c) 2007 - 2018, Intel Corporation  All rights reserved."
> > @@ -773,11 +776,11 @@ class Build():
> >                  ConfDirectoryPath = mws.join(self.WorkspaceDir, 'Conf')
> >          GlobalData.gConfDirectory = ConfDirectoryPath
> >          GlobalData.gDatabasePath = os.path.normpath(os.path.join(ConfDirectoryPath, GlobalData.gDatabasePath))
> >          if not os.path.exists(os.path.join(GlobalData.gConfDirectory, '.cache')):
> >              os.makedirs(os.path.join(GlobalData.gConfDirectory, '.cache'))
> > -        self.Db = WorkspaceDatabase()
> > +        self.Db = BuildDB
> >          self.BuildDatabase = self.Db.BuildObject
> >          self.Platform = None
> >          self.ToolChainFamily = None
> >          self.LoadFixAddress = 0
> >          self.UniFlag        = BuildOptions.Flag
> > @@ -1698,17 +1701,21 @@ class Build():
> >                  CmdListDict = {}
> >                  if GlobalData.gEnableGenfdsMultiThread and self.Fdf:
> >                      CmdListDict = self._GenFfsCmd(Wa.ArchList)
> >
> >                  for Arch in Wa.ArchList:
> > +                    PcdMaList    = []
> >                      GlobalData.gGlobalDefines['ARCH'] = Arch
> >                      Pa = PlatformAutoGen(Wa, self.PlatformFile, BuildTarget, ToolChain, Arch)
> >                      for Module in Pa.Platform.Modules:
> >                          # Get ModuleAutoGen object to generate C code file and makefile
> > -                        Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile)
> > +                        Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile,Pa.DataPipe)
> >                          if Ma is None:
> >                              continue
> > +                        if Ma.PcdIsDriver:
> > +                            Ma.PlatformInfo = Pa
> > +                            PcdMaList.append(Ma)
> >                          self.BuildModules.append(Ma)
> >                      self._BuildPa(self.Target, Pa, FfsCommand=CmdListDict)
> >
> >                  # Create MAP file when Load Fix Address is enabled.
> >                  if self.Target in ["", "all", "fds"]:
> > @@ -1800,11 +1807,11 @@ class Build():
> >                      AutoGenStart = time.time()
> >                      GlobalData.gGlobalDefines['ARCH'] = Arch
> >                      Pa = PlatformAutoGen(Wa, self.PlatformFile, BuildTarget, ToolChain, Arch)
> >                      for Module in Pa.Platform.Modules:
> >                          if self.ModuleFile.Dir == Module.Dir and self.ModuleFile.Name == Module.Name:
> > -                            Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile)
> > +                            Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile,Pa.DataPipe)
> >                              if Ma is None:
> >                                  continue
> >                              MaList.append(Ma)
> >                              if Ma.CanSkipbyHash():
> >                                  self.HashSkipModules.append(Ma)
> > @@ -1980,10 +1987,11 @@ class Build():
> >                  # multi-thread exit flag
> >                  ExitFlag = threading.Event()
> >                  ExitFlag.clear()
> >                  self.AutoGenTime += int(round((time.time() - WorkspaceAutoGenTime)))
> >                  for Arch in Wa.ArchList:
> > +                    PcdMaList    = []
> >                      AutoGenStart = time.time()
> >                      GlobalData.gGlobalDefines['ARCH'] = Arch
> >                      Pa = PlatformAutoGen(Wa, self.PlatformFile, BuildTarget, ToolChain, Arch)
> >                      if Pa is None:
> >                          continue
> > @@ -1997,14 +2005,17 @@ class Build():
> >                              if Inf in Pa.Platform.Modules:
> >                                  continue
> >                              ModuleList.append(Inf)
> >                      for Module in ModuleList:
> >                          # Get ModuleAutoGen object to generate C code file and makefile
> > -                        Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile)
> > +                        Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile,Pa.DataPipe)
> >
> >                          if Ma is None:
> >                              continue
> > +                        if Ma.PcdIsDriver:
> > +                            Ma.PlatformInfo = Pa
> > +                            PcdMaList.append(Ma)
> >                          if Ma.CanSkipbyHash():
> >                              self.HashSkipModules.append(Ma)
> >                              if GlobalData.gBinCacheSource:
> >                                  EdkLogger.quiet("cache hit: %s[%s]" % (Ma.MetaFile.Path, Ma.Arch))
> >                              continue
> > -- 
> > 2.20.1.windows.1
> > 
> > 
> > 
> > 
> > 
> 
> 
> 
> 

-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#46208): https://edk2.groups.io/g/devel/message/46208
Mute This Topic: https://groups.io/mt/32779331/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list