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.
The full reference documentation for rules is at https://haskell.build.
||Declare external repositories needed for rules_haskell|
||Setup a binary distribution of GHC|
||Build a library from Haskell source.|
||Build an executable from Haskell source.|
||Run a test suite.|
||Create API documentation.|
||Declare a compiler toolchain.|
||Import a prebuilt shared library.|
||Expose all transitive shared object libraries for haskell dependency.|
You'll need Bazel >= 0.14.0 installed.
The easy way
In a fresh directory, run:
$ curl https://haskell.build/start | sh
$ bazel build //... # Build all targets $ bazel test //... # Run all tests
Doing it manually
Add the following to your
WORKSPACE file, and select a
(or even an arbitrary commit hash) accordingly.
http_archive( name = "io_tweag_rules_haskell", strip_prefix = "rules_haskell-$VERSION", urls = ["https://github.com/tweag/rules_haskell/archive/v$VERSION.tar.gz"], ) load("@io_tweag_rules_haskell//haskell:repositories.bzl", "haskell_repositories") haskell_repositories() register_toolchains("//:ghc")
Then, add this to your root
load("@io_tweag_rules_haskell//haskell:haskell.bzl", "haskell_toolchain", ) haskell_toolchain( name = "ghc", version = "8.2.2", tools = "@my_ghc//:bin", )
haskell_toolchain rule instantiation brings a GHC compiler in
scope. It assumes that an external repository
@my_ghc was defined, pointing to an installation of GHC. The
recommended option is to provision GHC using Nix, but you can also
point to an existing local installation somewhere in your filesystem.
Using Nix, this is done by adding the following to your
nixpkgs_package( name = "my_ghc", attribute_path = "haskell.compiler.ghc822" )
Alternatively, you can point to an existing global installation:
new_local_repository( name = "my_ghc", path = "/usr/local", # Change path accordingly. build_file_content = """ package(default_visibility = ["//visibility:public"]) filegroup( name = "bin", srcs = glob(["bin/*"]), ) """ )
See rules_haskell_examples for examples of using these rules.
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 (
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 test --config lint //...
If tests fail then run the following to fix the formatting:
$ bazel run --direct_run //skylark:buildifier **/*.bzl **/BUILD
We may be supporting interop with other languages in one way or another. Please see languages listed below about how.
C/C++ libraries can be specified as dependencies. Importing prebuilt
libraries and exporting Haskell libraries as C/C++ dependencies
currently requires the
rules. These are temporary workarounds to Bazel limitations.
You can supply
java_* rule targets in
haskell_library. This will make jars produced by
those dependencies available during Haskell source compilation phase
(i.e. not during linking &c. but it's subject to change) and set the
CLASSPATH for that phase as well.
Building Cabal packages published on Hackage
This repository contains no special support for building Cabal packages. This is provided by downstream rule sets. We recommend Hazel for generating rules to build packages published on Hackage, or part of Stackage snapshots, using Bazel.
No such file or directory
If you see error messages complaining about missing
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-ld flags. We need to make
as visible manually in that case:
# Create a symlink to system executable 'as' genrule( name = "toolchain_as", outs = ["as"], cmd = "ln -s /usr/bin/as $@", ) # Make it visible to rules_haskell rules: haskell_toolchain( 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:
haskell_toolchain( 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-126.96.36.199:Distribution.Utils.LogProgress Error: 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-0.2.0.1 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.