1#! /bin/sh
2##
3## Copyright (C) by Argonne National Laboratory
4##     See COPYRIGHT in top-level directory
5##
6
7# Simple script to compile and/or link MPI programs.
8# This script knows the default flags and libraries, and can handle
9# alternative C compilers and the associated flags and libraries.
10# The important terms are:
11#    includedir, libdir - Directories containing an *installed* mpich
12#    prefix, execprefix - Often used to define includedir and libdir
13#    FC                 - Fortran 90 compiler
14#    WRAPPER_FCFLAGS    - Any special flags needed to compile
15#    WRAPPER_LDFLAGS    - Any special flags needed to link
16#    WRAPPER_LIBS       - Any special libraries needed in order to link
17#    FC_OTHER_LIBS      - Yet more libraries, needed just with FC
18#
19# We assume that (a) the C compiler can both compile and link programs
20#
21# Handling of command-line options:
22#   This is a little tricky because some options may contain blanks.
23#
24# Special issues with shared libraries - todo
25#
26# --------------------------------------------------------------------------
27# Set the default values of all variables.
28#
29# Directory locations: Fixed for any MPI implementation.
30# Set from the directory arguments to configure (e.g., --prefix=/usr/local)
31prefix=__PREFIX_TO_BE_FILLED_AT_INSTALL_TIME__
32exec_prefix=__EXEC_PREFIX_TO_BE_FILLED_AT_INSTALL_TIME__
33sysconfdir=__SYSCONFDIR_TO_BE_FILLED_AT_INSTALL_TIME__
34includedir=__INCLUDEDIR_TO_BE_FILLED_AT_INSTALL_TIME__
35libdir=__LIBDIR_TO_BE_FILLED_AT_INSTALL_TIME__
36modincdir=@modincdir@
37
38# Default settings for compiler, flags, and libraries
39# Determined by a combination of environment variables and tests within
40# configure (e.g., determining whehter -lsocket is needee)
41FC="@FC@"
42FCCPP="@FCCPP@"
43#
44# Fortran 90 Compiler characteristics
45FCINC="@FCINC@"
46# f90modinc specifies how to add a directory to the search path for modules.
47# Some compilers (Intel ifc version 5) do not support this concept, and
48# instead need
49# a specific list of files that contain module names and directories.
50# The FCMODINCSPEC is a more general approach that uses <dir> and <file>
51# for the directory and file respectively.
52FCMODINC="@FCMODINCFLAG@"
53FCMODINCSPEC="@FCMODINCSPEC@"
54FCEXT="@FCEXT@"
55#
56MPICH_VERSION="@MPICH_VERSION@"
57
58@fc_shlib_conf@
59
60# Attempt to construct dynamic loading info, based on the user
61# preference of rpath, runpath or none and on the detected libdir
62# flags.
63with_wrapper_dl_type=@with_wrapper_dl_type@
64if test "X${with_wrapper_dl_type}" = "Xrunpath" ; then
65    eval wrapper_dl_type_flags=\"${hardcode_libdir_flag_spec} ${enable_dtags_flag}\"
66elif test "X${with_wrapper_dl_type}" = "Xrpath" ; then
67    eval wrapper_dl_type_flags=\"${hardcode_libdir_flag_spec} ${disable_dtags_flag}\"
68else
69    wrapper_dl_type_flags=""
70fi
71
72# Internal variables
73# Show is set to echo to cause the compilation command to be echoed instead
74# of executed.
75Show=eval
76#
77# End of initialization of variables
78#---------------------------------------------------------------------
79# Environment Variables.
80# The environment variables MPICH_FC may be used to override the
81# default choices.
82# In addition, if there is a file $sysconfdir/mpifort-$FCname.conf,
83# where FCname is the name of the compiler with all spaces replaced by hyphens
84# (e.g., "fc -64" becomes "fc--64", that file is sources, allowing other
85# changes to the compilation environment.  See the variables used by the
86# script (defined above)
87# Added MPICH_FC_OLD, MPICH_FC can be used to prefix FC with external utility,
88# e.g. setenv MPICH_FC 'eval linkcache $MPICH_FC_OLD'
89if [ -n "$MPICH_FC" ] ; then
90    MPICH_FC_OLD="$FC"
91    FC="$MPICH_FC"
92    FCname=`echo $FC | sed 's/ /-/g'`
93    if [ -s $sysconfdir/mpifort-$FCname.conf ] ; then
94        . $sysconfdir/mpifort-$FCname.conf
95    fi
96fi
97# Allow a profiling option to be selected through an environment variable
98if [ -n "$MPIFORT_PROFILE" ] ; then
99    profConf=$MPIFORT_PROFILE
100fi
101#
102# ------------------------------------------------------------------------
103# Argument processing.
104# This is somewhat awkward because of the handling of arguments within
105# the shell.  We want to handle arguments that include spaces without
106# loosing the spacing (an alternative would be to use a more powerful
107# scripting language that would allow us to retain the array of values,
108# which the basic (rather than enhanced) Bourne shell does not.
109#
110# Look through the arguments for arguments that indicate compile only.
111# If these are *not* found, add the library options
112#
113linking=yes
114allargs=""
115interlib_deps=yes
116static_mpi=no
117for arg in "$@" ; do
118    # Set addarg to no if this arg should be ignored by the C compiler
119    addarg=yes
120    qarg=$arg
121    case $arg in
122	# ----------------------------------------------------------------
123	# Compiler options that affect whether we are linking or no
124    -c|-S|-E|-M|-MM)
125    # The compiler links by default
126    linking=no
127    ;;
128	# ----------------------------------------------------------------
129	# Options that control how we use mpifort (e.g., -show,
130	# -fc=* -config=*
131    -static)
132    interlib_deps=no
133    ;;
134    -static-mpi)
135    interlib_deps=no
136    static_mpi=yes
137    addarg=no
138    ;;
139    -echo)
140    addarg=no
141    set -x
142    ;;
143    -fc=*)
144    FC=`echo A$arg | sed -e 's/A-fc=//g'`
145    addarg=no
146    ;;
147    -fc=*)
148    FC=`echo A$arg | sed -e 's/A-fc=//g'`
149    addarg=no
150    ;;
151    -show)
152    addarg=no
153    Show=echo
154    ;;
155    -config=*)
156    addarg=no
157    FCname=`echo A$arg | sed -e 's/A-config=//g'`
158    if [ -s "$sysconfdir/mpifort-$FCname.conf" ] ; then
159        . "$sysconfdir/mpifort-$FCname.conf"
160    else
161	echo "Configuration file mpifort-$FCname.conf not found"
162    fi
163    ;;
164    -compile-info|-compile_info)
165    # -compile_info included for backward compatibility
166    Show=echo
167    addarg=no
168    ;;
169    -link-info|-link_info)
170    # -link_info included for backward compatibility
171    Show=echo
172    addarg=no
173    ;;
174    -v)
175    # Pass this argument to the compiler as well.
176    echo "mpifort for MPICH version $MPICH_VERSION"
177    # if there is only 1 argument, it must be -v.
178    if [ "$#" -eq "1" ] ; then
179        linking=no
180    fi
181    ;;
182    -profile=*)
183    # Pass the name of a profiling configuration.  As
184    # a special case, lib<name>.so or lib<name>.la may be used
185    # if the library is in $libdir
186    profConf=`echo A$arg | sed -e 's/A-profile=//g'`
187    addarg=no
188    # Loading the profConf file is handled below
189    ;;
190    -nativelinking)
191    # Internal option to use native compiler for linking without MPI libraries
192    nativelinking=yes
193    addarg=no
194    ;;
195    -help)
196    NC=`echo "$FC" | sed 's%\/% %g' | awk '{print $NF}' -`
197    if [ -f "$sysconfdir/mpixxx_opts.conf" ] ; then
198        . $sysconfdir/mpixxx_opts.conf
199        echo "    -fc=xxx       - Reset the native compiler to xxx."
200    else
201        if [ -f "./mpixxx_opts.conf" ] ; then
202            . ./mpixxx_opts.conf
203            echo "    -fc=xxx       - Reset the native compiler to xxx."
204        fi
205    fi
206    exit 0
207    ;;
208        # -----------------------------------------------------------------
209	# Other arguments.  We are careful to handle arguments with
210	# quotes (we try to quote all arguments in case they include
211	# any spaces)
212    *\"*)
213    qarg="'"$arg"'"
214    case $arg in
215       -D*)
216       cppflags="$cppflags $qarg"
217       ;;
218    esac
219    ;;
220    *\'*)
221    qarg='\"'"$arg"'\"'
222    case $arg in
223       -D*)
224       cppflags="$cppflags $qarg"
225       ;;
226    esac
227    ;;
228    # The following are special args used to handle .F files when the
229    # Fortran compiler itself does not handle these options
230    -I*)
231    cppflags="$cppflags $arg"
232    ;;
233    -D*)
234    cppflags="$cppflags $arg"
235    ;;
236    *.F|*.F90|.fpp|.FPP)
237# If FCCPP is not empty, then we need to do the following:
238#    If any input files have the .F or .F90 extension, then
239#        If FCCPP = false, then
240#            generate an error message and exit
241#        Use FCCPP to convert the file from .F to .f, using
242#            $TMPDIR/f$$-$count.f as the output file name
243#            Replace the input file with this name in the args
244# This is needed only for very broken systems
245#
246    if [ -n "$FCCPP" ] ; then
247        if [ "$FCCPP" = "false" ] ; then
248            echo "This Fortran compiler does not accept .F or .F90 files"
249	    exit 1
250        fi
251        addarg=no
252	# Remove and directory names and extension
253	$ext=`expr "$arg" : '.*\(\..*\)'`
254        bfile=`basename $arg $ext`
255	#
256	TMPDIR=${TMPDIR:-/tmp}
257	# Make sure that we use a valid extension for the temp file.
258        tmpfile=$TMPDIR/f$$-$bfile.$FCEXT
259        if $FCCPP $cppflags $arg > $tmpfile ; then
260            # Add this file to the commandline list
261	    count=`expr $count + 1`
262	    allargs="$allargs $tmpfile"
263	    rmfiles="$rmfiles $tmpfile"
264        else
265	    echo "Aborting compilation because of failure in preprocessing step"
266	    echo "for file $arg ."
267	    exit 1
268        fi
269    fi
270    # Otherwise, just accept the argument
271    ;;
272    # - end of special handling for .F files
273
274    *)
275    qarg="'$arg'"
276    ;;
277
278    esac
279    if [ $addarg = yes ] ; then
280        allargs="$allargs $qarg"
281    fi
282done
283
284if [ $# -eq 0 ] ; then
285    echo "Error: Command line argument is needed!"
286    "$0" -help
287    exit 1
288fi
289
290
291# -----------------------------------------------------------------------
292# Derived variables.  These are assembled from variables set from the
293# default, environment, configuration file (if any) and command-line
294# options (if any)
295
296PROFILE_FOO=
297# Handle the case of a profile switch
298if [ -n "$profConf" ] ; then
299    profConffile=
300    if [ -s "$libdir/lib$profConf.a" -o -s "$libdir/lib$profConf.so" ] ; then
301	PROFILE_FOO="-l$profConf"
302    elif [ -s "$sysconfdir/$profConf.conf" ] ; then
303	profConffile="$sysconfdir/$profConf.conf"
304    elif [ -s "$profConf.conf" ] ; then
305        profConffile="$profConf.conf"
306    else
307        echo "Profiling configuration file $profConf.conf not found in $sysconfdir"
308    fi
309    if [ -n "$profConffile" -a -s "$profConffile" ] ; then
310	. $profConffile
311    fi
312fi
313
314# Construct the line to add the include directory (not all compilers
315# use -I, unfortunately)
316if [ -z "${FCINC}" ] ; then
317    # If there is no path, add a link to the mpif.h file.
318    # There *must* be a way to provide the path the any modules (there
319    # may be too many to link)
320    if [ ! -r mpif.h ] ; then
321        #echo "Adding a symbolic link for mpif.h"
322	trap "$Show rm -f mpif.h" 0
323	# This should really be the (related) f77includedir.
324	$Show ln -s ${includedir}/mpif.h mpif.h
325	# Remember to remove this file
326	rmfiles="$rmfiles mpif.h"
327    fi
328    FCINCDIRS=
329else
330    # Normally, FCINC is just -I, but some compilers have used different
331    # command line arguments
332    FCINCDIRS=${FCINC}${includedir}
333fi
334
335# Handle the specification of the directory containing the modules
336if [ -n "$FCMODINCSPEC" ] ; then
337    newarg=`echo A"$FCMODINCSPEC" | \
338	sed -e 's/^A//' -e 's%<dir>%'"$includedir%g" -e 's/<file>/mpi/g'`
339    FCMODDIRS="$newarg"
340elif [ -n "$FCMODINC" ] ; then
341    FCMODDIRS="${FCMODINC}$modincdir"
342fi
343
344final_fcflags="@MPICH_MPIFORT_FCFLAGS@ @WRAPPER_FCFLAGS@"
345final_ldflags="@MPICH_MPIFORT_LDFLAGS@ @WRAPPER_LDFLAGS@"
346final_libs="@MPICH_MPIFORT_LIBS@"
347if test "@INTERLIB_DEPS@" = "no" -o "${interlib_deps}" = "no" ; then
348    final_ldflags="${final_ldflags} @LDFLAGS@"
349    final_libs="${final_libs} @LIBS@ @WRAPPER_LIBS@"
350fi
351
352# A temporary statement to invoke the compiler
353# Place the -L before any args incase there are any mpi libraries in there.
354# Eventually, we'll want to move this after any non-MPI implementation
355# libraries
356if [ "$linking" = yes ] ; then
357    if [ "$nativelinking" = yes ] ; then
358        $Show $FC $PROFILE_INCPATHS ${final_fcflags} ${final_ldflags} $allargs
359        rc=$?
360    else
361        if [ "$static_mpi" = no ] ; then
362          $Show $FC $PROFILE_INCPATHS ${final_fcflags} ${final_ldflags} "${allargs[@]}" $FCINCDIRS $FCMODDIRS -L$libdir -l@MPIFCLIBNAME@ $PROFILE_PRELIB $PROFILE_FOO ${wrapper_dl_type_flags} -l@MPILIBNAME@ @LPMPILIBNAME@ $PROFILE_POSTLIB ${final_libs} @FC_OTHER_LIBS@
363        else
364          $Show $FC $PROFILE_INCPATHS ${final_fcflags} ${final_ldflags} "${allargs[@]}" $FCINCDIRS $FCMODDIRS -L$libdir -l@MPIFCLIBNAME@ $PROFILE_PRELIB $PROFILE_FOO ${wrapper_dl_type_flags} $libdir/lib@MPILIBNAME@.a @LPMPILIBNAME@ $PROFILE_POSTLIB ${final_libs} @FC_OTHER_LIBS@
365        fi
366        rc=$?
367    fi
368else
369    $Show $FC $PROFILE_INCPATHS ${final_fcflags} $allargs $FCINCDIRS $FCMODDIRS
370    rc=$?
371fi
372if [ -n "$rmfiles" ] ; then
373    for file in $rmfiles ; do
374        objfile=`basename $file .f`
375	if [ -s "${objfile}.o" ] ; then
376	    # Rename
377	    destfile=`echo $objfile | sed -e "s/.*$$-//"`
378	    mv -f ${objfile}.o ${destfile}.o
379	fi
380        rm -f $file
381    done
382    rm -f $rmfiles
383fi
384exit $rc
385