]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - BaseTools/Source/Python/Common/ToolDefClassObject.py
BaseTools: fix imports
[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 - 2019, 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
17from __future__ import absolute_import\r
18import Common.LongFilePathOs as os\r
19import re\r
20from . import EdkLogger\r
21\r
22from .BuildToolError import *\r
23from Common.TargetTxtClassObject import TargetTxtDict\r
24from Common.LongFilePathSupport import OpenLongFilePath as open\r
25from Common.Misc import PathClass\r
26from Common.StringUtils import NormPath\r
27import Common.GlobalData as GlobalData\r
28from Common import GlobalData\r
29from Common.MultipleWorkspace import MultipleWorkspace as mws\r
30from .DataType import TAB_TOD_DEFINES_TARGET, TAB_TOD_DEFINES_TOOL_CHAIN_TAG,\\r
31 TAB_TOD_DEFINES_TARGET_ARCH, TAB_TOD_DEFINES_COMMAND_TYPE\\r
32 , TAB_TOD_DEFINES_FAMILY, TAB_TOD_DEFINES_BUILDRULEFAMILY,\\r
33 TAB_STAR, TAB_TAT_DEFINES_TOOL_CHAIN_CONF\r
34\r
35\r
36##\r
37# Static variables used for pattern\r
38#\r
39gMacroRefPattern = re.compile('(DEF\([^\(\)]+\))')\r
40gEnvRefPattern = re.compile('(ENV\([^\(\)]+\))')\r
41gMacroDefPattern = re.compile("DEFINE\s+([^\s]+)")\r
42gDefaultToolsDefFile = "tools_def.txt"\r
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
55 def __init__(self, FileName=None):\r
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
61 if FileName is not None:\r
62 self.LoadToolDefFile(FileName)\r
63\r
64 ## LoadToolDefFile\r
65 #\r
66 # Load target.txt file and parse it\r
67 #\r
68 # @param Filename: Input value for full path of tools_def.txt\r
69 #\r
70 def LoadToolDefFile(self, FileName):\r
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
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
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
100 List = Key.split('_')\r
101 if List[Index] == TAB_STAR:\r
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
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
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
119 FileContent = []\r
120 if os.path.isfile(FileName):\r
121 try:\r
122 F = open(FileName, 'r')\r
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
129 for Index in range(len(FileContent)):\r
130 Line = FileContent[Index].strip()\r
131 if Line == "" or Line[0] == '#':\r
132 continue\r
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
163 if isinstance(IncFileTmp, PathClass):\r
164 IncFile = IncFileTmp.Path\r
165 else:\r
166 IncFile = IncFileTmp\r
167\r
168 self.IncludeToolDefFile(IncFile)\r
169 continue\r
170\r
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
206 elif List[4] == TAB_STAR:\r
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
211 if List[0] != TAB_STAR:\r
212 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] += [List[0]]\r
213 if List[1] != TAB_STAR:\r
214 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] += [List[1]]\r
215 if List[2] != TAB_STAR:\r
216 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] += [List[2]]\r
217 if List[3] != TAB_STAR:\r
218 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] += [List[3]]\r
219 if List[4] == TAB_TOD_DEFINES_FAMILY and List[2] == TAB_STAR and List[3] == TAB_STAR:\r
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
230 if List[4] == TAB_TOD_DEFINES_BUILDRULEFAMILY and List[2] == TAB_STAR and List[3] == TAB_STAR:\r
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
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
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
246 EnvReference = gEnvRefPattern.findall(Value)\r
247 for Ref in EnvReference:\r
248 if Ref not in self.MacroDictionary and Ref.upper() not in self.MacroDictionary:\r
249 Value = Value.replace(Ref, "")\r
250 else:\r
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
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
265# Load tools_def.txt in input Conf dir\r
266#\r
267# @param ConfDir: Conf dir\r
268#\r
269# @retval ToolDef An instance of ToolDefClassObject() with loaded tools_def.txt\r
270#\r
271def ToolDefDict(ConfDir):\r
272 Target = TargetTxtDict(ConfDir)\r
273 ToolDef = ToolDefClassObject()\r
274 if TAB_TAT_DEFINES_TOOL_CHAIN_CONF in Target.TargetTxtDictionary:\r
275 ToolsDefFile = Target.TargetTxtDictionary[TAB_TAT_DEFINES_TOOL_CHAIN_CONF]\r
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
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