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