1## @file
2# The engine for building files
3#
4# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5# SPDX-License-Identifier: BSD-2-Clause-Patent
6#
7
8##
9# Import Modules
10#
11from __future__ import print_function
12import Common.LongFilePathOs as os
13import re
14import copy
15import string
16from Common.LongFilePathSupport import OpenLongFilePath as open
17
18from Common.GlobalData import *
19from Common.BuildToolError import *
20from Common.Misc import tdict, PathClass
21from Common.StringUtils import NormPath
22from Common.DataType import *
23from Common.TargetTxtClassObject import TargetTxtDict
24gDefaultBuildRuleFile = 'build_rule.txt'
25AutoGenReqBuildRuleVerNum = '0.1'
26
27import Common.EdkLogger as EdkLogger
28
29## Convert file type to file list macro name
30#
31#   @param      FileType    The name of file type
32#
33#   @retval     string      The name of macro
34#
35def FileListMacro(FileType):
36    return "%sS" % FileType.replace("-", "_").upper()
37
38## Convert file type to list file macro name
39#
40#   @param      FileType    The name of file type
41#
42#   @retval     string      The name of macro
43#
44def ListFileMacro(FileType):
45    return "%s_LIST" % FileListMacro(FileType)
46
47class TargetDescBlock(object):
48    def __init__(self, Inputs, Outputs, Commands, Dependencies):
49        self.InitWorker(Inputs, Outputs, Commands, Dependencies)
50
51    def InitWorker(self, Inputs, Outputs, Commands, Dependencies):
52        self.Inputs = Inputs
53        self.Outputs = Outputs
54        self.Commands = Commands
55        self.Dependencies = Dependencies
56        if self.Outputs:
57            self.Target = self.Outputs[0]
58        else:
59            self.Target = None
60
61    def __str__(self):
62        return self.Target.Path
63
64    def __hash__(self):
65        return hash(self.Target.Path)
66
67    def __eq__(self, Other):
68        if isinstance(Other, type(self)):
69            return Other.Target.Path == self.Target.Path
70        else:
71            return str(Other) == self.Target.Path
72
73    def AddInput(self, Input):
74        if Input not in self.Inputs:
75            self.Inputs.append(Input)
76
77    def IsMultipleInput(self):
78        return len(self.Inputs) > 1
79
80## Class for one build rule
81#
82# This represents a build rule which can give out corresponding command list for
83# building the given source file(s). The result can be used for generating the
84# target for makefile.
85#
86class FileBuildRule:
87    INC_LIST_MACRO = "INC_LIST"
88    INC_MACRO = "INC"
89
90    ## constructor
91    #
92    #   @param  Input       The dictionary representing input file(s) for a rule
93    #   @param  Output      The list representing output file(s) for a rule
94    #   @param  Command     The list containing commands to generate the output from input
95    #
96    def __init__(self, Type, Input, Output, Command, ExtraDependency=None):
97        # The Input should not be empty
98        if not Input:
99            Input = []
100        if not Output:
101            Output = []
102        if not Command:
103            Command = []
104
105        self.FileListMacro = FileListMacro(Type)
106        self.ListFileMacro = ListFileMacro(Type)
107        self.IncListFileMacro = self.INC_LIST_MACRO
108
109        self.SourceFileType = Type
110        # source files listed not in TAB_STAR or "?" pattern format
111        if not ExtraDependency:
112            self.ExtraSourceFileList = []
113        else:
114            self.ExtraSourceFileList = ExtraDependency
115
116        #
117        # Search macros used in command lines for <FILE_TYPE>_LIST and INC_LIST.
118        # If found, generate a file to keep the input files used to get over the
119        # limitation of command line length
120        #
121        self.MacroList = []
122        self.CommandList = []
123        for CmdLine in Command:
124            self.MacroList.extend(gMacroRefPattern.findall(CmdLine))
125            # replace path separator with native one
126            self.CommandList.append(CmdLine)
127
128        # Indicate what should be generated
129        if self.FileListMacro in self.MacroList:
130            self.GenFileListMacro = True
131        else:
132            self.GenFileListMacro = False
133
134        if self.ListFileMacro in self.MacroList:
135            self.GenListFile = True
136            self.GenFileListMacro = True
137        else:
138            self.GenListFile = False
139
140        if self.INC_LIST_MACRO in self.MacroList:
141            self.GenIncListFile = True
142        else:
143            self.GenIncListFile = False
144
145        # Check input files
146        self.IsMultipleInput = False
147        self.SourceFileExtList = set()
148        for File in Input:
149            Base, Ext = os.path.splitext(File)
150            if Base.find(TAB_STAR) >= 0:
151                # There's TAB_STAR in the file name
152                self.IsMultipleInput = True
153                self.GenFileListMacro = True
154            elif Base.find("?") < 0:
155                # There's no TAB_STAR and "?" in file name
156                self.ExtraSourceFileList.append(File)
157                continue
158            self.SourceFileExtList.add(Ext)
159
160        # Check output files
161        self.DestFileList = []
162        for File in Output:
163            self.DestFileList.append(File)
164
165        # All build targets generated by this rule for a module
166        self.BuildTargets = {}
167
168    ## str() function support
169    #
170    #   @retval     string
171    #
172    def __str__(self):
173        SourceString = ""
174        SourceString += " %s %s %s" % (self.SourceFileType, " ".join(self.SourceFileExtList), self.ExtraSourceFileList)
175        DestString = ", ".join([str(i) for i in self.DestFileList])
176        CommandString = "\n\t".join(self.CommandList)
177        return "%s : %s\n\t%s" % (DestString, SourceString, CommandString)
178
179    def Instantiate(self, Macros = None):
180        if Macros is None:
181            Macros = {}
182        NewRuleObject = copy.copy(self)
183        NewRuleObject.BuildTargets = {}
184        NewRuleObject.DestFileList = []
185        for File in self.DestFileList:
186            NewRuleObject.DestFileList.append(PathClass(NormPath(File, Macros)))
187        return NewRuleObject
188
189    ## Apply the rule to given source file(s)
190    #
191    #   @param  SourceFile      One file or a list of files to be built
192    #   @param  RelativeToDir   The relative path of the source file
193    #   @param  PathSeparator   Path separator
194    #
195    #   @retval     tuple       (Source file in full path, List of individual sourcefiles, Destination file, List of build commands)
196    #
197    def Apply(self, SourceFile, BuildRuleOrder=None):
198        if not self.CommandList or not self.DestFileList:
199            return None
200
201        # source file
202        if self.IsMultipleInput:
203            SrcFileName = ""
204            SrcFileBase = ""
205            SrcFileExt = ""
206            SrcFileDir = ""
207            SrcPath = ""
208            # SourceFile must be a list
209            SrcFile = "$(%s)" % self.FileListMacro
210        else:
211            SrcFileName, SrcFileBase, SrcFileExt = SourceFile.Name, SourceFile.BaseName, SourceFile.Ext
212            if SourceFile.Root:
213                SrcFileDir = SourceFile.SubDir
214                if SrcFileDir == "":
215                    SrcFileDir = "."
216            else:
217                SrcFileDir = "."
218            SrcFile = SourceFile.Path
219            SrcPath = SourceFile.Dir
220
221        # destination file (the first one)
222        if self.DestFileList:
223            DestFile = self.DestFileList[0].Path
224            DestPath = self.DestFileList[0].Dir
225            DestFileName = self.DestFileList[0].Name
226            DestFileBase, DestFileExt = self.DestFileList[0].BaseName, self.DestFileList[0].Ext
227        else:
228            DestFile = ""
229            DestPath = ""
230            DestFileName = ""
231            DestFileBase = ""
232            DestFileExt = ""
233
234        BuildRulePlaceholderDict = {
235            # source file
236            "src"       :   SrcFile,
237            "s_path"    :   SrcPath,
238            "s_dir"     :   SrcFileDir,
239            "s_name"    :   SrcFileName,
240            "s_base"    :   SrcFileBase,
241            "s_ext"     :   SrcFileExt,
242            # destination file
243            "dst"       :   DestFile,
244            "d_path"    :   DestPath,
245            "d_name"    :   DestFileName,
246            "d_base"    :   DestFileBase,
247            "d_ext"     :   DestFileExt,
248        }
249
250        DstFile = []
251        for File in self.DestFileList:
252            File = string.Template(str(File)).safe_substitute(BuildRulePlaceholderDict)
253            File = string.Template(str(File)).safe_substitute(BuildRulePlaceholderDict)
254            DstFile.append(PathClass(File, IsBinary=True))
255
256        if DstFile[0] in self.BuildTargets:
257            TargetDesc = self.BuildTargets[DstFile[0]]
258            if BuildRuleOrder and SourceFile.Ext in BuildRuleOrder:
259                Index = BuildRuleOrder.index(SourceFile.Ext)
260                for Input in TargetDesc.Inputs:
261                    if Input.Ext not in BuildRuleOrder or BuildRuleOrder.index(Input.Ext) > Index:
262                        #
263                        # Command line should be regenerated since some macros are different
264                        #
265                        CommandList = self._BuildCommand(BuildRulePlaceholderDict)
266                        TargetDesc.InitWorker([SourceFile], DstFile, CommandList, self.ExtraSourceFileList)
267                        break
268            else:
269                TargetDesc.AddInput(SourceFile)
270        else:
271            CommandList = self._BuildCommand(BuildRulePlaceholderDict)
272            TargetDesc = TargetDescBlock([SourceFile], DstFile, CommandList, self.ExtraSourceFileList)
273            TargetDesc.ListFileMacro = self.ListFileMacro
274            TargetDesc.FileListMacro = self.FileListMacro
275            TargetDesc.IncListFileMacro = self.IncListFileMacro
276            TargetDesc.GenFileListMacro = self.GenFileListMacro
277            TargetDesc.GenListFile = self.GenListFile
278            TargetDesc.GenIncListFile = self.GenIncListFile
279            self.BuildTargets[DstFile[0]] = TargetDesc
280        return TargetDesc
281
282    def _BuildCommand(self, Macros):
283        CommandList = []
284        for CommandString in self.CommandList:
285            CommandString = string.Template(CommandString).safe_substitute(Macros)
286            CommandString = string.Template(CommandString).safe_substitute(Macros)
287            CommandList.append(CommandString)
288        return CommandList
289
290## Class for build rules
291#
292# BuildRule class parses rules defined in a file or passed by caller, and converts
293# the rule into FileBuildRule object.
294#
295class BuildRule:
296    _SectionHeader = "SECTIONHEADER"
297    _Section = "SECTION"
298    _SubSectionHeader = "SUBSECTIONHEADER"
299    _SubSection = "SUBSECTION"
300    _InputFile = "INPUTFILE"
301    _OutputFile = "OUTPUTFILE"
302    _ExtraDependency = "EXTRADEPENDENCY"
303    _Command = "COMMAND"
304    _UnknownSection = "UNKNOWNSECTION"
305
306    _SubSectionList = [_InputFile, _OutputFile, _Command]
307
308    _PATH_SEP = "(+)"
309    _FileTypePattern = re.compile("^[_a-zA-Z][_\-0-9a-zA-Z]*$")
310    _BinaryFileRule = FileBuildRule(TAB_DEFAULT_BINARY_FILE, [], [os.path.join("$(OUTPUT_DIR)", "${s_name}")],
311                                    ["$(CP) ${src} ${dst}"], [])
312
313    ## Constructor
314    #
315    #   @param  File                The file containing build rules in a well defined format
316    #   @param  Content             The string list of build rules in a well defined format
317    #   @param  LineIndex           The line number from which the parsing will begin
318    #   @param  SupportedFamily     The list of supported tool chain families
319    #
320    def __init__(self, File=None, Content=None, LineIndex=0, SupportedFamily=[TAB_COMPILER_MSFT, "INTEL", "GCC", "RVCT"]):
321        self.RuleFile = File
322        # Read build rules from file if it's not none
323        if File is not None:
324            try:
325                self.RuleContent = open(File, 'r').readlines()
326            except:
327                EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=File)
328        elif Content is not None:
329            self.RuleContent = Content
330        else:
331            EdkLogger.error("build", PARAMETER_MISSING, ExtraData="No rule file or string given")
332
333        self.SupportedToolChainFamilyList = SupportedFamily
334        self.RuleDatabase = tdict(True, 4)  # {FileExt, ModuleType, Arch, Family : FileBuildRule object}
335        self.Ext2FileType = {}  # {ext : file-type}
336        self.FileTypeList = set()
337
338        self._LineIndex = LineIndex
339        self._State = ""
340        self._RuleInfo = tdict(True, 2)     # {toolchain family : {"InputFile": {}, "OutputFile" : [], "Command" : []}}
341        self._FileType = ''
342        self._BuildTypeList = set()
343        self._ArchList = set()
344        self._FamilyList = []
345        self._TotalToolChainFamilySet = set()
346        self._RuleObjectList = [] # FileBuildRule object list
347        self._FileVersion = ""
348
349        self.Parse()
350
351        # some intrinsic rules
352        self.RuleDatabase[TAB_DEFAULT_BINARY_FILE, TAB_COMMON, TAB_COMMON, TAB_COMMON] = self._BinaryFileRule
353        self.FileTypeList.add(TAB_DEFAULT_BINARY_FILE)
354
355    ## Parse the build rule strings
356    def Parse(self):
357        self._State = self._Section
358        for Index in range(self._LineIndex, len(self.RuleContent)):
359            # Clean up the line and replace path separator with native one
360            Line = self.RuleContent[Index].strip().replace(self._PATH_SEP, os.path.sep)
361            self.RuleContent[Index] = Line
362
363            # find the build_rule_version
364            if Line and Line[0] == "#" and Line.find(TAB_BUILD_RULE_VERSION) != -1:
365                if Line.find("=") != -1 and Line.find("=") < (len(Line) - 1) and (Line[(Line.find("=") + 1):]).split():
366                    self._FileVersion = (Line[(Line.find("=") + 1):]).split()[0]
367            # skip empty or comment line
368            if Line == "" or Line[0] == "#":
369                continue
370
371            # find out section header, enclosed by []
372            if Line[0] == '[' and Line[-1] == ']':
373                # merge last section information into rule database
374                self.EndOfSection()
375                self._State = self._SectionHeader
376            # find out sub-section header, enclosed by <>
377            elif Line[0] == '<' and Line[-1] == '>':
378                if self._State != self._UnknownSection:
379                    self._State = self._SubSectionHeader
380
381            # call section handler to parse each (sub)section
382            self._StateHandler[self._State](self, Index)
383        # merge last section information into rule database
384        self.EndOfSection()
385
386    ## Parse definitions under a section
387    #
388    #   @param  LineIndex   The line index of build rule text
389    #
390    def ParseSection(self, LineIndex):
391        pass
392
393    ## Parse definitions under a subsection
394    #
395    #   @param  LineIndex   The line index of build rule text
396    #
397    def ParseSubSection(self, LineIndex):
398        # currently nothing here
399        pass
400
401    ## Placeholder for not supported sections
402    #
403    #   @param  LineIndex   The line index of build rule text
404    #
405    def SkipSection(self, LineIndex):
406        pass
407
408    ## Merge section information just got into rule database
409    def EndOfSection(self):
410        Database = self.RuleDatabase
411        # if there's specific toolchain family, 'COMMON' doesn't make sense any more
412        if len(self._TotalToolChainFamilySet) > 1 and TAB_COMMON in self._TotalToolChainFamilySet:
413            self._TotalToolChainFamilySet.remove(TAB_COMMON)
414        for Family in self._TotalToolChainFamilySet:
415            Input = self._RuleInfo[Family, self._InputFile]
416            Output = self._RuleInfo[Family, self._OutputFile]
417            Command = self._RuleInfo[Family, self._Command]
418            ExtraDependency = self._RuleInfo[Family, self._ExtraDependency]
419
420            BuildRule = FileBuildRule(self._FileType, Input, Output, Command, ExtraDependency)
421            for BuildType in self._BuildTypeList:
422                for Arch in self._ArchList:
423                    Database[self._FileType, BuildType, Arch, Family] = BuildRule
424                    for FileExt in BuildRule.SourceFileExtList:
425                        self.Ext2FileType[FileExt] = self._FileType
426
427    ## Parse section header
428    #
429    #   @param  LineIndex   The line index of build rule text
430    #
431    def ParseSectionHeader(self, LineIndex):
432        self._RuleInfo = tdict(True, 2)
433        self._BuildTypeList = set()
434        self._ArchList = set()
435        self._FamilyList = []
436        self._TotalToolChainFamilySet = set()
437        FileType = ''
438        RuleNameList = self.RuleContent[LineIndex][1:-1].split(',')
439        for RuleName in RuleNameList:
440            Arch = TAB_COMMON
441            BuildType = TAB_COMMON
442            TokenList = [Token.strip().upper() for Token in RuleName.split('.')]
443            # old format: Build.File-Type
444            if TokenList[0] == "BUILD":
445                if len(TokenList) == 1:
446                    EdkLogger.error("build", FORMAT_INVALID, "Invalid rule section",
447                                    File=self.RuleFile, Line=LineIndex + 1,
448                                    ExtraData=self.RuleContent[LineIndex])
449
450                FileType = TokenList[1]
451                if FileType == '':
452                    EdkLogger.error("build", FORMAT_INVALID, "No file type given",
453                                    File=self.RuleFile, Line=LineIndex + 1,
454                                    ExtraData=self.RuleContent[LineIndex])
455                if self._FileTypePattern.match(FileType) is None:
456                    EdkLogger.error("build", FORMAT_INVALID, File=self.RuleFile, Line=LineIndex + 1,
457                                    ExtraData="Only character, number (non-first character), '_' and '-' are allowed in file type")
458            # new format: File-Type.Build-Type.Arch
459            else:
460                if FileType == '':
461                    FileType = TokenList[0]
462                elif FileType != TokenList[0]:
463                    EdkLogger.error("build", FORMAT_INVALID,
464                                    "Different file types are not allowed in the same rule section",
465                                    File=self.RuleFile, Line=LineIndex + 1,
466                                    ExtraData=self.RuleContent[LineIndex])
467                if len(TokenList) > 1:
468                    BuildType = TokenList[1]
469                if len(TokenList) > 2:
470                    Arch = TokenList[2]
471            self._BuildTypeList.add(BuildType)
472            self._ArchList.add(Arch)
473
474        if TAB_COMMON in self._BuildTypeList and len(self._BuildTypeList) > 1:
475            EdkLogger.error("build", FORMAT_INVALID,
476                            "Specific build types must not be mixed with common one",
477                            File=self.RuleFile, Line=LineIndex + 1,
478                            ExtraData=self.RuleContent[LineIndex])
479        if TAB_COMMON in self._ArchList and len(self._ArchList) > 1:
480            EdkLogger.error("build", FORMAT_INVALID,
481                            "Specific ARCH must not be mixed with common one",
482                            File=self.RuleFile, Line=LineIndex + 1,
483                            ExtraData=self.RuleContent[LineIndex])
484
485        self._FileType = FileType
486        self._State = self._Section
487        self.FileTypeList.add(FileType)
488
489    ## Parse sub-section header
490    #
491    #   @param  LineIndex   The line index of build rule text
492    #
493    def ParseSubSectionHeader(self, LineIndex):
494        SectionType = ""
495        List = self.RuleContent[LineIndex][1:-1].split(',')
496        FamilyList = []
497        for Section in List:
498            TokenList = Section.split('.')
499            Type = TokenList[0].strip().upper()
500
501            if SectionType == "":
502                SectionType = Type
503            elif SectionType != Type:
504                EdkLogger.error("build", FORMAT_INVALID,
505                                "Two different section types are not allowed in the same sub-section",
506                                File=self.RuleFile, Line=LineIndex + 1,
507                                ExtraData=self.RuleContent[LineIndex])
508
509            if len(TokenList) > 1:
510                Family = TokenList[1].strip().upper()
511            else:
512                Family = TAB_COMMON
513
514            if Family not in FamilyList:
515                FamilyList.append(Family)
516
517        self._FamilyList = FamilyList
518        self._TotalToolChainFamilySet.update(FamilyList)
519        self._State = SectionType.upper()
520        if TAB_COMMON in FamilyList and len(FamilyList) > 1:
521            EdkLogger.error("build", FORMAT_INVALID,
522                            "Specific tool chain family should not be mixed with general one",
523                            File=self.RuleFile, Line=LineIndex + 1,
524                            ExtraData=self.RuleContent[LineIndex])
525        if self._State not in self._StateHandler:
526            EdkLogger.error("build", FORMAT_INVALID, File=self.RuleFile, Line=LineIndex + 1,
527                            ExtraData="Unknown subsection: %s" % self.RuleContent[LineIndex])
528    ## Parse <InputFile> sub-section
529    #
530    #   @param  LineIndex   The line index of build rule text
531    #
532    def ParseInputFileSubSection(self, LineIndex):
533        FileList = [File.strip() for File in self.RuleContent[LineIndex].split(",")]
534        for ToolChainFamily in self._FamilyList:
535            if self._RuleInfo[ToolChainFamily, self._State] is None:
536                self._RuleInfo[ToolChainFamily, self._State] = []
537            self._RuleInfo[ToolChainFamily, self._State].extend(FileList)
538
539    ## Parse <ExtraDependency> sub-section
540    ## Parse <OutputFile> sub-section
541    ## Parse <Command> sub-section
542    #
543    #   @param  LineIndex   The line index of build rule text
544    #
545    def ParseCommonSubSection(self, LineIndex):
546        for ToolChainFamily in self._FamilyList:
547            if self._RuleInfo[ToolChainFamily, self._State] is None:
548                self._RuleInfo[ToolChainFamily, self._State] = []
549            self._RuleInfo[ToolChainFamily, self._State].append(self.RuleContent[LineIndex])
550
551    ## Get a build rule via [] operator
552    #
553    #   @param  FileExt             The extension of a file
554    #   @param  ToolChainFamily     The tool chain family name
555    #   @param  BuildVersion        The build version number. TAB_STAR means any rule
556    #                               is applicable.
557    #
558    #   @retval FileType        The file type string
559    #   @retval FileBuildRule   The object of FileBuildRule
560    #
561    # Key = (FileExt, ModuleType, Arch, ToolChainFamily)
562    def __getitem__(self, Key):
563        if not Key:
564            return None
565
566        if Key[0] in self.Ext2FileType:
567            Type = self.Ext2FileType[Key[0]]
568        elif Key[0].upper() in self.FileTypeList:
569            Type = Key[0].upper()
570        else:
571            return None
572
573        if len(Key) > 1:
574            Key = (Type,) + Key[1:]
575        else:
576            Key = (Type,)
577        return self.RuleDatabase[Key]
578
579    _StateHandler = {
580        _SectionHeader     : ParseSectionHeader,
581        _Section           : ParseSection,
582        _SubSectionHeader  : ParseSubSectionHeader,
583        _SubSection        : ParseSubSection,
584        _InputFile         : ParseInputFileSubSection,
585        _OutputFile        : ParseCommonSubSection,
586        _ExtraDependency   : ParseCommonSubSection,
587        _Command           : ParseCommonSubSection,
588        _UnknownSection    : SkipSection,
589    }
590
591class ToolBuildRule():
592
593    def __new__(cls, *args, **kw):
594        if not hasattr(cls, '_instance'):
595            orig = super(ToolBuildRule, cls)
596            cls._instance = orig.__new__(cls, *args, **kw)
597        return cls._instance
598
599    def __init__(self):
600        if not hasattr(self, 'ToolBuildRule'):
601            self._ToolBuildRule = None
602
603    @property
604    def ToolBuildRule(self):
605        if not self._ToolBuildRule:
606            self._GetBuildRule()
607        return self._ToolBuildRule
608
609    def _GetBuildRule(self):
610        BuildRuleFile = None
611        TargetObj = TargetTxtDict()
612        TargetTxt = TargetObj.Target
613        if TAB_TAT_DEFINES_BUILD_RULE_CONF in TargetTxt.TargetTxtDictionary:
614            BuildRuleFile = TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
615        if not BuildRuleFile:
616            BuildRuleFile = gDefaultBuildRuleFile
617        RetVal = BuildRule(BuildRuleFile)
618        if RetVal._FileVersion == "":
619            RetVal._FileVersion = AutoGenReqBuildRuleVerNum
620        else:
621            if RetVal._FileVersion < AutoGenReqBuildRuleVerNum :
622                # If Build Rule's version is less than the version number required by the tools, halting the build.
623                EdkLogger.error("build", AUTOGEN_ERROR,
624                                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])"\
625                                 % (RetVal._FileVersion, AutoGenReqBuildRuleVerNum))
626        self._ToolBuildRule = RetVal
627
628# This acts like the main() function for the script, unless it is 'import'ed into another
629# script.
630if __name__ == '__main__':
631    import sys
632    EdkLogger.Initialize()
633    if len(sys.argv) > 1:
634        Br = BuildRule(sys.argv[1])
635        print(str(Br[".c", SUP_MODULE_DXE_DRIVER, "IA32", TAB_COMPILER_MSFT][1]))
636        print()
637        print(str(Br[".c", SUP_MODULE_DXE_DRIVER, "IA32", "INTEL"][1]))
638        print()
639        print(str(Br[".c", SUP_MODULE_DXE_DRIVER, "IA32", "GCC"][1]))
640        print()
641        print(str(Br[".ac", "ACPI_TABLE", "IA32", TAB_COMPILER_MSFT][1]))
642        print()
643        print(str(Br[".h", "ACPI_TABLE", "IA32", "INTEL"][1]))
644        print()
645        print(str(Br[".ac", "ACPI_TABLE", "IA32", TAB_COMPILER_MSFT][1]))
646        print()
647        print(str(Br[".s", SUP_MODULE_SEC, "IPF", "COMMON"][1]))
648        print()
649        print(str(Br[".s", SUP_MODULE_SEC][1]))
650
651