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