Files
mercury/scripts/ml.in
Warwick Harvey 67a204a188 If a shared library directory given to `ml' is relative, turn it
Estimated hours taken: 1.5

scripts/ml.in:
	If a shared library directory given to `ml' is relative, turn it
	into an absolute path by prepending the current directory.  Also
	add options `--[no-]leave-shared-lib-dirs-relative' to `ml' to
	turn off/on this behaviour.
1999-07-01 02:58:50 +00:00

623 lines
15 KiB
Bash

#! /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 [<ml options>] [-- <gcc options>] 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 <directory>, --lib-dir <directory>
Include <directory> in the list of directories that the
linker will use to search for libraries.
-R <directory>, --shared-lib-dir <directory>
Include <directory> 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>, --grade <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