From e1f8c4e2e438ab849567d7e7cac36197a2537b54 Mon Sep 17 00:00:00 2001 From: Yves-Stan Le Cornec Date: Thu, 22 Jun 2023 18:56:35 +0200 Subject: [PATCH] wip --- extensions/haskell_toolchains.bzl | 45 ++--- haskell/ghc_bindist.bzl | 5 - rules_haskell_nix/MODULE.bazel | 16 +- rules_haskell_nix/declare_toolchains.bzl | 11 +- .../extensions/nix_haskell_toolchains.bzl | 161 +++++++----------- rules_haskell_tests/MODULE.bazel | 46 +++-- 6 files changed, 130 insertions(+), 154 deletions(-) diff --git a/extensions/haskell_toolchains.bzl b/extensions/haskell_toolchains.bzl index 4b420a9efc..cb7cf23d23 100644 --- a/extensions/haskell_toolchains.bzl +++ b/extensions/haskell_toolchains.bzl @@ -38,41 +38,17 @@ _bindist_tag = tag_class( ) def _all_toolchains_impl(rctx): - # toolchains = [] - # for (i, toolchain) in enumerate(rctx.attr.toolchains): - # # Registering toolchains with alias does not work yet, so we copy the content of the BUILD files. - # # https://github.com/bazelbuild/bazel/issues/16298 - # build_file = Label("@@{}//:BUILD".format(toolchain.workspace_name)) - # s = rctx.read(rctx.path(build_file)) - # print("BUILD=", s) - - # toolchains = [ - # """ - # alias( - # name = "toolchain_{i}", - # actual = {actual}, - # ) - # """.format(i = i, actual = repr(str(toolchain))) - # for (i, toolchain) in enumerate(rctx.attr.toolchains) - # ] - # rctx.file("BUILD.bazel", content = "\n".join(toolchains)) content = "\n".join(rctx.attr.toolchains) - print("content=", content) rctx.file("BUILD.bazel", content = content) _all_toolchains = repository_rule( implementation = _all_toolchains_impl, attrs = { - # "toolchains": attr.label_list(), "toolchains": attr.string_list(), }, ) def _haskell_toolchains_impl(mctx): - # We only consider the first `bindists` tag, because subsequent - # ones would have the same constraints and lower priority. - found_bindists = False - # Instead of creating one external repository for each `toolchain(...)` declaration, # we recover them in a list and declare them all in the `all_bindist_toolchains` repository. # In a way that respects @@ -83,11 +59,22 @@ def _haskell_toolchains_impl(mctx): # if/once the following issue is resolved # https://github.com/bazelbuild/bazel/issues/16298 toolchain_declarations = [] + toolchain_names = [] + found_bindists = False for module_index, module in enumerate(mctx.modules): for bindist_tag_index, bindist_tag in enumerate(module.tags.bindist): - name = "bindist_{}_{}_{}".format(module_index, bindist_tag_index, bindist_tag.name) - toolchain_declarations.append("# module:{} tag:bindist_{}".format(module.name, bindist_tag_index)) + name = "bindist_{}_{}_{}".format(module.name, module.version, bindist_tag.name) + if name in toolchain_names: + fail( + """module "{module}~{version}" used the "bindist" tag twice with the "{tag_name}" name""".format( + tag_name = bindist_tag.name, + module = module.name, + version = module.version, + ), + ) + else: + toolchain_names.append(name) ghc_bindist( name = name, version = bindist_tag.version, @@ -101,10 +88,11 @@ def _haskell_toolchains_impl(mctx): toolchain_declarations = toolchain_declarations, ) - for bindists_tag_index, bindists_tag in enumerate(module.tags.bindists): + for bindists_tag in module.tags.bindists: + # We only consider the first `bindists` tag, because subsequent + # ones would have the same constraints and lower priority. if not found_bindists: found_bindists = True - toolchain_declarations.append("# module:{} tag:bindists_{}".format(module.name, bindists_tag_index)) haskell_register_ghc_bindists( version = bindists_tag.version, ghcopts = bindists_tag.ghcopts, @@ -115,7 +103,6 @@ def _haskell_toolchains_impl(mctx): register = False, toolchain_declarations = toolchain_declarations, ) - # all_bindists.extend(toolchain_declarations) _all_toolchains( name = "all_bindist_toolchains", diff --git a/haskell/ghc_bindist.bzl b/haskell/ghc_bindist.bzl index ca2f9f2e0d..8455795a90 100644 --- a/haskell/ghc_bindist.bzl +++ b/haskell/ghc_bindist.bzl @@ -452,11 +452,6 @@ def ghc_bindist( locale = locale, **extra_attrs ) - ghc_bindist_toolchain_kwargs = { - "name": toolchain_name, - "bindist_name": bindist_name, - "target": target, - } if toolchain_declarations == None: _ghc_bindist_toolchain( name = toolchain_name, diff --git a/rules_haskell_nix/MODULE.bazel b/rules_haskell_nix/MODULE.bazel index caefb6779f..10b44086b6 100644 --- a/rules_haskell_nix/MODULE.bazel +++ b/rules_haskell_nix/MODULE.bazel @@ -8,6 +8,11 @@ bazel_dep( version = "0.16", ) +bazel_dep( + name = "rules_sh", + version = "0.3.0", +) + bazel_dep( name = "rules_nixpkgs_core", version = "0.9.0", @@ -46,11 +51,8 @@ nix_haskell_toolchains.config( use_repo( nix_haskell_toolchains, - # "all_nix_toolchains", - # "nix_toolchain_0_0_name_ghc_nixpkgs", - # "nix_toolchain_1_0_name_ghc_nixpkgs", - # "nix_toolchain_0_0_nix_toolchain_from_tests_ghc_nixpkgs", "hub", + "all_posix_toolchains", ) declare_nix_toolchains = use_extension( @@ -58,8 +60,12 @@ declare_nix_toolchains = use_extension( "declare_nix_toolchains", ) -use_repo(declare_nix_toolchains, "all_nix_toolchains") +use_repo( + declare_nix_toolchains, + "all_nix_toolchains", +) register_toolchains( "@all_nix_toolchains//:all", + "@all_posix_toolchains//:all", ) diff --git a/rules_haskell_nix/declare_toolchains.bzl b/rules_haskell_nix/declare_toolchains.bzl index 58b7d0e0a5..612bfc20d5 100644 --- a/rules_haskell_nix/declare_toolchains.bzl +++ b/rules_haskell_nix/declare_toolchains.bzl @@ -1,7 +1,6 @@ load( "@hub//:nix_ghcs.bzl", "ghc_labels", - "toolchain_configs", "toolchain_keys", "toolchains_2", ) @@ -9,7 +8,6 @@ load("@rules_haskell_nix//:nixpkgs.bzl", "register_ghc_from_nixpkgs_package") def _nix_toolchains_repo_impl(rctx): content = "\n".join(rctx.attr.toolchain_declarations) - print("content=", content) rctx.file("BUILD.bazel", content = content) _nix_toolchains_repo = repository_rule( @@ -20,7 +18,13 @@ _nix_toolchains_repo = repository_rule( ) def _declare_nix_toolchains_impl(mctx): - print("os from extension=", mctx.os.name) + # Instead of creating one external repository for each `toolchain(...)` declaration, + # we recover them in a list and declare them all in the `all_bindist_toolchains` repository. + # Following bazel's iteration order over modules so that toolchains declared by the root module take precedence + + # an alternative would be to use aliases to the (to get rid of the toolchain_declarations parameter) + # if/once the following issue is resolved + # https://github.com/bazelbuild/bazel/issues/16298 toolchain_declarations = [] for toolchain in toolchain_keys: kwargs = dict(toolchains_2[toolchain]) @@ -29,7 +33,6 @@ def _declare_nix_toolchains_impl(mctx): kwargs["nixpkgs_ghc"] = ghc_labels[toolchain] kwargs["module_ctx"] = mctx register_ghc_from_nixpkgs_package(**kwargs) - print("toolchain_declarations=", toolchain_declarations) _nix_toolchains_repo( name = "all_nix_toolchains", toolchain_declarations = toolchain_declarations, diff --git a/rules_haskell_nix/extensions/nix_haskell_toolchains.bzl b/rules_haskell_nix/extensions/nix_haskell_toolchains.bzl index bb693f0d8a..56e48b4642 100644 --- a/rules_haskell_nix/extensions/nix_haskell_toolchains.bzl +++ b/rules_haskell_nix/extensions/nix_haskell_toolchains.bzl @@ -1,16 +1,50 @@ -load( - "@rules_haskell_nix//:nixpkgs.bzl", - "haskell_register_ghc_nixpkgs", -) load( "@rules_nixpkgs_posix//:posix.bzl", "nixpkgs_sh_posix_configure", ) +load( + "@rules_nixpkgs_core//:util.bzl", + "default_constraints", + "ensure_constraints_pure", +) load( "@rules_nixpkgs_core//:nixpkgs.bzl", "nixpkgs_package", ) +# Based on _nixpkgs_sh_posix_toolchain from +# https://github.com/tweag/rules_nixpkgs/blob/420370f64f03ed9c1ff9b5e2994d06c0439cb1f2/toolchains/posix/posix.bzl#LL109C1-L128C1 +# Until the api is modified to register posix toolchains another way (maybe direcly via a module extension from rules_nixpkgs) +# or we can register the toolchains via an alias (https://github.com/bazelbuild/bazel/issues/16298) +def _nixpkgs_sh_posix_toolchain_str(mctx, name, workspace, exec_constraints = []): + exec_constraints, _ = ensure_constraints_pure( + default_constraints = default_constraints(mctx), + exec_constraints = exec_constraints, + ) + return """ +toolchain( + name = "{name}", + toolchain = "@{workspace}//:nixpkgs_sh_posix", + toolchain_type = "@rules_sh//sh/posix:toolchain_type", + exec_compatible_with = {exec_constraints}, + target_compatible_with = [], +) + """.format( + name = name, + workspace = workspace, + exec_constraints = exec_constraints, + ) + +def _all_posix_toolchains_impl(rctx): + rctx.file("BUILD.bazel", content = "\n".join(rctx.attr.toolchains)) + +_all_posix_toolchains = repository_rule( + implementation = _all_posix_toolchains_impl, + attrs = { + "toolchains": attr.string_list(), + }, + doc = "repository containing `toolchain` declarations for associated posix tooolchains that need to be registered", +) _config_tag = tag_class( attrs = { "version": attr.string( @@ -49,90 +83,54 @@ _config_tag = tag_class( doc = "creates a new toolchain ", ) -# def _all_toolchains_impl(rctx): -# content = "\n".join(rctx.attr.toolchains) -# print("content=", content) -# rctx.file("BUILD.bazel", content = content) - -# _all_toolchains = repository_rule( -# implementation = _all_toolchains_impl, -# attrs = { -# "toolchains": attr.string_list(), -# }, -# ) - def _hub_impl(rctx): rctx.file("BUILD") - toolchain_items = ["{}:{}".format(k, json.decode(v)) for k, v in rctx.attr.toolchains.items()] - - # print(toolchain_items) - ghc_labels_items = ["{}:{}".format(k, v) for k, v in rctx.attr.ghc_labels.items()] # The Label constructors need to be resolved in the hub repository which has visibility + ghc_labels_items = ["{}:{}".format(k, v) for k, v in rctx.attr.ghc_labels.items()] rctx.file( "nix_ghcs.bzl", - # content = "nix_ghcs = {{ {} }} ".format(",".join(items)), content = """ ghc_labels = {{ {ghc_labels} }} -toolchain_configs = {{ {toolchain_configs} }} toolchain_keys = {toolchain_keys} toolchains_2 = {toolchains_2} """.format( - # toolchain_configs = {k: json.decode(v) for k, v in rctx.attr.toolchains.items()}, - toolchain_configs = ",".join(toolchain_items), ghc_labels = ",".join(ghc_labels_items), - ghc_labels_2 = rctx.attr.ghc_labels_2, toolchain_keys = rctx.attr.toolchain_keys, toolchains_2 = rctx.attr.toolchains_2, ), ) - # repository_ctx.file( - # "ghc_paths.bzl", - # ) hub = repository_rule( implementation = _hub_impl, attrs = { "ghc_labels": attr.string_dict(), - "ghc_labels_2": attr.string(), - "toolchains": attr.string_dict(), "toolchains_2": attr.string(), "toolchain_keys": attr.string(), }, ) def _nix_haskell_toolchains_impl(mctx): - # Instead of creating one external repository for each `toolchain(...)` declaration, - # we recover them in a list and declare them all in the `all_bindist_toolchains` repository. - # In a way that respects - # bazel's iteration order over modules. - # toolchains declared by the root have priority - - # an alternative would be to use aliases to the (to get rid of the toolchain_declarations parameter) - # if/once the following issue is resolved - # https://github.com/bazelbuild/bazel/issues/16298 - toolchain_declarations = [] - # for module_index, module in enumerate(mctx.modules): - # for config_tag_index, config_tag in enumerate(module.tags.config): - # name = "nix_toolchain_{}_{}_{}".format(module_index, config_tag_index, config_tag.name) - # all_names.append(name) - ghc_labels = {} toolchains = {} toolchain_keys = [] # to remember the order - for module_index, module in enumerate(mctx.modules): - for config_tag_index, config_tag in enumerate(module.tags.config): + posix_toolchains = [] + for module in mctx.modules: + for config_tag in module.tags.config: if (module.name, module.version, config_tag.name) in toolchains: - fail("Same module is trying to define nix toolchains with the same name") - - #name = "nix_toolchain_{}_{}_{}".format(module_index, config_tag_index, config_tag.name) + fail( + """module "{module}~{version}" used the "config" tag twice with the "{tag_name}" name""".format( + tag_name = config_tag.name, + module = module.name, + version = module.version, + ), + ) name = "nix_toolchain_{}_{}_{}".format(module.name, module.version, config_tag.name) nixpkgs_ghc_repo_name = "{}_ghc_nixpkgs".format(name) nixpkgs_sh_posix_repo_name = "{}_sh_posix_nixpkgs".format(name) haskell_toolchain_repo_name = "{}_ghc_nixpkgs_haskell_toolchain".format(name) toolchain_repo_name = "{}_ghc_nixpkgs_toolchain".format(name) - toolchain_declarations.append("# module:{} tag:config_{}".format(module.name, config_tag_index)) nixpkgs_package( name = nixpkgs_ghc_repo_name, @@ -154,41 +152,27 @@ def _nix_haskell_toolchains_impl(mctx): repositories = config_tag.repositories, repository = config_tag.repository, ) - if config_tag.sh_posix_attributes != None: + if config_tag.sh_posix_attributes != []: sh_posix_nixpkgs_kwargs["packages"] = config_tag.sh_posix_attributes - # TODO: register posix toolchain. nixpkgs_sh_posix_configure( name = nixpkgs_sh_posix_repo_name, register = False, **sh_posix_nixpkgs_kwargs ) - # toolchains[(module.name, module.version, config_tag.name)] = struct( - # version = config_tag.version, - # name = name, - # static_runtime = config_tag.static_runtime, - # fully_static_link = config_tag.fully_static_link, - # # build_file = config_tag.build_file, - # # build_file_content = config_tag.build_file_content, - # ghcopts = config_tag.ghcopts, - # compiler_flags_select = config_tag.compiler_flags_select, - # haddock_flags = config_tag.haddock_flags, - # repl_ghci_args = config_tag.repl_ghci_args, - # cabalopts = config_tag.cabalopts, - # locale_archive = config_tag.locale_archive, - # # attribute_path = config_tag.attribute_path, - # sh_posix_attributes = config_tag.sh_posix_attributes, - # # nix_file = config_tag.nix_file, - # # nix_file_deps = config_tag.nix_file_deps, - # # nixopts = config_tag.nixopts, - # locale = config_tag.locale, - # # repositories = config_tag.repositories, - # # repository = config_tag.repository, - # # nix_file_content = config_tag.nix_file_content, - # exec_constraints = config_tag.exec_constraints, - # target_constraints = config_tag.target_constraints, - # ) + posix_toolchains.append( + _nixpkgs_sh_posix_toolchain_str( + name = "{}_{}_{}_posix_toolchain".format( + module.name, + module.version, + config_tag.name, + ), + mctx = mctx, + workspace = nixpkgs_sh_posix_repo_name, + exec_constraints = [], + ), + ) # For convenience we only use one tag and propagate the # toolchain configuration to the `declare_toolchains` @@ -201,23 +185,13 @@ def _nix_haskell_toolchains_impl(mctx): "name": name, "static_runtime": config_tag.static_runtime, "fully_static_link": config_tag.fully_static_link, - # build_file = config_tag.build_file, - # build_file_content = config_tag.build_file_content, "ghcopts": config_tag.ghcopts, "compiler_flags_select": config_tag.compiler_flags_select, "haddock_flags": config_tag.haddock_flags, "repl_ghci_args": config_tag.repl_ghci_args, "cabalopts": config_tag.cabalopts, "locale_archive": config_tag.locale_archive, - # attribute_path : config_tag.attribute_path, - # "sh_posix_attributes": config_tag.sh_posix_attributes, - # nix_file : config_tag.nix_file, - # nix_file_deps : config_tag.nix_file_deps, - # nixopts : config_tag.nixopts, "locale": config_tag.locale, - # repositories : config_tag.repositories, - # repository : config_tag.repository, - # nix_file_content : config_tag.nix_file_content, "exec_constraints": config_tag.exec_constraints, "target_constraints": config_tag.target_constraints, } @@ -225,17 +199,14 @@ def _nix_haskell_toolchains_impl(mctx): toolchain_keys.append((module.name, module.version, config_tag.name)) hub( name = "hub", - # ghc_labels = {repr(k): v for k, v in ghc_labels.items()}, ghc_labels = {repr(k): v for k, v in ghc_labels.items()}, - ghc_labels_2 = repr(ghc_labels), - toolchains = {repr(k): json.encode(v) for k, v in toolchains.items()}, toolchains_2 = repr(toolchains), toolchain_keys = repr(toolchain_keys), ) - # _all_toolchains( - # name = "all_nix_toolchains", - # toolchains = toolchain_declarations, - # ) + _all_posix_toolchains( + name = "all_posix_toolchains", + toolchains = posix_toolchains, + ) nix_haskell_toolchains = module_extension( implementation = _nix_haskell_toolchains_impl, diff --git a/rules_haskell_tests/MODULE.bazel b/rules_haskell_tests/MODULE.bazel index 73472c025b..e7f3907667 100644 --- a/rules_haskell_tests/MODULE.bazel +++ b/rules_haskell_tests/MODULE.bazel @@ -579,6 +579,8 @@ haskell_toolchains = use_extension( "haskell_toolchains", ) +test_ghc_version = "9.2.5" + test_ghcopts = [ "-XStandaloneDeriving", # Flag used at compile time "-threaded", # Flag used at link time @@ -604,15 +606,15 @@ test_cabalopts = [ "--haddock-option=--optghc=-DTESTS_TOOLCHAIN_CABALOPTS", ] -# TODO customise toolchain for windows -# + ([ -# # To avoid ghcide linking errors with heapsize on Windows of the form -# # -# # unknown symbol `heap_view_closurePtrs' -# # -# # See https://github.com/haskell/ghcide/pull/954 -# "--disable-library-for-ghci", -# ] if is_windows else []) +cabalopts_windows = test_cabalopts + [ + # To avoid ghcide linking errors with heapsize on Windows of the form + # + # unknown symbol `heap_view_closurePtrs' + # + # See https://github.com/haskell/ghcide/pull/954 + "--disable-library-for-ghci", +] + haskell_toolchains.bindists( cabalopts = test_cabalopts, ghcopts = test_ghcopts, @@ -620,12 +622,25 @@ haskell_toolchains.bindists( repl_ghci_args = test_repl_ghci_args, ) -# haskell_toolchains.bindist( -# name = "cusom_bindist", -# ghcopts = ["asdasdasda"], -# target = "linux_amd64", -# version = "9.2.5", -# ) +# We cannot configure cabalopts depending on the platform before calling haskell_toolchains.bindists: +# https://github.com/bazelbuild/bazel/issues/17880 +# So we add toolchains for windows separately, they take precedence over the one generated by +# haskell_toolchains.bindists and use the `cabalopts_windows` variable +[ + haskell_toolchains.bindist( + name = "windows_{}".format(target), + cabalopts = cabalopts_windows, + ghcopts = test_ghcopts, + haddock_flags = test_haddock_flags, + repl_ghci_args = test_repl_ghci_args, + target = target, + version = "9.2.5", + ) + for target in [ + "windows_amd64", + "windows_arm64", + ] +] nix_haskell_toolchains = use_extension( "@rules_haskell_nix//extensions:nix_haskell_toolchains.bzl", @@ -638,7 +653,6 @@ nix_haskell_toolchains.config( cabalopts = test_cabalopts, ghcopts = test_ghcopts, haddock_flags = test_haddock_flags, - # cabalopts = ["ashjads"], nix_file_content = """with import {}; haskell.packages.ghc925.ghc""", repl_ghci_args = test_repl_ghci_args, repository = "@nixpkgs_default",