Cabal packages

Rules

haskell_cabal_binary

Use Cabal to build a binary.

Examples

haskell_cabal_binary(
    name = "happy",
    srcs = glob(["**"]),
)

This rule assumes that the .cabal file defines a single executable with the same name as the package.

This rule does not use cabal-install. It calls the package's Setup.hs script directly if one exists, or the default one if not. All sources files that would have been part of a Cabal sdist need to be listed in srcs (crucially, including the .cabal file).

name

A unique name for this target.

cabalopts

Additional flags to pass to Setup.hs configure. Subject to make variable expansion.

Use --ghc-option=OPT to configure additional compiler flags. Use --haddock-option=--optghc=OPT if these flags are required for haddock generation as well.

compiler_flags

DEPRECATED. Use cabalopts with --ghc-option instead.

Flags to pass to Haskell compiler, in addition to those defined the cabal file. Subject to Make variable substitution.

deps

Package build dependencies. Note, setup dependencies need to be declared separately using setup_deps.

exe_name

Cabal executable component name. Defaults to the value of the name attribute.

flags

List of Cabal flags, will be passed to Setup.hs configure --flags=....

setup_deps

Dependencies for custom setup Setup.hs.

srcs

All files required to build the package, including the Cabal file.

tools

Tool dependencies. They are built using the host configuration, since the tools are executed as part of the build.

verbose

Whether to show the output of the build


haskell_cabal_library

Use Cabal to build a library.

Examples

haskell_cabal_library(
    name = "lib-0.1.0.0",
    srcs = ["lib.cabal", "Lib.hs", "Setup.hs"],
)

haskell_toolchain_library(name = "base")

haskell_binary(
    name = "bin",
    deps = [":base", ":lib-0.1.0.0"],
    srcs = ["Main.hs"],
)

This rule does not use cabal-install. It calls the package's Setup.hs script directly if one exists, or the default one if not. All sources files that would have been part of a Cabal sdist need to be listed in srcs (crucially, including the .cabal file). A haskell_cabal_library can be substituted for any haskell_library. The two are interchangeable in most contexts. However, using a plain haskell_library sometimes leads to better build times, and does not require drafting a .cabal file.

name

A unique name for this target.

cabalopts

Additional flags to pass to Setup.hs configure. Subject to make variable expansion.

Use --ghc-option=OPT to configure additional compiler flags. Use --haddock-option=--optghc=OPT if these flags are required for haddock generation as well.

compiler_flags

DEPRECATED. Use cabalopts with --ghc-option instead.

Flags to pass to Haskell compiler, in addition to those defined the cabal file. Subject to Make variable substitution.

deps

Package build dependencies. Note, setup dependencies need to be declared separately using setup_deps.

flags

List of Cabal flags, will be passed to Setup.hs configure --flags=....

haddock

Whether to generate haddock documentation.

package_name

Cabal package name. Defaults to name attribute.

setup_deps

Dependencies for custom setup Setup.hs.

srcs

All files required to build the package, including the Cabal file.

tools

Tool dependencies. They are built using the host configuration, since the tools are executed as part of the build.

unique_name

Whether the library name is known to be unique within the workspace. This is used by stack_snapshot where library names are known to be unique within the snapshot. If true, then the dynamic library symlink underneath _solib_<cpu> will be shortened to avoid exceeding the MACH-O header size limit on MacOS.

verbose

Whether to show the output of the build

version

Version of the Cabal package.


Macros and Functions

stack_snapshot

Use Stack to download and extract Cabal source distributions.

This rule will use Stack to compute the transitive closure of the subset of the given snapshot listed in the packages attribute, and generate a dependency graph. If a package in the closure depends on system libraries or other external libraries, use the extra_deps attribute to list them. This attribute works like the --extra-{include,lib}-dirs flags for Stack and cabal-install do. If a package has a custom setup with setup dependencies, use the setup_deps attribute to list them.

Packages that are in the snapshot need not have their versions specified. But any additional packages or version overrides will have to be specified with a package identifier of the form <package>-<version> in the packages attribute. Note that you cannot override the version of any packages built into GHC.

This rule invokes the stack tool for version and dependency resolution based on the specified snapshot. You can generate a stack_snapshot.json file to avoid invoking stack on every fetch and instead pin the outcome in a file that can be checked into revision control. Execute the following command:

bazel run @stackage-unpinned//:pin

Then specify the stack_snapshot_json attribute to point to the generated file:

stack_snapshot(
    ...
    stack_snapshot_json = "//:stackage_snapshot.json",
)

By default stack_snapshot defines a library target for each package. If a package does not contain a library component or contains executable components, then you need to declare so yourself using the components attribute. Library targets are exposed as @stackage//:<package-name> and executables are exposed as @stackage-exe//<package-name>:<executable-name>, assuming that you invoked stack_snapshot with name = "stackage".

In the external repository defined by the rule, all given packages are available as top-level targets named after each package. Additionally, the dependency graph is made available within packages.bzl as the dict packages mapping unversioned package names to structs holding the fields

  • name: The unversioned package name.
  • version: The package version.
  • library: Whether the package has a declared library component.
  • executables: List of declared executable components.
  • deps: The list of library dependencies according to stack.
  • tools: The list of tool dependencies according to stack.
  • flags: The list of Cabal flags.

NOTE: Make sure your GHC version matches the version expected by the snapshot. E.g. if you pass snapshot = "lts-13.15", make sure you use GHC 8.6.4 (e.g. by invoking rules_haskell_toolchains(version="8.6.4")). Sadly, rules_haskell cannot maintain this correspondence for you. You will need to manage it yourself. If you have a version mismatch, you will end up with versions of core GHC packages which do not match the versions listed in the snapshot, and potentially other problems.

Examples

stack_snapshot(
    name = "stackage",
    packages = ["conduit", "doctest", "lens", "zlib-0.6.2"],
    vendored_packages = {"split": "//split:split"},
    tools = ["@happy//:happy"],  # Use externally provided `happy`
    components = {
        "doctest": ["lib", "exe"],  # Optional since doctest is known to have an exe component.
        "happy": [],  # Override happy's default exe component.
    },
    snapshot = "lts-13.15",
    extra_deps = {"zlib": ["@zlib.dev//:zlib"]},
)

defines @stackage//:conduit, @stackage//:doctest, @stackage//:lens, @stackage//:zlib library targets and a @stackage-exe//doctest executable target. It also uses an externally provided happy rather than the one provided by the snapshot.

Alternatively

stack_snapshot(
    name = "stackage",
    packages = ["conduit", "doctest", "lens", "zlib"],
    flags = {"zlib": ["-non-blocking-ffi"]},
    tools = ["@happy//:happy"],  # Use externally provided `happy`
    components = {
        "doctest": ["lib", "exe"],  # Optional since doctest is known to have an exe component.
        "happy": [],  # Override happy's default exe component.
    },
    local_snapshot = "//:snapshot.yaml",
    extra_deps = {"zlib": ["@zlib.dev//:zlib"]},

Does the same as the previous example, provided there is a snapshot.yaml, at the root of the repository with content

resolver: lts-13.15

packages:
  - zlib-0.6.2

name

The name of the Bazel workspace.

stack

The stack binary to use to enumerate package dependencies.

extra_deps

Extra dependencies of packages, e.g. system libraries or C/C++ libraries. Dict of stackage package names to a list of targets. The list of targets is given as input to the named stackage package.

{
    "postgresql-libpq": ["@postgresql//:include"],
    "zlib": ["@zlib.dev//:zlib"]
}

means @postgresql//:include is passed to the stackage package postgresql-libpq while @zlib.dev//:zlib is passed to the stackage package zlib.

vendored_packages

Add or override a package to the snapshot with a custom unpacked source distribution. Each package must contain a Cabal file named <package-name>.cabal in the package root.

snapshot

The name of a Stackage snapshot. Incompatible with local_snapshot.

local_snapshot

A custom Stack snapshot file, as per the Stack documentation. Incompatible with snapshot.

stack_snapshot_json

A label to a stack_snapshot.json file, e.g. //:stack_snapshot.json. Specify this to use pinned artifacts for generating build targets.

packages

A set of package identifiers. For packages in the snapshot, version numbers can be omitted.

flags

A dict from package name to list of flags.

haddock

Whether to generate haddock documentation.

setup_deps

Setup dependencies of packages, e.g. cabal-doctest. Dict of stackage package names to a list of targets in the same format as for extra_deps.

tools

Tool dependencies. They are built using the host configuration, since the tools are executed as part of the build.

components

Defines which Cabal components to build for each package. A dict from package name to list of components. Use lib for the library component and exe:<exe-name> for an executable component, exe is a short-cut for exe:<package-name>. The library component will have the label @<workspace>//:<package> and an executable component will have the label @<workspace>-exe//<package>:<exe-name>, where <workspace> is the name given to the stack_snapshot invocation.

stack_update

A meta repository that is used to avoid multiple concurrent invocations of stack update which could fail due to a race on the hackage security lock.

verbose

Whether to show the output of the build.

kwargs