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