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