#!/bin/bash # --------------------------------------------------------------------------- # # ad3 : Run fortran CPP preprocessor on a single WAVEWATCH III # # source code file. Switches are set in the file 'switch', which # # has to be in the "bin" directory. After the preprocessing the code # # is compiled using the script comp in the "bin" directory. # # # # use : ad3 basename [itest [icomp]] # # basename: name of source code file without the '.F90' extension. # # file with .f or .f90 extension is not preprocessed. # # file with .c extension uses standard cc compiler. # # itest : test output switch. # # not defind or 0 : no test output # # all other : verbose mode # # icomp : compiling switch. # # not defind or 0 : compile. # # all other : do not compile. # # # # error codes : 1 : input error # # 2 : no environment file $ww3_env found. # # 3 : error in creating scratch directory. # # 4 : w3adc error. # # 5 : compiler error. # # # # programs used : # # comp : compiler script. # # # # remarks : # # # # - Do not use itest in w3adc to avoid spurious error messages. # # - The main WAVEWATCH directory ($main_dir) is obtained from the setup # # file $ww3_env, as is the scratch directory ($temp_dir). The following # # directories are used : # # $main_dir/src : Raw FORTRAN file ($basename.F90). # # $main_dir/bin : File with preprocessor switches 'switch', and # # compiler script 'comp'. # # $main_dir/obj : Final object modules ($basename.o). # # $main_dir/mod : Final modules (*.mod). # # # # The following temporary files (in $temp_dir) are used and are removed # # only if the corresponding step of ad3 is ompleted successfully : # # comp.out : input file for comp. # # comp.err : eror file for comp. # # comp.stat : status file of compiler, containing number of errors # # and number of warnings (generated by comp). # # # # - Check the compress variable in section 1.b to print or suppress the_ # # documentation in the clean FORTRAN files. # # # # Hendrik L. Tolman # # May 2009 # # January 2014 # # # # Copyright 2009-2014 National Weather Service (NWS), # # National Oceanic and Atmospheric Administration. All rights # # reserved. WAVEWATCH III is a trademark of the NWS. # # No unauthorized use without permission. # # # # --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- # # 1. Preparations # # --------------------------------------------------------------------------- # # 1.a Check and process input if [ "$#" -gt '3' ] || [ "$#" -lt 1 ] then echo "usage: ad3 basename [itest [icomp]]" 1>&2 ; exit 1 fi name=$1 if [ "$#" -ge '2' ] then itst=$2 else itst='0' fi if [ "$#" = '3' ] then icmp=$3 else icmp='0' fi # 1.b Internal variables - - - - - - - - - - - - - - - - - - - - - - - - - - - switch="switch" # file containing switches compress=0 # source code compression par in w3adc # if not 0, documentaion removed from .f90 file # 1.d Get data from setup file - - - - - - - - - - - - - - - - - - - - - - - - source $(dirname $0)/w3_setenv main_dir=$WWATCH3_DIR temp_dir=$WWATCH3_TMP source=$WWATCH3_SOURCE list=$WWATCH3_LIST # 1.d Set up paths etc. - - - - - - - - - - - - - - - - - - - - - - - - - - - path_b="$main_dir/bin" path_w="$( cd $temp_dir && pwd )" path_i="$main_dir/src" path_o="$main_dir/obj" path_m="$main_dir/mod" path_e="$main_dir/exe" if [ -n "`echo $name | grep scrip_ 2>/dev/null`" ] then path_i="$path_i/SCRIP" fi if [ ${name:0:3} = 'yow' ] then path_i="$path_i/PDLIB" fi if [ -z "$(env | grep switch_file)" ] then switch_file=$main_dir/bin/$switch fi sw_str=$(cat $switch_file) if [ ! -d $path_w ] then if ! `mkdir $path_w` then echo ' *** w3adc error ***' echo " Cannot create $path_w" exit 3 fi fi # 1.e Test necessity of running w3adc - - - - - - - - - - - - - - - - - - - - if [ -f $path_i/$name.F90 ] then w3adc='yes' idstr= else w3adc='no' idstr='[no w3adc]' fi # 1.f Set appropriate Fortran file suffix - - - - - - - - - - - - - - - - - - suffixes="ftn f F f90 F90 c" fexti=none for s in $suffixes do if [ -f $path_i/$name.$s ] then fexti=$s break fi done if [ "$fexti" = 'none' ] then echo ' *** ad3 error ***' echo " Source file $path_i/$name.* not found" echo " Source file suffixes checked: $suffixes" exit 2 fi if [ "$fexti" = 'ftn' ] then fexto=F90 else fexto=$fexti fi fext=$fexto # 1.g Output - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - echo "ad3 : processing $name $idstr" if [ "$itst" != '0' ] then echo ' ' ; echo 'Test output ad3 ' ; echo '----------------' echo " bin directory : $path_b " echo " work directory : $path_w " echo " input directory : $path_i " echo " object directory : $path_o " echo " module directory : $path_m " echo " executable dir. : $path_e " echo " switches file : $switch " ; echo ' ' echo " switches : $sw_str" echo ' ' fi # 1.h Final preparations - - - - - - - - - - - - - - - - - - - - - - - - - - - cd $path_w rm -f $name.$fext rm -f $name.l # --------------------------------------------------------------------------- # # 2. Run w3adc # # --------------------------------------------------------------------------- # # 2.a Make input file if [ "$w3adc" = 'yes' ] then # 2.b Run CPP preprocessor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Generate list of CPP Flags based on switches: CPPFLAGS=() for sw in $sw_str do CPPFLAGS+=("-DW3_$sw") done CPPFLAGS+=("-D__WW3_SWITCHES__='$sw_str'") # Also set endianness: CPPFLAGS+=("-DENDIANNESS=''") "${CPPFLAGS[@]}" $path_i/$name.F90 $name.F90 mv $name.i $name.F90 # 2.c Test the output of w3adc - - - - - - - - - - - - - - - - - - - - - - - - if [ ! -f $name.$fext ] then echo ' *** w3adc error ***' fi if [ "`wc -l $name.$fext | awk '{ print $1}'`" -lt '2' ] then echo ' *** w3adc error ***' echo " file $name.$fext not found (2)." fi else # 2.f No w3adc, just copy file - - - - - - - - - - - - - - - - - - - - - - - - cp $path_i/$name.$fext . fi if [ ! -f $name.$fext ] then echo ' *** adc error ***' echo " file $name.$fext not found." exit 5 fi # 2.g Stop if requested - - - - - - - - - - - - - - - - - - - - - - - - - - - if [ "$icmp" != '0' ] then exit 0 fi rm -f $path_o/$name.o ## Chris B: Dont delete *.mod - could clobber files in parallel make ## Need to delete specific mod file that could be upper/lower/mixed case! # rm -f *.mod ## too indiscriminate ## Using find -iname most succinct, but maybe not all version of find have ## the -iname option? # find . -iname "${name}.mod" -delete # not all versions of find have -iname? # Fall back on grep -i mods=`ls *.mod 2> /dev/null | grep -i "${name}.mod"` if [ -n ${mods} ]; then rm -f ${mods} fi # --------------------------------------------------------------------------- # # 3. Compile source code f / f90 # # --------------------------------------------------------------------------- # export fext # for use by comp export path_m # for use by comp export path_i # for use by comp if [ ! -f $name.c ] then # 3.a Run compile program error='0' $path_b/comp $name > comp.out.$name 2> comp.err.$name OK="$?" # 3.b Error escape location - - - - - - - - - - - - - - - - - - - - - - - - - if [ "$OK" != '0' ] then echo ' *** compile error ***' echo ' error in comp' echo '--- comp output -------------------------------------------------' cat comp.out.$name echo '--- comp error output -------------------------------------------' cat comp.err.$name echo '-----------------------------------------------------------------' error='6' rm -f comp.stat.$name fi rm -f comp.out.$name rm -f comp.err.$name # 3.c Check comp.stat - - - - - - - - - - - - - - - - - - - - - - - - - - - - if [ -f comp.stat.$name ] then nr_err="$(grep -i error comp.stat.$name | awk '{ print $2 }')" nr_war="$(grep -i warning comp.stat.$name | awk '{ print $2 }')" rm -f comp.stat.$name if [ "$nr_err" != '0' ] then echo " $nr_err errors found, see $path_w/$name.err" list='yes' else if [ "$nr_war" != '0' ] then echo " $nr_war warnings found, see $path_w/$name.out" list='yes' fi fi else echo ' *** compile error ***' echo " file comp.stat.$name not found" error='5' nr_err='1' rm -f $name.o fi # 3.d process object file - - - - - - - - - - - - - - - - - - - - - - - - - - if [ "$nr_err" != '0' ] && [ ! -f $name.o ] && [ "$error" = '0' ] then echo ' *** compile error ***' echo " file $name.o not found" error='5' fi if [ "$nr_err" != '0' ] then rm -f $name.o else mv $name.o $path_o/. ## ChrisB: Don't move all module files...could break parallel make. ## Just target specific module file (could be mixed case filename ## depending on compiler - use case insensitive find): # mods=`ls *.mod 2> /dev/null` ## Using find -iname most succinct, but maybe not all version of find have ## the -iname option? # mods=`find . -iname "${name}.mod"` # not all versions of find have -iname? # Fall back on grep -i mods=`ls *.mod 2> /dev/null | grep -i "${name}.mod"` if [ -n "$mods" ] then for mod in $mods do mv $mod $path_m/. echo " $mod" done fi fi # Note: the need for moving the .mod file and therefore the printing of the # $mod depend on the compiler behavior. # 3.e process output files - - - - - - - - - - - - - - - - - - - - - - - - - - rm -f $name.o if [ "$source" != 'yes' ] then rm -f $name.f $name.$fext fi if [ "$list" != 'yes' ] && [ "$error" = '0' ] then rm -f $name.l fi exit $error # --------------------------------------------------------------------------- # # 4. Compile source code c # # --------------------------------------------------------------------------- # # For now only diagnostics / profiling codes compiled with simple cc compiler else # 4.a Compile cc -c $name.c # 4.b Save object file if [ -f $name.o ] then mv $name.o $path_o/. else echo ' *** compile error ***' echo " file $name.o not found" error='6' fi fi # End of ad3 ---------------------------------------------------------------- #