#!/bin/sh
GCC_SELECT_VERSION="2.15"
symlink_hdrs0="stdint.h"
symlink_libs="libcc_dynamic.a \
libcc_kext.a \
libgcc.a \
libcc.a \
libstdc++.a \
libsupc++.a"
symlink_local_libs="libcc_noc++.a"
default_dirs="include/gcc/darwin \
libexec/gcc/darwin/i386 \
libexec/gcc/darwin/ppc \
lib/gcc/darwin"
switch_it()
{
local f who status argc=$ local n="\n`echo "usage: ${0 local usage="${0##*/} [-n] [-force] [2 | 3 | 3.<number> | 4.<number> ] [-h | --help] [-v | --version]$n [-l | --list] [-root]"
dashn=
switchto_cc=0
switchto_cc_driver=0
forced=
list_versions=
usr="/usr"
installing=
show_help=
root=
wrapper=
unwrap=0
while [ $ case $1 in
2* | -2* | 3* | -3* | 4.* | -4.* )
if [[ "$switchto_cc" != "0" && "$switchto_cc" != "$1" ]]; then
echo -e "usage: $usage"
echo " Inconsistent compiler versions specified."
exit 1
fi
switchto_cc=$1
shift
;;
-force | --force)
forced=1
shift
;;
-l | -list | --list)
list_versions=1
shift
;;
-h | --help | -help | -\?)
show_help=1
shift
;;
-n)
dashn="echo -e ""\040"
shift
;;
-dstroot | --dstroot)
shift
usr="`echo "$1" | sed -e 's,/$,,'`"
if [ "${usr##*/}" != "usr" ]; then
usr="$usr/usr"
fi
installing=1
shift
;;
-wrap | --wrap)
if [ $unwrap -ne 0 ]; then
echo "Cannot specify both --wrap and --unwrap."
exit 1
fi
shift
if [ -z "$1" ]; then
cat <<WRAP_HELP
Invalid --wrap option, please specify wrapper script after --wrap.
Writing Wrapper Scripts
-----------------------
Wrapper scripts should pass \$0 (argv[0]) through to the underlying program,
since drivers may use $0 to determine behavior. Here are a couple of
examples of how to write clean wrappers:
sh no-op wrapper: exec -a "\$0" "\$0.real" "\$@"
perl no-op wrapper: exec {"\$0.real"} (\$0, @ARGV);
WRAP_HELP
exit 1
fi
wrapper="$1"
shift
;;
-unwrap | --unwrap)
if [ -n "$wrapper" ]; then
echo "Cannot specify both --wrap and --unwrap."
exit 1
fi
unwrap=1
shift
;;
-root)
root=1
shift
;;
-v | -version | --version)
echo "gcc_select v$GCC_SELECT_VERSION"
exit 0
;;
*)
echo -e "usage: $usage"
echo " Invalid argument ($1)."
exit 1
;;
esac
done
if [ "$show_help" ]; then
echo
echo -e "usage: $usage"
echo
echo "2 Select gcc 2.95.2 as the default compiler."
echo "3 Select gcc 3.1 as the default compiler."
echo "3.x Select gcc 3.x as the default compiler."
echo "4.x Select gcc 4.x as the default compiler."
echo "-force Ensure the links are correct for the specified version"
echo " even if it maches the current default version."
echo "-h Display this help info."
echo "--help Same as -h."
echo "-l List available compiler versions."
echo "--list Same as -l."
echo "-n Show commands to do selection but do not execute them."
echo "-root Skip 'root' check and assume you have root access."
echo "-v Display gcc_select version number."
echo "--version Same as -v."
echo
exit 0
fi
if [ "$list_versions" ]; then
echo "Available compiler versions:"
cd /usr/include/gcc/darwin
command ls -d [234]*
exit 1
fi
actual_ver="`cc -v 2>&1 | grep -i 'gcc version'`"
current_cc="`echo \"$actual_ver\" | sed -e 's/.*gcc version \([0-9]*\.[0-9]*\).*/\1/'`"
if [[ ! "$current_cc" == 2* && ! "$current_cc" == 3* && ! "$current_cc" == 4* ]]; then
if [ $unwrap -eq 1 ]; then
if [ -z "$forced" -o -z "$switchto_cc" ]; then
echo "To restore from an invalid GCC wrapper, use gcc_select --force --unwrap 3.3"
exit 1
else
current_cc=$switchto_cc
fi
else
echo "Error trying to determine current cc version (got $current_cc)"
exit 1
fi
fi
if [ -n "$wrapper" ]; then
if [ ! -f "$wrapper" ]; then
echo "GCC wrapper doesn't exist."
exit 1
fi
for driver in $usr/bin/{gcc,g++,c++,cpp,gcov}-* ; do
case "$driver" in
*.real)
;;
*)
if [ -L "$driver" -a -f "$driver.real" ]; then
echo "Sorry, $driver is already wrapped and we're trying to wrap it again."
if [ -z "$forced" ]; then exit 1 ; fi
fi
if [ -f "$driver.real" ]; then
echo "Error, $driver already appears to be wrapped but there is no link to it."
if [ -z "$forced" ]; then exit 1 ; fi
fi
if [ -L "$driver" ]; then
$dashn ln -sf "`readlink $driver`.real" "$driver.real" || {
echo "Couldn't symlink $driver.real to `readlink $driver`.real"
if [ -z "$forced" ]; then exit 1 ; fi
}
else
$dashn mv "$driver" "$driver.real" || {
echo "Couldn't move $driver to $driver.real"
if [ -z "$forced" ]; then exit 1 ; fi
}
fi
$dashn ln -sf "$wrapper" "$driver" || {
echo "Couldn't make symbolic link from $driver to $wrapper"
$dashn mv "$driver.real" "$driver" || echo "...and couldn't restore $driver.real to $driver"
if [ -z "$forced" ]; then exit 1 ; fi
}
;;
esac
done
forced=1
elif [ $unwrap -ne 0 ]; then
for driver in $usr/bin/{gcc,g++,c++,cpp,gcov}-*; do
case "$driver" in
*.real)
if [ -L "$driver" ]; then
$dashn rm -f "$driver" || {
echo "Couldn't remove $driver"
if [ -z "$forced" ]; then exit 1 ; fi
}
fi
;;
*)
DRIVER_LINK=
if [ -f "$driver.real" -o -L "$driver.real" ]; then DRIVER_LINK=1 ; fi
if [ -L "$driver" -a -n "$DRIVER_LINK" ]; then
$dashn rm -f "$driver" || {
echo "Couldn't remove symbolic link $driver"
if [ -z "$forced" ]; then exit 1 ; fi
}
if [ -f "$driver.real" ]; then
if [ -L "$driver.real" ] && expr "$(readlink "$driver.real")" : ".*\\.real\$" > /dev/null; then
newdest=$(readlink "$driver.real" | sed "s/\\.real\$//")
$dashn ln -sf "$newdest" "$driver.real" || {
echo "Couldn't relink $driver.real to $newdest"
if [ -z "$forced" ]; then exit 1 ; fi
}
fi
$dashn mv "$driver.real" "$driver" || {
echo "Couldn't move $driver.real to $driver"
if [ -z "$forced" ]; then exit 1 ; fi
}
fi
else
echo "Sorry, $driver does not appear to be wrapped."
if [ -z "$forced" ] ; then exit 1 ; fi
fi
;;
esac
done
forced=1
fi
if [ $argc -eq 0 ] || [ $argc -eq 1 -a "$show_ver" ]; then
echo "Current default compiler:"
echo "$actual_ver"
exit 0
fi
if [ "$forced" ] && [ "$switchto_cc" == "0" ]; then
switchto_cc=$current_cc
fi
case "$switchto_cc" in
0)
echo -e "usage: $usage"
echo " You did not specify a compiler version."
exit 1
;;
2 | 2\.95\.2)
switchto_cc_driver="2"
switchto_cc="2.95.2"
;;
3 | 3\.1)
switchto_cc_driver="3"
switchto_cc="3.1"
;;
*)
switchto_cc_driver="-$switchto_cc"
;;
esac
if [ ! "$installing" -a "$switchto_cc" != "0" ]; then
if [ ! "$forced" -a "$switchto_cc" == "$current_cc" ]; then
echo "You are already using gcc version $current_cc as the default compiler."
exit 0
fi
list=
for driver in cc c++ gcc g++ cc.real c++.real gcc.real g++.real; do
if [ -e /usr/bin/$driver -a ! -L /usr/bin/$driver ]; then
list="$list /usr/bin/$driver"
fi
done
for header in $symlink_hdrs0 ; do
if [ -e /usr/include/$header -a ! -L /usr/include/$header ]; then
list="$list /usr/include/$header"
fi
done
if [ $os_version -lt 100400 ]; then
for lib in $symlink_libs; do
if [ -e /usr/lib/$lib -a ! -L /usr/lib/$lib ]; then
list="$list /usr/lib/$lib"
fi
done
for lib in $symlink_local_libs; do
if [ -e /usr/local/lib/$lib -a ! -L /usr/local/lib/$lib ]; then
list="$list /usr/local/lib/$lib"
fi
done
fi
if [ "$list" != "" ]; then
show_list "The following file(s) exist on your system but are NOT symlinks." \
"Delete them before using gcc_select." $list
exit 1
fi
if [ "$dashn" = "" -a ! "$root" ]; then
who=$UID
if [ $who != 0 ]; then
echo '*******************************************'
echo '*** THE gcc_select SCRIPT MUST BE RUN ***'
echo '*** AS root (OR WITH THE -root OPTION). ***'
echo '*** NO CHANGES WERE MADE TO YOUR SETUP. ***'
echo '*******************************************'
exit 1
fi
fi
fi
missing=
for file_or_dir in \
/usr/bin/gcc$switchto_cc_driver \
/usr/bin/g++$switchto_cc_driver \
/usr/include/gcc/darwin/$switchto_cc/stdint.h \
/usr/include/gcc/darwin/$switchto_cc/ ; do
if [ ! -e $file_or_dir ]; then
missing="$missing $file_or_dir"
fi
done
if [ $os_version -lt 100400 -o $switchto_cc \< 4.0 ]; then
for file_or_dir in \
/usr/include/gcc/darwin/$switchto_cc/float.h \
/usr/include/gcc/darwin/$switchto_cc/stdarg.h \
/usr/include/gcc/darwin/$switchto_cc/stdbool.h \
/usr/include/gcc/darwin/$switchto_cc/varargs.h \
/usr/include/gcc/darwin/$switchto_cc/ ; do
if [ ! -e $file_or_dir ]; then
missing="$missing $file_or_dir"
fi
done
fi
if [ "$missing" != "" ]; then
show_list "The following is missing from your gcc $switchto_cc compiler installation." \
"Reinstall the $switchto_cc compiler, or use another release." $missing
exit 1
fi
if [ $switchto_cc \< 3.5 ]; then
if [ ! -e /usr/libexec/gcc/darwin/ppc/$switchto_cc ]; then
"Files in /usr/libexec/gcc/darwin/ppc/$switchto_cc are missing from your gcc
"compiler installation. Reinstall the $switchto_cc compiler, or use another release."
exit 1
fi
if [ ! -e /usr/lib/gcc/darwin/ppc/$switchto_cc ]; then
"Files in /usr/lib/gcc/darwin/ppc/$switchto_cc are missing from your gcc
"compiler installation. Reinstall the $switchto_cc compiler, or use another release."
exit 1
fi
fi
if [ "$dashn" != "" ]; then
echo "Commands that would be executed if \"-n\" were not specified:"
fi
$dashn mkdir -p $usr/bin
$dashn rm -f $usr/bin/cc $usr/bin/c++
if [ -L $usr/bin/gcc$switchto_cc_driver -o -n "$wrapper" ]; then
$dashn ln -sf gcc$switchto_cc_driver.real $usr/bin/cc.real
$dashn ln -sf g++$switchto_cc_driver.real $usr/bin/c++.real
for driver in gcc g++ gcov; do
$dashn ln -sf $driver$switchto_cc_driver.real $usr/bin/$driver.real
done
else
$dashn rm -f $usr/bin/cc.real
$dashn rm -f $usr/bin/c++.real
for driver in gcc g++ gcov; do
$dashn rm -f $usr/bin/$driver.real
done
fi
$dashn ln -sf gcc$switchto_cc_driver $usr/bin/cc
$dashn ln -sf g++$switchto_cc_driver $usr/bin/c++
for driver in gcc g++ gcov; do
$dashn rm -f $usr/bin/$driver
if [ -x /usr/bin/$driver$switchto_cc_driver ]; then
$dashn ln -sf $driver$switchto_cc_driver $usr/bin/$driver
fi
done
for dir in $default_dirs; do
if [ -d /usr/$dir ]; then
$dashn mkdir -p $usr/$dir
$dashn rm -f $usr/$dir/default
$dashn ln -sf $switchto_cc $usr/$dir/default
fi
done
if [ $os_version -ge 100400 ]; then
for lib in $symlink_libs libcc_dynamic.a ; do
[ -L $usr/lib/$lib ] && $dashn rm -f $usr/lib/$lib
done
for lib in $symlink_local_libs ; do
[ -L $usr/local/lib/$lib ] && $dashn rm -f $usr/local/lib/$lib
done
else
$dashn mkdir -p $usr/lib
for lib in $symlink_libs; do
$dashn rm -f $usr/lib/$lib
if [ -e /usr/lib/gcc/darwin/default/$lib ]; then
$dashn ln -sf gcc/darwin/default/$lib $usr/lib/$lib
fi
done
$dashn mkdir -p $usr/local/lib
for lib in $symlink_local_libs; do
$dashn rm -f $usr/local/lib/$lib
if [ -e /usr/lib/gcc/darwin/default/$lib ]; then
$dashn ln -sf ../gcc/darwin/default/$lib $usr/local/lib/$lib
fi
done
if [ ! -e $usr/lib/libcc_dynamic.a ]; then
$dashn ln -sf gcc/darwin/default/libgcc.a $usr/lib/libcc_dynamic.a
fi
fi
if [ $switchto_cc \> 3.3 ]; then
$dashn rm -f $usr/lib/gcc/darwin/default
fi
$dashn mkdir -p $usr/include
for header in $symlink_hdrs0; do
$dashn rm -f $usr/include/$header
if [ -e /usr/include/gcc/darwin/default/$header ]; then
$dashn ln -sf gcc/darwin/default/$header $usr/include/$header
fi
done
$dashn mkdir -p $usr/share/man/man1
for manpage in c++ g++ gcc gcov cpp; do
$dashn rm -f $usr/share/man/man1/$manpage.1
if [ -e /usr/share/man/man1/$manpage$switchto_cc_driver.1 ]; then
$dashn ln -sf $manpage$switchto_cc_driver.1 $usr/share/man/man1/$manpage.1
fi
done
$dashn rm -rf $usr/share/man/man1/cc.1
if [ -e /usr/share/man/man1/gcc.1 ]; then
$dashn ln -sf gcc.1 $usr/share/man/man1/cc.1
fi
if [ ! "$installing" ]; then
if [ "$dashn" == "" ]; then
actual_ver="`cc -v 2>&1 | grep -i 'gcc version'`"
current_cc="`echo \"$actual_ver\" | sed -e 's/.*gcc version \([^ ]*\).*/\1/'`"
if [[ ! "$current_cc" == 2* && ! "$current_cc" == 3* && ! "$current_cc" == 4* ]]; then
echo "Error trying to determine current cc version (got $current_cc)"
exit 1
fi
echo "Default compiler has been set to:"
echo "$actual_ver"
fi
else
echo "$(basename $0): SYMLINKS UNDER '$usr'"
echo "$(basename $0): NOW POINT AT gcc$switchto_cc_driver ($switchto_cc)"
fi
exit 0
}
show_list()
{
local info1="$1"
local info2="$2"
shift 2
if [ ${ echo "$info1"
if [ "$info2" != "" ]; then
echo "$info2"
fi
for f; do
echo " $f"
done
fi
}
os_version=$(sw_vers -productVersion | awk -F. '{ printf "%02d%02d%02d", $1, $2, $3 }')
if [ $os_version -lt 100200 ]; then
echo "You must be using MacOS X 10.2 (Jaguar) or later."
exit 1
fi
switch_it "$@"