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