2 # This file is used to be the main entrance of ECC tool
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
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.
17 import os
, time
, glob
, sys
18 import Common
.EdkLogger
as EdkLogger
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
33 from Exception import *
37 # This class is used to define Ecc main entrance
39 # @param object: Inherited from object class
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."
48 self
.InitDefaultConfigIni()
49 self
.OutputFile
= 'output.txt'
50 self
.ReportFile
= 'Report.csv'
51 self
.ExceptionFile
= 'exception.xml'
53 self
.ScanSourceCode
= True
54 self
.ScanMetaData
= True
56 # Parse the options and args
59 # Generate checkpoints list
60 EccGlobalData
.gConfig
= Configuration(self
.ConfigFile
)
62 # Generate exception list
63 EccGlobalData
.gException
= ExceptionCheck(self
.ExceptionFile
)
66 EccGlobalData
.gDb
= Database
.Database(Database
.DATABASE_PATH
)
67 EccGlobalData
.gDb
.InitDatabase(self
.IsInit
)
79 EccGlobalData
.gDb
.Close()
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
)
85 if os
.path
.exists(path
):
86 self
.ConfigFile
= path
88 self
.ConfigFile
= 'config.ini'
92 # Build the database for target
94 def BuildDatabase(self
):
96 EccGlobalData
.gDb
.TblReport
.Drop()
97 EccGlobalData
.gDb
.TblReport
.Create()
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()
108 EccGlobalData
.gIdentifierTableList
= GetTableList((MODEL_FILE_C
, MODEL_FILE_H
), 'Identifier', EccGlobalData
.gDb
)
110 ## BuildMetaDataFileDatabase
112 # Build the database for meta data files
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()):
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
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
)
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
)
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
)
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
)
162 EccGlobalData
.gDb
.Conn
.commit()
164 EdkLogger
.quiet("Building database for meta data files done!")
168 # Check each checkpoint
171 EdkLogger
.quiet("Checking ...")
174 EdkLogger
.quiet("Checking done!")
178 # Generate the scan report
181 EdkLogger
.quiet("Generating report ...")
182 EccGlobalData
.gDb
.TblReport
.ToCSV(self
.ReportFile
)
183 EdkLogger
.quiet("Generating report done!")
185 def GetRealPathCase(self
, path
):
186 TmpPath
= path
.rstrip(os
.sep
)
187 PathParts
= TmpPath
.split(os
.sep
)
188 if len(PathParts
) == 0:
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('.')
196 if Dir
.upper() == PathParts
[0].upper():
199 if PathParts
[0].strip().endswith(':'):
200 PathParts
[0] = PathParts
[0].upper()
201 ParentDir
= PathParts
[0]
203 if PathParts
[0] == '':
207 PathParts
.remove(PathParts
[0]) # need to remove the parent
208 for Part
in PathParts
:
209 Dirs
= os
.listdir(ParentDir
+ os
.sep
)
211 if Dir
.upper() == Part
.upper():
224 def ParseOption(self
):
225 EdkLogger
.quiet("Loading ECC configuration ... done")
226 (Options
, Target
) = self
.EccOptionParser()
228 if Options
.Workspace
:
229 os
.environ
["WORKSPACE"] = Options
.Workspace
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")
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
241 self
.SetLogLevel(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
)
256 EccGlobalData
.gTarget
= self
.GetRealPathCase(os
.path
.normpath(Options
.Target
))
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:
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
271 # Set current log level of the tool based on args
273 # @param Option: The option list including log level setting
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)
283 EdkLogger
.SetLevel(EdkLogger
.INFO
)
285 ## Parse command line options
287 # Using standard Python module optparse to parse command line option of this tool.
289 # @retval Opt A optparse.Values object containing the parsed options
290 # @retval Args Target of build command
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.")
319 (Opt
, Args
)=Parser
.parse_args()
325 # This acts like the main() function for the script, unless it is 'import'ed into another
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")
334 StartTime
= time
.clock()
336 FinishTime
= time
.clock()
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
))