BuildEngine.py 24 KB

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