From b48b7eba4e4f865562a18cb96641f817c7cbdb60 Mon Sep 17 00:00:00 2001 From: Will Jones Date: Fri, 17 Jul 2020 13:55:48 +0100 Subject: [PATCH] Add support for building fully-static binaries This commit implements support for fully-statically-linked binaries by extending functionality linked to the `is_static` attribute of an active Haskell toolchain. In particular: * Packages built with Cabal will be passed fields that ensure their static artifacts are relocatable (`-fPIC` and `-fexternal-dynamic-refs`). * Intermediate artifacts (such as binaries built by `hsc2hs` for the purposes of generating Haskell code) will also be built statically to avoid issues caused by the absences of dynamic libraries. * Linker flags for REPLs will be generated so that they correctly find static C library dependencies instead of failing/finding dynamic counterparts. --- docs/haskell-use-cases.rst | 171 +++++++++++++++++++++++++++- haskell/cabal.bzl | 32 +++++- haskell/ghc_bindist.bzl | 9 +- haskell/nixpkgs.bzl | 76 ++++++++++++- haskell/private/actions/compile.bzl | 17 ++- haskell/private/cc_libraries.bzl | 13 ++- haskell/private/cc_wrapper.py.tpl | 8 ++ haskell/private/haskell_impl.bzl | 4 +- haskell/repl.bzl | 16 ++- haskell/toolchain.bzl | 19 +++- 10 files changed, 339 insertions(+), 26 deletions(-) diff --git a/docs/haskell-use-cases.rst b/docs/haskell-use-cases.rst index 06a902e2c..e3fbddfb4 100644 --- a/docs/haskell-use-cases.rst +++ b/docs/haskell-use-cases.rst @@ -16,7 +16,7 @@ workspace in the current working directory with a few dummy build targets. See the following sections about customizing the workspace. Making rules_haskell available ----------------------------------- +------------------------------ First of all, the ``WORKSPACE`` file must specify how to obtain rules_haskell. To use a released version, do the following:: @@ -562,8 +562,175 @@ It is worth noting that Bazel's worker strategy is not sandboxed by default. Thi confuse our worker relatively easily. Therefore, it is recommended to supply ``--worker_sandboxing`` to ``bazel build`` -- possibly, via your ``.bazelrc.local`` file. +Building fully-statically-linked binaries +----------------------------------------- + +Fully-statically linked binaries have no runtime linkage dependencies and are +thus typically more portable and easier to package (e.g. in containers) than +their dynamically-linked counterparts. The trade-off is that +fully-statically-linked binaries can be larger than dynamically-linked binaries, +due to the fact that all symbols must be bundled into a single output. +``rules_haskell`` has support for building fully-statically-linked binaries +using Nix-provisioned GHC toolchains and the ``static_runtime`` and +``fully_static_link`` attributes of the ``haskell_register_ghc_nixpkgs`` macro:: + + load( + "@rules_haskell//haskell:nixpkgs.bzl", + "haskell_register_ghc_nixpkgs", + ) + + haskell_register_ghc_nixpkgs( + version = "X.Y.Z", + attribute_path = "staticHaskell.ghc", + repositories = {"nixpkgs": "@nixpkgs"}, + static_runtime = True, + fully_static_link = True, + ) + +Note that the ``attribute_path`` must refer to a GHC derivation capable of +building fully-statically-linked binaries. Often this will require you to +customise a GHC derivation in your Nix package set. If you are unfamiliar with +Nix, one way to add such a custom package to an existing set is with an +*overlay*. Detailed documentation on overlays is available at +https://nixos.wiki/wiki/Overlays, but for the purposes of this documentation, +it's enough to know that overlays are essentially functions which accept package +sets (conventionally called ``super``) and produce new package sets. We can +write an overlay that modifies the ``ghc`` derivation in its argument to add +flags that allow it to produce fully-statically-linked binaries as follows:: + + let + # Pick a version of Nixpkgs that we will base our package set on (apply an + # overlay to). + baseCommit = "..."; # Pick a Nixpkgs version to pin to. + baseSha = "..."; # The SHA of the above version. + + baseNixpkgs = builtins.fetchTarball { + name = "nixos-nixpkgs"; + url = "https://github.com/NixOS/nixpkgs/archive/${baseCommit}.tar.gz"; + sha256 = baseSha; + }; + + # Our overlay. We add a `staticHaskell.ghc` path matching that specified in + # the haskell_register_ghc_nixpkgs rule above which overrides the `ghc` + # derivation provided in the base set (`super.ghc`) with some necessary + # arguments. + overlay = self: super: { + staticHaskell = { + ghc = (super.ghc.override { + enableRelocatedStaticLibs = true; + enableShared = false; + }).overrideAttrs (oldAttrs: { + preConfigure = '' + ${oldAttrs.preConfigure or ""} + echo "GhcLibHcOpts += -fPIC -fexternal-dynamic-refs" >> mk/build.mk + echo "GhcRtsHcOpts += -fPIC -fexternal-dynamic-refs" >> mk/build.mk + ''; + }); + }; + }; + + in + args@{ overlays ? [], ... }: + import baseNixpkgs (args // { + overlays = [overlay] ++ overlays; + }) + +In this example we use the ``override`` and ``overrideAttrs`` functions to +produce a GHC derivation suitable for our needs. Ideally, +``enableRelocatedStaticLibs`` and ``enableShared`` should be enough, but +upstream Nixpkgs does not at present reliably pass ``-fexternal-dynamic-refs`` +when ``-fPIC`` is passed, which is required to generate fully-statically-linked +executables. + +You may wish to base your GHC derivation on one which uses Musl, a C library +designed for static linking (unlike glibc, which can cause issues when linked +statically). `static-haskell-nix`_ is an example of a project which provides +such a GHC derivation and can be used like so:: + + let + baseCommit = "..."; # Pick a Nixpkgs version to pin to. + baseSha = "..."; # The SHA of the above version. + + staticHaskellNixCommit = "..."; Pick a static-haskell-nix version to pin to. + + baseNixpkgs = builtins.fetchTarball { + name = "nixos-nixpkgs"; + url = "https://github.com/NixOS/nixpkgs/archive/${baseCommit}.tar.gz"; + sha256 = baseSha; + }; + + staticHaskellNixpkgs = builtins.fetchTarball + "https://github.com/nh2/static-haskell-nix/archive/${staticHaskellNixCommit}.tar.gz"; + + # The `static-haskell-nix` repository contains several entry points for e.g. + # setting up a project in which Nix is used solely as the build/package + # management tool. We are only interested in the set of packages that underpin + # these entry points, which are exposed in the `survey` directory's + # `approachPkgs` property. + staticHaskellPkgs = ( + import (staticHaskellNixpkgs + "/survey/default.nix") {} + ).approachPkgs; + + overlay = self: super: { + staticHaskell = staticHaskellPkgs.extend (selfSH: superSH: { + ghc = (superSH.ghc.override { + enableRelocatedStaticLibs = true; + enableShared = false; + }).overrideAttrs (oldAttrs: { + preConfigure = '' + ${oldAttrs.preConfigure or ""} + echo "GhcLibHcOpts += -fPIC -fexternal-dynamic-refs" >> mk/build.mk + echo "GhcRtsHcOpts += -fPIC -fexternal-dynamic-refs" >> mk/build.mk + ''; + }); + }); + }; + + in + args@{ overlays ? [], ... }: + import baseNixpkgs (args // { + overlays = [overlay] ++ overlays; + }) + +If you adopt a Musl-based GHC you should also take care to ensure that the C +toolchain used by ``rules_haskell`` also uses Musl; you can do this using the +``nixpkgs_cc_configure`` rule from ``rules_nixpkgs`` and providing a Nix +expression that supplies appropriate ``cc`` and ``binutils`` derivations:: + + nixpkgs_cc_configure( + repository = "@nixpkgs", + + # The `staticHaskell` attribute in the previous example exposes the + # Musl-backed `cc` and `binutils` derivations already, so it's just a + # matter of exposing them to nixpkgs_cc_configure. + nix_file_content = """ + with import { config = {}; overlays = []; }; buildEnv { + name = "bazel-cc-toolchain"; + paths = [ staticHaskell.stdenv.cc staticHaskell.binutils ]; + } + """, + ) + +With the toolchain taken care of, you can then create fully-statically-linked +binaries by passing the ``-optl-static`` and ``-optl-pthread`` flags as +``compiler_flags`` to GHC, e.g. in ``haskell_binary``:: + + haskell_binary( + name = ..., + srcs = [ + ..., + ], + ..., + compiler_flags = [ + "-optl-static", + "-optl-pthread", + ], + ) + +.. _static-haskell-nix: https://github.com/nh2/static-haskell-nix + Containerization with rules_docker -------------------------------------- +---------------------------------- Making use of both ``rules_docker`` and ``rules_nixpkgs``, it's possible to containerize ``rules_haskell`` ``haskell_binary`` build targets for deployment. In a nutshell, first we must use diff --git a/haskell/cabal.bzl b/haskell/cabal.bzl index 745366c8c..48752f8f4 100644 --- a/haskell/cabal.bzl +++ b/haskell/cabal.bzl @@ -165,7 +165,7 @@ def _prepare_cabal_inputs( dynamic = True, ) - # Executables build by Cabal will link Haskell libraries statically, so we + # Executables built by Cabal will link Haskell libraries statically, so we # only need to include dynamic C libraries in the runfiles tree. (_, runfiles_libs) = get_library_files( hs, @@ -230,6 +230,34 @@ def _prepare_cabal_inputs( ], uniquify = True, ) + + # When building in a static context, we need to make sure that Cabal passes + # a couple of options that ensure any static code it builds can be linked + # correctly. + # + # * If we are using a static runtime, we need to ensure GHC generates + # position-independent code (PIC). On Unix we need to pass GHC both + # `-fPIC` and `-fexternal-dynamic-refs`: with `-fPIC` alone, GHC will + # generate `R_X86_64_PC32` relocations on Unix, which prevent loading its + # static libraries as PIC. + # + # * If we are building fully-statically-linked binaries, we need to ensure that + # we pass arguments to `hsc2hs` such that objects it builds are statically + # linked, otherwise we'll get dynamic linking errors when trying to + # execute those objects to generate code as part of the build. Since the + # static configuration should ensure that all the objects involved are + # themselves statically built, this is just a case of passing `-static` to + # the linker used by `hsc2hs` (which will be our own wrapper script which + # eventually calls `gcc`, etc.). + if hs.toolchain.static_runtime: + args.add("--ghc-option=-fPIC") + + if not hs.toolchain.is_windows: + args.add("--ghc-option=-fexternal-dynamic-refs") + + if hs.toolchain.fully_static_link: + args.add("--hsc2hs-option=--lflag=-static") + args.add("--") args.add_all(package_databases, map_each = _dirname, format_each = "--package-db=%s") args.add_all(direct_include_dirs, format_each = "--extra-include-dirs=%s") @@ -359,7 +387,7 @@ def _haskell_cabal_library_impl(ctx): else: profiling_library = None static_library = vanilla_library - if hs.toolchain.is_static: + if hs.toolchain.static_runtime: dynamic_library = None else: dynamic_library = hs.actions.declare_file( diff --git a/haskell/ghc_bindist.bzl b/haskell/ghc_bindist.bzl index 785d8501b..291f28c4c 100644 --- a/haskell/ghc_bindist.bzl +++ b/haskell/ghc_bindist.bzl @@ -304,7 +304,8 @@ haskell_toolchain( tools = [":bin"], libraries = toolchain_libraries, version = "{version}", - is_static = {is_static}, + static_runtime = {static_runtime}, + fully_static_link = {fully_static_link}, compiler_flags = {compiler_flags}, haddock_flags = {haddock_flags}, repl_ghci_args = {repl_ghci_args}, @@ -315,7 +316,11 @@ haskell_toolchain( """.format( toolchain_libraries = toolchain_libraries, version = ctx.attr.version, - is_static = os == "windows", + static_runtime = os == "windows", + + # At present we don't support fully-statically-linked binaries with GHC + # bindists. + fully_static_link = False, compiler_flags = ctx.attr.compiler_flags, haddock_flags = ctx.attr.haddock_flags, repl_ghci_args = ctx.attr.repl_ghci_args, diff --git a/haskell/nixpkgs.bzl b/haskell/nixpkgs.bzl index 85f7bb606..30eac1f76 100644 --- a/haskell/nixpkgs.bzl +++ b/haskell/nixpkgs.bzl @@ -76,7 +76,8 @@ haskell_toolchain( tools = {tools}, libraries = toolchain_libraries, version = "{version}", - is_static = {is_static}, + static_runtime = {static_runtime}, + fully_static_link = {fully_static_link}, compiler_flags = {compiler_flags} + {compiler_flags_select}, haddock_flags = {haddock_flags}, cabalopts = {cabalopts}, @@ -90,7 +91,8 @@ haskell_toolchain( toolchain_libraries = toolchain_libraries, tools = ["@rules_haskell_ghc_nixpkgs//:bin"], version = repository_ctx.attr.version, - is_static = repository_ctx.attr.is_static, + static_runtime = repository_ctx.attr.static_runtime, + fully_static_link = repository_ctx.attr.fully_static_link, compiler_flags = repository_ctx.attr.compiler_flags, compiler_flags_select = compiler_flags_select, haddock_flags = repository_ctx.attr.haddock_flags, @@ -107,7 +109,8 @@ _ghc_nixpkgs_haskell_toolchain = repository_rule( # These attributes just forward to haskell_toolchain. # They are documented there. "version": attr.string(), - "is_static": attr.bool(), + "static_runtime": attr.bool(), + "fully_static_link": attr.bool(), "compiler_flags": attr.string_list(), "compiler_flags_select": attr.string_list_dict(), "haddock_flags": attr.string_list(), @@ -162,7 +165,9 @@ _ghc_nixpkgs_toolchain = repository_rule(_ghc_nixpkgs_toolchain_impl) def haskell_register_ghc_nixpkgs( version, - is_static = False, + is_static = None, # DEPRECATED. See _check_static_attributes_compatibility. + static_runtime = None, + fully_static_link = None, build_file = None, build_file_content = None, compiler_flags = None, @@ -209,6 +214,17 @@ def haskell_register_ghc_nixpkgs( ``` Args: + is_static: Deprecated. The functionality it previously gated + (supporting GHC versions with static runtime systems) now sits under + static_runtime, a name chosen to avoid confusion with the new flag + fully_static_link, which controls support for fully-statically-linked + binaries. During the deprecation period, we rewrite is_static to + static_runtime in this macro as long as the new attributes aren't also + used. This argument and supporting code should be removed in a future release. + static_runtime: True if and only if a static GHC runtime is to be used. This is + required in order to use statically-linked Haskell libraries with GHCi + and Template Haskell. + fully_static_link: True if and only if fully-statically-linked binaries are to be built. compiler_flags_select: temporary workaround to pass conditional arguments. See https://github.com/bazelbuild/bazel/issues/9199 for details. sh_posix_attributes: List of attribute paths to extract standard Unix shell tools from. @@ -219,6 +235,12 @@ def haskell_register_ghc_nixpkgs( haskell_toolchain_repo_name = "rules_haskell_ghc_nixpkgs_haskell_toolchain" toolchain_repo_name = "rules_haskell_ghc_nixpkgs_toolchain" + static_runtime, fully_static_link = _check_static_attributes_compatibility( + is_static = is_static, + static_runtime = static_runtime, + fully_static_link = fully_static_link, + ) + # The package from the system. nixpkgs_package( name = nixpkgs_ghc_repo_name, @@ -237,7 +259,8 @@ def haskell_register_ghc_nixpkgs( _ghc_nixpkgs_haskell_toolchain( name = haskell_toolchain_repo_name, version = version, - is_static = is_static, + static_runtime = static_runtime, + fully_static_link = fully_static_link, compiler_flags = compiler_flags, compiler_flags_select = compiler_flags_select, haddock_flags = haddock_flags, @@ -265,6 +288,49 @@ def haskell_register_ghc_nixpkgs( **sh_posix_nixpkgs_kwargs ) +def _check_static_attributes_compatibility(is_static, static_runtime, fully_static_link): + """Asserts that attributes passed to `haskell_register_ghc_nixpkgs` for + controlling use of GHC's static runtime and whether or not to build + fully-statically-linked binaries are compatible. + + Args: + is_static: Deprecated. The functionality it previously gated + (supporting GHC versions with static runtime systems) now sits under + static_runtime, a name chosen to avoid confusion with the new flag + fully_static_link, which controls support for fully-statically-linked + binaries. During the deprecation period, we rewrite is_static to + static_runtime in this macro as long as the new attributes aren't also + used. This argument and supporting code should be removed in a future release. + static_runtime: True if and only if a static GHC runtime is to be used. This is + required in order to use statically-linked Haskell libraries with GHCi + and Template Haskell. + fully_static_link: True if and only if fully-statically-linked binaries are to be built. + + Returns: + A tuple of static_runtime, fully_static_link attributes, which are guaranteed + not to be None, taking into account the deprecated is_static argument. + """ + + # Check for use of the deprecated `is_static` attribute. + if is_static != None: + if static_runtime != None or fully_static_link != None: + fail("is_static is deprecated. Please use the static_runtime attribute instead.") + + print("WARNING: is_static is deprecated. Please use the static_runtime attribute instead.") + static_runtime = is_static + + # Currently we do not support the combination of a dynamic runtime system + # and fully-statically-linked binaries, so fail if this has been selected. + if not static_runtime and fully_static_link: + fail( + """\ +Fully-statically-linked binaries with a dynamic runtime are not currently supported. +Please pass static_runtime = True if you wish to build fully-statically-linked binaries. +""", + ) + + return bool(static_runtime), bool(fully_static_link) + def _find_children(repository_ctx, target_dir): find_args = [ "find", diff --git a/haskell/private/actions/compile.bzl b/haskell/private/actions/compile.bzl index d1bf0bd1c..cb5b6ece3 100644 --- a/haskell/private/actions/compile.bzl +++ b/haskell/private/actions/compile.bzl @@ -56,6 +56,21 @@ def _process_hsc_file(hs, cc, hsc_flags, hsc_inputs, hsc_file): args.add_all(["--cflag=" + f for f in cc.compiler_flags]) args.add_all(["--cflag=" + f for f in cc.include_args]) args.add_all(["--lflag=" + f for f in cc.linker_flags]) + + # If are building fully-statically-linked binaries, we need to ensure that + # we pass arguments to `hsc2hs` such that objects it builds are statically + # linked, otherwise we'll get dynamic linking errors when trying to execute + # those objects to generate code as part of the build. Since the static + # configuration should ensure that all the objects involved are themselves + # statically built, this is just a case of passing `-static` to the linker + # used by `hsc2hs` (which will be our own wrapper script which eventually + # calls `gcc`, etc.). + # + # Note that we also do this in our Cabal wrapper, where `hsc2hs` might be + # called by Cabal as part of the build process. + if hs.toolchain.fully_static_link: + args.add("--lflag=-static") + args.add_all(hsc_flags) # Add an empty PATH variable if not already specified in hs.env. @@ -258,7 +273,7 @@ def _compilation_defaults(hs, cc, java, posix, dep_info, plugin_dep_info, srcs, # to debug issues in non-sandboxed builds. "-Wmissing-home-modules", ]) - if hs.toolchain.is_static and not hs.toolchain.is_windows: + if hs.toolchain.static_runtime and not hs.toolchain.is_windows: # A static GHC RTS requires -fPIC. However, on Unix we also require # -fexternal-dynamic-refs, otherwise GHC still generates R_X86_64_PC32 # relocations which prevents loading these static libraries as PIC. diff --git a/haskell/private/cc_libraries.bzl b/haskell/private/cc_libraries.bzl index 5cba114eb..dcd54adb6 100644 --- a/haskell/private/cc_libraries.bzl +++ b/haskell/private/cc_libraries.bzl @@ -58,7 +58,7 @@ def get_ghci_library_files(hs, cc_libraries_info, libraries_to_link, include_rea hs, cc_libraries_info, libraries_to_link, - dynamic = not hs.toolchain.is_static, + dynamic = not hs.toolchain.static_runtime, pic = True, include_real_paths = include_real_paths, ) @@ -95,7 +95,7 @@ def get_library_files(hs, cc_libraries_info, libraries_to_link, dynamic = False, pic = dynamic # PIC is irrelevant on static GHC. - pic_required = pic and not hs.toolchain.is_static + pic_required = pic and not hs.toolchain.static_runtime for lib_to_link in libraries_to_link: cc_library_info = cc_libraries_info.libraries[cc_library_key(lib_to_link)] dynamic_lib = None @@ -131,7 +131,7 @@ def get_library_files(hs, cc_libraries_info, libraries_to_link, dynamic = False, return (static_libs, dynamic_libs) -def link_libraries(libs, args, prefix_optl = False): +def link_libraries(libs, args, path_prefix = "", prefix_optl = False): """Add linker flags to link against the given libraries. This function is intended for linking C library dependencies. Haskell @@ -141,15 +141,18 @@ def link_libraries(libs, args, prefix_optl = False): Args: libs: Sequence of File, libraries to link. args: Args or List, append arguments to this object. + path_prefix: String, a prefix to apply to search directory arguments. If + this is a directory, trailing slashes should be included explicitly (this + function will not add them automatically). prefix_optl: Bool, whether to prefix linker flags by -optl """ if prefix_optl: libfmt = "-optl-l%s" - dirfmt = "-optl-L%s" + dirfmt = "-optl-L" + path_prefix + "%s" else: libfmt = "-l%s" - dirfmt = "-L%s" + dirfmt = "-L" + path_prefix + "%s" if hasattr(args, "add_all"): args.add_all(libs, map_each = get_lib_name, format_each = libfmt) diff --git a/haskell/private/cc_wrapper.py.tpl b/haskell/private/cc_wrapper.py.tpl index 036bf3dd6..04aec91d2 100644 --- a/haskell/private/cc_wrapper.py.tpl +++ b/haskell/private/cc_wrapper.py.tpl @@ -46,6 +46,14 @@ used to avoid command line length limitations. See https://gitlab.haskell.org/ghc/ghc/issues/17185. +- Fixes invocations that handle temporary and intermediate binaries + + GHC with Template Haskell or tools like hsc2hs build temporary Haskell + binaries (that e.g. generate other Haskell code) as part of the build + process. This wrapper ensures that linking behaviour for these binaries + matches the characteristics of the wider build (e.g. runpath configuration, + etc.) + """ from bazel_tools.tools.python.runfiles import runfiles as bazel_runfiles diff --git a/haskell/private/haskell_impl.bzl b/haskell/private/haskell_impl.bzl index 219b8cb94..3705f167e 100644 --- a/haskell/private/haskell_impl.bzl +++ b/haskell/private/haskell_impl.bzl @@ -180,7 +180,7 @@ def _haskell_binary_common_impl(ctx, is_test): inspect_coverage = _should_inspect_coverage(ctx, hs, is_test) dynamic = not ctx.attr.linkstatic - if with_profiling or hs.toolchain.is_static: + if with_profiling or hs.toolchain.static_runtime: # NOTE We can't have profiling and dynamic code at the # same time, see: # https://ghc.haskell.org/trac/ghc/ticket/15394 @@ -362,7 +362,7 @@ def haskell_library_impl(ctx): srcs_files, import_dir_map = _prepare_srcs(ctx.attr.srcs) with_shared = not ctx.attr.linkstatic - if with_profiling or hs.toolchain.is_static: + if with_profiling or hs.toolchain.static_runtime: # NOTE We can't have profiling and dynamic code at the # same time, see: # https://ghc.haskell.org/trac/ghc/ticket/15394 diff --git a/haskell/repl.bzl b/haskell/repl.bzl index ee8459f16..d235c4ba7 100644 --- a/haskell/repl.bzl +++ b/haskell/repl.bzl @@ -316,12 +316,26 @@ def _compiler_flags_and_inputs(hs, repl_info, static = False, path_prefix = ""): cc_library_files = _concat(get_library_files(hs, cc_libraries_info, cc_libraries)) else: cc_library_files = get_ghci_library_files(hs, cc_libraries_info, cc_libraries) - link_libraries(cc_library_files, args) + + # REPL scripts `cd` into the workspace root. Depending on their provenance, + # some C libraries' files may be in subdirectories which are _only_ relative + # to the execroot. External static C library dependencies are an example of + # this -- unchanged we may end up with paths like + # `external/some_dependency/lib` and/or + # `bazel-out/k8-fastbuild/bin/_solib_k8/...`; the former containing the + # archive (`.a`) file we want, but only being relative to the execroot, and + # the latter being relative to both the workspace root and the execroot but + # only containing dynamic libraries. + # + # We fix this by prefixing paths with the execroot when generating linker + # flags so that all required libraries are visible. + link_libraries(cc_library_files, args, path_prefix = path_prefix + "/") if static: all_library_files = _concat(get_library_files(hs, cc_libraries_info, all_libraries, include_real_paths = True)) else: all_library_files = get_ghci_library_files(hs, cc_libraries_info, all_libraries, include_real_paths = True) + inputs = depset(transitive = [ repl_info.load_info.source_files, repl_info.dep_info.package_databases, diff --git a/haskell/toolchain.bzl b/haskell/toolchain.bzl index 5fca09280..f19917f33 100644 --- a/haskell/toolchain.bzl +++ b/haskell/toolchain.bzl @@ -168,7 +168,8 @@ def _haskell_toolchain_impl(ctx): libraries = libraries, is_darwin = ctx.attr.is_darwin, is_windows = ctx.attr.is_windows, - is_static = ctx.attr.is_static, + static_runtime = ctx.attr.static_runtime, + fully_static_link = ctx.attr.fully_static_link, version = ctx.attr.version, global_pkg_db = pkgdb_file, protoc = ctx.executable._protoc, @@ -217,8 +218,11 @@ _haskell_toolchain = rule( doc = "Whether compile on and for Windows.", mandatory = True, ), - "is_static": attr.bool( - doc = "Whether GHC was linked statically.", + "static_runtime": attr.bool( + doc = "Whether GHC was linked with a static runtime.", + ), + "fully_static_link": attr.bool( + doc = "Whether GHC should build fully-statically-linked binaries.", ), "locale": attr.string( default = "C.UTF-8", @@ -250,7 +254,8 @@ Label pointing to the locale archive file to use. Mostly useful on NixOS. def haskell_toolchain( name, version, - is_static, + static_runtime, + fully_static_link, tools, libraries, compiler_flags = [], @@ -274,7 +279,8 @@ def haskell_toolchain( haskell_toolchain( name = "ghc", version = "1.2.3", - is_static = is_static, + static_runtime = static_runtime, + fully_static_link = fully_static_link, tools = ["@sys_ghc//:bin"], compiler_flags = ["-Wall"], ) @@ -296,7 +302,8 @@ def haskell_toolchain( _haskell_toolchain( name = name, version = version, - is_static = is_static, + static_runtime = static_runtime, + fully_static_link = fully_static_link, tools = tools, libraries = libraries, compiler_flags = compiler_flags,