#! /bin/sh # vim: ts=4 sw=4 noet # @configure_input@ #---------------------------------------------------------------------------# # Copyright (C) 1995-2008, 2010-2011The 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_DEFAULT_GRADE, ... # # ************************************************************************* # *** IMPORTANT NOTE: any changes to this file may also require similar *** # *** changes to compiler/compile_target_code.m and configure.in *** # ************************************************************************* Usage="\ Name: ml - Mercury Linker Usage: ml [] [-- ] files..." FULLARCH=@FULLARCH@ DEFAULT_GRADE=${MERCURY_DEFAULT_GRADE=@DEFAULT_GRADE@} # include the file `parse_ml_options.sh-subr' @PARSE_ML_OPTIONS@ # add /usr/local/lib to the default search path, if needed ALL_LOCAL_C_LIB_DIRS=${MERCURY_ALL_LOCAL_C_LIB_DIRS=@ALL_LOCAL_C_LIB_DIRS@} NONSHARED_LIB_DIR=${MERCURY_NONSHARED_LIB_DIR=@NONSHARED_LIB_DIR@} 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_SH@"} SHLIB_RPATH_OPT=${MERCURY_SHLIB_RPATH_OPT="@SHLIB_RPATH_OPT@"} SHLIB_RPATH_SEP=${MERCURY_SHLIB_RPATH_SEP="@SHLIB_RPATH_SEP@"} FIX_PATH_FOR_LINKER=${MERCURY_PATH_FOR_LINKER="@FIX_PATH_FOR_CC@"} LD_STATIC_FLAGS="@LD_STATIC_FLAGS@" LDFLAGS_FOR_THREADS="@LDFLAGS_FOR_THREADS@" LDFLAGS_FOR_TRACE="@LDFLAGS_FOR_TRACE@" LD_LIBFLAGS_FOR_THREADS="@LD_LIBFLAGS_FOR_THREADS@" THREAD_LIBS="@THREAD_LIBS@" TRACE_BASE_LIBS_SYSTEM="@TRACE_BASE_LIBS_SYSTEM@" TMPDIR=${TMPDIR=/tmp} MATH_LIB=${MERCURY_MATH_LIB="@MATH_LIB@"} # Note: the setting of SHARED_LIBS needs to come after the setting of MATH_LIB, # since @SHARED_LIBS_SH@ may refer to $MATH_LIB. SHARED_LIBS=${MERCURY_SHARED_LIBS="@SHARED_LIBS_SH@"} # Set the MACOSX_DEPLOYMENT_TARGET environment variable if needed. @SET_MACOSX_DEPLOYMENT_TARGET@ # When compiling in the hlc.gc grade using the Microsoft Visual C # compiler, the default maximum stack size of 4Mb is too low for a # recursive language. # XXX at some stage this should become an option to ml LINK=${LINK=/stack:10485760} # 10 Mb export LINK case "$CC" in *gcc*) COMPILER=gcc ;; *lcc*) COMPILER=lcc ;; *clang*) COMPILER=clang ;; *cl* | *CL*) COMPILER=cl ;; cc* | */cc*) COMPILER=cc ;; *) COMPILER=unknown ;; esac # On some systems we need -ldl (libdl.so) for dlopen() etc. # The name of the needed library is determined by autoconf and passed through # this variable. 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 the files indicated # in scripts/c2init.in. RT_LIB_NAME=mer_rt STD_LIB_NAME=mer_std TRACE_LIB_NAME=mer_trace SSDB_LIB_NAME=mer_ssdb EVENTSPEC_LIB_NAME=mer_eventspec BROWSER_LIB_NAME=mer_browser MDBCOMP_LIB_NAME=mer_mdbcomp MAYBE_STATIC_OPT="" case $debug in true) trace=true ;; false) ;; esac trace_base=false case $trace in true) trace_base=true ;; false) ;; esac case $ss_debug in true) trace_base=true ;; false) ;; esac case "$mercury_stdlib_dir" in "") LIBDIR= ;; *) LIBDIR=$mercury_stdlib_dir/lib ;; 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-*-freebsd*|i*86-*-cygwin*|i*86-*-solaris*) # Shared libraries are not the default on the above systems. # See configure.in for details. 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-*-freebsd*|i*86-*-cygwin*) # Shared libraries are not the default on the above systems. # See configure.in for details. # # We don't do this for Solaris/x86 because -ldl is # only available for dynamically linked executables # XXX With these defaults linking with Mercury # libraries other than the standard library will fail. case $make_shared_lib in false) all_libs=static ;; esac ;; esac ;; esac # Defaults have been set, now set options. case $all_libs in static) MAYBE_STATIC_OPT=$LD_STATIC_FLAGS ;; esac # # compute the canonical grade name from the options settings # # include the file `canonical_grade.sh-subr' @CANONICAL_GRADE@ # if the --print-grade option is specified, # then all we do is print the grade and then exit case "$print_grade" in true) echo $GRADE exit 0 ;; esac # Compute the gc grade from the grade case "$GRADE" in *.par*.gcd*.prof*) gc_grade=par_gc_debug_prof ;; *.par*.gcd*) gc_grade=par_gc_debug ;; *.gcd*.prof*) gc_grade=gc_debug_prof ;; *.gcd*) gc_grade=gc_debug ;; *.par*.gc*.prof*) gc_grade=par_gc_prof ;; *.par*.gc*) gc_grade=par_gc ;; *.gc*.prof*) gc_grade=gc_prof ;; *.gc*) gc_grade=gc ;; *.hgc*) gc_grade=hgc ;; *.mps*) gc_grade=mps ;; *) gc_grade=nogc ;; esac # if the --print-gc-grade option is specified, # then all we do is print the gc grade and then exit case "$print_gc_grade" in true) echo $gc_grade exit 0 ;; esac case "$gc_grade" in nogc) LIBGC= LIBGC_STATIC= ;; hgc) # HGC is part of the runtime, don't link anything extra. LIBGC= LIBGC_STATIC= ;; *) LIBGC="-l$gc_grade" LIBGC_STATIC=`$FIX_PATH_FOR_LINKER $LIBDIR/lib$gc_grade.@LIB_SUFFIX@` ;; esac case $readline in true) ;; false) READLINE_LIBRARIES= ;; esac case $trace_base in true) TRACE_BASE_LIBS="-l$EVENTSPEC_LIB_NAME \ -l$BROWSER_LIB_NAME -l$MDBCOMP_LIB_NAME" TRACE_BASE_LIBS_SYSTEM="$TRACE_BASE_LIBS_SYSTEM \ $READLINE_LIBRARIES" TRACE_BASE_STATIC_LIBS="\ `$FIX_PATH_FOR_LINKER \ $LIBDIR/$GRADE/lib$EVENTSPEC_LIB_NAME.@LIB_SUFFIX@` \ `$FIX_PATH_FOR_LINKER \ $LIBDIR/$GRADE/lib$BROWSER_LIB_NAME.@LIB_SUFFIX@` \ `$FIX_PATH_FOR_LINKER \ $LIBDIR/$GRADE/lib$MDBCOMP_LIB_NAME.@LIB_SUFFIX@`" ;; false) TRACE_BASE_LIBS= TRACE_BASE_LIBS_SYSTEM= TRACE_BASE_STATIC_LIBS= ;; esac case $trace in true) TRACE_LIBS="-l$TRACE_LIB_NAME $TRACE_BASE_LIBS" TRACE_LIBS_SYSTEM="$TRACE_BASE_LIBS_SYSTEM" TRACE_STATIC_LIBS="\ `$FIX_PATH_FOR_LINKER \ $LIBDIR/$GRADE/lib$TRACE_LIB_NAME.@LIB_SUFFIX@` \ $TRACE_BASE_STATIC_LIBS" ;; false) TRACE_LIBS= TRACE_LIBS_SYSTEM= TRACE_STATIC_LIBS= ;; esac case $ss_debug in true) SSDB_LIBS="-l$SSDB_LIB_NAME" SSDB_STATIC_LIBS="\ `$FIX_PATH_FOR_LINKER \ $LIBDIR/$GRADE/lib$SSDB_LIB_NAME.@LIB_SUFFIX@`" ;; false) SSDB_LIBS= SSDB_STATIC_LIBS= ;; esac case $strip in true) STRIP_OPTS="-s" ;; false) STRIP_OPTS="" ;; esac # Determine whether to link the executable with debugging symbols when using # MSVC. if test $strip = "false" -a $COMPILER = "cl" then DEBUG_FLAG="-DEBUG" else DEBUG_FLAG="" fi case $gc_method in mps) use_thread_libs=true ;; esac case $thread_safe in true) use_thread_libs=true ;; esac case $use_thread_libs.$make_shared_lib in true.false) ARCH_OPTS=$LDFLAGS_FOR_THREADS ;; true.true) ARCH_OPTS=$LD_LIBFLAGS_FOR_THREADS ;; false.*) THREAD_LIBS="" ;; esac # Set the correct flags if we're to use the MS Visual C runtime. use_msvcrt=@USE_MSVCRT@ if test $use_msvcrt = "yes" then MSVCRT_OPTS="-MD" # Enable linking with the MS Visual C runtime. NODEFAULTLIB_FLAG="-nodefaultlib:libc" else MSVCRT_OPTS="" NODEFAULTLIB_FLAG="" fi 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" case $trace in true) ARCH_OPTS="$ARCH_OPTS $LD_LIBFLAGS_FOR_TRACE" ;; esac ;; false) LINKER="$CC" UNDEF_OPT="" RPATH_OPT="$EXE_RPATH_OPT" RPATH_SEP="$EXE_RPATH_SEP" STDLIBS="$MATH_LIB $THREAD_LIBS" case $trace in true) ARCH_OPTS="$ARCH_OPTS $LDFLAGS_FOR_TRACE" ;; esac ;; esac # If the --print-link-command option is specified, # then all we do is print the command used to link executables # and then exit. case "$print_link_command" in true) echo $LINKER exit 0 ;; esac # If the --print-shared-lib-command option is specified, # then all we do is print the command used to link executables # and then exit. case "$print_shared_lib_link_command" in true) echo $LINK_SHARED_OBJ exit 0 ;; esac if $print_map then PRINT_MAP_OPT="-Wl,--print-map" else PRINT_MAP_OPT="" fi merc_libdir_opts="\ @LIB_LIBPATH@$LIBDIR/$GRADE @LIB_LIBPATH@$LIBDIR " system_libdir_opts= for dir in $ALL_LOCAL_C_LIB_DIRS kludge_for_broken_shells; do if test "$dir" != "kludge_for_broken_shells" then system_libdir_opts="@LIB_LIBPATH@$dir $system_libdir_opts" fi done LIBDIR_OPTS="$user_libdir_opts $merc_libdir_opts $system_libdir_opts" case $mercury_libs in shared) MERCURY_LIBS=${MERCURY_LIBS="$SSDB_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" merc_shlib_dirs="$merc_shlib_dirs $LIBDIR" ;; static) MERCURY_LIBS=${MERCURY_LIBS="$SSDB_STATIC_LIBS \ $TRACE_STATIC_LIBS \ `$FIX_PATH_FOR_LINKER \ $LIBDIR/$GRADE/lib$STD_LIB_NAME.@LIB_SUFFIX@` \ `$FIX_PATH_FOR_LINKER \ $LIBDIR/$GRADE/lib$RT_LIB_NAME.@LIB_SUFFIX@` \ $LIBGC_STATIC"} LIBS=${LIBS="$MERCURY_LIBS $TRACE_LIBS_SYSTEM $STDLIBS"} merc_shlib_dirs="" ;; none) LIBS="$TRACE_LIBS_SYSTEM $STDLIBS" LIBDIR_OPTS="$user_libdir_opts $system_libdir_opts" merc_shlib_dirs="" ;; esac case $all_libs in shared) system_shlib_dirs=$ALL_LOCAL_C_LIB_DIRS ;; static) system_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 \ $system_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 "$MKFIFO" in none) demangle=false ;; esac LINKER_PRE_FLAGS="$MSVCRT_OPTS $PRINT_MAP_OPT $UNDEF_OPT $STRIP_OPTS $MAYBE_STATIC_OPT $ARCH_OPTS" LINKER_POST_FLAGS="@LINK_OPT_SEP@ $NODEFAULTLIB_FLAG $DEBUG_FLAG $LIBDIR_OPTS $RPATH_OPT_LIST $LIBS" case $verbose in true) echo "ml: using grade \`$GRADE'" case $demangle in false) echo $LINKER $LINKER_PRE_FLAGS "$@" $LINKER_POST_FLAGS ;; true) echo $LINKER $LINKER_PRE_FLAGS "$@" $LINKER_POST_FLAGS "|" 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 try=0 until ML_TMPDIR=$TMPDIR/ml$$.$try PIPE=$ML_TMPDIR/pipe trap 'rmdir $ML_TMPDIR >/dev/null 2>&1; exit 1' 1 2 3 13 15 mkdir $ML_TMPDIR do try="`expr $try + 1`" # give up after 20 tries case "$try" in 20) echo "ml: unable to create temporary directory for pipe" \ 1>&2 exit 1 ;; esac done 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 --explain-link-errors 1>&2 < $PIPE & # Execute $CC with stdout & stderr redirected to go via the pipe # to $DEMANGLER and then to stderr. case $# in 0) $LINKER $LINKER_PRE_FLAGS $LINKER_POST_FLAGS >$PIPE 2>&1 ;; *) $LINKER $LINKER_PRE_FLAGS "$@" $LINKER_POST_FLAGS >$PIPE 2>&1 ;; esac linker_status=$? # Now we can remove the pipe; since is an open file, it will stay # around until $DEMANGLER exits. rm -rf $ML_TMPDIR # Wait for the demangler to exit before exiting ourselves. wait exit $linker_status ;; false) case $# in 0) exec $LINKER $LINKER_PRE_FLAGS $LINKER_POST_FLAGS ;; *) exec $LINKER $LINKER_PRE_FLAGS "$@" $LINKER_POST_FLAGS ;; esac ;; esac