mirror of
https://github.com/digital-asset/daml.git
synced 2024-11-10 10:46:11 +03:00
d2e2c21684
New year, new copyright, new expected unknown issues with various files that won't be covered by the script and/or will be but shouldn't change. I'll do the details on Jan 1, but would appreciate this being preapproved so I can actually get it merged by then. CHANGELOG_BEGIN CHANGELOG_END
306 lines
9.1 KiB
Python
306 lines
9.1 KiB
Python
# Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||
# SPDX-License-Identifier: Apache-2.0
|
||
|
||
load(
|
||
"@rules_haskell//haskell:defs.bzl",
|
||
"haskell_binary",
|
||
"haskell_library",
|
||
"haskell_repl",
|
||
"haskell_test",
|
||
)
|
||
load(
|
||
"@rules_haskell//haskell:c2hs.bzl",
|
||
"c2hs_library",
|
||
)
|
||
load("//bazel_tools:hlint.bzl", "haskell_hlint")
|
||
load("@os_info//:os_info.bzl", "is_windows")
|
||
|
||
# This file defines common Haskell language extensions and compiler flags used
|
||
# throughout this repository. The initial set of flags is taken from the
|
||
# daml-foundations project. If you find that additional flags are required for
|
||
# another project, consider whether all projects could benefit from these
|
||
# changes. If so, add them here.
|
||
#
|
||
# Use the macros `da_haskell_*` defined in this file, instead of stock rules
|
||
# `haskell_*` from `rules_haskell` in order for these default flags to take
|
||
# effect.
|
||
|
||
common_haskell_exts = [
|
||
"BangPatterns",
|
||
"DeriveDataTypeable",
|
||
"DeriveFoldable",
|
||
"DeriveFunctor",
|
||
"DeriveGeneric",
|
||
"DeriveTraversable",
|
||
"FlexibleContexts",
|
||
"GeneralizedNewtypeDeriving",
|
||
"LambdaCase",
|
||
"NamedFieldPuns",
|
||
"NumericUnderscores",
|
||
"OverloadedStrings",
|
||
"PackageImports",
|
||
"RecordWildCards",
|
||
"ScopedTypeVariables",
|
||
"StandaloneDeriving",
|
||
"TupleSections",
|
||
"TypeApplications",
|
||
"ViewPatterns",
|
||
]
|
||
|
||
common_haskell_flags = [
|
||
"-Wall",
|
||
"-Werror",
|
||
"-Wincomplete-uni-patterns",
|
||
"-Wno-name-shadowing",
|
||
"-fno-omit-yields",
|
||
"-fno-ignore-asserts",
|
||
]
|
||
|
||
# Passing these to libraries produces a (harmless but annoying) warning.
|
||
common_binary_haskell_flags = common_haskell_flags + [
|
||
"-threaded",
|
||
"-rtsopts",
|
||
# run on two cores, disable idle & parallel GC
|
||
"-with-rtsopts=-N2 -qg -I0",
|
||
]
|
||
|
||
def _wrap_rule(rule, common_flags, name = "", deps = [], hackage_deps = [], compiler_flags = [], **kwargs):
|
||
ext_flags = ["-X%s" % ext for ext in common_haskell_exts]
|
||
stackage_libs = ["@stackage//:{}".format(dep) for dep in hackage_deps]
|
||
rule(
|
||
name = name,
|
||
compiler_flags = ext_flags + common_flags + compiler_flags,
|
||
deps = stackage_libs + deps,
|
||
**kwargs
|
||
)
|
||
|
||
# We don't fetch HLint on Windows
|
||
if not is_windows:
|
||
haskell_hlint(
|
||
name = name + "@hlint",
|
||
deps = [name],
|
||
testonly = True,
|
||
)
|
||
|
||
# Load Main module on executable rules.
|
||
repl_ghci_commands = []
|
||
if "main_function" in kwargs:
|
||
main_module = ".".join(kwargs["main_function"].split(".")[:-1])
|
||
repl_ghci_commands = [
|
||
":m " + main_module,
|
||
]
|
||
da_haskell_repl(
|
||
name = name + "@ghci",
|
||
deps = [name],
|
||
repl_ghci_commands = repl_ghci_commands,
|
||
testonly = kwargs.get("testonly", False),
|
||
visibility = ["//visibility:public"],
|
||
)
|
||
|
||
def da_haskell_library(**kwargs):
|
||
"""
|
||
Define a Haskell library.
|
||
|
||
Allows to define Hackage dependencies using `hackage_deps`,
|
||
applies common Haskell options defined in `bazel_tools/haskell.bzl`
|
||
and forwards to `haskell_library` from `rules_haskell`.
|
||
Refer to the [`rules_haskell` documentation][rules_haskell_docs].
|
||
|
||
[rules_haskell_docs]: https://api.haskell.build/
|
||
|
||
Example:
|
||
```
|
||
da_haskell_library(
|
||
name = "example",
|
||
src_strip_prefix = "src",
|
||
srcs = glob(["src/**/*.hs"]),
|
||
hackage_deps = [
|
||
"base",
|
||
"text",
|
||
],
|
||
deps = [
|
||
"//some/package:target",
|
||
],
|
||
visibility = ["//visibility:public"],
|
||
)
|
||
```
|
||
"""
|
||
_wrap_rule(haskell_library, common_haskell_flags, **kwargs)
|
||
|
||
def da_haskell_binary(main_function = "Main.main", **kwargs):
|
||
"""
|
||
Define a Haskell executable.
|
||
|
||
Allows to define Hackage dependencies using `hackage_deps`,
|
||
applies common Haskell options defined in `bazel_tools/haskell.bzl`
|
||
and forwards to `haskell_binary` from `rules_haskell`.
|
||
Refer to the [`rules_haskell` documentation][rules_haskell_docs].
|
||
|
||
[rules_haskell_docs]: https://api.haskell.build/
|
||
|
||
Example:
|
||
```
|
||
da_haskell_binary(
|
||
name = "example",
|
||
src_strip_prefix = "src",
|
||
srcs = glob(["src/**/*.hs"]),
|
||
hackage_deps = [
|
||
"base",
|
||
"text",
|
||
],
|
||
deps = [
|
||
"//some/package:target",
|
||
],
|
||
visibility = ["//visibility:public"],
|
||
)
|
||
```
|
||
"""
|
||
_wrap_rule(
|
||
haskell_binary,
|
||
common_binary_haskell_flags,
|
||
# Make this argument explicit, so we can distinguish library and
|
||
# executable rules in _wrap_rule.
|
||
main_function = main_function,
|
||
**kwargs
|
||
)
|
||
|
||
def da_haskell_test(main_function = "Main.main", testonly = True, **kwargs):
|
||
"""
|
||
Define a Haskell test suite.
|
||
|
||
Allows to define Hackage dependencies using `hackage_deps`,
|
||
applies common Haskell options defined in `bazel_tools/haskell.bzl`
|
||
and forwards to `haskell_test` from `rules_haskell`.
|
||
Refer to the [`rules_haskell` documentation][rules_haskell_docs].
|
||
|
||
[rules_haskell_docs]: https://api.haskell.build/
|
||
|
||
Example:
|
||
```
|
||
da_haskell_test(
|
||
name = "example",
|
||
src_strip_prefix = "src",
|
||
srcs = glob(["src/**/*.hs"]),
|
||
hackage_deps = [
|
||
"base",
|
||
"text",
|
||
],
|
||
deps = [
|
||
"//some/package:target",
|
||
],
|
||
visibility = ["//visibility:public"],
|
||
)
|
||
```
|
||
"""
|
||
_wrap_rule(
|
||
haskell_test,
|
||
common_binary_haskell_flags,
|
||
# Make this argument explicit, so we can distinguish library and
|
||
# executable rules in _wrap_rule.
|
||
main_function = main_function,
|
||
# Make this argument explicit, so we can distinguish test targets
|
||
# in _wrap_rule.
|
||
testonly = testonly,
|
||
**kwargs
|
||
)
|
||
|
||
def da_haskell_repl(**kwargs):
|
||
"""
|
||
Define a Haskell repl.
|
||
|
||
Applies common Haskell options defined in `bazel_tools/haskell.bzl`
|
||
and forwards to `haskell_repl` from `rules_haskell`.
|
||
Refer to the [`rules_haskell` documentation][rules_haskell_docs].
|
||
|
||
[rules_haskell_docs]: https://api.haskell.build/
|
||
|
||
Example:
|
||
```
|
||
da_haskell_repl(
|
||
name = "repl",
|
||
# Load these packages and their dependencies by source.
|
||
# Will only load packages from the local workspace by source.
|
||
deps = [
|
||
"//some/package:target_a",
|
||
"//some/package:target_b",
|
||
],
|
||
# (optional) only load targets matching these patterns by source.
|
||
experimental_from_source = [
|
||
"//some/package/...",
|
||
"//some/other/package/...",
|
||
],
|
||
# (optional) don't load targets matching these patterns by source.
|
||
experimental_from_binary = [
|
||
"//some/vendored/package/...",
|
||
],
|
||
# (optional) Pass extra arguments to ghci.
|
||
repl_ghci_args = [
|
||
"-fexternal-interpreter",
|
||
],
|
||
# (optional) Make runfiles available to the REPL, or not.
|
||
collect_data = True,
|
||
)
|
||
```
|
||
|
||
"""
|
||
|
||
# Set default arguments
|
||
with_defaults = dict(
|
||
# Whether to make runfiles, such as the daml stdlib, available to the
|
||
# REPL. Pass --define ghci_data=True to enable.
|
||
collect_data = select({
|
||
"//:ghci_data": True,
|
||
"//conditions:default": False,
|
||
}),
|
||
experimental_from_binary = ["//nix/..."],
|
||
repl_ghci_args = [
|
||
"-fexternal-interpreter",
|
||
"-j",
|
||
"+RTS",
|
||
"-I0",
|
||
"-n2m",
|
||
"-A128m",
|
||
"-qb0",
|
||
"-RTS",
|
||
],
|
||
)
|
||
with_defaults.update(kwargs)
|
||
|
||
# The common_haskell_exts and common_haskell_flags are already passed on
|
||
# the library/binary/test rule wrappers. haskell_repl will pick these up
|
||
# automatically, if such targets are loaded by source.
|
||
# Right now we don't set any default flags.
|
||
haskell_repl(**with_defaults)
|
||
|
||
def _sanitize_string_for_usage(s):
|
||
res_array = []
|
||
for idx in range(len(s)):
|
||
c = s[idx]
|
||
if c.isalnum() or c == ".":
|
||
res_array.append(c)
|
||
else:
|
||
res_array.append("_")
|
||
return "".join(res_array)
|
||
|
||
def c2hs_suite(name, hackage_deps, deps = [], srcs = [], c2hs_srcs = [], c2hs_src_strip_prefix = "", **kwargs):
|
||
ts = []
|
||
for file in c2hs_srcs:
|
||
n = _sanitize_string_for_usage(file)
|
||
c2hs_library(
|
||
name = n,
|
||
srcs = [file],
|
||
deps = deps + [":" + t for t in ts],
|
||
src_strip_prefix = c2hs_src_strip_prefix,
|
||
# language-c fails to pass mingw’s intrinsic-impl.h header if
|
||
# we do not unset this option.
|
||
extra_args = ["-C-U__GCC_ASM_FLAG_OUTPUTS__"] if is_windows else [],
|
||
)
|
||
ts.append(n)
|
||
da_haskell_library(
|
||
name = name,
|
||
srcs = [":" + t for t in ts] + srcs,
|
||
deps = deps,
|
||
hackage_deps = hackage_deps,
|
||
**kwargs
|
||
)
|