#!/bin/bash # # Script to update/install the latest versions of all the most # important Common Lisp packages. Uses SBCL but otherwise tries to be # somewhat independent of your local environment. # # Intended to quickly bootstrap a working development environment for # Lisp free software hackers. # # Idea from jhbuild by James Henstridge (a Gnome hacker). # # Contributors: # Luke Gorrie # Anthony Chaumas-Pellet # Christophe Rhodes # David Lichteblau # Eric Marsden set -e if [ "$CLNET_USER" == "" ]; then CLNET_USER=:pserver:anonymous:anonymous fi cd $(dirname $0) system_dir="$(pwd)/systems" source_dir="$(pwd)/source" target_dir="$(pwd)/target" self="$0" while test -h "$self"; do self=`readlink "$self"` done if test x`uname -o` = xCygwin; then windowsp=1 else windowsp="" fi source clbuild.conf if test -n "$windowsp" -a x$USER_INIT = x/dev/null; then USER_INIT=NUL fi if test -n "$USER_INIT"; then common_options="--userinit $USER_INIT" else common_options="" fi # SBCL-specific options build_options="--noinform --noprint --disable-debugger $common_options" run_options="--disable-debugger $common_options" quit="(sb-ext:quit)" eval="--eval" require_asdf="(require :asdf)" # CLIM configuration case x$CLIM_BACKEND in xgraphic-forms) EXTRA_CLIM_FEATURES="(pushnew :clim-graphic-forms *features*)" maybe_load_clx="nil" ;; xgtkairo) EXTRA_CLIM_FEATURES="(pushnew :gtkairo *features*)" maybe_load_clx="nil" ;; x|xclx) EXTRA_CLIM_FEATURES="nil" maybe_load_clx="(unless (find-package :xlib) (asdf:operate 'asdf:load-op :clx))" ;; *) echo "invalid $CLIM_BACKEND, expected clx, gtkairo, or graphic-forms." 1>&2 exit 1 ;; esac if test -n "$windowsp"; then system_namestring="`cygpath -m $system_dir`/" source_namestring="`cygpath -m $source_dir`/" target_namestring="`cygpath -m $target_dir`/" self="c:/cygwin/bin/bash $self" else system_namestring="$system_dir/" source_namestring="$source_dir/" target_namestring="$target_dir/" fi set_central_registry="(setq asdf:*central-registry* '(#p\"${system_namestring}\"))" if [ ! -z $CCL ]; then # user wants OpenMCL instead of SBCL. Make it so. lisp=$CCL build_options="--batch" # fixme, that's not good enough run_options="--batch" # ditto quit="(ccl:quit)" elif [ ! -z $CLISP ]; then # user wants CLISP instead of SBCL. Make it so. cat <&1 >/dev/null; then while read line; do echo -e '\r\c' echo -n "$blank_line" echo -e '\r\c' echo -n $line | cut -b 1-65 | tr -d '\n' done echo -e '\r\c' echo -n "$blank_line" echo -e '\r\c' else while read line; do echo $line done fi } clbuild_lisp() { ${lisp} $common_options \ $eval "$require_asdf" \ $eval "$set_central_registry" \ $eval "$EXTRA_CLIM_FEATURES" \ "$@" } dribble_get() { label="$1" name="$2" if test -d `echo ${name}*/ | awk '{print $1;}'`; then echo -n "UPDATE " else echo -n "NEW " fi echo "$label $name" } get_darcs() { name="$1" url="$2" # don't use tail_last, since darcs already has this kind of progress bar if [ -d $name ]; then dribble_get "darcs pull" $name (cd $name; darcs pull --all) else dribble_get "darcs get" $name darcs get $url $name fi ln -f -s $(pwd)/$name/*.asd ${system_dir} } get_svn() { name="$1" url="$2" dribble_get "svn co" $name svn co $url $name | tail_last ln -f -s $(pwd)/$name/*.asd ${system_dir}/ } get_cvs() { module="$1" repository="$2" dribble_get "cvs co" $module cvs -d $repository co $module | tail_last ln -f -s $(pwd)/$module/*.asd ${system_dir}/ || true } # zzz I don't like the way the existing directory is removed completely. get_tarball() { name="$1" url="$2" flags="${3:-z}" tmp=$TMPDIR/${name}.tar.gz dribble_get wget $name [ -d ${name}*/ ] && rm -rf ${name}*/ wget \ --no-check-certificate \ --progress=dot \ -O "$tmp" \ $url \ 2>&1 | tail_last tar v${flags}xf "$tmp" | tail_last rm "$tmp" ln -f -s $(pwd)/${name}*/*.asd ${system_dir}/ } get_svn_clnet() { name="$1" path="$2" get_svn $name svn://common-lisp.net/project/$name/svn/$2 } get_cvs_clnet() { module="$1" project="${2:-$1}" get_cvs $module ${CLNET_USER}@common-lisp.net:/project/$project/cvsroot } get_ediware() { name="$1" get_tarball $name http://weitz.de/files/${name}.tar.gz } get_tarball_bz2() { get_tarball "$1" "$2" j } recompile() { rm -f monster.core touch source/eclipse/config.lisp cmd="${1:-$quit}" ${lisp} $build_options \ $eval "$require_asdf" \ $eval "$set_central_registry" \ $eval "$EXTRA_CLIM_FEATURES" \ $eval "$maybe_load_clx" \ $eval "(asdf:oos 'asdf:load-op :mcclim)" \ $eval "(asdf:oos 'asdf:load-op :cl-ppcre)" \ $eval "(asdf:oos 'asdf:load-op :clim-listener)" \ $eval "(asdf:oos 'asdf:load-op :skippy)" \ $eval "(asdf:oos 'asdf:load-op :gsharp)" \ $eval "(asdf:oos 'asdf:load-op :clim-examples)" \ $eval "(asdf:oos 'asdf:load-op :closure)" \ $eval "(asdf:oos 'asdf:load-op :beirc)" \ $eval "(asdf:oos 'asdf:load-op :climacs)" \ $eval "(asdf:oos 'asdf:load-op :climplayer)" \ $eval "(asdf:oos 'asdf:load-op :hunchentoot-test)" \ $eval "(asdf:oos 'asdf:load-op :cl-webdav)" \ $eval "(asdf:oos 'asdf:load-op :eclipse)" \ $eval "(eclipse-system:compile-themes \"source/eclipse/themes/microGUI/\" \"source/eclipse/themes/Step/\" \"source/eclipse/themes/brushed-metal/\" \"source/eclipse/themes/CoolClean/\")" \ $eval "$cmd" echo "$0 ok" } count_systems() { n_asd=`ls -1 $system_dir/*.asd | wc -l` echo "$n_asd systems definition files registered" } update() { rm -f monster.core TMPDIR=`mktemp -d /tmp/clbuild.XXXXXXXXXX` cleanup() { rm -rf $TMPDIR } trap cleanup exit cd $source_dir source ../update.sh echo "update complete" count_systems } help() { cat <= 2.8.) EOF } check_program() { if ! "$1" --help >/dev/null; then echo Error: Cannot find a working installation of "$1" exit 1 fi echo "found `which $1`" } # for programs that don't understand --help, or (like cvs) are stupid enough # to return a failure code when invoked using a correct --help option... check_misdesigned_program() { if ! which "$1" >/dev/null; then echo Error: Cannot find a working installation of "$1" exit 1 fi echo "found `which $1`" } start_clim() { system=$1 cmd="$2" ${lisp} $run_options \ $eval "$require_asdf" \ $eval "$set_central_registry" \ $eval "$EXTRA_CLIM_FEATURES" \ $eval "$maybe_load_clx" \ $eval "(asdf:operate 'asdf:load-op :mcclim)" \ $eval "(asdf:operate 'asdf:load-op $system)" \ $eval "$cmd" \ $eval "$quit" } interactive_menu() { if ! dialog --clear --title "clbuild" \ --menu "Welcome to clbuild's interactive menu.\n\n\ If unsure, choose 'update' to download the userland, then try\n\ running one of applications." \ 0 0 0 \ "update" "download/update all applications" \ "recompile" "recompile all applications" \ "dumpcore" "recompile and dump a core file for faster startup" \ "" "" \ "buildsbcl" "download/update and compile SBCL" \ "world" "buildsbcl && update && dumpcore" \ "" "" \ "slime" "run the Superior Lisp Interaction Mode in a fresh Emacs" \ "slime -nw" "run the Superior Lisp Interaction Mode (in this TTY)" \ "lisp" "run Lisp in the terminal" \ "" "" \ "gsharp" "run the Gsharp score editor" \ "climacs" "run the Climacs text editor" \ "closure" "run the CLOSURE web browser" \ "beirc" "run the Beirc IRC client" \ "climplayer" "run the CLIMPlayer music player" \ "demodemo" "run some random CLIM examples" \ "hunchentoot" "run the Hunchentoot web server test" \ "webdav" "run the CL-WEBDAV server" \ "eclipse" "run the eclipse window manager" \ "" "" \ "clear" "Delete all fasls" \ "mrproper" "Delete all downloaded source and fasls" \ "" "" \ "quit" "Exit clbuild" \ 2>$TMPDIR/choice then echo menu aborted exit 0 fi choice="`cat $TMPDIR/choice`" case $choice in webdav) if dialog --title "clbuild webdav" --clear --inputbox \ "A WebDAV server will be started on http://localhost:4242.\n\n\ Files will be served for read and write operations without authentication.\n\n\ Please choose a directory to be exported." \ 16 72 /tmp 2>$TMPDIR/choice then directory=`cat $TMPDIR/choice` if test -d $directory; then choice="webdav $directory" else $DIALOG --title "clbuild webdav" --clear \ --msgbox "Error: Directory not found: $directory" \ 10 41 choice="" fi else choice="" fi ;; eclipse) if dialog --title "clbuild webdav" --clear --inputbox \ "Please enter the X11 display to run eclipse on." \ 16 72 ${DISPLAY:-:0} 2>$TMPDIR/choice then choice="eclipse `cat $TMPDIR/choice`" else choice="" fi ;; esac case $choice in "") ;; quit) exit 0 ;; *) echo "$0" $choice || echo clbuild: $choice failed echo echo Type RET to continue read ;; esac } check() { echo "Checking for helper applications..." check_misdesigned_program cvs check_program svn check_program darcs check_program wget check_program tar check_misdesigned_program mktemp echo "Success: All helper applications found." echo echo "Checking Lisp startup..." if ${lisp} $run_options $eval $quit >/dev/null; then echo "Success: Lisp starts up using \"$lisp\"" else echo "Error: Cannot run Lisp using \"$lisp\"" exit 1 fi echo echo "Looking for installable systems..." count_systems } dumpcore() { recompile '(sb-ext:save-lisp-and-die "monster.core")' echo "monster.core dumped" } if test -f monster.core; then # echo "using `pwd`/monster.core" run_options="--core monster.core $run_options" fi case $1 in check) check ;; world) "$0" clean && "$0" buildsbcl && "$0" build ;; clean) rm -f monster.core cd $source_dir find . -name "*.fasl" -exec rm {} \; find . -name "*.lx64fsl" -exec rm {} \; ;; mrproper) rm -rf monster.core ${source_dir} ${target_dir} ;; update) update ;; recompile) recompile ;; build) update dumpcore ;; dumpcore) if [ -n "$CCL" ]; then echo "Sorry, dumpcore not implemented for OpenMCL yet." 1>&2 exit 1 fi dumpcore ;; buildsbcl) if [ -n "$CCL" ]; then echo "Cowardly refusing to build SBCL when \$CCL is set." 1>&2 exit 1 fi cd ${source_dir} cvs -d :pserver:anonymous:@sbcl.cvs.sourceforge.net:/cvsroot/sbcl co sbcl # Enable threads if test -z "$windowsp"; then echo '(lambda (list) (pushnew :sb-thread list) list)' > sbcl/customize-target-features.lisp fi (cd sbcl; sh make.sh; SBCL_HOME= INSTALL_ROOT=${target_dir} sh install.sh) ;; lisp) shift; clbuild_lisp "$@" ;; sbcl) if [ -n "$CCL" ]; then echo "Cowardly refusing to run SBCL when \$CCL is set." 1>&2 exit 1 fi shift; clbuild_lisp "$@" ;; openmcl) if [ -z "$CCL" ]; then echo "Cannot run OpenMCL because \$CCL is not set." 1>&2 exit 1 fi shift; clbuild_lisp "$@" ;; slime) shift emacs_args="$@" emacs=${EMACS-emacs} $emacs \ -eval "(setq load-path (cons \"${source_namestring}slime\" load-path))" \ -eval "(setq inhibit-splash-screen t)" \ -eval "(load \"${source_namestring}slime/slime\")" \ -eval "(setq inferior-lisp-program \"$self lisp\")" \ -eval "(slime-setup)" \ -eval '(slime)' \ ${emacs_args} ;; listener) start_clim :clim-listener "(clim-listener:run-listener)" ;; gsharp) start_clim :gsharp "(gsharp::gsharp)" ;; demodemo) start_clim :clim-examples "(clim-demo::demodemo)" ;; climacs) start_clim :climacs "(climacs:climacs)" ;; closure) start_clim :closure "(clim-user::run-closure :new-process nil)" ;; beirc) start_clim :beirc "(beirc:beirc :new-process nil)" ;; climplayer) check_program fileschanged check_misdesigned_program mplayer start_clim :climplayer "(climplayer:climplayer)" ;; hunchentoot) if ! test -f /usr/lib/libssl.so; then echo "WARNING: /usr/lib/libssl.so not found, did you install OpenSSL?" echo "(type RET to continue anyway)" read fi ${lisp} $run_options \ $eval "$require_asdf" \ $eval "$set_central_registry" \ $eval "(asdf:operate 'asdf:load-op :hunchentoot-test)" \ $eval "(setf tbnl:*catch-errors-p* nil)" \ $eval "(hunchentoot:start-server :port 4242)" \ $eval '(format t "~%Webserver is running at http://localhost:4242/hunchentoot/test~%")' \ $eval '(format t "Type RET to quit~%")' \ $eval '(read-line)' \ $eval "$quit" ;; webdav) if ! test -f /usr/lib/libssl.so; then echo "WARNING: /usr/lib/libssl.so not found, did you install OpenSSL?" echo "(type RET to continue anyway)" read fi directory="$2/" if ! test -d "$directory"; then echo Error: Expected directory as an argument. echo usage: clbuild webdav DIRECTORY exit 1 fi ${lisp} $run_options \ $eval "$require_asdf" \ $eval "$set_central_registry" \ $eval "(asdf:operate 'asdf:load-op :cl-webdav)" \ $eval "(setf tbnl:*catch-errors-p* nil)" \ $eval "(setf dav:*file-resource-base-path-namestring* \"$directory\")" \ $eval "(push (dav:create-dav-dispatcher 'dav:file-resource) tbnl:*dispatch-table*)" \ $eval "(hunchentoot:start-server :port 4242)" \ $eval "(format t \"~%WebDAV server for $directory is running at http://localhost:4242/~%\")" \ $eval '(format t "Type RET to quit~%")' \ $eval '(read-line)' \ $eval "$quit" ;; eclipse) options="" if test -n "$2"; then options=":display \"$2\"" fi touch source/eclipse/config.lisp # zzz cl-user::*eclipse-initfile*?! # zzz cl-user::*eclipse-eclipsedir*?! ${lisp} $run_options \ $eval "$require_asdf" \ $eval "$set_central_registry" \ $eval "(unless (find-package :eclipse) (asdf:operate 'asdf:load-op :eclipse))" \ $eval "(defparameter cl-user::*eclipse-initfile* \".eclipse.lisp\")" \ $eval "(defparameter cl-user::*eclipse-eclipsedir* nil)" \ $eval "(unless (find-package :eclipse) (eclipse-system:compile-themes \"source/eclipse/themes/microGUI/\" \"source/eclipse/themes/Step/\" \"source/eclipse/themes/brushed-metal/\" \"source/eclipse/themes/CoolClean/\"))" \ $eval "(load (compile-file \"source/eclipse/lib/clx-ext/event.lisp\"))" \ $eval "(eclipse:eclipse $options)" \ $eval "$quit" ;; help|--help|-h|-H) help ;; ""|dialog) if ! dialog --help >/dev/null; then cat <