CRUX : Home

Home :: Documentation :: Download :: Development :: Community :: Wiki :: Ports :: Bugs :: Links :: About

Back to wiki start page

Categories: Ports

Haskell on CRUX

Author

Lucas Hazel

Description

This page will discuss how to install the GHC on a CRUX? box. Writing ports for 3rd party libraries will also be covered.

My collection of haskell ports is available at http://git.die.net.au/cgit/crux/ports/haskell

Instructions

To build GHC you need a working compiler, so first we need to install from a prepackaged binary, here is the Pkgfile:

# Description: Haskell compiler
# URL: http://www.haskell.org/haskellwiki/Glasgow_Haskell_Compiler
# Maintainer: Lucas Hazel, lucas at die dot net dot au
# Depends on: libgmp
name=ghc
version=6.8.3
release=1
source=(http://www.haskell.org/ghc/dist/$version/$name-$version-x86_64-unknown-linux.tar.bz2)
build() {
        cd $name-$version
        ./configure --prefix=/usr
        make
        mkdir -p $PKG/usr/{bin,lib}
        make DESTDIR=$PKG install
        rm -rf $PKG/usr/share/doc
}

Don't worry, we just install this so we can build it again from source. So, let's do that by replacing the source line to:

source=(http://www.haskell.org/ghc/dist/$version/$name-$version-src.tar.bz2
http://www.haskell.org/ghc/dist/$version/$name-$version-src-extralibs.tar.bz2)

Fire off pkgmk then go have a coffee or 4. Building ghc from source will take a long time.

Haskell ports

Haskell libraries need to be registered with the compiler when ever they are installed, upgraded or removed. Handling installation and upgrading are simple within the CRUX domain, I will describe the process using the X11 module.

Here is an example Pkgfile:

# Description: A Haskell binding to the X11 graphics library.
# URL: http://darcs.haskell.org/X11
# Maintainer: Lucas Hazel <lucas@die.net.au>
# Depends on: ghc

name=ghc-x11
version=1.4.2
release=1
source=(http://hackage.haskell.org/packages/archive/X11/$version/X11-$version.tar.gz)

build() {
        cd X11-$version
        runghc Setup.hs configure -g --prefix=/usr \
                --libsubdir='$compiler/lib/$pkgid'

        runghc Setup.hs build

        runghc Setup.hs register --gen-script
        runghc Setup.hs unregister --gen-script

        install -D -m744 register.sh $PKG/usr/share/ghc/$name/register.sh
        install -m744 unregister.sh $PKG/usr/share/ghc/$name/unregister.sh

        runghc Setup.hs copy --destdir=$PKG

        rm -rf $PKG/usr/share/doc
}

As you can see, the build process is quite simple, but at the same time may appear unfamiliar. Many haskell modules use a Setup.hs or Setup.lhs file, think setup.py for python modules. Just like setup.py it comes equipped with a variety of sub-commands. Most of the ones used here should make sense to "advanced linux users", but I will discuss the more interesting ones a bit further.

The first point of interest is the configure sub-command, in particular the --libsubdir flag, which defines where to install the library. You'll notice the variables used are quoted, we do this as they are internal to setup script, alternatively you could escape them using the backslash operator.

Secondly, I'll your attention to the generation of the register and unregister scripts, these will be used by the installation scripts of the port, which I will discuss now.

Installing and upgrading can be handled within the CRUX domain through the use of pre-install and post-install

The pre-install script can be used to handle package upgrades, by unregistering the library from the compiler if it is already installed which determined by the existence of the unregister script generated in the Pkgfile. This allows the files to be safely removed by pkgadd -u

#!/bin/sh
UNREGISTER=/usr/share/ghc/ghc-x11/unregister.sh
[ -x $UNREGISTER ] && $UNREGISTER

We can then use the post-install script to (re)register the library with the compiler:

#!/bin/sh
/usr/share/ghc/ghc-x11/register.sh

Finally we need to handle the even of when we uninstall a library for whatever reason, to do this we need to make use of a pre-remove script to allow the unregistration of the library before the files are removed. I'm sure you can guess what that file will look like, but here it is anyway.

#!/bin/sh
UNREGISTER=/usr/share/ghc/ghc-x11/unregister.sh
[ -x $UNREGISTER ] && $UNREGISTER

It is important to note that pre-remove is not a standard installation script with CRUX and is not handled by prt-get, therefore, you will need to remove any haskell modules manually.

# cd $PATH_TO_HASKELL_PORT/$NAME
# sh pre-remove
...
# pkgrm $NAME

Upgrading and Installing with cabal-install

You have a few options when it comes to managing haskell packages:

Cabal is a package management system for haskell. Many components of the GHC standard library are updated before the next release of GHC. These updates often include security update, bug fixes and new features, so it can be a good idea to keep your standard library up to date in between GHC releases.

Cabal comes with both --local and --global options, the local option allows you to install and register haskell libraries in your home directory. This provides a convenient method of testing a haskell library before you decide to create a CRUX port.

Updating the Package List

$ cabal update

...too easy.

Installing Packages

So you've tested some haskell libraries and think other CRUX users might find them useful. Our first step is to resolve the dependency chain.

$ cabal install [PACKAGE] --dry-run --reinstall -v

This will give a list of packages and versions required to install the package, it will be your job as port maintainer to find what libraries will need new ports, what ones are part of the standard library and which are maintained by someone else, now for an example, this time we'll use xmonad.

$ cabal install xmonad --dry-run --reinstall -v
/usr/bin/ghc --numeric-version
looking for package tool: ghc-pkg near compiler in /usr/bin
found package tool in /usr/bin/ghc-pkg
/usr/bin/ghc-pkg --version
/usr/bin/ghc --supported-languages
Reading installed packages...
/usr/bin/ghc-pkg dump --global
/usr/bin/ghc-pkg dump --user
Reading available packages...
Resolving dependencies...
selecting xmonad-0.8.1 (hackage) and discarding X11-1.2, 1.2.2, 1.2.3,
1.2.3.1, 1.3.0, 1.4.0, 1.4.1, 1.4.2, xmonad-0.1, 0.2, 0.3, 0.4, 0.4.1, 0.5,
0.6, 0.7 and 0.8
selecting process-1.0.1.0 (installed) and discarding directory-1.0.0.0,
filepath-1.0, 1.1.0.0, 1.1.0.1, old-locale-1.0.0.0, 1.0.0.1, old-time-1.0.0.0,
process-1.0.0.0, 1.0.1.1, unix-2.0, 2.2.0.0, 2.3.0.0 and 2.3.1.0
selecting directory-1.0.0.2 (installed)
selecting filepath-1.1.0.1 (installed)
selecting ghc-prim-0.1.0.0 (installed)
selecting integer-0.1.0.0 (installed)
selecting old-locale-1.0.0.1 (installed)
selecting old-time-1.0.0.1 (installed)
selecting rts-1.0 (installed)
selecting unix-2.3.1.0 (installed)
selecting containers-0.2.0.0 (installed or hackage) and discarding
containers-0.1.0.0 and 0.1.0.1
selecting array-0.2.0.0 (installed or hackage) and discarding array-0.1.0.0
selecting syb-0.1.0.0 (installed or hackage)
selecting X11-1.4.5 (installed or hackage) and discarding X11-1.4.3 and 1.4.4
selecting mtl-1.1.0.2 (installed or hackage) and discarding mtl-1.0, 1.1.0.0
and 1.1.0.1
selecting base-3.0.3.0 (installed) and 4.0.0.0 (installed) and discarding
syb-0.1.0.0
In order, the following would be installed:
xmonad-0.8.1 (reinstall)

From this we can gather the latest version of xmonad is 0.8.1. Some investigation (and experience) also tells us that there is one library required that is not found in the standard library, X11. This is all the information we require to build a port for xmonad (which I have already described how to do). Of course some ports are going to be have more complicated dependency chains and if we get more haskell users on CRUX the need to investigate the existence of ports by other maintainers will grow.

Upgrading packages

If you want to update your standard library of find if any ports you maintain require updating, simply issue the following command.

$ cabal upgrade --global --dry-run
Resolving dependencies...
In order, the following would be installed (use -v for more details):
HTTP-4000.0.4
ghc-paths-0.1.0.5
haddock-2.4.1
regex-base-0.93.1
regex-posix-0.94.1
regex-compat-0.92
time-1.1.2.3

Of these, I know HTTP is not in the standard library, as it is a port I am maintaining. All the others are part of the standard library. I can now upgrade these with the following command.

cabal upgrade --global ghc-paths haddock regex-base regex-posix regex-compat time

I can now investigate updating the HTTP library in my ports.