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
27 from Common
.String
import NormPath
28 from Common
.BuildVersion
import gBUILD_VERSION
29 from Common
import BuildToolError
31 from MetaFileWorkspace
.MetaFileParser
import DscParser
32 from MetaFileWorkspace
.MetaFileParser
import DecParser
33 from MetaFileWorkspace
.MetaFileParser
import InfParser
34 from MetaFileWorkspace
.MetaFileParser
import Fdf
35 from MetaFileWorkspace
.MetaFileTable
import MetaFileStorage
38 from Exception import *
42 # This class is used to define Ecc main entrance
44 # @param object: Inherited from object class
48 # Version and Copyright
49 self
.VersionNumber
= ("0.01" + " " + gBUILD_VERSION
)
50 self
.Version
= "%prog Version " + self
.VersionNumber
51 self
.Copyright
= "Copyright (c) 2009 - 2010, Intel Corporation All rights reserved."
53 self
.InitDefaultConfigIni()
54 self
.OutputFile
= 'output.txt'
55 self
.ReportFile
= 'Report.csv'
56 self
.ExceptionFile
= 'exception.xml'
58 self
.ScanSourceCode
= True
59 self
.ScanMetaData
= True
62 # Parse the options and args
65 # Generate checkpoints list
66 EccGlobalData
.gConfig
= Configuration(self
.ConfigFile
)
68 # Generate exception list
69 EccGlobalData
.gException
= ExceptionCheck(self
.ExceptionFile
)
72 EccGlobalData
.gDb
= Database
.Database(Database
.DATABASE_PATH
)
73 EccGlobalData
.gDb
.InitDatabase(self
.IsInit
)
85 EccGlobalData
.gDb
.Close()
87 def InitDefaultConfigIni(self
):
88 paths
= map(lambda p
: os
.path
.join(p
, 'Ecc', 'config.ini'), sys
.path
)
89 paths
= (os
.path
.realpath('config.ini'),) + tuple(paths
)
91 if os
.path
.exists(path
):
92 self
.ConfigFile
= path
94 self
.ConfigFile
= 'config.ini'
98 # Build the database for target
100 def BuildDatabase(self
):
102 EccGlobalData
.gDb
.TblReport
.Drop()
103 EccGlobalData
.gDb
.TblReport
.Create()
107 if self
.ScanSourceCode
:
108 EdkLogger
.quiet("Building database for source code ...")
109 c
.CollectSourceCodeDataIntoDB(EccGlobalData
.gTarget
)
110 if self
.ScanMetaData
:
111 EdkLogger
.quiet("Building database for source code done!")
112 self
.BuildMetaDataFileDatabase()
114 EccGlobalData
.gIdentifierTableList
= GetTableList((MODEL_FILE_C
, MODEL_FILE_H
), 'Identifier', EccGlobalData
.gDb
)
115 EccGlobalData
.gCFileList
= GetFileList(MODEL_FILE_C
, EccGlobalData
.gDb
)
116 EccGlobalData
.gHFileList
= GetFileList(MODEL_FILE_H
, EccGlobalData
.gDb
)
118 ## BuildMetaDataFileDatabase
120 # Build the database for meta data files
122 def BuildMetaDataFileDatabase(self
):
123 EdkLogger
.quiet("Building database for meta data files ...")
124 Op
= open(EccGlobalData
.gConfig
.MetaDataFileCheckPathOfGenerateFileList
, 'w+')
125 #SkipDirs = Read from config file
126 SkipDirs
= EccGlobalData
.gConfig
.SkipDirList
127 SkipDirString
= string
.join(SkipDirs
, '|')
128 p
= re
.compile(r
'.*[\\/](?:%s)[\\/]?.*' % SkipDirString
)
129 for Root
, Dirs
, Files
in os
.walk(EccGlobalData
.gTarget
):
130 if p
.match(Root
.upper()):
133 Dirname
= os
.path
.join(Root
, Dir
)
134 if os
.path
.islink(Dirname
):
135 Dirname
= os
.path
.realpath(Dirname
)
136 if os
.path
.isdir(Dirname
):
137 # symlinks to directories are treated as directories
142 if len(File
) > 4 and File
[-4:].upper() == ".DEC":
143 Filename
= os
.path
.normpath(os
.path
.join(Root
, File
))
144 EdkLogger
.quiet("Parsing %s" % Filename
)
145 Op
.write("%s\r" % Filename
)
146 #Dec(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)
147 self
.MetaFile
= DecParser(Filename
, MODEL_FILE_DEC
, EccGlobalData
.gDb
.TblDec
)
148 self
.MetaFile
.Start()
150 if len(File
) > 4 and File
[-4:].upper() == ".DSC":
151 Filename
= os
.path
.normpath(os
.path
.join(Root
, File
))
152 EdkLogger
.quiet("Parsing %s" % Filename
)
153 Op
.write("%s\r" % Filename
)
154 #Dsc(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)
155 self
.MetaFile
= DscParser(Filename
, MODEL_FILE_DSC
, MetaFileStorage(EccGlobalData
.gDb
.TblDsc
.Cur
, Filename
, MODEL_FILE_DSC
, True))
156 # alwasy do post-process, in case of macros change
157 self
.MetaFile
.DoPostProcess()
158 self
.MetaFile
.Start()
159 self
.MetaFile
._PostProcess
()
161 if len(File
) > 4 and File
[-4:].upper() == ".INF":
162 Filename
= os
.path
.normpath(os
.path
.join(Root
, File
))
163 EdkLogger
.quiet("Parsing %s" % Filename
)
164 Op
.write("%s\r" % Filename
)
165 #Inf(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)
166 self
.MetaFile
= InfParser(Filename
, MODEL_FILE_INF
, EccGlobalData
.gDb
.TblInf
)
167 self
.MetaFile
.Start()
169 if len(File
) > 4 and File
[-4:].upper() == ".FDF":
170 Filename
= os
.path
.normpath(os
.path
.join(Root
, File
))
171 EdkLogger
.quiet("Parsing %s" % Filename
)
172 Op
.write("%s\r" % Filename
)
173 Fdf(Filename
, True, EccGlobalData
.gWorkspace
, EccGlobalData
.gDb
)
178 EccGlobalData
.gDb
.Conn
.commit()
180 EdkLogger
.quiet("Building database for meta data files done!")
184 # Check each checkpoint
187 EdkLogger
.quiet("Checking ...")
190 EdkLogger
.quiet("Checking done!")
194 # Generate the scan report
197 EdkLogger
.quiet("Generating report ...")
198 EccGlobalData
.gDb
.TblReport
.ToCSV(self
.ReportFile
)
199 EdkLogger
.quiet("Generating report done!")
201 def GetRealPathCase(self
, path
):
202 TmpPath
= path
.rstrip(os
.sep
)
203 PathParts
= TmpPath
.split(os
.sep
)
204 if len(PathParts
) == 0:
206 if len(PathParts
) == 1:
207 if PathParts
[0].strip().endswith(':'):
208 return PathParts
[0].upper()
209 # Relative dir, list . current dir
210 Dirs
= os
.listdir('.')
212 if Dir
.upper() == PathParts
[0].upper():
215 if PathParts
[0].strip().endswith(':'):
216 PathParts
[0] = PathParts
[0].upper()
217 ParentDir
= PathParts
[0]
219 if PathParts
[0] == '':
223 PathParts
.remove(PathParts
[0]) # need to remove the parent
224 for Part
in PathParts
:
225 Dirs
= os
.listdir(ParentDir
+ os
.sep
)
227 if Dir
.upper() == Part
.upper():
240 def ParseOption(self
):
241 EdkLogger
.quiet("Loading ECC configuration ... done")
242 (Options
, Target
) = self
.EccOptionParser()
244 if Options
.Workspace
:
245 os
.environ
["WORKSPACE"] = Options
.Workspace
247 # Check workspace envirnoment
248 if "WORKSPACE" not in os
.environ
:
249 EdkLogger
.error("ECC", BuildToolError
.ATTRIBUTE_NOT_AVAILABLE
, "Environment variable not found",
250 ExtraData
="WORKSPACE")
252 EccGlobalData
.gWorkspace
= os
.path
.normpath(os
.getenv("WORKSPACE"))
253 if not os
.path
.exists(EccGlobalData
.gWorkspace
):
254 EdkLogger
.error("ECC", BuildToolError
.FILE_NOT_FOUND
, ExtraData
="WORKSPACE = %s" % EccGlobalData
.gWorkspace
)
255 os
.environ
["WORKSPACE"] = EccGlobalData
.gWorkspace
257 self
.SetLogLevel(Options
)
260 if Options
.ConfigFile
!= None:
261 self
.ConfigFile
= Options
.ConfigFile
262 if Options
.OutputFile
!= None:
263 self
.OutputFile
= Options
.OutputFile
264 if Options
.ReportFile
!= None:
265 self
.ReportFile
= Options
.ReportFile
266 if Options
.ExceptionFile
!= None:
267 self
.ExceptionFile
= Options
.ExceptionFile
268 if Options
.Target
!= None:
269 if not os
.path
.isdir(Options
.Target
):
270 EdkLogger
.error("ECC", BuildToolError
.OPTION_VALUE_INVALID
, ExtraData
="Target [%s] does NOT exist" % Options
.Target
)
272 EccGlobalData
.gTarget
= self
.GetRealPathCase(os
.path
.normpath(Options
.Target
))
274 EdkLogger
.warn("Ecc", EdkLogger
.ECC_ERROR
, "The target source tree was not specified, using current WORKSPACE instead!")
275 EccGlobalData
.gTarget
= os
.path
.normpath(os
.getenv("WORKSPACE"))
276 if Options
.keepdatabase
!= None:
278 if Options
.metadata
!= None and Options
.sourcecode
!= None:
279 EdkLogger
.error("ECC", BuildToolError
.OPTION_CONFLICT
, ExtraData
="-m and -s can't be specified at one time")
280 if Options
.metadata
!= None:
281 self
.ScanSourceCode
= False
282 if Options
.sourcecode
!= None:
283 self
.ScanMetaData
= False
287 # Set current log level of the tool based on args
289 # @param Option: The option list including log level setting
291 def SetLogLevel(self
, Option
):
292 if Option
.verbose
!= None:
293 EdkLogger
.SetLevel(EdkLogger
.VERBOSE
)
294 elif Option
.quiet
!= None:
295 EdkLogger
.SetLevel(EdkLogger
.QUIET
)
296 elif Option
.debug
!= None:
297 EdkLogger
.SetLevel(Option
.debug
+ 1)
299 EdkLogger
.SetLevel(EdkLogger
.INFO
)
301 ## Parse command line options
303 # Using standard Python module optparse to parse command line option of this tool.
305 # @retval Opt A optparse.Values object containing the parsed options
306 # @retval Args Target of build command
308 def EccOptionParser(self
):
309 Parser
= OptionParser(description
= self
.Copyright
, version
= self
.Version
, prog
= "Ecc.exe", usage
= "%prog [options]")
310 Parser
.add_option("-t", "--target sourcepath", action
="store", type="string", dest
='Target',
311 help="Check all files under the target workspace.")
312 Parser
.add_option("-c", "--config filename", action
="store", type="string", dest
="ConfigFile",
313 help="Specify a configuration file. Defaultly use config.ini under ECC tool directory.")
314 Parser
.add_option("-o", "--outfile filename", action
="store", type="string", dest
="OutputFile",
315 help="Specify the name of an output file, if and only if one filename was specified.")
316 Parser
.add_option("-r", "--reportfile filename", action
="store", type="string", dest
="ReportFile",
317 help="Specify the name of an report file, if and only if one filename was specified.")
318 Parser
.add_option("-e", "--exceptionfile filename", action
="store", type="string", dest
="ExceptionFile",
319 help="Specify the name of an exception file, if and only if one filename was specified.")
320 Parser
.add_option("-m", "--metadata", action
="store_true", type=None, help="Only scan meta-data files information if this option is specified.")
321 Parser
.add_option("-s", "--sourcecode", action
="store_true", type=None, help="Only scan source code files information if this option is specified.")
322 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.")
323 Parser
.add_option("-l", "--log filename", action
="store", dest
="LogFile", help="""If specified, the tool should emit the changes that
324 were made by the tool after printing the result message.
325 If filename, the emit to the file, otherwise emit to
326 standard output. If no modifications were made, then do not
327 create a log file, or output a log message.""")
328 Parser
.add_option("-q", "--quiet", action
="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
329 Parser
.add_option("-v", "--verbose", action
="store_true", type=None, help="Turn on verbose output with informational messages printed, "\
330 "including library instances selected, final dependency expression, "\
331 "and warning messages, etc.")
332 Parser
.add_option("-d", "--debug", action
="store", type="int", help="Enable debug messages at specified level.")
333 Parser
.add_option("-w", "--workspace", action
="store", type="string", dest
='Workspace', help="Specify workspace.")
335 (Opt
, Args
)=Parser
.parse_args()
341 # This acts like the main() function for the script, unless it is 'import'ed into another
344 if __name__
== '__main__':
345 # Initialize log system
346 EdkLogger
.Initialize()
347 EdkLogger
.IsRaiseError
= False
348 EdkLogger
.quiet(time
.strftime("%H:%M:%S, %b.%d %Y ", time
.localtime()) + "[00:00]" + "\n")
350 StartTime
= time
.clock()
352 FinishTime
= time
.clock()
354 BuildDuration
= time
.strftime("%M:%S", time
.gmtime(int(round(FinishTime
- StartTime
))))
355 EdkLogger
.quiet("\n%s [%s]" % (time
.strftime("%H:%M:%S, %b.%d %Y", time
.localtime()), BuildDuration
))