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
)
109 EccGlobalData
.gCFileList
= GetFileList(MODEL_FILE_C
, EccGlobalData
.gDb
)
110 EccGlobalData
.gHFileList
= GetFileList(MODEL_FILE_H
, EccGlobalData
.gDb
)
112 ## BuildMetaDataFileDatabase
114 # Build the database for meta data files
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()):
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
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
)
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
)
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
)
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
)
164 EccGlobalData
.gDb
.Conn
.commit()
166 EdkLogger
.quiet("Building database for meta data files done!")
170 # Check each checkpoint
173 EdkLogger
.quiet("Checking ...")
176 EdkLogger
.quiet("Checking done!")
180 # Generate the scan report
183 EdkLogger
.quiet("Generating report ...")
184 EccGlobalData
.gDb
.TblReport
.ToCSV(self
.ReportFile
)
185 EdkLogger
.quiet("Generating report done!")
187 def GetRealPathCase(self
, path
):
188 TmpPath
= path
.rstrip(os
.sep
)
189 PathParts
= TmpPath
.split(os
.sep
)
190 if len(PathParts
) == 0:
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('.')
198 if Dir
.upper() == PathParts
[0].upper():
201 if PathParts
[0].strip().endswith(':'):
202 PathParts
[0] = PathParts
[0].upper()
203 ParentDir
= PathParts
[0]
205 if PathParts
[0] == '':
209 PathParts
.remove(PathParts
[0]) # need to remove the parent
210 for Part
in PathParts
:
211 Dirs
= os
.listdir(ParentDir
+ os
.sep
)
213 if Dir
.upper() == Part
.upper():
226 def ParseOption(self
):
227 EdkLogger
.quiet("Loading ECC configuration ... done")
228 (Options
, Target
) = self
.EccOptionParser()
230 if Options
.Workspace
:
231 os
.environ
["WORKSPACE"] = Options
.Workspace
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")
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
243 self
.SetLogLevel(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
)
258 EccGlobalData
.gTarget
= self
.GetRealPathCase(os
.path
.normpath(Options
.Target
))
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:
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
273 # Set current log level of the tool based on args
275 # @param Option: The option list including log level setting
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)
285 EdkLogger
.SetLevel(EdkLogger
.INFO
)
287 ## Parse command line options
289 # Using standard Python module optparse to parse command line option of this tool.
291 # @retval Opt A optparse.Values object containing the parsed options
292 # @retval Args Target of build command
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.")
321 (Opt
, Args
)=Parser
.parse_args()
327 # This acts like the main() function for the script, unless it is 'import'ed into another
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")
336 StartTime
= time
.clock()
338 FinishTime
= time
.clock()
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
))