{"id":14235982,"url":"https://github.com/tweag/rules_haskell","last_synced_at":"2025-05-15T01:08:38.699Z","repository":{"id":38486155,"uuid":"109669839","full_name":"tweag/rules_haskell","owner":"tweag","description":"Haskell rules for Bazel.","archived":false,"fork":false,"pushed_at":"2025-05-12T09:32:17.000Z","size":9494,"stargazers_count":269,"open_issues_count":212,"forks_count":81,"subscribers_count":29,"default_branch":"master","last_synced_at":"2025-05-14T07:14:56.616Z","etag":null,"topics":["bazel","bazel-rules","build-system","haskell"],"latest_commit_sha":null,"homepage":"https://haskell.build","language":"Starlark","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tweag.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-11-06T08:50:01.000Z","updated_at":"2025-05-12T09:02:08.000Z","dependencies_parsed_at":"2024-12-16T14:29:45.076Z","dependency_job_id":"6252cb71-afb8-41d0-bdbd-8a203fbaa6d7","html_url":"https://github.com/tweag/rules_haskell","commit_stats":{"total_commits":2928,"total_committers":100,"mean_commits":29.28,"dds":0.7247267759562841,"last_synced_commit":"487535b8b10d496d8aa11aa4e9f1c91da476cf61"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tweag%2Frules_haskell","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tweag%2Frules_haskell/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tweag%2Frules_haskell/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tweag%2Frules_haskell/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tweag","download_url":"https://codeload.github.com/tweag/rules_haskell/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254123743,"owners_count":22018631,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bazel","bazel-rules","build-system","haskell"],"created_at":"2024-08-20T21:02:36.596Z","updated_at":"2025-05-15T01:08:33.649Z","avatar_url":"https://github.com/tweag.png","language":"Starlark","funding_links":[],"categories":["Starlark"],"sub_categories":[],"readme":"\u003cp align=\"left\"\u003e\u003cimg src=\"logo/horizontal.png\" alt=\"rules_haskell\" height=\"100px\"\u003e\u003c/p\u003e\n\n# Haskell rules for [Bazel][bazel]\n\n[![Continuous Integration](https://github.com/tweag/rules_haskell/actions/workflows/workflow.yaml/badge.svg?event=schedule)](https://github.com/tweag/rules_haskell/actions/workflows/workflow.yaml)\n\nBazel CI: [![Build status](https://badge.buildkite.com/1de3270f1df070a99978adb6efa180d0c32eac58e0fd1938d1.svg?branch=master)](https://buildkite.com/bazel/rules-haskell-haskell)\n\nBazel automates building and testing software. It scales to very large\nmulti-language projects. This project extends Bazel with build rules\nfor Haskell. Get started building your own project using these rules\nwith the [setup script below](#setup).\n\n[bazel]: https://bazel.build/\n[bazel-getting-started]: https://bazel.build/start\n[bazel-cli]: https://docs.bazel.build/versions/master/command-line-reference.html\n[external-repositories]: https://docs.bazel.build/versions/master/external.html\n[nix]: https://nixos.org/nix\n\n## Rule summary\n\nThe full reference documentation for rules is at https://haskell.build.\n\n## Setup\n\nYou'll need [Bazel \u003e= 6.0][bazel-getting-started] installed.\n\nIf you are on NixOS, skip to the [Nixpkgs](#Nixpkgs) section.\n\n### System dependencies\n\nRefer to the \"Before you begin\" section in [the documentation](docs/haskell.rst).\n\n### The easy way\n\nIn a fresh directory, run:\n\n```console\n$ curl https://haskell.build/start | sh\n```\n\nAlternatively, if you want to start a project with bzlmod, run:\n\n```console\n$ sh \u003c(curl https://haskell.build/start) --with-bzlmod=true\n```\n\nThis will generate initial `WORKSPACE` and `BUILD` files for you. See the\n[examples](./examples) and the [API reference](#Rules) below to adapt these for\nyour project. Then,\n\n```console\n$ bazel build //...    # Build all targets\n$ bazel test //...     # Run all tests\n```\n\nYou can learn more about Bazel's command line\nsyntax [here][bazel-cli]. Common [commands][bazel-cli-commands] are\n`build`, `test`, `run` and `coverage`.\n\n\n### Nixpkgs\n\nThis rule set supports using [Nixpkgs][nixpkgs] to provision your GHC\ntoolchain and to fetch hackage packages from there. To create your\nproject, pass `--use-nix`, like so:\n\n```console\n$ sh \u003c(curl https://haskell.build/start) --use-nix\n```\n\nThis generates the same files as above, but uses `nixpkgs` to\nprovision GHC.\n\nIf you are on NixOS, this is the only way to set up your project,\nbecause the GHC toolchain provisioned through binary distributions\ncannot be executed on NixOS.\n\n[bazel-cli-commands]: https://docs.bazel.build/versions/master/command-line-reference.html#commands\n[nixpkgs]: https://nixos.org/nixpkgs/\n\n## Tutorial and Examples\n\nWe provide a [tutorial for writing your first rules][tutorial].\nThe corresponding source code is in [./tutorial](./tutorial).\n\nA collection of example rules is in [./examples](./examples).\n\n[tutorial]: https://rules-haskell.readthedocs.io/en/latest/\n\n## Rules\n\nSee https://api.haskell.build for the reference documentation on provided\nrules. Using [./serve-docs.sh](./serve-docs.sh), you can also view\nthis documentation locally.\n\n## Troubleshooting\n\n### No such file or directory\n\nIf you see error messages complaining about missing `as` (`ld` or indeed\nsome other executable):\n\n```\ncc: error trying to exec 'as': execvp: No such file or directory\n`cc' failed in phase `Assembler'. (Exit code: 1)\n```\n\nIt means that your `gcc` cannot find `as` by itself. This happens only on\ncertain operating systems which have `gcc` compiled without `--with-as` and\n`--with-ld` flags. We need to make `as` visible manually in that case:\n\n```bzl\n# Create a symlink to system executable 'as'\ngenrule(\n    name = \"toolchain_as\",\n    outs = [\"as\"],\n    cmd = \"ln -s /usr/bin/as $@\",\n)\n\n# Make it visible to rules_haskell rules:\nhaskell_toolchain(\n    name = \"ghc\",\n    tools = [\"@ghc//:bin\"],\n    version = \"8.4.1\",\n    extra_binaries = [\":toolchain_as\"], # \u003c----\n)\n```\n\n### `__STDC_VERSION__` does not advertise C99 or later\n\nIf you see an error message like this:\n\n```\n/root/.cache/bazel/_bazel_root/b8b1b1d6144a88c698a010767d2217af/external/ghc/lib/ghc-8.4.1/include/Stg.h:29:3: error:\n     error: #error __STDC_VERSION__ does not advertise C99 or later\n     # error __STDC_VERSION__ does not advertise C99 or later\n       ^\n   |\n29 | # error __STDC_VERSION__ does not advertise C99 or later\n   |   ^\n```\n\nIt means that your `gcc` selects incorrect flavor of C by default. We need\nC99 or later, as the error message says, so try this:\n\n```bzl\nhaskell_toolchain(\n    name = \"ghc\",\n    tools = [\"@ghc//:bin\"],\n    version = \"8.4.1\",\n    compiler_flags = [\"-optc-std=c99\"], # \u003c----\n)\n```\n\n### `bazel` fails because some executable cannot be found\n\nMake sure you run your build in a pure nix shell\n(`nix-shell --pure shell.nix`). If it still doesn’t build,\nit is likely a bug.\n\n### A Haskell dependency fails with strange error messages\n\nIf you get cabal error messages the likes of:\n\n```\nCallStack (from HasCallStack):\n  dieNoWrap, called at libraries/Cabal/Cabal/Distribution/Utils/LogProgress.hs:61:9 in Cabal-2.0.1.0:Distribution.Utils.LogProgress\nError:\n    The following packages are broken because other packages they depend on are missing. These broken packages must be rebuilt before they can be used.\ninstalled package lens-labels-0.2.0.1 is broken due to missing package profunctors-5.2.2-HzcVdviprlKb7Ap1woZu4, tagged-0.8.5-HviTdonkllN1ZD6he1Zn8I\n```\n\nyou’ve most likely hit GHC’s\n[infamous non-deterministic library ID bug](https://nixos.org/nixpkgs/manual/#how-to-recover-from-ghcs-infamous-non-deterministic-library-id-bug).\n\n### Warning about home modules during non-sandboxed builds\n\nSay you have a folder that mixes source files for two different\nlibraries or for a library and an executable. If you build with\nsandboxing turned off, it is possible that GHC will use the source\nfiles for one library during the build of the other. The danger in\nthis situation is that because GHC used inputs that Bazel didn't know\nabout, incremental rebuilds might not be correct. This is why you get\na warning of the following form if this happens:\n\n```\n\u003cno location info\u003e: warning: [-Wmissing-home-modules]\n    Modules are not listed in command line but needed for compilation: Foo\n```\n\nTurning sandboxing on (this is Bazel's default on Linux and macOS)\nprotects against this problem. If sandboxing is not an option, simply\nput the source files for each target in a separate directory (you can\nstill use a single `BUILD` file to define all targets).\n\n### hGetContents: invalid argument (invalid byte sequence)\n\nIf you are using the GHC bindists and see an error message like this:\n\n```\nhaddock: internal error: /tmp/tmputn68mya/doc/html/path-io/haddock-response300-1.txt: hGetContents: invalid argument (invalid byte sequence)\n```\n\nIt means that the default locale (`C.UTF-8`) does not work on your system.\nYou can use a locale that your system has. For example, if your system has the\nlocale `en_US.UTF-8`, you can specify that locale:\n\n```bzl\nrules_haskell_toolchains(\n    locale = \"en_US.UTF-8\", # \u003c----\n    version = \"8.4.1\",\n)\n```\n\nTo find available locales, run `locale -a` in a terminal. You should see output like the following:\n\n```console\n$ locale -a\nC\nen_US\nen_US.iso88591\nen_US.utf8\nPOSIX\n```\n\n### Windows: Incorrect `cc_toolchain` used\n\nIf you're using Windows, bazel might use a different `cc_toolchain`\nthan is required to build. This might happen if the environment has a\n`cc_toolchain` from Visual Studio. This might show up with an error like:\n```\nTraceback (most recent call last):\n  File \"\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\Bazel.runfiles_w5rfpqk5\\runfiles\\rules_haskell\\haskell\\cabal_wrapper.py\", line 105, in \u003cmodule\u003e\n    strip = find_exe(\"external/local_config_cc/wrapper/bin/msvc_nop.bat\")\n  File \"\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\Bazel.runfiles_w5rfpqk5\\runfiles\\rules_haskell\\haskell\\cabal_wrapper.py\", line 56, in find_exe\n    if not os.path.isfile(path) and \"True\" == \"True\":\n  File \"C:\\Python37\\lib\\genericpath.py\", line 30, in isfile\n    st = os.stat(path)\nTypeError: stat: path should be string, bytes, os.PathLike or integer, not NoneType\n```\n\nYou can override the `cc_toolchain` chosen with the following flag:\n```\n--crosstool_top=@rules_haskell_ghc_windows_amd64//:cc_toolchain\n```\nThis chooses the `cc_toolchain` bundled with GHC.\n\n### GHC settings file does not exist\n\nIf 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`:\n\n```\n.../lib/settings: openFile: does not exist (No such file or directory)\n```\n\nThis 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.\n\nYou 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.\n\n### Windows: protoc.exe exits with an error\n\nIf you see\n```\nprotoc.exe: error while loading shared libraries: api-ms-win-crt-filesystem-l1-1-0.dll: cannot open shared object file: No such file or directory\n```\nor\n```\nProcess finished with exit code -1073741515 (0xC0000135)\n```\nthis usually means the executable cannot find a DLL it depends on (not necessarily the DLL that is mentioned in the error message).\n\nNewer Windows GHC distributions (\u003e= 9.4), come with clang as the C/C++ compiler, and executables produced using that toolchain depend on the libc++ DLL, which is found in the `mingw\\bin` directory of the bindist. You can pass `--proto_compiler @rules_haskell//tests:protoc` as a build flag to bazel as a workaround (see [tests/protoc.bzl]).\n\n## For `rules_haskell` developers\n\n### Configuring your platform\n\n`rules_haskell` can be built and tested on Linux, MacOS, and Windows. Depending\non the platform GHC can be provisioned using nixpkgs or by downloading a binary\ndistribution. In case of nixpkgs other toolchains (C compiler, Python, shell\ntools) will also be provided by nixpkgs, in case of bindist they will be taken\nfrom the environment (`$PATH`). The following `--config` options select the\ncorresponding combination of operating system and GHC distribution:\n\n|                     |      Linux      |      MacOS      |      Windows      |\n| ------------------- | --------------- | --------------- | ----------------- |\n| nixpkgs             | `linux-nixpkgs` | `macos-nixpkgs` |                   |\n| binary distribution | `linux-bindist` | `macos-bindist` | `windows-bindist` |\n\nHint: You can use Bazel's `--announce_rc` flag to see what options are being\nused for a command in a specific configuration. E.g.\n```\n$ bazel build //tests:run-tests --config linux-nixpkgs --nobuild --announce_rc\n```\n\nHint: To avoid repetition you can add your configuration to `.bazelrc.local`.\n```\necho \"build --config=linux-nixpkgs\" \u003e\u003e.bazelrc.local\n```\n\n### Saving common command-line flags to a file\n\nIf you find yourself constantly passing the same flags on the\ncommand-line for certain commands (such as `--host_platform` or\n`--compiler`), you can augment the [`.bazelrc`](./.bazelrc) file in\nthis repository with a `.bazelrc.local` file. This file is ignored by\nGit.\n\n### Reference a local checkout of `rules_haskell`\n\nWhen you develop on `rules_haskell`, you usually do it in the context\nof a different project that has `rules_haskell` as a `WORKSPACE`\ndependency, like so:\n\n```\nhttp_archive(\n    name = \"rules_haskell\",\n    strip_prefix = \"rules_haskell-\" + version,\n    sha256 = …,\n    urls = …,\n)\n```\n\nTo reference a local checkout instead, use the\n[`--override_repository`][override_repository] command line option:\n\n```\nbazel build/test/run/sync \\\n  --override_repository rules_haskell=/path/to/checkout\n```\n\nIf you don’t want to type that every time, [temporarily add it to\n`.bazelrc`][bazelrc].\n\n[override_repository]: https://docs.bazel.build/versions/master/command-line-reference.html#flag--override_repository\n[local_repository]: https://docs.bazel.build/versions/master/be/workspace.html#local_repository\n[bazelrc]: https://docs.bazel.build/versions/master/best-practices.html#bazelrc\n\n### Test Suite\n\nTo run the test suite for these rules, you'll need [Nix][nix]\ninstalled. First, from the project’s folder start a pure nix shell:\n\n```\n$ nix-shell --pure shell.nix\n```\n\nThis will make sure that bazel has the exact same environment\non every development system (`python`, `ghc`, `go`, …).\n\nTo build and run tests locally, execute:\n\n```\n$ bazel test //... \u0026\u0026 cd rules_haskell_tests \u0026\u0026 bazel test //...\n```\n\nStarlark code in this project is formatted according to the output of\n[buildifier]. You can check that the formatting is correct using:\n\n```\n$ bazel run //buildifier \u0026\u0026 cd rules_haskell_tests \u0026\u0026 bazel run //buildifier\n```\n\nIf tests fail then run the following to fix the formatting:\n\n```\n$ git rebase --exec \"bazel run //buildifier:buildifier-fix \u0026\u0026 cd rules_haskell_tests \u0026\u0026 bazel run //buildifier:buildifier-fix\" \u003cfirst commit\u003e\n```\n\nwhere `\u003cfirst commit\u003e` is the first commit in your pull request.\nThis fixes formatting for each of your commits separately, to keep\nthe history clean.\n\n[buildifier]: https://github.com/bazelbuild/buildtools/tree/master/buildifier\n\n### \u003ca name=\"nixpkgs-pin\" /\u003eHow to update the nixpkgs pin\n\nYou have to find a new git commit where all our `shell.nix`\ndependencies are available from the official NixOS Hydra binary cache.\n\nAt least for `x86-linux` this is guaranteed for the `unstable`\nchannels. You can find the `nixpkgs` git commit of current `unstable`\nhere:\n\nhttps://nixos.org/channels/nixos-unstable/git-revision\n\nThat might be too old for your use-case (because all tests have to\npass for that channel to be updated), so as a fallback there is:\n\nhttps://nixos.org/channels/nixos-unstable-small/git-revision\n\nYou copy that hash to `url` in\n[`./nixpkgs/default.nix`](./nixpkgs/default.nix). Don’t forget to\nchange the `sha256` or it will use the old version. Please update the\ndate comment to the date of the `nixpkgs` commit you are pinning to.\n\n### GitHub Actions Cache\n\nThe GitHub actions CI pipeline uses\n[`actions/cache`](https://github.com/actions/cache) to store the Bazel\nrepository cache. The `cache-version` must be updated manually in the `env`\nsection in the [workflow](./.github/workflows/workflow.yaml) to invalidate the\ncache if any cacheable external dependencies are changed.\n\n#### “unable to start any build”\n\n```\nerror: unable to start any build; either increase '--max-jobs' or enable remote builds\n```\n\nWe set `--builders \"\"` and `--max-jobs 0` on CI to be sure all\ndependencies are coming from binary caches. You might need to add an\nexception (TODO: where to add exception) or [switch to a different\nnixpkgs pin](#nixpkgs-pin).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftweag%2Frules_haskell","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftweag%2Frules_haskell","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftweag%2Frules_haskell/lists"}