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