This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
rules_haskell provides Bazel build rules for Haskell projects. It extends Bazel with capabilities to build, test, and manage Haskell code at scale, supporting multiple GHC versions and both binary distributions and Nixpkgs-based toolchains.
Build, test, and lint commands:
# Build all targets
bazel build //...
# Run all tests
bazel test //...
# Build and run tests (separate workspaces)
bazel test //... && cd rules_haskell_tests && bazel test //...
# Format check (buildifier)
bazel run //buildifier && cd rules_haskell_tests && bazel run //buildifier
# Fix formatting
bazel run //buildifier:buildifier-fix && cd rules_haskell_tests && bazel run //buildifier:buildifier-fix
# Build documentation
bazel build //docs:api_html
bazel build //docs:guide_html
# Run coverage
bazel coverage //...The repository uses a layered .bazelrc configuration:
.bazelrc- imports other configs.bazelrc.common- shared settings, platform configs.bazelrc.bzlmod- bzlmod-specific settings.bazelrc.local- user-specific settings (gitignored).bazelrc.auth- authentication for remote cache (gitignored)
Platform-specific configurations:
--config=linux-nixpkgs- Linux with Nixpkgs toolchain--config=macos-nixpkgs- macOS with Nixpkgs toolchain--config=linux-bindist- Linux with GHC binary distribution--config=macos-bindist- macOS with GHC binary distribution--config=windows-bindist- Windows with GHC binary distribution--config=ci- CI-specific settings with remote cache
Add your preferred config to .bazelrc.local:
build --config=linux-nixpkgs
For Nixpkgs-based development (recommended on NixOS, optional elsewhere):
# Enter nix shell (provides Bazel, GHC, and all dependencies)
nix-shell --pure shell.nix
# Specify GHC version (default: 9.4.8)
nix-shell --pure shell.nix --argstr ghcVersion 9.6.5
# Without doc tools (faster)
nix-shell --pure shell.nix --arg docTools falseThe nix shell provides: Bazel 6, GHC (version-specific), Stack, Go, Python3, JDK11, git, and various utilities.
The repository is organized into three separate Bazel workspaces:
-
rules_haskell/(root) - Core rule definitions and implementationhaskell/*.bzl- Public rule APIshaskell/private/*.bzl- Internal implementation detailshaskell/asterius/- Asterius (Haskell-to-WebAssembly) supportdocs/- Documentation source
-
rules_haskell_nix/- Nixpkgs integration and examples- Tests for Nixpkgs-specific functionality
-
rules_haskell_tests/- Comprehensive test suitetests/- Test cases covering various scenarios- Tests must be run separately:
cd rules_haskell_tests && bazel test //...
Tag-based test filtering is critical for platform compatibility:
-requires_nix- Exclude Nixpkgs-only tests when using bindists-dont_test_on_darwin- Exclude macOS-incompatible tests-dont_test_on_windows- Exclude Windows-incompatible tests-dont_test_with_bindist- Exclude tests incompatible with GHC bindists-requires_threaded_rts- Exclude tests needing threaded runtimecoverage-compatible- Only tests that work with coverage
Tests are automatically filtered based on the selected config (linux-bindist, macos-nixpkgs, etc.).
GHC versions are managed through:
haskell/private/ghc_ci.bzl- Defines default GHC versionhaskell/ghc_bindist.bzl- Binary distribution supportstackage_snapshot.yamland version-specific variants (stackage_snapshot_9.4.8.yaml, etc.)
Supported GHC versions: 9.4.8 (default), 9.6.5, 9.8.2, 9.10.3
Set GHC version via environment variable:
export GHC_VERSION=9.6.5
bazel build //...Haskell rules follow a three-layer architecture:
-
Public API (
haskell/defs.bzl)- User-facing macros and rules
- Attribute definitions in
_haskell_common_attrs - Exports:
haskell_library,haskell_binary,haskell_test,haskell_doc,haskell_repl
-
Implementation (
haskell/private/haskell_impl.bzl)- Core logic for compilation, linking, and packaging
- Functions:
haskell_library_impl,haskell_binary_impl,haskell_test_impl
-
Actions (
haskell/private/actions/*.bzl)- Low-level build actions
compile.bzl- GHC compilationlink.bzl- Linking executablespackage.bzl- Creating package databasesinfo.bzl- Extracting package information
Providers pass information between rules:
HaskellLibraryInfo- Library metadata, exposed modules, dependenciesHaskellBinaryInfo- Binary outputsHaskellModuleInfo- Experimental module-level informationHaskellCoverageInfo- Code coverage data
Toolchains (haskell/toolchain.bzl) define platform-specific GHC configurations:
- GHC version and tools (ghc, ghc-pkg, haddock, runghc)
- Compiler flags
- Locale settings
- Platform constraints
Register toolchains via:
haskell_register_ghc_bindists()- Binary distributions- Nixpkgs-based registration through
rules_nixpkgs
stack_snapshot rule (haskell/cabal.bzl) integrates Stackage snapshots:
- Converts Stack's
stackage_snapshot.yamlto Bazel targets - Supports custom setup dependencies
- Vendored packages (e.g., custom
ghc-pathsreplacement) - Per-GHC-version snapshot files
Example from WORKSPACE:
stack_snapshot(
name = "stackage",
packages = ["base", "bytestring", "lens-family-core", ...],
local_snapshot = "//:stackage_snapshot_9.4.8.yaml",
vendored_packages = {
"ghc-paths": "@rules_haskell//tools/ghc-paths",
},
)Aspects (haskell_cc_libraries_aspect, haskell_doc_aspect, haskell_repl_aspect) traverse dependency graphs to:
- Collect C/C++ library dependencies
- Generate documentation with transitive deps
- Set up REPL environments
- Branch from master - All development happens on feature branches
- Test locally - Run
bazel test //...before pushing - Format code - Run buildifier to format
.bzlfiles - Update tests - Add tests in
rules_haskell_tests/tests/ - Test both workspaces - Ensure both root and
rules_haskell_testspass
# Single test target
bazel test //tests:haskell_test_name
# Specific test pattern
bazel test //tests/...:haskell_*
# With specific GHC version
GHC_VERSION=9.6.5 bazel test //tests:some_test
# Force rebuild
bazel test //tests:some_test --nocache_test_results# Show verbose build output
bazel build //target --verbose_failures
# Show GHC command lines
bazel build //target -s
# Debug sandbox issues
bazel build //target --sandbox_debug
# Profile build
bazel build //target --profile=profile.jsonRemote cache is read-only for developers, read-write for CI. To enable:
-
Create
.bazelrc.auth:build --remote_header=x-buildbuddy-api-key=YOUR_API_KEY -
Add to
.bazelrc.local:build --config=remote-cache
GHC settings file not found with packages using GHC API (doctest, ghcide, proto-lens-protoc):
- Use
@rules_haskell//tools/ghc-pathsinstead of theghc-pathspackage - This prevents baked-in paths to Bazel sandbox directories
Non-deterministic library ID bug:
- Known GHC issue causing broken package databases
- See: https://nixos.org/nixpkgs/manual/#how-to-recover-from-ghcs-infamous-non-deterministic-library-id-bug
Warning about home modules during non-sandboxed builds:
- Enable sandboxing (default on Linux/macOS)
- Or separate source files into different directories per target
Windows: protoc.exe missing DLL:
- Use
--proto_compiler @rules_haskell//tests:protocflag - GHC >= 9.4 uses clang requiring libc++ DLL from
mingw\bin
Reference documentation is auto-generated using Stardoc:
- Source: Rule docstrings in
.bzlfiles - Output:
docs/api_htmlanddocs/guide_htmltargets - Public API reference: https://api.haskell.build
- Tutorial and guide: https://rules-haskell.readthedocs.io/
Local docs preview:
./serve-docs.shThe repository supports both WORKSPACE and MODULE.bazel (bzlmod):
- Run tests with bzlmod:
bazel test //... --enable_bzlmod=true - Some GHC versions have limited bzlmod support (9.8.2, 9.6.5)
- Windows uses separate remote cache for bzlmod due to absolute path issues
GitHub Actions workflow (.github/workflows/workflow.yaml) tests:
- Matrix dimensions: OS (Ubuntu, macOS, Windows), module (rules_haskell, rules_haskell_tests), GHC version, bzlmod mode
- Nixpkgs tests: Ubuntu 24.04, macOS 14 with nix-shell
- Bindist tests: All three OS with binary GHC distributions
- Examples tests: Separate workspace with all examples
CI-specific behavior:
cache-versionenv var to invalidate GitHub Actions cache- BuildBuddy remote cache with read-write access
- Memory management:
bazel shutdownbetween test phases on some platforms
- No Bitnami images - User configuration forbids Bitnami container images
- Maintainer: Aleksei Sviridkin (f@lex.la)
- Primary branch:
master(notmain) - Start script:
curl https://haskell.build/start | shgenerates initial project setup - Platform constraints defined in
haskell/platforms/list.bzl