2009-07-17 11:10:31 +02:00
## @file
# This file is used to be the main entrance of ECC tool
#
# Copyright (c) 2009, Intel Corporation
# All rights reserved. This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
# Import Modules
#
import os , time , glob , sys
import Common . EdkLogger as EdkLogger
import Database
import EccGlobalData
from MetaDataParser import *
from optparse import OptionParser
from Configuration import Configuration
from Check import Check
from Common . InfClassObject import Inf
from Common . DecClassObject import Dec
from Common . DscClassObject import Dsc
from Common . FdfClassObject import Fdf
from Common . String import NormPath
from Common import BuildToolError
import c
2009-09-11 05:14:43 +02:00
import re , string
2009-07-17 11:10:31 +02:00
from Exception import *
## Ecc
#
# This class is used to define Ecc main entrance
#
# @param object: Inherited from object class
#
class Ecc ( object ) :
def __init__ ( self ) :
# Version and Copyright
self . VersionNumber = " 0.01 "
self . Version = " % prog Version " + self . VersionNumber
self . Copyright = " Copyright (c) 2009, Intel Corporation All rights reserved. "
self . InitDefaultConfigIni ( )
self . OutputFile = ' output.txt '
self . ReportFile = ' Report.csv '
self . ExceptionFile = ' exception.xml '
self . IsInit = True
self . ScanSourceCode = True
self . ScanMetaData = True
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
# Parse the options and args
self . ParseOption ( )
# Generate checkpoints list
EccGlobalData . gConfig = Configuration ( self . ConfigFile )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
# Generate exception list
EccGlobalData . gException = ExceptionCheck ( self . ExceptionFile )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
# Init Ecc database
EccGlobalData . gDb = Database . Database ( Database . DATABASE_PATH )
EccGlobalData . gDb . InitDatabase ( self . IsInit )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
# Build ECC database
self . BuildDatabase ( )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
# Start to check
self . Check ( )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
# Show report
self . GenReport ( )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
# Close Database
EccGlobalData . gDb . Close ( )
def InitDefaultConfigIni ( self ) :
paths = map ( lambda p : os . path . join ( p , ' Ecc ' , ' config.ini ' ) , sys . path )
paths = ( os . path . realpath ( ' config.ini ' ) , ) + tuple ( paths )
for path in paths :
if os . path . exists ( path ) :
self . ConfigFile = path
return
self . ConfigFile = ' config.ini '
## BuildDatabase
#
# Build the database for target
#
def BuildDatabase ( self ) :
# Clean report table
EccGlobalData . gDb . TblReport . Drop ( )
EccGlobalData . gDb . TblReport . Create ( )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
# Build database
if self . IsInit :
if self . ScanSourceCode :
EdkLogger . quiet ( " Building database for source code ... " )
c . CollectSourceCodeDataIntoDB ( EccGlobalData . gTarget )
if self . ScanMetaData :
EdkLogger . quiet ( " Building database for source code done! " )
self . BuildMetaDataFileDatabase ( )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
EccGlobalData . gIdentifierTableList = GetTableList ( ( MODEL_FILE_C , MODEL_FILE_H ) , ' Identifier ' , EccGlobalData . gDb )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
## BuildMetaDataFileDatabase
#
# Build the database for meta data files
#
def BuildMetaDataFileDatabase ( self ) :
EdkLogger . quiet ( " Building database for meta data files ... " )
Op = open ( EccGlobalData . gConfig . MetaDataFileCheckPathOfGenerateFileList , ' w+ ' )
#SkipDirs = Read from config file
SkipDirs = EccGlobalData . gConfig . SkipDirList
2009-09-11 05:14:43 +02:00
SkipDirString = string . join ( SkipDirs , ' | ' )
p = re . compile ( r ' .*[ \\ /](?: %s )[ \\ /]?.* ' % SkipDirString )
2009-07-17 11:10:31 +02:00
for Root , Dirs , Files in os . walk ( EccGlobalData . gTarget ) :
2009-09-11 05:14:43 +02:00
if p . match ( Root . upper ( ) ) :
continue
2009-07-17 11:10:31 +02:00
for Dir in Dirs :
Dirname = os . path . join ( Root , Dir )
if os . path . islink ( Dirname ) :
Dirname = os . path . realpath ( Dirname )
if os . path . isdir ( Dirname ) :
# symlinks to directories are treated as directories
Dirs . remove ( Dir )
Dirs . append ( Dirname )
for File in Files :
if len ( File ) > 4 and File [ - 4 : ] . upper ( ) == " .DEC " :
Filename = os . path . normpath ( os . path . join ( Root , File ) )
EdkLogger . quiet ( " Parsing %s " % Filename )
Op . write ( " %s \r " % Filename )
Dec ( Filename , True , True , EccGlobalData . gWorkspace , EccGlobalData . gDb )
continue
if len ( File ) > 4 and File [ - 4 : ] . upper ( ) == " .DSC " :
Filename = os . path . normpath ( os . path . join ( Root , File ) )
EdkLogger . quiet ( " Parsing %s " % Filename )
Op . write ( " %s \r " % Filename )
Dsc ( Filename , True , True , EccGlobalData . gWorkspace , EccGlobalData . gDb )
continue
if len ( File ) > 4 and File [ - 4 : ] . upper ( ) == " .INF " :
Filename = os . path . normpath ( os . path . join ( Root , File ) )
EdkLogger . quiet ( " Parsing %s " % Filename )
Op . write ( " %s \r " % Filename )
Inf ( Filename , True , True , EccGlobalData . gWorkspace , EccGlobalData . gDb )
continue
if len ( File ) > 4 and File [ - 4 : ] . upper ( ) == " .FDF " :
Filename = os . path . normpath ( os . path . join ( Root , File ) )
EdkLogger . quiet ( " Parsing %s " % Filename )
Op . write ( " %s \r " % Filename )
2009-09-11 05:14:43 +02:00
Fdf ( Filename , True , EccGlobalData . gWorkspace , EccGlobalData . gDb )
2009-07-17 11:10:31 +02:00
continue
Op . close ( )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
# Commit to database
EccGlobalData . gDb . Conn . commit ( )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
EdkLogger . quiet ( " Building database for meta data files done! " )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
##
#
# Check each checkpoint
#
def Check ( self ) :
EdkLogger . quiet ( " Checking ... " )
EccCheck = Check ( )
EccCheck . Check ( )
EdkLogger . quiet ( " Checking done! " )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
##
#
# Generate the scan report
#
def GenReport ( self ) :
EdkLogger . quiet ( " Generating report ... " )
EccGlobalData . gDb . TblReport . ToCSV ( self . ReportFile )
EdkLogger . quiet ( " Generating report done! " )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
def GetRealPathCase ( self , path ) :
TmpPath = path . rstrip ( os . sep )
PathParts = TmpPath . split ( os . sep )
if len ( PathParts ) == 0 :
return path
if len ( PathParts ) == 1 :
if PathParts [ 0 ] . strip ( ) . endswith ( ' : ' ) :
return PathParts [ 0 ] . upper ( )
# Relative dir, list . current dir
Dirs = os . listdir ( ' . ' )
for Dir in Dirs :
if Dir . upper ( ) == PathParts [ 0 ] . upper ( ) :
return Dir
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
if PathParts [ 0 ] . strip ( ) . endswith ( ' : ' ) :
PathParts [ 0 ] = PathParts [ 0 ] . upper ( )
ParentDir = PathParts [ 0 ]
RealPath = ParentDir
if PathParts [ 0 ] == ' ' :
RealPath = os . sep
ParentDir = os . sep
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
PathParts . remove ( PathParts [ 0 ] ) # need to remove the parent
for Part in PathParts :
Dirs = os . listdir ( ParentDir + os . sep )
for Dir in Dirs :
if Dir . upper ( ) == Part . upper ( ) :
RealPath + = os . sep
RealPath + = Dir
break
ParentDir + = os . sep
ParentDir + = Dir
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
return RealPath
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
## ParseOption
#
# Parse options
#
def ParseOption ( self ) :
EdkLogger . quiet ( " Loading ECC configuration ... done " )
( Options , Target ) = self . EccOptionParser ( )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
# Check workspace envirnoment
if " WORKSPACE " not in os . environ :
2009-09-11 05:14:43 +02:00
EdkLogger . error ( " ECC " , BuildToolError . ATTRIBUTE_NOT_AVAILABLE , " Environment variable not found " ,
2009-07-17 11:10:31 +02:00
ExtraData = " WORKSPACE " )
else :
EccGlobalData . gWorkspace = os . path . normpath ( os . getenv ( " WORKSPACE " ) )
if not os . path . exists ( EccGlobalData . gWorkspace ) :
EdkLogger . error ( " ECC " , BuildToolError . FILE_NOT_FOUND , ExtraData = " WORKSPACE = %s " % EccGlobalData . gWorkspace )
os . environ [ " WORKSPACE " ] = EccGlobalData . gWorkspace
# Set log level
self . SetLogLevel ( Options )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
# Set other options
if Options . ConfigFile != None :
self . ConfigFile = Options . ConfigFile
if Options . OutputFile != None :
self . OutputFile = Options . OutputFile
if Options . ReportFile != None :
self . ReportFile = Options . ReportFile
if Options . Target != None :
if not os . path . isdir ( Options . Target ) :
EdkLogger . error ( " ECC " , BuildToolError . OPTION_VALUE_INVALID , ExtraData = " Target [ %s ] does NOT exist " % Options . Target )
else :
EccGlobalData . gTarget = self . GetRealPathCase ( os . path . normpath ( Options . Target ) )
else :
EdkLogger . warn ( " Ecc " , EdkLogger . ECC_ERROR , " The target source tree was not specified, using current WORKSPACE instead! " )
EccGlobalData . gTarget = os . path . normpath ( os . getenv ( " WORKSPACE " ) )
if Options . keepdatabase != None :
self . IsInit = False
if Options . metadata != None and Options . sourcecode != None :
EdkLogger . error ( " ECC " , BuildToolError . OPTION_CONFLICT , ExtraData = " -m and -s can ' t be specified at one time " )
if Options . metadata != None :
self . ScanSourceCode = False
if Options . sourcecode != None :
self . ScanMetaData = False
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
## SetLogLevel
#
# Set current log level of the tool based on args
#
2009-09-11 05:14:43 +02:00
# @param Option: The option list including log level setting
2009-07-17 11:10:31 +02:00
#
def SetLogLevel ( self , Option ) :
if Option . verbose != None :
EdkLogger . SetLevel ( EdkLogger . VERBOSE )
elif Option . quiet != None :
EdkLogger . SetLevel ( EdkLogger . QUIET )
elif Option . debug != None :
EdkLogger . SetLevel ( Option . debug + 1 )
else :
EdkLogger . SetLevel ( EdkLogger . INFO )
## Parse command line options
#
# Using standard Python module optparse to parse command line option of this tool.
#
# @retval Opt A optparse.Values object containing the parsed options
# @retval Args Target of build command
#
def EccOptionParser ( self ) :
Parser = OptionParser ( description = self . Copyright , version = self . Version , prog = " Ecc.exe " , usage = " % prog [options] " )
Parser . add_option ( " -t " , " --target sourcepath " , action = " store " , type = " string " , dest = ' Target ' ,
help = " Check all files under the target workspace. " )
Parser . add_option ( " -c " , " --config filename " , action = " store " , type = " string " , dest = " ConfigFile " ,
help = " Specify a configuration file. Defaultly use config.ini under ECC tool directory. " )
Parser . add_option ( " -o " , " --outfile filename " , action = " store " , type = " string " , dest = " OutputFile " ,
help = " Specify the name of an output file, if and only if one filename was specified. " )
Parser . add_option ( " -r " , " --reportfile filename " , action = " store " , type = " string " , dest = " ReportFile " ,
help = " Specify the name of an report file, if and only if one filename was specified. " )
Parser . add_option ( " -m " , " --metadata " , action = " store_true " , type = None , help = " Only scan meta-data files information if this option is specified. " )
Parser . add_option ( " -s " , " --sourcecode " , action = " store_true " , type = None , help = " Only scan source code files information if this option is specified. " )
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. " )
2009-09-11 05:14:43 +02:00
Parser . add_option ( " -l " , " --log filename " , action = " store " , dest = " LogFile " , help = """ If specified, the tool should emit the changes that
were made by the tool after printing the result message .
If filename , the emit to the file , otherwise emit to
standard output . If no modifications were made , then do not
2009-07-17 11:10:31 +02:00
create a log file , or output a log message . """ )
Parser . add_option ( " -q " , " --quiet " , action = " store_true " , type = None , help = " Disable all messages except FATAL ERRORS. " )
Parser . add_option ( " -v " , " --verbose " , action = " store_true " , type = None , help = " Turn on verbose output with informational messages printed, " \
" including library instances selected, final dependency expression, " \
" and warning messages, etc. " )
Parser . add_option ( " -d " , " --debug " , action = " store " , type = " int " , help = " Enable debug messages at specified level. " )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
( Opt , Args ) = Parser . parse_args ( )
2009-09-11 05:14:43 +02:00
2009-07-17 11:10:31 +02:00
return ( Opt , Args )
##
#
# This acts like the main() function for the script, unless it is 'import'ed into another
# script.
#
if __name__ == ' __main__ ' :
# Initialize log system
EdkLogger . Initialize ( )
EdkLogger . IsRaiseError = False
EdkLogger . quiet ( time . strftime ( " % H: % M: % S, % b. %d % Y " , time . localtime ( ) ) + " [00:00] " + " \n " )
StartTime = time . clock ( )
Ecc = Ecc ( )
FinishTime = time . clock ( )
BuildDuration = time . strftime ( " % M: % S " , time . gmtime ( int ( round ( FinishTime - StartTime ) ) ) )
EdkLogger . quiet ( " \n %s [ %s ] " % ( time . strftime ( " % H: % M: % S, % b. %d % Y " , time . localtime ( ) ) , BuildDuration ) )