diff --git a/haskell/haskell.bzl b/haskell/haskell.bzl index 18aff6539..a6ed7c87a 100644 --- a/haskell/haskell.bzl +++ b/haskell/haskell.bzl @@ -4,6 +4,7 @@ load(":private/providers.bzl", "HaskellBuildInfo", "HaskellLibraryInfo", "HaskellBinaryInfo", + "HaskellPrebuiltPackageInfo", "HaskellProtobufInfo", "CcSkylarkApiProviderHacked", ) @@ -226,6 +227,45 @@ $ bazel-bin/.../hello-lib-repl # run the script ``` """ +def _haskell_import_impl(ctx): + if ctx.attr.package: + package = ctx.attr.package + else: + package = ctx.label.name + return [HaskellPrebuiltPackageInfo(package = package)] + +"""Wrap a prebuilt dependency as a rule. + +Example: + ```bzl + haskell_import( + name = "base_pkg", + package = "base", + ) + haskell_library( + name = "hello-lib", + srcs = ["Lib.hs"], + deps = [ + ":base_pkg", + "//hello-sublib:lib", + ], + ) + ``` + +This rule may wrap any prebuilt dependencies, i.e., GHC packages that aren't +supplied by Bazel. Depending on the wrapped rule eliminates the need to list +the package name in prebuilt_dependencies. + +Often, rules of this type will be generated automatically by frameworks such +as Hazel. +""" +haskell_import = rule( + _haskell_import_impl, + attrs = dict( + package = attr.string(doc = "A non-Bazel-supplied GHC package name. Defaults to the name of the rule."), + ), +) + haskell_doc = _haskell_doc haskell_lint = _haskell_lint diff --git a/haskell/private/dependencies.bzl b/haskell/private/dependencies.bzl index c338f347e..de1a22b5c 100644 --- a/haskell/private/dependencies.bzl +++ b/haskell/private/dependencies.bzl @@ -3,6 +3,7 @@ load(":private/providers.bzl", "HaskellBuildInfo", "HaskellBinaryInfo", "HaskellLibraryInfo", + "HaskellPrebuiltPackageInfo", "CcSkylarkApiProviderHacked", ) load(":private/set.bzl", "set") @@ -95,6 +96,19 @@ def gather_dep_info(ctx): external_libraries = dicts.add(acc.external_libraries, binfo.external_libraries), direct_prebuilt_deps = acc.direct_prebuilt_deps, ) + elif HaskellPrebuiltPackageInfo in dep: + pkg = dep[HaskellPrebuiltPackageInfo].package + acc = HaskellBuildInfo( + package_ids = acc.package_ids, + package_confs = acc.package_confs, + package_caches = acc.package_caches, + static_libraries = acc.static_libraries, + dynamic_libraries = acc.dynamic_libraries, + interface_files = acc.interface_files, + prebuilt_dependencies = set.mutable_insert(acc.prebuilt_dependencies, pkg), + external_libraries = acc.external_libraries, + direct_prebuilt_deps = set.mutable_insert(acc.direct_prebuilt_deps, pkg), + ) else: # If not a Haskell dependency, pass it through as-is to the # linking phase. diff --git a/haskell/private/providers.bzl b/haskell/private/providers.bzl index 885f55647..c37939742 100644 --- a/haskell/private/providers.bzl +++ b/haskell/private/providers.bzl @@ -60,6 +60,13 @@ HaskellBinaryInfo = provider( }, ) +HaskellPrebuiltPackageInfo = provider( + doc = "Information about a prebuilt GHC package.", + fields = { + "package": "Package name", + }, +) + HaddockInfo = provider( doc = "Haddock information.", fields = { diff --git a/tests/haskell_import/BUILD b/tests/haskell_import/BUILD new file mode 100644 index 000000000..f7dd82886 --- /dev/null +++ b/tests/haskell_import/BUILD @@ -0,0 +1,35 @@ +package(default_testonly = 1) + +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_import", + "haskell_test", +) + +haskell_import( + name = "bytestring", +) + +haskell_import( + name = "text_pkg", + package = "text", +) + +haskell_library( + name = "Lib", + srcs = ["Lib.hs"], + prebuilt_dependencies = ["base"], + deps = [":bytestring"], +) + +haskell_test( + name = "binary", + srcs = ["Bin.hs"], + main_file = "Bin.hs", + prebuilt_dependencies = ["base"], + deps = [ + ":text_pkg", + ":Lib", + ], +) diff --git a/tests/haskell_import/Bin.hs b/tests/haskell_import/Bin.hs new file mode 100644 index 000000000..a0e7117d2 --- /dev/null +++ b/tests/haskell_import/Bin.hs @@ -0,0 +1,8 @@ +module Main (main) where + +import qualified Data.Text.IO as T +import qualified Data.Text.Encoding as E + +import Lib (message) + +main = T.putStrLn $ E.decodeUtf8 message diff --git a/tests/haskell_import/Lib.hs b/tests/haskell_import/Lib.hs new file mode 100644 index 000000000..66a2161a1 --- /dev/null +++ b/tests/haskell_import/Lib.hs @@ -0,0 +1,5 @@ +module Lib (message) where + +import qualified Data.ByteString.Char8 as B + +message = B.pack "hello, world"