• Stars
    star
    265
  • Rank 154,577 (Top 4 %)
  • Language Starlark
  • License
    Apache License 2.0
  • Created about 7 years ago
  • Updated about 1 month ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Haskell rules for Bazel.

rules_haskell

Haskell rules for Bazel

Continuous integration

Bazel CI: 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 with the setup script below.

Rule summary

The full reference documentation for rules is at https://haskell.build.

Setup

You'll need Bazel >= 5.0 installed.

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

System dependencies

Refer to the "Before you begin" section in the documentation.

The easy way

In a fresh directory, run:

$ curl https://haskell.build/start | 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.

Nixpkgs

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 https://haskell.build/start) --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.

Rules

See https://api.haskell.build for the reference documentation on provided rules. Using ./serve-docs.sh, you can also view this documentation locally.

Troubleshooting

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'
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-2.0.1.0: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.

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).

hGetContents: invalid argument (invalid byte sequence)

If you are using the GHC bindists and see an error message like this:

haddock: internal error: /tmp/tmputn68mya/doc/html/path-io/haddock-response300-1.txt: hGetContents: invalid argument (invalid byte sequence)

It means that the default locale (C.UTF-8) does not work on your system. You can use a locale that your system has. For example, if your system has the locale en_US.UTF-8, you can specify that locale:

rules_haskell_toolchains(
    locale = "en_US.UTF-8", # <----
    version = "8.4.1",
)

To find available locales, run locale -a in a terminal. You should see output like the following:

$ locale -a
C
en_US
en_US.iso88591
en_US.utf8
POSIX

MacOS: Error: DEVELOPER_DIR not set.

Make sure to set the following environment variable:

export BAZEL_USE_CPP_ONLY_TOOLCHAIN=1

This ensures that Bazel picks the correct C compiler.

Windows: Incorrect cc_toolchain used

If you're using Windows, bazel might use a different cc_toolchain than is required to build. This might happen if the environment has a cc_toolchain from Visual Studio. This might show up with an error like:

Traceback (most recent call last):
  File "\\?\C:\Users\appveyor\AppData\Local\Temp\1\Bazel.runfiles_w5rfpqk5\runfiles\rules_haskell\haskell\cabal_wrapper.py", line 105, in <module>
    strip = find_exe("external/local_config_cc/wrapper/bin/msvc_nop.bat")
  File "\\?\C:\Users\appveyor\AppData\Local\Temp\1\Bazel.runfiles_w5rfpqk5\runfiles\rules_haskell\haskell\cabal_wrapper.py", line 56, in find_exe
    if not os.path.isfile(path) and "True" == "True":
  File "C:\Python37\lib\genericpath.py", line 30, in isfile
    st = os.stat(path)
TypeError: stat: path should be string, bytes, os.PathLike or integer, not NoneType

You can override the cc_toolchain chosen with the following flag:

--crosstool_top=@rules_haskell_ghc_windows_amd64//:cc_toolchain

This chooses the cc_toolchain bundled with GHC.

GHC settings file does not exist

If you use the GHC bindist toolchain, i.e. haskell_register_ghc_bindists, then you may encounter the following type of error with packages that use the GHC API, e.g. doctest, ghcide, or proto-lens-protoc:

.../lib/settings: openFile: does not exist (No such file or directory)

This could be caused by a dependency on the ghc-paths package which bakes the path to the GHC installation at build time into the binary. In the GHC bindist use case this path points into Bazel's sandbox working directory which can change between build actions and between build-time and runtime.

You can use @rules_haskell//tools/ghc-paths as a drop-in replacement to work around this issue. See tools/ghc-paths/README.md for further details.

For rules_haskell developers

Configuring your platform

rules_haskell can be built and tested on Linux, MacOS, and Windows. Depending on the platform GHC can be provisioned using nixpkgs or by downloading a binary distribution. In case of nixpkgs other toolchains (C compiler, Python, shell tools) will also be provided by nixpkgs, in case of bindist they will be taken from the environment ($PATH). The following --config options select the corresponding combination of operating system and GHC distribution:

Linux MacOS Windows
nixpkgs linux-nixpkgs macos-nixpkgs
binary distribution linux-bindist macos-bindist windows-bindist

Hint: You can use Bazel's --announce_rc flag to see what options are being used for a command in a specific configuration. E.g.

$ bazel build //tests:run-tests --config linux-nixpkgs --nobuild --announce_rc

Hint: To avoid repetition you can add your configuration to .bazelrc.local.

echo "build --config=linux-nixpkgs" >>.bazelrc.local

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:

http_archive(
    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 //... && cd rules_haskell_tests && bazel test //...

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

$ bazel run //buildifier && cd rules_haskell_tests && bazel run //buildifier

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

$ git rebase --exec "bazel run //buildifier:buildifier-fix && cd rules_haskell_tests && bazel run //buildifier: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:

https://nixos.org/channels/nixos-unstable/git-revision

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:

https://nixos.org/channels/nixos-unstable-small/git-revision

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.

GitHub Actions Cache

The GitHub actions CI pipeline uses actions/cache to store the Bazel repository cache. The cache-version must be updated manually in the env section in the workflow to invalidate the cache if any cacheable external dependencies are changed.

β€œ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.

More Repositories

1

nickel

Better configuration for less
Rust
2,275
star
2

asterius

DEPRECATED in favor of ghc wasm backend, see https://www.tweag.io/blog/2022-11-22-wasm-backend-merged-in-ghc
Haskell
1,978
star
3

ormolu

A formatter for Haskell source code
Haskell
958
star
4

jupyenv

Declarative and reproducible Jupyter environments - powered by Nix
Nix
660
star
5

HaskellR

The full power of R in Haskell.
Haskell
583
star
6

topiary

Rust
486
star
7

sparkle

Haskell on Apache Spark.
Haskell
447
star
8

monad-bayes

A library for probabilistic programming in Haskell.
Jupyter Notebook
407
star
9

awesome-learning-haskell

A collection of resources which were useful to Tweagers for learning Haskell and its various aspects
399
star
10

funflow

Functional workflows
Haskell
361
star
11

linear-base

Standard library for linear types in Haskell.
Haskell
335
star
12

rules_nixpkgs

Rules for importing Nixpkgs packages into Bazel.
Starlark
285
star
13

inline-java

Haskell/Java interop via inline Java code in Haskell modules.
Haskell
230
star
14

capability

Extensional capabilities and deriving combinators
Haskell
214
star
15

FawltyDeps

Python dependency checker
Python
192
star
16

clodl

Turn dynamically linked ELF binaries and libraries into self-contained closures.
Starlark
170
star
17

inline-js

Call JavaScript from Haskell, and vice versa!
Haskell
128
star
18

opam-nix

Turn opam-based OCaml projects into Nix derivations
Nix
111
star
19

nixtract

A CLI tool to extract the graph of derivations from a Nix flake.
Rust
81
star
20

nix-hour

Questions for the weekly Nix Hour
Nix
77
star
21

linear-types

Drafts, notes and resources for adding linear typing to GHC.
TeX
75
star
22

python-monorepo-example

Example of a python monorepo using pip, the poetry backend, and Pants
Python
75
star
23

terraform-provider-nixos

Terraform provider for NixOS and NixOps
Go
70
star
24

tf-ncl

Terraform Configurations with Nickel
Rust
65
star
25

distributed-closure

Serializable closures for distributed programming.
Haskell
63
star
26

terraform-provider-secret

Terraform secret provider
Shell
62
star
27

guides

Designing, programming and deploying, in style.
58
star
28

servant-template

A modern template for a Servant
Haskell
51
star
29

nix_bazel_codelab

Nix+Bazel Codelab
Starlark
49
star
30

kernmantle

Braiding extensible effects together in a pipeline/workflow of tasks
Haskell
47
star
31

pirouette

Language-generic workbench for building static analysis
Haskell
47
star
32

python-nix

Python-Nix FFI library using the new C API
Python
45
star
33

skyscope

A tool for visualising and exploring Bazel Skyframe graphs.
Haskell
45
star
34

rules_sh

Shell rules for Bazel
Starlark
42
star
35

nix-ux

Nix UX improvements
Nix
36
star
36

genealogos

Genealogos, a Nix sbom generator
Rust
36
star
37

blog-resources

Extra resources for Tweag's blog posts.
Jupyter Notebook
35
star
38

cooked-validators

Haskell
35
star
39

lagoon

Data centralization tool
Haskell
35
star
40

webauthn

A library for parsing and validating webauthn/fido2 credentials
Haskell
34
star
41

haskell-training

Material for Haskell training
Haskell
31
star
42

hyperion

A lab for future Criterion features.
Haskell
29
star
43

ghc-wasm-miso-examples

Haskell
24
star
44

rust-alpine-mimalloc

Shell
23
star
45

network-transport-zeromq

ZeroMQ transport for distributed-process (aka Cloud Haskell)
Haskell
22
star
46

nix-remote-rust

Rust
21
star
47

haskell-stack-nix-example

Examples of valid and invalid Stack + Nix integration
Nix
20
star
48

timestats

A library to profile time in a Haskell program
Haskell
17
star
49

ssh-participation

An ssh server that creates new users on-the-fly, great for letting users participate in a demo
Nix
16
star
50

nix_gazelle_extension

Gazelle language extension for nix files
Go
15
star
51

epcb

Nix RFC draft on evaluation purity and caching builtins
15
star
52

nixpkgs-graph-explorer

Explore the nixpkgs dependency graph
Python
14
star
53

nixpkgs-graph

Generate a graph from nixpkgs
Python
14
star
54

haskell-binaryen

Haskell bindings to binaryen.
WebAssembly
14
star
55

gazelle_cabal

A gazelle extension to produce Haskell rules from cabal files
Haskell
13
star
56

smtlib-backends

A Haskell library providing low-level functions for SMTLIB-based interaction with SMT solvers.
Haskell
13
star
57

chainsail

Replica Exchange sampling as-a-service
Python
11
star
58

rust-wasm-threads

Examples of Web Workers using rust and WASM
Rust
11
star
59

random-quality

Framework for testing quality of random number generators
Nix
10
star
60

rules_haskell_examples

Examples of using Bazel's Haskell rules.
9
star
61

funflow2

Compose and run computational workflows
Haskell
9
star
62

rust-wasm-nix

Nix
9
star
63

store-graph

simple haskell code that builds a graph from the nix store
Shell
9
star
64

purescript-unlift

MonadBase, MonadUnliftEffect, MonadUnliftAff, and MonadUnlift
Nix
9
star
65

stackage-head

Stackage builds based on GHC HEAD
Haskell
9
star
66

nix-installer-generator

Nix installer generator
Nix
8
star
67

functionless

CLI tool for packaging Haskell executables for AWS Lambda
Java
8
star
68

formik-apollo

A little bit of for using Formik with Apollo
TypeScript
8
star
69

ch-nixops-example

Example deployment of Cloud Haskell app using NixOps.
Haskell
8
star
70

nix-store-gcs-proxy

A HTTP nix store that proxies requests to Google Storage
Nix
8
star
71

ghc-wasm32-wasi

DEPRECATED, new home https://gitlab.haskell.org/ghc/ghc-wasm-meta
Nix
7
star
72

python-nix-flake-template

Bootstrap a reproducible yet flexible Python development environment using Nix
Nix
7
star
73

ghc-wasm-bindists

Stable links for various GHC WASM bindists
Haskell
7
star
74

terraform-gcp-cdn-bucket

A Google Storage Bucket + CDN configuration
HCL
7
star
75

servant-oauth2

A modern servant wrapper around the wai-middleware-auth OAuth2 provider implementations.
Haskell
7
star
76

chainsail-resources

Examples, documentation and other additional resources related to Chainsail
Python
6
star
77

hello-plutarch

Template project for smart-contracts in Plutarch
Nix
6
star
78

summer-of-nix-modules

Incremental module system buildup for Summer of Nix
Nix
6
star
79

tendermint-bazel

Building Go with Bazel
Go
6
star
80

linear-constraints

TeX
6
star
81

ghc-asterius

DEPRECATED, new home https://gitlab.haskell.org/ghc/ghc
Haskell
6
star
82

remote-execution-nix

nix to bazel-re proxy
Rust
6
star
83

work-daigest

Create a digest of your work week using a LLM
Python
6
star
84

tf-ncl-examples

Examples of Terraform configuration with Nickel
NCL
5
star
85

nickel-lang.org

The website of the Nickel language
JavaScript
5
star
86

nix-marp

Run Marp tools via Nix
Nix
5
star
87

nickel-kubernetes

Typecheck, template and modularize your Kubernetes definitions with Nickel
Rust
5
star
88

pyfunflow

Declarative composable typed workflows in Python
Python
5
star
89

duckling

a Haskell library that parses text into structured data
Haskell
4
star
90

graft

Haskell
4
star
91

nix-unit-testing

A showcase of different unit testing frameworks for Nix.
Python
4
star
92

rules_purescript

Python
4
star
93

toronto_reproducibility_workshop

Slides and toy project for the talk at the Toronto Workshop on Reproducibility
Python
4
star
94

nixos-specialisation-dual-boot

Nix
4
star
95

organist-example

Python
4
star
96

gh-migration-scripts

Repository to house scripts to help with GH migration projects
JavaScript
4
star
97

gazelle_haskell_modules

A gazelle extension to generate haskell_module rules
Haskell
4
star
98

inputs

Utilities for building forms with React
TypeScript
3
star
99

pthread

Bindings for the pthread library
Haskell
3
star
100

cooked-smart-contracts

Smart contracts for the Cardano blockchain written with Cooked-validators
Haskell
3
star