]> git.proxmox.com Git - mirror_edk2.git/blob - 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
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 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, 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 # Check workspace envirnoment
229 if "WORKSPACE" not in os.environ:
230 EdkLogger.error("ECC", BuildToolError.ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found",
231 ExtraData="WORKSPACE")
232 else:
233 EccGlobalData.gWorkspace = os.path.normpath(os.getenv("WORKSPACE"))
234 if not os.path.exists(EccGlobalData.gWorkspace):
235 EdkLogger.error("ECC", BuildToolError.FILE_NOT_FOUND, ExtraData="WORKSPACE = %s" % EccGlobalData.gWorkspace)
236 os.environ["WORKSPACE"] = EccGlobalData.gWorkspace
237 # Set log level
238 self.SetLogLevel(Options)
239
240 # Set other options
241 if Options.ConfigFile != None:
242 self.ConfigFile = Options.ConfigFile
243 if Options.OutputFile != None:
244 self.OutputFile = Options.OutputFile
245 if Options.ReportFile != None:
246 self.ReportFile = Options.ReportFile
247 if Options.Target != None:
248 if not os.path.isdir(Options.Target):
249 EdkLogger.error("ECC", BuildToolError.OPTION_VALUE_INVALID, ExtraData="Target [%s] does NOT exist" % Options.Target)
250 else:
251 EccGlobalData.gTarget = self.GetRealPathCase(os.path.normpath(Options.Target))
252 else:
253 EdkLogger.warn("Ecc", EdkLogger.ECC_ERROR, "The target source tree was not specified, using current WORKSPACE instead!")
254 EccGlobalData.gTarget = os.path.normpath(os.getenv("WORKSPACE"))
255 if Options.keepdatabase != None:
256 self.IsInit = False
257 if Options.metadata != None and Options.sourcecode != None:
258 EdkLogger.error("ECC", BuildToolError.OPTION_CONFLICT, ExtraData="-m and -s can't be specified at one time")
259 if Options.metadata != None:
260 self.ScanSourceCode = False
261 if Options.sourcecode != None:
262 self.ScanMetaData = False
263
264 ## SetLogLevel
265 #
266 # Set current log level of the tool based on args
267 #
268 # @param Option: The option list including log level setting
269 #
270 def SetLogLevel(self, Option):
271 if Option.verbose != None:
272 EdkLogger.SetLevel(EdkLogger.VERBOSE)
273 elif Option.quiet != None:
274 EdkLogger.SetLevel(EdkLogger.QUIET)
275 elif Option.debug != None:
276 EdkLogger.SetLevel(Option.debug + 1)
277 else:
278 EdkLogger.SetLevel(EdkLogger.INFO)
279
280 ## Parse command line options
281 #
282 # Using standard Python module optparse to parse command line option of this tool.
283 #
284 # @retval Opt A optparse.Values object containing the parsed options
285 # @retval Args Target of build command
286 #
287 def EccOptionParser(self):
288 Parser = OptionParser(description = self.Copyright, version = self.Version, prog = "Ecc.exe", usage = "%prog [options]")
289 Parser.add_option("-t", "--target sourcepath", action="store", type="string", dest='Target',
290 help="Check all files under the target workspace.")
291 Parser.add_option("-c", "--config filename", action="store", type="string", dest="ConfigFile",
292 help="Specify a configuration file. Defaultly use config.ini under ECC tool directory.")
293 Parser.add_option("-o", "--outfile filename", action="store", type="string", dest="OutputFile",
294 help="Specify the name of an output file, if and only if one filename was specified.")
295 Parser.add_option("-r", "--reportfile filename", action="store", type="string", dest="ReportFile",
296 help="Specify the name of an report file, if and only if one filename was specified.")
297 Parser.add_option("-m", "--metadata", action="store_true", type=None, help="Only scan meta-data files information if this option is specified.")
298 Parser.add_option("-s", "--sourcecode", action="store_true", type=None, help="Only scan source code files information if this option is specified.")
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.")
300 Parser.add_option("-l", "--log filename", action="store", dest="LogFile", help="""If specified, the tool should emit the changes that
301 were made by the tool after printing the result message.
302 If filename, the emit to the file, otherwise emit to
303 standard output. If no modifications were made, then do not
304 create a log file, or output a log message.""")
305 Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
306 Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed, "\
307 "including library instances selected, final dependency expression, "\
308 "and warning messages, etc.")
309 Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")
310
311 (Opt, Args)=Parser.parse_args()
312
313 return (Opt, Args)
314
315 ##
316 #
317 # This acts like the main() function for the script, unless it is 'import'ed into another
318 # script.
319 #
320 if __name__ == '__main__':
321 # Initialize log system
322 EdkLogger.Initialize()
323 EdkLogger.IsRaiseError = False
324 EdkLogger.quiet(time.strftime("%H:%M:%S, %b.%d %Y ", time.localtime()) + "[00:00]" + "\n")
325
326 StartTime = time.clock()
327 Ecc = Ecc()
328 FinishTime = time.clock()
329
330 BuildDuration = time.strftime("%M:%S", time.gmtime(int(round(FinishTime - StartTime))))
331 EdkLogger.quiet("\n%s [%s]" % (time.strftime("%H:%M:%S, %b.%d %Y", time.localtime()), BuildDuration))