]>
Commit | Line | Data |
---|---|---|
30fdf114 LG |
1 | ## @file\r |
2 | # This file is used to generate DEPEX file for module's dependency expression\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 | ## Import Modules\r | |
14 | #\r | |
15 | import sys\r | |
1be2ed90 | 16 | import Common.LongFilePathOs as os\r |
30fdf114 LG |
17 | import re\r |
18 | import traceback\r | |
1be2ed90 | 19 | from Common.LongFilePathSupport import OpenLongFilePath as open\r |
30fdf114 LG |
20 | from StringIO import StringIO\r |
21 | from struct import pack\r | |
22 | from Common.BuildToolError import *\r | |
23 | from Common.Misc import SaveFileOnChange\r | |
24 | from Common.Misc import GuidStructureStringToGuidString\r | |
25 | from Common import EdkLogger as EdkLogger\r | |
b36d134f | 26 | from Common.BuildVersion import gBUILD_VERSION\r |
30fdf114 LG |
27 | \r |
28 | ## Regular expression for matching "DEPENDENCY_START ... DEPENDENCY_END"\r | |
29 | gStartClosePattern = re.compile(".*DEPENDENCY_START(.+)DEPENDENCY_END.*", re.S)\r | |
30 | \r | |
31 | ## Mapping between module type and EFI phase\r | |
32 | gType2Phase = {\r | |
33 | "BASE" : None,\r | |
34 | "SEC" : "PEI",\r | |
35 | "PEI_CORE" : "PEI",\r | |
36 | "PEIM" : "PEI",\r | |
37 | "DXE_CORE" : "DXE",\r | |
38 | "DXE_DRIVER" : "DXE",\r | |
39 | "DXE_SMM_DRIVER" : "DXE",\r | |
40 | "DXE_RUNTIME_DRIVER": "DXE",\r | |
41 | "DXE_SAL_DRIVER" : "DXE",\r | |
42 | "UEFI_DRIVER" : "DXE",\r | |
43 | "UEFI_APPLICATION" : "DXE",\r | |
b303ea72 | 44 | "SMM_CORE" : "DXE",\r |
5a9c3e3e SV |
45 | "MM_STANDALONE" : "MM",\r |
46 | "MM_CORE_STANDALONE" : "MM",\r | |
30fdf114 LG |
47 | }\r |
48 | \r | |
49 | ## Convert dependency expression string into EFI internal representation\r | |
50 | #\r | |
51 | # DependencyExpression class is used to parse dependency expression string and\r | |
52 | # convert it into its binary form.\r | |
53 | #\r | |
54 | class DependencyExpression:\r | |
55 | \r | |
56 | ArchProtocols = set([\r | |
57 | '665e3ff6-46cc-11d4-9a38-0090273fc14d', # 'gEfiBdsArchProtocolGuid'\r | |
58 | '26baccb1-6f42-11d4-bce7-0080c73c8881', # 'gEfiCpuArchProtocolGuid'\r | |
59 | '26baccb2-6f42-11d4-bce7-0080c73c8881', # 'gEfiMetronomeArchProtocolGuid'\r | |
60 | '1da97072-bddc-4b30-99f1-72a0b56fff2a', # 'gEfiMonotonicCounterArchProtocolGuid'\r | |
61 | '27cfac87-46cc-11d4-9a38-0090273fc14d', # 'gEfiRealTimeClockArchProtocolGuid'\r | |
62 | '27cfac88-46cc-11d4-9a38-0090273fc14d', # 'gEfiResetArchProtocolGuid'\r | |
63 | 'b7dfb4e1-052f-449f-87be-9818fc91b733', # 'gEfiRuntimeArchProtocolGuid'\r | |
64 | 'a46423e3-4617-49f1-b9ff-d1bfa9115839', # 'gEfiSecurityArchProtocolGuid'\r | |
65 | '26baccb3-6f42-11d4-bce7-0080c73c8881', # 'gEfiTimerArchProtocolGuid'\r | |
66 | '6441f818-6362-4e44-b570-7dba31dd2453', # 'gEfiVariableWriteArchProtocolGuid'\r | |
67 | '1e5668e2-8481-11d4-bcf1-0080c73c8881', # 'gEfiVariableArchProtocolGuid'\r | |
68 | '665e3ff5-46cc-11d4-9a38-0090273fc14d' # 'gEfiWatchdogTimerArchProtocolGuid'\r | |
69 | ]\r | |
70 | )\r | |
71 | \r | |
72 | OpcodePriority = {\r | |
73 | "AND" : 1,\r | |
74 | "OR" : 1,\r | |
75 | "NOT" : 2,\r | |
76 | # "SOR" : 9,\r | |
77 | # "BEFORE": 9,\r | |
78 | # "AFTER" : 9,\r | |
79 | }\r | |
80 | \r | |
81 | Opcode = {\r | |
82 | "PEI" : {\r | |
83 | "PUSH" : 0x02,\r | |
84 | "AND" : 0x03,\r | |
85 | "OR" : 0x04,\r | |
86 | "NOT" : 0x05,\r | |
87 | "TRUE" : 0x06,\r | |
88 | "FALSE" : 0x07,\r | |
89 | "END" : 0x08\r | |
90 | },\r | |
91 | \r | |
92 | "DXE" : {\r | |
93 | "BEFORE": 0x00,\r | |
94 | "AFTER" : 0x01,\r | |
95 | "PUSH" : 0x02,\r | |
96 | "AND" : 0x03,\r | |
97 | "OR" : 0x04,\r | |
98 | "NOT" : 0x05,\r | |
99 | "TRUE" : 0x06,\r | |
100 | "FALSE" : 0x07,\r | |
101 | "END" : 0x08,\r | |
102 | "SOR" : 0x09\r | |
5a9c3e3e SV |
103 | },\r |
104 | \r | |
105 | "MM" : {\r | |
106 | "BEFORE": 0x00,\r | |
107 | "AFTER" : 0x01,\r | |
108 | "PUSH" : 0x02,\r | |
109 | "AND" : 0x03,\r | |
110 | "OR" : 0x04,\r | |
111 | "NOT" : 0x05,\r | |
112 | "TRUE" : 0x06,\r | |
113 | "FALSE" : 0x07,\r | |
114 | "END" : 0x08,\r | |
115 | "SOR" : 0x09\r | |
30fdf114 LG |
116 | }\r |
117 | }\r | |
118 | \r | |
119 | # all supported op codes and operands\r | |
120 | SupportedOpcode = ["BEFORE", "AFTER", "PUSH", "AND", "OR", "NOT", "END", "SOR"]\r | |
121 | SupportedOperand = ["TRUE", "FALSE"]\r | |
122 | \r | |
123 | OpcodeWithSingleOperand = ['NOT', 'BEFORE', 'AFTER']\r | |
124 | OpcodeWithTwoOperand = ['AND', 'OR']\r | |
125 | \r | |
126 | # op code that should not be the last one\r | |
127 | NonEndingOpcode = ["AND", "OR", "NOT", 'SOR']\r | |
128 | # op code must not present at the same time\r | |
129 | ExclusiveOpcode = ["BEFORE", "AFTER"]\r | |
130 | # op code that should be the first one if it presents\r | |
131 | AboveAllOpcode = ["SOR", "BEFORE", "AFTER"]\r | |
132 | \r | |
133 | #\r | |
134 | # open and close brace must be taken as individual tokens\r | |
135 | #\r | |
136 | TokenPattern = re.compile("(\(|\)|\{[^{}]+\{?[^{}]+\}?[ ]*\}|\w+)")\r | |
137 | \r | |
138 | ## Constructor\r | |
139 | #\r | |
140 | # @param Expression The list or string of dependency expression\r | |
141 | # @param ModuleType The type of the module using the dependency expression\r | |
142 | #\r | |
143 | def __init__(self, Expression, ModuleType, Optimize=False):\r | |
144 | self.ModuleType = ModuleType\r | |
145 | self.Phase = gType2Phase[ModuleType]\r | |
146 | if type(Expression) == type([]):\r | |
147 | self.ExpressionString = " ".join(Expression)\r | |
148 | self.TokenList = Expression\r | |
149 | else:\r | |
150 | self.ExpressionString = Expression\r | |
151 | self.GetExpressionTokenList()\r | |
152 | \r | |
153 | self.PostfixNotation = []\r | |
154 | self.OpcodeList = []\r | |
155 | \r | |
156 | self.GetPostfixNotation()\r | |
157 | self.ValidateOpcode()\r | |
158 | \r | |
159 | EdkLogger.debug(EdkLogger.DEBUG_8, repr(self))\r | |
160 | if Optimize:\r | |
161 | self.Optimize()\r | |
162 | EdkLogger.debug(EdkLogger.DEBUG_8, "\n Optimized: " + repr(self))\r | |
163 | \r | |
164 | def __str__(self):\r | |
165 | return " ".join(self.TokenList)\r | |
166 | \r | |
167 | def __repr__(self):\r | |
168 | WellForm = ''\r | |
169 | for Token in self.PostfixNotation:\r | |
170 | if Token in self.SupportedOpcode:\r | |
171 | WellForm += "\n " + Token\r | |
172 | else:\r | |
173 | WellForm += ' ' + Token\r | |
174 | return WellForm\r | |
175 | \r | |
176 | ## Split the expression string into token list\r | |
177 | def GetExpressionTokenList(self):\r | |
178 | self.TokenList = self.TokenPattern.findall(self.ExpressionString)\r | |
179 | \r | |
180 | ## Convert token list into postfix notation\r | |
181 | def GetPostfixNotation(self):\r | |
182 | Stack = []\r | |
183 | LastToken = ''\r | |
184 | for Token in self.TokenList:\r | |
185 | if Token == "(":\r | |
186 | if LastToken not in self.SupportedOpcode + ['(', '', None]:\r | |
187 | EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operator before open parentheses",\r | |
188 | ExtraData="Near %s" % LastToken)\r | |
189 | Stack.append(Token)\r | |
190 | elif Token == ")":\r | |
191 | if '(' not in Stack:\r | |
192 | EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: mismatched parentheses",\r | |
193 | ExtraData=str(self))\r | |
194 | elif LastToken in self.SupportedOpcode + ['', None]:\r | |
195 | EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operand before close parentheses",\r | |
196 | ExtraData="Near %s" % LastToken)\r | |
197 | while len(Stack) > 0:\r | |
198 | if Stack[-1] == '(':\r | |
199 | Stack.pop()\r | |
200 | break\r | |
201 | self.PostfixNotation.append(Stack.pop())\r | |
202 | elif Token in self.OpcodePriority:\r | |
203 | if Token == "NOT":\r | |
204 | if LastToken not in self.SupportedOpcode + ['(', '', None]:\r | |
205 | EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operator before NOT",\r | |
206 | ExtraData="Near %s" % LastToken)\r | |
207 | elif LastToken in self.SupportedOpcode + ['(', '', None]:\r | |
208 | EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operand before " + Token,\r | |
209 | ExtraData="Near %s" % LastToken)\r | |
210 | \r | |
211 | while len(Stack) > 0:\r | |
212 | if Stack[-1] == "(" or self.OpcodePriority[Token] >= self.OpcodePriority[Stack[-1]]:\r | |
213 | break\r | |
214 | self.PostfixNotation.append(Stack.pop())\r | |
215 | Stack.append(Token)\r | |
216 | self.OpcodeList.append(Token)\r | |
217 | else:\r | |
218 | if Token not in self.SupportedOpcode:\r | |
219 | # not OP, take it as GUID\r | |
220 | if LastToken not in self.SupportedOpcode + ['(', '', None]:\r | |
221 | EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operator before %s" % Token,\r | |
222 | ExtraData="Near %s" % LastToken)\r | |
223 | if len(self.OpcodeList) == 0 or self.OpcodeList[-1] not in self.ExclusiveOpcode:\r | |
224 | if Token not in self.SupportedOperand:\r | |
225 | self.PostfixNotation.append("PUSH")\r | |
226 | # check if OP is valid in this phase\r | |
227 | elif Token in self.Opcode[self.Phase]:\r | |
228 | if Token == "END":\r | |
229 | break\r | |
230 | self.OpcodeList.append(Token)\r | |
231 | else:\r | |
232 | EdkLogger.error("GenDepex", PARSER_ERROR,\r | |
233 | "Opcode=%s doesn't supported in %s stage " % (Token, self.Phase),\r | |
234 | ExtraData=str(self))\r | |
235 | self.PostfixNotation.append(Token)\r | |
236 | LastToken = Token\r | |
237 | \r | |
238 | # there should not be parentheses in Stack\r | |
239 | if '(' in Stack or ')' in Stack:\r | |
240 | EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: mismatched parentheses",\r | |
241 | ExtraData=str(self))\r | |
242 | while len(Stack) > 0:\r | |
243 | self.PostfixNotation.append(Stack.pop())\r | |
244 | if self.PostfixNotation[-1] != 'END':\r | |
245 | self.PostfixNotation.append("END")\r | |
246 | \r | |
247 | ## Validate the dependency expression\r | |
248 | def ValidateOpcode(self):\r | |
249 | for Op in self.AboveAllOpcode:\r | |
250 | if Op in self.PostfixNotation:\r | |
251 | if Op != self.PostfixNotation[0]:\r | |
252 | EdkLogger.error("GenDepex", PARSER_ERROR, "%s should be the first opcode in the expression" % Op,\r | |
253 | ExtraData=str(self))\r | |
254 | if len(self.PostfixNotation) < 3:\r | |
255 | EdkLogger.error("GenDepex", PARSER_ERROR, "Missing operand for %s" % Op,\r | |
256 | ExtraData=str(self))\r | |
257 | for Op in self.ExclusiveOpcode:\r | |
258 | if Op in self.OpcodeList:\r | |
259 | if len(self.OpcodeList) > 1:\r | |
260 | EdkLogger.error("GenDepex", PARSER_ERROR, "%s should be the only opcode in the expression" % Op,\r | |
261 | ExtraData=str(self))\r | |
262 | if len(self.PostfixNotation) < 3:\r | |
263 | EdkLogger.error("GenDepex", PARSER_ERROR, "Missing operand for %s" % Op,\r | |
264 | ExtraData=str(self))\r | |
265 | if self.TokenList[-1] != 'END' and self.TokenList[-1] in self.NonEndingOpcode:\r | |
266 | EdkLogger.error("GenDepex", PARSER_ERROR, "Extra %s at the end of the dependency expression" % self.TokenList[-1],\r | |
267 | ExtraData=str(self))\r | |
268 | if self.TokenList[-1] == 'END' and self.TokenList[-2] in self.NonEndingOpcode:\r | |
269 | EdkLogger.error("GenDepex", PARSER_ERROR, "Extra %s at the end of the dependency expression" % self.TokenList[-2],\r | |
270 | ExtraData=str(self))\r | |
271 | if "END" in self.TokenList and "END" != self.TokenList[-1]:\r | |
272 | EdkLogger.error("GenDepex", PARSER_ERROR, "Extra expressions after END",\r | |
273 | ExtraData=str(self))\r | |
274 | \r | |
275 | ## Simply optimize the dependency expression by removing duplicated operands\r | |
276 | def Optimize(self):\r | |
277 | ValidOpcode = list(set(self.OpcodeList))\r | |
278 | if len(ValidOpcode) != 1 or ValidOpcode[0] not in ['AND', 'OR']:\r | |
279 | return\r | |
280 | Op = ValidOpcode[0]\r | |
281 | NewOperand = []\r | |
282 | AllOperand = set()\r | |
283 | for Token in self.PostfixNotation:\r | |
284 | if Token in self.SupportedOpcode or Token in NewOperand:\r | |
285 | continue\r | |
286 | AllOperand.add(Token)\r | |
287 | if Token == 'TRUE':\r | |
288 | if Op == 'AND':\r | |
289 | continue\r | |
290 | else:\r | |
291 | NewOperand.append(Token)\r | |
292 | break\r | |
293 | elif Token == 'FALSE':\r | |
294 | if Op == 'OR':\r | |
295 | continue\r | |
296 | else:\r | |
297 | NewOperand.append(Token)\r | |
298 | break\r | |
299 | NewOperand.append(Token)\r | |
300 | \r | |
301 | # don't generate depex if only TRUE operand left\r | |
302 | if self.ModuleType == 'PEIM' and len(NewOperand) == 1 and NewOperand[0] == 'TRUE':\r | |
303 | self.PostfixNotation = []\r | |
47fea6af | 304 | return\r |
30fdf114 LG |
305 | \r |
306 | # don't generate depex if all operands are architecture protocols\r | |
5a9c3e3e | 307 | if self.ModuleType in ['UEFI_DRIVER', 'DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'DXE_SMM_DRIVER', 'MM_STANDALONE'] and \\r |
30fdf114 LG |
308 | Op == 'AND' and \\r |
309 | self.ArchProtocols == set([GuidStructureStringToGuidString(Guid) for Guid in AllOperand]):\r | |
310 | self.PostfixNotation = []\r | |
311 | return\r | |
312 | \r | |
313 | if len(NewOperand) == 0:\r | |
314 | self.TokenList = list(AllOperand)\r | |
315 | else:\r | |
316 | self.TokenList = []\r | |
317 | while True:\r | |
318 | self.TokenList.append(NewOperand.pop(0))\r | |
319 | if NewOperand == []:\r | |
320 | break\r | |
321 | self.TokenList.append(Op)\r | |
322 | self.PostfixNotation = []\r | |
323 | self.GetPostfixNotation()\r | |
324 | \r | |
325 | \r | |
326 | ## Convert a GUID value in C structure format into its binary form\r | |
327 | #\r | |
328 | # @param Guid The GUID value in C structure format\r | |
329 | #\r | |
330 | # @retval array The byte array representing the GUID value\r | |
331 | #\r | |
332 | def GetGuidValue(self, Guid):\r | |
333 | GuidValueString = Guid.replace("{", "").replace("}", "").replace(" ", "")\r | |
334 | GuidValueList = GuidValueString.split(",")\r | |
335 | if len(GuidValueList) != 11:\r | |
336 | EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid GUID value string or opcode: %s" % Guid)\r | |
337 | return pack("1I2H8B", *(int(value, 16) for value in GuidValueList))\r | |
338 | \r | |
339 | ## Save the binary form of dependency expression in file\r | |
340 | #\r | |
341 | # @param File The path of file. If None is given, put the data on console\r | |
342 | #\r | |
343 | # @retval True If the file doesn't exist or file is changed\r | |
344 | # @retval False If file exists and is not changed.\r | |
345 | #\r | |
346 | def Generate(self, File=None):\r | |
347 | Buffer = StringIO()\r | |
348 | if len(self.PostfixNotation) == 0:\r | |
349 | return False\r | |
350 | \r | |
351 | for Item in self.PostfixNotation:\r | |
352 | if Item in self.Opcode[self.Phase]:\r | |
353 | Buffer.write(pack("B", self.Opcode[self.Phase][Item]))\r | |
354 | elif Item in self.SupportedOpcode:\r | |
355 | EdkLogger.error("GenDepex", FORMAT_INVALID,\r | |
356 | "Opcode [%s] is not expected in %s phase" % (Item, self.Phase),\r | |
357 | ExtraData=self.ExpressionString)\r | |
358 | else:\r | |
359 | Buffer.write(self.GetGuidValue(Item))\r | |
360 | \r | |
361 | FilePath = ""\r | |
362 | FileChangeFlag = True\r | |
363 | if File == None:\r | |
364 | sys.stdout.write(Buffer.getvalue())\r | |
365 | FilePath = "STDOUT"\r | |
366 | else:\r | |
367 | FileChangeFlag = SaveFileOnChange(File, Buffer.getvalue(), True)\r | |
368 | \r | |
369 | Buffer.close()\r | |
370 | return FileChangeFlag\r | |
371 | \r | |
b36d134f | 372 | versionNumber = ("0.04" + " " + gBUILD_VERSION)\r |
30fdf114 | 373 | __version__ = "%prog Version " + versionNumber\r |
52302d4d | 374 | __copyright__ = "Copyright (c) 2007-2010, Intel Corporation All rights reserved."\r |
30fdf114 LG |
375 | __usage__ = "%prog [options] [dependency_expression_file]"\r |
376 | \r | |
377 | ## Parse command line options\r | |
378 | #\r | |
379 | # @retval OptionParser\r | |
380 | #\r | |
381 | def GetOptions():\r | |
382 | from optparse import OptionParser\r | |
383 | \r | |
384 | Parser = OptionParser(description=__copyright__, version=__version__, usage=__usage__)\r | |
385 | \r | |
386 | Parser.add_option("-o", "--output", dest="OutputFile", default=None, metavar="FILE",\r | |
387 | help="Specify the name of depex file to be generated")\r | |
388 | Parser.add_option("-t", "--module-type", dest="ModuleType", default=None,\r | |
389 | help="The type of module for which the dependency expression serves")\r | |
390 | Parser.add_option("-e", "--dependency-expression", dest="Expression", default="",\r | |
391 | help="The string of dependency expression. If this option presents, the input file will be ignored.")\r | |
392 | Parser.add_option("-m", "--optimize", dest="Optimize", default=False, action="store_true",\r | |
393 | help="Do some simple optimization on the expression.")\r | |
394 | Parser.add_option("-v", "--verbose", dest="verbose", default=False, action="store_true",\r | |
395 | help="build with verbose information")\r | |
396 | Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")\r | |
397 | Parser.add_option("-q", "--quiet", dest="quiet", default=False, action="store_true",\r | |
398 | help="build with little information")\r | |
399 | \r | |
400 | return Parser.parse_args()\r | |
401 | \r | |
402 | \r | |
403 | ## Entrance method\r | |
404 | #\r | |
405 | # @retval 0 Tool was successful\r | |
406 | # @retval 1 Tool failed\r | |
407 | #\r | |
408 | def Main():\r | |
409 | EdkLogger.Initialize()\r | |
410 | Option, Input = GetOptions()\r | |
411 | \r | |
412 | # Set log level\r | |
413 | if Option.quiet:\r | |
414 | EdkLogger.SetLevel(EdkLogger.QUIET)\r | |
415 | elif Option.verbose:\r | |
416 | EdkLogger.SetLevel(EdkLogger.VERBOSE)\r | |
417 | elif Option.debug != None:\r | |
418 | EdkLogger.SetLevel(Option.debug + 1)\r | |
419 | else:\r | |
420 | EdkLogger.SetLevel(EdkLogger.INFO)\r | |
421 | \r | |
422 | try:\r | |
423 | if Option.ModuleType == None or Option.ModuleType not in gType2Phase:\r | |
424 | EdkLogger.error("GenDepex", OPTION_MISSING, "Module type is not specified or supported")\r | |
425 | \r | |
426 | DxsFile = ''\r | |
427 | if len(Input) > 0 and Option.Expression == "":\r | |
428 | DxsFile = Input[0]\r | |
429 | DxsString = open(DxsFile, 'r').read().replace("\n", " ").replace("\r", " ")\r | |
430 | DxsString = gStartClosePattern.sub("\\1", DxsString)\r | |
431 | elif Option.Expression != "":\r | |
432 | if Option.Expression[0] == '"':\r | |
433 | DxsString = Option.Expression[1:-1]\r | |
434 | else:\r | |
435 | DxsString = Option.Expression\r | |
436 | else:\r | |
437 | EdkLogger.error("GenDepex", OPTION_MISSING, "No expression string or file given")\r | |
438 | \r | |
439 | Dpx = DependencyExpression(DxsString, Option.ModuleType, Option.Optimize)\r | |
440 | if Option.OutputFile != None:\r | |
14c48571 | 441 | FileChangeFlag = Dpx.Generate(Option.OutputFile)\r |
47fea6af | 442 | if not FileChangeFlag and DxsFile:\r |
14c48571 | 443 | #\r |
444 | # Touch the output file if its time stamp is older than the original\r | |
445 | # DXS file to avoid re-invoke this tool for the dependency check in build rule.\r | |
446 | #\r | |
447 | if os.stat(DxsFile)[8] > os.stat(Option.OutputFile)[8]:\r | |
448 | os.utime(Option.OutputFile, None)\r | |
30fdf114 LG |
449 | else:\r |
450 | Dpx.Generate()\r | |
451 | except BaseException, X:\r | |
452 | EdkLogger.quiet("")\r | |
453 | if Option != None and Option.debug != None:\r | |
454 | EdkLogger.quiet(traceback.format_exc())\r | |
455 | else:\r | |
456 | EdkLogger.quiet(str(X))\r | |
457 | return 1\r | |
458 | \r | |
459 | return 0\r | |
460 | \r | |
461 | if __name__ == '__main__':\r | |
462 | sys.exit(Main())\r | |
463 | \r |