### Install GraphViz and xdot on Ubuntu Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell.md Install the necessary tools to visualize Bazel dependency graphs locally on Ubuntu systems. ```bash sudo apt update && sudo apt install graphviz xdot ``` -------------------------------- ### Build and Run Tutorial Examples Source: https://github.com/tweag/rules_haskell/blob/master/tutorial/README.md Commands to build specific libraries and executables, followed by running the main application. ```bash $ bazel build //lib:booleans $ bazel build //main:demorgan $ bazel run //main:demorgan ``` -------------------------------- ### Query Vector Example Targets Source: https://github.com/tweag/rules_haskell/blob/master/examples/README.md This Bazel query command lists all targets associated with the vector example, useful for understanding the project structure. ```bash bazel query //vector/... ``` -------------------------------- ### Initialize project with quick start script Source: https://context7.com/tweag/rules_haskell/llms.txt Use the provided curl script to bootstrap a new rules_haskell project with various configuration options. ```bash # Create a new project with WORKSPACE-based setup curl https://haskell.build/start | sh # Create with bzlmod support sh <(curl https://haskell.build/start) --with-bzlmod=true # Create with Nixpkgs GHC toolchain sh <(curl https://haskell.build/start) --use-nix ``` -------------------------------- ### Build the basic_modules project with Bazel Source: https://github.com/tweag/rules_haskell/blob/master/examples/basic_modules/README.md Execute this command within the examples directory to build the Haskell package. ```bash $ bazel build //basic_modules ``` -------------------------------- ### Define Haskell project targets Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Example project structure with base, library, and binary targets. ```default haskell_toolchain_library( name = "base", ) haskell_library( name = "library-a", srcs = ["Lib/A.hs"], deps = [":base"], ) haskell_library( name = "library-b", srcs = ["Lib/B.hs"], deps = [":base"], ) haskell_binary( name = "binary", srcs = ["Main.hs"], deps = [ ":base", ":library-a", ":library-b", ], ) ``` -------------------------------- ### Configure MODULE.bazel for bzlmod Source: https://context7.com/tweag/rules_haskell/llms.txt Setup rules_haskell using bzlmod extensions for toolchains and stack snapshots. ```bzl # MODULE.bazel module(name = "my_project", version = "1.0") bazel_dep(name = "rules_haskell", version = "1.0") # Configure toolchain haskell_toolchains = use_extension( "@rules_haskell//extensions:haskell_toolchains.bzl", "haskell_toolchains", ) haskell_toolchains.bindists(version = "9.4.8") use_repo(haskell_toolchains, "all_bindist_toolchains") register_toolchains("@all_bindist_toolchains//:all") # Configure stack snapshot stack_snapshot = use_extension( "@rules_haskell//extensions:stack_snapshot.bzl", "stack_snapshot", ) stack_snapshot.package(name = "base") stack_snapshot.package(name = "text") stack_snapshot.snapshot(snapshot = "lts-21.25") use_repo(stack_snapshot, "stackage") ``` -------------------------------- ### Configure WORKSPACE for rules_haskell Source: https://context7.com/tweag/rules_haskell/llms.txt Manual setup for rules_haskell dependencies, toolchains, and Stackage snapshots in the WORKSPACE file. ```bzl # WORKSPACE load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "rules_haskell", sha256 = "...", strip_prefix = "rules_haskell-1.0", url = "https://github.com/tweag/rules_haskell/releases/download/v1.0/rules_haskell-1.0.tar.gz", ) load("@rules_haskell//haskell:repositories.bzl", "rules_haskell_dependencies") rules_haskell_dependencies() load("@rules_haskell//haskell:toolchain.bzl", "rules_haskell_toolchains") rules_haskell_toolchains(version = "9.2.8") # Import Stackage packages load("@rules_haskell//haskell:cabal.bzl", "stack_snapshot") stack_snapshot( name = "stackage", snapshot = "lts-21.25", packages = ["base", "text", "aeson"], ) ``` -------------------------------- ### Define a haskell_binary target Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Example of a standard binary target definition in a BUILD file. ```default haskell_binary( name = "hello", srcs = ["Main.hs", "Other.hs"], deps = ["//lib:some_lib"], ) ``` -------------------------------- ### Install system dependencies on Ubuntu Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell.md Required packages for building Haskell projects with Bazel on Ubuntu systems. ```default build-essential libffi-dev libgmp-dev libtinfo6 libtinfo-dev python3 openjdk-11-jdk ``` -------------------------------- ### Error: Unable to start any build Source: https://github.com/tweag/rules_haskell/blob/master/README.md This error occurs when Bazel cannot start builds, often due to CI configurations that restrict job execution. Increase '--max-jobs' or enable remote builds. Consider switching to a different nixpkgs pin if issues persist. ```bash error: unable to start any build; either increase '--max-jobs' or enable remote builds ``` -------------------------------- ### Stack Snapshot Configuration for ghcide Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Example configuration for a local stack snapshot file used to build ghcide with specific components. ```yaml resolver: nightly-2019-09-21 packages: # Taken from the extra-deps field. - haskell-lsp-0.21.0.0 - haskell-lsp-types-0.21.0.0 - lsp-test-0.10.2.0 - hie-bios-0.4.0 - fuzzy-0.1.0.0 - regex-pcre-builtin-0.95.1.1.8.43 - regex-base-0.94.0.0 - regex-tdfa-1.3.1.0 - shake-0.18.5 - parser-combinators-1.2.1 - haddock-library-1.8.0 - tasty-rerun-1.1.17 - ghc-check-0.1.0.3 # Point to the ghcide revision that you would like to use. - github: digital-asset/ghcide commit: "39605333c34039241768a1809024c739df3fb2bd" sha256: "47cca96a6e5031b3872233d5b9ca14d45f9089da3d45a068e1b587989fec4364" ``` -------------------------------- ### Add GHC installation data dependencies Source: https://github.com/tweag/rules_haskell/blob/master/tools/ghc-paths/README.md When runtime access to GHC installation files is needed, include the relevant targets in your Bazel target's `data` attribute. This ensures executables can find necessary GHC components. ```python data = [ # If you use `GHC.Paths.ghc` or `GHC.Paths.ghc_pkg` "@rules_haskell//tools/ghc-paths:bin", # If you use `GHC.Paths.docdir` "@rules_haskell//tools/ghc-paths:docdir", # If you use `GHC.Paths.libdir` "@rules_haskell//tools/ghc-paths:libdir", ], ``` -------------------------------- ### Example dependency output Source: https://github.com/tweag/rules_haskell/blob/master/debug/linking_utils/README.md Shows the structure of the dependency analysis output when missing items are found or when the binary is complete. ```python {'libfoo.so.5': {'libbar.so.1': {'libbaz.so.6': 'MISSING'}}} ``` ```python {} ``` -------------------------------- ### Build Main Haskell Targets Source: https://github.com/tweag/rules_haskell/blob/master/examples/README.md Commands to build the primary Haskell targets for the cat_hs, vector, and rts examples. ```bash bazel build //cat_hs/exec/cat_hs ``` ```bash bazel build //vector ``` ```bash bazel build //rts:add-one-hs ``` -------------------------------- ### Package Haskell Binaries into OCI Containers Source: https://context7.com/tweag/rules_haskell/llms.txt Package Haskell binaries into OCI containers using rules_oci. This example demonstrates building a tarball, creating an OCI image, and pushing it. ```bzl load("@rules_haskell//haskell:defs.bzl", "haskell_binary") load("@rules_oci//oci:defs.bzl", "oci_image", "oci_push") load("@rules_pkg//pkg:tar.bzl", "pkg_tar") haskell_binary( name = "server", srcs = ["Main.hs"], deps = ["@stackage//:base", "@stackage//:warp"], ghcopts = ["-O2", "-threaded", "-rtsopts"], ) pkg_tar( name = "server_tar", srcs = [":server"], ) oci_image( name = "server_image", base = "@haskell-base-image//image", tars = [":server_tar"], exposed_ports = ["8080/tcp"], entrypoint = ["/server"], ) oci_push( name = "server_push", image = ":server_image", repository = "gcr.io/my-project/server", remote_tags = ["latest"], ) ``` -------------------------------- ### Generate and View Dependency Graph with xdot Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell.md Pipe the output of `bazel query` directly to `xdot` to generate and view the dependency graph. This command requires GraphViz and xdot to be installed. ```bash xdot <(bazel query --nohost_deps --noimplicit_deps \ 'deps(//lib:booleans)' --output graph) ``` -------------------------------- ### Navigate to the tutorial directory Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell.md Change the current working directory to the tutorial folder. ```default $ cd tutorial ``` -------------------------------- ### Initialize project with Nixpkgs Source: https://github.com/tweag/rules_haskell/blob/master/README.md Bootstrap a project using Nixpkgs to provision the GHC toolchain. ```console $ sh <(curl https://haskell.build/start) --use-nix ``` -------------------------------- ### Initialize a new Haskell project Source: https://github.com/tweag/rules_haskell/blob/master/README.md Commands to bootstrap a new project with default or Bzlmod configurations. ```console $ curl https://haskell.build/start | sh ``` ```console $ sh <(curl https://haskell.build/start) --with-bzlmod=true ``` -------------------------------- ### Build Tutorial Workspace Source: https://github.com/tweag/rules_haskell/blob/master/tutorial/README.md Builds all targets within the tutorial workspace. ```bash $ bazel build //... ``` -------------------------------- ### View Coverage Report Output Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Example output generated when running a test with coverage enabled. ```default INFO: From Testing //somepackage:test: ==================== Test output for //somepackage:test: Overall report 100% expressions used (9/9) 100% boolean coverage (0/0) 100% guards (0/0) 100% 'if' conditions (0/0) 100% qualifiers (0/0) 100% alternatives used (0/0) 100% local declarations used (0/0) 100% top-level declarations used (3/3) ============================================================================= ``` -------------------------------- ### Query Tutorial Targets Source: https://github.com/tweag/rules_haskell/blob/master/tutorial/README.md Lists all targets available in the tutorial workspace. ```bash $ bazel query //... //main:demorgan //main:base //lib:booleans ``` -------------------------------- ### Preview Local Documentation Source: https://github.com/tweag/rules_haskell/blob/master/CLAUDE.md Run this script to preview the auto-generated documentation locally. ```bash ./serve-docs.sh ``` -------------------------------- ### Define library-level dependencies Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Example of a library dependency that forces all modules to depend on the entire target library. ```default haskell_module( name = "Lib2Mod1", src = "src/LibMod1.hs", src_strip_prefix = "src", deps = [":Lib2Mod2"], ) haskell_library( name = "lib2", modules = [ "Lib2Mod1", "Lib2Mod2", ], deps = [ ":lib", "//:base", "//:template-haskell", ], ) ``` -------------------------------- ### Initialize a new project Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Use the provided shell script to create a new Bazel workspace with default Haskell build targets. ```shell $ curl https://haskell.build/start | sh ``` -------------------------------- ### Project directory structure Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell.md The layout of the tutorial project directory. ```default rules_haskell └── tutorial ├── WORKSPACE ├── main │ ├── BUILD.bazel │ └── Main.hs └── lib ├── BUILD.bazel └── Bool.hs ``` -------------------------------- ### Configure integration test with specific versions Source: https://github.com/tweag/rules_haskell/blob/master/rules_haskell_tests/tests/integration_testing/README.md Example of defining an integration test that targets specific Bazel versions. ```bzl rules_haskell_integration_test( name = "some_test", srcs = ["SomeTest.hs"], workspace_path = "some_test", bindist_bazel_versions = ["4.1.0"], nixpkgs_bazel_package = ["bazel_4"], ) ``` -------------------------------- ### Run ARM binaries with QEMU Source: https://github.com/tweag/rules_haskell/blob/master/examples/arm/README.md Execute the compiled ARM binaries within a QEMU environment. ```bash cd examples/arm nix-shell --pure qemu-shell.nix --run "qemu-aarch64 bazel-bin/example" nix-shell --pure qemu-shell.nix --run "qemu-aarch64 bazel-bin/example2" ``` -------------------------------- ### Building and Executing ghcide Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Commands to build the ghcide executable via Bazel. ```default bazel build @ghcide-exe//ghcide bazel-bin/external/ghcide/ghcide-0.1.0/_install/bin/ghcide ``` -------------------------------- ### Patching a Haskell Package with `vendored_packages` Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Inject a patched version of a Hackage package using `stack_snapshot` and `http_archive`. This example shows how to patch the `split` package. ```default stack_snapshot( ... vendored_packages = { "split": "@split//:split", }, ) http_archive( name = "split", build_file_content = """load(@rules_haskell//haskell:cabal.bzl, "haskell_cabal_library") load(@stackage//:packages.bzl, "packages") haskell_cabal_library( name = "split", version = packages["split"].version, srcs = glob(["**"]), deps = packages["split"].deps, visibility = ["//visibility:public"], ) """, patch_args = ["-p1"], patches = ["@rules_haskell_examples//:split.patch"], sha256 = "1dcd674f7c5f276f33300f5fd59e49d1ac6fc92ae949fd06a0f6d3e9d9ac1413", strip_prefix = "split-0.2.3.3", urls = ["http://hackage.haskell.org/package/split-0.2.3.3/split-0.2.3.3.tar.gz"], ) ``` -------------------------------- ### Run the cat_hs Executable with Bazel Source: https://github.com/tweag/rules_haskell/blob/master/examples/cat_hs/README.md This command demonstrates how to run the cat_hs executable. Pass '-h' for help or a file path as an argument to process. ```bash $ bazel run //cat_hs/exec/cat_hs -- -h ``` ```bash $ bazel run //cat_hs/exec/cat_hs -- $PWD/README.md ``` -------------------------------- ### Execute Core Bazel Commands Source: https://github.com/tweag/rules_haskell/blob/master/CLAUDE.md Standard commands for building, testing, linting, and generating documentation for the project. ```bash # 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 //... ``` -------------------------------- ### Cabal broken package error Source: https://github.com/tweag/rules_haskell/blob/master/README.md Example of a Cabal error message indicating broken packages due to GHC's non-deterministic library ID bug. ```text 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 ``` -------------------------------- ### Register Nixpkgs-based Static GHC Toolchain Source: https://context7.com/tweag/rules_haskell/llms.txt Configure a GHC toolchain from Nixpkgs for static builds. Set `static_runtime` and `fully_static_link` to `True` for static linking. ```bzl # In WORKSPACE for Nixpkgs-based static builds haskell_register_ghc_nixpkgs( version = "9.2.8", attribute_path = "staticHaskell.ghc", repositories = {"nixpkgs": "@nixpkgs"}, static_runtime = True, fully_static_link = True, ) ``` -------------------------------- ### Build the Haskell Package with Bazel Source: https://github.com/tweag/rules_haskell/blob/master/examples/cat_hs/README.md Use this command to build all targets within the cat_hs Haskell project. Ensure you are in the 'examples/' directory. ```bash $ bazel build //cat_hs/... ``` -------------------------------- ### Configure Nixpkgs overlay for GHC Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Appends GHC runtime options to the build configuration via a Nix overlay. ```nix echo "GhcRtsHcOpts += -fPIC -fexternal-dynamic-refs" >> mk/build.mk ''; }); }); }; in args@{ overlays ? [], ... }: import baseNixpkgs (args // { overlays = [overlay] ++ overlays; }) ``` -------------------------------- ### Nixpkgs Pin Update Example Source: https://github.com/tweag/rules_haskell/blob/master/README.md Update the 'url' in './nixpkgs/default.nix' with a new git commit hash from NixOS unstable channels. Remember to change the 'sha256' and update the date comment. ```nix url = "https://github.com/NixOS/nixpkgs/archive/YOUR_COMMIT_HASH.tar.gz"; sha256 = "YOUR_SHA256_HASH"; ``` -------------------------------- ### Generate PR list for CHANGELOG using GitHub CLI Source: https://github.com/tweag/rules_haskell/blob/master/MAINTAINERS.md Fetches merged pull requests since the last release and formats them into a markdown file. Requires the GitHub CLI and jq installed. ```bash gh pr list -L 500 -B master -s merged \ --json number,mergedAt,title,body \ | jq -r --argjson release "$(gh release view --json createdAt)" ' reverse | .[] | select(.mergedAt > $release.createdAt) | ["# PR#\(.number): \(.title)", "*Merged: \(.mergedAt)*", "\(.body)\n"] | join("\n\n")' \ > PRs.md ``` -------------------------------- ### Build ARM project with Bazel Source: https://github.com/tweag/rules_haskell/blob/master/examples/arm/README.md Execute the build process for the ARM target using the specified platform and Nixpkgs configuration. ```bash cd examples/arm nix-shell --pure --run "bazel build //... --platforms=//:linux_aarch64 --config linux-nixpkgs" ``` -------------------------------- ### Extend runfiles with add_data rule Source: https://github.com/tweag/rules_haskell/blob/master/tools/ghc-paths/README.md Use the `add_data` rule to augment the runfiles of an existing target, particularly useful for targets not directly controlled. This example adds `libdir` to the runfiles of a `ghcide` executable. ```python load("//tools/ghc-paths:defs.bzl", "add_data") add_data( name = "ghcide", data = ["//tools/ghc-paths:libdir"], executable = "@ghcide-exe//ghcide", ) ``` -------------------------------- ### Integrate Stackage Snapshots with stack_snapshot Source: https://github.com/tweag/rules_haskell/blob/master/CLAUDE.md Use the `stack_snapshot` rule to integrate Stackage snapshots into Bazel. This rule converts Stack's `stackage_snapshot.yaml` to Bazel targets and supports custom setup dependencies and vendored packages. ```python 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", }, ) ``` -------------------------------- ### Configure Local Bazel Settings Source: https://github.com/tweag/rules_haskell/blob/master/CLAUDE.md Add preferred build configurations to the local .bazelrc file. ```text build --config=linux-nixpkgs ``` -------------------------------- ### Configure IDE Integration with ghcide Source: https://context7.com/tweag/rules_haskell/llms.txt Set up hie-bios to enable language server support for Bazel projects. ```bzl # BUILD.bazel load("@rules_haskell//haskell:defs.bzl", "haskell_repl") haskell_repl( name = "hie-bios", deps = [ "//lib:mylib", "//app:myapp", ], collect_data = False, ) # Run: bazel run //:hie-bios@bios > compile_flags.txt ``` ```bash # .hie-bios #!/usr/bin/env bash set -euo pipefail bazel run //:hie-bios@bios echo -Wwarn >>"$HIE_BIOS_OUTPUT" ``` ```yaml # hie.yaml cradle: bios: program: ".hie-bios" ``` -------------------------------- ### Build and test project targets Source: https://github.com/tweag/rules_haskell/blob/master/README.md Standard Bazel commands to execute builds and tests. ```console $ bazel build //... # Build all targets $ bazel test //... # Run all tests ``` -------------------------------- ### Configure NixOS build platform Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell.md Append the host platform configuration to the local Bazel configuration file for NixOS users. ```default $ echo 'build --host_platform=@rules_nixpkgs_core//platforms:host' >> .bazelrc.local ``` -------------------------------- ### Manage Nix Development Environments Source: https://github.com/tweag/rules_haskell/blob/master/CLAUDE.md Commands to enter a Nix shell with appropriate dependencies and toolchain versions. ```bash # 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 false ``` -------------------------------- ### Run bazel-coverage-report-renderer Source: https://github.com/tweag/rules_haskell/blob/master/tools/coverage-reports/README.md Execute the renderer tool by pointing it to the generated test.xml file and specifying a destination directory for the HTML reports. ```bash bazel-coverage-report-renderer \ --testlog=/two-libs/test.xml \ --destdir=path/to/destination/directory> ``` -------------------------------- ### Build and run Haskell targets Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell.md Commands to build, execute, and run Bazel targets. ```default $ bazel build //main:demorgan ``` ```default INFO: Found 1 target... Target //main:demorgan up-to-date: bazel-bin/main/demorgan INFO: Elapsed time: 2.728s, Critical Path: 1.23s ``` ```default $ bazel-bin/main/demorgan ``` ```default $ bazel run //main:demorgan ``` -------------------------------- ### Build and run local tests Source: https://github.com/tweag/rules_haskell/blob/master/README.md Execute this command to build and run the test suite locally. It includes running tests within the main repository and a sub-directory. ```Bash $ bazel test //... && cd rules_haskell_tests && bazel test //... ``` -------------------------------- ### Register GHC toolchain from Nixpkgs Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Configure a hermetic build by pulling the GHC compiler from Nixpkgs. ```starlark load( "@io_tweag_rules_nixpkgs//nixpkgs:nixpkgs.bzl", "nixpkgs_git_repository", ) nixpkgs_git_repository( name = "nixpkgs", revision = "19.03", # Any tag or commit hash ) load( "@rules_haskell//haskell:nixpkgs.bzl", "haskell_register_ghc_nixpkgs", ) haskell_register_ghc_nixpkgs( version = "X.Y.Z", # Any GHC version attribute_path = "ghc", # The Nix attribute path to the compiler. repositories = {"nixpkgs": "@nixpkgs"}, ) ``` -------------------------------- ### Configure Remote Cache Source: https://github.com/tweag/rules_haskell/blob/master/CLAUDE.md Set up remote cache access by creating a `.bazelrc.auth` file for API keys and adding a configuration to your `.bazelrc.local` file. ```bash build --remote_header=x-buildbuddy-api-key=YOUR_API_KEY ``` ```bash build --config=remote-cache ``` -------------------------------- ### Build the test suite with cabal Source: https://github.com/tweag/rules_haskell/blob/master/examples/primitive/test/README.md Use this command from the root directory of the primitive package to build the test suite while enabling tests. ```bash cabal new-build test --enable-tests ``` -------------------------------- ### Run a REPL for a target Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Command to launch an interactive session for a defined Haskell target. ```default $ bazel run //:hello@repl ``` -------------------------------- ### Configure C toolchains Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Registers native and cross-toolchains for C using nixpkgs_cc_configure. ```default nixpkgs_cc_configure( name = "nixpkgs_config_cc_x86", exec_constraints = [ "@platforms//cpu:x86_64", "@platforms//os:linux", ], repository = "@nixpkgs", target_constraints = [ "@platforms//cpu:x86_64", "@platforms//os:linux", ], ) nixpkgs_cc_configure( name = "nixpkgs_config_cc_arm", attribute_path = "cc-aarch64", exec_constraints = [ "@platforms//cpu:x86_64", "@platforms//os:linux", ], nix_file = "//:arm-cross.nix", repository = "@nixpkgs", target_constraints = [ "@platforms//cpu:aarch64", "@platforms//os:linux", ], ) ``` -------------------------------- ### Discovering runfiles in Haskell Source: https://github.com/tweag/rules_haskell/blob/master/tools/runfiles/README.md Demonstrates using the Bazel.Runfiles library to locate and read data files or execute binaries within the Bazel runfiles tree. ```haskell module Main (main) where import qualified Bazel.Runfiles as Runfiles import Control.Monad (when) import System.Process (callProcess) main :: IO () main = do r <- Runfiles.create foo <- readFile (Runfiles.rlocation r "rules_haskell/tools/runfiles/test-data.txt") when (lines foo /= ["foo"]) -- ignore trailing newline $ error $ "Incorrect contents: got: " ++ show foo callProcess (Runfiles.rlocation r "rules_haskell/tools/runfiles/bin") [] ``` -------------------------------- ### Configure BUILD.bazel for Haskell OCI images Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Defines the Haskell binary, packages it into a tarball, and creates an OCI image using the base image. ```starlark load("@rules_oci//oci:defs.bzl", "oci_image", "oci_push") load("@rules_pkg//pkg:tar.bzl", "pkg_tar") haskell_binary( name = "my_binary", srcs = ["Main.hs"], ghcopts = [ "-O2", "-threaded", "-rtsopts", "-with-rtsopts=-N", ], deps = [ ":my_haskell_library_dep", # for example... # ... ], ) pkg_tar( name = "my_binary_tar", srcs = [":my_binary"], ) oci_image( name = "my_binary_image", base = "@haskell-base-image//image", tars = [":pkg_tar"], exposed_ports = [ "8000/tcp" ], entrypoint = ["/my_binary"], ) ``` -------------------------------- ### Build Fully Static Binaries with Haskell Source: https://context7.com/tweag/rules_haskell/llms.txt Use the `fully_static_link` feature to build fully statically linked Haskell executables. Ensure your toolchain supports static linking. ```bzl load("@rules_haskell//haskell:defs.bzl", "haskell_binary") haskell_binary( name = "static-app", srcs = ["Main.hs"], deps = ["@stackage//:base"], # Enable fully static linking via feature flag features = ["fully_static_link"], ) ``` -------------------------------- ### Configure cross-compilation for ARM Source: https://context7.com/tweag/rules_haskell/llms.txt Define platforms and register a cross-compiler toolchain using Nixpkgs. ```bzl # BUILD.bazel platform( name = "linux_aarch64", constraint_values = [ "@platforms//os:linux", "@platforms//cpu:aarch64", ], ) # WORKSPACE load("@rules_haskell//haskell:nixpkgs.bzl", "haskell_register_ghc_nixpkgs") # Register cross-compiler haskell_register_ghc_nixpkgs( name = "aarch64", version = "8.10.4", nix_file = "//:arm-cross.nix", attribute_path = "ghc-aarch64", static_runtime = True, exec_constraints = [ "@platforms//cpu:x86_64", "@platforms//os:linux", ], target_constraints = [ "@platforms//cpu:aarch64", "@platforms//os:linux", ], repository = "@nixpkgs", ) ``` ```bash # Build for ARM bazel build //:myapp \ --platforms=//:linux_aarch64 \ --incompatible_enable_cc_toolchain_resolution ``` -------------------------------- ### Import GHC toolchain libraries Source: https://context7.com/tweag/rules_haskell/llms.txt Exposes prebuilt libraries included with the GHC distribution for use as dependencies. ```bzl load("@rules_haskell//haskell:defs.bzl", "haskell_toolchain_library") # Standard GHC libraries haskell_toolchain_library(name = "base") haskell_toolchain_library(name = "bytestring") haskell_toolchain_library(name = "containers") haskell_toolchain_library(name = "text") haskell_toolchain_library(name = "mtl") haskell_toolchain_library(name = "template-haskell") # Use with custom package name if different from target name haskell_toolchain_library( name = "ghc_lib", package = "ghc", ) ``` -------------------------------- ### Run Tests for the Haskell Project with Bazel Source: https://github.com/tweag/rules_haskell/blob/master/examples/cat_hs/README.md Execute this command to run all tests defined for the cat_hs Haskell project. This is useful for verifying the correctness of the implementation. ```bash $ bazel test //cat_hs/... ``` -------------------------------- ### Run integration tests via tags Source: https://github.com/tweag/rules_haskell/blob/master/rules_haskell_tests/tests/integration_testing/README.md Execute all tests tagged with 'integration'. ```bash bazel test --test_tag_filters=integration //... ``` -------------------------------- ### Creating a Nix overlay for static GHC Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Define an overlay to override the GHC derivation with necessary flags for static linking, such as -fPIC and -fexternal-dynamic-refs. ```default let # Pick a version of Nixpkgs that we will base our package set on (apply an # overlay to). baseCommit = "..."; # Pick a Nixpkgs version to pin to. baseSha = "..."; # The SHA of the above version. baseNixpkgs = builtins.fetchTarball { name = "nixos-nixpkgs"; url = "https://github.com/NixOS/nixpkgs/archive/${baseCommit}.tar.gz"; sha256 = baseSha; }; # Our overlay. We add a `staticHaskell.ghc` path matching that specified in # the haskell_register_ghc_nixpkgs rule above which overrides the `ghc` # derivation provided in the base set (`super.ghc`) with some necessary # arguments. overlay = self: super: { staticHaskell = { ghc = (super.ghc.override { enableRelocatedStaticLibs = true; enableShared = false; }).overrideAttrs (oldAttrs: { preConfigure = '' ${oldAttrs.preConfigure or ""} echo "GhcLibHcOpts += -fPIC -fexternal-dynamic-refs" >> mk/build.mk echo "GhcRtsHcOpts += -fPIC -fexternal-dynamic-refs" >> mk/build.mk ''; }); }; }; in args@{ overlays ? [], ... }: import baseNixpkgs (args // { overlays = [overlay] ++ overlays; }) ``` -------------------------------- ### Using static-haskell-nix for GHC derivation Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Integrate the static-haskell-nix project to provide a GHC derivation based on Musl for improved static linking compatibility. ```default let baseCommit = "..."; # Pick a Nixpkgs version to pin to. baseSha = "..."; # The SHA of the above version. staticHaskellNixCommit = "..."; Pick a static-haskell-nix version to pin to. baseNixpkgs = builtins.fetchTarball { name = "nixos-nixpkgs"; url = "https://github.com/NixOS/nixpkgs/archive/${baseCommit}.tar.gz"; sha256 = baseSha; }; staticHaskellNixpkgs = builtins.fetchTarball "https://github.com/nh2/static-haskell-nix/archive/${staticHaskellNixCommit}.tar.gz"; # The `static-haskell-nix` repository contains several entry points for e.g. # setting up a project in which Nix is used solely as the build/package # management tool. We are only interested in the set of packages that underpin # these entry points, which are exposed in the `survey` directory's # `approachPkgs` property. staticHaskellPkgs = ( import (staticHaskellNixpkgs + "/survey/default.nix") {} ).approachPkgs; overlay = self: super: { staticHaskell = staticHaskellPkgs.extend (selfSH: superSH: { ghc = (superSH.ghc.override { enableRelocatedStaticLibs = true; enableShared = false; }).overrideAttrs (oldAttrs: { preConfigure = '' ${oldAttrs.preConfigure or ""} echo "GhcLibHcOpts += -fPIC -fexternal-dynamic-refs" >> mk/build.mk ``` -------------------------------- ### Manage Dependencies with Stackage Source: https://context7.com/tweag/rules_haskell/llms.txt Use stack_snapshot to import and pin Haskell packages from Stackage snapshots. ```bzl load("@rules_haskell//haskell:cabal.bzl", "stack_snapshot") stack_snapshot( name = "stackage", snapshot = "lts-21.25", packages = [ "base", "aeson", "lens", "text", "bytestring", "containers", "mtl", # Override version from snapshot "zlib-0.6.3", ], # Cabal flags flags = { "zlib": ["-non-blocking-ffi"], "aeson": ["+ordered-keymap"], }, # System library dependencies extra_deps = { "zlib": ["@zlib.dev//:zlib"], "postgresql-libpq": ["@postgresql//:include"], }, # Setup dependencies for custom Setup.hs setup_deps = { "some-package": ["@stackage//:Cabal"], }, # Executable tools needed during build tools = ["@happy//:happy", "@alex//:alex"], # Component declarations components = { "doctest": ["lib", "exe"], "proto-lens-protoc": ["lib", "exe"], }, # Enable Haddock generation haddock = True, ) # Pin dependencies for reproducibility # Run: bazel run @stackage-unpinned//:pin # Then add: stack_snapshot( name = "stackage", stack_snapshot_json = "//:stackage_snapshot.json", # ... other attributes ) ``` -------------------------------- ### Configure C toolchain with nixpkgs_cc_configure Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Uses nixpkgs_cc_configure to supply a Musl-based C toolchain for static Haskell builds. ```starlark nixpkgs_cc_configure( repository = "@nixpkgs", # The `staticHaskell` attribute in the previous example exposes the # Musl-backed `cc` and `binutils` derivations already, so it's just a # matter of exposing them to nixpkgs_cc_configure. nix_file_content = """ with import { config = {}; overlays = []; }; buildEnv { name = "bazel-cc-toolchain"; paths = [ staticHaskell.stdenv.cc staticHaskell.binutils ]; } """, ) ``` -------------------------------- ### Set host platform in .bazelrc Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Configure the host platform to enable toolchain resolution for Nixpkgs-based toolchains. ```text build --host_platform=@io_tweag_rules_nixpkgs//nixpkgs/platforms:host ``` -------------------------------- ### Build API documentation via command-line aspect Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Use the haskell_doc_aspect to generate documentation for targets from the command line. ```console $ bazel build //my/pkg:mylib \ --aspects @rules_haskell//haskell:defs.bzl%haskell_doc_aspect ``` -------------------------------- ### Register GHC toolchains Source: https://context7.com/tweag/rules_haskell/llms.txt Configures GHC binary distributions for specific platforms within the WORKSPACE file. ```bzl load("@rules_haskell//haskell:toolchain.bzl", "rules_haskell_toolchains") # Register GHC from binary distributions rules_haskell_toolchains( version = "9.2.8", # Platform-specific distribution selection dist = { "linux_amd64": "deb10", "linux_arm64": "deb10", }, # Locale for Haddock (fix encoding issues) locale = "en_US.UTF-8", ) # Alternative: specific GHC variants rules_haskell_toolchains( version = "9.4.8", variant = { "linux_amd64": "alpine3_12", # For static builds }, ) ``` -------------------------------- ### Build a Haskell binary Source: https://context7.com/tweag/rules_haskell/llms.txt Defines an executable target with source files, dependencies, and GHC options. Includes an automatically generated REPL target accessible via the @repl suffix. ```bzl load("@rules_haskell//haskell:defs.bzl", "haskell_binary", "haskell_toolchain_library") # Declare toolchain libraries from GHC haskell_toolchain_library(name = "base") haskell_binary( name = "hello", srcs = ["Main.hs", "Utils.hs"], deps = [":base", "//lib:mylib"], ghcopts = ["-threaded", "-O2"], main_function = "Main.main", # Enable static linking linkstatic = True, # Data files available at runtime data = ["data/config.json"], ) # Access REPL: bazel run //:hello@repl ``` -------------------------------- ### List available system locales Source: https://github.com/tweag/rules_haskell/blob/master/README.md Command to list available locales on the system to identify a valid string for configuration. ```console $ locale -a C en_US en_US.iso88591 en_US.utf8 POSIX ``` -------------------------------- ### Define a Nix base image Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Creates a layered Docker image containing essential runtime libraries for Haskell binaries. ```nix let haskellBase = dockerTools.buildLayeredImage { name = "haskell-base-image-unwrapped"; created = "now"; contents = [ glibc libffi gmp zlib iana-etc cacert ]; # Here we can specify nix-provisioned libraries our haskell_binary products may need at runtime }; # rules_nixpkgs require the nix output to be a directory, # so we create one in which we put the image we've just created in runCommand "haskell-base-image" { } '' mkdir -p $out gunzip -c ${haskellBase} > $out/image '' ``` -------------------------------- ### Create Haskell REPL Source: https://context7.com/tweag/rules_haskell/llms.txt Use haskell_repl to create an interactive development environment for multiple targets. ```bzl load("@rules_haskell//haskell:defs.bzl", "haskell_repl") haskell_repl( name = "dev-repl", deps = [ "//lib:mylib", "//app:myapp", ], # Load these targets from source experimental_from_source = [ "//lib:mylib", "//app:myapp", ], # Additional GHCi arguments repl_ghci_args = [ "-fobject-code", "-fdefer-type-errors", ], # Don't collect data dependencies collect_data = False, ) # Run: bazel run //:dev-repl ``` -------------------------------- ### GHC settings file missing error Source: https://github.com/tweag/rules_haskell/blob/master/README.md Error message indicating that the GHC settings file cannot be found, often due to hardcoded paths in ghc-paths. ```text .../lib/settings: openFile: does not exist (No such file or directory) ``` -------------------------------- ### Add Bazel configuration to .bazelrc.local Source: https://github.com/tweag/rules_haskell/blob/master/README.md Add this line to your .bazelrc.local file to avoid repeating configuration flags in Bazel commands. ```Bash echo "build --config=linux-nixpkgs" >>.bazelrc.local ``` -------------------------------- ### Configure rules_haskell in WORKSPACE Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Load and define the rules_haskell repository using http_archive. ```starlark load( "@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive" ) http_archive( name = "rules_haskell", sha256 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", strip_prefix = "rules_haskell-M.NN", url = "https://github.com/tweag/rules_haskell/releases/download/vM.NN/rules_haskell-M.NN.tar.gz", ) ``` -------------------------------- ### Build a Haskell library Source: https://context7.com/tweag/rules_haskell/llms.txt Creates a reusable library with support for module visibility, re-exports, and package metadata. ```bzl load("@rules_haskell//haskell:defs.bzl", "haskell_library", "haskell_toolchain_library") haskell_toolchain_library(name = "base") haskell_toolchain_library(name = "text") haskell_library( name = "mylib", srcs = glob(["src/**/*.hs"]), deps = [":base", ":text"], # Hide internal modules from downstream consumers hidden_modules = ["Internal.Utils"], # Re-export modules from dependencies reexported_modules = { "//sublib:lib": "SubLib.Public as MyLib.SubLib", }, # Package metadata for Cabal compatibility package_name = "mylib", version = "1.0.0", visibility = ["//visibility:public"], ghcopts = [ "-Wall", "-Werror", "-Wcompat", ], ) ``` -------------------------------- ### Registering a static GHC toolchain Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Configure the haskell_register_ghc_nixpkgs macro with static_runtime and fully_static_link attributes enabled. ```default load( "@rules_haskell//haskell:nixpkgs.bzl", "haskell_register_ghc_nixpkgs", ) haskell_register_ghc_nixpkgs( version = "X.Y.Z", attribute_path = "staticHaskell.ghc", repositories = {"nixpkgs": "@nixpkgs"}, static_runtime = True, fully_static_link = True, ) ``` -------------------------------- ### Bazel label syntax Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell.md The standard format for referencing targets within a Bazel workspace. ```default //path/to/package:target-name ``` -------------------------------- ### Nix shell for pure development environment Source: https://github.com/tweag/rules_haskell/blob/master/README.md Enter a pure Nix shell to ensure a consistent development environment with predefined toolchains like Python and GHC. ```Bash $ nix-shell --pure shell.nix ``` -------------------------------- ### Bazel build flag for protoc.exe workaround Source: https://github.com/tweag/rules_haskell/blob/master/README.md Use this build flag to work around protoc.exe DLL loading issues on Windows, especially with newer GHC distributions. ```Starlark --proto_compiler @rules_haskell//tests:protoc ``` -------------------------------- ### Define base image with nixpkgs_package Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Uses nixpkgs_package to define a base image for containerization. ```starlark nixpkgs_package( name = "haskell-base-image", repository = "//nixpkgs:default.nix", # See below for how to define this nix_file = "//nixpkgs:haskellBaseImageDocker.nix", build_file_content = """ package(default_visibility = [ "//visibility:public" ]) exports_files(["image"]) """, ) ``` -------------------------------- ### Configure local_repository for rules_haskell Source: https://github.com/tweag/rules_haskell/blob/master/rules_haskell_tests/tests/integration_testing/README.md Add this to the WORKSPACE file within your test workspace to reference the rules_haskell dependency. ```bzl local_repository( name = "rules_haskell", path = "%RULES_HASKELL_PATH%" ) ``` -------------------------------- ### Register a native compiler in WORKSPACE Source: https://github.com/tweag/rules_haskell/blob/master/docs/haskell-use-cases.md Registers a native compiler for the execution platform, necessary for running Setup.hs scripts. ```default haskell_register_ghc_nixpkgs( name = "x86", version = "8.10.4", attribute_path = "haskell.compiler.ghc8102", exec_constraints = [ "@platforms//cpu:x86_64", "@platforms//os:linux", ], target_constraints = [ "@platforms//cpu:x86_64", "@platforms//os:linux", ], repository = "@nixpkgs", ) ``` -------------------------------- ### Build and run a Haskell test suite Source: https://context7.com/tweag/rules_haskell/llms.txt Configures a test target with support for code coverage analysis and specific test execution parameters. ```bzl load("@rules_haskell//haskell:defs.bzl", "haskell_test", "haskell_toolchain_library") haskell_toolchain_library(name = "base") haskell_test( name = "unit-tests", srcs = ["Test/Main.hs", "Test/UnitTests.hs"], deps = [ ":base", "//lib:mylib", "@stackage//:hspec", "@stackage//:QuickCheck", ], # Code coverage settings expected_covered_expressions_percentage = 80, expected_uncovered_expression_count = 10, strict_coverage_analysis = False, coverage_report_format = "text", # Test configuration ghcopts = ["-threaded"], size = "small", timeout = "short", ) # Run: bazel test //:unit-tests # Run with coverage: bazel coverage //:unit-tests --test_output=all ```