]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/AutoGen/GenDepex.py
BaseTools: Replace BSD License with BSD+Patent License
[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
2e351cbe 5# SPDX-License-Identifier: BSD-2-Clause-Patent\r
30fdf114
LG
6\r
7## Import Modules\r
8#\r
9import sys\r
1be2ed90 10import Common.LongFilePathOs as os\r
30fdf114
LG
11import re\r
12import traceback\r
1be2ed90 13from Common.LongFilePathSupport import OpenLongFilePath as open\r
86379ac4 14from io import BytesIO\r
30fdf114
LG
15from struct import pack\r
16from Common.BuildToolError import *\r
17from Common.Misc import SaveFileOnChange\r
18from Common.Misc import GuidStructureStringToGuidString\r
a10def91
YF
19from Common.Misc import GuidStructureByteArrayToGuidString\r
20from Common.Misc import GuidStringToGuidStructureString\r
30fdf114 21from Common import EdkLogger as EdkLogger\r
b36d134f 22from Common.BuildVersion import gBUILD_VERSION\r
8bb63e37 23from Common.DataType import *\r
30fdf114
LG
24\r
25## Regular expression for matching "DEPENDENCY_START ... DEPENDENCY_END"\r
26gStartClosePattern = re.compile(".*DEPENDENCY_START(.+)DEPENDENCY_END.*", re.S)\r
27\r
28## Mapping between module type and EFI phase\r
29gType2Phase = {\r
8bb63e37
CJ
30 SUP_MODULE_BASE : None,\r
31 SUP_MODULE_SEC : "PEI",\r
32 SUP_MODULE_PEI_CORE : "PEI",\r
33 SUP_MODULE_PEIM : "PEI",\r
34 SUP_MODULE_DXE_CORE : "DXE",\r
35 SUP_MODULE_DXE_DRIVER : "DXE",\r
36 SUP_MODULE_DXE_SMM_DRIVER : "DXE",\r
37 SUP_MODULE_DXE_RUNTIME_DRIVER: "DXE",\r
38 SUP_MODULE_DXE_SAL_DRIVER : "DXE",\r
39 SUP_MODULE_UEFI_DRIVER : "DXE",\r
40 SUP_MODULE_UEFI_APPLICATION : "DXE",\r
41 SUP_MODULE_SMM_CORE : "DXE",\r
42 SUP_MODULE_MM_STANDALONE : "MM",\r
43 SUP_MODULE_MM_CORE_STANDALONE : "MM",\r
30fdf114
LG
44}\r
45\r
46## Convert dependency expression string into EFI internal representation\r
47#\r
48# DependencyExpression class is used to parse dependency expression string and\r
49# convert it into its binary form.\r
50#\r
51class DependencyExpression:\r
52\r
c5c7e68a 53 ArchProtocols = {\r
30fdf114
LG
54 '665e3ff6-46cc-11d4-9a38-0090273fc14d', # 'gEfiBdsArchProtocolGuid'\r
55 '26baccb1-6f42-11d4-bce7-0080c73c8881', # 'gEfiCpuArchProtocolGuid'\r
56 '26baccb2-6f42-11d4-bce7-0080c73c8881', # 'gEfiMetronomeArchProtocolGuid'\r
57 '1da97072-bddc-4b30-99f1-72a0b56fff2a', # 'gEfiMonotonicCounterArchProtocolGuid'\r
58 '27cfac87-46cc-11d4-9a38-0090273fc14d', # 'gEfiRealTimeClockArchProtocolGuid'\r
59 '27cfac88-46cc-11d4-9a38-0090273fc14d', # 'gEfiResetArchProtocolGuid'\r
60 'b7dfb4e1-052f-449f-87be-9818fc91b733', # 'gEfiRuntimeArchProtocolGuid'\r
61 'a46423e3-4617-49f1-b9ff-d1bfa9115839', # 'gEfiSecurityArchProtocolGuid'\r
62 '26baccb3-6f42-11d4-bce7-0080c73c8881', # 'gEfiTimerArchProtocolGuid'\r
63 '6441f818-6362-4e44-b570-7dba31dd2453', # 'gEfiVariableWriteArchProtocolGuid'\r
64 '1e5668e2-8481-11d4-bcf1-0080c73c8881', # 'gEfiVariableArchProtocolGuid'\r
65 '665e3ff5-46cc-11d4-9a38-0090273fc14d' # 'gEfiWatchdogTimerArchProtocolGuid'\r
c5c7e68a 66 }\r
30fdf114
LG
67\r
68 OpcodePriority = {\r
31ff1c44
CJ
69 DEPEX_OPCODE_AND : 1,\r
70 DEPEX_OPCODE_OR : 1,\r
71 DEPEX_OPCODE_NOT : 2,\r
30fdf114
LG
72 }\r
73\r
74 Opcode = {\r
75 "PEI" : {\r
31ff1c44
CJ
76 DEPEX_OPCODE_PUSH : 0x02,\r
77 DEPEX_OPCODE_AND : 0x03,\r
78 DEPEX_OPCODE_OR : 0x04,\r
79 DEPEX_OPCODE_NOT : 0x05,\r
80 DEPEX_OPCODE_TRUE : 0x06,\r
81 DEPEX_OPCODE_FALSE : 0x07,\r
82 DEPEX_OPCODE_END : 0x08\r
30fdf114
LG
83 },\r
84\r
85 "DXE" : {\r
31ff1c44
CJ
86 DEPEX_OPCODE_BEFORE: 0x00,\r
87 DEPEX_OPCODE_AFTER : 0x01,\r
88 DEPEX_OPCODE_PUSH : 0x02,\r
89 DEPEX_OPCODE_AND : 0x03,\r
90 DEPEX_OPCODE_OR : 0x04,\r
91 DEPEX_OPCODE_NOT : 0x05,\r
92 DEPEX_OPCODE_TRUE : 0x06,\r
93 DEPEX_OPCODE_FALSE : 0x07,\r
94 DEPEX_OPCODE_END : 0x08,\r
95 DEPEX_OPCODE_SOR : 0x09\r
5a9c3e3e
SV
96 },\r
97\r
98 "MM" : {\r
31ff1c44
CJ
99 DEPEX_OPCODE_BEFORE: 0x00,\r
100 DEPEX_OPCODE_AFTER : 0x01,\r
101 DEPEX_OPCODE_PUSH : 0x02,\r
102 DEPEX_OPCODE_AND : 0x03,\r
103 DEPEX_OPCODE_OR : 0x04,\r
104 DEPEX_OPCODE_NOT : 0x05,\r
105 DEPEX_OPCODE_TRUE : 0x06,\r
106 DEPEX_OPCODE_FALSE : 0x07,\r
107 DEPEX_OPCODE_END : 0x08,\r
108 DEPEX_OPCODE_SOR : 0x09\r
30fdf114
LG
109 }\r
110 }\r
111\r
112 # all supported op codes and operands\r
31ff1c44
CJ
113 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
114 SupportedOperand = [DEPEX_OPCODE_TRUE, DEPEX_OPCODE_FALSE]\r
30fdf114 115\r
31ff1c44
CJ
116 OpcodeWithSingleOperand = [DEPEX_OPCODE_NOT, DEPEX_OPCODE_BEFORE, DEPEX_OPCODE_AFTER]\r
117 OpcodeWithTwoOperand = [DEPEX_OPCODE_AND, DEPEX_OPCODE_OR]\r
30fdf114
LG
118\r
119 # op code that should not be the last one\r
31ff1c44 120 NonEndingOpcode = [DEPEX_OPCODE_AND, DEPEX_OPCODE_OR, DEPEX_OPCODE_NOT, DEPEX_OPCODE_SOR]\r
30fdf114 121 # op code must not present at the same time\r
31ff1c44 122 ExclusiveOpcode = [DEPEX_OPCODE_BEFORE, DEPEX_OPCODE_AFTER]\r
30fdf114 123 # op code that should be the first one if it presents\r
31ff1c44 124 AboveAllOpcode = [DEPEX_OPCODE_SOR, DEPEX_OPCODE_BEFORE, DEPEX_OPCODE_AFTER]\r
30fdf114
LG
125\r
126 #\r
127 # open and close brace must be taken as individual tokens\r
128 #\r
129 TokenPattern = re.compile("(\(|\)|\{[^{}]+\{?[^{}]+\}?[ ]*\}|\w+)")\r
130\r
131 ## Constructor\r
132 #\r
133 # @param Expression The list or string of dependency expression\r
134 # @param ModuleType The type of the module using the dependency expression\r
135 #\r
136 def __init__(self, Expression, ModuleType, Optimize=False):\r
137 self.ModuleType = ModuleType\r
138 self.Phase = gType2Phase[ModuleType]\r
0d1f5b2b 139 if isinstance(Expression, type([])):\r
30fdf114
LG
140 self.ExpressionString = " ".join(Expression)\r
141 self.TokenList = Expression\r
142 else:\r
143 self.ExpressionString = Expression\r
144 self.GetExpressionTokenList()\r
145\r
146 self.PostfixNotation = []\r
147 self.OpcodeList = []\r
148\r
149 self.GetPostfixNotation()\r
150 self.ValidateOpcode()\r
151\r
152 EdkLogger.debug(EdkLogger.DEBUG_8, repr(self))\r
153 if Optimize:\r
154 self.Optimize()\r
155 EdkLogger.debug(EdkLogger.DEBUG_8, "\n Optimized: " + repr(self))\r
156\r
157 def __str__(self):\r
158 return " ".join(self.TokenList)\r
159\r
160 def __repr__(self):\r
161 WellForm = ''\r
162 for Token in self.PostfixNotation:\r
163 if Token in self.SupportedOpcode:\r
164 WellForm += "\n " + Token\r
165 else:\r
166 WellForm += ' ' + Token\r
167 return WellForm\r
168\r
169 ## Split the expression string into token list\r
170 def GetExpressionTokenList(self):\r
171 self.TokenList = self.TokenPattern.findall(self.ExpressionString)\r
172\r
173 ## Convert token list into postfix notation\r
174 def GetPostfixNotation(self):\r
175 Stack = []\r
176 LastToken = ''\r
177 for Token in self.TokenList:\r
178 if Token == "(":\r
179 if LastToken not in self.SupportedOpcode + ['(', '', None]:\r
180 EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operator before open parentheses",\r
181 ExtraData="Near %s" % LastToken)\r
182 Stack.append(Token)\r
183 elif Token == ")":\r
184 if '(' not in Stack:\r
185 EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: mismatched parentheses",\r
186 ExtraData=str(self))\r
187 elif LastToken in self.SupportedOpcode + ['', None]:\r
188 EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operand before close parentheses",\r
189 ExtraData="Near %s" % LastToken)\r
190 while len(Stack) > 0:\r
191 if Stack[-1] == '(':\r
192 Stack.pop()\r
193 break\r
194 self.PostfixNotation.append(Stack.pop())\r
195 elif Token in self.OpcodePriority:\r
31ff1c44 196 if Token == DEPEX_OPCODE_NOT:\r
30fdf114
LG
197 if LastToken not in self.SupportedOpcode + ['(', '', None]:\r
198 EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operator before NOT",\r
199 ExtraData="Near %s" % LastToken)\r
200 elif LastToken in self.SupportedOpcode + ['(', '', None]:\r
201 EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operand before " + Token,\r
202 ExtraData="Near %s" % LastToken)\r
203\r
204 while len(Stack) > 0:\r
205 if Stack[-1] == "(" or self.OpcodePriority[Token] >= self.OpcodePriority[Stack[-1]]:\r
206 break\r
207 self.PostfixNotation.append(Stack.pop())\r
208 Stack.append(Token)\r
209 self.OpcodeList.append(Token)\r
210 else:\r
211 if Token not in self.SupportedOpcode:\r
212 # not OP, take it as GUID\r
213 if LastToken not in self.SupportedOpcode + ['(', '', None]:\r
214 EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operator before %s" % Token,\r
215 ExtraData="Near %s" % LastToken)\r
216 if len(self.OpcodeList) == 0 or self.OpcodeList[-1] not in self.ExclusiveOpcode:\r
217 if Token not in self.SupportedOperand:\r
31ff1c44 218 self.PostfixNotation.append(DEPEX_OPCODE_PUSH)\r
30fdf114
LG
219 # check if OP is valid in this phase\r
220 elif Token in self.Opcode[self.Phase]:\r
31ff1c44 221 if Token == DEPEX_OPCODE_END:\r
30fdf114
LG
222 break\r
223 self.OpcodeList.append(Token)\r
224 else:\r
225 EdkLogger.error("GenDepex", PARSER_ERROR,\r
226 "Opcode=%s doesn't supported in %s stage " % (Token, self.Phase),\r
227 ExtraData=str(self))\r
228 self.PostfixNotation.append(Token)\r
229 LastToken = Token\r
230\r
231 # there should not be parentheses in Stack\r
232 if '(' in Stack or ')' in Stack:\r
233 EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: mismatched parentheses",\r
234 ExtraData=str(self))\r
235 while len(Stack) > 0:\r
236 self.PostfixNotation.append(Stack.pop())\r
31ff1c44
CJ
237 if self.PostfixNotation[-1] != DEPEX_OPCODE_END:\r
238 self.PostfixNotation.append(DEPEX_OPCODE_END)\r
30fdf114
LG
239\r
240 ## Validate the dependency expression\r
241 def ValidateOpcode(self):\r
242 for Op in self.AboveAllOpcode:\r
243 if Op in self.PostfixNotation:\r
244 if Op != self.PostfixNotation[0]:\r
245 EdkLogger.error("GenDepex", PARSER_ERROR, "%s should be the first opcode in the expression" % Op,\r
246 ExtraData=str(self))\r
247 if len(self.PostfixNotation) < 3:\r
248 EdkLogger.error("GenDepex", PARSER_ERROR, "Missing operand for %s" % Op,\r
249 ExtraData=str(self))\r
250 for Op in self.ExclusiveOpcode:\r
251 if Op in self.OpcodeList:\r
252 if len(self.OpcodeList) > 1:\r
253 EdkLogger.error("GenDepex", PARSER_ERROR, "%s should be the only opcode in the expression" % Op,\r
254 ExtraData=str(self))\r
255 if len(self.PostfixNotation) < 3:\r
256 EdkLogger.error("GenDepex", PARSER_ERROR, "Missing operand for %s" % Op,\r
257 ExtraData=str(self))\r
31ff1c44 258 if self.TokenList[-1] != DEPEX_OPCODE_END and self.TokenList[-1] in self.NonEndingOpcode:\r
30fdf114
LG
259 EdkLogger.error("GenDepex", PARSER_ERROR, "Extra %s at the end of the dependency expression" % self.TokenList[-1],\r
260 ExtraData=str(self))\r
31ff1c44 261 if self.TokenList[-1] == DEPEX_OPCODE_END and self.TokenList[-2] in self.NonEndingOpcode:\r
30fdf114
LG
262 EdkLogger.error("GenDepex", PARSER_ERROR, "Extra %s at the end of the dependency expression" % self.TokenList[-2],\r
263 ExtraData=str(self))\r
31ff1c44 264 if DEPEX_OPCODE_END in self.TokenList and DEPEX_OPCODE_END != self.TokenList[-1]:\r
30fdf114
LG
265 EdkLogger.error("GenDepex", PARSER_ERROR, "Extra expressions after END",\r
266 ExtraData=str(self))\r
267\r
268 ## Simply optimize the dependency expression by removing duplicated operands\r
269 def Optimize(self):\r
cf306290
CJ
270 OpcodeSet = set(self.OpcodeList)\r
271 # if there are isn't one in the set, return\r
272 if len(OpcodeSet) != 1:\r
273 return\r
274 Op = OpcodeSet.pop()\r
275 #if Op isn't either OR or AND, return\r
276 if Op not in [DEPEX_OPCODE_AND, DEPEX_OPCODE_OR]:\r
30fdf114 277 return\r
30fdf114
LG
278 NewOperand = []\r
279 AllOperand = set()\r
280 for Token in self.PostfixNotation:\r
281 if Token in self.SupportedOpcode or Token in NewOperand:\r
282 continue\r
283 AllOperand.add(Token)\r
31ff1c44
CJ
284 if Token == DEPEX_OPCODE_TRUE:\r
285 if Op == DEPEX_OPCODE_AND:\r
30fdf114
LG
286 continue\r
287 else:\r
288 NewOperand.append(Token)\r
289 break\r
31ff1c44
CJ
290 elif Token == DEPEX_OPCODE_FALSE:\r
291 if Op == DEPEX_OPCODE_OR:\r
30fdf114
LG
292 continue\r
293 else:\r
294 NewOperand.append(Token)\r
295 break\r
296 NewOperand.append(Token)\r
297\r
298 # don't generate depex if only TRUE operand left\r
31ff1c44 299 if self.ModuleType == SUP_MODULE_PEIM and len(NewOperand) == 1 and NewOperand[0] == DEPEX_OPCODE_TRUE:\r
30fdf114 300 self.PostfixNotation = []\r
47fea6af 301 return\r
30fdf114
LG
302\r
303 # don't generate depex if all operands are architecture protocols\r
8bb63e37 304 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 305 Op == DEPEX_OPCODE_AND and \\r
c5c7e68a 306 self.ArchProtocols == set(GuidStructureStringToGuidString(Guid) for Guid in AllOperand):\r
30fdf114
LG
307 self.PostfixNotation = []\r
308 return\r
309\r
310 if len(NewOperand) == 0:\r
311 self.TokenList = list(AllOperand)\r
312 else:\r
313 self.TokenList = []\r
314 while True:\r
315 self.TokenList.append(NewOperand.pop(0))\r
316 if NewOperand == []:\r
317 break\r
318 self.TokenList.append(Op)\r
319 self.PostfixNotation = []\r
320 self.GetPostfixNotation()\r
321\r
322\r
323 ## Convert a GUID value in C structure format into its binary form\r
324 #\r
325 # @param Guid The GUID value in C structure format\r
326 #\r
327 # @retval array The byte array representing the GUID value\r
328 #\r
329 def GetGuidValue(self, Guid):\r
330 GuidValueString = Guid.replace("{", "").replace("}", "").replace(" ", "")\r
331 GuidValueList = GuidValueString.split(",")\r
a10def91
YF
332 if len(GuidValueList) != 11 and len(GuidValueList) == 16:\r
333 GuidValueString = GuidStringToGuidStructureString(GuidStructureByteArrayToGuidString(Guid))\r
334 GuidValueString = GuidValueString.replace("{", "").replace("}", "").replace(" ", "")\r
335 GuidValueList = GuidValueString.split(",")\r
30fdf114
LG
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