feat(third_party/bazel): Check in rules_haskell from Tweag
This commit is contained in:
parent
2eb1dc26e4
commit
f723b8b878
479 changed files with 51484 additions and 0 deletions
354
third_party/bazel/rules_haskell/haskell/nixpkgs.bzl
vendored
Normal file
354
third_party/bazel/rules_haskell/haskell/nixpkgs.bzl
vendored
Normal file
|
|
@ -0,0 +1,354 @@
|
|||
"""Workspace rules (Nixpkgs)"""
|
||||
|
||||
load("@bazel_skylib//lib:dicts.bzl", "dicts")
|
||||
load(
|
||||
"@io_tweag_rules_nixpkgs//nixpkgs:nixpkgs.bzl",
|
||||
"nixpkgs_package",
|
||||
)
|
||||
|
||||
def haskell_nixpkgs_package(
|
||||
name,
|
||||
attribute_path,
|
||||
nix_file_deps = [],
|
||||
repositories = {},
|
||||
build_file_content = None,
|
||||
build_file = None,
|
||||
**kwargs):
|
||||
"""Load a single haskell package.
|
||||
The package is expected to be in the form of the packages generated by
|
||||
`genBazelBuild.nix`
|
||||
"""
|
||||
repositories = dicts.add(
|
||||
{"bazel_haskell_wrapper": "@io_tweag_rules_haskell//haskell:nix/default.nix"},
|
||||
repositories,
|
||||
)
|
||||
|
||||
nixpkgs_args = dict(
|
||||
name = name,
|
||||
attribute_path = attribute_path,
|
||||
build_file_content = build_file_content,
|
||||
nix_file_deps = nix_file_deps + ["@io_tweag_rules_haskell//haskell:nix/default.nix"],
|
||||
repositories = repositories,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
if build_file_content:
|
||||
nixpkgs_args["build_file_content"] = build_file_content
|
||||
elif build_file:
|
||||
nixpkgs_args["build_file"] = build_file
|
||||
else:
|
||||
nixpkgs_args["build_file_content"] = """
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
load("@io_tweag_rules_haskell//haskell:import.bzl", haskell_import_new = "haskell_import")
|
||||
|
||||
load(":BUILD.bzl", "targets")
|
||||
targets()
|
||||
"""
|
||||
|
||||
nixpkgs_package(
|
||||
**nixpkgs_args
|
||||
)
|
||||
|
||||
def _bundle_impl(repository_ctx):
|
||||
build_file_content = """
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
"""
|
||||
for package in repository_ctx.attr.packages:
|
||||
build_file_content += """
|
||||
alias(
|
||||
name = "{package}",
|
||||
actual = "@{base_repo}-{package}//:pkg",
|
||||
)
|
||||
""".format(
|
||||
package = package,
|
||||
base_repo = repository_ctx.attr.base_repository,
|
||||
)
|
||||
repository_ctx.file("BUILD", build_file_content)
|
||||
|
||||
_bundle = repository_rule(
|
||||
attrs = {
|
||||
"packages": attr.string_list(),
|
||||
"base_repository": attr.string(),
|
||||
},
|
||||
implementation = _bundle_impl,
|
||||
)
|
||||
"""
|
||||
Generate an alias from `@base_repo//:package` to `@base_repo-package//:pkg` for
|
||||
each one of the input package
|
||||
"""
|
||||
|
||||
def haskell_nixpkgs_packages(name, base_attribute_path, packages, **kwargs):
|
||||
"""Import a set of haskell packages from nixpkgs.
|
||||
|
||||
This takes as input the same arguments as
|
||||
[nixpkgs_package](https://github.com/tweag/rules_nixpkgs#nixpkgs_package),
|
||||
expecting the `attribute_path` to resolve to a set of haskell packages
|
||||
(such as `haskellPackages` or `haskell.packages.ghc822`) preprocessed by
|
||||
the `genBazelBuild` function. It also takes as input a list of packages to
|
||||
import (which can be generated by the `gen_packages_list` function).
|
||||
"""
|
||||
for package in packages:
|
||||
haskell_nixpkgs_package(
|
||||
name = name + "-" + package,
|
||||
attribute_path = base_attribute_path + "." + package,
|
||||
**kwargs
|
||||
)
|
||||
_bundle(
|
||||
name = name,
|
||||
packages = packages,
|
||||
base_repository = name,
|
||||
)
|
||||
|
||||
def _is_nix_platform(repository_ctx):
|
||||
return repository_ctx.which("nix-build") != None
|
||||
|
||||
def _gen_imports_impl(repository_ctx):
|
||||
repository_ctx.file("BUILD", "")
|
||||
extra_args_raw = ""
|
||||
for foo, bar in repository_ctx.attr.extra_args.items():
|
||||
extra_args_raw += foo + " = " + bar + ", "
|
||||
bzl_file_content = """
|
||||
load("{repo_name}", "packages")
|
||||
load("@io_tweag_rules_haskell//haskell:nixpkgs.bzl", "haskell_nixpkgs_packages")
|
||||
|
||||
def import_packages(name):
|
||||
haskell_nixpkgs_packages(
|
||||
name = name,
|
||||
packages = packages,
|
||||
{extra_args_raw}
|
||||
)
|
||||
""".format(
|
||||
repo_name = repository_ctx.attr.packages_list_file,
|
||||
extra_args_raw = extra_args_raw,
|
||||
)
|
||||
|
||||
# A dummy 'packages.bzl' file with a no-op 'import_packages()' on unsupported platforms
|
||||
bzl_file_content_unsupported_platform = """
|
||||
def import_packages(name):
|
||||
return
|
||||
"""
|
||||
if _is_nix_platform(repository_ctx):
|
||||
repository_ctx.file("packages.bzl", bzl_file_content)
|
||||
else:
|
||||
repository_ctx.file("packages.bzl", bzl_file_content_unsupported_platform)
|
||||
|
||||
_gen_imports_str = repository_rule(
|
||||
implementation = _gen_imports_impl,
|
||||
attrs = dict(
|
||||
packages_list_file = attr.label(doc = "A list containing the list of packages to import"),
|
||||
# We pass the extra arguments to `haskell_nixpkgs_packages` as strings
|
||||
# since we can't forward arbitrary arguments in a rule and they will be
|
||||
# converted to strings anyways.
|
||||
extra_args = attr.string_dict(doc = "Extra arguments for `haskell_nixpkgs_packages`"),
|
||||
),
|
||||
)
|
||||
"""
|
||||
Generate a repository containing a file `packages.bzl` which imports the given
|
||||
packages list.
|
||||
"""
|
||||
|
||||
def _gen_imports(name, packages_list_file, extra_args):
|
||||
"""
|
||||
A wrapper around `_gen_imports_str` which allows passing an arbitrary set of
|
||||
`extra_args` instead of a set of strings
|
||||
"""
|
||||
extra_args_str = {label: repr(value) for (label, value) in extra_args.items()}
|
||||
_gen_imports_str(
|
||||
name = name,
|
||||
packages_list_file = packages_list_file,
|
||||
extra_args = extra_args_str,
|
||||
)
|
||||
|
||||
def haskell_nixpkgs_packageset(name, base_attribute_path, repositories = {}, **kwargs):
|
||||
"""Import all the available haskell packages.
|
||||
The arguments are the same as the arguments of ``nixpkgs_package``, except
|
||||
for the ``base_attribute_path`` which should point to an `haskellPackages`
|
||||
set in the nix expression
|
||||
|
||||
Example:
|
||||
|
||||
In `haskellPackages.nix`:
|
||||
|
||||
```nix
|
||||
with import <nixpkgs> {};
|
||||
|
||||
let wrapPackages = callPackage <bazel_haskell_wrapper> { }; in
|
||||
{ haskellPackages = wrapPackages haskell.packages.ghc822; }
|
||||
```
|
||||
|
||||
In your `WORKSPACE`
|
||||
|
||||
```bazel
|
||||
# Define a nix repository to fetch the packages from
|
||||
load("@io_tweag_rules_nixpkgs//nixpkgs:nixpkgs.bzl",
|
||||
"nixpkgs_git_repository")
|
||||
nixpkgs_git_repository(
|
||||
name = "nixpkgs",
|
||||
revision = "9a787af6bc75a19ac9f02077ade58ddc248e674a",
|
||||
)
|
||||
|
||||
load("@io_tweag_rules_haskell//haskell:nixpkgs.bzl",
|
||||
"haskell_nixpkgs_packageset",
|
||||
|
||||
# Generate a list of all the available haskell packages
|
||||
haskell_nixpkgs_packageset(
|
||||
name = "hackage-packages",
|
||||
repositories = {"@nixpkgs": "nixpkgs"},
|
||||
nix_file = "//haskellPackages.nix",
|
||||
base_attribute_path = "haskellPackages",
|
||||
)
|
||||
load("@hackage-packages//:packages.bzl", "import_packages")
|
||||
import_packages(name = "hackage")
|
||||
```
|
||||
|
||||
Then in your `BUILD` files, you can access to the whole of hackage as
|
||||
`@hackage//:{your-package-name}`
|
||||
"""
|
||||
|
||||
repositories = dicts.add(
|
||||
{"bazel_haskell_wrapper": "@io_tweag_rules_haskell//haskell:nix/default.nix"},
|
||||
repositories,
|
||||
)
|
||||
|
||||
nixpkgs_package(
|
||||
name = name + "-packages-list",
|
||||
attribute_path = base_attribute_path + ".packageNames",
|
||||
repositories = repositories,
|
||||
build_file_content = """
|
||||
exports_files(["all-haskell-packages.bzl"])
|
||||
""",
|
||||
fail_not_supported = False,
|
||||
**kwargs
|
||||
)
|
||||
_gen_imports(
|
||||
name = name,
|
||||
packages_list_file = "@" + name + "-packages-list//:all-haskell-packages.bzl",
|
||||
extra_args = dict(
|
||||
repositories = repositories,
|
||||
base_attribute_path = base_attribute_path,
|
||||
**kwargs
|
||||
),
|
||||
)
|
||||
|
||||
def _ghc_nixpkgs_toolchain_impl(repository_ctx):
|
||||
# These constraints might look tautological, because they always
|
||||
# match the host platform if it is the same as the target
|
||||
# platform. But they are important to state because Bazel
|
||||
# toolchain resolution prefers other toolchains with more specific
|
||||
# constraints otherwise.
|
||||
target_constraints = ["@bazel_tools//platforms:x86_64"]
|
||||
if repository_ctx.os.name == "linux":
|
||||
target_constraints.append("@bazel_tools//platforms:linux")
|
||||
elif repository_ctx.os.name == "mac os x":
|
||||
target_constraints.append("@bazel_tools//platforms:osx")
|
||||
exec_constraints = list(target_constraints)
|
||||
exec_constraints.append("@io_tweag_rules_haskell//haskell/platforms:nixpkgs")
|
||||
|
||||
compiler_flags_select = repository_ctx.attr.compiler_flags_select or {"//conditions:default": []}
|
||||
locale_archive = repr(repository_ctx.attr.locale_archive or None)
|
||||
|
||||
repository_ctx.file(
|
||||
"BUILD",
|
||||
executable = False,
|
||||
content = """
|
||||
load("@io_tweag_rules_haskell//haskell:toolchain.bzl", "haskell_toolchain")
|
||||
|
||||
haskell_toolchain(
|
||||
name = "toolchain",
|
||||
tools = ["{tools}"],
|
||||
version = "{version}",
|
||||
compiler_flags = {compiler_flags} + {compiler_flags_select},
|
||||
haddock_flags = {haddock_flags},
|
||||
repl_ghci_args = {repl_ghci_args},
|
||||
# On Darwin we don't need a locale archive. It's a Linux-specific
|
||||
# hack in Nixpkgs.
|
||||
locale_archive = {locale_archive},
|
||||
exec_compatible_with = {exec_constraints},
|
||||
target_compatible_with = {target_constraints},
|
||||
)
|
||||
""".format(
|
||||
tools = "@io_tweag_rules_haskell_ghc-nixpkgs//:bin",
|
||||
version = repository_ctx.attr.version,
|
||||
compiler_flags = repository_ctx.attr.compiler_flags,
|
||||
compiler_flags_select = "select({})".format(compiler_flags_select),
|
||||
haddock_flags = repository_ctx.attr.haddock_flags,
|
||||
repl_ghci_args = repository_ctx.attr.repl_ghci_args,
|
||||
locale_archive = locale_archive,
|
||||
exec_constraints = exec_constraints,
|
||||
target_constraints = target_constraints,
|
||||
),
|
||||
)
|
||||
|
||||
_ghc_nixpkgs_toolchain = repository_rule(
|
||||
_ghc_nixpkgs_toolchain_impl,
|
||||
local = False,
|
||||
attrs = {
|
||||
# These attributes just forward to haskell_toolchain.
|
||||
# They are documented there.
|
||||
"version": attr.string(),
|
||||
"compiler_flags": attr.string_list(),
|
||||
"compiler_flags_select": attr.string_list_dict(),
|
||||
"haddock_flags": attr.string_list(),
|
||||
"repl_ghci_args": attr.string_list(),
|
||||
"locale_archive": attr.string(),
|
||||
},
|
||||
)
|
||||
|
||||
def haskell_register_ghc_nixpkgs(
|
||||
version,
|
||||
build_file = None,
|
||||
compiler_flags = None,
|
||||
compiler_flags_select = None,
|
||||
haddock_flags = None,
|
||||
repl_ghci_args = None,
|
||||
locale_archive = None,
|
||||
attribute_path = "haskellPackages.ghc",
|
||||
nix_file = None,
|
||||
nix_file_deps = [],
|
||||
repositories = {}):
|
||||
"""Register a package from Nixpkgs as a toolchain.
|
||||
|
||||
Toolchains can be used to compile Haskell code. To have this
|
||||
toolchain selected during [toolchain
|
||||
resolution][toolchain-resolution], set a host platform that
|
||||
includes the `@io_tweag_rules_haskell//haskell/platforms:nixpkgs`
|
||||
constraint value.
|
||||
|
||||
[toolchain-resolution]: https://docs.bazel.build/versions/master/toolchains.html#toolchain-resolution
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
haskell_register_ghc_nixpkgs(
|
||||
locale_archive = "@glibc_locales//:locale-archive",
|
||||
atttribute_path = "haskellPackages.ghc",
|
||||
version = "1.2.3", # The version of GHC
|
||||
)
|
||||
```
|
||||
|
||||
Setting the host platform can be done on the command-line like
|
||||
in the following:
|
||||
|
||||
```
|
||||
--host_platform=@io_tweag_rules_haskell//haskell/platforms:linux_x86_64_nixpkgs
|
||||
```
|
||||
|
||||
"""
|
||||
haskell_nixpkgs_package(
|
||||
name = "io_tweag_rules_haskell_ghc-nixpkgs",
|
||||
attribute_path = attribute_path,
|
||||
build_file = build_file or "@io_tweag_rules_haskell//haskell:ghc.BUILD",
|
||||
nix_file = nix_file,
|
||||
nix_file_deps = nix_file_deps,
|
||||
repositories = repositories,
|
||||
)
|
||||
_ghc_nixpkgs_toolchain(
|
||||
name = "io_tweag_rules_haskell_ghc-nixpkgs-toolchain",
|
||||
version = version,
|
||||
compiler_flags = compiler_flags,
|
||||
compiler_flags_select = compiler_flags_select,
|
||||
haddock_flags = haddock_flags,
|
||||
repl_ghci_args = repl_ghci_args,
|
||||
locale_archive = locale_archive,
|
||||
)
|
||||
native.register_toolchains("@io_tweag_rules_haskell_ghc-nixpkgs-toolchain//:toolchain")
|
||||
Loading…
Add table
Add a link
Reference in a new issue