darshan-gen-cc.pl.in 4.89 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
#!/usr/bin/perl -w
#
#  (C) 2009 by Argonne National Laboratory.
#      See COPYRIGHT in top-level directory.
#

# takes a standard mpicc script as an argument and tried to generate a
# darshan-enabled mpicc script to mimic it's behavior

use Getopt::Long;
use English;

13 14 15 16
$CP_WRAPPERS="@CP_WRAPPERS@";
$DARSHAN_LIB_PATH="@darshan_lib_path@";
$CP_ZLIB_LINK_FLAGS="@__CP_ZLIB_LINK_FLAGS@";

17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
my $input_file = "";
my $output_file = "";

process_args();

# run original mpicc with -show argument to capture command line for
# compilation and linking
my $compile_cmd = `$input_file -show -c foo.c`;
if (!($compile_cmd))
{
    printf STDERR "Error: failed to invoke $input_file with -show\n";
    exit(1);
}

my $link_cmd = `$input_file -show foo.o -o foo`;
if (!($link_cmd))
{
    printf STDERR "Error: failed to invoke $input_file with -show\n";
    exit(1);
}

# check command lines for accuracy
if(!($compile_cmd =~ /-c foo.c/) || !($link_cmd =~ /foo.o -o foo/))
{
    printf STDERR "Error: faulty output from $input_file with -show.\n";
    exit(1);
}
44 45
chomp($compile_cmd);
chomp($link_cmd);
46 47 48

open (OUTPUT, ">$output_file") || die("Error opening output file: $!");

49
# substitute arguments and darshan options into commands
50 51 52
$base_link_cmd = $link_cmd;
$base_link_cmd =~ s/foo.o -o foo/"\$\{allargs\[\@\]\}"/g;
$link_cmd =~ s/foo.o -o foo/"\$\{allargs\[\@\]\}" -L$DARSHAN_LIB_PATH $CP_ZLIB_LINK_FLAGS -ldarshan-mpi-io -lz $CP_WRAPPERS/g;
53
$link_cmd =~ s/$/ -L$DARSHAN_LIB_PATH -ldarshan-posix/g;
54
$compile_cmd =~ s/-c foo.c/"\$\{allargs\[\@\]\}"/g;
55

56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
print OUTPUT <<'EOF';
#!/bin/sh
#
# Auto-generated mpicc script from darshan-gen-cc.pl
#
#
# Internal variables
# Show is set to echo to cause the compilation command to be echoed instead 
# of executed.
Show=

linking=yes
allargs=("$@")
argno=0
for arg in "$@" ; do
    # Set addarg to no if this arg should be ignored by the C compiler
    addarg=yes
    case "$arg" in 
 	# ----------------------------------------------------------------
	# Compiler options that affect whether we are linking or no
    -c|-S|-E|-M|-MM)
    # The compiler links by default
    linking=no
    ;;
    -show)
    addarg=no
    Show=echo
    ;;
    esac
    if [ $addarg = no ] ; then
	unset allargs[$argno]
    fi
    # Some versions of bash do not accept ((argno++))
    argno=`expr $argno + 1`
done
if [ "$linking" = yes ] ; then
    if [ -n "$C_LINKPATH_SHL" ] ; then
	# prepend the path for the shared libraries to the library list
	mpilibs="$C_LINKPATH_SHL$libdir $mpilibs"
    fi
96 97
EOF
print OUTPUT <<EOF;
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
    # Trial run to generate a symbol listing.  We only enable Darshan if:
    # a) MPI is used
    # b) PMPI is _not_ used
    #
    # We want Darshan to get out of the way if the user is doing a runtime
    # test in configure (in which case MPI objects break the executable) or
    # if the user is using another PMPI based tool

    used_darshan=0

    # create a temporary file
    tmpfile=`mktemp`
    # generate a map of the symbol names
    # don't use -shared for this step
    stock_link_cmd_no_shared=`echo \$base_link_cmd | sed 's/ -shared / /g'`
    \$stock_link_cmd_no_shared -Wl,-Map,\$tmpfile \$LDFLAGS -o /dev/null >& /dev/null
    # is MPI in there?
    grep MPI \$tmpfile >& /dev/null
    rc_mpi=\$?
    # is PMPI in there (except for the mpich library itself)?
    grep \\(PMPI \$tmpfile | grep -v mpich.cnk.a >& /dev/null
    rc_pmpi=\$?
    rm \$tmpfile >& /dev/null

    # disable darshan if the executable is not an MPI program (this feature
    # mainly allows runtime configure tests to work
    if [ \$rc_mpi -eq 0 ] ; then
        # disable darshan if something else is already using PMPI; we don't
        # want to cause any symbol conflicts
        if [ \$rc_pmpi -ne 0 ] ; then
            \$Show \$link_cmd
            used_darshan=1
        fi
    fi

    # otherwise use the normal command line
    if [ "\$used_darshan" = "0" ] ; then
        \$Show \$base_link_cmd
136 137
    fi
    rc=\$?
138
else
139 140
    \$Show $compile_cmd
    rc=\$?
141 142
fi

143
exit \$rc
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
EOF

close(OUTPUT);

chmod(0755, $output_file); 

exit(0);

sub process_args
{
    use vars qw( $opt_help $opt_output );

    Getopt::Long::Configure("no_ignore_case", "bundling");
    GetOptions( "help",
        "output=s");

    if($opt_help)
    {
        print_help();
        exit(0);
    }

    if($opt_output)
    {
        $output_file = $opt_output;
    }
    else
    {
        print_help();
        exit(1);
    }

    # there should only be one remaining argument: the input file 
    if($#ARGV != 0)
    {
        print "Error: invalid arguments.\n";
        print_help();
        exit(1);
    }
    $input_file = $ARGV[0];

    return;
}

sub print_help
{
    print <<EOF;

Usage: $PROGRAM_NAME <stock mpicc> --output <modified mpicc>

    --help          Prints this help message
    --output        Specifies name of output script

Purpose:

    This script takes an existing mpicc script as input and generates a
    modified version that includes Darshan support.

EOF
    return;
}