Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tree: df3a20c81a
Fetching contributors…

Cannot retrieve contributors at this time

executable file 484 lines (435 sloc) 13.756 kB
#!/usr/bin/env bash
# Fail if we try to use an undefined value
set -u
# Quit on errors
set -e
#
# Display usage message then quit
#
function help_then_exit() {
echo Usage: "$0" [flags]
echo
echo "Possible flags:"
echo "-h Display this message"
echo "-b [path] Use [path] as \$OCAMLBREW_BASE"
echo "-c \"[flags]\" Flags to pass to OCaml's configure"
echo "-a Install everything with no prompts"
echo "-o Install OCaml only, no prompts"
echo "-f Install OCaml and findlib only, no prompts"
echo "-s [path] Install OCaml from Subversion [path]"
echo "-t Install OCaml from Subversion trunk"
echo "-n [name] Install under \$OCAMLBREW_BASE/[name]"
echo
echo "The build and installation will occur under \$OCAMLBREW_BASE"
echo "Subversion path should be relative to $OCAML_SVN_ROOT"
exit 1
}
#
# Print a message when quitting due to an error
#
function handle_error() {
[ -t 3 ] && {
echo "Something errored out, please check the log file for details:"
echo "$OCAMLBREW_LOGFILE"
echo Exiting...
} >&3
}
#
# Initialize output redirection
#
function init_redirect() {
exec 3>&1
exec > "$OCAMLBREW_LOGFILE"
exec 2>&1
}
#
# Output which should be displayed on screen and logged
#
function say() {
echo "$*" >&3
echo "$*"
}
#
# Read input without logging the input prompt
#
function prompt() {
echo -n "$*" >&3
read
}
#
# Initialize lots and lots of global build and installation variables
#
function init_variables() {
# Installation prefix for the software being installed
: ${OCAMLBREW_BASE="$HOME"/ocamlbrew}
# By default, there is no custom OCaml installation directory name
: ${OCAMLBREW_NAME=""}
# Specific installation set options
: ${INSTALL_ALL="false"}
: ${INSTALL_OCAML_ONLY="false"}
: ${INSTALL_OCAML_FINDLIB_ONLY="false"}
: ${OCAMLBREW_INSTALL_SVN="false"}
# Set configuration options such as installation and build locations here
# OCaml from Subversion
: ${OCAMLBREW_SVN_PATH=trunk}
# The version of OCaml we are installing and download URL
: ${OCAML_MAJOR_VERSION=3}
: ${OCAML_MINOR_VERSION=12}
: ${OCAML_PATCH_VERSION=1}
: ${OCAML_VERSION=$OCAML_MAJOR_VERSION.$OCAML_MINOR_VERSION.$OCAML_PATCH_VERSION}
: ${OCAML_URL=http://caml.inria.fr/pub/distrib/ocaml-$OCAML_MAJOR_VERSION.$OCAML_MINOR_VERSION/ocaml-$OCAML_VERSION.tar.gz}
# findlib version we are installing and download URL
: ${FINDLIB_MAJOR_VERSION=1}
: ${FINDLIB_MINOR_VERSION=2}
: ${FINDLIB_PATCH_VERSION=7}
: ${FINDLIB_VERSION=$FINDLIB_MAJOR_VERSION.$FINDLIB_MINOR_VERSION.$FINDLIB_PATCH_VERSION}
: ${FINDLIB_URL=http://download.camlcity.org/download/findlib-$FINDLIB_VERSION.tar.gz}
if [ "$OCAMLBREW_NAME" != "" ]; then
# Install path based on a custom directory name
OCAML_BASE="$OCAMLBREW_BASE"/"$OCAMLBREW_NAME"
elif [ "$OCAMLBREW_INSTALL_SVN" = "true" ]; then
# Install path based on location in the Subversion tree
OCAML_BASE="$OCAMLBREW_BASE"/ocaml-svn/"$OCAMLBREW_SVN_PATH"
else
# Install path based on release version of OCaml
OCAML_BASE="$OCAMLBREW_BASE"/ocaml-"$OCAML_VERSION"
fi
# Parent directory where software will be built
: ${BUILD_DIR="$OCAML_BASE"/build}
# Configuration flags for OCaml
: ${OCAML_CONFIG_FLAGS=""}
# odb paths
: ${ODB_BUILD_DIR="$BUILD_DIR"/odb}
: ${ODB_INSTALL_DIR="$OCAML_BASE"/odb}
# Output will be redirected to this file
: ${OCAMLBREW_LOGFILE=`mktemp -t ocamlbrew.XXXXXXXXXX`}
}
#
# Handle command line arguments
#
function parse_opts() {
while getopts "hb:c:aofs:tn:" OPTION; do
case $OPTION in
h)
help_then_exit ;;
b)
OCAMLBREW_BASE="$OPTARG"
;;
c)
OCAML_CONFIG_FLAGS="$(tr [=] [\ ] <<< "$OPTARG")"
;;
a)
INSTALL_ALL="true"
;;
o)
INSTALL_OCAML_ONLY="true"
;;
f)
INSTALL_OCAML_FINDLIB_ONLY="true"
;;
s)
OCAMLBREW_INSTALL_SVN="true"
OCAMLBREW_SVN_PATH="$OPTARG"
;;
t)
OCAMLBREW_INSTALL_SVN="true"
;;
n)
OCAMLBREW_NAME="$OPTARG"
;;
?)
help_then_exit ;;
esac
done
}
#
# Display greeting, optional prompts, and summary message
#
function greet() {
say Welcome to ocamlbrew!
say
if [ "$OCAMLBREW_INSTALL_SVN" = "true" ]; then
say Working with "$OCAML_SVN_ROOT""$OCAMLBREW_SVN_PATH"
else
say Working with "$OCAML_URL"
fi
say Software will be built and installed under "$OCAML_BASE"
say Output will be written to "$OCAMLBREW_LOGFILE"
say You can \"tail -f "$OCAMLBREW_LOGFILE"\" in another terminal to track
say the build process.
say
SHOW_CONTINUE_PROMPT="true"
FINDLIB_INSTALL="false"
ODB_INSTALL="false"
OASIS_INSTALL="false"
UTOP_INSTALL="false"
BATTERIES_INSTALL="false"
OCAMLSCRIPT_INSTALL="false"
if [ "$INSTALL_ALL" = "true" ]; then
SHOW_CONTINUE_PROMPT="false"
FINDLIB_INSTALL="true"
ODB_INSTALL="true"
OASIS_INSTALL="true"
UTOP_INSTALL="true"
BATTERIES_INSTALL="true"
OCAMLSCRIPT_INSTALL="true"
elif [ "$INSTALL_OCAML_ONLY" = "true" ]; then
# Nothing to do, the defaults get us here
SHOW_CONTINUE_PROMPT="false"
OCAML_ONLY="true"
elif [ "$INSTALL_OCAML_FINDLIB_ONLY" = "true" ]; then
SHOW_CONTINUE_PROMPT="false"
FINDLIB_INSTALL="true"
ODB_INSTALL="true"
else
# Ask the user what components they would like to install
prompt "Would you like to install findlib? (y/n) "
reply_lower="$(tr [A-Z] [a-z] <<< "$REPLY")"
if [ "$reply_lower" != "y" ]; then
FINDLIB_INSTALL="false"
ODB_INSTALL="false"
OASIS_INSTALL="false"
UTOP_INSTALL="false"
BATTERIES_INSTALL="false"
OCAMLSCRIPT_INSTALL="false"
else
FINDLIB_INSTALL="true"
ODB_INSTALL="true"
prompt "Would you like to install oasis? (y/n) "
reply_lower="$(tr [A-Z] [a-z] <<< "$REPLY")"
if [ "$reply_lower" = "y" ]; then
OASIS_INSTALL="true"
else
OASIS_INSTALL="false"
fi
prompt "Would you like to install utop? (y/n) "
reply_lower="$(tr [A-Z] [a-z] <<< "$REPLY")"
if [ "$reply_lower" = "y" ]; then
UTOP_INSTALL="true"
else
UTOP_INSTALL="false"
fi
prompt "Would you like to install Batteries? (y/n) "
reply_lower="$(tr [A-Z] [a-z] <<< "$REPLY")"
if [ "$reply_lower" = "y" ]; then
BATTERIES_INSTALL="true"
else
BATTERIES_INSTALL="false"
fi
prompt "Would you like to install ocamlscript? (y/n) "
reply_lower="$(tr [A-Z] [a-z] <<< "$REPLY")"
if [ "$reply_lower" = "y" ]; then
OCAMLSCRIPT_INSTALL="true"
else
OCAMLSCRIPT_INSTALL="false"
fi
fi
fi
# Print a summary of what we are going to do, then continue
say This script is about to:
say Install OCaml
if "$FINDLIB_INSTALL" = "true"; then say and install findlib; fi
if "$ODB_INSTALL" = "true"; then say and install odb; fi
if "$OASIS_INSTALL" = "true"; then say and install oasis; fi
if "$UTOP_INSTALL" = "true"; then say and install utop; fi
if "$BATTERIES_INSTALL" = "true"; then say and install Batteries; fi
if "$OCAMLSCRIPT_INSTALL" = "true"; then say and install ocamlscript; fi
say
if [ "$SHOW_CONTINUE_PROMPT" = "true" ]; then
prompt "Continue (y/n)? "
reply_lower="$(tr [A-Z] [a-z] <<< "$REPLY")"
if [ "$reply_lower" != "y" ]; then
say Exiting...
rm -f "$OCAMLBREW_LOGFILE"
exit 1
fi
fi
}
#
# Create the build directory
#
function setup_build_dir() {
# Create and move to the build directory
mkdir -p "$BUILD_DIR"
pushd "$BUILD_DIR"
}
#
# Handle OCaml brewing
#
function brew_ocaml() {
case $1 in
retrieve)
say Retrieving OCaml
if [ "$OCAMLBREW_INSTALL_SVN" = "true" ]; then
mkdir build
svn checkout "$OCAML_SVN_ROOT""$OCAMLBREW_SVN_PATH" build
cd build
else
curl -O "$OCAML_URL"
tar xzf ocaml-$OCAML_VERSION.tar.gz
cd ocaml-$OCAML_VERSION
fi
;;
build)
say Building OCaml
./configure -prefix "$OCAML_BASE" $OCAML_CONFIG_FLAGS
make world.opt
;;
install)
say Installing OCaml
make install
# Install the compiler libraries as well. They are needed for utop and some
# other projects.
mkdir -p "$OCAML_BASE"/lib/ocaml/compiler-libs/typing
mkdir -p "$OCAML_BASE"/lib/ocaml/compiler-libs/parsing
mkdir -p "$OCAML_BASE"/lib/ocaml/compiler-libs/utils
cp typing/*.cmi "$OCAML_BASE"/lib/ocaml/compiler-libs/typing/
cp parsing/*.cmi "$OCAML_BASE"/lib/ocaml/compiler-libs/parsing/
cp utils/*.cmi "$OCAML_BASE"/lib/ocaml/compiler-libs/utils/
cd ..
;;
esac
}
#
# Handle findlib brewing
#
function brew_findlib() {
case $1 in
retrieve)
say Retrieving findlib
curl -O "$FINDLIB_URL"
;;
build)
say Extracting and building findlib
tar xzf findlib-$FINDLIB_VERSION.tar.gz
cd findlib-$FINDLIB_VERSION
./configure
make all opt
;;
install)
say Installing and configuring findlib
make install
# Extra configuration for OCaml libraries with C stubs, as recommended by the
# findlib documentation.
mkdir `ocamlfind printconf destdir`/stublibs
echo `ocamlfind printconf destdir`/stublibs >> `ocamlfind printconf ldconf`
;;
esac
}
#
# Handle odb brewing
#
function brew_odb() {
case $1 in
retrieve)
say Retrieving the latest version of odb.ml
cd "$OCAML_BASE"/bin
curl -O https://raw.github.com/thelema/odb/master/odb.ml
chmod +x odb.ml
;;
configure)
cd "$OCAML_BASE"/etc
curl -O https://raw.github.com/thelema/odb/master/odb.bashrc
set +u
export ODB_BUILD_DIR="$ODB_BUILD_DIR"
export ODB_INSTALL_DIR="$ODB_INSTALL_DIR"
source odb.bashrc
set -u
mkdir -p "$ODB_BUILD_DIR"
mkdir -p "$ODB_INSTALL_DIR"
# Create a sourceable environment
{
echo export ODB_BUILD_DIR="$ODB_BUILD_DIR"
echo export ODB_INSTALL_DIR="$ODB_INSTALL_DIR"
echo source "$OCAML_BASE"/etc/odb.bashrc
} >> "$OCAML_BASE"/etc/ocamlbrew.bashrc
;;
esac
}
#
# Install packages with odb, potentially with some extra setup
#
function install_with_odb() {
say Installing "$1" with odb.ml
case $1 in
oasis)
odb.ml oUnit fileutils
odb.ml oasis
;;
utop)
# React is an optional dependency of Lwt
odb.ml react
# Make sure Lwt is built with React support
odb.ml --configure-flags --enable-react lwt
odb.ml utop
;;
*)
odb.ml "$1"
;;
esac
}
#
# Print a friendly closing message
#
function closing_message() {
say
say "You may want to add the following line to your ~/.bashrc so that OCaml is
readily available to use:
source $OCAML_BASE/etc/ocamlbrew.bashrc
Enjoy!"
}
# Print out a message to let the user know they should check the output log
# when an error occurs
trap "handle_error" ERR
################################
# This is where the fun begins #
################################
# Root for Subversion checkouts
OCAML_SVN_ROOT="http://caml.inria.fr/svn/ocaml/"
# Preparation
parse_opts "$@"
init_variables
init_redirect
greet
setup_build_dir
# OCaml
brew_ocaml "retrieve"
brew_ocaml "build"
brew_ocaml "install"
# Setup the path so that OCaml is visible
PATH="$OCAML_BASE"/bin:$PATH
# Make sure we have an etc directory to put configuration files in
mkdir -p "$OCAML_BASE"/etc
# Create a sourceable environment
echo export PATH="$OCAML_BASE"/bin:\$PATH > "$OCAML_BASE"/etc/ocamlbrew.bashrc
# findlib
if [ "$FINDLIB_INSTALL" = "true" ]; then
brew_findlib "retrieve"
brew_findlib "build"
brew_findlib "install"
fi
# odb
if [ "$ODB_INSTALL" = "true" ]; then
brew_odb "retrieve"
brew_odb "configure"
fi
# oasis
if [ "$OASIS_INSTALL" = "true" ]; then
install_with_odb "oasis"
fi
# utop
if [ "$UTOP_INSTALL" = "true" ]; then
install_with_odb "utop"
fi
# Batteries
if [ "$BATTERIES_INSTALL" = "true" ]; then
install_with_odb "batteries"
fi
# ocamlscript
if [ "$OCAMLSCRIPT_INSTALL" = "true" ]; then
install_with_odb "ocamlscript"
fi
# All done!
say Done!
popd
closing_message
Jump to Line
Something went wrong with that request. Please try again.