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