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