Subversion Repositories DevTools

Rev

Rev 255 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#! perl
########################################################################
# Copyright ( C ) 2004 ERG Limited, All rights reserved
#
# Module name   : gen_metrics.pl
# Module type   : JATS Makefile system
# Compiler(s)   : n/a
# Environment(s): JATS
#
# Description   : Post process the JATS build and makefiles and generate
#                 a collection of program metrics
#
# Usage:          JATS etool gen_metrics
#
# Version   Who     Date        Description
#           DDP     07-Dec-04   Created
#......................................................................#

require 5.006_001;

use strict;
use warnings;
use JatsError;
use JatsMakeInfo;
use ReadBuildConfig qw(:All);
use FileUtils;
use JatsSystem;
use JatsMakeConfig;

use Pod::Usage;                             # Required for help support
use Getopt::Long;                           # Option processing

#
#   Global variables
#
my  $VERSION = "1.0.0";                     # Update this
my  %source;                                # Source files
my  %include;                               # Local include directories
my  $cccc_path = "c:/Program Files/CCCC/cccc.exe";   # Path to CCCC utility
my  $cccc_out  = "./interface/cccc";        # Output directory

#
#   Global variables - Options
#
my  $opt_help = 0;
my  $opt_manual;
my  $opt_verbose = 0;
my  $opt_headers = 0;
my  $opt_cccc_path;

my $result = GetOptions (
                "help+"         => \$opt_help,              # flag, multiple use allowed
                "manual"        => \$opt_manual,            # flag, multiple use allowed
                "verbose+"      => \$opt_verbose,           # flag, multiple use allowed
                "headers!"      => \$opt_headers,           # Flag, +no allowed
                "cccc=s"        => \$opt_cccc_path          # String
                );

                #
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
                #

#-------------------------------------------------------------------------------
# Function        : Main entry point
#
# Description     : Parse user arguments
#                   Generate metrics
#
# Inputs          : None
#
# Returns         : Error code
#

#
#   Process help and manual options
#
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
pod2usage(-verbose => 1)  if ($opt_help == 2 );
pod2usage(-verbose => 2)  if ($opt_manual || ($opt_help > 2));

#
#   Configure the Error reporting process now that we have the user options
#
ErrorConfig( 'name'    =>'METRICS',
             'verbose' => $opt_verbose,
            );

#
#   Ensure that we are in a suitable directory
#   Need to be in the project root directory
#
Verbose ("Locate project root directory");

#
#   Locate the base of the JATS build
#   This will be provided by Makefile.gbe
#
ReadMakeInfo();
my $interface_path = "$::ScmRoot/$::ScmInterface";

#
#   Read in all the makefile data in one hit
#
my $mfdata = JatsMakeConfigReader::GetAllMakeInfo();
#   Sanity test of user options
#

if ( $opt_cccc_path )
{
    Error ("CCCC not found: $opt_cccc_path") unless ( -x $opt_cccc_path );
    $cccc_path = $opt_cccc_path;
}
Error ("CCCC not found: $cccc_path" ) unless ( -x "$cccc_path" );

#-------------------------------------------------------------------------------
#   Process all the constituent makefile data and buildup a list of source files
#
foreach my $dir ( $mfdata->AllDirs() )
{
    my $mff = $mfdata->GetEntry($dir);

    Verbose ("Processing: $dir");

    foreach my $tgt ( $mff->GetPlatforms() )
    {
        my $cwd = $mff->GetDataItem($tgt, '$Cwd');
        Verbose( "Target: $tgt, CWD: $cwd\n");

        #
        #   Locate all the C, C++ and headers
        #   I don't think JATS handles Java file at the moment
        #
        foreach my $var ( '@CXXSRCS' ,'@CSRCS', '@CHDRS' )
        {
            if ( my $data = $mff->GetDataItem($tgt, $var) )
            {
                Verbose2( "$var : @{$data}");
                foreach my $file ( @$data )
                {
                    #
                    #   Add the makefile's CWD to the file unless the file
                    #   already has an absolute path
                    #
                    $file = $cwd . "/" . $file unless ( $file =~ m~^/~ );
                    unless ( $source{$file} )
                    {
                        $source{$file} = 1;
                        Verbose ("Adding: $file");
                    }
                }
            }
        }

        #
        #   Locate all the included directories in case we need
        #   an exhaustive search of all header files
        #
        foreach my $var ( '@INCDIRS' )
        {
            if ( my $data = $mff->GetDataItem($tgt, $var) )
            {
                Verbose2( "$var : @{$data}");
                foreach my $dir ( @$data )
                {
                    #
                    #   Add the makefile's CWD to the file unless the file
                    #   already has an absolute path
                    #
                    $dir = $cwd . "/" . $dir unless ( $dir =~ m~^/~ );
                    unless ( $include{$dir} )
                    {
                        $include{$dir} = 1;
                        Verbose ("Adding dir: $dir");
                    }
                }
            }
        }
    }
}

#-------------------------------------------------------------------------------
#   Now have a complete list of files that are specified as source files
#   within all the project makefile.pl's, but these are not all the source
#   files as the included header files are not mentioned
#
#   This may be sufficient as it is a list of the interface file
#
#   If requested add all the header files from all the include directories
if ( $opt_headers )
{
    foreach my $dir ( keys %include )
    {
        my @files = glob ( "$dir/*.h" );
        foreach my $file ( @files )
        {
            unless ( $source{$file} )
            {
                $source{$file} = 1;
                Verbose ("Adding header: $file");
            }
        }
    }
}

#-------------------------------------------------------------------------------
#   Kick of the CCCC processing of all the discovered source files
#   Remove any existing CCCC output
#
    System ("rm -rf $cccc_out");
    System ("mkdir -p $cccc_out");

    my @file_list = sort keys( %source );
    System ("\"$cccc_path\" --outdir=$cccc_out @file_list");

    # --debug_mask=plc

    exit;

#-------------------------------------------------------------------------------
#   Documentation
#

=pod

=for htmltoc    SYSUTIL::

=head1 NAME

gen_metrics - Create Metrics

=head1 SYNOPSIS

 jats etool gen_metrics [options]

 Options:
    -help              - Brief help message
    -help -help        - Detailed help message
    -man               - Full documentation
    -verbose           - Verbose display of operation
    -cccc=path         - Alternate location of the CCCC program
    -[no]headers       - Add all headers files from included subdirectories

=head1 OPTIONS

=over 8

=item B<-help>

Print a brief help message and exits.

=item B<-help -help>

Print a detailed help message with an explanation for each option.

=item B<-man>

Prints the manual page and exits.

=item B<-verbose>

Prints internal information during the execution of the script. This option
does not affect the operation of the underlying CCCC program

=item B<-cccc=path>

This option specifies the absolute path of the F<CCCC.EXE> utility program. The
default operation looks for "cccc" in its standard installed location. Under
Windows this is F<c:/Program Files/CCCC/cccc.exe>

=item B<-[no]headers>

Includes all the ".h" files in directories named in "IncDir" directives.
The default operation is "noheaders"

=back

=head1 DESCRIPTION

The program uses a utility called CCCC to generate a variety of static
program metrics including:

=over 8

=item *

Lines of Code

=item *

Comment Lines

=item  *

McCabe's Cyclomatic Complexity

=back

CCCC is a tool for the analysis of source code in various languages (primarily
C++), which generates a report in HTML format on various measurements of the
code processed. Although the tool was originally implemented to process C++ and
ANSI C, the present version is also able to process Java source files, and
support has been present in earlier versions for Ada95. The name CCCC stands for
'C and C++ Code Counter'.

This program uses the information generated by the "JATS BUILD" process to
determine a list of files to been processed by the utility. Files for
inclusion are:

=over 4

=item *

Files specified with a "Src" directive
Only C, C++ and Header files are included

=item *

All headers files in directories named in a "AddIncDir" or
"AddDir" directive. This operation is not default. It must
been invoked with the "-header" option

=back

The CCCC program generates a number of output files in the interface/cccc
directory. The main files of interest are:

=over 4

=item *

cccc.html - Main output file

=item *

anonymous.html - Details of "C" files by function.
This file contains information that is not present in the
summary file.

=back

CCCC also generates a series of XML files that contains the same information
as the HTML files.

=head1 USAGE

The gen_metrics program uses information extracted from the build.pl and
makefile.pl files when the sandbox build environment is created. This
information is generated by the JATS BUILD command. This command must been run
before the gen_metrics program.

The gen_metrics program is an extension to the JATS framework. It must be run
within the JATS framework and not standalone.

=head2  Example

The following command will generate a set of metrics for the files in a sandbox.
It is assumed that the user is in the same directory as the packages build.pl
script.

    jats build
    jats etool gen_metrics.pl

This command sequence will do the following:

=over 4

=item C<jats build>

This will build the sandbox, generate makefile files and store information
extracted from the makefile.pl for possible post processing.

This command does not have to immediately preceed the metrics generation
command, but it does need to be performed at some stage before the metrics
cane be generated.

=item C<jats etool gen_metrics.pl>

This will post process the stored information and determine the source files
for the package, before running the CCCC utility over the files.

=back

=cut