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