]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/Ecc/Ecc.py
BaseTools: Use absolute import in Ecc
[mirror_edk2.git] / BaseTools / Source / Python / Ecc / Ecc.py
CommitLineData
30fdf114
LG
1## @file\r
2# This file is used to be the main entrance of ECC tool\r
3#\r
f7496d71 4# Copyright (c) 2009 - 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\r
14##\r
15# Import Modules\r
16#\r
b6f6b636 17from __future__ import absolute_import\r
1be2ed90 18import Common.LongFilePathOs as os, time, glob, sys\r
30fdf114 19import Common.EdkLogger as EdkLogger\r
b6f6b636
GL
20from . import Database\r
21from . import EccGlobalData\r
22from .MetaDataParser import *\r
30fdf114 23from optparse import OptionParser\r
b6f6b636
GL
24from .Configuration import Configuration\r
25from .Check import Check\r
9508d0fa 26import Common.GlobalData as GlobalData\r
d0acc87a 27\r
5a57246e 28from Common.StringUtils import NormPath\r
b36d134f 29from Common.BuildVersion import gBUILD_VERSION\r
30fdf114 30from Common import BuildToolError\r
9508d0fa 31from Common.Misc import PathClass\r
64b2609f 32from Common.Misc import DirCache\r
b6f6b636
GL
33from .MetaFileWorkspace.MetaFileParser import DscParser\r
34from .MetaFileWorkspace.MetaFileParser import DecParser\r
35from .MetaFileWorkspace.MetaFileParser import InfParser\r
36from .MetaFileWorkspace.MetaFileParser import Fdf\r
37from .MetaFileWorkspace.MetaFileTable import MetaFileStorage\r
38from . import c\r
fd171542 39import re, string\r
b6f6b636 40from .Exception import *\r
1be2ed90 41from Common.LongFilePathSupport import OpenLongFilePath as open\r
c4f52e12 42from Common.MultipleWorkspace import MultipleWorkspace as mws\r
30fdf114
LG
43\r
44## Ecc\r
45#\r
46# This class is used to define Ecc main entrance\r
47#\r
48# @param object: Inherited from object class\r
49#\r
50class Ecc(object):\r
51 def __init__(self):\r
52 # Version and Copyright\r
45258285 53 self.VersionNumber = ("1.0" + " Build " + gBUILD_VERSION)\r
30fdf114 54 self.Version = "%prog Version " + self.VersionNumber\r
f7496d71 55 self.Copyright = "Copyright (c) 2009 - 2018, Intel Corporation All rights reserved."\r
30fdf114
LG
56\r
57 self.InitDefaultConfigIni()\r
58 self.OutputFile = 'output.txt'\r
59 self.ReportFile = 'Report.csv'\r
60 self.ExceptionFile = 'exception.xml'\r
61 self.IsInit = True\r
62 self.ScanSourceCode = True\r
63 self.ScanMetaData = True\r
d0acc87a 64 self.MetaFile = ''\r
e4ac870f 65 self.OnlyScan = None\r
fd171542 66\r
30fdf114
LG
67 # Parse the options and args\r
68 self.ParseOption()\r
45258285 69 EdkLogger.info(time.strftime("%H:%M:%S, %b.%d %Y ", time.localtime()) + "[00:00]" + "\n")\r
f7496d71 70\r
9508d0fa
LG
71 #\r
72 # Check EFI_SOURCE (Edk build convention). EDK_SOURCE will always point to ECP\r
73 #\r
74 WorkspaceDir = os.path.normcase(os.path.normpath(os.environ["WORKSPACE"]))\r
75 os.environ["WORKSPACE"] = WorkspaceDir\r
f7496d71 76\r
c4f52e12
LY
77 # set multiple workspace\r
78 PackagesPath = os.getenv("PACKAGES_PATH")\r
79 mws.setWs(WorkspaceDir, PackagesPath)\r
f7496d71 80\r
9508d0fa 81 if "ECP_SOURCE" not in os.environ:\r
c4f52e12 82 os.environ["ECP_SOURCE"] = mws.join(WorkspaceDir, GlobalData.gEdkCompatibilityPkg)\r
9508d0fa
LG
83 if "EFI_SOURCE" not in os.environ:\r
84 os.environ["EFI_SOURCE"] = os.environ["ECP_SOURCE"]\r
85 if "EDK_SOURCE" not in os.environ:\r
86 os.environ["EDK_SOURCE"] = os.environ["ECP_SOURCE"]\r
87\r
88 #\r
89 # Unify case of characters on case-insensitive systems\r
90 #\r
91 EfiSourceDir = os.path.normcase(os.path.normpath(os.environ["EFI_SOURCE"]))\r
92 EdkSourceDir = os.path.normcase(os.path.normpath(os.environ["EDK_SOURCE"]))\r
93 EcpSourceDir = os.path.normcase(os.path.normpath(os.environ["ECP_SOURCE"]))\r
f7496d71 94\r
9508d0fa
LG
95 os.environ["EFI_SOURCE"] = EfiSourceDir\r
96 os.environ["EDK_SOURCE"] = EdkSourceDir\r
97 os.environ["ECP_SOURCE"] = EcpSourceDir\r
f7496d71 98\r
9508d0fa
LG
99 GlobalData.gWorkspace = WorkspaceDir\r
100 GlobalData.gEfiSource = EfiSourceDir\r
101 GlobalData.gEdkSource = EdkSourceDir\r
102 GlobalData.gEcpSource = EcpSourceDir\r
103\r
104 GlobalData.gGlobalDefines["WORKSPACE"] = WorkspaceDir\r
105 GlobalData.gGlobalDefines["EFI_SOURCE"] = EfiSourceDir\r
106 GlobalData.gGlobalDefines["EDK_SOURCE"] = EdkSourceDir\r
107 GlobalData.gGlobalDefines["ECP_SOURCE"] = EcpSourceDir\r
f7496d71 108\r
45258285 109 EdkLogger.info("Loading ECC configuration ... done")\r
30fdf114
LG
110 # Generate checkpoints list\r
111 EccGlobalData.gConfig = Configuration(self.ConfigFile)\r
fd171542 112\r
30fdf114
LG
113 # Generate exception list\r
114 EccGlobalData.gException = ExceptionCheck(self.ExceptionFile)\r
fd171542 115\r
30fdf114
LG
116 # Init Ecc database\r
117 EccGlobalData.gDb = Database.Database(Database.DATABASE_PATH)\r
118 EccGlobalData.gDb.InitDatabase(self.IsInit)\r
fd171542 119\r
64b2609f
LG
120 #\r
121 # Get files real name in workspace dir\r
122 #\r
123 GlobalData.gAllFiles = DirCache(GlobalData.gWorkspace)\r
f7496d71 124\r
30fdf114 125 # Build ECC database\r
e4ac870f
LG
126# self.BuildDatabase()\r
127 self.DetectOnlyScanDirs()\r
f7496d71 128\r
30fdf114
LG
129 # Start to check\r
130 self.Check()\r
fd171542 131\r
30fdf114
LG
132 # Show report\r
133 self.GenReport()\r
fd171542 134\r
30fdf114
LG
135 # Close Database\r
136 EccGlobalData.gDb.Close()\r
137\r
138 def InitDefaultConfigIni(self):\r
139 paths = map(lambda p: os.path.join(p, 'Ecc', 'config.ini'), sys.path)\r
140 paths = (os.path.realpath('config.ini'),) + tuple(paths)\r
141 for path in paths:\r
142 if os.path.exists(path):\r
143 self.ConfigFile = path\r
144 return\r
145 self.ConfigFile = 'config.ini'\r
146\r
e4ac870f
LG
147\r
148 ## DetectOnlyScan\r
149 #\r
150 # Detect whether only scanned folders have been enabled\r
151 #\r
152 def DetectOnlyScanDirs(self):\r
153 if self.OnlyScan == True:\r
154 OnlyScanDirs = []\r
155 # Use regex here if multiple spaces or TAB exists in ScanOnlyDirList in config.ini file\r
156 for folder in re.finditer(r'\S+', EccGlobalData.gConfig.ScanOnlyDirList):\r
157 OnlyScanDirs.append(folder.group())\r
158 if len(OnlyScanDirs) != 0:\r
159 self.BuildDatabase(OnlyScanDirs)\r
160 else:\r
161 EdkLogger.error("ECC", BuildToolError.OPTION_VALUE_INVALID, ExtraData="Use -f option need to fill specific folders in config.ini file")\r
162 else:\r
163 self.BuildDatabase()\r
f7496d71
LG
164\r
165\r
30fdf114
LG
166 ## BuildDatabase\r
167 #\r
168 # Build the database for target\r
169 #\r
e4ac870f 170 def BuildDatabase(self, SpeciDirs = None):\r
30fdf114
LG
171 # Clean report table\r
172 EccGlobalData.gDb.TblReport.Drop()\r
173 EccGlobalData.gDb.TblReport.Create()\r
fd171542 174\r
30fdf114 175 # Build database\r
f7496d71 176 if self.IsInit:\r
30fdf114 177 if self.ScanMetaData:\r
64b2609f 178 EdkLogger.quiet("Building database for Meta Data File ...")\r
e4ac870f 179 self.BuildMetaDataFileDatabase(SpeciDirs)\r
64b2609f
LG
180 if self.ScanSourceCode:\r
181 EdkLogger.quiet("Building database for Meta Data File Done!")\r
4231a819 182 if SpeciDirs is None:\r
e4ac870f
LG
183 c.CollectSourceCodeDataIntoDB(EccGlobalData.gTarget)\r
184 else:\r
185 for specificDir in SpeciDirs:\r
186 c.CollectSourceCodeDataIntoDB(os.path.join(EccGlobalData.gTarget, specificDir))\r
fd171542 187\r
30fdf114 188 EccGlobalData.gIdentifierTableList = GetTableList((MODEL_FILE_C, MODEL_FILE_H), 'Identifier', EccGlobalData.gDb)\r
e56468c0 189 EccGlobalData.gCFileList = GetFileList(MODEL_FILE_C, EccGlobalData.gDb)\r
190 EccGlobalData.gHFileList = GetFileList(MODEL_FILE_H, EccGlobalData.gDb)\r
b3d07ff8 191 EccGlobalData.gUFileList = GetFileList(MODEL_FILE_UNI, EccGlobalData.gDb)\r
fd171542 192\r
30fdf114
LG
193 ## BuildMetaDataFileDatabase\r
194 #\r
195 # Build the database for meta data files\r
196 #\r
e4ac870f
LG
197 def BuildMetaDataFileDatabase(self, SpecificDirs = None):\r
198 ScanFolders = []\r
4231a819 199 if SpecificDirs is None:\r
e4ac870f
LG
200 ScanFolders.append(EccGlobalData.gTarget)\r
201 else:\r
f7496d71 202 for specificDir in SpecificDirs:\r
e4ac870f 203 ScanFolders.append(os.path.join(EccGlobalData.gTarget, specificDir))\r
30fdf114
LG
204 EdkLogger.quiet("Building database for meta data files ...")\r
205 Op = open(EccGlobalData.gConfig.MetaDataFileCheckPathOfGenerateFileList, 'w+')\r
206 #SkipDirs = Read from config file\r
207 SkipDirs = EccGlobalData.gConfig.SkipDirList\r
fd171542 208 SkipDirString = string.join(SkipDirs, '|')\r
e4ac870f
LG
209# p = re.compile(r'.*[\\/](?:%s)[\\/]?.*' % SkipDirString)\r
210 p = re.compile(r'.*[\\/](?:%s^\S)[\\/]?.*' % SkipDirString)\r
211 for scanFolder in ScanFolders:\r
212 for Root, Dirs, Files in os.walk(scanFolder):\r
213 if p.match(Root.upper()):\r
30fdf114 214 continue\r
e4ac870f
LG
215 for Dir in Dirs:\r
216 Dirname = os.path.join(Root, Dir)\r
217 if os.path.islink(Dirname):\r
218 Dirname = os.path.realpath(Dirname)\r
219 if os.path.isdir(Dirname):\r
220 # symlinks to directories are treated as directories\r
221 Dirs.remove(Dir)\r
222 Dirs.append(Dirname)\r
f7496d71 223\r
e4ac870f
LG
224 for File in Files:\r
225 if len(File) > 4 and File[-4:].upper() == ".DEC":\r
226 Filename = os.path.normpath(os.path.join(Root, File))\r
227 EdkLogger.quiet("Parsing %s" % Filename)\r
228 Op.write("%s\r" % Filename)\r
229 #Dec(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
230 self.MetaFile = DecParser(Filename, MODEL_FILE_DEC, EccGlobalData.gDb.TblDec)\r
231 self.MetaFile.Start()\r
232 continue\r
233 if len(File) > 4 and File[-4:].upper() == ".DSC":\r
234 Filename = os.path.normpath(os.path.join(Root, File))\r
235 EdkLogger.quiet("Parsing %s" % Filename)\r
236 Op.write("%s\r" % Filename)\r
237 #Dsc(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
238 self.MetaFile = DscParser(PathClass(Filename, Root), MODEL_FILE_DSC, MetaFileStorage(EccGlobalData.gDb.TblDsc.Cur, Filename, MODEL_FILE_DSC, True))\r
239 # alwasy do post-process, in case of macros change\r
240 self.MetaFile.DoPostProcess()\r
241 self.MetaFile.Start()\r
242 self.MetaFile._PostProcess()\r
243 continue\r
244 if len(File) > 4 and File[-4:].upper() == ".INF":\r
245 Filename = os.path.normpath(os.path.join(Root, File))\r
246 EdkLogger.quiet("Parsing %s" % Filename)\r
247 Op.write("%s\r" % Filename)\r
248 #Inf(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
249 self.MetaFile = InfParser(Filename, MODEL_FILE_INF, EccGlobalData.gDb.TblInf)\r
250 self.MetaFile.Start()\r
251 continue\r
252 if len(File) > 4 and File[-4:].upper() == ".FDF":\r
253 Filename = os.path.normpath(os.path.join(Root, File))\r
254 EdkLogger.quiet("Parsing %s" % Filename)\r
255 Op.write("%s\r" % Filename)\r
256 Fdf(Filename, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
257 continue\r
b3d07ff8
HC
258 if len(File) > 4 and File[-4:].upper() == ".UNI":\r
259 Filename = os.path.normpath(os.path.join(Root, File))\r
260 EdkLogger.quiet("Parsing %s" % Filename)\r
261 Op.write("%s\r" % Filename)\r
1b2467c5
HC
262 FileID = EccGlobalData.gDb.TblFile.InsertFile(Filename, MODEL_FILE_UNI)\r
263 EccGlobalData.gDb.TblReport.UpdateBelongsToItemByFile(FileID, File)\r
b3d07ff8
HC
264 continue\r
265\r
30fdf114 266 Op.close()\r
fd171542 267\r
30fdf114
LG
268 # Commit to database\r
269 EccGlobalData.gDb.Conn.commit()\r
fd171542 270\r
30fdf114 271 EdkLogger.quiet("Building database for meta data files done!")\r
fd171542 272\r
30fdf114
LG
273 ##\r
274 #\r
275 # Check each checkpoint\r
276 #\r
277 def Check(self):\r
278 EdkLogger.quiet("Checking ...")\r
279 EccCheck = Check()\r
280 EccCheck.Check()\r
281 EdkLogger.quiet("Checking done!")\r
fd171542 282\r
30fdf114
LG
283 ##\r
284 #\r
285 # Generate the scan report\r
286 #\r
287 def GenReport(self):\r
288 EdkLogger.quiet("Generating report ...")\r
289 EccGlobalData.gDb.TblReport.ToCSV(self.ReportFile)\r
290 EdkLogger.quiet("Generating report done!")\r
fd171542 291\r
30fdf114
LG
292 def GetRealPathCase(self, path):\r
293 TmpPath = path.rstrip(os.sep)\r
294 PathParts = TmpPath.split(os.sep)\r
295 if len(PathParts) == 0:\r
296 return path\r
297 if len(PathParts) == 1:\r
298 if PathParts[0].strip().endswith(':'):\r
299 return PathParts[0].upper()\r
300 # Relative dir, list . current dir\r
301 Dirs = os.listdir('.')\r
302 for Dir in Dirs:\r
303 if Dir.upper() == PathParts[0].upper():\r
304 return Dir\r
fd171542 305\r
30fdf114
LG
306 if PathParts[0].strip().endswith(':'):\r
307 PathParts[0] = PathParts[0].upper()\r
308 ParentDir = PathParts[0]\r
309 RealPath = ParentDir\r
310 if PathParts[0] == '':\r
311 RealPath = os.sep\r
312 ParentDir = os.sep\r
fd171542 313\r
30fdf114
LG
314 PathParts.remove(PathParts[0]) # need to remove the parent\r
315 for Part in PathParts:\r
316 Dirs = os.listdir(ParentDir + os.sep)\r
317 for Dir in Dirs:\r
318 if Dir.upper() == Part.upper():\r
319 RealPath += os.sep\r
320 RealPath += Dir\r
321 break\r
322 ParentDir += os.sep\r
323 ParentDir += Dir\r
fd171542 324\r
30fdf114 325 return RealPath\r
fd171542 326\r
30fdf114
LG
327 ## ParseOption\r
328 #\r
329 # Parse options\r
330 #\r
331 def ParseOption(self):\r
30fdf114 332 (Options, Target) = self.EccOptionParser()\r
fd171542 333\r
52302d4d
LG
334 if Options.Workspace:\r
335 os.environ["WORKSPACE"] = Options.Workspace\r
e56468c0 336\r
30fdf114
LG
337 # Check workspace envirnoment\r
338 if "WORKSPACE" not in os.environ:\r
fd171542 339 EdkLogger.error("ECC", BuildToolError.ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found",\r
30fdf114
LG
340 ExtraData="WORKSPACE")\r
341 else:\r
342 EccGlobalData.gWorkspace = os.path.normpath(os.getenv("WORKSPACE"))\r
343 if not os.path.exists(EccGlobalData.gWorkspace):\r
344 EdkLogger.error("ECC", BuildToolError.FILE_NOT_FOUND, ExtraData="WORKSPACE = %s" % EccGlobalData.gWorkspace)\r
345 os.environ["WORKSPACE"] = EccGlobalData.gWorkspace\r
346 # Set log level\r
347 self.SetLogLevel(Options)\r
fd171542 348\r
30fdf114 349 # Set other options\r
4231a819 350 if Options.ConfigFile is not None:\r
30fdf114 351 self.ConfigFile = Options.ConfigFile\r
4231a819 352 if Options.OutputFile is not None:\r
30fdf114 353 self.OutputFile = Options.OutputFile\r
4231a819 354 if Options.ReportFile is not None:\r
30fdf114 355 self.ReportFile = Options.ReportFile\r
4231a819 356 if Options.ExceptionFile is not None:\r
52302d4d 357 self.ExceptionFile = Options.ExceptionFile\r
4231a819 358 if Options.Target is not None:\r
30fdf114
LG
359 if not os.path.isdir(Options.Target):\r
360 EdkLogger.error("ECC", BuildToolError.OPTION_VALUE_INVALID, ExtraData="Target [%s] does NOT exist" % Options.Target)\r
361 else:\r
362 EccGlobalData.gTarget = self.GetRealPathCase(os.path.normpath(Options.Target))\r
363 else:\r
364 EdkLogger.warn("Ecc", EdkLogger.ECC_ERROR, "The target source tree was not specified, using current WORKSPACE instead!")\r
365 EccGlobalData.gTarget = os.path.normpath(os.getenv("WORKSPACE"))\r
4231a819 366 if Options.keepdatabase is not None:\r
30fdf114 367 self.IsInit = False\r
4231a819 368 if Options.metadata is not None and Options.sourcecode is not None:\r
30fdf114 369 EdkLogger.error("ECC", BuildToolError.OPTION_CONFLICT, ExtraData="-m and -s can't be specified at one time")\r
4231a819 370 if Options.metadata is not None:\r
30fdf114 371 self.ScanSourceCode = False\r
4231a819 372 if Options.sourcecode is not None:\r
30fdf114 373 self.ScanMetaData = False\r
4231a819 374 if Options.folders is not None:\r
e4ac870f 375 self.OnlyScan = True\r
fd171542 376\r
30fdf114
LG
377 ## SetLogLevel\r
378 #\r
379 # Set current log level of the tool based on args\r
380 #\r
fd171542 381 # @param Option: The option list including log level setting\r
30fdf114
LG
382 #\r
383 def SetLogLevel(self, Option):\r
4231a819 384 if Option.verbose is not None:\r
30fdf114 385 EdkLogger.SetLevel(EdkLogger.VERBOSE)\r
4231a819 386 elif Option.quiet is not None:\r
30fdf114 387 EdkLogger.SetLevel(EdkLogger.QUIET)\r
4231a819 388 elif Option.debug is not None:\r
30fdf114
LG
389 EdkLogger.SetLevel(Option.debug + 1)\r
390 else:\r
391 EdkLogger.SetLevel(EdkLogger.INFO)\r
392\r
393 ## Parse command line options\r
394 #\r
395 # Using standard Python module optparse to parse command line option of this tool.\r
396 #\r
397 # @retval Opt A optparse.Values object containing the parsed options\r
398 # @retval Args Target of build command\r
399 #\r
400 def EccOptionParser(self):\r
401 Parser = OptionParser(description = self.Copyright, version = self.Version, prog = "Ecc.exe", usage = "%prog [options]")\r
402 Parser.add_option("-t", "--target sourcepath", action="store", type="string", dest='Target',\r
403 help="Check all files under the target workspace.")\r
404 Parser.add_option("-c", "--config filename", action="store", type="string", dest="ConfigFile",\r
405 help="Specify a configuration file. Defaultly use config.ini under ECC tool directory.")\r
406 Parser.add_option("-o", "--outfile filename", action="store", type="string", dest="OutputFile",\r
407 help="Specify the name of an output file, if and only if one filename was specified.")\r
408 Parser.add_option("-r", "--reportfile filename", action="store", type="string", dest="ReportFile",\r
409 help="Specify the name of an report file, if and only if one filename was specified.")\r
52302d4d
LG
410 Parser.add_option("-e", "--exceptionfile filename", action="store", type="string", dest="ExceptionFile",\r
411 help="Specify the name of an exception file, if and only if one filename was specified.")\r
30fdf114
LG
412 Parser.add_option("-m", "--metadata", action="store_true", type=None, help="Only scan meta-data files information if this option is specified.")\r
413 Parser.add_option("-s", "--sourcecode", action="store_true", type=None, help="Only scan source code files information if this option is specified.")\r
414 Parser.add_option("-k", "--keepdatabase", action="store_true", type=None, help="The existing Ecc database will not be cleaned except report information if this option is specified.")\r
fd171542 415 Parser.add_option("-l", "--log filename", action="store", dest="LogFile", help="""If specified, the tool should emit the changes that\r
416 were made by the tool after printing the result message.\r
417 If filename, the emit to the file, otherwise emit to\r
418 standard output. If no modifications were made, then do not\r
30fdf114
LG
419 create a log file, or output a log message.""")\r
420 Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")\r
421 Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed, "\\r
422 "including library instances selected, final dependency expression, "\\r
423 "and warning messages, etc.")\r
424 Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")\r
52302d4d 425 Parser.add_option("-w", "--workspace", action="store", type="string", dest='Workspace', help="Specify workspace.")\r
e4ac870f 426 Parser.add_option("-f", "--folders", action="store_true", type=None, help="Only scanning specified folders which are recorded in config.ini file.")\r
fd171542 427\r
30fdf114 428 (Opt, Args)=Parser.parse_args()\r
fd171542 429\r
30fdf114
LG
430 return (Opt, Args)\r
431\r
432##\r
433#\r
434# This acts like the main() function for the script, unless it is 'import'ed into another\r
435# script.\r
436#\r
437if __name__ == '__main__':\r
438 # Initialize log system\r
439 EdkLogger.Initialize()\r
440 EdkLogger.IsRaiseError = False\r
30fdf114
LG
441\r
442 StartTime = time.clock()\r
443 Ecc = Ecc()\r
444 FinishTime = time.clock()\r
445\r
446 BuildDuration = time.strftime("%M:%S", time.gmtime(int(round(FinishTime - StartTime))))\r
447 EdkLogger.quiet("\n%s [%s]" % (time.strftime("%H:%M:%S, %b.%d %Y", time.localtime()), BuildDuration))\r