Skip to content
Haskell rules for Bazel.
Python Haskell Shell Nix Smarty C
Branch: master
Clone or download
mergify Merge pull request #1102 from tweag/cabal_library_haddock
haskell_cabal_library: Add haddocks
Latest commit 3659373 Dec 5, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
.bazelci Remove requires_hackage tag Nov 4, 2019
.circleci CI: collapse consecutive `nix-shell --run` calls Sep 11, 2019
debug/linking_utils Change the workspace name Jul 22, 2019
docs Completes the prototype implementation of Bazel persistent worker mod… Aug 28, 2019
examples Mirror zlib's http_archive Nov 19, 2019
nixpkgs Update to Bazel 1.1 Nov 14, 2019
protobuf Systematically use BUILD.bazel instead of BUILD. Apr 13, 2019
tests Remove references to Hazel Nov 26, 2019
tools Remove references to Hazel Nov 26, 2019
tutorial Move rules_haskell_toolchains Nov 14, 2019
.gitignore Introduce .bazelrc.local file for local customizations. Use it to sim… Jan 22, 2019
.mergify.yml mergify: merge, but rebase PR onto master instead of merging Sep 10, 2019
AUTHORS Add AUTHORS and CONTRIBUTORS files like the official repos have. Nov 6, 2017
BUILD.bazel Remove references to Hazel Nov 26, 2019 Move rules_haskell_toolchains Nov 14, 2019 Fix issue tracker link. Dec 14, 2017
CONTRIBUTORS Add contributor. Mar 5, 2018
WORKSPACE Remove references to Hazel Nov 26, 2019
constants.bzl Switch tests to using stack_install for Hackage dependencies May 22, 2019
netlify.toml Use Netlify to deploy and host API documentation. Aug 11, 2018 Add haskell_repl docs Jun 7, 2019
shell.nix Update to Bazel 1.1 Nov 14, 2019
start rules_sh requires at least Bazel 0.29 Nov 14, 2019


Haskell rules for Bazel

CircleCI Build Status

Bazel automates building and testing software. It scales to very large multi-language projects. This project extends Bazel with build rules for Haskell. Get started building your own project using these rules wih the setup script below.

Rule summary

The full reference documentation for rules is at


You'll need Bazel >= 0.27 installed.

If you are on NixOS, skip to the Nixpkgs section.

The easy way

In a fresh directory, run:

$ curl | sh

This will generate initial WORKSPACE and BUILD files for you. See the examples and the API reference below to adapt these for you project. Then,

$ bazel build //...    # Build all targets
$ bazel test //...     # Run all tests

You can learn more about Bazel's command line syntax here. Common commands are build, test, run and coverage.


This rule set supports using Nixpkgs to provision your GHC toolchain and to fetch hackage packages from there. To create your project, pass --use-nix, like so:

$ sh <(curl --use-nix

This generates the same files as above, but uses nixpkgs to provision GHC.

If you are on NixOS, this is the only way to set up your project, because the GHC toolchain provisioned through binary distributions cannot be executed on NixOS.

If you are on macOS, you will have to set the environment variable BAZEL_USE_CPP_ONLY_TOOLCHAIN = 1, so that Bazel picks the correct C compiler.

Tutorial and Examples

We provide a tutorial for writing your first rules. The corresponding source code is in ./tutorial.

A collection of example rules is in ./examples.


See for the reference documentation on provided rules. Using ./, you can also view this documentation locally.


No such file or directory

If you see error messages complaining about missing as (ld or indeed some other executable):

cc: error trying to exec 'as': execvp: No such file or directory
`cc' failed in phase `Assembler'. (Exit code: 1)

It means that your gcc cannot find as by itself. This happens only on certain operating systems which have gcc compiled without --with-as and --with-ld flags. We need to make as visible manually in that case:

# Create a symlink to system executable 'as'
    name = "toolchain_as",
    outs = ["as"],
    cmd = "ln -s /usr/bin/as $@",

# Make it visible to rules_haskell rules:
    name = "ghc",
    tools = ["@ghc//:bin"],
    version = "8.4.1",
    extra_binaries = [":toolchain_as"], # <----

__STDC_VERSION__ does not advertise C99 or later

If you see an error message like this:

/root/.cache/bazel/_bazel_root/b8b1b1d6144a88c698a010767d2217af/external/ghc/lib/ghc-8.4.1/include/Stg.h:29:3: error:
     error: #error __STDC_VERSION__ does not advertise C99 or later
     # error __STDC_VERSION__ does not advertise C99 or later
29 | # error __STDC_VERSION__ does not advertise C99 or later
   |   ^

It means that your gcc selects incorrect flavor of C by default. We need C99 or later, as the error message says, so try this:

    name = "ghc",
    tools = ["@ghc//:bin"],
    version = "8.4.1",
    compiler_flags = ["-optc-std=c99"], # <----

bazel fails because some executable cannot be found

Make sure you run your build in a pure nix shell (nix-shell --pure shell.nix). If it still doesn’t build, it is likely a bug.

A Haskell dependency fails with strange error messages

If you get cabal error messages the likes of:

CallStack (from HasCallStack):
  dieNoWrap, called at libraries/Cabal/Cabal/Distribution/Utils/LogProgress.hs:61:9 in Cabal-
    The following packages are broken because other packages they depend on are missing. These broken packages must be rebuilt before they can be used.
installed package lens-labels- is broken due to missing package profunctors-5.2.2-HzcVdviprlKb7Ap1woZu4, tagged-0.8.5-HviTdonkllN1ZD6he1Zn8I

you’ve most likely hit GHC’s infamous non-deterministic library ID bug.

Warning about home modules during non-sandboxed builds

Say you have a folder that mixes source files for two different libraries or for a library and an executable. If you build with sandboxing turned off, it is possible that GHC will use the source files for one library during the build of the other. The danger in this situation is that because GHC used inputs that Bazel didn't know about, incremental rebuilds might not be correct. This is why you get a warning of the following form if this happens:

<no location info>: warning: [-Wmissing-home-modules]
    Modules are not listed in command line but needed for compilation: Foo

Turning sandboxing on (this is Bazel's default on Linux and macOS) protects against this problem. If sandboxing is not an option, simply put the source files for each target in a separate directory (you can still use a single BUILD file to define all targets).

For rules_haskell developers

Saving common command-line flags to a file

If you find yourself constantly passing the same flags on the command-line for certain commands (such as --host_platform or --compiler), you can augment the .bazelrc file in this repository with a .bazelrc.local file. This file is ignored by Git.

Reference a local checkout of rules_haskell

When you develop on rules_haskell, you usually do it in the context of a different project that has rules_haskell as a WORKSPACE dependency, like so:

    name = "rules_haskell",
    strip_prefix = "rules_haskell-" + version,
    sha256 = …,
    urls = …,

To reference a local checkout instead, use the --override_repository command line option:

bazel build/test/run/sync \
  --override_repository rules_haskell=/path/to/checkout

If you don’t want to type that every time, temporarily add it to .bazelrc.

Test Suite

To run the test suite for these rules, you'll need Nix installed. First, from the project’s folder start a pure nix shell:

$ nix-shell --pure shell.nix

This will make sure that bazel has the exact same environment on every development system (python, ghc, go, …).

To build and run tests locally, execute:

$ bazel test //...

Skylark code in this project is formatted according to the output of buildifier. You can check that the formatting is correct using:

$ bazel run //:buildifier

If tests fail then run the following to fix the formatting:

$ git rebase --exec "bazel run //:buildifier-fix" <first commit>

where <first commit> is the first commit in your pull request. This fixes formatting for each of your commits separately, to keep the history clean.

How to update the nixpkgs pin

You have to find a new git commit where all our shell.nix dependencies are available from the official NixOS Hydra binary cache.

At least for x86-linux this is guaranteed for the unstable channels. You can find the nixpkgs git commit of current unstable here:

That might be too old for your use-case (because all tests have to pass for that channel to be updated), so as a fallback there is:

You copy that hash to url in ./nixpkgs/default.nix. Don’t forget to change the sha256 or it will use the old version. Please update the date comment to the date of the nixpkgs commit you are pinning to.


Pull Requests are checked by CircleCI.

If a check fails and you cannot reproduce it locally (e.g. it failed on Darwin and you only run Linux), you can ssh into CircleCI to aid debugging.

“unable to start any build”

error: unable to start any build; either increase '--max-jobs' or enable remote builds

We set --builders "" and --max-jobs 0 on CI to be sure all dependencies are coming from binary caches. You might need to add an exception (TODO: where to add exception) or switch to a different nixpkgs pin.

You can’t perform that action at this time.