#! /bin/sh # @configure_input@ #---------------------------------------------------------------------------# # Copyright (C) 1995-1999 The University of Melbourne. # This file may only be copied under the terms of the GNU General # Public License - see the file COPYING in the Mercury distribution. #---------------------------------------------------------------------------# # # ML - Mercury Linker. # # Invokes GCC with the appropriate options to link in the Mercury library. # # Usage: see below. # # Environment variables: MERCURY_C_LIB_DIR, MERCURY_DEFAULT_GRADE, ... Help="\ Name: ml - Mercury Linker Usage: ml [] [-- ] files... Options: -h, --help Print this help message. Diagnostics options: -v, --verbose Echo the gcc command line before executing it. --no-demangle Don't pipe the output of the linker through the Mercury demangler. --allow-undef --allow-undefined Don't report an error if there are unresolved symbols. This option is only used if you are building a shared library (with \`--make-shared-lib); when building executables, unresolved symbols are always errors. This option is useful when building shared libraries that are not intended to be self-contained. Dynamic/static linking options: --mercury-libs {shared, static, none} Specify which version of the standard Mercury libraries to link with: --mercury-libs shared Link with the shared libraries (*.so), if possible, otherwise with the static ones. --mercury-libs static Link with the static libraries (*.a). --mercury-libs none Don't link in the Mercury standard libraries. -shared, --shared Similar to \`--mercury-libs shared', but applies to all libraries, not just the standard Mercury libraries. -static, --static Similar to \`--mercury-libs static', but applies to all libraries, not just the standard Mercury libraries. --make-shared-lib Produce a shared library, rather than an executable. Directory options: -L , --lib-dir Include in the list of directories that the linker will use to search for libraries. -R , --shared-lib-dir Include in the list of directories that the dynamic linker will use to search for shared libraries. --leave-shared-lib-dirs-relative Don't convert relative shared library directory names into absolute paths. --no-leave-shared-lib-dirs-relative Convert relative shared library directory names into absolute paths. This is the default. Debugging options: -t, --trace Link in the Mercury debugging libraries. This option is needed if any of the modules being linked were compiled with tracing enabled. However, \`--debug' implies \`--trace', so if you're using \`--debug', then you don't need to explicitly specify \`--trace'. Note that \`--trace' is incompatible with \`--static' on some platforms (e.g. sparc-sun-solaris2.6). -r-, --no-readline Don't link in the GPL'd GNU Readline Library. -g, --c-debug, --no-strip Do not strip C debugging information. Grade options: -s , --grade --asm-labels --gcc-non-local-gotos --gcc-global-registers --gc {conservative, accurate, none} -p, --profiling --profile-calls --profile-time --profile-memory --debug --low-level-debug --use-trail --pic-reg See the documentation in the \"Invocation\" section of the Mercury User's Guide." FULLARCH=@FULLARCH@ NONSHARED_LIB_DIR=${MERCURY_NONSHARED_LIB_DIR=@NONSHARED_LIB_DIR@} DEFAULT_LIBDIR=@LIBDIR@/lib LIBDIR=${MERCURY_C_LIB_DIR=$DEFAULT_LIBDIR} DEFAULT_GRADE=${MERCURY_DEFAULT_GRADE=@DEFAULT_GRADE@} # DEMANGLER=${MERCURY_DEMANGLER=@LIBDIR@/bin/@FULLARCH@/mdemangle} DEMANGLER=${MERCURY_DEMANGLER=mdemangle} CC=${MERCURY_C_COMPILER="@CC@"} MKFIFO=${MERCURY_MKFIFO="@MKFIFO@"} ERROR_UNDEFINED="@ERROR_UNDEFINED@" ALLOW_UNDEFINED="@ALLOW_UNDEFINED@" EXE_RPATH_OPT=${MERCURY_EXE_RPATH_OPT="@EXE_RPATH_OPT@"} EXE_RPATH_SEP=${MERCURY_EXE_RPATH_SEP="@EXE_RPATH_SEP@"} EXT_FOR_SHARED_LIB=${MERCURY_EXT_FOR_SHARED_LIB="@EXT_FOR_SHARED_LIB@"} LINK_SHARED_OBJ=${MERCURY_LINK_SHARED_OBJ="@LINK_SHARED_OBJ@"} SHLIB_RPATH_OPT=${MERCURY_SHLIB_RPATH_OPT="@SHLIB_RPATH_OPT@"} SHLIB_RPATH_SEP=${MERCURY_SHLIB_RPATH_SEP="@SHLIB_RPATH_SEP@"} SHARED_LIBS=${MERCURY_SHARED_LIBS="@SHARED_LIBS@"} # On some systems (Solaris for exemple), we need libraries to be able to # use sockets. The name of the needed libraries is determined by autoconf # and passed through this variable. SOCKET_LIBRARY="@SOCKET_LIBRARY@" # Likewise for -ldl (libdl.so), which is often needed for dlopen() etc. DL_LIBRARY="@DL_LIBRARY@" # Likewise for -lreadline -l{termcap,curses,ncurses} READLINE_LIBRARIES="@READLINE_LIBRARIES@" # If you change these, you will also need to change Mmake.common.in, # scripts/c2init.in, tools/bootcheck, tools/binary, tools/binary_step # and tools/linear. RT_LIB_NAME=mer_rt STD_LIB_NAME=mer_std TRACE_LIB_NAME=mer_trace BROWSER_LIB_NAME=mer_browser verbose=false allow_undefined=false trace=false readline=true case $FULLARCH in *-win95|*-winnt|*-win32|*-cygwin32|*-cygwin) # `gcc -s' is broken in gnu-win32 strip=false ;; *) strip=true ;; esac mercury_libs=default all_libs=default demangle=true MAYBE_STATIC_OPT="" make_shared_lib=false leave_shlib_dirs_relative=false user_shlib_dirs="" # include the file `init_grade_options.sh-subr' @INIT_GRADE_OPTIONS@ while : ; do case "$1" in -h|--help|"-?") echo "$Help" exit 0 ;; -v|--verbose) verbose=true ;; --demangle) demangle=true ;; --no-demangle) demangle=false ;; --allow-undef|--allow-undefined) allow_undef=true ;; --no-allow-undef|--no-allow-undefined) allow_undef=false ;; -t|--trace) trace=true ;; -t-|--no-trace) trace=false ;; -r|--readline) readline=true ;; -r-|--no-readline) readline=false ;; -g-|--no-c-debug|--strip) strip=true ;; -g|--c-debug|--no-strip) strip=false ;; --make-shared-lib) make_shared_lib=true # on some targets, stripping shared libraries will # make them unusable, I think, so don't strip strip=false ;; --no-libs) progname=`basename $0` cat 1>&2 << EOF $progname: Warning: option \`--no-libs' is deprecated -- $progname: please use the new option \`--mercury-libs none' instead. $progname: Support for \`--no-libs' may be removed in a future release. EOF mercury_libs=none ;; --mercury-libs) case "$2" in shared|static|none|default) mercury_libs="$2" shift ;; *) progname=`basename $0` cat 1>&2 << EOF $progname: Error: parameter to \`--mercury-libs' option should be either $progname: \`shared', \`static', \`none', or \`default', not \`$2'. $progname: Try \`$0 --help' for help. EOF exit 1 ;; esac ;; -shared|--shared) all_libs=shared case $mercury_libs in static|default) mercury_libs=shared ;; esac ;; -static|--static) all_libs=static case $mercury_libs in shared|default) mercury_libs=static ;; esac ;; -L|--lib-dir) dir="$2" user_libdir_opts="$user_libdir_opts -L$dir" shift ;; -L*) user_libdir_opts="$user_libdir_opts $1" ;; --leave-shared-lib-dirs-relative) leave_shlib_dirs_relative=true ;; --no-leave-shared-lib-dirs-relative) leave_shlib_dirs_relative=false ;; -R|--shared-lib-dir) dir="$2" case $leave_shlib_dirs_relative in false) case "$dir" in /*) ;; *) dir="`pwd`/$dir" ;; esac ;; esac user_shlib_dirs="$user_shlib_dirs $dir" shift ;; -R*) dir="` expr $1 : '-R\(.*\)' `" case $leave_shlib_dirs_relative in false) case "$dir" in /*) ;; *) dir="`pwd`/$dir" ;; esac ;; esac user_shlib_dirs="$user_shlib_dirs $dir" ;; # include the file `parse_grade_options.sh-subr' @PARSE_GRADE_OPTIONS@ --) shift break ;; *) break ;; esac shift done # include the file `final_grade_options.sh-subr' @FINAL_GRADE_OPTIONS@ # --require-tracing (which is implied by --debug) implies --trace case $require_tracing in true) trace=true ;; false) ;; esac # If you haven't set mercury_libs, set it to the default value # (shared on most systems). Note that if you have set all_libs, # it will also have set mercury_libs. case $mercury_libs in default) mercury_libs=shared case $FULLARCH in i?86-*-linux*|i?86-*-freebsd*) # shared libraries are not the default on Linux # -- see README.Linux # Likewise for FreeBSD case $make_shared_lib in false) mercury_libs=static ;; esac ;; esac ;; esac # If you haven't set all_libs, set it to the default value # (shared on most systems). case $all_libs in default) all_libs=shared case $FULLARCH in i?86-*-linux*|i?86-*-freebsd*) # shared libraries are not the default on Linux # -- see README.Linux # Likewise for FreeBSD case $make_shared_lib in false) all_libs=static ;; esac ;; esac ;; esac # Defaults have been set, now set options. case $all_libs in static) case $FULLARCH in *-linux*) # On Linux, if we're linking statically, we need to # pass `-defsym _DYNAMIC=0' to the linker, to avoid # undefined references to _DYNAMIC in # boehm_gc/dyn_load.c. # (We might eventually need similar treatment # for other OSs too) MAYBE_STATIC_OPT="-static -Wl,-defsym,_DYNAMIC=0" ;; *) MAYBE_STATIC_OPT=-static ;; esac esac # # compute the grade from the options settings # case $non_local_gotos,$global_regs in true,true) GRADE="fast" ;; true,false) GRADE="jump" ;; false,true) GRADE="reg" ;; false,false) GRADE="none" ;; esac case $asm_labels in true) GRADE="asm_$GRADE" ;; false) ;; esac case $gc_method in conservative) GRADE="$GRADE.gc" ;; accurate) GRADE="$GRADE.agc" ;; esac case $profile_time,$profile_calls,$profile_memory in true,true,false) GRADE="$GRADE.prof" ;; true,false,false) GRADE="$GRADE.proftime" ;; false,true,false) GRADE="$GRADE.profcalls" ;; true,true,true) GRADE="$GRADE.profall" ;; false,true,true) GRADE="$GRADE.memprof" ;; false,false,false) ;; *) progname=`basename $0` echo \ "$progname: Error: invalid combination of profiling options." 1>&2 exit 1 ;; esac case $use_trail in true) GRADE="$GRADE.tr" ;; false) ;; esac case $stack_trace,$require_tracing in true,true) GRADE="$GRADE.debug" ;; false,true) GRADE="$GRADE.trace" ;; true,false) GRADE="$GRADE.strce" ;; false,false) ;; esac case $thread_safe in true) GRADE="$GRADE.par" ;; false) ;; esac case "$GRADE" in *.gc.prof*) LIBGC="-lgc_prof" LIBGC_STATIC="$LIBDIR/$FULLARCH/libgc_prof.a" ;; *.gc*) LIBGC="-lgc" LIBGC_STATIC="$LIBDIR/$FULLARCH/libgc.a" ;; *) LIBGC= LIBGC_STATIC= ;; esac case $readline in true) ;; false) READLINE_LIBRARIES= ;; esac case $trace in true) TRACE_LIBS="-l$TRACE_LIB_NAME -l$BROWSER_LIB_NAME" TRACE_LIBS_SYSTEM="$SOCKET_LIBRARY $DL_LIBRARY \ $READLINE_LIBRARIES" TRACE_STATIC_LIBS="\ $LIBDIR/$GRADE/$FULLARCH/lib$TRACE_LIB_NAME.a \ $LIBDIR/$GRADE/$FULLARCH/lib$BROWSER_LIB_NAME.a" ;; false) TRACE_LIBS= TRACE_LIBS_SYSTEM= TRACE_STATIC_LIBS= ;; esac case $strip in true) STRIP_OPTS="-s" ;; false) STRIP_OPTS="" ;; esac case $thread_safe in true) case "$FULLARCH" in *-osf*) THREAD_LIBS="-lpthreads -lc_r" ;; *-linux*) THREAD_LIBS="-lpthread" ;; *-solaris*) THREAD_LIBS="-lpthread -ldl" ;; *) echo "$0: warning: don't know which" \ "library to use for pthreads" 1>&2 THREAD_LIBS="" ;; esac ;; false) THREAD_LIBS="" ;; esac case $make_shared_lib in true) LINKER="$LINK_SHARED_OBJ" case $allow_undef in true) UNDEF_OPT="$ALLOW_UNDEFINED" ;; false) UNDEF_OPT="$ERROR_UNDEFINED" ;; esac RPATH_OPT="$SHLIB_RPATH_OPT" RPATH_SEP="$SHLIB_RPATH_SEP" STDLIBS="$SHARED_LIBS $THREAD_LIBS" ;; false) LINKER="$CC" UNDEF_OPT="" RPATH_OPT="$EXE_RPATH_OPT" RPATH_SEP="$EXE_RPATH_SEP" STDLIBS="-lm $THREAD_LIBS" ;; esac merc_libdir_opts="\ -L$LIBDIR/$GRADE/$FULLARCH -L$LIBDIR/$FULLARCH -L/usr/local/lib " LIBDIR_OPTS="$user_libdir_opts $merc_libdir_opts" case $mercury_libs in shared) MERCURY_LIBS=${MERCURY_LIBS="$TRACE_LIBS -l$STD_LIB_NAME -l$RT_LIB_NAME $LIBGC"} LIBS=${LIBS="$MERCURY_LIBS $TRACE_LIBS_SYSTEM $STDLIBS"} merc_shlib_dirs="$merc_shlib_dirs $LIBDIR/$GRADE/$FULLARCH" merc_shlib_dirs="$merc_shlib_dirs $LIBDIR/$FULLARCH" ;; static) MERCURY_LIBS=${MERCURY_LIBS="$TRACE_STATIC_LIBS $LIBDIR/$GRADE/$FULLARCH/lib$STD_LIB_NAME.a \ $LIBDIR/$GRADE/$FULLARCH/lib$RT_LIB_NAME.a \ $LIBGC_STATIC"} LIBS=${LIBS="$MERCURY_LIBS $TRACE_LIBS_SYSTEM $STDLIBS"} merc_shlib_dirs="" ;; none) LIBS="$TRACE_LIBS_SYSTEM $STDLIBS" LIBDIR_OPTS="$user_libdir_opts" merc_shlib_dirs="" ;; esac RPATH_OPT_LIST= # only set RPATH_OPT_LIST if the system supports shared libraries case $EXT_FOR_SHARED_LIB in so) prev="" for dir in $user_shlib_dirs $merc_shlib_dirs 'kludge for broken shells' do case "$dir" in 'kludge for broken shells') ;; *) case "$prev" in "") RPATH_OPT_LIST="$RPATH_OPT$dir" ;; *) RPATH_OPT_LIST="$RPATH_OPT_LIST$RPATH_SEP$dir" ;; esac ;; esac prev=$dir done ;; esac case $FULLARCH in # # On Irix 5, grades `fast' and `jump' only work in non_shared mode. # *-sgi-irix5*) case $non_local_gotos in true) ARCH_OPTS=-non_shared NONSHARED_PATH="$NONSHARED_LIB_DIR:/usr/lib/nonshared" LIBRARY_PATH="$NONSHARED_PATH:$LIBRARY_PATH" export LIBRARY_PATH ;; esac ;; # # On Linux ELF, `-rdynamic' is needed to make symbols # exported for use in code linked in with dlopen(), # which is used for interactive queries in the # Mercury debugger. # *-linux*aout*) # Linux a.out -- no special options needed ;; *-linux*) # Linux ELF -- need to add `-rdynamic' if using the debugger case $trace in true) ARCH_OPTS=-rdynamic esac ;; esac case "$MKFIFO" in none) demangle=false ;; esac case $verbose in true) echo "ml: using grade \`$GRADE'" case $demangle in false) echo $LINKER $UNDEF_OPT $STRIP_OPTS $MAYBE_STATIC_OPT \ $ARCH_OPTS $LIBDIR_OPTS $RPATH_OPT_LIST "$@" $LIBS ;; true) echo $LINKER $UNDEF_OPT $STRIP_OPTS $MAYBE_STATIC_OPT \ $ARCH_OPTS $LIBDIR_OPTS $RPATH_OPT_LIST "$@" $LIBS "|" echo "$DEMANGLER" ;; esac ;; esac case $demangle in true) # we would like to just run $CC and pipe the result into $DEMANGLER, # but `$CC | $DEMANGLER' would return the wrong exit status, so # we need to use a named pipe; if the system doesn't have named # pipes, then we don't use the demangler # create the pipe, making sure we remove it if interrupted old_umask=`umask` umask 022 ML_TMPDIR=/tmp/ml$$ PIPE=$ML_TMPDIR/pipe trap 'rmdir $ML_TMPDIR >/dev/null 2>&1; exit 1' 1 2 3 13 15 if mkdir $ML_TMPDIR ; then true else echo "Unable to create temporary pipe" 1>&2 exit 1 fi trap 'rm -rf $ML_TMPDIR; exit 1' 1 2 3 13 15 umask $old_umask $MKFIFO $PIPE # execute the demangler in the background, with stdin # coming from the pipe and with stdout redirected to stderr exec $DEMANGLER 1>&2 < $PIPE & # redirect our stdout and stderr into the pipe exec >$PIPE 2>&1 # now we can remove the pipe; since is an open file, it will # stay around until $CC and $DEMANGLER exit rm -rf $ML_TMPDIR # finally execute $CC; stdout & stderr will # go via the pipe to $DEMANGLER and then to stderr ;; esac case $# in 0) exec $LINKER $UNDEF_OPT $STRIP_OPTS $MAYBE_STATIC_OPT $ARCH_OPTS \ $LIBDIR_OPTS $RPATH_OPT_LIST $LIBS ;; *) exec $LINKER $UNDEF_OPT $STRIP_OPTS $MAYBE_STATIC_OPT $ARCH_OPTS \ $LIBDIR_OPTS $RPATH_OPT_LIST "$@" $LIBS ;; esac