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