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