Cabal packages
Bazel

Cabal packages


haskell_cabal_binary

haskell_cabal_binary(name, deps, srcs, cabalopts, compiler_flags, exe_name, flags,
                     generate_paths_module, setup_deps, tools, verbose)

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

Attributes

name Name; required

A unique name for this target.

deps List of labels; optional; default is []

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

srcs List of labels; optional; default is []

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

cabalopts List of strings; optional; default is []

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 List of strings; optional; default is []

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.

exe_name String; optional; default is ""

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

flags List of strings; optional; default is []

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

generate_paths_module Boolean; optional; default is False

If True the rule will generate a Paths_{pkgname} module based on the haskell_runfiles library. In that case, the @rules_haskell//tools/runfiles target should also be added to the deps attribute, and the runfiles package should be added to the component’s build-depends section of the .cabal file. WARNING: this is not supported in profiling mode yet.

setup_deps List of labels; optional; default is []

Dependencies for custom setup Setup.hs.

tools List of labels; optional; default is []

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

verbose Boolean; optional; default is True

Whether to show the output of the build


haskell_cabal_library

haskell_cabal_library(name, deps, srcs, cabalopts, compiler_flags, flags, generate_paths_module,
                      haddock, package_name, setup_deps, sublibrary_name, tools, unique_name, verbose,
                      version)

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.

Attributes

name Name; required

A unique name for this target.

deps List of labels; optional; default is []

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

srcs List of labels; optional; default is []

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

cabalopts List of strings; optional; default is []

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 List of strings; optional; default is []

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

flags List of strings; optional; default is []

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

generate_paths_module Boolean; optional; default is False

If True the rule will generate a Paths_{pkgname} module based on the haskell_runfiles library. In that case, the @rules_haskell//tools/runfiles target should also be added to the deps attribute, and the runfiles package should be added to the component’s build-depends section of the .cabal file. WARNING: this is not supported in profiling mode yet.

haddock Boolean; optional; default is True

Whether to generate haddock documentation.

package_name String; optional; default is ""

Cabal package name. Defaults to name attribute.

setup_deps List of labels; optional; default is []

Dependencies for custom setup Setup.hs.

sublibrary_name String; optional; default is ""

sublibrary of the Cabal package to build

tools List of labels; optional; default is []

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

unique_name Boolean; optional; default is False

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 Boolean; optional; default is True

Whether to show the output of the build

version String; required

Version of the Cabal package.


stack_snapshot

stack_snapshot(name, stack, extra_deps, vendored_packages, snapshot, local_snapshot,
               stack_snapshot_json, packages, flags, haddock, setup_deps, tools, components,
               components_dependencies, stack_update, verbose, netrc, toolchain_libraries,
               setup_stack, label_builder, kwargs)

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 items of the packages attribute and all items of the vendored_packages attribute are made available as top-level targets named after each package with public visibility. Other packages that are dependencies of vendored packages are made available with visibility restricted to these vendored packages.

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.
  • visibility: The visibility of the given package.

NOTE: Make sure your GHC version matches the version expected by the snapshot. E.g. if you pass snapshot = "lts-20.3", make sure you use GHC 9.2.5 (e.g. by invoking rules_haskell_toolchains(version="9.2.5")). 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-20.3",
    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-20.3

packages:
  - zlib-0.6.2

Attributes

name required

The name of the Bazel workspace.

stack optional; default is None

The stack binary to use to enumerate package dependencies.

extra_deps optional; default is {}

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 optional; default is {}

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 optional; default is ""

The name of a Stackage snapshot. Incompatible with local_snapshot.

local_snapshot optional; default is None

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

stack_snapshot_json optional; default is None

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

packages optional; default is []

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

flags optional; default is {}

A dict from package name to list of flags.

haddock optional; default is True

Whether to generate haddock documentation.

setup_deps optional; default is {}

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 optional; default is []

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

components optional; default is {}

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

components_dependencies optional; default is {}

Internal dependencies between package components. For each package, these dependencies are described as a string representing a JSON dictionary of lists. (WARNING: this will likely change in the future). The most common case is the following, where the main library of a package depends on sublibraries:

components_dependencies = {
  "package-name": """{"lib:package-name": ["lib:sublib1", "lib:sublib2"]}""",
},

stack_update optional; default is None

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 optional; default is False

Whether to show the output of the build.

netrc optional; default is ""

Location of the .netrc file to use for authentication. Defaults to ~/.netrc if present.

toolchain_libraries optional; default is None

If this snapshot is to be used with a compiler providing a non standard set of toolchain libraries, these must be declared here. In the case of asterius, this list can be loaded from the toolchain_libraries.bzl of the toolchain repositories (a stack_snapshot repository is not tied to a particular toolchain, but the toolchain libraries must correspond):

rules_haskell_asterius_toolchains(version = "0.0.1")
load("@linux_amd64_asterius//:toolchain_libraries.bzl", "toolchain_libraries")
stack_snapshot(
    ...,
    toolchain_libraries = toolchain_libraries,
    ...,
)

setup_stack optional; default is True

Do not try to install stack if set to False (only usefull with bzlmod when only the first call to stack_snapshot must do the install).

label_builder optional; default is <function lambda>

A function to build a Label from the context of the caller module extension (only useful with bzlmod until we provide our own module extension).

kwargs optional

use_stack

use_stack(stack)

Force given stack binary in all invocations of stack_snapshot.

Globally override the stack version used by all instances of stack_snapshot. WARNING: This should only be used in the top-level repository.

Examples

# WORKSPACE

# Order is important! Placing `use_stack()` after any occurrence of `stack_snapshot`
# (also any one nested within another macro call) will fail the build.
use_stack("@x_stack//:stack")
stack_snapshot(
    name = "x",
    # this is ignored due to `use_stack()
    stack = "@y_stack:stack",
    # ...
)
# BUILD.bazel
haskell_binary(
    # ...
    # targets in `x` will be built using `x_stack`, NOT `y_stack`
    deps = ["@x//:all"],
)

Attributes

stack required