]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/Ecc/Ecc.py
Sync BaseTool trunk (version r2460) into EDKII BaseTools. The change mainly includes:
[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
40d841f6
LG
4# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
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
17import os, time, glob, sys\r
18import Common.EdkLogger as EdkLogger\r
19import Database\r
20import EccGlobalData\r
21from MetaDataParser import *\r
22from optparse import OptionParser\r
23from Configuration import Configuration\r
24from Check import Check\r
d0acc87a
LG
25\r
26\r
30fdf114 27from Common.String import NormPath\r
b36d134f 28from Common.BuildVersion import gBUILD_VERSION\r
30fdf114 29from Common import BuildToolError\r
d0acc87a
LG
30\r
31from MetaFileWorkspace.MetaFileParser import DscParser\r
32from MetaFileWorkspace.MetaFileParser import DecParser\r
33from MetaFileWorkspace.MetaFileParser import InfParser\r
34from MetaFileWorkspace.MetaFileParser import Fdf\r
35from MetaFileWorkspace.MetaFileTable import MetaFileStorage\r
30fdf114 36import c\r
fd171542 37import re, string\r
30fdf114
LG
38from Exception import *\r
39\r
40## Ecc\r
41#\r
42# This class is used to define Ecc main entrance\r
43#\r
44# @param object: Inherited from object class\r
45#\r
46class Ecc(object):\r
47 def __init__(self):\r
48 # Version and Copyright\r
b36d134f 49 self.VersionNumber = ("0.01" + " " + gBUILD_VERSION)\r
30fdf114 50 self.Version = "%prog Version " + self.VersionNumber\r
52302d4d 51 self.Copyright = "Copyright (c) 2009 - 2010, Intel Corporation All rights reserved."\r
30fdf114
LG
52\r
53 self.InitDefaultConfigIni()\r
54 self.OutputFile = 'output.txt'\r
55 self.ReportFile = 'Report.csv'\r
56 self.ExceptionFile = 'exception.xml'\r
57 self.IsInit = True\r
58 self.ScanSourceCode = True\r
59 self.ScanMetaData = True\r
d0acc87a 60 self.MetaFile = ''\r
fd171542 61\r
30fdf114
LG
62 # Parse the options and args\r
63 self.ParseOption()\r
64\r
65 # Generate checkpoints list\r
66 EccGlobalData.gConfig = Configuration(self.ConfigFile)\r
fd171542 67\r
30fdf114
LG
68 # Generate exception list\r
69 EccGlobalData.gException = ExceptionCheck(self.ExceptionFile)\r
fd171542 70\r
30fdf114
LG
71 # Init Ecc database\r
72 EccGlobalData.gDb = Database.Database(Database.DATABASE_PATH)\r
73 EccGlobalData.gDb.InitDatabase(self.IsInit)\r
fd171542 74\r
30fdf114
LG
75 # Build ECC database\r
76 self.BuildDatabase()\r
fd171542 77\r
30fdf114
LG
78 # Start to check\r
79 self.Check()\r
fd171542 80\r
30fdf114
LG
81 # Show report\r
82 self.GenReport()\r
fd171542 83\r
30fdf114
LG
84 # Close Database\r
85 EccGlobalData.gDb.Close()\r
86\r
87 def InitDefaultConfigIni(self):\r
88 paths = map(lambda p: os.path.join(p, 'Ecc', 'config.ini'), sys.path)\r
89 paths = (os.path.realpath('config.ini'),) + tuple(paths)\r
90 for path in paths:\r
91 if os.path.exists(path):\r
92 self.ConfigFile = path\r
93 return\r
94 self.ConfigFile = 'config.ini'\r
95\r
96 ## BuildDatabase\r
97 #\r
98 # Build the database for target\r
99 #\r
100 def BuildDatabase(self):\r
101 # Clean report table\r
102 EccGlobalData.gDb.TblReport.Drop()\r
103 EccGlobalData.gDb.TblReport.Create()\r
fd171542 104\r
30fdf114
LG
105 # Build database\r
106 if self.IsInit:\r
107 if self.ScanSourceCode:\r
108 EdkLogger.quiet("Building database for source code ...")\r
109 c.CollectSourceCodeDataIntoDB(EccGlobalData.gTarget)\r
110 if self.ScanMetaData:\r
111 EdkLogger.quiet("Building database for source code done!")\r
112 self.BuildMetaDataFileDatabase()\r
fd171542 113\r
30fdf114 114 EccGlobalData.gIdentifierTableList = GetTableList((MODEL_FILE_C, MODEL_FILE_H), 'Identifier', EccGlobalData.gDb)\r
e56468c0 115 EccGlobalData.gCFileList = GetFileList(MODEL_FILE_C, EccGlobalData.gDb)\r
116 EccGlobalData.gHFileList = GetFileList(MODEL_FILE_H, EccGlobalData.gDb)\r
fd171542 117\r
30fdf114
LG
118 ## BuildMetaDataFileDatabase\r
119 #\r
120 # Build the database for meta data files\r
121 #\r
122 def BuildMetaDataFileDatabase(self):\r
123 EdkLogger.quiet("Building database for meta data files ...")\r
124 Op = open(EccGlobalData.gConfig.MetaDataFileCheckPathOfGenerateFileList, 'w+')\r
125 #SkipDirs = Read from config file\r
126 SkipDirs = EccGlobalData.gConfig.SkipDirList\r
fd171542 127 SkipDirString = string.join(SkipDirs, '|')\r
128 p = re.compile(r'.*[\\/](?:%s)[\\/]?.*' % SkipDirString)\r
30fdf114 129 for Root, Dirs, Files in os.walk(EccGlobalData.gTarget):\r
fd171542 130 if p.match(Root.upper()):\r
131 continue\r
30fdf114
LG
132 for Dir in Dirs:\r
133 Dirname = os.path.join(Root, Dir)\r
134 if os.path.islink(Dirname):\r
135 Dirname = os.path.realpath(Dirname)\r
136 if os.path.isdir(Dirname):\r
137 # symlinks to directories are treated as directories\r
138 Dirs.remove(Dir)\r
139 Dirs.append(Dirname)\r
140\r
141 for File in Files:\r
142 if len(File) > 4 and File[-4:].upper() == ".DEC":\r
143 Filename = os.path.normpath(os.path.join(Root, File))\r
144 EdkLogger.quiet("Parsing %s" % Filename)\r
145 Op.write("%s\r" % Filename)\r
d0acc87a
LG
146 #Dec(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
147 self.MetaFile = DecParser(Filename, MODEL_FILE_DEC, EccGlobalData.gDb.TblDec)\r
148 self.MetaFile.Start()\r
30fdf114
LG
149 continue\r
150 if len(File) > 4 and File[-4:].upper() == ".DSC":\r
151 Filename = os.path.normpath(os.path.join(Root, File))\r
152 EdkLogger.quiet("Parsing %s" % Filename)\r
153 Op.write("%s\r" % Filename)\r
d0acc87a
LG
154 #Dsc(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
155 self.MetaFile = DscParser(Filename, MODEL_FILE_DSC, MetaFileStorage(EccGlobalData.gDb.TblDsc.Cur, Filename, MODEL_FILE_DSC, True))\r
156 # alwasy do post-process, in case of macros change\r
157 self.MetaFile.DoPostProcess()\r
158 self.MetaFile.Start()\r
159 self.MetaFile._PostProcess()\r
30fdf114
LG
160 continue\r
161 if len(File) > 4 and File[-4:].upper() == ".INF":\r
162 Filename = os.path.normpath(os.path.join(Root, File))\r
163 EdkLogger.quiet("Parsing %s" % Filename)\r
164 Op.write("%s\r" % Filename)\r
d0acc87a
LG
165 #Inf(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
166 self.MetaFile = InfParser(Filename, MODEL_FILE_INF, EccGlobalData.gDb.TblInf)\r
167 self.MetaFile.Start()\r
30fdf114
LG
168 continue\r
169 if len(File) > 4 and File[-4:].upper() == ".FDF":\r
170 Filename = os.path.normpath(os.path.join(Root, File))\r
171 EdkLogger.quiet("Parsing %s" % Filename)\r
172 Op.write("%s\r" % Filename)\r
fd171542 173 Fdf(Filename, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
30fdf114
LG
174 continue\r
175 Op.close()\r
fd171542 176\r
30fdf114
LG
177 # Commit to database\r
178 EccGlobalData.gDb.Conn.commit()\r
fd171542 179\r
30fdf114 180 EdkLogger.quiet("Building database for meta data files done!")\r
fd171542 181\r
30fdf114
LG
182 ##\r
183 #\r
184 # Check each checkpoint\r
185 #\r
186 def Check(self):\r
187 EdkLogger.quiet("Checking ...")\r
188 EccCheck = Check()\r
189 EccCheck.Check()\r
190 EdkLogger.quiet("Checking done!")\r
fd171542 191\r
30fdf114
LG
192 ##\r
193 #\r
194 # Generate the scan report\r
195 #\r
196 def GenReport(self):\r
197 EdkLogger.quiet("Generating report ...")\r
198 EccGlobalData.gDb.TblReport.ToCSV(self.ReportFile)\r
199 EdkLogger.quiet("Generating report done!")\r
fd171542 200\r
30fdf114
LG
201 def GetRealPathCase(self, path):\r
202 TmpPath = path.rstrip(os.sep)\r
203 PathParts = TmpPath.split(os.sep)\r
204 if len(PathParts) == 0:\r
205 return path\r
206 if len(PathParts) == 1:\r
207 if PathParts[0].strip().endswith(':'):\r
208 return PathParts[0].upper()\r
209 # Relative dir, list . current dir\r
210 Dirs = os.listdir('.')\r
211 for Dir in Dirs:\r
212 if Dir.upper() == PathParts[0].upper():\r
213 return Dir\r
fd171542 214\r
30fdf114
LG
215 if PathParts[0].strip().endswith(':'):\r
216 PathParts[0] = PathParts[0].upper()\r
217 ParentDir = PathParts[0]\r
218 RealPath = ParentDir\r
219 if PathParts[0] == '':\r
220 RealPath = os.sep\r
221 ParentDir = os.sep\r
fd171542 222\r
30fdf114
LG
223 PathParts.remove(PathParts[0]) # need to remove the parent\r
224 for Part in PathParts:\r
225 Dirs = os.listdir(ParentDir + os.sep)\r
226 for Dir in Dirs:\r
227 if Dir.upper() == Part.upper():\r
228 RealPath += os.sep\r
229 RealPath += Dir\r
230 break\r
231 ParentDir += os.sep\r
232 ParentDir += Dir\r
fd171542 233\r
30fdf114 234 return RealPath\r
fd171542 235\r
30fdf114
LG
236 ## ParseOption\r
237 #\r
238 # Parse options\r
239 #\r
240 def ParseOption(self):\r
241 EdkLogger.quiet("Loading ECC configuration ... done")\r
242 (Options, Target) = self.EccOptionParser()\r
fd171542 243\r
52302d4d
LG
244 if Options.Workspace:\r
245 os.environ["WORKSPACE"] = Options.Workspace\r
e56468c0 246\r
30fdf114
LG
247 # Check workspace envirnoment\r
248 if "WORKSPACE" not in os.environ:\r
fd171542 249 EdkLogger.error("ECC", BuildToolError.ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found",\r
30fdf114
LG
250 ExtraData="WORKSPACE")\r
251 else:\r
252 EccGlobalData.gWorkspace = os.path.normpath(os.getenv("WORKSPACE"))\r
253 if not os.path.exists(EccGlobalData.gWorkspace):\r
254 EdkLogger.error("ECC", BuildToolError.FILE_NOT_FOUND, ExtraData="WORKSPACE = %s" % EccGlobalData.gWorkspace)\r
255 os.environ["WORKSPACE"] = EccGlobalData.gWorkspace\r
256 # Set log level\r
257 self.SetLogLevel(Options)\r
fd171542 258\r
30fdf114
LG
259 # Set other options\r
260 if Options.ConfigFile != None:\r
261 self.ConfigFile = Options.ConfigFile\r
262 if Options.OutputFile != None:\r
263 self.OutputFile = Options.OutputFile\r
264 if Options.ReportFile != None:\r
265 self.ReportFile = Options.ReportFile\r
52302d4d
LG
266 if Options.ExceptionFile != None:\r
267 self.ExceptionFile = Options.ExceptionFile\r
30fdf114
LG
268 if Options.Target != None:\r
269 if not os.path.isdir(Options.Target):\r
270 EdkLogger.error("ECC", BuildToolError.OPTION_VALUE_INVALID, ExtraData="Target [%s] does NOT exist" % Options.Target)\r
271 else:\r
272 EccGlobalData.gTarget = self.GetRealPathCase(os.path.normpath(Options.Target))\r
273 else:\r
274 EdkLogger.warn("Ecc", EdkLogger.ECC_ERROR, "The target source tree was not specified, using current WORKSPACE instead!")\r
275 EccGlobalData.gTarget = os.path.normpath(os.getenv("WORKSPACE"))\r
276 if Options.keepdatabase != None:\r
277 self.IsInit = False\r
278 if Options.metadata != None and Options.sourcecode != None:\r
279 EdkLogger.error("ECC", BuildToolError.OPTION_CONFLICT, ExtraData="-m and -s can't be specified at one time")\r
280 if Options.metadata != None:\r
281 self.ScanSourceCode = False\r
282 if Options.sourcecode != None:\r
283 self.ScanMetaData = False\r
fd171542 284\r
30fdf114
LG
285 ## SetLogLevel\r
286 #\r
287 # Set current log level of the tool based on args\r
288 #\r
fd171542 289 # @param Option: The option list including log level setting\r
30fdf114
LG
290 #\r
291 def SetLogLevel(self, Option):\r
292 if Option.verbose != None:\r
293 EdkLogger.SetLevel(EdkLogger.VERBOSE)\r
294 elif Option.quiet != None:\r
295 EdkLogger.SetLevel(EdkLogger.QUIET)\r
296 elif Option.debug != None:\r
297 EdkLogger.SetLevel(Option.debug + 1)\r
298 else:\r
299 EdkLogger.SetLevel(EdkLogger.INFO)\r
300\r
301 ## Parse command line options\r
302 #\r
303 # Using standard Python module optparse to parse command line option of this tool.\r
304 #\r
305 # @retval Opt A optparse.Values object containing the parsed options\r
306 # @retval Args Target of build command\r
307 #\r
308 def EccOptionParser(self):\r
309 Parser = OptionParser(description = self.Copyright, version = self.Version, prog = "Ecc.exe", usage = "%prog [options]")\r
310 Parser.add_option("-t", "--target sourcepath", action="store", type="string", dest='Target',\r
311 help="Check all files under the target workspace.")\r
312 Parser.add_option("-c", "--config filename", action="store", type="string", dest="ConfigFile",\r
313 help="Specify a configuration file. Defaultly use config.ini under ECC tool directory.")\r
314 Parser.add_option("-o", "--outfile filename", action="store", type="string", dest="OutputFile",\r
315 help="Specify the name of an output file, if and only if one filename was specified.")\r
316 Parser.add_option("-r", "--reportfile filename", action="store", type="string", dest="ReportFile",\r
317 help="Specify the name of an report file, if and only if one filename was specified.")\r
52302d4d
LG
318 Parser.add_option("-e", "--exceptionfile filename", action="store", type="string", dest="ExceptionFile",\r
319 help="Specify the name of an exception file, if and only if one filename was specified.")\r
30fdf114
LG
320 Parser.add_option("-m", "--metadata", action="store_true", type=None, help="Only scan meta-data files information if this option is specified.")\r
321 Parser.add_option("-s", "--sourcecode", action="store_true", type=None, help="Only scan source code files information if this option is specified.")\r
322 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 323 Parser.add_option("-l", "--log filename", action="store", dest="LogFile", help="""If specified, the tool should emit the changes that\r
324 were made by the tool after printing the result message.\r
325 If filename, the emit to the file, otherwise emit to\r
326 standard output. If no modifications were made, then do not\r
30fdf114
LG
327 create a log file, or output a log message.""")\r
328 Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")\r
329 Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed, "\\r
330 "including library instances selected, final dependency expression, "\\r
331 "and warning messages, etc.")\r
332 Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")\r
52302d4d 333 Parser.add_option("-w", "--workspace", action="store", type="string", dest='Workspace', help="Specify workspace.")\r
fd171542 334\r
30fdf114 335 (Opt, Args)=Parser.parse_args()\r
fd171542 336\r
30fdf114
LG
337 return (Opt, Args)\r
338\r
339##\r
340#\r
341# This acts like the main() function for the script, unless it is 'import'ed into another\r
342# script.\r
343#\r
344if __name__ == '__main__':\r
345 # Initialize log system\r
346 EdkLogger.Initialize()\r
347 EdkLogger.IsRaiseError = False\r
348 EdkLogger.quiet(time.strftime("%H:%M:%S, %b.%d %Y ", time.localtime()) + "[00:00]" + "\n")\r
349\r
350 StartTime = time.clock()\r
351 Ecc = Ecc()\r
352 FinishTime = time.clock()\r
353\r
354 BuildDuration = time.strftime("%M:%S", time.gmtime(int(round(FinishTime - StartTime))))\r
355 EdkLogger.quiet("\n%s [%s]" % (time.strftime("%H:%M:%S, %b.%d %Y", time.localtime()), BuildDuration))\r