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