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