2 # This file is used to define each component of tools_def.txt file
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
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.
17 import Common
.LongFilePathOs
as os
21 from Dictionary
import *
22 from BuildToolError
import *
23 from TargetTxtClassObject
import *
24 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
25 from Common
.Misc
import PathClass
26 from Common
.String
import NormPath
27 import Common
.GlobalData
as GlobalData
28 from Common
import GlobalData
29 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
32 # Static variables used for pattern
34 gMacroRefPattern
= re
.compile('(DEF\([^\(\)]+\))')
35 gEnvRefPattern
= re
.compile('(ENV\([^\(\)]+\))')
36 gMacroDefPattern
= re
.compile("DEFINE\s+([^\s]+)")
37 gDefaultToolsDefFile
= "tools_def.txt"
41 # This class defined content used in file tools_def.txt
43 # @param object: Inherited from object class
44 # @param Filename: Input value for full path of tools_def.txt
46 # @var ToolsDefTxtDictionary: To store keys and values defined in target.txt
47 # @var MacroDictionary: To store keys and values defined in DEFINE statement
49 class ToolDefClassObject(object):
50 def __init__(self
, FileName
=None):
51 self
.ToolsDefTxtDictionary
= {}
52 self
.MacroDictionary
= {}
53 for Env
in os
.environ
:
54 self
.MacroDictionary
["ENV(%s)" % Env
] = os
.environ
[Env
]
57 self
.LoadToolDefFile(FileName
)
61 # Load target.txt file and parse it
63 # @param Filename: Input value for full path of tools_def.txt
65 def LoadToolDefFile(self
, FileName
):
66 # set multiple workspace
67 PackagesPath
= os
.getenv("PACKAGES_PATH")
68 mws
.setWs(GlobalData
.gWorkspace
, PackagesPath
)
70 self
.ToolsDefTxtDatabase
= {
71 TAB_TOD_DEFINES_TARGET
: [],
72 TAB_TOD_DEFINES_TOOL_CHAIN_TAG
: [],
73 TAB_TOD_DEFINES_TARGET_ARCH
: [],
74 TAB_TOD_DEFINES_COMMAND_TYPE
: []
77 self
.IncludeToolDefFile(FileName
)
82 # Load target.txt file and parse it as if it's contents were inside the main file
84 # @param Filename: Input value for full path of tools_def.txt
86 def IncludeToolDefFile(self
, FileName
):
88 if os
.path
.isfile(FileName
):
90 F
= open(FileName
, 'r')
91 FileContent
= F
.readlines()
93 EdkLogger
.error("tools_def.txt parser", FILE_OPEN_FAILURE
, ExtraData
=FileName
)
95 EdkLogger
.error("tools_def.txt parser", FILE_NOT_FOUND
, ExtraData
=FileName
)
97 for Index
in range(len(FileContent
)):
98 Line
= FileContent
[Index
].strip()
99 if Line
== "" or Line
[0] == '#':
102 if Line
.startswith("!include"):
103 IncFile
= Line
[8:].strip()
104 Done
, IncFile
= self
.ExpandMacros(IncFile
)
106 EdkLogger
.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE
,
107 "Macro or Environment has not been defined",
108 ExtraData
=IncFile
[4:-1], File
=FileName
, Line
=Index
+1)
109 IncFile
= NormPath(IncFile
)
111 if not os
.path
.isabs(IncFile
):
115 IncFileTmp
= PathClass(IncFile
, GlobalData
.gWorkspace
)
116 ErrorCode
= IncFileTmp
.Validate()[0]
121 IncFileTmp
= mws
.join(GlobalData
.gWorkspace
, IncFile
)
122 if not os
.path
.exists(IncFileTmp
):
124 # try directory of current file
126 IncFileTmp
= PathClass(IncFile
, os
.path
.dirname(FileName
))
127 ErrorCode
= IncFileTmp
.Validate()[0]
129 EdkLogger
.error("tools_def.txt parser", FILE_NOT_FOUND
, ExtraData
=IncFile
)
131 if type(IncFileTmp
) is PathClass
:
132 IncFile
= IncFileTmp
.Path
136 self
.IncludeToolDefFile(IncFile
)
139 NameValuePair
= Line
.split("=", 1)
140 if len(NameValuePair
) != 2:
141 EdkLogger
.warn("tools_def.txt parser", "Line %d: not correct assignment statement, skipped" % (Index
+ 1))
144 Name
= NameValuePair
[0].strip()
145 Value
= NameValuePair
[1].strip()
147 if Name
== "IDENTIFIER":
148 EdkLogger
.debug(EdkLogger
.DEBUG_8
, "Line %d: Found identifier statement, skipped: %s" % ((Index
+ 1), Value
))
151 MacroDefinition
= gMacroDefPattern
.findall(Name
)
152 if MacroDefinition
!= []:
153 Done
, Value
= self
.ExpandMacros(Value
)
155 EdkLogger
.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE
,
156 "Macro or Environment has not been defined",
157 ExtraData
=Value
[4:-1], File
=FileName
, Line
=Index
+1)
159 MacroName
= MacroDefinition
[0].strip()
160 self
.MacroDictionary
["DEF(%s)" % MacroName
] = Value
161 EdkLogger
.debug(EdkLogger
.DEBUG_8
, "Line %d: Found macro: %s = %s" % ((Index
+ 1), MacroName
, Value
))
164 Done
, Value
= self
.ExpandMacros(Value
)
166 EdkLogger
.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE
,
167 "Macro or Environment has not been defined",
168 ExtraData
=Value
[4:-1], File
=FileName
, Line
=Index
+1)
170 List
= Name
.split('_')
172 EdkLogger
.verbose("Line %d: Not a valid name of definition: %s" % ((Index
+ 1), Name
))
175 EdkLogger
.verbose("Line %d: '*' is not allowed in last field: %s" % ((Index
+ 1), Name
))
178 self
.ToolsDefTxtDictionary
[Name
] = Value
180 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_TARGET
] += [List
[0]]
182 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_TOOL_CHAIN_TAG
] += [List
[1]]
184 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_TARGET_ARCH
] += [List
[2]]
186 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_COMMAND_TYPE
] += [List
[3]]
187 if List
[4] == TAB_TOD_DEFINES_FAMILY
and List
[2] == '*' and List
[3] == '*':
188 if TAB_TOD_DEFINES_FAMILY
not in self
.ToolsDefTxtDatabase
:
189 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_FAMILY
] = {}
190 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_FAMILY
][List
[1]] = Value
191 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] = {}
192 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][List
[1]] = Value
193 elif List
[1] not in self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_FAMILY
]:
194 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_FAMILY
][List
[1]] = Value
195 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][List
[1]] = Value
196 elif self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_FAMILY
][List
[1]] != Value
:
197 EdkLogger
.verbose("Line %d: No override allowed for the family of a tool chain: %s" % ((Index
+ 1), Name
))
198 if List
[4] == TAB_TOD_DEFINES_BUILDRULEFAMILY
and List
[2] == '*' and List
[3] == '*':
199 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in self
.ToolsDefTxtDatabase \
200 or List
[1] not in self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_FAMILY
]:
201 EdkLogger
.verbose("Line %d: The family is not specified, but BuildRuleFamily is specified for the tool chain: %s" % ((Index
+ 1), Name
))
202 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][List
[1]] = Value
204 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_TARGET
] = list(set(self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_TARGET
]))
205 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_TOOL_CHAIN_TAG
] = list(set(self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_TOOL_CHAIN_TAG
]))
206 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_TARGET_ARCH
] = list(set(self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_TARGET_ARCH
]))
207 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_COMMAND_TYPE
] = list(set(self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_COMMAND_TYPE
]))
209 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_TARGET
].sort()
210 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_TOOL_CHAIN_TAG
].sort()
211 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_TARGET_ARCH
].sort()
212 self
.ToolsDefTxtDatabase
[TAB_TOD_DEFINES_COMMAND_TYPE
].sort()
214 KeyList
= [TAB_TOD_DEFINES_TARGET
, TAB_TOD_DEFINES_TOOL_CHAIN_TAG
, TAB_TOD_DEFINES_TARGET_ARCH
, TAB_TOD_DEFINES_COMMAND_TYPE
]
215 for Index
in range(3, -1, -1):
216 for Key
in dict(self
.ToolsDefTxtDictionary
):
217 List
= Key
.split('_')
218 if List
[Index
] == '*':
219 for String
in self
.ToolsDefTxtDatabase
[KeyList
[Index
]]:
221 NewKey
= '%s_%s_%s_%s_%s' % tuple(List
)
222 if NewKey
not in self
.ToolsDefTxtDictionary
:
223 self
.ToolsDefTxtDictionary
[NewKey
] = self
.ToolsDefTxtDictionary
[Key
]
225 del self
.ToolsDefTxtDictionary
[Key
]
226 elif List
[Index
] not in self
.ToolsDefTxtDatabase
[KeyList
[Index
]]:
227 del self
.ToolsDefTxtDictionary
[Key
]
231 # Replace defined macros with real value
233 # @param Value: The string with unreplaced macros
235 # @retval Value: The string which has been replaced with real value
237 def ExpandMacros(self
, Value
):
238 EnvReference
= gEnvRefPattern
.findall(Value
)
239 for Ref
in EnvReference
:
240 if Ref
not in self
.MacroDictionary
:
241 Value
= Value
.replace(Ref
, "")
243 Value
= Value
.replace(Ref
, self
.MacroDictionary
[Ref
])
246 MacroReference
= gMacroRefPattern
.findall(Value
)
247 for Ref
in MacroReference
:
248 if Ref
not in self
.MacroDictionary
:
250 Value
= Value
.replace(Ref
, self
.MacroDictionary
[Ref
])
256 # Load tools_def.txt in input Conf dir
258 # @param ConfDir: Conf dir
260 # @retval ToolDef An instance of ToolDefClassObject() with loaded tools_def.txt
262 def ToolDefDict(ConfDir
):
263 Target
= TargetTxtDict(ConfDir
)
264 ToolDef
= ToolDefClassObject()
265 if DataType
.TAB_TAT_DEFINES_TOOL_CHAIN_CONF
in Target
.TargetTxtDictionary
:
266 ToolsDefFile
= Target
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TOOL_CHAIN_CONF
]
268 ToolDef
.LoadToolDefFile(os
.path
.normpath(ToolsDefFile
))
270 ToolDef
.LoadToolDefFile(os
.path
.normpath(os
.path
.join(ConfDir
, gDefaultToolsDefFile
)))
272 ToolDef
.LoadToolDefFile(os
.path
.normpath(os
.path
.join(ConfDir
, gDefaultToolsDefFile
)))
277 # This acts like the main() function for the script, unless it is 'import'ed into another
280 if __name__
== '__main__':
281 ToolDef
= ToolDefDict(os
.getenv("WORKSPACE"))