darshan-gen-cc.pl.in 7.17 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
my $input_file = "";
my $output_file = "";
19
my $trim_exe_path = 0;
20
my $xl_check=0;
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

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);
}
46 47
chomp($compile_cmd);
chomp($link_cmd);
48

49 50 51 52 53 54 55 56 57 58 59 60 61 62
#
# Incomprehensible re to eat the leading path of the compiler command
# and only give the basename.
#
# /cmd -> cmd
# cmd -> cmd
# /x/y/x/z/cmd -> cmd
#
if ($trim_exe_path)
{
    $compile_cmd =~ s/\/*([^\/ ]+\/)*//;
    $link_cmd =~ s/\/*([^\/ ]+\/)*//;
}

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

65
# substitute arguments and darshan options into commands
66 67
$base_link_cmd = $link_cmd;
$base_link_cmd =~ s/foo.o -o foo/"\$\{allargs\[\@\]\}"/g;
68
$link_cmd =~ s/foo.o -o foo/"\$\{newallargs\[\@\]\}" -L$DARSHAN_LIB_PATH $CP_ZLIB_LINK_FLAGS -ldarshan-mpi-io -lz $CP_WRAPPERS/g;
69
$link_cmd =~ s/$/ -L$DARSHAN_LIB_PATH -ldarshan-posix/g;
70
$compile_cmd =~ s/-c foo.c/"\$\{allargs\[\@\]\}"/g;
71

72 73 74 75
# create link cmd with noshrargs variable
$link_cmd_no_shared = $base_link_cmd;
$link_cmd_no_shared =~ s/allargs/noshrargs/;

Philip Carns's avatar
Philip Carns committed
76
print OUTPUT<<'EOF';
Philip Carns's avatar
Philip Carns committed
77
#!/bin/bash
78 79 80 81 82 83 84 85
#
# 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=
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
EOF

if ($xl_check == 1)
{
print OUTPUT<<'EOF';
#
# Check for IBM XL Linker Parameters
#
# If IPA linker is used, we must disable darshan
# because the IPA linker doesn't support -wrap.
#
function check_XL()
{
    arg=$1;
    ipa_enabled=0;

    if [ "$arg" = "-O5" ]; then
        ipa_enabled=1;
    fi 
    if [ "$arg" = "-O4" ]; then
        ipa_enabled=1;
    fi 
    if [ "$arg" = "-qipa" ]; then
        ipa_enabled=1;
    fi

    return $ipa_enabled;
}
EOF
}
116

117
print OUTPUT<<'EOF';
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
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
147
EOF
Philip Carns's avatar
Philip Carns committed
148
print OUTPUT<<"EOF";
149 150 151 152 153 154 155 156
    # 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

157 158
    # if allargs includes any libraries, then we need to get 
    # -ldarshan-mpi-io in there first
159 160
    argno=0;
    once=0;
161
    compiler_check=0;
162 163
    newallargs=\("\$\{allargs\[\@\]\}"\);
    for arg in "\$\{newallargs\[\@\]\}"; do
164
        res=`expr match "\$arg" "-l"`;
165 166 167 168 169 170 171 172
        if [ \$res -gt 0 -a \$once -lt 1 ]; then
            newallargs[\$argno]=-ldarshan-mpi-io
            argno=`expr \$argno + 1`
            newallargs[\$argno]=\$arg;
            once=1;
        else
            newallargs[\$argno]=\$arg;
        fi
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
EOF

#
# Add any functional tests for linker parameters
#
       if ($xl_check)
       {
print OUTPUT<<"EOF";
           check_XL "\$arg";
           if [ \$? -ne 0 ]; then
               compiler_check=1;
           fi
EOF
       }

print OUTPUT<<"EOF";
189 190
        argno=`expr \$argno + 1`
    done
191

192 193 194 195 196 197
    used_darshan=0

    # create a temporary file
    tmpfile=`mktemp`
    # generate a map of the symbol names
    # don't use -shared for this step
198 199 200 201 202 203 204 205 206 207
    argno=0
    noshrargs=\("\$\{allargs\[\@\]\}");
    for arg in "\$\{noshrargs\[\@\]\}"; do
        if [ "\$arg" = "-shared" ]; then
            unset noshrarg[\$argno];
        fi
        argno=`expr \$argno + 1`
    done
    $link_cmd_no_shared -Wl,-Map,\$tmpfile \$LDFLAGS -o /dev/null >& /dev/null

208 209 210
    # is MPI in there?
    grep MPI \$tmpfile >& /dev/null
    rc_mpi=\$?
211 212
    # is PMPI being used for any init, finalize, or mpi-io calls?
    grep -E \\(PMPI_File_\\)\\|\\(PMPI_Init\\)\\|\\(PMPI_Finalize\\) \$tmpfile | grep -v -E \\(mpich.cnk.a\\|mpich.a\\) |grep \\(PMPI >& /dev/null
213 214 215 216 217 218 219 220
    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
221
        if [ \$rc_pmpi -ne 0 ] && [ \$compiler_check -eq 0 ]; then
Philip Carns's avatar
Philip Carns committed
222
            \$Show $link_cmd
223 224 225 226 227 228
            used_darshan=1
        fi
    fi

    # otherwise use the normal command line
    if [ "\$used_darshan" = "0" ] ; then
Philip Carns's avatar
Philip Carns committed
229
        \$Show $base_link_cmd
230 231
    fi
    rc=\$?
232
else
233 234
    \$Show $compile_cmd
    rc=\$?
235 236
fi

237
exit \$rc
238 239 240 241 242 243 244 245 246 247
EOF

close(OUTPUT);

chmod(0755, $output_file); 

exit(0);

sub process_args
{
248
    use vars qw( $opt_help $opt_output $opt_trim $opt_xl );
249 250 251

    Getopt::Long::Configure("no_ignore_case", "bundling");
    GetOptions( "help",
252
        "output=s",
253 254
        "trim",
        "xl");
255 256 257 258 259 260 261

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

262 263 264 265 266
    if($opt_trim)
    {
        $trim_exe_path=1;
    }

267 268 269 270 271
    if($opt_xl)
    {
        $xl_check=1;
    }

272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
    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
{
Philip Carns's avatar
Philip Carns committed
296
    print<<"EOF";
297 298 299 300 301

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

    --help          Prints this help message
    --output        Specifies name of output script
302
    --trim          Trim the compilers path
303 304
    --xl            Disables darshan if certain linker parameters are used
                    (Intended for IBM XL Compilers)
305 306 307 308 309 310 311 312 313 314

Purpose:

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

EOF
    return;
}