#!/bin/sh
##############################################################################
# charmc: Compiler for Converse/Charm/Charm++ programs
#
# Converted to Bourne Shell by Orion Sky Lawlor, 10/21/1999
#
# Initialize the main controlling variables, setup error handler
# ALL variables used by this script should be initialized here.
#
##############################################################################

#Prepare aliases for the external commands we use--
# Note that adding /bin/ to everything breaks Cygwin32.
RM="rm -f"
CP="cp -p"
MV="mv"
LN="ln"
WC="wc"
SED="sed"

MACHTYPE=""
SEQUENTIAL=""
NATIVE=""
LANGUAGE=""
BALANCE="rand"
TRACEMODE=""
TRACE_OBJ=
MEMORY="default"
THREAD="default"
VERBOSE=""
DEBUG_SCRIPT=""
SAVE=""
PURIFY=""
SKIPLINK=""
OVERRIDE_CC=""
OVERRIDE_CXX=""
OVERRIDE_F90=""
OVERRIDE_LD=""
OVERRIDE_LDXX=""
#Generic options, passed to everything
OPTS=""
#Specific options
#charm internal flag, only pass to c and cxx, not f90
OPTS_CPP_INTERNAL="-D__CHARMC__=1"
OPTS_CPP=
OPTS_LDRO="" 
OPTS_CC=""
OPTS_CC_GENCPM=""
OPTS_CXX="" 
OPTS_F90=""
OPTS_LD=""  
OPTS_LDXX=""
OPTS_PIC=""
USE_PIC="0"

CHARMDEBUG=""
LINK_PYTHON=""
OBJECT=""
EXPLICIT_OBJECT="no"
EXPLICIT_COMPILATION="no"
POST_LANGUAGE=""
POST_LIBRARIES=""    
PRE_LIBRARIES=""  
USE_F90_LIBRARIES="0"  
USE_F77_LIBRARIES="0"  
F90_MODDIR=
AMPIMAIN=""
COPYTO=""        
MODCOPIES=""        
MODULES=""
BALANCER=""
FILES=""       
OBJECTFILES=""  
DELETE=""    
MAINOBJ=""   
GENCPM=""
OPTIMIZE_MODE=""
PRODUCTION_MODE=""
USE_RELIABLE_CC=""
USE_FASTEST_CC=""
PROG_EXT=""
GENDEPENDS="no"
COUNTTOKENS="no"
USE_OPENMP="no"

COPY_CHARMRUN=true
USE_BUILD_OPTIONS=0

COPY_EXIT="true"
CHARM_SHARED="0"
BUILD_SHARE="0"
SWAPGLOBALS="0"
TLSGLOBALS="0"
ROSE_OMP_TLS_GLOBALS="no"
NOABORT=""

TAU_MAKEFILE=Make.tau
TAU_TRACE_MPI=1

CMK_CELL=0
SPU_USE_CPP=0
SPU_EXTRA_LIBS=""

MPI_INTEROPERATE=""
NO_MAIN_MODULE=""
NO_MAIN=""
CUSTOM_PARTITION=""
PREPROCESS_CI="yes"
INPUT_GIVEN=""

####################################################################
#
#  Utility routines used below
#
###################################################################

# PrintUsage: prints a helpful command-line usage message and quits
# Args: any additional messages
printUsage() {
    printVersion
    echo 
    echo "Usage: charmc [ flags ] <files>"
    echo
    echo "  flags:"
    echo "        -o <target> -g -O"
    echo "        -D<define> -I<include path> -L<lib path> -l<library> -s"
    echo "        -machine <mach> -seq -host -language <lang> -pg <opt>"
    echo "        -balance <mode> -tracemode <mode> -memory <mode>"
    echo "        -modules <comma-separated list of C++ modules> -thread"
    echo "        -debug-script -count-tokens -default-to-aout -E -S -M"
    echo "        -verbose -save -purify -cp <dest> -cpmod -gen-cpm <pkg>"
    echo "        -swapglobals -tlsglobals -roseomptlsglobals"
    echo "        -use-reliable-cc -use-fastest-cc -use-new-std"
    echo "        -cc <new cc> -c++ <new CC> -ld <new ld> -ld++ <new LD>"
    echo "        -cpp-option <opt> -ldro-option <opt> -cc-option <opt>"
    echo "        -c++-option <opt> -ld-option <opt> -ld++-option <opt>"
    echo "        -f90 <new f90> -f90-option <opt> -fmoddir <f90mod path>"
    echo "        -flibs -rpath <path> -custom-part -touch-on-failure"
    echo "        -mpi -openmp -no-trace-mpi -build-shared -charm-shared"
    echo "        -no-charmrun -no-preprocess-ci -nomain-module -nomain"
    echo "        -nof90main -f90main"
    echo
    echo "  Charmc compiles C, C++, f77, f90, AMPI, Converse, Converse++, Charm, "
    echo "and Charm++ programs.  The flags generally match those of cc or f77."
    echo "  Other options that are not listed here will be passed directly to the"
    echo "underlying compiler and/or linker."
    echo "Parallel Programming Lab, UIUC, 2017."
    echo $*
    exit 1
}

# End blows away the temporary files (unless SAVE is true) and exits
# Args: <exit code>
End() {
    if [ -z "$SAVE" ]
	then
        for FILE in `echo $FILES`
        do
            #BASE=`stripExtention $FILE`
            TMP=`basename $FILE`".TMP"
            $RM $TMP.P.C $TMP.cpp $TMP.space $TMP.xlat $TMP.o
            $RM $TMP.c $TMP.c.0.h $TMP.c.1.h $TMP.c.2.h
            $RM $TMP.i $TMP.$CMK_CPP_SUFFIX
        done
        $RM core $DELETE
	if test -n "$modInitObj"
	then
	    [ -n "$VERBOSE" ] && echo $RM $modInitSrc $modInitObj
	    DoNoErrCheck $RM $modInitSrc $modInitObj > /dev/null 2>&1
	fi
    fi
    exit $1
}

# Write this error message to stderr
# ("1>&2" redirects the echo output to stderr).
Warning() {
	echo "$@" 1>&2
}

# This procedure prints an error message and exits.
# Args: written to stderr
Abort() {
	Warning "Fatal Error by charmc in directory "`pwd`
	Warning "   $@"
	Warning "charmc exiting..."
	End 1
}


# Instead of an ECHO_CMD variable, I define a procedure Do,
# which (possibly) echos, runs, and tests the errors of the given command.
# Args: executed as given
DoNoErrCheck() {
	[ -n "$VERBOSE" ] && echo "charmc: Executing $@" 1>&2
	eval "$@"
}

Do() {
	DoNoErrCheck "$@"
	Do_res=$?
# The UNIX result code better be zero, or we die
	[ $Do_res -eq 0 -o -n "$NOABORT" ] || Abort "Command $@ returned error code $Do_res"
}

# This procedure removes the extention (the ".c" in "./main.c") from
# its first argument, and prints the result. Unlike the builtin command
# basename, it keeps the directory path.
# Args: <name to strip>
stripExtention() {
	se_base=`basename $1`
#	se_base=`echo $1 | awk -F/ '{print $NF}'`
	se_strip=`echo $se_base | awk -F. '{ORS="";print $1;for (i=2;i<NF;i++) print "."$i}'`
	se_ret=`echo $1 | awk -F/ '{ORS="";for (i=1;i<NF;i++) print $i"/"}'`"$se_strip"
	echo $se_ret
}

# GetExtention returns the extention on the given file name
# or "" if none.  (e.g. "./bob/snack.c" returns ".c")
# Args: <name to find extention of>
getExtention() {
#	se_base=`echo $1 | awk -F/ '{print $NF}'`
#        se_ret=`echo $se_base | awk -F. '{if (NF<=1) print ""; else print "."$NF}'`
#	echo $se_ret
	se_ret=`echo $1 | sed -e 's/.*\././'`
	if test "$se_ret" = $1
        then
          echo ""
        else
          echo $se_ret
        fi
}

Debugf() {
	[ -n "$VERBOSE" ] && echo "charmc>" $@
}

Debug() {
    if [ -n "$DEBUG_SCRIPT" ]
    then
	echo 
	echo "------- Charmc Debugging info: $* -------"
	echo "CHARMBIN=$CHARMBIN"
	echo "CHARMINC=$CHARMINC"
	echo "CHARMLIB=$CHARMLIB"
	echo "FILES=$FILES"
	echo "DELETE=$DELETE"
	echo "OBJECT=$OBJECT"
	echo "LANGUAGE=$LANGUAGE"
#	echo "Working directory="`pwd`
    fi
}

# Return success if $1 is not in any of the other arguments
notInList() {
	search=$1
	shift
	while [ $# -gt 0 ]
	do
		if [ "$search" = "$1" ]
		then
			# It's already in there-- fail
			return 1
		fi
		shift
	done
	# It's missing--succeed
	return 0
}

# Add arguments to our modules list, avoiding duplicates
AddModules() {
    for M in "$@"
    do
      notInList $M $MODULES && MODULES="$MODULES $M"
    done
}

# Add this word to this list, avoiding duplicates
AddList() {
    ret=""
    while [ $# -gt 1 ]
    do
        ret="$ret $1"
        shift
    done
    if notInList $1 $ret
    then
        ret="$ret $1"
    fi
    echo $ret
}

# Drop the first argument anywhere it appears in the subsequent list
DropList() {
    drop="$1"
    shift

    ret=""
    while [ $# -gt 1 ]
    do
        if [ "$1" != "$drop" ]; then
            ret="$ret $1"
        fi
        shift
    done

    echo $ret
}

# TEMP_BASE is appended with this script's process ID (PID),
# so multiple charmcs can run in parallel without overwriting
# each other's temporary files.
TEMP_BASE="/tmp/charmc_tmp.$$"

# Try to find CHARMBIN by looking in directory where charmc is
findCharmBin() {
if [ -z "$CHARMBIN" ]
then
	SCRIPT=$1
	CHARMBIN=`dirname $SCRIPT`
#	CHARMBIN=`cd $CHARMBIN; pwd`
# NOTE: this script no longer tries to follow soft links
# to find the "original" charmc-- if this is bad, 
# translate these lines to Bourne shell from C shell:
# -------------------- Begin C Shell ------------------------->
#    if ($SCRIPT:h != $SCRIPT:t) then
#        cd $SCRIPT:h
#        set SCRIPT=$SCRIPT:t
#    else
#        foreach dir ($path)
#            if (-x $dir/$SCRIPT && ! -d $dir/$SCRIPT) then
#                cd $dir
#                break
#            endif
#        end
#    endif
#    while (x`find $SCRIPT -type l -print` == x$SCRIPT)
#        set SCRIPT=`ls -al ./$SCRIPT:t | sed -e "s@.*-> @@"`
#        if ($SCRIPT:h != $SCRIPT:t) then
#            cd $SCRIPT:h
#            set SCRIPT=$SCRIPT:t
#        endif
#    end
#    set CHARMBIN=`pwd`
# <------------------ End C Shell -----------------------------
fi
}

printVersion()
{
	findCharmBin $0
	version=`cat $CHARMBIN/../include/VERSION`
	echo Charm++ Version $version
}


##############################################################################
#
# The following section identifies CHARMBIN, the charm binary-directory.
#
##############################################################################

ORIGDIR=`pwd`

# Try to find CHARMBIN by looking in directory where charmc is

findCharmBin $0

UNAME=`uname -s`
FIRST_THREE=`uname -s | awk '{print substr($1,1,3)}' `
if [ "$FIRST_THREE" = "CYG" -o "$UNAME" = "Interix" ]
then
# Running on a windows system-- append .exe to file names
	PROG_EXT=".exe"
fi

CHARMLIB="$CHARMBIN/../lib"
CHARMINC="$CHARMBIN/../include"
CHARMLIBSO=
if test -d "$CHARMBIN/../lib_so" 
then
  CHARMLIBSO=`cd $CHARMBIN/../lib_so 2>/dev/null && pwd`
  #getting absolute path is harder than thought because of symbolic links and ..
  #ksh needs cd -P to resolve werid symbolic links, however -P is not portable
  #csh is ok too if it exists 
  test -z "$CHARMLIBSO" && CHARMLIBSO=`cd -P $CHARMBIN/../lib_so 2>/dev/null && pwd`
  test -z "$CHARMLIBSO" && CHARMLIBSO=`csh -c "cd $CHARMBIN/../lib_so >& /dev/null && pwd"`
  test -z "$CHARMLIBSO" && echo "$CHARMBIN/../lib_so: not found" && exit 1
fi

##############################################################################
#
# Parse the arguments
#
# Don't do any analysis in here, just the parsing.
#
##############################################################################

[ $# -eq 0 ] && printUsage "Error: No arguments given."

processArgs() {
while [ ! $# -eq 0 ]
do
	arg="$1"
	shift

	case "$arg" in
	"-V")
		printVersion
		exit 0
		;;

	"-machine")
		MACHTYPE="$1"
		shift
		;;

	"-seq")
		SEQUENTIAL=true
		;;

	"-host")
		NATIVE=true
		;;

	"-language")
		# Parse out some fake languages (that are actually modules)
		case "$1" in
		"ampi") AddModules tcharmmain ampi ;;
		"ampif") AddModules tcharmmain ampif ; USE_F90_LIBRARIES="1" ;;
		"armci") AddModules tcharmmain armci ;;
		"armcif") AddModules tcharmmain armci ; USE_F90_LIBRARIES="1" ;;
		"fem") AddModules tcharmmain fem ; AMPIMAIN="femmain";;
		"femf") AddModules tcharmmain fem ; AMPIMAIN="femmain"; USE_F90_LIBRARIES="1" ;;
		"ParFUM_TOPS") AddModules tcharmmain ParFUM ParFUM_TOPS ; AMPIMAIN="ParFUMmain";;
    "ParFUM") AddModules tcharmmain ParFUM ; AMPIMAIN="ParFUMmain";;
    "ParFUMf") AddModules tcharmmain ParFUM ; AMPIMAIN="ParFUMmain"; USE_F90_LIBRARIES="1" ;;
		"mblock") AddModules tcharmmain mblock ;;
		"mblockf") AddModules tcharmmain mblock ; USE_F90_LIBRARIES="1" ;;
		*) 
			LANGUAGE="$1"
			POST_LANGUAGE=1
			;;
		esac
		shift
		;;

        "-debug")
                # Requested support from charmdebug: add some modules and libraries
                CHARMDEBUG=1
                MEMORY="charmdebug"
                ;;

	"-module"|"-modules")
		AddModules `echo $1 | sed -e 's/,/ /g'`
                INPUT_GIVEN="1"
		shift
		;;

	"-balancer")
#                test -n "$BALANCER" && Abort "More than one -balancer specified!"
		BALANCER="$BALANCER $1"
		mod=`echo $1| sed -e 's/:/ /' -e 's/,/ /g'`
		AddModules $mod
		shift
		;;

	"-balance")
		BALANCE="$1"
		shift
		;;

	"-queue")
		Warning "Warning: -queue currently being ignored."
		shift
		;;

	"-memory")
	        MEMORY="$1"
		shift
		;;

	"-thread")
	        THREAD="$1"
		shift
		;;

	"-tracemode")
		TRACEMODE_NEW=`AddList $TRACEMODE $1`
 		if [ "$TRACEMODE_NEW" = "$TRACEMODE" ]
		then
			Warning "Warning: Duplicate tracemode $1 ignored"
		else
			TRACEMODE=$TRACEMODE_NEW
		fi
		shift
		;;
	"-no-trace-mpi")
		TAU_TRACE_MPI=0
		;;
	
	"-swapglobal"|"-swapglobals")
		SWAPGLOBALS="1"
		USE_PIC="1"
		;;

	"-tlsglobal"|"-tlsglobals")
		TLSGLOBALS="1"
		;;

	"-roseomptlsglobals")
		ROSE_OMP_TLS_GLOBALS="yes"
		;;

	"-verbose")
		echo "Verbose mode set"
		VERBOSE=true
		;;

        "-spu-cpp")
		SPU_USE_CPP=1
		;;

        "-spu-lib")
		SPU_EXTRA_LIBS="$SPU_EXTRA_LIBS -l$1"
		shift
		;;

        "-intrinsic")
		XI_INTERNAL=true
		;;

	"-debug-script")
	        echo "Will give excessive charmc debugging output..."
		DEBUG_SCRIPT=true
		;;

	"-save")
		SAVE=true
		;;

	"-purify")
		PURIFY=true
		;;

	"-use-reliable-cc")
		USE_RELIABLE_CC=1
		;;

	"-use-fastest-cc")
		USE_FASTEST_CC=1
		;;

	"-cc")
		OVERRIDE_CC="$1"
		shift
		;;

	"-c++")
		OVERRIDE_CXX="$1"
		shift
		;;

	"-f90")
		OVERRIDE_F90="$1"
		shift
		;;

	"-ld")
		OVERRIDE_LD="$1"
		shift
		;;

	"-ld++")
		OVERRIDE_LDXX="$1"
		shift
		;;

	"-cpp-option")
		OPTS_CPP="$OPTS_CPP $1"
		shift
		;;

	"-ldro-option")
		OPTS_LDRO="$OPTS_LDRO $1"
		shift
		;;

	"-cc-option")
		OPTS_CC="$OPTS_CC $1"
		shift
		;;

	"-c++-option")
		OPTS_CXX="$OPTS_CXX $1"
		shift
		;;

	"-f90-option")
		OPTS_F90="$OPTS_F90 $1"
		shift
		;;

	"-ld-option")
		OPTS_LD="$OPTS_LD $1"
		shift
		;;

	"-ld++-option")
		OPTS_LDXX="$OPTS_LDXX $1"
		shift
		;;

	"-rpath")
		OPTS_LDXX="$OPTS_LDXX -rpath $1"
		shift
		;;
	
	"-fortran"|"-flib"|"-flibs")
		USE_F90_LIBRARIES="1" 
		;;
	"-f77")
		USE_F77="1" 
		;;
	"-fortran77"|"-f77lib"|"-f77libs")
		USE_F77_LIBRARIES="1" 
		;;
	"-E")
# Run preprocessor only
		PREPROCESS="yes"
		SKIPLINK="yes"
		OPTS="$OPTS $arg"
		;;
        "-preprocess")
# Run preprocessor as an extra step, continue after preprocessing
		PREPROCESS="yes"
		;;
	"-no-preprocess-ci")
# Turn off the preprocessor for ci files
		PREPROCESS_CI="no"
		;;
	"-P"|"-S")
# Run preprocessor/assembler only
		SKIPLINK="yes"
		OPTS="$OPTS $arg"
		;;
#------ Dependency generation ---------
	"-M" | "-MM" | "-MMD" | "-MG")
		SKIPLINK="yes"
		OPTS="$OPTS $arg"
		GENDEPENDS="yes"
		;;
	"-MF" | "-MT" | "-MQ" | "-MD")	#-MP will pass through automatically
		OPTS="$OPTS $arg $1"
		shift
		;;
#--------------------------------------
    "-count-tokens")
		OPTS="$OPTS $arg"
        COUNTTOKENS="yes"
        ;;
	"-default-to-aout")
		if [ "$EXPLICIT_OBJECT $EXPLICIT_COMPILATION" = "no no" ]
		then
		      OBJECT="a.out"
		fi
		;;
        -print-prog-name=*)
                echo $arg | cut -d'=' -f2
                exit 0
                ;;
	"-c")
		if [ "$EXPLICIT_OBJECT" = "no" ]
		then
		      OBJECT=""
		fi
		EXPLICIT_COMPILATION="yes"
		;;

	"-o")
		EXPLICIT_OBJECT="yes"
		OBJECT=$1
		shift
		;;

	"-cp")
		COPYTO="$1"
		shift
		;;

	"-cpmod")
		MODCOPIES="$1 $MODCOPIES"
		shift
		;;

	"-gen-cpm")
		GENCPM="$GENCPM $1"
		shift
		;;

	-I)
		OPTS_CPP="$OPTS_CPP -I$1"
		shift
		;;

	-D*|-I*)
		if echo "$arg" | grep ' '  > /dev/null 2>/dev/null 
		then
		  OPTS_CPP="$OPTS_CPP "\"$arg\"
		else
		  OPTS_CPP="$OPTS_CPP $arg"
   		fi
		;;

        -Werror)
                WERROR="1"
                ;;

        -Wno-error)
                WERROR="0"
                ;;

	"-use-new-std")
        USE_NEW_STD="1"
		;;

	"-no-use-new-std")
		USE_NEW_STD="0"
		;;

	-LANG*)
		Warning "passing unrecognized option $arg to all compilers and linkers"
		OPTS="$OPTS $arg"
		;;
	-shared|-G)
		BUILD_SHARE="1"
		;;
	-L*|-shared|-G) # note that this is not executed if $arg == -shared|-G, due to the case above; might be a bug
		OPTS_LD="$OPTS_LD $arg"
		;;
	-charm-shared|-cs)
		CHARM_SHARED="1"
		;;
	-build-shared)
		# used internally when building Charm++ to create lib_so
		BUILD_SHARE="1"
		;;
	-no-build-shared)
		# used internally not to build Charm++ lib_so
		BUILD_SHARE="0"
		;;
	"-optimize")
		OPTIMIZE_MODE=true
		;;

	"-no-optimize")
		OPTIMIZE_MODE=false
		;;

	"-production")
		PRODUCTION_MODE=true
		;;
	"-no-production")
		PRODUCTION_MODE=false
		;;

	-Wl,*)
		POST_LIBRARIES="$POST_LIBRARIES $arg"
		;;
	
	"-pg"|"-g"|-W*|-O*)
		OPTS="$OPTS $arg"
		;;

	"-fmoddir")
		F90_MODDIR="$F90_MODDIR $1"
		shift
		;;

	-l*|*.a)
		if [ -n "$POST_LANGUAGE" ]
		then
			POST_LIBRARIES="$POST_LIBRARIES $arg"
		else
			PRE_LIBRARIES="$PRE_LIBRARIES $arg"
		fi
                INPUT_GIVEN="1"
		;;

	-s)
		OPTS_LD="$OPTS_LD   $arg"
		;;
	-no-charmrun)
		COPY_CHARMRUN=false
		;;
	-use-build-options)
		USE_BUILD_OPTIONS=1
		;;
        -h|--help)
	        printUsage
		;;
	-f90main)
		F90_MAIN=1
		;;
	-nof90main)
		F90_MAIN=
		;;
	-mpi)
		MPI_INTEROPERATE="yes"
		NO_MAIN="yes"
		;;
	-nomain-module)
		NO_MAIN_MODULE="yes"
		;;
	-nomain)
		NO_MAIN="yes"
		;;
	-custom-part)
		CUSTOM_PARTITION="yes"
		;;

	-fopenmp|-openmp)
		USE_OPENMP="yes"
		;;

	-touch-on-failure)
		NOABORT="yes"
		;;

	-*|+*)
#		Warning "passing unrecognized option $arg to all compilers and linkers"
		OPTS="$OPTS  $arg"
		;;
	*.*)
		[ -n "$VERBOSE" ] && echo "Adding file $arg..."
		FILES="$FILES $arg"
                INPUT_GIVEN="1"
		;;
# Default
	*)
#		printUsage  "Error: Unrecognized argument $arg"
#		Warning "passing unrecognized option $arg to all compilers and linkers"
		OPTS="$OPTS  $arg"
		;;
	esac
done
}

trap 'End 1' 2

# Process original command-line arguments
eval processArgs "$@"


##############################################################################
#
# Load module dependencies.
#
##############################################################################

Debug "About to read machine config script"
Debug "Read config script, setting defaults..."

[ ! -r $CHARMINC/conv-config.sh ] && Abort "Cannot find conv-config.sh in $CHARMINC"
. $CHARMINC/conv-config.sh $CHARMINC

Debug "Setting vars..."

if [ "$USE_BUILD_OPTIONS" = "1" ]  
then
	[ -n "$VERBOSE" ] && echo "Charmc applying build time options: $BUILDOPTS"
	OPTS="$OPTS $BUILDOPTS"
fi

# If we are debugging, add "-g -O0" to the C/C++ flags
if [ -n "$CHARMDEBUG" -a -z "$SEQUENTIAL" -a -z "$NATIVE" ]; then
       if [ -n "$CMK_BUILD_PYTHON" ]; then
         	AddModules PythonCCS charmdebug_python
		POST_LIBRARIES=`AddList $POST_LIBRARIES -lpython${CMK_BUILD_PYTHON}`
   	fi
    	OPTS_CPP="$OPTS_CPP -O0 -g"
fi

PROCESSED_MODULES=""

if [ "$WERROR" = "1" ]
then
    OPTS="$OPTS $CMK_WARNINGS_ARE_ERRORS"
fi

# If the user has asked for the latest language standards (C11 or CPP11)
if [ "$USE_NEW_STD" = "1" ]
then
    # and if configure confirmed that the underlying compiler knows abt C11, enable it
    if [ "$CMK_COMPILER_KNOWS_C11" = "1" ]
    then
        OPTS_CC="$OPTS $CMK_ENABLE_C11"
    fi
    # and if configure confirmed that the underlying compiler knows abt CPP11, enable it
    if [ "$CMK_COMPILER_KNOWS_CPP11" = "1" ]
    then
        OPTS_CXX="$OPTS $CMK_ENABLE_CPP11"
    fi
fi

if [ "$ROSE_OMP_TLS_GLOBALS" = "yes" ]
then
    USE_OPENMP="yes"
    TLSGLOBALS="1"

    if [ ! -x "$CMK_ROSE_OMP_TOOL" ]
    then
	Abort "The environment variable CMK_ROSE_OMP_TOOL must contain the path to a built binary of the ROSE OpenMP variable privatization tool"
    fi
fi

if [ "$USE_OPENMP" = "yes" -o "$CMK_OMP" = "1" -a -z "$SEQUENTIAL" -a -z "$NATIVE" ]
then
    [ -n "$VERBOSE" ] && echo OpenMP support enabled
    OPTS_CC="$OPTS_CC $CMK_C_OPENMP"
    OPTS_CXX="$OPTS_CXX $CMK_C_OPENMP"
    OPTS_F90="$OPTS_F90 $CMK_F_OPENMP"
    OPTS_LD="$OPTS_LD $CMK_LD_OPENMP"
    OPTS_LDXX="$OPTS_LDXX $CMK_LD_OPENMP"
else
    [ -n "$VERBOSE" ] && echo OpenMP support not enabled
fi

if [ "$TLSGLOBALS" = "1" ]
then
    OPTS_CC="$OPTS_CC -mno-tls-direct-seg-refs"
    OPTS_CXX="$OPTS_CXX -mno-tls-direct-seg-refs"
    OPTS_F90="$OPTS_F90 -mno-tls-direct-seg-refs"
    OPTS_LD="$OPTS_LD -static -Wl,--allow-multiple-definition"
    OPTS_LDXX="$OPTS_LDXX -static -Wl,--allow-multiple-definition"
fi

# Look up and add the dependencies for module $1
findModuleDep() {
	M=$1
	notInList $M $PROCESSED_MODULES || return
	PROCESSED_MODULES="$PROCESSED_MODULES $M"
	#PRE_LIBRARIES=`AddList $PRE_LIBRARIES -lmodule$M`
	PRE_LIBRARIES=`AddList -lmodule$M $PRE_LIBRARIES`
# HACK: add modules to both ends of library list, to avoid
#  undefined symbol CkRegisterMainModule when it's in a module file.
	POST_LIBRARIES=`AddList $POST_LIBRARIES -lmodule$M`
	if [ "$M" = "PythonCCS" ]
            then
            LINK_PYTHON=1
        fi

	dep=""
# fixme: should search everything in the -L library paths:
	for dir in `echo . $CHARMLIB`
	do
		d="$dir/libmodule$M.dep"
		[ -r "$d" ] && dep=$d
	done
	if [ -r "$dep" ]
	then
		# Add the module dependencies in this file
		# Debugf "Adding module" $M "dependencies from" $dep
		deps=`cat $dep`
		Debugf "Module" $M "adds dependencies:" $deps
		processArgs $deps
	fi
}

# Repeat the module-dependency search until we find no
#  new modules:
START_MODULES=""
while [ "$START_MODULES" != "$MODULES" ]
do
	Debugf "----------- Module dependency search ------------"
	START_MODULES="$MODULES"
	for m in $MODULES
	do
		findModuleDep $m
	done
done

Debugf "----------- Module dependency search complete ------------"



##############################################################################
#
# Load machine-specific configuration data, then handle overrides to it.
#
##############################################################################


if [ x"$CMK_NO_BUILD_SHARED" = "xfalse" ]
then
 	BUILD_SHARE="1"
fi

if [ "$BUILD_SHARE" = "1" ]
then
	if [ x"$CMK_NO_BUILD_SHARED" = "xtrue" -o -z "$CHARMLIBSO" ]
	then
		BUILD_SHARE="0"
	else
		USE_PIC="1"
	fi
fi

OPTS_PIC="$CMK_PIC"
if [ "$USE_PIC" = "1" ]
then
       OPTS_CC="$OPTS_CC $OPTS_PIC"
       OPTS_CXX="$OPTS_CXX $OPTS_PIC"
       OPTS_F90="$OPTS_F90 $OPTS_PIC"
       OPTS_LD="$OPTS_LD $OPTS_PIC"
fi

if [ "$BUILD_SHARE" = "1" ]
then
	# ignore BUILD_SHARE if the target is not .a or .so
	case "$OBJECT" in
	*.a|*.so|*.so.*|*.sl|*.dylib)
 		OPTS_LD="$OPTS_LD $CMK_LD_SHARED $OPTS_LDRO -L$CHARMLIBSO"
		;;
	*)	
		BUILD_SHARE="0"
		;;
	esac
fi

if [ -n "$OVERRIDE_CC" ]
then
    CMK_CC="$OVERRIDE_CC"
fi
Debug "set 2"
if [ -n "$OVERRIDE_CXX" ]
then
    CMK_CXX="$OVERRIDE_CXX"
fi

if [ -n "$OVERRIDE_F90" ]
then
    CMK_CF90="$OVERRIDE_F90"
fi

if [ -n "$OVERRIDE_LD" ]
then
    CMK_LD="$OVERRIDE_LD"
fi

if [ -n "$OVERRIDE_LDXX" ]
then
    CMK_LDXX="$OVERRIDE_LDXX"
fi

if [ -n "$USE_RELIABLE_CC" ]
then
	CMK_CC="$CMK_CC_RELIABLE"
fi

if [ -n "$USE_FASTEST_CC" ]
then
    CMK_CC="$CMK_CC_FASTEST"
fi

if [ -n "$USE_F77" ]
then
    CMK_CF90=$CMK_CF77
    CMK_CF90_FIXED=$CMK_CF77
    CMK_F90LIBS=$CMK_F77LIBS
fi

if [ -n "$CMK_F90_MODINC" ]
then
    CMK_CF90_MODINC="$CMK_F90_MODINC"
else
    CMK_CF90_MODINC="-M"
fi

if [ -n "$F90_MODDIR" ]
then
    for dir in $F90_MODDIR
    do
      OPTS_F90="$OPTS_F90 $CMK_CF90_MODINC $dir"
    done
fi

if [ -n "$CMK_F90_USE_MODDIR" ]
then
    CMK_CF90="$CMK_CF90 $CMK_CF90_MODINC $CHARMINC $CMK_SYSINC"
fi

if [ -n "$SEQUENTIAL" ]
then
    CMK_CC="$CMK_SEQ_CC -DCMK_SEQUENTIAL=1 "
    CMK_LD="$CMK_SEQ_LD"
    CMK_CXX="$CMK_SEQ_CXX -DCMK_SEQUENTIAL=1 " 
    CMK_CF90="$CMK_SEQ_F90 " 
    CMK_LDXX="$CMK_SEQ_LDXX" 
    CMK_AR="$CMK_SEQ_AR"
    CMK_RANLIB="$CMK_SEQ_RANLIB"
fi

if [ -n "$NATIVE" ]
then
    CMK_CC="$CMK_NATIVE_CC " 
    CMK_LD="$CMK_NATIVE_LD" 
    CMK_CXX="$CMK_NATIVE_CXX " 
    CMK_LDXX="$CMK_NATIVE_LDXX" 
fi

if [ -n "$PREPROCESS" ]
then
    CMK_CF90=$CMK_FPP
fi

if [ -n "$PURIFY" ]
then
    CMK_LD="purify $CMK_LD"
    CMK_LDXX="purify $CMK_LDXX"
fi

Debug "set 4"
if [ "$OPTIMIZE_MODE" = "true" ]
then
    OPTS_CC="$CMK_C_OPTIMIZE $OPTS_CC"
    OPTS_CXX="$CMK_CXX_OPTIMIZE $OPTS_CXX"
    OPTS_F90="$CMK_F90_OPTIMIZE $OPTS_F90"
    OPTS_LD="$CMK_C_OPTIMIZE $OPTS_LD"
    OPTS_LDXX="$CMK_CXX_OPTIMIZE $OPTS_LDXX"
fi

# Pick up per-architecture production mode settings
if [ "$PRODUCTION_MODE" = "true" ]
then
    OPTS_CC="$CMK_PRODUCTION $CMK_C_PRODUCTION $OPTS_CC"
    OPTS_CXX="$CMK_PRODUCTION $CMK_CXX_PRODUCTION $OPTS_CXX"
    OPTS_F90="$CMK_PRODUCTION $CMK_F90_PRODUCTION $OPTS_F90"
    OPTS_LD="$CMK_PRODUCTION $CMK_C_PRODUCTION $OPTS_LD"
    OPTS_LDXX="$CMK_PRODUCTION $CMK_CXX_PRODUCTION $OPTS_LDXX"
fi

if [ -n "$XI_INTERNAL" ]
then
    CMK_XIOPTS="$CMK_XIOPTS -intrinsic"
fi

if [ "$GENDEPENDS" = "yes" ]
then
    CMK_XIOPTS="$CMK_XIOPTS -M"
fi

if [ "$COUNTTOKENS" = "yes" ]
then
    CMK_XIOPTS="$CMK_XIOPTS -count-tokens"
fi

if test "$CMK_WITH_TAU" = "true"
then
  echo "include $TAU_MAKEFILE" > _make.tau.tmp
  echo "print-%:; @echo \$(\$*)" >> _make.tau.tmp
  TAU_LIBS=`make --no-print-directory -f _make.tau.tmp print-TAU_LIBS`
  TAU_MPI_LIBS=`make --no-print-directory -f _make.tau.tmp print-TAU_MPI_LIBS` 
  TAU_MPI_FLIBS=`make --no-print-directory -f _make.tau.tmp print-TAU_MPI_FLIBS`
  TAU_DEFS=`make --no-print-directory -f _make.tau.tmp print-TAU_DEFS`
  TAU_INCLUDE=`make --no-print-directory -f _make.tau.tmp print-TAU_INCLUDE`

  rm -f _make.tau.tmp
fi

#Add generic options to the compiler- and linker-options
OPTS_CC="$OPTS $TAU_DEFS $TAU_INCLUDE $OPTS_CC"
OPTS_CXX="$OPTS $TAU_DEFS $TAU_INCLUDE $OPTS_CXX"
OPTS_F90="$OPTS $OPTS_F90"
OPTS_LD="$OPTS $OPTS_LD"
# OPTS_LDXX gets OPTS from OPTS_LD

if [ -n "$F90_MAIN" ] 
then
# for_main needs to be placed at beginning
	CMK_LD="$CMK_LD $CMK_F90MAINLIBS"
	CMK_LDXX="$CMK_LDXX $CMK_F90MAINLIBS"
fi

# There's really no analog for this in the Bourne shell: 
#  -------- C Shell ------> onintr failure
# Luckily, it's irrelevant as long as nobody sends us a ^Z.

##############################################################################
#
# Check for valid choice of LANGUAGE
#
##############################################################################
Debug "Checking language..."

if [ -z "$LANGUAGE" ]
then
    LANGUAGE="charm++"
    [ -n "$SEQUENTIAL" ] && LANGUAGE=c
fi

case "$LANGUAGE" in
"c"|"C"|"c++"|"C++")
	[ -z "$SEQUENTIAL" -a -z "$NATIVE" ] && Abort "Language $LANGUAGE is for sequential programs"
	;;
esac

# update charm to bgcharm
if [ "$LANGUAGE" = "charm++" -a -n "$CMK_BIGSIM" ]
then
        LANGUAGE="bgcharm++"
fi
if [ "$LANGUAGE" = "converse++" -a -n "$CMK_BIGSIM" ]
then
        LANGUAGE="bgconverse++"
fi
if [ "$LANGUAGE" = "bgcharm++" ]
then
	TRACEMODE=`AddList $TRACEMODE bluegene`
fi

if [ $USE_F77_LIBRARIES = "1" ]
then
	POST_LIBRARIES="$POST_LIBRARIES $CMK_F77LIBS"
fi

if [ $USE_F90_LIBRARIES = "1" ]
then

	if [ ! -r $CHARMLIB/libconv-utilf.a ]
	then
		Abort "Error: Fortran support library $CHARMLIB/libconv-utilf.a missing. Is your Fortran compiler working?"
	fi

	POST_LIBRARIES="$POST_LIBRARIES -lconv-utilf $CMK_F90LIBS"
fi

########################################################################
#
# We've parsed and verified the command-line parameters.
# Now we prepare routines to clean up and exit.
# None of these routines ever returns-- they all just exit.
#
########################################################################


Copyobj() {
	if [ "a$COPYTO" != "a" -a "a$COPYTO" != "a$OBJECT" ] 
	then
		[ -d $COPYTO ] && COPYTO="$COPYTO/"
		if [ "a$PROG_EXT" != "a" -a -r "$OBJECT$PROG_EXT" ] ; then
			Warning "Appending $PROG_EXT to object file name"
			OBJECT="$OBJECT$PROG_EXT"
		fi
		[ ! -d $COPYTO ] && DoNoErrCheck $RM $COPYTO 
		Do $CP $OBJECT $COPYTO
	fi
	test -n "$COPY_EXIT" && Success
}

Copymod() {
	for COPY in `echo $MODCOPIES`
	do
		if [ "a$COPY" != "a$OBJECT" ] 
		then
			[ -d $COPY ] && COPY="$COPY/"
			if [ -n "$CMK_MOD_NAME_ALLCAPS" ] ; then
			  OBJECT=`echo $OBJECT | tr "a-z" "A-Z"`
			fi
			if [ -r "$OBJECT.$CMK_MOD_EXT" ] ; then
			  Warning "Appending .$CMK_MOD_EXT to object file name"
			  OBJECT="$OBJECT.$CMK_MOD_EXT"
			fi
			[ ! -d $COPY ] && DoNoErrCheck $RM $COPY 
			Do $CP $OBJECT $COPY
		fi
	done
	Success
}

Success() {
	End 0
}


##############################################################################
#
# Preprocess the GEN-CPM files
#
##############################################################################

Debug "Preprocessing GEN-CPM files"

if [ "$CMK_USING_BGCLANG" = "1" ]
then
  OPTS_CC_GENCPM="-x c "  # -x c is only applied for the preprocessing of the GEN-CPM files on BG/Q
fi

OPTS_CC_GENCPM="$OPTS_CC $OPTS_CC_GENCPM"
for FILE in `echo $GENCPM`
do
# This used to be "$FILE:r", which strips the extention
	BASE=`stripExtention $FILE`
	TMP=`basename $FILE`".TMP"
	DELETE="$DELETE $TMP.c $TMP.i"
	DoNoErrCheck $RM $BASE.cpm.h $TMP.c
	Do touch $BASE.cpm.h
	Do $LN -f -s $FILE $TMP.c
	Do $CMK_CPP_C -I$CHARMINC $CMK_SYSINC $OPTS_CC_GENCPM $OPTS_CPP $TMP.c > $TMP.i
	Do $CHARMBIN/conv-cpm $TMP.i $BASE.cpm.h
done

##############################################################################
#
# Compile all specified files
#
# All temporary files named *.TMP.* for easy cleanup.
#
##############################################################################

Debug "About to compile..."

numFiles=`echo $FILES | wc -w`
for FILE in `echo $FILES`
do
	BASE=`stripExtention \`basename $FILE\``
	TMP=`basename $FILE`".TMP"
	FILE_EXT=`getExtention $FILE`
	BASEO="$BASE.o"
	DESTO="-o $BASEO"

	# in case of: charmc -o object.o -c foo.c,
	# avoid foo.c => remove foo.o => foo.o => object.o,
	# instead generate object.o directly.
 	# remove and generate foo.o may be dangerous in parallel make 
	# for example in the case of compiling several objs from one 
	# same c file such as memory.c.
	if [ $numFiles = 1 -a -n "$OBJECT" ]
	then
		OBJ_EXT=`getExtention $OBJECT`
		if [ "$OBJ_EXT" = '.o' -o "$OBJ_EXT" = '.co' ]
          	then
        	    BASEO=$OBJECT
		    DESTO="-o $OBJECT"
	  	fi
        fi

#	if [ "$FILE_EXT" != ".o" -a "$FILE_EXT" != ".co" -a "$FILE_EXT" != ".M" -a "$FILE_EXT" != ".ci" ]
#	then
        case "$FILE_EXT" in
        .c|.s|.C|.cc|.cxx|.cpp|.c++|.cu|.f|.F|.f90|.F90|.fpp|.FPP|.f77|.F77)
		[ $VERBOSE ] && echo "Compiling $FILE"
		DoNoErrCheck $RM $BASEO $BASE.f.o
        esac
#	fi
	if [ ! -z "$SKIPLINK" ] 
	then
		DESTO=""
	fi
	NU_OBJ=""

	if [ "$ROSE_OMP_TLS_GLOBALS" = "yes" ]
	then
	    case "$FILE" in
		*.c)
		    Do $CMK_ROSE_OMP_TOOL -I$CHARMINC $CMK_SYSINC $OPTS_CPP_INTERNAL $OPTS_CPP $OPTS_CC -c $FILE
		    FILE="rose_$FILE"
		    ;;
		*.C|*.cc|*.cxx|*.cpp|*.c++)
		    Do $CMK_ROSE_OMP_TOOL -I$CHARMINC $CMK_SYSINC $OPTS_CPP_INTERNAL $OPTS_CPP $OPTS_CXX -c $FILE
		    FILE="rose_$FILE"
		    ;;
		*.f|*.F|*.f77|*.F77)
		    Do $CMK_ROSE_OMP_TOOL -I$CHARMINC $CMK_SYSINC $OPTS_CPP $OPTS_F90 -c $FILE
		    FILE="rose_$FILE"
		    ;;
		*.f90|*.F90|*.fpp|*.FPP)
		    test -z "$PREPROCESS" && OPTS_F90="$OPTS_F90 -c"
		    Do $CMK_ROSE_OMP_TOOL -I$CHARMINC $CMK_SYSINC $OPTS_CPP $OPTS_F90 $FILE
		    FILE="rose_$FILE"
		    ;;
	    esac
	fi

	case "$FILE" in
	*.ci)
                XIOPTS=$CMK_XIOPTS
                test "$LANGUAGE" = "f90charm" && XIOPTS="$XIOPTS -f90"
                if [ "$PREPROCESS_CI" = "yes" ]
                then
		  Do $CMK_CPP_CHARM $OPTS_CPP $FILE | Do $CHARMBIN/charmxi $XIOPTS -orig-file $FILE
                else
		  Do $CHARMBIN/charmxi $XIOPTS $FILE
                fi
		;;
	*.c|*.s)
		Do $CMK_CC -I$CHARMINC $CMK_SYSINC $OPTS_CPP_INTERNAL $OPTS_CPP $OPTS_CC -c $FILE $DESTO
		NU_OBJ=$BASEO
		if [ "$Do_res" -ne 0 ]
		then
		    touch $BASEO
		fi
		;;
	*.C|*.cc|*.cxx|*.cpp|*.c++|*.cu)
                if [ -n "$NATIVE" ]
                then
                    Do $CMK_NATIVE_CXX -I$CHARMINC $CMK_SYSINC $OPTS_CPP_INTERNAL $OPTS_CPP -c $FILE $DESTO
                else
                    Do $CMK_CXX -I$CHARMINC $CMK_SYSINC $OPTS_CPP_INTERNAL $OPTS_CPP $OPTS_CXX -c $FILE $DESTO
                fi
		NU_OBJ=$BASEO
		if [ "$Do_res" -ne 0 ]
		then
		    touch $BASEO
		fi
		;;
	*.f|*.F|*.f77|*.F77)
		test -z "$CMK_CF90_FIXED" && Abort "No F90 compiler (CMK_CF90_FIXED) defined"
		Do $CMK_CF90_FIXED -I$CHARMINC $CMK_SYSINC $OPTS_CPP $OPTS_F90 -c $FILE $DESTO
		NU_OBJ=$BASEO
		if [ "$Do_res" -ne 0 ]
		then
		    touch $BASEO
		fi
		;;
	*.f90|*.F90|*.fpp|*.FPP)
		test -z "$CMK_CF90" && Abort "No F90 compiler (CMK_CF90) defined"
		test -z "$PREPROCESS" && OPTS_F90="$OPTS_F90 -c"
		Do $CMK_CF90 -I$CHARMINC $CMK_SYSINC $OPTS_CPP $OPTS_F90 $FILE $DESTO
		NU_OBJ=$BASEO
		if [ "$Do_res" -ne 0 ]
		then
		    touch $BASEO
		fi
		;;
	*.fc|*.FC)
		Abort "I'm not yet smart enough to compile $FILE"
		;;
	*.o|*.so|*.so.*|*.sl|*.a|*.dylib|*.co)
		# make sure to link against shared charm library if creating a shared object:
		case $FILE in
			*.so|*.so.*|*.dylib) CHARM_SHARED=1 ;;
		esac
		[ ! -s $FILE ] && Abort "$FILE: file not recognized: File truncated"
		OBJECTFILES="$OBJECTFILES $FILE"
		;;
	*.M|*.mod)
	        OBJECT="$BASE"
		Copymod
		Success
		;;
	*)
		Abort "file with unrecognized extension $FILE"
	esac
# Handle new object files
	if [ -n "$NU_OBJ" -a -n "$OBJECT" ] 
	then
		if [ "$OBJECT" != "$BASEO" ]
		then
			DELETE="$DELETE $NU_OBJ"
		fi
		OBJECTFILES="$OBJECTFILES $NU_OBJ"
	fi
done

##############################################################################
#
#                        POSSIBLY, SKIP LINK-STEP
#
# 1. No $OBJECT may be specified at all --- its just a compilation.
# 2. If $OBJECT is a ".a" file, a library is created from $OBJECTFILES.
# 3. If $OBJECT is a ".o" file, then an "LDRO" is created from $OBJECTFILES.
# 4. Language may be sequential.  Do a quick and easy linkage.
#
#               in any of these cases, the full link step is skipped.
#
##############################################################################

MakeSO() {
	Debugf "Running ldro..."
	DoNoErrCheck $RM $OBJECT
	# convert to absolute path if required
	if test -n "$CMK_LD_SHARED_ABSOLUTE_PATH"
	then
	dir=`dirname $OBJECT`
	fname=`basename $OBJECT`
	dir=`cd $dir; pwd`
	OBJECT=$dir/$fname
	fi
	if test "$MAKE_LDXX" = "1"
	then
 	  soCmd="$CMK_LDXX -o $OBJECT $OPTS_LD $OPTS_LDRO $OBJECTFILES $PRE_LIBRARIES $POST_LIBRARIES $CMK_LD_SHARED_LIBS"
	else
	  soCmd="$CMK_LD -o $OBJECT $OPTS_LD $OPTS_LDRO $OBJECTFILES $PRE_LIBRARIES $POST_LIBRARIES $CMK_LD_SHARED_LIBS"
	fi
	DoNoErrCheck $soCmd
	Do_res=$?
	if [ $Do_res -ne 0 ]
	then
	    if [ -n $NOABORT ]
	    then
		touch $OBJECT
	    else
		echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
		echo "!!  Failed to compile Charm++ shared library. You can disable shared  !!"
		echo "!!  lib compilation by providing --no-build-shared build option like: !!"
		echo "!!     ./build charm++ net-linux --no-build-shared -O                 !!"
		echo "!!  or reexecute this charmc command with --no-build-shared compile option        !!"
		echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
		Abort "Command $soCmd returned error code $Do_res"
	    fi
	fi
	Copyobj
}

if [ -z "$OBJECT" -o ! -z "$SKIPLINK" ] 
then
# We have no target object, or are playing preprocessor tricks-- just end
	Debugf "No target object-- finished"
	Success
fi

Debug "About to link..."

if [ "$INPUT_GIVEN" != "1" ]
then
    Abort "Trying to link, but no object files or library archives were specified"
fi

# if interoperate dont create the library now, wait to collect all info
if [ "$MPI_INTEROPERATE" = "" ]
then
case "$OBJECT" in
*.o)
	Debugf "Converting $FILES to $OBJECTFILES"
	nFiles=`echo $FILES | wc -w`
	nObj=`echo $OBJECTFILES | wc -w`
# One source file, one .o: just move the .o
	if [ $OBJECT != $OBJECTFILES ]
	then
		Debugf "Moving .o to destination"
		DoNoErrCheck $RM $OBJECT
		Do $MV $OBJECTFILES $OBJECT
	fi
	Copyobj
	;;
*.so|*.so.*|*.sl|*.dylib)
# Make shared library
	# if no build share is set, exit normally.
	if [ "$BUILD_SHARE" = 0 ]
	then
		Warning "Warning: building shared library is not supported, recompile charm++ with '--build-shared'."
		End 0
	elif [ "$CHARM_SHARED" = "0" ]
	then
	  	MakeSO
	fi
	;;
*.a)
# Make regular (.a, non-shared) library
	# in case building charm so, build .so under lib_so as well # Gengbin
	if [ "$BUILD_SHARE" = "1" ]
	then
	  COPY_EXIT=""
	  OBJECT_SAVE=$OBJECT
	  COPYTO_SAVE=$COPYTO
	  if [ -z "$COPYTO" ]
	  then
	    DESTDIR=`echo $OBJECT | sed -e 's@lib/[^/]*\.a$@lib_so@'`
	    OBJECT=`echo $OBJECT | sed -e 's@lib/\([^/]*\)\.a$@lib_so/\1.a@'`
	  else
	    COPYTO=`echo $COPYTO | sed -e 's@lib[/]*$@lib_so@'`
	    DESTDIR=$COPYTO
	  fi
	  OBJECT=`echo $OBJECT | sed -e 's/\.a$/.'"$CMK_SHARED_SUF"'/'`
	  [ -f $DESTDIR/.charmso ] && MakeSO
	  COPYTO=$COPYTO_SAVE
	  OBJECT=$OBJECT_SAVE
	  COPY_EXIT="true"
	fi
	# build normal .a
	DoNoErrCheck $RM $OBJECT
	Do $CMK_AR $OBJECT $OBJECTFILES
	Do $CMK_RANLIB $OBJECT
	Copyobj
	;;
esac
fi
# If the above case returns, we're not creating a .o or .a file,
# so linking is needed.

############ Determine the language and libraries ##########

# Parse out the real languages
case "$LANGUAGE" in
"charm++f")
	LANGUAGE="charm++"
	USE_F90_LIBRARIES="1"
	;;
"f90charm")
        PRE_LIBRARIES="$PRE_LIBRARIES -lf90charm -lckf"
        POST_LIBRARIES="$POST_LIBRARIES $CMK_F90LIBS"
	;;
"bluegene"|"bigsim")
        PRE_LIBRARIES="$PRE_LIBRARIES -lconv-bigsim -lconv-bigsim-logs"
	;;
"ckbluegene")
        POST_LIBRARIES="$POST_LIBRARIES -lbluegene"
	;;
"bgcharm++")
        PRE_LIBRARIES="$PRE_LIBRARIES -lconv-bigsim -lconv-bigsim-logs -lconv-bluegene-stub"
	;;
"bgconverse++")
        MIDDLE_LIBS="$MIDDLE_LIBS -lconv-bigsim -lconv-bigsim-logs"
	;;
esac

# DMK - ACCEL SUPPORT - If this is a cell build, add the spe code object to POST_LIBRARIES
if [ $CMK_CELL -eq 1 ]
then

  if [ "$LANGUAGE" = "converse++" ]
  then
    # Include a "do nothing" register_accel_spe_funcs() function
    POST_LIBRARIES="$POST_LIBRARIES -lnoAccelStub"
  fi

  if [ "$LANGUAGE" = "charm++" ]
  then

    if [ $SPU_USE_CPP -eq 1 ]
    then
        SPU_COMPILER=$CMK_SPU_CXX
        SPU_LINKER=$CMK_SPU_LDXX
    else
        SPU_COMPILER=$CMK_SPU_CC
        SPU_LINKER=$CMK_SPU_LD
    fi

    # Make the spe object file to be included
    Do $SPU_COMPILER -c -I$CHARMINC $CMK_SYSINC -o main__funcLookup__.genSPECode.o main__funcLookup__.genSPECode.c -DCMK_CELL_SPE=1
    Do $SPU_LINKER -L$CHARMLIB -o main__funcLookup__.genSPECode main__funcLookup__.genSPECode.o $CMK_SPERT_LIBS $SPU_EXTRA_LIBS
    Do $CMK_PPU_EMBEDSPU spert_main main__funcLookup__.genSPECode main__funcLookup__.genSPECode.ppe.o

    # Include the spe object file for linking into main executable
    POST_LIBRARIES="$POST_LIBRARIES main__funcLookup__.genSPECode.ppe.o"

  fi
fi

if [ "$AMPIMAIN" != "" ]
then
	OBJECTFILES="$CHARMLIB/lib$AMPIMAIN.o $OBJECTFILES"
fi

if [ "$SWAPGLOBALS" = "1" ]
then
	swapo="$CHARMLIB/libglobal-swap.a"
	if [ ! -r "$swapo" -o ! -s "$swapo" ]
	then
		echo "Global-swapping library $swapo missing--"
		echo "  Is -swapglobals supported on this machine?"
		exit 1
	else
		MIDDLE_LIBS="-lglobal-swap $MIDDLE_LIBS"
	fi
fi
if [ "$SWAPGLOBALS" = "2" ]
then
	echo "-copyglobals option is no longer supported by Charm++/AMPI"
	exit 1
fi


# dummy main module
if [ "$MPI_INTEROPERATE" != "" -a "$NO_MAIN_MODULE" = "" ]
then
	POST_LIBRARIES="-lmpi-mainmodule $POST_LIBRARIES"
fi

# check if we're linking a sequential object
case "$LANGUAGE" in
"c"|"C"|"f90"|"f77")
        if [ -n "$NATIVE" ]
 	then
	  Do $CMK_NATIVE_LD $OPTS_LD -o $OBJECT $OBJECTFILES \
		-L$CHARMLIB $PRE_LIBRARIES $CMK_NATIVE_LIBS $POST_LIBRARIES
  	else
	  Do $CMK_SEQ_LD $OPTS_LD -o $OBJECT $OBJECTFILES \
		-L$CHARMLIB $PRE_LIBRARIES $CMK_SEQ_LIBS $POST_LIBRARIES
	fi
	Copyobj
	;;
"c++"|"C++")
        if [ -n "$NATIVE" ]
 	then
	  Do $CMK_NATIVE_LDXX $OPTS_LD -o $OBJECT $OBJECTFILES \
		-L$CHARMLIB $PRE_LIBRARIES $CMK_NATIVE_LIBS $POST_LIBRARIES
	else
	  Do $CMK_SEQ_LDXX $OPTS_LD -o $OBJECT $OBJECTFILES \
		-L$CHARMLIB $PRE_LIBRARIES $CMK_SEQ_LIBS $POST_LIBRARIES
	fi
	Copyobj
	;;
esac

##############################################################################
#
# Some quick consistency checks prior to full link-step
#
# Check for valid choice of TRACEMODE
# Check for valid choice of BALANCE
# Check for compatibility among BALANCE and TRACEMODE
#
##############################################################################

Debug "About to check TRACEMODE=$TRACEMODE and BALANCE=$BALANCE..."

# Check for valid choice of TRACEMODE

# [ -r $CHARMLIB/libtrace-projections.a ] || Abort "trace libraries not installed.  Is Charm++ built properly?"

if [ x"$TRACEMODE" != x ]
then
for trace in $TRACEMODE; do
    [ ! -r "$CHARMLIB/libtrace-$trace.a" ] && Abort "charmc : No such tracemode $trace"

    case "$LANGUAGE" in
        "converse"|"converse++"|"bgconverse++"|"bigsim"|"bluegene")
            if [ "$trace" != "counter" ]; then
                Warning "Tracemode $trace isn't supported in Converse-level programs; Dropping it"
                TRACEMODE=`DropList $trace $TRACEMODE`
                continue
            fi
            ;;
        *)
            ;;
    esac

    TRACE_OBJ="$TRACE_OBJ -ltrace-$trace"
done

TRACE_OBJ="$TRACE_OBJ $CMK_LIBZ"
fi

if test x$LANGUAGE = x"bgcharm++"
then 
    BALANCE=bluegene
fi

BAL_EXT=`getExtention $BALANCE`
if [ -z "$BAL_EXT" ]; then
  # Balance has no extension-- is a library reference
  if [ -f "${CHARMLIB}/libldb-$BALANCE.a" ]; then
    BAL_OBJ="${CHARMLIB}/libldb-$BALANCE.a"
  else
    BAL_OBJ="${CHARMLIBSO}/libldb-$BALANCE.so"
  fi
else
  # Balance has some extension-- must be a .o or .a file
  BAL_OBJ="$BALANCE"
fi

Debug "Finished with BAL_OBJ=$BAL_OBJ, TRACEMODE=$TRACEMODE..."

if [ ! -r "$BAL_OBJ" ]
then
	if [ "$BALANCE" = "$BAL_OBJ" ]
	then
		Abort "Could not find load balancer object $BAL_OBJ"
	else
		(cd $CHARMLIB ; ls -al libldb-*)
		Abort "Unknown load balancer $BALANCE / $BAL_OBJ"
	fi
fi

BAL_OBJ="-lldb-$BALANCE -lconv-ldb"

# Check for valid choice of MEMORY

# Isomalloc does not work on BGQ:
if [ "$CMK_BLUEGENEQ" = "1" ] && [ "$MEMORY" = "isomalloc" -o "$MEMORY" = "os-isomalloc" ]
then
  Abort "Isomalloc is not supported on BlueGene/Q."
fi

# Isomalloc does not work on Clang in non-SMP mode, so use os-isomalloc instead:
if [ "$MEMORY" = "isomalloc" -a "$CMK_USING_CLANG" = "1" -a "$CMK_SMP" != "1" ]
then
  MEMORY="os-isomalloc"
  echo "Warning: changing '-memory isomalloc' to '-memory os-isomalloc' on Clang non-SMP build target."
fi

if [ -f "${CHARMLIB}/libmemory-${MEMORY}.a" ]; then
  MEM_OBJ="${CHARMLIB}/libmemory-${MEMORY}.a"
else
  MEM_OBJ="${CHARMLIBSO}/libmemory-${MEMORY}.so"
fi

if [ ! -r $MEM_OBJ -o ! -s $MEM_OBJ ] 
then
  (cd $CHARMLIB ; list=`ls libmemory-* 2>/dev/null`; test -n "$list" && for i in $list; do [ -s $i ] && ls -l $i; done )
  Abort "charmc : No such memory mode $MEMORY"
fi

MEM_OBJ="-lmemory-${MEMORY}"

# For memory wrapping around the OS allocator, need to add also the wrapper object
case $MEMORY in
  os-*)
     MEM_OBJ=$MEM_OBJ" -lmemory-os-wrapper"
  ;;
esac

# Check for valid choice of THREAD

if [ "$CHARM_SHARED" = "1" -a -n "$CMK_LD_SHARED_THREAD" -a "$THREAD" = "default" ]
then
  THREAD=$CMK_LD_SHARED_THREAD
fi
if [ "$TLSGLOBALS"  = "1" ]
then
    # make sure we don't add an extra -tls
  if ! echo $THREAD | grep '\-tls$' > /dev/null 2> /dev/null
  then
    THREAD=${THREAD}-tls
  fi
fi

if [ -f "${CHARMLIB}/libthreads-${THREAD}.a" ]; then
  THREAD_OBJ="${CHARMLIB}/libthreads-${THREAD}.a"
else
  THREAD_OBJ="${CHARMLIBSO}/libthreads-${THREAD}.so"
fi

if [ ! -r $THREAD_OBJ -o ! -s $THREAD_OBJ ] 
then
  (cd $CHARMLIB ; list=`ls libthreads-* 2>/dev/null`; test -n "$list" && for i in $list; do [ -s $i ] && ls -l $i; done )
  Abort "charmc : No such thread mode $THREAD"
fi

THREAD_OBJ="-lthreads-${THREAD}"

################# Build the module initialization function ##################
modInitName="moduleinit$$"
modInitSrc="$modInitName.C"
modInitObj="$modInitName.o"
DoNoErrCheck $RM $modInitSrc $modInitObj > /dev/null 2>&1

for module in $MODULES; do
    echo "extern void _register$module(void);" >> $modInitSrc
done
for trace in $TRACEMODE; do
    if test $trace = "summary" 
    then
      echo "  extern void _registerTraceSummary();" >> $modInitSrc
    elif test $trace = "projections"
    then
      echo "  extern void _registerTraceProjections();" >> $modInitSrc
    elif test $trace = "simple"
    then
      echo "  extern void _registerTraceSimple();" >> $modInitSrc
    elif test $trace = "Tau"
    then
      echo "  extern void _registerTraceTau();" >> $modInitSrc
    elif test $trace = "utilization" 
    then 
      echo "  extern void _registerTraceUtilization();" >> $modInitSrc 
    elif test $trace = "controlPoints"
    then
      echo "  extern void _registerTraceControlPoints();" >> $modInitSrc
    elif test $trace = "perfReport"
    then
      Do $CP $CHARMBIN/fuzzytree.txt fuzzytree.txt
      Do $CP $CHARMBIN/tree.txt tree.txt
      echo "  extern void _registerTraceAutoPerf();" >> $modInitSrc

    elif test $trace = "all"
    then
      echo "  extern void _registerTraceProjections();" >> $modInitSrc
      echo "  extern void _registerTraceControlPoints();" >> $modInitSrc
      echo "  extern void _registerTraceSummary();" >> $modInitSrc
    fi
done
if test -n "$BALANCER"
then
    echo "extern void LBDefaultCreate(const char *);" >> $modInitSrc
fi
echo "void _registerExternalModules(char **argv) { (void)argv;" >> $modInitSrc
for module in $MODULES; do
    [ -n "$VERBOSE" ] && echo "Adding registration for module $module"
    echo "  _register$module();" >> $modInitSrc
done
for trace in $TRACEMODE; do
    if test $trace = "summary"
    then
      echo "  _registerTraceSummary();" >> $modInitSrc
    elif test $trace = "projections"
    then
      echo "  _registerTraceProjections();" >> $modInitSrc
    elif test $trace = "Tau"
    then
      TRACE_WITH_TAU=1
      echo "  _registerTraceTau();" >> $modInitSrc
    elif test $trace = "simple"
    then
      echo "  _registerTraceSimple();" >> $modInitSrc
    elif test $trace = "utilization" 
    then 
      echo "  _registerTraceUtilization();" >>  $modInitSrc 
    elif test $trace = "controlPoints"
    then
      echo "  _registerTraceControlPoints();" >> $modInitSrc
    elif test $trace = "perfReport"
    then
      echo "  _registerTraceAutoPerf();" >> $modInitSrc
    elif test $trace = "all"
    then
      echo "  _registerTraceProjections();" >> $modInitSrc
      echo "  _registerTraceControlPoints();" >> $modInitSrc
      echo "  _registerTraceSummary();" >> $modInitSrc
    fi
done
if test -n "$BALANCER"
then
    [ -n "$VERBOSE" ] && echo "Adding load balancer for $BALANCER"
    for deflb in $BALANCER
    do
      echo "  LBDefaultCreate(\"$deflb\");" >> $modInitSrc
    done
fi
echo "}" >> $modInitSrc

# creating projections
echo "void _createTraces(char **argv) { (void)argv;" >> $modInitSrc
for trace in $TRACEMODE; do
    [ -n "$VERBOSE" ] && echo "Adding registration for trace $trace"
    echo "extern void _createTrace$trace(char **argv);" >> $modInitSrc
    echo "_createTrace$trace(argv);" >> $modInitSrc
done
echo "}" >> $modInitSrc

Do $CMK_CXX $OPTS_CPP_INTERNAL $OPTS_CPP $OPTS_CXX -c $modInitSrc -o $modInitObj

###############################################################################
#
#                               Finally, LINK
#
###############################################################################

Debug "About to perform final link..."

MAKE_LDXX="0"
MAKE_LD="0"

CORE_LIBS="-lconv-core -ltmgr -lconv-util -lconv-partition $TRACE_OBJ"

# get TAU stub makefile variables
if test "$CMK_WITH_TAU" = "true"
then
  echo "include $TAU_MAKEFILE" > _make.tau.tmp
  echo "print-%:; @echo \$(\$*)" >> _make.tau.tmp
  TAU_LIBS=`make --no-print-directory -f _make.tau.tmp print-TAU_LIBS`
  TAU_MPI_LIBS=`make --no-print-directory -f _make.tau.tmp print-TAU_MPI_LIBS` 
  TAU_MPI_FLIBS=`make --no-print-directory -f _make.tau.tmp print-TAU_MPI_FLIBS`
  TAU_DEFS=`make --no-print-directory -f _make.tau.tmp print-TAU_DEFS`
  TAU_INCLUDE=`make --no-print-directory -f _make.tau.tmp print-TAU_INCLUDE`

  rm -f _make.tau.tmp
fi
# done getting TAU variables

if [ "$BUILD_SHARE" = "0" ]
then
       MIDDLE_LIBS="$MIDDLE_LIBS $MEM_OBJ $THREAD_OBJ"
fi

case "$LANGUAGE" in
"f90charm")
	MAKE_LDXX="1"
	MIDDLE_LIBS="-lck $MIDDLE_LIBS -lconv-cplus-y $CORE_LIBS "
        CMK_SYSLIBS="$CMK_SYSLIBS -lm"
        if [ "$NO_MAIN" = "" ]
        then
	  MIDDLE_LIBS="-lckmain $MIDDLE_LIBS"
        fi
	if [ "$TAU_TRACE_MPI" = "1" ]
	then
		TAU_LIBS="$TAU_MPI_FLIBS $TAU_LIBS"
	else
		TAU_LIBS="$TAU_LIBS"
	fi
	;;
"charm"|"charm++"|"f90charm"|"ckbluegene"|"bgcharm++")
	MAKE_LDXX="1"
	MIDDLE_LIBS="-lck $MIDDLE_LIBS -lconv-cplus-y $CORE_LIBS "
        if [ "$NO_MAIN" = "" ]
        then
	  MIDDLE_LIBS="-lckmain $MIDDLE_LIBS"
        fi
        CMK_SYSLIBS="$CMK_SYSLIBS -lm"
	if [ "$TAU_TRACE_MPI" = "1" ]
	then
		TAU_LIBS="$TAU_MPI_LIBS $TAU_LIBS"
	else
		TAU_LIBS="$TAU_LIBS"
	fi
	;;
"converse")
	MAKE_LD="1"
	MIDDLE_LIBS="$MIDDLE_LIBS -lconv-cplus-n $CORE_LIBS -ltrace-converse "
        CMK_SYSLIBS="$CMK_SYSLIBS -lm"
	;;
"converse++"|"bluegene"|"bigsim"|"bgconverse++")
	MAKE_LDXX="1"
	MIDDLE_LIBS="$MIDDLE_LIBS -lconv-cplus-y $CORE_LIBS -ltrace-converse "
        CMK_SYSLIBS="$CMK_SYSLIBS -lm"
	;;
*)
	Abort "Unrecognized choice of language $LANGUAGE"
	;;
esac

if [ "$BUILD_SHARE" = "0" ]
then
	MIDDLE_LIBS="$MIDDLE_LIBS $MEM_OBJ $THREAD_OBJ"
fi

POST_LIBRARIES="$POST_LIBRARIES -lmoduleNDMeshStreamer -lmodulecompletion"

if [ "$CHARM_SHARED" = "1" ]
then
  [ -z "$CHARMLIBSO" ] &&  Abort "Charm++ lib_so directory not found!"
  # build user executable/shared lib linking with charm .so
  OPTS_LD="$OPTS_LD $CMK_LD_LIBRARY_PATH"
  if [ "$BUILD_SHARE" = "1" ]
  then
    LANG_LIBS="-L$CHARMLIBSO $OBJECTFILES $PRE_LIBRARIES"
  else
    LANG_LIBS="-L$CHARMLIBSO $OBJECTFILES $modInitObj $PRE_LIBRARIES"
  fi
else
  # if interoperate, need a lib with moduleinit
  if [ "$MPI_INTEROPERATE" != "" ]
  then
    LANG_LIBS="-L$CHARMLIB -I$CHARMINC $CMK_SYSINC $PRE_LIBRARIES"
  else
    LANG_LIBS="-L$CHARMLIB -I$CHARMINC $CMK_SYSINC $OBJECTFILES $modInitObj $PRE_LIBRARIES"
  fi
fi
if [ "$TRACE_WITH_TAU" = 1 ]
then
	echo "Linking with the TAU libraries: $TAU_LIBS"
	ALL_LIBS="$LANG_LIBS $MIDDLE_LIBS $BAL_OBJ $CMK_LIBS $POST_LIBRARIES $CMK_SYSLIBS $TAU_LIBS"
else
	ALL_LIBS="$LANG_LIBS $MIDDLE_LIBS $BAL_OBJ $CMK_LIBS $POST_LIBRARIES $CMK_SYSLIBS"
fi
Debugf "All libraries are: $ALL_LIBS"

#currently only support creation of .a
if [ "$MPI_INTEROPERATE" != "" ]
then
case "$OBJECT" in
*.a)
	# in case building charm so, build .so under lib_so as well # Gengbin
	DoNoErrCheck $RM $OBJECT
        echo "$CMK_AR $OBJECT $OBJECTFILES $modInitObj"
	Do $CMK_AR $OBJECT $OBJECTFILES $modInitObj
	Do $CMK_RANLIB $OBJECT
        echo "export CHARM_ALL_LIBS=\"$ALL_LIBS\"" > ./charm_all_libs.sh
        echo "CHARM_ALL_LIBS=\"$ALL_LIBS\""
	Copyobj
	;;
*.so|*.so.*|*.sl|*.dylib)
        echo "Warning: building shared library failed; for interoperation build
        static library."
        End 0
	;;
esac
fi

if [ "$MPI_INTEROPERATE" != "" ]
then
  ALL_LIBS="$OBJECTFILES $modInitObj $ALL_LIBS"
fi

if [ "$BUILD_SHARE" = "1" -a "$CHARM_SHARED" = "1" ]
then
  # build an application .so linking with charm .so
  OPTS_LD="$OPTS_LD $CMK_LD_SHARED $OPTS_LDRO -L$CHARMLIBSO"
  Debugf "Running ldro..."
  DoNoErrCheck $RM $OBJECT
  [ "$MAKE_LDXX" = "1" ] && Do $CMK_LDXX $OPTS_LD $OPTS_LDXX -o $OBJECT $ALL_LIBS
  [ "$MAKE_LD" = "1" ] && Do $CMK_LD $OPTS_LD -o $OBJECT $ALL_LIBS
  Copyobj
else
# Make a regular executable: call the appropriate linker
  [ "$MAKE_LDXX" = "1" ] && Do $CMK_LDXX $OPTS_LD $OPTS_LDXX -o $OBJECT $ALL_LIBS
  [ "$MAKE_LD" = "1" ] && Do $CMK_LD $OPTS_LD -o $OBJECT $ALL_LIBS
fi

########################################################################
#
# Copy conv-host to user directory if it is present in installation.
#
########################################################################

if test "$COPY_CHARMRUN" = "true"
then
  targ=charmrun$CMK_POST_EXE
  [ ! -x $CHARMBIN/$targ -a -n "$CMK_POST_EXE" ] && targ=charmrun
  convhost=conv-host$CMK_POST_EXE

  if [ -x $CHARMBIN/$targ ]
  then
	DoNoErrCheck $RM $targ
	Do $CP $CHARMBIN/$targ $targ
  fi
fi

[ -z "$SAVE" ] && DoNoErrCheck $RM $modInitSrc $modInitObj > /dev/null 2>&1

Copyobj
