#!/bin/bash set -e API=https://practical-scheme.net/gauche/releases # Ensure Gauche availability # See https://github.com/practical-scheme/get-gauche/README function usage { cat <<"EOF" Usage: get-gauche.sh [--system|--home|--current|--prefix PREFIX|--update] [--auto][--version VERSION][--check-only][--force][--list] [--fixed-path][--keep-builddir][--sudo] [--skip-tests][--configure-args ARGS][--destdir DIR] [--uninstall] Options: --auto When get-gauche.sh finds Gauche needs to be installed, it proceed to download and install without asking the user. By default, the user is asked before download begins. --check-only detect Gauche and report result, but not to attempt download and install. --configure-args ARGS Pass ARGS to `configure' script of Gauche. ARGS are passed as is. --current install Gauche under the current directory. Equivalent to --prefix `pwd`. --destdir DIR set DESIDIR to DIR when run `male install'. This can be used to prepare a binary tarball. --fixed-path detect Gauche only under prefix (specified by --prefix, --system, --home or --current option). By default, get-gauche.sh also checks under directories in PATH. --force regardless of the result of version check, always download and install the specified version of Gauche. --home install Gauche under the user's home directory. Equivalent to --preifx $HOME. --keep-builddir Do not remove build directory after installation. Useful for troubleshooting. Build directory is created under the current directory with a name 'build-YYYYMMDD_hhmmss.xxxxxx' where 'YYYYMMDD_hhmmss' is the timestamp and 'xxxxxx' is a random string. --list show valid Gauche versions for --version option and exit. No other operations are performed. --prefix PREFIX install Gauche under PREFIX. The gosh executable is in PREFIX/bin, binary libraries are in PREFIX/lib, etc. --skip-tests Skip running self-tests before installing, in the emergency case when you have to do so. DO NOT USE THIS, unless you know what you're doing. --sudo invoke 'make install' via sudo. Needed if you want to install Gauche where you don't have write permissions. You may be asked to type your password by sudo. --uninstall uninstall the version of Gauche which would've been installed if this option weren't given. The other versions of Gauche remains, if they exist. Note: This operation removes all the files of the specified version, but may keep empty directories created by installation. --update install Gauche under the same directory as the currently installed one. If no previous installation is found, get-gauche.sh prompts the user to type the directory. --system install Gauche under system directory. Equivalent to --prefix /usr. --version VERSION specify the desired version of Gauche. VERSION can be a version string (e.g. '0.9.5'), or either one of the following: * 'latest' : The latest official release * 'snapshot' : The latest "snapshot" release, usually suffixed with '-p1' or -p2', if it's newer than the latest release. Otherwise, the latest release. * 'bleeding' : The latest "bleeding-edge" sources, which is created daily automatically. Note that it may be unstable or even doesn't build. By default, 'latest' is assumed. EOF } function cleanup { if [ "$keep_builddir" != yes ]; then if [ -d "$WORKDIR" ]; then rm -rf "$WORKDIR" fi fi } trap cleanup EXIT function do_list { curl -f $API/.txt exit 0 } function do_check_for_windows1 { # check msys shell case `uname -a` in MSYS*) echo "Msys shell is not supported. Please use Mingw shell." echo "Aborting." exit 1 ;; esac # check current path case `uname -a` in CYGWIN*|MINGW*) if pwd | grep -q "[[:space:]]"; then echo "Current path includes white space." echo "Please use current path not including white space." echo "Aborting." exit 1 fi ;; esac # get mingw directory case `uname -a` in MINGW*) case "$MSYSTEM" in MINGW64) mingwdir=${MINGWDIR:-/mingw64};; MINGW32) mingwdir=${MINGWDIR:-/mingw32};; *) #mingwdir=${MINGWDIR:-/mingw} echo 'Environment variable MSYSTEM is neither "MINGW32" or "MINGW64".' echo "Aborting." exit 1 ;; esac ;; esac } function do_check_for_windows2 { # check version (v0.9.4 or earlier) case `uname -a` in CYGWIN*|MINGW*) case "$desired_version" in 0.9.[234]|0.9.[234][._-]*) echo "On Windows, this script doesn't support Gauche version 0.9.4 or earlier." echo "Aborting." exit 1 ;; esac ;; esac } function do_check_for_windows3 { # check install path (v0.9.6_pre3 or earlier) case `uname -a` in CYGWIN*|MINGW*) case "$desired_version" in 0.9.6_pre[123]|0.9.[2345]|0.9.[2345][._-]*) if echo "$prefix" | grep -q "[[:space:]]"; then echo "Gauche version $desired_version can't be installed to the path" echo "including white space directly." echo "Please specify install path not including white space" echo "and manually copy files to the real install path after" echo "this script is finished." echo "Aborting." exit 1 fi ;; esac ;; esac # check write permission case `uname -a` in CYGWIN*|MINGW*) if [ ! -d "$prefix" ]; then mkdir -p "$prefix" fi set +e write_check=`mktemp "$prefix/writechk.XXXXXXXX"` if [ $? -ne 0 ]; then echo "Administrator rights might be required." echo "Aborting." exit 1 fi set -e if [ -f "$write_check" ]; then rm -f "$write_check" fi ;; esac } function do_check_prefix { gauche_config_path=`/usr/bin/which gauche-config 2>/dev/null ||:` if [ ! -z "$gauche_config_path" ]; then default_prefix=`gauche-config --prefix` existing_prefix=$default_prefix else default_prefix=/usr/local existing_prefix= fi if [ "$updating" = yes ]; then prefix=$existing_prefix fi if [ -z "$prefix" ]; then if [ "$auto" = yes ]; then echo "Prefix must be specified with --auto option." exit 1 fi if [ "$check_only" = yes ]; then prefix=$default_prefix else echo -n "Where to install Gauche? Enter directory name [$default_prefix]: " read prefix < /dev/tty if [ -z "$prefix" ]; then prefix=$default_prefix fi fi fi } function do_check_gosh { # We already have $prefix set old_path=$PATH if [ $fixed_path = "yes" ]; then PATH=$prefix/bin else # We add $prefix/bin to path so that if gosh has been installed with # the given prefix we can find it. PATH=$prefix/bin:$PATH fi gosh_path=`/usr/bin/which gosh 2>/dev/null || :` PATH=$old_path } # Make path absolute, and canonical form if we're on Windows. function canonical_path { path=$1 case $path in /*) ;; [A-Za-z]:*) ;; *) path=`pwd`/$path ;; esac case `uname -a` in CYGWIN*|MINGW*) path=`cygpath "$path"` ;; *) ;; esac echo $path } function check_destination { path=$1 if [ -d $path ]; then if [ ! -w $path ]; then echo "NOTE: You don't have the write permission of the install destination ($prefix)." if [ x$auto = xyes ]; then echo "Use --sudo option to override permissions." exit 1 else echo -n "Do you want to run 'make install' via sudo? [y/N]: " read ans < /dev/tty case "$ans" in [yY]*) ;; *) echo "Use --sudo option to override permissions." exit 1;; esac echo "*** You may be asked your password by sudo before installation." SUDO=sudo fi fi elif [ -e $path ]; then echo "Won't be able to install, because $path is in the way." exit 1 else check_destination `dirname $path` fi } function do_patch_to_source { case `uname -a` in CYGWIN*|MINGW*) # add libdir setting to avoid build error on install path patch_file=tools/gc-configure.gnu-gauche.in if [ -f $patch_file ]; then if ! grep -q -e '--libdir=/usr/local/lib' $patch_file; then cp $patch_file $patch_file.bak sed -e '/CPPFLAGS=/i \ --libdir=/usr/local/lib \\' $patch_file.bak > $patch_file fi fi # add double quotes to avoid build error on install path patch_file=lib/Makefile.in if [ -f $patch_file ]; then if ! grep -q -e '\"\$(exec_prefix)/bin/gosh\"' $patch_file; then cp $patch_file $patch_file.bak sed -e 's@\($(exec_prefix)/bin/gosh\)@\"\1\"@' $patch_file.bak > $patch_file fi fi # add preload module to avoid load error in gen-staticinit # (v0.9.6_pre6 or earlier) case "$desired_version" in 0.9.6_pre[123456]|0.9.[2345]|0.9.[2345][._-]*) patch_file=src/preload.scm if [ -f $patch_file ]; then if ! grep -q -e '(use gauche\.threads)' $patch_file; then cp $patch_file $patch_file.bak sed -e '/(use srfi-1)/i (use gauche.threads)' $patch_file.bak > $patch_file fi fi ;; esac # skip standalone test to avoid link error in MinGW 32bit # (v0.9.6_pre6 or earlier) case "$desired_version" in 0.9.6_pre[123456]|0.9.[2345]|0.9.[2345][._-]*) patch_file=test/scripts.scm if [ -f $patch_file ]; then if ! grep -q -e ';(wrap-with-test-directory static-test-1)' $patch_file; then cp $patch_file $patch_file.bak sed -e 's@\((wrap-with-test-directory static-test-1)\)@;\1@' $patch_file.bak > $patch_file fi fi ;; esac ;; esac } function do_copy_library_files { # copy mingw dll case `uname -a` in MINGW*) case "$MSYSTEM" in MINGW64|MINGW32) mingw_dll="libwinpthread-1.dll";; *) mingw_dll="mingwm10.dll";; esac for dll in $mingw_dll; do if [ -f $mingwdir/bin/$dll ]; then cp $mingwdir/bin/$dll "$prefix/bin" fi done ;; esac } # After this, cwd is the top of the extracted source tree ready to be built. function do_fetch_and_cd { CWD=`pwd` DATETIME=`date +%Y%m%d_%H%M%S` WORKDIR=`mktemp -d "$CWD/build-$DATETIME.XXXXXXXX"` uninstall=$1 cd $WORKDIR if ! curl -f -L --progress-bar -o Gauche-$desired_version.tgz $API/$desired_version.tgz; then echo "Failed URL:" $API/$desired_version.tgz exit 1 fi tar xf Gauche-$desired_version.tgz rm Gauche-$desired_version.tgz # The actual directory name may differ when $version is latest or snapshot cd Gauche-* do_patch_to_source } # Must be called in the top of extracted source tree function do_install { case `uname -a` in CYGWIN*|MINGW*) ./configure "--prefix=$prefix" --with-dbm=ndbm,odbm $configure_args make if [ "$skip_tests" != yes ]; then make -s check fi # If we use $destdir, we can't simply run 'make install', for # it tries to recreate slibcat in $prefix. if [ -z "$destdir" ]; then make install (cd src; make install-mingw) make install-examples else make DESTDIR=$destdir install-pkg make DESTDIR=$destdir install-doc (cd src; make DESTDIR=$destdir install-mingw) make DESTDIR=$destdir install-examples fi ;; *) ./configure "--prefix=$prefix" $configure_args MAKE=make if hash gmake 2>/dev/null; then MAKE=gmake; fi $MAKE -j if [ "$skip_tests" != yes ]; then $MAKE -s check fi # If we use $destdir, we can't simply run 'make install', for # it tries to recreate slibcat in $prefix. if [ -z "$destdir" ]; then $SUDO $MAKE install else $SUDO $MAKE DESTDIR=$destdir install-pkg $SUDO $MAKE DESTDIR=$destdir install-doc fi ;; esac do_copy_library_files echo "################################################################" echo "# Gauche installed under $destdir$prefix/{bin,lib,share}" echo "################################################################" } function do_uninstall { case `uname -a` in CYGWIN*|MINGW*) ./configure "--prefix=$prefix" --with-dbm=ndbm,odbm $configure_args make uninstall ;; *) ./configure "--prefix=$prefix" $configure_args MAKE=make if hash gmake 2>/dev/null; then MAKE=gmake; fi $SUDO $MAKE uninstall ;; esac echo "################################################################" echo "# Gauche uninstalled from $prefix/{bin,lib,share}" echo "################################################################" } # TRANSIENT: Gauche 0.9.15 or before can't handle bleeding edge version # numbers, so we monkey-patch it. This calls user-side gosh, so we have # to keep the monkey-patch around until all the user installations of # Gauche is updated. function compare_version { "$gosh_path" -b <integer num)) suffix) (errorf "unparsable release number: ~s" vn))) ) (if (version>? "$1" "$2") (print "GT") (print "LE")) EOF } ################################################################ # main entry point # prefix= updating= destdir= desired_version=latest check_only=no fixed_path=no force=no keep_builddir=no configure_args= skip_tests=no SUDO= if ! curl --version > /dev/null 2>&1; then echo "Can't find curl on this machine. Please install it and run get-gauche.sh again." exit 1 fi while test $# != 0 do case $1 in --*=?*) option=`expr "X$1" : 'X\([^=]*\)='` optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` extra_shift=: ;; --*=) option=`expr "X$1" : 'X\([^=]*\)='` optarg= extra_shift=: ;; *) option=$1 optarg=$2 extra_shift=shift ;; esac case $option in --list) do_list;; --system) prefix=/usr ;; --home) prefix=$HOME ;; --current) prefix=`pwd` ;; --prefix) prefix=$optarg; $extra_shift ;; --destdir) destdir=$optarg; $extra_shift ;; --update) updating=yes ;; --uninstall) uninstalling=yes ;; --version) desired_version=$optarg; $extra_shift ;; --auto) auto=yes ;; --check-only) check_only=yes ;; --fixed-path) fixed_path=yes ;; --force) force=yes ;; --keep-builddir) keep_builddir=yes ;; --skip-tests) skip_tests=yes ;; --configure-args) configure_args=$optarg; $extra_shift ;; --sudo) SUDO=sudo ;; *) echo "Unrecognized option: $option"; usage; exit 1;; esac shift done do_check_for_windows1 do_check_prefix prefix=`canonical_path "$prefix"` if [ -z "$destdir" ]; then do_check_gosh; else destdir=`canonical_path "$destdir"` fi # # If --check-only, just report the check result and exit # if [ "$check_only" = yes ]; then if [ -z "$gosh_path" ]; then echo "Gauche not found" exit 1 else echo "Found gosh in '$gosh_path'" "$gosh_path" -V exit 0 fi fi # # Resolve 'latest' and 'snapshot' versions to the actual version # case $desired_version in latest) desired_version=`curl -f $API/latest.txt 2>/dev/null`;; snapshot) desired_version=`curl -f $API/snapshot.txt 2>/dev/null`;; bleeding) desired_version=`curl -f $API/bleeding.txt 2>/dev/null`;; esac do_check_for_windows2 # # Compare with current version # if [ ! -z "$gosh_path" ]; then current_version=`"$gosh_path" -E "print (gauche-version)" -Eexit` fi if [ ! -z "$destdir" ]; then # if we're making binary tarball, install it unconditionally. need_install=yes auto=yes elif [ -z "$current_version" ]; then if [ "$fixed_path" = "yes" ]; then echo "Gauche is not found in $prefix." else echo "Gauche is not found on the system." fi need_install=yes else cmp=`compare_version $desired_version $current_version` case $cmp in GT) echo "You have Gauche $current_version in '$gosh_path'." need_install=yes;; LE) echo "You already have Gauche $current_version in '$gosh_path'." if [ "$force" != yes ]; then echo "No need to install. (Use --force option to install $desired_version.)" fi ;; esac fi # # Proceed to install # if [ "$force" = yes -o "$need_install" = yes ]; then if [ "$auto" != yes ]; then if [ "$uninstalling" != yes ]; then echo -n "Install Gauche $desired_version under $prefix? [y/N]: " else echo -n "Uninstall Gauche $desired_version under $prefix? [y/N]: " fi read ans < /dev/tty case "$ans" in [yY]*) ;; *) exit 0;; esac if [ "$skip_tests" = yes ]; then echo -n "You specified to skip tests. Are you sure? [y/N]: " read ans < /dev/tty case "$ans" in [yY]*) ;; *) exit 0;; esac fi fi case `uname -a` in CYGWIN*|MINGW*) do_check_for_windows3;; *) if [ x$SUDO = x ]; then check_destination "$destdir$prefix" fi ;; esac echo "Start installing Gauche $desired_version..." do_fetch_and_cd if [ "$uninstalling" != yes ]; then do_install else do_uninstall fi fi