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