John Lenz committed 0683b8a

Add cross-building haskell post

Comments (0)

Files changed (2)


+* mkdir gitit-env; cd gitit-env
+* virthualenv
+* source .virthaulenv/bin/activate
+* cd /opt
+* sudo mkdir cabaldata
+* sudo chown `whoami` cabaldata
+* cd ~/gitit-env
+* cabal install --datadir /opt/cabaldata gitit


+title: Cross-Building Haskell Programs using LXC
+author: John Lenz
+tags: haskell, lxc
+date: September 19, 2012
+One of the benifits of Haskell is that compiled Haskell programs can be run on any computer, even
+computers without any Haskell packages installed.  For this to work the version of libc and various
+helper libraries like zlib must match between the build machine and the target machine, so for
+deployment between similar distribution versions one can just compile right on the develop machine
+and deploy.  Unfortunately, if you are like me and want to deploy code to a server running 32-bit
+Debian stable and your development machine is 64-bit Ubuntu 12.04, you need a way of compiling
+32-bit Haskell programs on the Ubuntu machine.
+After some work, I was able to get [virthualenv]( on
+my development machine to cross-compile using a downloaded i386 binary ghc (this used the recent
+multiarch support in Debian and Ubuntu).  This worked and produced 32-bit Haskell programs and
+simple programs worked fine, unfortunately the version of zlib did not match so running more
+complicated programs on Debian would exit with an error.  (The changes to get virthualenv + i386 ghc
+working were mostly to tell ghc to pass "-m32" to gcc.)  Because of the library version issue, I
+decided to investigate instead using containers to run a copy of Debian on my Ubuntu development
+machine. The default container technology in Ubuntu 12.04 is [LXC](, so
+that is what I used.
+# An LXC container with the latest GHC
+I suggest you first read [this documentation]( on
+LXC in Ubuntu.  A word of warning, LXC had several significant changes in Ubuntu 12.04 so if you do
+a google search for LXC and Ubuntu you get a lot of outdated information.  I was tripped up by this
+initially, instead I suggest you stick to the Ubuntu document linked above, it is way easier than a
+lot of tutorials I found in a google search.
+To install LXC, just apt-get install lxc.  I didn't need to do any configuration beyond that.  Next,
+we need to edit the debian template to specify the arch.  The ubuntu templates support specifying
+the arch on the command line, but unfortunately the debian templates in 12.04 don't.  (This might
+change in future versions, so if you are reading this much after September 2012 you should check out
+the options.)  In any case, edit /usr/lib/lxc/templates/lxc-debian and go to around line 191.  After
+the code checking architecture, I just added a line 'arch="i386"' to force i386 arch.
+Next, create the container.
+# sudo lxc-create -t debian -n deb386
+Next, login with root/root, change the root password, create a user, install sudo, and add the user to sudo.
+# passwd
+# adduser myuser
+# apt-get install sudo vim-tiny
+# usermod -G sudo myuser
+From now on, I switch to logging in to the container using ssh as the user I just created. I use
+ssh-copy-id so I don't need a password to log in.  Once logged in as a user, install the packages
+needed by GHC and download the [binary package]( for
+GHC.  (Readers from the future: you might consider a later version of GHC, probably the same one
+used by the latest haskell platform.)
+# sudo apt-get install wget bzip2 libgmp3c2 gcc make libgmp3-dev zlib1g-dev
+# wget <url for ghc>
+Extract ghc, configure and install.  Note I install ghc in a path in opt so in the future I can
+upgrade to a new version of GHC easily.
+# cd ghc-7.4.2
+# ./configure --prefix=/opt/ghc.7.4.2
+# sudo make install
+# vi ~/.bashrc, add /opt/ghc.7.4.2/bin to the path
+Next, download the latest [cabal-install]( source
+package (the link near the bottom for cabal-install-ver.tar.gz).  I copy and paste the link to wget
+inside the terminal.  Extract cabal, and run to install cabal locally for your user.
+Note, an alternative is to install the [Haskell Platform]( from
+source, but this requires several more debian packages like opengl installed, and since we are just
+going to be using virthualenv anyway, the haskell platform isn't required.
+# cd cabal-install-0.14.0
+# sh
+# vi ~/.bashrc, add ~/.cabal/bin to path
+Next, update the cabal repo and install virthaulenv.  Note, virthaulenv was recently renamed as
+hsenv but hsenv has not released yet.  Readers from the future should use hsenv instead once it is
+# cabal update
+# cabal install virthualenv
+Now that cabal and virthaulenv are installed, you have a full-featured build machine for Haskell.
+Right now I build manually by cloning my repo inside the container and running the appropriate
+virthaulenv and cabal build commands, but I am considering writing a simple build script which pulls
+and compiles.
+# An example
+The main use for my container is for [gitit]( and
+[yesod]( to deploy servers to my debian stable server.  But these are
+slightly more complicated so I will leave talking about them to a future post.  But as a short
+example, I show how pandoc can be compiled.  These are generic virthualenv commands, see the
+virthualenv README for more information.
+# mkdir pandoc && cd pandoc
+# virthaulenv
+# source .virthualenv/bin/activate
+# cabal install pandoc
+Now the binary at ~/.cabal/bin/pandoc can be copied to debian stable and run.
+The main issue with packages compiled this way is cabal's data directory, which programs access using
+Whichever directory is used to compile for example gitit must be present on the debian server.  In a
+future post I will explain in more detail how to make gitit deployable.  Note this issue will even
+partially hurt pandoc compiled as above, since pandoc also uses getDataFileName for some templates.