]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - BaseTools/Source/Python/Common/ToolDefClassObject.py
OvmfPkg/SerializeVariablesLib: Relax check for the read-only variable
[mirror_edk2.git] / BaseTools / Source / Python / Common / ToolDefClassObject.py
... / ...
CommitLineData
1## @file\r
2# This file is used to define each component of tools_def.txt file\r
3#\r
4# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
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
17import Common.LongFilePathOs as os\r
18import re\r
19import EdkLogger\r
20\r
21from Dictionary import *\r
22from BuildToolError import *\r
23from TargetTxtClassObject import *\r
24from Common.LongFilePathSupport import OpenLongFilePath as open\r
25from Common.Misc import PathClass\r
26from Common.String import NormPath\r
27import Common.GlobalData as GlobalData\r
28from Common import GlobalData\r
29from Common.MultipleWorkspace import MultipleWorkspace as mws\r
30\r
31##\r
32# Static variables used for pattern\r
33#\r
34gMacroRefPattern = re.compile('(DEF\([^\(\)]+\))')\r
35gEnvRefPattern = re.compile('(ENV\([^\(\)]+\))')\r
36gMacroDefPattern = re.compile("DEFINE\s+([^\s]+)")\r
37gDefaultToolsDefFile = "tools_def.txt"\r
38\r
39## ToolDefClassObject\r
40#\r
41# This class defined content used in file tools_def.txt\r
42#\r
43# @param object: Inherited from object class\r
44# @param Filename: Input value for full path of tools_def.txt\r
45#\r
46# @var ToolsDefTxtDictionary: To store keys and values defined in target.txt\r
47# @var MacroDictionary: To store keys and values defined in DEFINE statement\r
48#\r
49class ToolDefClassObject(object):\r
50 def __init__(self, FileName=None):\r
51 self.ToolsDefTxtDictionary = {}\r
52 self.MacroDictionary = {}\r
53 for Env in os.environ:\r
54 self.MacroDictionary["ENV(%s)" % Env] = os.environ[Env]\r
55\r
56 if FileName != None:\r
57 self.LoadToolDefFile(FileName)\r
58\r
59 ## LoadToolDefFile\r
60 #\r
61 # Load target.txt file and parse it\r
62 #\r
63 # @param Filename: Input value for full path of tools_def.txt\r
64 #\r
65 def LoadToolDefFile(self, FileName):\r
66 # set multiple workspace\r
67 PackagesPath = os.getenv("PACKAGES_PATH")\r
68 mws.setWs(GlobalData.gWorkspace, PackagesPath)\r
69\r
70 self.ToolsDefTxtDatabase = {\r
71 TAB_TOD_DEFINES_TARGET : [],\r
72 TAB_TOD_DEFINES_TOOL_CHAIN_TAG : [],\r
73 TAB_TOD_DEFINES_TARGET_ARCH : [],\r
74 TAB_TOD_DEFINES_COMMAND_TYPE : []\r
75 }\r
76\r
77 self.IncludeToolDefFile(FileName)\r
78\r
79\r
80 ## IncludeToolDefFile\r
81 #\r
82 # Load target.txt file and parse it as if it's contents were inside the main file\r
83 #\r
84 # @param Filename: Input value for full path of tools_def.txt\r
85 #\r
86 def IncludeToolDefFile(self, FileName):\r
87 FileContent = []\r
88 if os.path.isfile(FileName):\r
89 try:\r
90 F = open(FileName, 'r')\r
91 FileContent = F.readlines()\r
92 except:\r
93 EdkLogger.error("tools_def.txt parser", FILE_OPEN_FAILURE, ExtraData=FileName)\r
94 else:\r
95 EdkLogger.error("tools_def.txt parser", FILE_NOT_FOUND, ExtraData=FileName)\r
96\r
97 for Index in range(len(FileContent)):\r
98 Line = FileContent[Index].strip()\r
99 if Line == "" or Line[0] == '#':\r
100 continue\r
101\r
102 if Line.startswith("!include"):\r
103 IncFile = Line[8:].strip()\r
104 Done, IncFile = self.ExpandMacros(IncFile)\r
105 if not Done:\r
106 EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,\r
107 "Macro or Environment has not been defined",\r
108 ExtraData=IncFile[4:-1], File=FileName, Line=Index+1)\r
109 IncFile = NormPath(IncFile)\r
110\r
111 if not os.path.isabs(IncFile):\r
112 #\r
113 # try WORKSPACE\r
114 #\r
115 IncFileTmp = PathClass(IncFile, GlobalData.gWorkspace)\r
116 ErrorCode = IncFileTmp.Validate()[0]\r
117 if ErrorCode != 0:\r
118 #\r
119 # try PACKAGES_PATH\r
120 #\r
121 IncFileTmp = mws.join(GlobalData.gWorkspace, IncFile)\r
122 if not os.path.exists(IncFileTmp):\r
123 #\r
124 # try directory of current file\r
125 #\r
126 IncFileTmp = PathClass(IncFile, os.path.dirname(FileName))\r
127 ErrorCode = IncFileTmp.Validate()[0]\r
128 if ErrorCode != 0:\r
129 EdkLogger.error("tools_def.txt parser", FILE_NOT_FOUND, ExtraData=IncFile)\r
130\r
131 if type(IncFileTmp) is PathClass:\r
132 IncFile = IncFileTmp.Path\r
133 else:\r
134 IncFile = IncFileTmp\r
135\r
136 self.IncludeToolDefFile(IncFile)\r
137 continue\r
138\r
139 NameValuePair = Line.split("=", 1)\r
140 if len(NameValuePair) != 2:\r
141 EdkLogger.warn("tools_def.txt parser", "Line %d: not correct assignment statement, skipped" % (Index + 1))\r
142 continue\r
143\r
144 Name = NameValuePair[0].strip()\r
145 Value = NameValuePair[1].strip()\r
146\r
147 if Name == "IDENTIFIER":\r
148 EdkLogger.debug(EdkLogger.DEBUG_8, "Line %d: Found identifier statement, skipped: %s" % ((Index + 1), Value))\r
149 continue\r
150\r
151 MacroDefinition = gMacroDefPattern.findall(Name)\r
152 if MacroDefinition != []:\r
153 Done, Value = self.ExpandMacros(Value)\r
154 if not Done:\r
155 EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,\r
156 "Macro or Environment has not been defined",\r
157 ExtraData=Value[4:-1], File=FileName, Line=Index+1)\r
158\r
159 MacroName = MacroDefinition[0].strip()\r
160 self.MacroDictionary["DEF(%s)" % MacroName] = Value\r
161 EdkLogger.debug(EdkLogger.DEBUG_8, "Line %d: Found macro: %s = %s" % ((Index + 1), MacroName, Value))\r
162 continue\r
163\r
164 Done, Value = self.ExpandMacros(Value)\r
165 if not Done:\r
166 EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,\r
167 "Macro or Environment has not been defined",\r
168 ExtraData=Value[4:-1], File=FileName, Line=Index+1)\r
169\r
170 List = Name.split('_')\r
171 if len(List) != 5:\r
172 EdkLogger.verbose("Line %d: Not a valid name of definition: %s" % ((Index + 1), Name))\r
173 continue\r
174 elif List[4] == '*':\r
175 EdkLogger.verbose("Line %d: '*' is not allowed in last field: %s" % ((Index + 1), Name))\r
176 continue\r
177 else:\r
178 self.ToolsDefTxtDictionary[Name] = Value\r
179 if List[0] != '*':\r
180 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] += [List[0]]\r
181 if List[1] != '*':\r
182 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] += [List[1]]\r
183 if List[2] != '*':\r
184 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] += [List[2]]\r
185 if List[3] != '*':\r
186 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] += [List[3]]\r
187 if List[4] == TAB_TOD_DEFINES_FAMILY and List[2] == '*' and List[3] == '*':\r
188 if TAB_TOD_DEFINES_FAMILY not in self.ToolsDefTxtDatabase:\r
189 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY] = {}\r
190 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] = Value\r
191 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY] = {}\r
192 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value\r
193 elif List[1] not in self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]:\r
194 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] = Value\r
195 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value\r
196 elif self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] != Value:\r
197 EdkLogger.verbose("Line %d: No override allowed for the family of a tool chain: %s" % ((Index + 1), Name))\r
198 if List[4] == TAB_TOD_DEFINES_BUILDRULEFAMILY and List[2] == '*' and List[3] == '*':\r
199 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in self.ToolsDefTxtDatabase \\r
200 or List[1] not in self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]:\r
201 EdkLogger.verbose("Line %d: The family is not specified, but BuildRuleFamily is specified for the tool chain: %s" % ((Index + 1), Name))\r
202 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value\r
203\r
204 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET]))\r
205 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG]))\r
206 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH]))\r
207 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE]))\r
208\r
209 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET].sort()\r
210 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG].sort()\r
211 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH].sort()\r
212 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE].sort()\r
213\r
214 KeyList = [TAB_TOD_DEFINES_TARGET, TAB_TOD_DEFINES_TOOL_CHAIN_TAG, TAB_TOD_DEFINES_TARGET_ARCH, TAB_TOD_DEFINES_COMMAND_TYPE]\r
215 for Index in range(3, -1, -1):\r
216 for Key in dict(self.ToolsDefTxtDictionary):\r
217 List = Key.split('_')\r
218 if List[Index] == '*':\r
219 for String in self.ToolsDefTxtDatabase[KeyList[Index]]:\r
220 List[Index] = String\r
221 NewKey = '%s_%s_%s_%s_%s' % tuple(List)\r
222 if NewKey not in self.ToolsDefTxtDictionary:\r
223 self.ToolsDefTxtDictionary[NewKey] = self.ToolsDefTxtDictionary[Key]\r
224 continue\r
225 del self.ToolsDefTxtDictionary[Key]\r
226 elif List[Index] not in self.ToolsDefTxtDatabase[KeyList[Index]]:\r
227 del self.ToolsDefTxtDictionary[Key]\r
228\r
229 ## ExpandMacros\r
230 #\r
231 # Replace defined macros with real value\r
232 #\r
233 # @param Value: The string with unreplaced macros\r
234 #\r
235 # @retval Value: The string which has been replaced with real value\r
236 #\r
237 def ExpandMacros(self, Value):\r
238 EnvReference = gEnvRefPattern.findall(Value)\r
239 for Ref in EnvReference:\r
240 if Ref not in self.MacroDictionary:\r
241 Value = Value.replace(Ref, "")\r
242 else:\r
243 Value = Value.replace(Ref, self.MacroDictionary[Ref])\r
244 \r
245\r
246 MacroReference = gMacroRefPattern.findall(Value)\r
247 for Ref in MacroReference:\r
248 if Ref not in self.MacroDictionary:\r
249 return False, Ref\r
250 Value = Value.replace(Ref, self.MacroDictionary[Ref])\r
251\r
252 return True, Value\r
253\r
254## ToolDefDict\r
255#\r
256# Load tools_def.txt in input Conf dir\r
257#\r
258# @param ConfDir: Conf dir\r
259#\r
260# @retval ToolDef An instance of ToolDefClassObject() with loaded tools_def.txt\r
261#\r
262def ToolDefDict(ConfDir):\r
263 Target = TargetTxtDict(ConfDir)\r
264 ToolDef = ToolDefClassObject()\r
265 if DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF in Target.TargetTxtDictionary:\r
266 ToolsDefFile = Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]\r
267 if ToolsDefFile:\r
268 ToolDef.LoadToolDefFile(os.path.normpath(ToolsDefFile))\r
269 else:\r
270 ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(ConfDir, gDefaultToolsDefFile)))\r
271 else:\r
272 ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(ConfDir, gDefaultToolsDefFile)))\r
273 return ToolDef\r
274\r
275##\r
276#\r
277# This acts like the main() function for the script, unless it is 'import'ed into another\r
278# script.\r
279#\r
280if __name__ == '__main__':\r
281 ToolDef = ToolDefDict(os.getenv("WORKSPACE"))\r
282 pass\r