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