Building a windows-executable Haskell program with stack and AppVeyor

Posted on January 5, 2016 by Noon van der Silk

In this post we’ll see how to setup a CI build that generates Windows executables for stack-based Haskell projects.

So imagine you love Haskell and you have written a Haskell program, you’ve hosted it on GitHub and you’ve dilligently set up a CI build on Travis that uses stack to build/test/etc.

Now, because stack is great and life is good, people can build your project from the source largely without issue. But suppose now that you’d like to provide Windows binaries for download. It so happens that we live in an age where this is completely automatable! Let’s see how.

The essence of my approach is to use the CI system AppVeyor (essentially like a Travis for Windows), and the following appveyor.yml file (full file below, I’ll go through details next):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
build: off

before_build:
- curl -ostack.zip -L --insecure http://www.stackage.org/stack/windows-i386
- 7z x stack.zip stack.exe
- sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules
# Appveyor doesn't clone recursively.
- git submodule update --init --recursive

skip_tags: true

build_script:
# Suppress output from stack setup, as there is a lot and it's not necessary.
- stack setup --no-terminal > nul
- stack build --only-snapshot --no-terminal
- stack --local-bin-path . install haskmas
# Set a magical environment variable
- cmd: for /f %%i in ('stack exec -- haskmas -v') do set HASKMAS_VERSION=%%i

artifacts:
- path: haskmas.exe

# Auto-deploy
deploy:
  - provider: GitHub
    tag: 'haskmas-$(HASKMAS_VERSION)'
    release: 'Release haskmas-$(HASKMAS_VERSION)'
    auth_token:
      secure: FZXhwa1ucQwyFtswv/XNUJkclAxoz4YGGu69dSOEEkwG7Rlh/Gho66SJtOUJ57kN
    artifact: haskmas.exe
    on:
      branch: master

Details:

You can see from the releases on the haskmas project istelf that I fumbled around with this setup a bit. Mostly I observed that the manual release process on AppVeyor doesn’t quite operate the way I’d’ve hoped; but in any case AppVeyor is a pretty convenient service; it’s very nice to see something for Windows in this space.

I based my configuration off of the one for the stack tool itself. Note that there is some mention of caching in there that might speed up the build (my build takes ~17 minutes on AppVeyor compared to ~2 minutes on travis).

All-in-all, technical details about automatically pushing releases aside, AppVeyor+stack is a really nice way to build Windows binaries from exactly the same source as your linux binaries. The only outstanding item to do is to combine artifacts from travis and AppVeyor into a single entity that can be released dually; but on the other hand tooling could always be written to perform this semi-manually, from your working computer, when you are ready to release.

The repo is here: haskmas. As a side benefit, I made the haskmas program take command line arguments to control how it operates! So now you don’t need to compile it to get a tree of arbitrary depth!