#!/bin/sh
##**************************************************************
##
## Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
## University of Wisconsin-Madison, WI.
## 
## Licensed under the Apache License, Version 2.0 (the "License"); you
## may not use this file except in compliance with the License.  You may
## obtain a copy of the License at
## 
##    http://www.apache.org/licenses/LICENSE-2.0
## 
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
##**************************************************************

#condor_compile ld
#
#  This script can conditionally adjust the arguments to ld to link in
#  the Condor libraries.  If this script is invoked from condor_compile,
#  then the Condor libraries are linked in.  If this script is not
#  invoked via condor_compile, then it just forwards all the arguments
#  along directly to the system linker. 
#
#  THIS SCRIPT IS BEST VIEW WITH TAB STOPS IN YOUR EDITOR AT 4 SPACES
#
#   Author Todd Tannenbaum, 6/97

ldargs=$*

# Since uname and basename live in different places on various
# platforms, use a PATH.
PATH=/bin:/usr/bin:$PATH

# Determine where the real "ld" is.  It will either be /bin/ld or
# /bin/ld.real depending upon if condor_compile was fully installed
# or not.  On IRIX, however, things are more complicated because there
# are multiple linkers, so we mess around to see which one we should call.
# On linux and SunOS5, they are simply in a directory other than /bin.
CONDOR_FULLINSTALL=false

# touch the activity file if it is available to us in our environment. It is
# the root invocation(in the process tree) condor_compile's responsibility to 
# check for and clean this file up under normal and signalling circumstances
if [ "X$CONDOR_LD_IN_USE_FILE" != "X" ]; then
	touch $CONDOR_LD_IN_USE_FILE
	chmod 600 $CONDOR_LD_IN_USE_FILE
fi

# Call uname to get the OS.
os=`uname -s`
osver=`uname -r`

# Get the major version number for this Unix
if [ $os = "HP-UX" ]; then
	osmajver=`uname -r | awk -F. '{print $2}' -`
else
	osmajver=`uname -r | awk -F. '{print $1}' -`
fi

# Due to compatibility libraries on various linux machines, figure out what
# machine hardware we have so we can pick the right compatibility flags
# for the compiler. Once a true standard universe port is done to this 
# architecture we can remove this specific functionality concerning 'osmach'.
osmach=`uname -m`

# figure out if this version of the Condor syscall libraries were built with 
# gcc3 or later. 
is_gcc3=0
if [ -f $CONDOR_LIBDIR/libcomp_libgcc.a ]; then
	is_gcc3=1
	libcomp_libstdcpp="$CONDOR_LIBDIR/libcomp_libstdc++.a"
	libcomp_libgcc="$CONDOR_LIBDIR/libcomp_libgcc.a"
	libcomp_libgcc_eh="$CONDOR_LIBDIR/libcomp_libgcc_eh.a"
fi

# now, if we are gcc3 or later, add the stdc++ archive automatically to the
# link line just after our syscall library so we can resolve the increasingly 
# complex c++ bindings in our 
# system call/remote i/o libs. This is because gcc c++ support has evolved 
# really far in the internal compiler libraries(which now all depend on each 
# other in complex ways), and we can no longer construct a 
# libcondorc++support.a which is good enough anymore for gcc3 and later
# compilers.
if [ $is_gcc3 = 1 ]; then
	CONDOR_CLIB=`echo $CONDOR_CLIB $libcomp_libstdcpp`
fi

case $os in
	HP-UX )
		if [ $osmajver = "10" ]; then
			if [ -x /usr/ccs/bin/ld.real ]; then
				CONDOR_FULLINSTALL=true
			fi
			if [ $CONDOR_FULLINSTALL = true ]; then
				osld="/usr/ccs/bin/ld.real"
			else
				osld="/usr/ccs/bin/ld"
			fi
		fi
		if [ $osmajver = "09" ]; then
			if [ -x /bin/ld.real ]; then
				CONDOR_FULLINSTALL=true
			fi
			if [ $CONDOR_FULLINSTALL = true ]; then
				osld="/bin/ld.real"
			else
				osld="/bin/ld"
			fi
		fi
		;;
	SunOS )
		if [ $osmajver = 5 ]; then
			if [ -x /usr/ccs/bin/ld.real ]; then
				CONDOR_FULLINSTALL=true
			fi
			if [ $CONDOR_FULLINSTALL = true ]; then
				osld="/usr/ccs/bin/ld.real"
			else
				osld="/usr/ccs/bin/ld"
			fi
		fi
		if [ $osmajver = 4 ]; then
			if [ -x /bin/ld.real ]; then
				CONDOR_FULLINSTALL=true
			fi
			if [ $CONDOR_FULLINSTALL = true ]; then
				osld="/bin/ld.real"
			else
				osld="/bin/ld"
			fi
		fi
		;;
	Linux )
		if [ -x /usr/bin/ld.real ]; then
			CONDOR_FULLINSTALL=true
		fi
		if [ $CONDOR_FULLINSTALL = true ]; then
			osld="/usr/bin/ld.real"
		else
			osld="/usr/bin/ld"
		fi
		;;
	* )
		if [ -x /bin/ld.real ]; then
			CONDOR_FULLINSTALL=true
		fi
		if [ $CONDOR_FULLINSTALL = true ]; then
			osld="/bin/ld.real"
		else
			osld="/bin/ld"
		fi
		;;
esac

if [ A$CONDOR_COMPILE = Ayes ]; then 
  osfull="$os$osmajver"
  oscrt0="crt0.o"
  osldalt="/bin/ld"

  case $os in

	HP-UX )	
				ldargs="-a archive" 
	;;

	SunOS )	
	 			if [ $osmajver = 4 ]; then
					ldargs="-Bstatic" 
				else
					ldargs="" 
					oscrt0="crt1.o"
				fi 
	;;

	Linux )
				oscrt0="crt1.o"
				ldargs="-Bstatic" 
	;;

	* ) 		echo "ERROR: condor_compile: I do not know how to link for this operating system"
         		exit 1 
	;;

  esac

  lgcc=false
  ignore=false
  # Handle the "-c" option to ld which reads ld commands from a file
  while [ A$1 != A ]
  do
     brokenbase=$1
     if [ $brokenbase = -c ]; then
        shift
        tmp_for_me=`cat $1`
        newargs=`echo $newargs $tmp_for_me`
     else
        newargs=`echo $newargs $brokenbase`
     fi
     shift
  done

  for argument in $newargs
  do

	 # Strip off any pathnames so we can recognize crt[01].o sans paths...
     brokenbase=`basename /stupidbasename/$argument`
     if [ A$brokenbase = A ]; then
        brokenbase=$argument
     fi

     case $brokenbase in

	 # mimic -static-libgcc for gcc3+ by throwing this library out since this
	 # library is just a shard version of libgcc.a
	 -lgcc_s ) 
	 	# However, throwing this out is not quite good enough, if we do, then
		# we MUST include libcomp_libgcc_eh in the link line since that
		# is a part of the -static-libgcc feature set. This gets done below
		# when processing -lgcc.
	 	;;

	-lgcc_s_32 )
		# when running the 32-bit x86 libraries in compatibility mode on 
		# an opteron, remove this flag. The libcomp_libgcc_eh.a inclusion
		# replaces the functionality of this specific library. This
		# specific case should probably be reconsidered in the event of
		# a true opteron port.
		if [ $os = "Linux" -a $osmach = "x86_64" ]; then
			ignore=true
		else
			ldargs=`echo $ldargs $argument`
		fi
		;;
	
	# under linux with gcc3+, we must link our executables statically and this
	# requires that we use a special crtbegin shipped with the compiler that
	# allows C++ exceptions to function. XXX This code might change slightly
	# when we move to other OSes like Solaris under gcc3....
	crtbegin\.o)
		if [ $os = "Linux" -a $is_gcc3 = 1 ]; then
			tmp=`echo $argument | sed -e 's/crtbegin\.o/crtbeginT\.o/'`
				ldargs=`echo $ldargs $tmp`
		else
			# otherwise just propogate what we find if it is just a gcc 2.96
			# (or anything else) compiler which has a crtbegin.o and, via
			# manual inspection, not a crtbeginT.o. This is apparently in 
			# order to make c++ exceptions work.
			ldargs=`echo $ldargs $argument`
		fi
		;;
	
	-dynamic-linker )
		if [ $os = "Linux" ]; then
			# don't save this since we're not dynamically linking
			ldargs=`echo $ldargs`
			ignore=true
		fi
		;;
	
	-ldl )
		if [ $os = "Linux" ]; then
			# don't save this since we're not dynamically linking
			ldargs=`echo $ldargs`
		fi
		;;
	
	--as-needed | --no-as-needed )
		if [ $os = "Linux" ]; then
			# don't save this since we're not dynamically linking
			ldargs=`echo $ldargs`
		fi
		;;

	 # Throw out options that ask for shared libs on gcc3+ with linux
	 -shared )
	 		if [ $os = "Linux" ]; then
				ignore=true
			else
				ldargs=`echo $ldargs $argument`
			fi ;;

	 # Replace Standard C lib or GNU Standard C lib with condor_syscall_lib
     -lgcc )  
	 		# ok, whenever we see this flag under gcc3, we must replace it with
			# the hard archives, but we only add the CONDOR_CLIB library the 
			# *first* time we see this flag.
			if [ $is_gcc3 = 1 ]; then
				brokenbase=`echo $libcomp_libgcc $libcomp_libgcc_eh`
			fi
			
			if [ $lgcc = false ]; then
				if [ $osfull = "SunOS5" ]; then
                 	ldargs=`echo $ldargs $CONDOR_CLIB -Bdynamic -lsocket -lnsl $brokenbase`
				else
                 	ldargs=`echo $ldargs $CONDOR_CLIB $brokenbase`
				fi
                lgcc=true 
            else
                ldargs=`echo $ldargs $brokenbase`
              fi ;;

	# This argument appears only for gcc3 and later compilers
	-lgcc_eh ) 

			# get rid of this flag, replacing it with a hard archive of it
			# that we ship with Condor. This library will appear multiple
			# times on the link line sine it is often paired with -lgcc.
			# However, in the off chance that -lgcc_eh is used in another
			# place on the link line by itself cause the user is doing
			# wierd, I must failthfully translate it.

			brokenbase=`echo $libcomp_libgcc_eh`
            ldargs=`echo $ldargs $brokenbase`

			;;


     -lc )  if [ $lgcc = false ]; then
				if [ $osfull = "SunOS5" ]; then
                 	ldargs=`echo $ldargs $CONDOR_CLIB -Bdynamic -lsocket -lnsl -lc`
				else
					# don't add -lc for linux, since we provide our own.
                 	ldargs=`echo $ldargs $CONDOR_CLIB `
				fi
                lgcc=true 
              else
				if [ $os = "Linux" ]; then
					# This is to ensure that the glibc we ship gets linked
					# against it the correct nss reolution libraries we ship 
					# that are also from the condor lib dir.
					ldargs=`echo -L$CONDOR_LIBDIR $ldargs -lcondor_c -lcondor_nss_files -lcondor_nss_dns -lcondor_resolv -lcondor_c -lcondor_nss_files -lcondor_nss_dns -lcondor_resolv -lcondor_c`
				else
					ldargs=`echo $ldargs -lc `
				fi
              fi ;;

	# do some renaming of the glibc libraries we compiled which we name
	# mangle to prevent unexpected behavior from people including our lib
	# directory in with their other stuff like for libcondorapi.a.
	-lresolv)
		if [ $os = "Linux" ]; then
			ldargs=`echo $ldargs -lcondor_resolv `
		else
			ldargs=`echo $ldargs $argument `
		fi	
		;;

	-lnss_files)
		if [ $os = "Linux" ]; then
			ldargs=`echo $ldargs -lcondor_nss_files `
		else
			ldargs=`echo $ldargs $argument `
		fi
		;;

	-lnss_dns)
		if [ $os = "Linux" ]; then
			ldargs=`echo $ldargs -lcondor_nss_dns `
		else
			ldargs=`echo $ldargs $argument `
		fi
		;;

	 # Make certain condor_syscall_lib appears on the link line before any of
	 # the following language-helper libraries.  Note variable $brokenbase is
	 # currently set to the library name we may match on.
     -lstdc++ | -lg++ | -lgfortranbegin | -lf2c | -lg2c | -lp2c | -lftn | -lf77 | -lF77 | -lfrtbegin)

		# if we see -lstdc++ specifically, then replace it with the archive
		# version that we ship with Condor. XXX This might need tweaking if
		# other compilers besides gcc uses libstdc++ too...
		if [ $is_gcc3 = 1 -a "X$brokenbase" = "X-lstdc++" ]; then
			brokenbase=`echo $libcomp_libstdcpp`
		fi
		

	 		if [ $lgcc = false ]; then
				if [ $osfull = "SunOS5" ]; then
                 	ldargs=`echo $ldargs $CONDOR_CLIB -Bdynamic -lsocket -lnsl $brokenbase`
				else
                 	ldargs=`echo $ldargs $CONDOR_CLIB $brokenbase`
				fi
                lgcc=true 
            else
                ldargs=`echo $ldargs $brokenbase`
            fi ;;

	 # Replace crt[01].o with condor_rt0
     $oscrt0 ) ldargs=`echo $ldargs $CONDOR_RT0` ;;

	 # Throw out options that tell the linker to strip the binary.
	 # If the binary is stripped, then Condor complains that a STANDARD
	 # universe job was not linked with condor_syscall_lib.
     -s ) ;;

	 # Throw out options that ask for shared libs on HPUX
	 -a ) 			
			if [ $os = "HP-UX" ]; then
		 		ignore=true
		  	else
				ldargs=`echo $ldargs $argument`
		  	fi ;;

	 # Throw out options that ask for shared libs on SunOS 4.x
	 -Bdynamic ) 
			if [ $osfull != "SunOS4" ]; then
				ldargs=`echo $ldargs $argument`
		  	fi ;;

	 # Throw out options that insist on static libs, and do not allow
	 # us to switch to dynamic when we link in -lsocket, on SunOS 5.x
	 -dn ) 
			if [ $osfull != "SunOS5" ]; then
				ldargs=`echo $ldargs $argument`
		  	fi ;;

	 # Just copy over any other arguments, unless ignore is true
     * )  if [ $ignore = false ]; then
			ldargs=`echo $ldargs $argument` 
		  else 
			ignore=false
	      fi ;;

     esac
  done

  # Finally, tack on our C++ support library at the very end of the
  # link line. However, if we are using gcc3+, then do NOT tack this on
  # since we now include the entire C++ run time.
  if [ $is_gcc3 = 0 ]; then
	ldargs=`echo $ldargs $CONDOR_CPLUS`
  fi

  echo "LINKING FOR CONDOR : $osld $ldargs"
fi

# We always run the code below this point, whether called from condor_compile
# or not...  

# Fire up the "real" linker now that arguments have been modified if need be.

eval $osld $ldargs

