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