diff --git a/hazel.bzl b/hazel.bzl index 9d5b26c..3f3ccd1 100644 --- a/hazel.bzl +++ b/hazel.bzl @@ -8,9 +8,12 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", ) +load("//tools:ghc.bzl", "get_ghc_workspace", "default_ghc_workspaces") load("//tools:mangling.bzl", "hazel_binary", "hazel_library", "hazel_workspace") def _cabal_haskell_repository_impl(ctx): + ghc_workspace = get_ghc_workspace(ctx.attr.ghc_workspaces, ctx) + pkg = "{}-{}".format(ctx.attr.package_name, ctx.attr.package_version) url = "https://hackage.haskell.org/package/{}.tar.gz".format(pkg) # If the SHA is wrong, the error message is very unhelpful: @@ -31,7 +34,7 @@ def _cabal_haskell_repository_impl(ctx): symlink_and_invoke_hazel( ctx, ctx.attr.hazel_base_repo_name, - ctx.attr.ghc_workspace, + ghc_workspace, ctx.attr.package_flags, ctx.attr.package_name + ".cabal", "package.bzl" @@ -45,7 +48,7 @@ _cabal_haskell_repository = repository_rule( "package_flags": attr.string_dict(mandatory=True), "hazel_base_repo_name": attr.string(mandatory=True), "sha256": attr.string(mandatory=True), - "ghc_workspace": attr.string(mandatory=True), + "ghc_workspaces": attr.string_dict(mandatory=True), }) def _core_library_repository_impl(ctx): @@ -110,7 +113,7 @@ def hazel_repositories( extra_libs_hdrs={}, extra_libs_strip_include_prefix={}, exclude_packages=[], - ghc_workspace="@ghc"): + ghc_workspaces=default_ghc_workspaces): """Generates external dependencies for a set of Haskell packages. This macro should be invoked in the WORKSPACE. It generates a set of @@ -138,7 +141,10 @@ def hazel_repositories( extra_libs_hdrs: Similar to extra_libs, but provides header files. extra_libs_strip_include_prefix: Similar to extra_libs, but allows to get include prefix to strip. - ghc_workspace: Workspace in which GHC is provided. Default "@ghc". + ghc_workspaces: Dictionary mapping OS names to GHC workspaces. + Default: Linux/MacOS: "@ghc", Windows: "@ghc_windows". + Dictionary keys correspond to CPU values as returned by + `get_cpu_value` from `@bazel_tools//tools/cpp:lib_cc_configure.bzl`. """ hazel_base_repo_name = "hazel_base_repository" @@ -146,7 +152,7 @@ def hazel_repositories( hazel_base_repository( name = hazel_base_repo_name, - ghc="{}//:bin/ghc".format(ghc_workspace), + ghc_workspaces = ghc_workspaces, extra_libs = extra_libs, extra_libs_hdrs = extra_libs_hdrs, extra_libs_strip_include_prefix = extra_libs_strip_include_prefix, @@ -173,7 +179,7 @@ def hazel_repositories( package_flags = flags, sha256 = pkgs[p].sha256 if hasattr(pkgs[p], "sha256") else None, hazel_base_repo_name = hazel_base_repo_name, - ghc_workspace = ghc_workspace, + ghc_workspaces = ghc_workspaces, ) for p in core_packages: diff --git a/hazel_base_repository/hazel_base_repository.bzl b/hazel_base_repository/hazel_base_repository.bzl index 472e384..fed5767 100644 --- a/hazel_base_repository/hazel_base_repository.bzl +++ b/hazel_base_repository/hazel_base_repository.bzl @@ -1,5 +1,9 @@ +load("//tools:ghc.bzl", "get_ghc_workspace", "get_executable_name") + def _hazel_base_repository_impl(ctx): - ctx.symlink(ctx.attr.ghc, "ghc") + ghc_workspace = get_ghc_workspace(ctx.attr.ghc_workspaces, ctx) + ghc_label = get_executable_name("{}//:bin/ghc".format(ghc_workspace), ctx) + ghc = ctx.path(Label(ghc_label)) cabal2bazel_srcs = [ "@ai_formation_hazel//hazel_base_repository:cabal2bazel.hs", @@ -13,7 +17,7 @@ def _hazel_base_repository_impl(ctx): ctx.symlink(Label(f), l.name) res = ctx.execute([ - "./ghc", + ghc, "-Wall", "-Werror", # Only use core packages of GHC, nothing from the the user level: @@ -26,7 +30,7 @@ def _hazel_base_repository_impl(ctx): if res.return_code != 0: fail("Couldn't build cabal2bazel:\n{}\n{}".format(res.stdout,res.stderr)) - res = ctx.execute(["./ghc", "--numeric-version"]) + res = ctx.execute([ghc, "--numeric-version"]) if res.return_code != 0: fail("Couldn't get GHC version:\n{}\n{}".format(res.stdout,res.stderr)) @@ -53,7 +57,7 @@ extra_libs_strip_include_prefix = {} hazel_base_repository = repository_rule( implementation=_hazel_base_repository_impl, attrs={ - "ghc": attr.label(mandatory=True), + "ghc_workspaces": attr.string_dict(mandatory=True), "extra_libs": attr.string_dict(mandatory=True), "extra_libs_hdrs": attr.string_dict(mandatory=True), "extra_libs_strip_include_prefix": attr.string_dict(mandatory=True), diff --git a/tools/ghc.bzl b/tools/ghc.bzl new file mode 100644 index 0000000..47b19aa --- /dev/null +++ b/tools/ghc.bzl @@ -0,0 +1,26 @@ +load("@bazel_tools//tools/cpp:lib_cc_configure.bzl", "get_cpu_value") + +default_ghc_workspaces = { + "k8": "@ghc", + "darwin": "@ghc", + "x64_windows": "@ghc_windows", +} + +def get_ghc_workspace(ghc_workspaces, repository_ctx): + """Return the GHC workspace appropriate for the current OS.""" + cpu_value = get_cpu_value(repository_ctx) + if cpu_value not in ghc_workspaces: + fail("No known GHC workspace for CPU {} in {}".format( + cpu_value, ghc_workspaces)) + return ghc_workspaces[cpu_value] + + +def get_executable_name(name, repository_ctx): + """Return the executable name for the current platform. + + On Windows, appends `.exe` to `name`. Otherwise, returns `name`. + """ + if get_cpu_value(repository_ctx) == "x64_windows": + return "%s.exe"%name + else: + return name