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).
Example usage (generated)
load("@rules_haskell//haskell:cabal.bzl", "haskell_cabal_binary")
haskell_cabal_binary(
# A unique name for this target.
name = "",
)
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=...
.
generate_paths_module
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.
WARNING: this is not supported in profiling mode yet.
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.
Example usage (generated)
load("@rules_haskell//haskell:cabal.bzl", "haskell_cabal_library")
haskell_cabal_library(
# A unique name for this target.
name = "",
# Version of the Cabal package.
version = "",
)
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=...
.
generate_paths_module
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.
WARNING: this is not supported in profiling mode yet.
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.
sublibrary_name
sublibrary of the Cabal package to build
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 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-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
Example usage (generated)
load("@rules_haskell//haskell:cabal.bzl", "stack_snapshot")
stack_snapshot(
# The name of the Bazel workspace.
name = "",
)
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
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
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
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.
netrc
Location of the .netrc file to use for authentication.
Defaults to ~/.netrc
if present.