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