Skip to content

Instantly share code, notes, and snippets.

@AlainODea
Last active January 26, 2019 17:34
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save AlainODea/06f9d063d4989e1bc00d to your computer and use it in GitHub Desktop.
Save AlainODea/06f9d063d4989e1bc00d to your computer and use it in GitHub Desktop.
WIP: SmartOS installing Haskell Cabal 1.16.1.0 (look at install_cabal.sh)
#!/bin/sh
set -o xtrace
# A script to bootstrap cabal-install.
# It works by downloading and installing the Cabal, zlib and
# HTTP packages. It then installs cabal-install itself.
# It expects to be run inside the cabal-install directory.
# install settings, you can override these by setting environment vars
#VERBOSE
#EXTRA_CONFIGURE_OPTS
# programs, you can override these by setting environment vars
GHC=${GHC:-ghc}
GHC_PKG=${GHC_PKG:-ghc-pkg}
WGET=${WGET:-wget}
CURL=${CURL:-curl}
FETCH=${FETCH:-fetch}
TAR=${TAR:-tar}
GUNZIP=${GUNZIP:-gunzip}
SCOPE_OF_INSTALLATION="--user"
DEFAULT_PREFIX="${HOME}/.cabal"
for arg in $*
do
case "${arg}" in
"--user")
SCOPE_OF_INSTALLATION=${arg}
shift;;
"--global")
SCOPE_OF_INSTALLATION=${arg}
DEFAULT_PREFIX="/usr/local"
shift;;
*)
echo "Unknown argument or option, quitting: ${arg}"
echo "usage: bootstrap.sh [OPTION]"
echo
echo "options:"
echo " --user Install for the local user (default)"
echo " --global Install systemwide (must be run as root)"
exit;;
esac
done
PREFIX=${PREFIX:-${DEFAULT_PREFIX}}
# Versions of the packages to install.
# The version regex says what existing installed versions are ok.
PARSEC_VER="3.1.3"; PARSEC_VER_REGEXP="[23]\." # == 2.* || == 3.*
DEEPSEQ_VER="1.3.0.1"; DEEPSEQ_VER_REGEXP="1\.[1-9]\." # >= 1.1 && < 2
TEXT_VER="0.11.2.3"; TEXT_VER_REGEXP="0\.([2-9]|(1[0-1]))\." # >= 0.2 && < 0.12
NETWORK_VER="2.3.1.1"; NETWORK_VER_REGEXP="2\." # == 2.*
CABAL_VER="1.16.0.3"; CABAL_VER_REGEXP="1\.1[67]\." # >= 1.16 && < 1.18
TRANS_VER="0.3.0.0"; TRANS_VER_REGEXP="0\.[23]\." # >= 0.2.* && < 0.4.*
MTL_VER="2.1.2"; MTL_VER_REGEXP="[12]\." # == 1.* || == 2.*
HTTP_VER="4000.2.4"; HTTP_VER_REGEXP="4000\.[012]\." # == 4000.0.* || 4000.1.* || 4000.2.*
ZLIB_VER="0.5.4.0"; ZLIB_VER_REGEXP="0\.[45]\." # == 0.4.* || == 0.5.*
TIME_VER="1.4.0.1" TIME_VER_REGEXP="1\.[1234]\.?" # >= 1.1 && < 1.5
RANDOM_VER="1.0.1.1" RANDOM_VER_REGEXP="1\.0\." # >= 1 && < 1.1
HACKAGE_URL="https://hackage.haskell.org/package"
die () {
echo
echo "Error during cabal-install bootstrap:"
echo $1 >&2
exit 2
}
# Check we're in the right directory:
grep "cabal-install" ./cabal-install.cabal > /dev/null 2>&1 \
|| die "The bootstrap.sh script must be run in the cabal-install directory"
${GHC} --numeric-version > /dev/null \
|| die "${GHC} not found (or could not be run). If ghc is installed make sure it is on your PATH or set the GHC and GHC_PKG vars."
${GHC_PKG} --version > /dev/null \
|| die "${GHC_PKG} not found."
GHC_VER=`${GHC} --numeric-version`
GHC_PKG_VER=`${GHC_PKG} --version | cut -d' ' -f 5`
[ ${GHC_VER} = ${GHC_PKG_VER} ] \
|| die "Version mismatch between ${GHC} and ${GHC_PKG} If you set the GHC variable then set GHC_PKG too"
# Cache the list of packages:
echo "Checking installed packages for ghc-${GHC_VER}..."
${GHC_PKG} list --global ${SCOPE_OF_INSTALLATION} > ghc-pkg.list \
|| die "running '${GHC_PKG} list' failed"
# Will we need to install this package, or is a suitable version installed?
need_pkg () {
PKG=$1
VER_MATCH=$2
if egrep " ${PKG}-${VER_MATCH}" ghc-pkg.list > /dev/null 2>&1
then
return 1;
else
return 0;
fi
#Note: we cannot use "! grep" here as Solaris 9 /bin/sh doesn't like it.
}
info_pkg () {
PKG=$1
VER=$2
VER_MATCH=$3
if need_pkg ${PKG} ${VER_MATCH}
then
echo "${PKG}-${VER} will be downloaded and installed."
else
echo "${PKG} is already installed and the version is ok."
fi
}
fetch_pkg () {
PKG=$1
VER=$2
URL=${HACKAGE_URL}/${PKG}-${VER}/${PKG}-${VER}.tar.gz
if which ${CURL} > /dev/null
then
${CURL} --fail -C - -O ${URL} || die "Failed to download ${PKG}."
elif which ${WGET} > /dev/null
then
${WGET} -c ${URL} || die "Failed to download ${PKG}."
elif which ${FETCH} > /dev/null
then
${FETCH} ${URL} || die "Failed to download ${PKG}."
else
die "Failed to find a downloader. 'curl', 'wget' or 'fetch' is required."
fi
[ -f "${PKG}-${VER}.tar.gz" ] \
|| die "Downloading ${URL} did not create ${PKG}-${VER}.tar.gz"
}
unpack_pkg () {
PKG=$1
VER=$2
rm -rf "${PKG}-${VER}.tar" "${PKG}-${VER}"/
${GUNZIP} -f "${PKG}-${VER}.tar.gz" \
|| die "Failed to gunzip ${PKG}-${VER}.tar.gz"
${TAR} -xf "${PKG}-${VER}.tar" \
|| die "Failed to untar ${PKG}-${VER}.tar.gz"
[ -d "${PKG}-${VER}" ] \
|| die "Unpacking ${PKG}-${VER}.tar.gz did not create ${PKG}-${VER}/"
}
install_pkg () {
PKG=$1
[ -x Setup ] && ./Setup clean
[ -f Setup ] && rm Setup
${GHC} --make Setup -o Setup -optl-lssp \
|| die "Compiling the Setup script failed"
[ -x Setup ] || die "The Setup script does not exist or cannot be run"
./Setup configure ${SCOPE_OF_INSTALLATION} "--prefix=${PREFIX}" \
--with-compiler=${GHC} --with-hc-pkg=${GHC_PKG} \
${EXTRA_CONFIGURE_OPTS} ${VERBOSE} \
|| die "Configuring the ${PKG} package failed"
./Setup build ${VERBOSE} \
|| die "Building the ${PKG} package failed"
./Setup install ${VERBOSE} \
|| die "Installing the ${PKG} package failed"
}
do_pkg () {
PKG=$1
VER=$2
VER_MATCH=$3
if need_pkg ${PKG} ${VER_MATCH}
then
echo
echo "Downloading ${PKG}-${VER}..."
fetch_pkg ${PKG} ${VER}
unpack_pkg ${PKG} ${VER}
cd "${PKG}-${VER}"
install_pkg ${PKG} ${VER}
cd ..
fi
}
# Actually do something!
info_pkg "Cabal" ${CABAL_VER} ${CABAL_VER_REGEXP}
info_pkg "transformers" ${TRANS_VER} ${TRANS_VER_REGEXP}
info_pkg "mtl" ${MTL_VER} ${MTL_VER_REGEXP}
info_pkg "deepseq" ${DEEPSEQ_VER} ${DEEPSEQ_VER_REGEXP}
info_pkg "text" ${TEXT_VER} ${TEXT_VER_REGEXP}
info_pkg "parsec" ${PARSEC_VER} ${PARSEC_VER_REGEXP}
info_pkg "network" ${NETWORK_VER} ${NETWORK_VER_REGEXP}
info_pkg "time" ${TIME_VER} ${TIME_VER_REGEXP}
info_pkg "HTTP" ${HTTP_VER} ${HTTP_VER_REGEXP}
info_pkg "zlib" ${ZLIB_VER} ${ZLIB_VER_REGEXP}
info_pkg "random" ${RANDOM_VER} ${RANDOM_VER_REGEXP}
do_pkg "Cabal" ${CABAL_VER} ${CABAL_VER_REGEXP}
do_pkg "transformers" ${TRANS_VER} ${TRANS_VER_REGEXP}
do_pkg "mtl" ${MTL_VER} ${MTL_VER_REGEXP}
do_pkg "deepseq" ${DEEPSEQ_VER} ${DEEPSEQ_VER_REGEXP}
do_pkg "text" ${TEXT_VER} ${TEXT_VER_REGEXP}
do_pkg "parsec" ${PARSEC_VER} ${PARSEC_VER_REGEXP}
do_pkg "network" ${NETWORK_VER} ${NETWORK_VER_REGEXP}
do_pkg "time" ${TIME_VER} ${TIME_VER_REGEXP}
do_pkg "HTTP" ${HTTP_VER} ${HTTP_VER_REGEXP}
do_pkg "zlib" ${ZLIB_VER} ${ZLIB_VER_REGEXP}
do_pkg "random" ${RANDOM_VER} ${RANDOM_VER_REGEXP}
install_pkg "cabal-install"
echo
echo "==========================================="
CABAL_BIN="$PREFIX/bin"
if [ -x "$CABAL_BIN/cabal" ]
then
echo "The 'cabal' program has been installed in $CABAL_BIN/"
echo "You should either add $CABAL_BIN to your PATH"
echo "or copy the cabal program to a directory that is on your PATH."
echo
echo "The first thing to do is to get the latest list of packages with:"
echo " cabal update"
echo "This will also create a default config file (if it does not already"
echo "exist) at $HOME/.cabal/config"
echo
echo "By default cabal will install programs to $HOME/.cabal/bin"
echo "If you do not want to add this directory to your PATH then you can"
echo "change the setting in the config file, for example you could use:"
echo "symlink-bindir: $HOME/bin"
else
echo "Sorry, something went wrong."
echo "The 'cabal' executable was not successfully installed into"
echo "$CABAL_BIN/"
fi
echo
rm ghc-pkg.list
Name: cabal-install
Version: 1.16.1.0
Synopsis: The command-line interface for Cabal and Hackage.
Description:
The \'cabal\' command-line program simplifies the process of managing
Haskell software by automating the fetching, configuration, compilation
and installation of Haskell libraries and programs.
homepage: http://www.haskell.org/cabal/
bug-reports: https://github.com/haskell/cabal/issues
License: BSD3
License-File: LICENSE
Author: Lemmih <lemmih@gmail.com>
Paolo Martini <paolo@nemail.it>
Bjorn Bringert <bjorn@bringert.net>
Isaac Potoczny-Jones <ijones@syntaxpolice.org>
Duncan Coutts <duncan@community.haskell.org>
Maintainer: cabal-devel@haskell.org
Copyright: 2005 Lemmih <lemmih@gmail.com>
2006 Paolo Martini <paolo@nemail.it>
2007 Bjorn Bringert <bjorn@bringert.net>
2007 Isaac Potoczny-Jones <ijones@syntaxpolice.org>
2007-2012 Duncan Coutts <duncan@community.haskell.org>
Category: Distribution
Build-type: Simple
Extra-Source-Files: README bash-completion/cabal bootstrap.sh
Cabal-Version: >= 1.6
source-repository head
type: git
location: https://github.com/haskell/cabal/
subdir: cabal-install
flag old-base
description: Old, monolithic base
default: False
flag bytestring-in-base
Executable cabal
Main-Is: Main.hs
ghc-options: -Wall -threaded
if impl(ghc >= 6.8)
ghc-options: -fwarn-tabs
Other-Modules:
Distribution.Client.BuildReports.Anonymous
Distribution.Client.BuildReports.Storage
Distribution.Client.BuildReports.Types
Distribution.Client.BuildReports.Upload
Distribution.Client.Check
Distribution.Client.Config
Distribution.Client.Configure
Distribution.Client.Dependency
Distribution.Client.Dependency.TopDown
Distribution.Client.Dependency.TopDown.Constraints
Distribution.Client.Dependency.TopDown.Types
Distribution.Client.Dependency.Types
Distribution.Client.Dependency.Modular
Distribution.Client.Dependency.Modular.Assignment
Distribution.Client.Dependency.Modular.Builder
Distribution.Client.Dependency.Modular.Configured
Distribution.Client.Dependency.Modular.ConfiguredConversion
Distribution.Client.Dependency.Modular.Dependency
Distribution.Client.Dependency.Modular.Explore
Distribution.Client.Dependency.Modular.Flag
Distribution.Client.Dependency.Modular.Index
Distribution.Client.Dependency.Modular.IndexConversion
Distribution.Client.Dependency.Modular.Log
Distribution.Client.Dependency.Modular.Message
Distribution.Client.Dependency.Modular.Package
Distribution.Client.Dependency.Modular.Preference
Distribution.Client.Dependency.Modular.PSQ
Distribution.Client.Dependency.Modular.Solver
Distribution.Client.Dependency.Modular.Tree
Distribution.Client.Dependency.Modular.Validate
Distribution.Client.Dependency.Modular.Version
Distribution.Client.Fetch
Distribution.Client.FetchUtils
Distribution.Client.GZipUtils
Distribution.Client.Haddock
Distribution.Client.HttpUtils
Distribution.Client.IndexUtils
Distribution.Client.Init
Distribution.Client.Init.Heuristics
Distribution.Client.Init.Licenses
Distribution.Client.Init.Types
Distribution.Client.Install
Distribution.Client.InstallPlan
Distribution.Client.InstallSymlink
Distribution.Client.JobControl
Distribution.Client.List
Distribution.Client.PackageIndex
Distribution.Client.PackageUtils
Distribution.Client.Setup
Distribution.Client.SetupWrapper
Distribution.Client.SrcDist
Distribution.Client.Tar
Distribution.Client.Targets
Distribution.Client.Types
Distribution.Client.Unpack
Distribution.Client.Update
Distribution.Client.Upload
Distribution.Client.Utils
Distribution.Client.World
Distribution.Client.Win32SelfUpgrade
Distribution.Compat.Exception
Distribution.Compat.FilePerms
Distribution.Compat.Time
Paths_cabal_install
build-depends: base >= 2 && < 5,
Cabal >= 1.16.0 && < 1.18,
filepath >= 1.0 && < 1.4,
network >= 1 && < 2.6,
HTTP >= 4000.0.2 && < 4001,
zlib >= 0.4 && < 0.6,
time >= 1.1 && < 1.5,
mtl >= 2.0 && < 3
if flag(old-base)
build-depends: base < 3
else
build-depends: base >= 3,
process >= 1 && < 1.2,
directory >= 1 && < 1.3,
pretty >= 1 && < 1.2,
random >= 1 && < 1.1,
containers >= 0.1 && < 0.6,
array >= 0.1 && < 0.5,
old-time >= 1 && < 1.2
if flag(bytestring-in-base)
build-depends: base >= 2.0 && < 2.2
else
build-depends: base < 2.0 || >= 3.0, bytestring >= 0.9
if os(windows)
build-depends: Win32 >= 2 && < 3
cpp-options: -DWIN32
else
build-depends: unix >= 1.0 && < 2.7
if os(solaris)
extra-libraries: ssp
extensions: CPP, ForeignFunctionInterface
c-sources: cbits/getnumcores.c
#!/bin/bash
# Just enough to bootstrap cabal CLI on top of PKGSRC ghc (7.6.3 as of this writing)
#
# This allows GHC 7.10.3 which then allows GHC 8.X.Y:
# https://gist.github.com/kellymclaughlin/9f96bf902d19fa83ee191de3ab190361
#
# Mechanism:
#
# 1. install ghc
# 2. boostrap cabal CLI with patched package and scripts
pkgin -y update
pkgin -y full-upgrade
pkgin -y install ghc build-essential
cabal_install_version=1.16.0.1
cabal_install_directory=cabal-install-${cabal_install_version}
cabal_install_archive=${cabal_install_directory}.tar.gz
curl -O https://www.haskell.org/cabal/release/${cabal_install_directory}/${cabal_install_archive}
tar xf ${cabal_install_archive}
cd ${cabal_install_directory}
curl -O https://gist.github.com/AlainODea/06f9d063d4989e1bc00d/raw/79fadc9aa3b7bd20ecfe7bfb2b5526f4619fd727/cabal-install.cabal
curl -O https://gist.github.com/AlainODea/06f9d063d4989e1bc00d/raw/79fadc9aa3b7bd20ecfe7bfb2b5526f4619fd727/bootstrap.sh
chmod +x bootstrap.sh
./bootstrap.sh
@AlainODea
Copy link
Author

GHC from PKGSRC on SmartOS is missing the cabal command. This comes from the cabal-install Haskell package.

Building cabal-install 1.16.1.0 on SmartOS base-multiarch@17.1.0 is a bit difficult due to dynamic library changes.

You need to modify the cabal-install.cabal file to include a conditional statement to explicitly depend on libssp (put this in below build-depends: unix...):

    if os(solaris)
      extra-libraries: ssp

The bootstrap itself won't run unmodified either because:

  1. The layout of Hackage has changed (HACKAGE_URL and URL need to change)
  2. Making Setup requires -lssp to work since we're driving ghc directly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment