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