Home | History | Annotate | Download | only in AutoGen
      1 ## @file

      2 # The engine for building files

      3 #

      4 # Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>

      5 # This program and the accompanying materials

      6 # are licensed and made available under the terms and conditions of the BSD License

      7 # which accompanies this distribution.  The full text of the license may be found at

      8 # http://opensource.org/licenses/bsd-license.php

      9 #

     10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

     11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

     12 #

     13 
     14 ##

     15 # Import Modules

     16 #

     17 import Common.LongFilePathOs as os
     18 import re
     19 import copy
     20 import string
     21 from Common.LongFilePathSupport import OpenLongFilePath as open
     22 
     23 from Common.GlobalData import *
     24 from Common.BuildToolError import *
     25 from Common.Misc import tdict, PathClass
     26 from Common.String import NormPath
     27 from Common.DataType import *
     28 
     29 import Common.EdkLogger as EdkLogger
     30 
     31 ## Convert file type to file list macro name

     32 #

     33 #   @param      FileType    The name of file type

     34 #

     35 #   @retval     string      The name of macro

     36 #

     37 def FileListMacro(FileType):
     38     return "%sS" % FileType.replace("-", "_").upper()
     39 
     40 ## Convert file type to list file macro name

     41 #

     42 #   @param      FileType    The name of file type

     43 #

     44 #   @retval     string      The name of macro

     45 #

     46 def ListFileMacro(FileType):
     47     return "%s_LIST" % FileListMacro(FileType)
     48 
     49 class TargetDescBlock(object):
     50     _Cache_ = {}    # {TargetFile : TargetDescBlock object}

     51 
     52     # Factory method

     53     def __new__(Class, Inputs, Outputs, Commands, Dependencies):
     54         if Outputs[0] in Class._Cache_:
     55             Tdb = Class._Cache_[Outputs[0]]
     56             for File in Inputs:
     57                 Tdb.AddInput(File)
     58         else:
     59             Tdb = super(TargetDescBlock, Class).__new__(Class)
     60             Tdb._Init(Inputs, Outputs, Commands, Dependencies)
     61             #Class._Cache_[Outputs[0]] = Tdb

     62         return Tdb
     63 
     64     def _Init(self, Inputs, Outputs, Commands, Dependencies):
     65         self.Inputs = Inputs
     66         self.Outputs = Outputs
     67         self.Commands = Commands
     68         self.Dependencies = Dependencies
     69         if self.Outputs:
     70             self.Target = self.Outputs[0]
     71         else:
     72             self.Target = None
     73 
     74     def __str__(self):
     75         return self.Target.Path
     76 
     77     def __hash__(self):
     78         return hash(self.Target.Path)
     79 
     80     def __eq__(self, Other):
     81         if type(Other) == type(self):
     82             return Other.Target.Path == self.Target.Path
     83         else:
     84             return str(Other) == self.Target.Path
     85 
     86     def AddInput(self, Input):
     87         if Input not in self.Inputs:
     88             self.Inputs.append(Input)
     89 
     90     def IsMultipleInput(self):
     91         return len(self.Inputs) > 1
     92 
     93     @staticmethod
     94     def Renew():
     95         TargetDescBlock._Cache_ = {}
     96 
     97 ## Class for one build rule

     98 #

     99 # This represents a build rule which can give out corresponding command list for

    100 # building the given source file(s). The result can be used for generating the

    101 # target for makefile.

    102 #

    103 class FileBuildRule:
    104     INC_LIST_MACRO = "INC_LIST"
    105     INC_MACRO = "INC"
    106 
    107     ## constructor

    108     #

    109     #   @param  Input       The dictionary represeting input file(s) for a rule

    110     #   @param  Output      The list represeting output file(s) for a rule

    111     #   @param  Command     The list containing commands to generate the output from input

    112     #

    113     def __init__(self, Type, Input, Output, Command, ExtraDependency=None):
    114         # The Input should not be empty

    115         if not Input:
    116             Input = []
    117         if not Output:
    118             Output = []
    119         if not Command:
    120             Command = []
    121 
    122         self.FileListMacro = FileListMacro(Type)
    123         self.ListFileMacro = ListFileMacro(Type)
    124         self.IncListFileMacro = self.INC_LIST_MACRO
    125 
    126         self.SourceFileType = Type
    127         # source files listed not in "*" or "?" pattern format

    128         if not ExtraDependency:
    129             self.ExtraSourceFileList = []
    130         else:
    131             self.ExtraSourceFileList = ExtraDependency
    132 
    133         #

    134         # Search macros used in command lines for <FILE_TYPE>_LIST and INC_LIST.

    135         # If found, generate a file to keep the input files used to get over the

    136         # limitation of command line length

    137         #

    138         self.MacroList = []
    139         self.CommandList = []
    140         for CmdLine in Command:
    141             self.MacroList.extend(gMacroRefPattern.findall(CmdLine))
    142             # replace path separator with native one

    143             self.CommandList.append(CmdLine)
    144 
    145         # Indicate what should be generated

    146         if self.FileListMacro in self.MacroList:
    147             self.GenFileListMacro = True
    148         else:
    149             self.GenFileListMacro = False
    150 
    151         if self.ListFileMacro in self.MacroList:
    152             self.GenListFile = True
    153             self.GenFileListMacro = True
    154         else:
    155             self.GenListFile = False
    156 
    157         if self.INC_LIST_MACRO in self.MacroList:
    158             self.GenIncListFile = True
    159         else:
    160             self.GenIncListFile = False
    161 
    162         # Check input files

    163         self.IsMultipleInput = False
    164         self.SourceFileExtList = []
    165         for File in Input:
    166             Base, Ext = os.path.splitext(File)
    167             if Base.find("*") >= 0:
    168                 # There's "*" in the file name

    169                 self.IsMultipleInput = True
    170                 self.GenFileListMacro = True
    171             elif Base.find("?") < 0:
    172                 # There's no "*" and "?" in file name

    173                 self.ExtraSourceFileList.append(File)
    174                 continue
    175             if Ext not in self.SourceFileExtList:
    176                 self.SourceFileExtList.append(Ext)
    177 
    178         # Check output files

    179         self.DestFileList = []
    180         for File in Output:
    181             self.DestFileList.append(File)
    182 
    183         # All build targets generated by this rule for a module

    184         self.BuildTargets = {}
    185 
    186     ## str() function support

    187     #

    188     #   @retval     string

    189     #

    190     def __str__(self):
    191         SourceString = ""
    192         SourceString += " %s %s %s" % (self.SourceFileType, " ".join(self.SourceFileExtList), self.ExtraSourceFileList)
    193         DestString = ", ".join(self.DestFileList)
    194         CommandString = "\n\t".join(self.CommandList)
    195         return "%s : %s\n\t%s" % (DestString, SourceString, CommandString)
    196 
    197     ## Check if given file extension is supported by this rule

    198     #

    199     #   @param  FileExt     The extension of a file

    200     #

    201     #   @retval True        If the extension is supported

    202     #   @retval False       If the extension is not supported

    203     #

    204     def IsSupported(self, FileExt):
    205         return FileExt in self.SourceFileExtList
    206 
    207     def Instantiate(self, Macros={}):
    208         NewRuleObject = copy.copy(self)
    209         NewRuleObject.BuildTargets = {}
    210         NewRuleObject.DestFileList = []
    211         for File in self.DestFileList:
    212             NewRuleObject.DestFileList.append(PathClass(NormPath(File, Macros)))
    213         return NewRuleObject
    214 
    215     ## Apply the rule to given source file(s)

    216     #

    217     #   @param  SourceFile      One file or a list of files to be built

    218     #   @param  RelativeToDir   The relative path of the source file

    219     #   @param  PathSeparator   Path separator

    220     #

    221     #   @retval     tuple       (Source file in full path, List of individual sourcefiles, Destionation file, List of build commands)

    222     #

    223     def Apply(self, SourceFile, BuildRuleOrder=None):
    224         if not self.CommandList or not self.DestFileList:
    225             return None
    226 
    227         # source file

    228         if self.IsMultipleInput:
    229             SrcFileName = ""
    230             SrcFileBase = ""
    231             SrcFileExt = ""
    232             SrcFileDir = ""
    233             SrcPath = ""
    234             # SourceFile must be a list

    235             SrcFile = "$(%s)" % self.FileListMacro
    236         else:
    237             SrcFileName, SrcFileBase, SrcFileExt = SourceFile.Name, SourceFile.BaseName, SourceFile.Ext
    238             if SourceFile.Root:
    239                 SrcFileDir = SourceFile.SubDir
    240                 if SrcFileDir == "":
    241                     SrcFileDir = "."
    242             else:
    243                 SrcFileDir = "."
    244             SrcFile = SourceFile.Path
    245             SrcPath = SourceFile.Dir
    246 
    247         # destination file (the first one)

    248         if self.DestFileList:
    249             DestFile = self.DestFileList[0].Path
    250             DestPath = self.DestFileList[0].Dir
    251             DestFileName = self.DestFileList[0].Name
    252             DestFileBase, DestFileExt = self.DestFileList[0].BaseName, self.DestFileList[0].Ext
    253         else:
    254             DestFile = ""
    255             DestPath = ""
    256             DestFileName = ""
    257             DestFileBase = ""
    258             DestFileExt = ""
    259 
    260         BuildRulePlaceholderDict = {
    261             # source file

    262             "src"       :   SrcFile,
    263             "s_path"    :   SrcPath,
    264             "s_dir"     :   SrcFileDir,
    265             "s_name"    :   SrcFileName,
    266             "s_base"    :   SrcFileBase,
    267             "s_ext"     :   SrcFileExt,
    268             # destination file

    269             "dst"       :   DestFile,
    270             "d_path"    :   DestPath,
    271             "d_name"    :   DestFileName,
    272             "d_base"    :   DestFileBase,
    273             "d_ext"     :   DestFileExt,
    274         }
    275 
    276         DstFile = []
    277         for File in self.DestFileList:
    278             File = string.Template(str(File)).safe_substitute(BuildRulePlaceholderDict)
    279             File = string.Template(str(File)).safe_substitute(BuildRulePlaceholderDict)
    280             DstFile.append(PathClass(File, IsBinary=True))
    281 
    282         if DstFile[0] in self.BuildTargets:
    283             TargetDesc = self.BuildTargets[DstFile[0]]
    284             if BuildRuleOrder and SourceFile.Ext in BuildRuleOrder:
    285                 Index = BuildRuleOrder.index(SourceFile.Ext)
    286                 for Input in TargetDesc.Inputs:
    287                     if Input.Ext not in BuildRuleOrder or BuildRuleOrder.index(Input.Ext) > Index:
    288                         #

    289                         # Command line should be regenerated since some macros are different

    290                         #

    291                         CommandList = self._BuildCommand(BuildRulePlaceholderDict)
    292                         TargetDesc._Init([SourceFile], DstFile, CommandList, self.ExtraSourceFileList)
    293                         break
    294             else:
    295                 TargetDesc.AddInput(SourceFile)
    296         else:
    297             CommandList = self._BuildCommand(BuildRulePlaceholderDict)
    298             TargetDesc = TargetDescBlock([SourceFile], DstFile, CommandList, self.ExtraSourceFileList)
    299             TargetDesc.ListFileMacro = self.ListFileMacro
    300             TargetDesc.FileListMacro = self.FileListMacro
    301             TargetDesc.IncListFileMacro = self.IncListFileMacro
    302             TargetDesc.GenFileListMacro = self.GenFileListMacro
    303             TargetDesc.GenListFile = self.GenListFile
    304             TargetDesc.GenIncListFile = self.GenIncListFile
    305             self.BuildTargets[DstFile[0]] = TargetDesc
    306         return TargetDesc
    307 
    308     def _BuildCommand(self, Macros):
    309         CommandList = []
    310         for CommandString in self.CommandList:
    311             CommandString = string.Template(CommandString).safe_substitute(Macros)
    312             CommandString = string.Template(CommandString).safe_substitute(Macros)
    313             CommandList.append(CommandString)
    314         return CommandList
    315 
    316 ## Class for build rules

    317 #

    318 # BuildRule class parses rules defined in a file or passed by caller, and converts

    319 # the rule into FileBuildRule object.

    320 #

    321 class BuildRule:
    322     _SectionHeader = "SECTIONHEADER"
    323     _Section = "SECTION"
    324     _SubSectionHeader = "SUBSECTIONHEADER"
    325     _SubSection = "SUBSECTION"
    326     _InputFile = "INPUTFILE"
    327     _OutputFile = "OUTPUTFILE"
    328     _ExtraDependency = "EXTRADEPENDENCY"
    329     _Command = "COMMAND"
    330     _UnknownSection = "UNKNOWNSECTION"
    331 
    332     _SubSectionList = [_InputFile, _OutputFile, _Command]
    333 
    334     _PATH_SEP = "(+)"
    335     _FileTypePattern = re.compile("^[_a-zA-Z][_\-0-9a-zA-Z]*$")
    336     _BinaryFileRule = FileBuildRule(TAB_DEFAULT_BINARY_FILE, [], [os.path.join("$(OUTPUT_DIR)", "${s_name}")],
    337                                     ["$(CP) ${src} ${dst}"], [])
    338 
    339     ## Constructor

    340     #

    341     #   @param  File                The file containing build rules in a well defined format

    342     #   @param  Content             The string list of build rules in a well defined format

    343     #   @param  LineIndex           The line number from which the parsing will begin

    344     #   @param  SupportedFamily     The list of supported tool chain families

    345     #

    346     def __init__(self, File=None, Content=None, LineIndex=0, SupportedFamily=["MSFT", "INTEL", "GCC", "RVCT"]):
    347         self.RuleFile = File
    348         # Read build rules from file if it's not none

    349         if File != None:
    350             try:
    351                 self.RuleContent = open(File, 'r').readlines()
    352             except:
    353                 EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=File)
    354         elif Content != None:
    355             self.RuleContent = Content
    356         else:
    357             EdkLogger.error("build", PARAMETER_MISSING, ExtraData="No rule file or string given")
    358 
    359         self.SupportedToolChainFamilyList = SupportedFamily
    360         self.RuleDatabase = tdict(True, 4)  # {FileExt, ModuleType, Arch, Family : FileBuildRule object}

    361         self.Ext2FileType = {}  # {ext : file-type}

    362         self.FileTypeList = set()
    363 
    364         self._LineIndex = LineIndex
    365         self._State = ""
    366         self._RuleInfo = tdict(True, 2)     # {toolchain family : {"InputFile": {}, "OutputFile" : [], "Command" : []}}

    367         self._FileType = ''
    368         self._BuildTypeList = []
    369         self._ArchList = []
    370         self._FamilyList = []
    371         self._TotalToolChainFamilySet = set()
    372         self._RuleObjectList = [] # FileBuildRule object list

    373         self._FileVersion = ""
    374 
    375         self.Parse()
    376 
    377         # some intrinsic rules

    378         self.RuleDatabase[TAB_DEFAULT_BINARY_FILE, "COMMON", "COMMON", "COMMON"] = self._BinaryFileRule
    379         self.FileTypeList.add(TAB_DEFAULT_BINARY_FILE)
    380 
    381     ## Parse the build rule strings

    382     def Parse(self):
    383         self._State = self._Section
    384         for Index in range(self._LineIndex, len(self.RuleContent)):
    385             # Clean up the line and replace path separator with native one

    386             Line = self.RuleContent[Index].strip().replace(self._PATH_SEP, os.path.sep)
    387             self.RuleContent[Index] = Line
    388             
    389             # find the build_rule_version

    390             if Line and Line[0] == "#" and Line.find(TAB_BUILD_RULE_VERSION) <> -1:
    391                 if Line.find("=") <> -1 and Line.find("=") < (len(Line) - 1) and (Line[(Line.find("=") + 1):]).split():
    392                     self._FileVersion = (Line[(Line.find("=") + 1):]).split()[0]
    393             # skip empty or comment line

    394             if Line == "" or Line[0] == "#":
    395                 continue
    396 
    397             # find out section header, enclosed by []

    398             if Line[0] == '[' and Line[-1] == ']':
    399                 # merge last section information into rule database

    400                 self.EndOfSection()
    401                 self._State = self._SectionHeader
    402             # find out sub-section header, enclosed by <>

    403             elif Line[0] == '<' and Line[-1] == '>':
    404                 if self._State != self._UnknownSection:
    405                     self._State = self._SubSectionHeader
    406 
    407             # call section handler to parse each (sub)section

    408             self._StateHandler[self._State](self, Index)
    409         # merge last section information into rule database

    410         self.EndOfSection()
    411 
    412     ## Parse definitions under a section

    413     #

    414     #   @param  LineIndex   The line index of build rule text

    415     #

    416     def ParseSection(self, LineIndex):
    417         pass
    418 
    419     ## Parse definitions under a subsection

    420     #

    421     #   @param  LineIndex   The line index of build rule text

    422     #

    423     def ParseSubSection(self, LineIndex):
    424         # currenly nothing here

    425         pass
    426 
    427     ## Placeholder for not supported sections

    428     #

    429     #   @param  LineIndex   The line index of build rule text

    430     #

    431     def SkipSection(self, LineIndex):
    432         pass
    433 
    434     ## Merge section information just got into rule database

    435     def EndOfSection(self):
    436         Database = self.RuleDatabase
    437         # if there's specific toochain family, 'COMMON' doesn't make sense any more

    438         if len(self._TotalToolChainFamilySet) > 1 and 'COMMON' in self._TotalToolChainFamilySet:
    439             self._TotalToolChainFamilySet.remove('COMMON')
    440         for Family in self._TotalToolChainFamilySet:
    441             Input = self._RuleInfo[Family, self._InputFile]
    442             Output = self._RuleInfo[Family, self._OutputFile]
    443             Command = self._RuleInfo[Family, self._Command]
    444             ExtraDependency = self._RuleInfo[Family, self._ExtraDependency]
    445 
    446             BuildRule = FileBuildRule(self._FileType, Input, Output, Command, ExtraDependency)
    447             for BuildType in self._BuildTypeList:
    448                 for Arch in self._ArchList:
    449                     Database[self._FileType, BuildType, Arch, Family] = BuildRule
    450                     for FileExt in BuildRule.SourceFileExtList:
    451                         self.Ext2FileType[FileExt] = self._FileType
    452 
    453     ## Parse section header

    454     #

    455     #   @param  LineIndex   The line index of build rule text

    456     #

    457     def ParseSectionHeader(self, LineIndex):
    458         self._RuleInfo = tdict(True, 2)
    459         self._BuildTypeList = []
    460         self._ArchList = []
    461         self._FamilyList = []
    462         self._TotalToolChainFamilySet = set()
    463         FileType = ''
    464         RuleNameList = self.RuleContent[LineIndex][1:-1].split(',')
    465         for RuleName in RuleNameList:
    466             Arch = 'COMMON'
    467             BuildType = 'COMMON'
    468             TokenList = [Token.strip().upper() for Token in RuleName.split('.')]
    469             # old format: Build.File-Type

    470             if TokenList[0] == "BUILD":
    471                 if len(TokenList) == 1:
    472                     EdkLogger.error("build", FORMAT_INVALID, "Invalid rule section",
    473                                     File=self.RuleFile, Line=LineIndex + 1,
    474                                     ExtraData=self.RuleContent[LineIndex])
    475 
    476                 FileType = TokenList[1]
    477                 if FileType == '':
    478                     EdkLogger.error("build", FORMAT_INVALID, "No file type given",
    479                                     File=self.RuleFile, Line=LineIndex + 1,
    480                                     ExtraData=self.RuleContent[LineIndex])
    481                 if self._FileTypePattern.match(FileType) == None:
    482                     EdkLogger.error("build", FORMAT_INVALID, File=self.RuleFile, Line=LineIndex + 1,
    483                                     ExtraData="Only character, number (non-first character), '_' and '-' are allowed in file type")
    484             # new format: File-Type.Build-Type.Arch

    485             else:
    486                 if FileType == '':
    487                     FileType = TokenList[0]
    488                 elif FileType != TokenList[0]:
    489                     EdkLogger.error("build", FORMAT_INVALID,
    490                                     "Different file types are not allowed in the same rule section",
    491                                     File=self.RuleFile, Line=LineIndex + 1,
    492                                     ExtraData=self.RuleContent[LineIndex])
    493                 if len(TokenList) > 1:
    494                     BuildType = TokenList[1]
    495                 if len(TokenList) > 2:
    496                     Arch = TokenList[2]
    497             if BuildType not in self._BuildTypeList:
    498                 self._BuildTypeList.append(BuildType)
    499             if Arch not in self._ArchList:
    500                 self._ArchList.append(Arch)
    501 
    502         if 'COMMON' in self._BuildTypeList and len(self._BuildTypeList) > 1:
    503             EdkLogger.error("build", FORMAT_INVALID,
    504                             "Specific build types must not be mixed with common one",
    505                             File=self.RuleFile, Line=LineIndex + 1,
    506                             ExtraData=self.RuleContent[LineIndex])
    507         if 'COMMON' in self._ArchList and len(self._ArchList) > 1:
    508             EdkLogger.error("build", FORMAT_INVALID,
    509                             "Specific ARCH must not be mixed with common one",
    510                             File=self.RuleFile, Line=LineIndex + 1,
    511                             ExtraData=self.RuleContent[LineIndex])
    512 
    513         self._FileType = FileType
    514         self._State = self._Section
    515         self.FileTypeList.add(FileType)
    516 
    517     ## Parse sub-section header

    518     #

    519     #   @param  LineIndex   The line index of build rule text

    520     #

    521     def ParseSubSectionHeader(self, LineIndex):
    522         SectionType = ""
    523         List = self.RuleContent[LineIndex][1:-1].split(',')
    524         FamilyList = []
    525         for Section in List:
    526             TokenList = Section.split('.')
    527             Type = TokenList[0].strip().upper()
    528 
    529             if SectionType == "":
    530                 SectionType = Type
    531             elif SectionType != Type:
    532                 EdkLogger.error("build", FORMAT_INVALID,
    533                                 "Two different section types are not allowed in the same sub-section",
    534                                 File=self.RuleFile, Line=LineIndex + 1,
    535                                 ExtraData=self.RuleContent[LineIndex])
    536 
    537             if len(TokenList) > 1:
    538                 Family = TokenList[1].strip().upper()
    539             else:
    540                 Family = "COMMON"
    541 
    542             if Family not in FamilyList:
    543                 FamilyList.append(Family)
    544 
    545         self._FamilyList = FamilyList
    546         self._TotalToolChainFamilySet.update(FamilyList)
    547         self._State = SectionType.upper()
    548         if 'COMMON' in FamilyList and len(FamilyList) > 1:
    549             EdkLogger.error("build", FORMAT_INVALID,
    550                             "Specific tool chain family should not be mixed with general one",
    551                             File=self.RuleFile, Line=LineIndex + 1,
    552                             ExtraData=self.RuleContent[LineIndex])
    553         if self._State not in self._StateHandler:
    554             EdkLogger.error("build", FORMAT_INVALID, File=self.RuleFile, Line=LineIndex + 1,
    555                             ExtraData="Unknown subsection: %s" % self.RuleContent[LineIndex])
    556     ## Parse <InputFile> sub-section

    557     #

    558     #   @param  LineIndex   The line index of build rule text

    559     #

    560     def ParseInputFile(self, LineIndex):
    561         FileList = [File.strip() for File in self.RuleContent[LineIndex].split(",")]
    562         for ToolChainFamily in self._FamilyList:
    563             InputFiles = self._RuleInfo[ToolChainFamily, self._State]
    564             if InputFiles == None:
    565                 InputFiles = []
    566                 self._RuleInfo[ToolChainFamily, self._State] = InputFiles
    567             InputFiles.extend(FileList)
    568 
    569     ## Parse <ExtraDependency> sub-section

    570     #

    571     #   @param  LineIndex   The line index of build rule text

    572     #

    573     def ParseCommon(self, LineIndex):
    574         for ToolChainFamily in self._FamilyList:
    575             Items = self._RuleInfo[ToolChainFamily, self._State]
    576             if Items == None:
    577                 Items = []
    578                 self._RuleInfo[ToolChainFamily, self._State] = Items
    579             Items.append(self.RuleContent[LineIndex])
    580 
    581     ## Get a build rule via [] operator

    582     #

    583     #   @param  FileExt             The extension of a file

    584     #   @param  ToolChainFamily     The tool chain family name

    585     #   @param  BuildVersion        The build version number. "*" means any rule

    586     #                               is applicalbe.

    587     #

    588     #   @retval FileType        The file type string

    589     #   @retval FileBuildRule   The object of FileBuildRule

    590     #

    591     # Key = (FileExt, ModuleType, Arch, ToolChainFamily)

    592     def __getitem__(self, Key):
    593         if not Key:
    594             return None
    595 
    596         if Key[0] in self.Ext2FileType:
    597             Type = self.Ext2FileType[Key[0]]
    598         elif Key[0].upper() in self.FileTypeList:
    599             Type = Key[0].upper()
    600         else:
    601             return None
    602 
    603         if len(Key) > 1:
    604             Key = (Type,) + Key[1:]
    605         else:
    606             Key = (Type,)
    607         return self.RuleDatabase[Key]
    608 
    609     _StateHandler = {
    610         _SectionHeader     : ParseSectionHeader,
    611         _Section           : ParseSection,
    612         _SubSectionHeader  : ParseSubSectionHeader,
    613         _SubSection        : ParseSubSection,
    614         _InputFile         : ParseInputFile,
    615         _OutputFile        : ParseCommon,
    616         _ExtraDependency   : ParseCommon,
    617         _Command           : ParseCommon,
    618         _UnknownSection    : SkipSection,
    619     }
    620 
    621 # This acts like the main() function for the script, unless it is 'import'ed into another

    622 # script.

    623 if __name__ == '__main__':
    624     import sys
    625     EdkLogger.Initialize()
    626     if len(sys.argv) > 1:
    627         Br = BuildRule(sys.argv[1])
    628         print str(Br[".c", "DXE_DRIVER", "IA32", "MSFT"][1])
    629         print
    630         print str(Br[".c", "DXE_DRIVER", "IA32", "INTEL"][1])
    631         print
    632         print str(Br[".c", "DXE_DRIVER", "IA32", "GCC"][1])
    633         print
    634         print str(Br[".ac", "ACPI_TABLE", "IA32", "MSFT"][1])
    635         print
    636         print str(Br[".h", "ACPI_TABLE", "IA32", "INTEL"][1])
    637         print
    638         print str(Br[".ac", "ACPI_TABLE", "IA32", "MSFT"][1])
    639         print
    640         print str(Br[".s", "SEC", "IPF", "COMMON"][1])
    641         print
    642         print str(Br[".s", "SEC"][1])
    643 
    644