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