]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Common/ToolDefClassObject.py
There is a limitation on WINDOWS OS for the length of entire file path can’t be large...
[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 - 2014, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
9 #
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 #
13
14 ##
15 # Import Modules
16 #
17 import Common.LongFilePathOs as os
18 import re
19 import EdkLogger
20
21 from Dictionary import *
22 from BuildToolError import *
23 from TargetTxtClassObject import *
24 from Common.LongFilePathSupport import OpenLongFilePath as open
25
26 ##
27 # Static variables used for pattern
28 #
29 gMacroRefPattern = re.compile('(DEF\([^\(\)]+\))')
30 gEnvRefPattern = re.compile('(ENV\([^\(\)]+\))')
31 gMacroDefPattern = re.compile("DEFINE\s+([^\s]+)")
32 gDefaultToolsDefFile = "Conf/tools_def.txt"
33
34 ## ToolDefClassObject
35 #
36 # This class defined content used in file tools_def.txt
37 #
38 # @param object: Inherited from object class
39 # @param Filename: Input value for full path of tools_def.txt
40 #
41 # @var ToolsDefTxtDictionary: To store keys and values defined in target.txt
42 # @var MacroDictionary: To store keys and values defined in DEFINE statement
43 #
44 class ToolDefClassObject(object):
45 def __init__(self, FileName = None):
46 self.ToolsDefTxtDictionary = {}
47 self.MacroDictionary = {}
48 for Env in os.environ:
49 self.MacroDictionary["ENV(%s)" % Env] = os.environ[Env]
50
51 if FileName != None:
52 self.LoadToolDefFile(FileName)
53
54 ## LoadToolDefFile
55 #
56 # Load target.txt file and parse it, return a set structure to store keys and values
57 #
58 # @param Filename: Input value for full path of tools_def.txt
59 #
60 def LoadToolDefFile(self, FileName):
61 FileContent = []
62 if os.path.isfile(FileName):
63 try:
64 F = open(FileName,'r')
65 FileContent = F.readlines()
66 except:
67 EdkLogger.error("tools_def.txt parser", FILE_OPEN_FAILURE, ExtraData=FileName)
68 else:
69 EdkLogger.error("tools_def.txt parser", FILE_NOT_FOUND, ExtraData=FileName)
70
71 self.ToolsDefTxtDatabase = {
72 TAB_TOD_DEFINES_TARGET : [],
73 TAB_TOD_DEFINES_TOOL_CHAIN_TAG : [],
74 TAB_TOD_DEFINES_TARGET_ARCH : [],
75 TAB_TOD_DEFINES_COMMAND_TYPE : []
76 }
77
78 for Index in range(len(FileContent)):
79 Line = FileContent[Index].strip()
80 if Line == "" or Line[0] == '#':
81 continue
82 NameValuePair = Line.split("=", 1)
83 if len(NameValuePair) != 2:
84 EdkLogger.warn("tools_def.txt parser", "Line %d: not correct assignment statement, skipped" % (Index + 1))
85 continue
86
87 Name = NameValuePair[0].strip()
88 Value = NameValuePair[1].strip()
89
90 if Name == "IDENTIFIER":
91 EdkLogger.debug(EdkLogger.DEBUG_8, "Line %d: Found identifier statement, skipped: %s" % ((Index + 1), Value))
92 continue
93
94 MacroDefinition = gMacroDefPattern.findall(Name)
95 if MacroDefinition != []:
96 Done, Value = self.ExpandMacros(Value)
97 if not Done:
98 EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,
99 "Macro or Environment has not been defined",
100 ExtraData=Value[4:-1], File=FileName, Line=Index+1)
101
102 MacroName = MacroDefinition[0].strip()
103 self.MacroDictionary["DEF(%s)" % MacroName] = Value
104 EdkLogger.debug(EdkLogger.DEBUG_8, "Line %d: Found macro: %s = %s" % ((Index + 1), MacroName, Value))
105 continue
106
107 Done, Value = self.ExpandMacros(Value)
108 if not Done:
109 EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,
110 "Macro or Environment has not been defined",
111 ExtraData=Value[4:-1], File=FileName, Line=Index+1)
112
113 List = Name.split('_')
114 if len(List) != 5:
115 EdkLogger.verbose("Line %d: Not a valid name of definition: %s" % ((Index + 1), Name))
116 continue
117 elif List[4] == '*':
118 EdkLogger.verbose("Line %d: '*' is not allowed in last field: %s" % ((Index + 1), Name))
119 continue
120 else:
121 self.ToolsDefTxtDictionary[Name] = Value
122 if List[0] != '*':
123 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] += [List[0]]
124 if List[1] != '*':
125 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] += [List[1]]
126 if List[2] != '*':
127 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] += [List[2]]
128 if List[3] != '*':
129 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] += [List[3]]
130 if List[4] == TAB_TOD_DEFINES_FAMILY and List[2] == '*' and List[3] == '*':
131 if TAB_TOD_DEFINES_FAMILY not in self.ToolsDefTxtDatabase:
132 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY] = {}
133 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] = Value
134 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY] = {}
135 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value
136 elif List[1] not in self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]:
137 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] = Value
138 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value
139 elif self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] != Value:
140 EdkLogger.verbose("Line %d: No override allowed for the family of a tool chain: %s" % ((Index + 1), Name))
141 if List[4] == TAB_TOD_DEFINES_BUILDRULEFAMILY and List[2] == '*' and List[3] == '*':
142 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in self.ToolsDefTxtDatabase \
143 or List[1] not in self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]:
144 EdkLogger.verbose("Line %d: The family is not specified, but BuildRuleFamily is specified for the tool chain: %s" % ((Index + 1), Name))
145 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value
146
147 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET]))
148 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG]))
149 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH]))
150 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE]))
151
152 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET].sort()
153 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG].sort()
154 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH].sort()
155 self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE].sort()
156
157 KeyList = [TAB_TOD_DEFINES_TARGET, TAB_TOD_DEFINES_TOOL_CHAIN_TAG, TAB_TOD_DEFINES_TARGET_ARCH, TAB_TOD_DEFINES_COMMAND_TYPE]
158 for Index in range(3,-1,-1):
159 for Key in dict(self.ToolsDefTxtDictionary):
160 List = Key.split('_')
161 if List[Index] == '*':
162 for String in self.ToolsDefTxtDatabase[KeyList[Index]]:
163 List[Index] = String
164 NewKey = '%s_%s_%s_%s_%s' % tuple(List)
165 if NewKey not in self.ToolsDefTxtDictionary:
166 self.ToolsDefTxtDictionary[NewKey] = self.ToolsDefTxtDictionary[Key]
167 continue
168 del self.ToolsDefTxtDictionary[Key]
169 elif List[Index] not in self.ToolsDefTxtDatabase[KeyList[Index]]:
170 del self.ToolsDefTxtDictionary[Key]
171
172 ## ExpandMacros
173 #
174 # Replace defined macros with real value
175 #
176 # @param Value: The string with unreplaced macros
177 #
178 # @retval Value: The string which has been replaced with real value
179 #
180 def ExpandMacros(self, Value):
181 EnvReference = gEnvRefPattern.findall(Value)
182 for Ref in EnvReference:
183 if Ref not in self.MacroDictionary:
184 Value = Value.replace(Ref, "")
185 else:
186 Value = Value.replace(Ref, self.MacroDictionary[Ref])
187
188
189 MacroReference = gMacroRefPattern.findall(Value)
190 for Ref in MacroReference:
191 if Ref not in self.MacroDictionary:
192 return False, Ref
193 Value = Value.replace(Ref, self.MacroDictionary[Ref])
194
195 return True, Value
196
197 ## ToolDefDict
198 #
199 # Load tools_def.txt in input workspace dir
200 #
201 # @param WorkSpace: Workspace dir
202 #
203 # @retval ToolDef An instance of ToolDefClassObject() with loaded tools_def.txt
204 #
205 def ToolDefDict(WorkSpace):
206 Target = TargetTxtDict(WorkSpace)
207 ToolDef = ToolDefClassObject()
208 if DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF in Target.TargetTxtDictionary:
209 gDefaultToolsDefFile = Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
210 ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(WorkSpace, gDefaultToolsDefFile)))
211 return ToolDef
212
213 ##
214 #
215 # This acts like the main() function for the script, unless it is 'import'ed into another
216 # script.
217 #
218 if __name__ == '__main__':
219 ToolDef = ToolDefDict(os.getenv("WORKSPACE"))
220 pass