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