#! /bin/sh
# make-cross - create a cheap cross-compiler for similar platforms
# Copyright (C) 1998 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2, or (at
# your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

progname=`echo "$0" | sed 's%^.*/%%'`
help="Try \`\`$progname --help'' for more information."
force=no
run=
only_wrap_cc=no

CC=${CC-gcc}

prefix=
target=
root=
for arg
do
  case "$arg" in
  -f | --f | --fo | --for | --forc | --force)
    force=yes
    ;;

  --h | --he | --hel | --help)
    cat <<EOF
Usage: $progname [OPTION]... TARGET [INSTALL-ROOT]

Create a GCC cross-compiler from a similar native configuration.

    --cc-only         create a symbolic link only for the compiler
                        [default=all binutils and GCC programs]
-n, --dry-run         print commands rather than running them
-f, --force           replace existing files
    --help            display this message and exit
    --version         print version information and exit

TARGET is the name of the target platform.  \`TARGET-specs' will be used
as the GCC spec file.

INSTALL-ROOT is the directory in which all files and links should be
created.

The CC environment variable specifies the compiler program (usually \`gcc'
or \`egcs'), with any required arguments.
EOF
    exit 0
    ;;

  --c | --cc | --cc- | --cc-o | --cc-on | --cc-onl | --cc-only )
    only_wrap_cc=yes
    ;;

  -n | --d | --dr | --dry | --dry- | --dry-r | --dry-ru | --dry-run)
    run=echo
    ;;

  --version)
    echo "make-cross 1.7"
    exit 0
    ;;

  -*)
    echo "$progname: unrecognized option \`$arg'" 1>&2
    echo "$help" 1>&2
    exit 1
    ;;

  *)
    if test -z "$target"; then
      target="$arg"
    elif test -z "$root"; then
      root=`echo "$arg" | sed 's%/$%%'`
    else
      echo "$progname: too many arguments" 1>&2
      echo "$help" 1>&2
      exit 1
    fi
    ;;
  esac
  lastarg="$arg"
done

if test -z "$target"; then
  echo "$progname: you must specify a TARGET" 1>&2
  echo "$help" 1>&2
  exit 1
fi

cspecs="${target}-specs"
if test ! -f "$cspecs"; then
  echo "$progname: \`$cspecs' must be a valid GCC spec file" 1>&2
  exit 1
fi

# Determine the absolute name of the given CC.
set dummy $CC
shift
CC=`which "$1"`
shift
test $# -gt 0 && CC="$CC $@"

nspecs=`$CC -v 2>&1 | sed 's/.* //; q'`
case "$nspecs" in
/*) ;;
*)
  echo "$progname: cannot determine \`$CC' spec file location" 1>&2
  echo "Did you set the CC environment variable correctly?" 1>&2
  echo "$help" 1>&2
  exit 1
  ;;
esac

native=`echo "$nspecs" | sed 's%^.*/\([^/]*\)/[^/]*/[^/]*$%\1%'`
if test "X$native" = "X$nspecs"; then
  echo "$progname: cannot determine $CC platform from \`$nspecs'" 1>&2
  exit 1
fi

version=`echo "$nspecs" | sed 's%^.*/\([^/]*\)/[^/]*$%\1%'`
if test "X$version" = "X$nspecs"; then
  echo "$progname: cannot determine version name from \`$nspecs'" 1>&2
  exit 1
fi

gcclib=`echo "$nspecs" | sed 's%/[^/]*/[^/]*/[^/]*$%%'`
if test "X$gcclib" = "X$nspecs"; then
  echo "$progname: cannot determine gcc-lib directory from \`$nspecs'" 1>&2
  exit 1
fi

prefix=`echo "$gcclib" | sed 's%/[^/]*/[^/]*$%%'`
if test "X$prefix" = "X$gcclib"; then
  echo "$progname: cannot determine PREFIX from \`$gcclib'" 1>&2
  exit 1
fi

bindir="$root$prefix/bin"
tbindir="$root$prefix/$target/bin"

cdir="$root$gcclib/$target/$version"
ndir="$gcclib/$native/$version"

# Populate the cross-directory.
if test -d "$cdir"; then
  if test $force = yes; then
    $run rm -rf "$cdir"
  elif test -z "$run"; then
    echo "$progname: \`$cdir' already exists; aborting" 1>&2
    exit 1
  fi
fi

if test ! -d "$cdir"; then
  test -z "$run" && echo "mkdir -p $cdir"
  $run mkdir -p "$cdir" || test -d "$cdir" || exit $?
fi

for f in `cd "$ndir" && ls`; do
  case "$f" in
  specs)
    test -z "$run" && echo "cp $cspecs $cdir/$f"
    $run cp "$cspecs" "$cdir/$f" || exit $?
    ;;
  # Don't link to these libs, as they are OS-dependent.
  libstdc++.* | libobjc.*) ;;
  *)
    test -z "$run" && echo "ln -s ../../$native/$version/$f $cdir/$f"
    $run ln -s "../../$native/$version/$f" "$cdir/$f" || exit $?
    ;;
  esac
done

# Some GNU/Linux boxes have their crtbegin and crtend files in /usr/lib.
for f in crtbegin.o crtbeginS.o crtend.o crtendS.o crt1.o; do
  if test ! -L "$cdir/$f"; then
    if test -f "/usr/lib/$f"; then
      test -z "$run" && echo "ln -s /usr/lib/$f $cdir/$f"
      $run ln -s "/usr/lib/$f" "$cdir/$f" || exit $?
    else
      echo "$progname: WARNING: cannot find \`$f'" 1>&2
    fi
  fi
done

# Create the bindirs.
if test ! -d "$tbindir"; then
  test -z "$run" && echo "mkdir -p $tbindir"
  $run mkdir -p "$tbindir" || test -d "$tbindir" || exit $?
fi

if test ! -d "$bindir"; then
  test -z "$run" && echo "mkdir -p $bindir"
  $run mkdir -p "$bindir" || test -d "$bindir" || exit $?
fi

# Create the cross compiler wrapper.
set dummy $CC
cc=`echo "$2" | sed 's%^.*[/-]%%'`
tcc="${target}-"`echo "$2" | sed 's%^.*[/-]%%'`
if test -f "$bindir/$tcc"; then
  if test $force = yes; then
    $run rm -f "$bindir/$tcc"
  elif test -z "$run"; then
    echo "$progname: \`$bindir/$tcc' already exists; aborting" 1>&2
    exit 1
  fi
fi

echo "creating $bindir/$tcc"
if test -z "$run"; then
  rm -f "$bindir/$tcc"
  trap 'rm -f "$bindir/$tcc"; exit 1' 1 2 15
  cat <<EOF > "$bindir/$tcc"
#! /bin/sh
# $tcc - cross-compile for $target using $CC

# Make sure we find shared library dependencies without hardcoding them.
rpath_link="-Wl,-rpath-link=$prefix/$target/lib"
for arg
do
  case "\$arg" in
  -c | -S | -E | -M | -MM )
    # No linking to do, so avoid gratuitous warnings.
    rpath_link=
    ;;
  esac
done
exec $CC -b $target -nostdinc \\
	-isystem $gcclib/$target/$version/include \\
	-isystem $prefix/$target/include \\
	\$rpath_link \${1+"\$@"}
EOF
  chmod +x "$bindir/$tcc" || { rm -f "$bindir/$tcc"; exit 1; }
  trap 1 2 15
fi

# Now install the symbolic links.
if test $only_wrap_cc = yes; then
  progs="$cc"
else
  # Binutils programs:
  progs="addr2line ar as c++filt gasp ld nm objcopy objdump ranlib size \
	 strings strip"
  # GCC programs:
  progs="c++ g++ gcc $cc $progs"
fi

done_cclink=no
for f in $progs; do
  tf="$target-$f"
  if test "X$f" = "X$cc"; then
    test $done_cclink = yes && continue
    done_cclink=yes
  else
    # Create links in the main directory.
    test $force = yes && $run rm -f "$bindir/$tf"
    case "$f" in
    c++ | g++ | gcc)
      # Links to the wrapper.
      echo "ln -s $tcc $bindir/$tf"
      test -n "$run" || ln -s "$tcc" "$bindir/$tf" || exit $?
      ;;

    *)
      # Links to native tools.
      if test ! -f "$prefix/bin/$f"; then
        echo "$progname: WARNING: \`$prefix/bin/$f' is not a file" 1>&2
      fi
      echo "ln -s $f $bindir/$tf"
      test -n "$run" || ln -s "$f" "$bindir/$tf" || exit $?
      ;;
    esac
  fi

  # Alternative names for tools.
  test $force = yes && $run rm -f "$tbindir/$f"
  echo "ln -s ../../bin/$tf $tbindir/$f"
  test -z "$run" && (ln -s "../../bin/$tf" "$tbindir/$f" || exit $?)
done

# Print out some warnings, so that people don't make silly mistakes.
if test ! -d "$prefix/$target/include"; then
  echo "$progname: WARNING: \`$prefix/$target/include' is not a directory" 1>&2
fi

if test ! -d "$prefix/$target/lib"; then
  echo "$progname: WARNING: \`$prefix/$target/lib' is not a directory" 1>&2
fi
exit 0
