From c056ea615cb32bec593031cf0064e327f2fb436a Mon Sep 17 00:00:00 2001 From: Yves-Stan Le Cornec Date: Wed, 27 Oct 2021 17:20:33 +0200 Subject: [PATCH 1/3] Make asterius toolchain depend on the regular one. --- haskell/asterius/asterius_config.bzl | 4 +- haskell/toolchain.bzl | 65 +++++++++++++++------------- 2 files changed, 36 insertions(+), 33 deletions(-) diff --git a/haskell/asterius/asterius_config.bzl b/haskell/asterius/asterius_config.bzl index 3c8d01033..fb46621dc 100644 --- a/haskell/asterius/asterius_config.bzl +++ b/haskell/asterius/asterius_config.bzl @@ -1,7 +1,7 @@ # asterius equivalents of tools from the haskell toolchain. ASTERIUS_BINARIES = { - "ghc": "ahc", - "ghc-pkg": "ahc-pkg", + "ahc": "ghc", + "ahc-pkg": "ghc_pkg", } def asterius_tools_config(exec_cc_toolchain, posix_toolchain, node_toolchain, tools_for_ghc_pkg): diff --git a/haskell/toolchain.bzl b/haskell/toolchain.bzl index b769dbb9f..54580116a 100644 --- a/haskell/toolchain.bzl +++ b/haskell/toolchain.bzl @@ -107,36 +107,43 @@ default_tools_config = struct( supports_haddock = True, ) +def _lookup_binaries(names, files, version = ""): + binaries = {} + for tool in list(names): + for file in files: + basename_no_ext = paths.split_extension(file.basename)[0] + if tool == basename_no_ext: + binaries[tool] = file + break + if version and "%s-%s" % (tool, version) == basename_no_ext: + binaries[tool] = file + break + if not tool in binaries: + fail("Cannot find {} in {}".format(tool, files)) + return binaries + def _haskell_toolchain_impl(ctx): numeric_version = [int(x) for x in ctx.attr.version.split(".")] if numeric_version == [8, 10, 1] or numeric_version == [8, 10, 2]: fail("GHC 8.10.1 and 8.10.2 not supported. Upgrade to 8.10.3 or later.") - # Store the binaries of interest in ghc_binaries. - ghc_binaries = {} - - for tool in _GHC_BINARIES: - if ctx.attr.asterius_binaries: - # We first look for binaries provided by asterius, - # then we complete the toolchain with the regular ghc. - if tool in ASTERIUS_BINARIES: - for file in ctx.files.asterius_binaries: - basename_no_ext = paths.split_extension(file.basename)[0] - if ASTERIUS_BINARIES[tool] == basename_no_ext: - ghc_binaries[tool] = file - break - if tool in ghc_binaries: - continue - for file in ctx.files.tools: - basename_no_ext = paths.split_extension(file.basename)[0] - if tool == basename_no_ext: - ghc_binaries[tool] = file - break - elif "%s-%s" % (tool, ctx.attr.version) == basename_no_ext: - ghc_binaries[tool] = file - break - if not tool in ghc_binaries: - fail("Cannot find {} in {}".format(tool, ctx.attr.tools)) + if ctx.attr.asterius_binaries: + # we recover binaries that are not provided by asterius via the regular toolchain. + exec_tools_struct = ctx.toolchains["@rules_haskell//haskell:toolchain"].tools + tools_struct_args = { + k: getattr(exec_tools_struct, k) + for name in _GHC_BINARIES + for k in [name.replace("-", "_")] + } + ahc_binaries = _lookup_binaries(ASTERIUS_BINARIES.keys(), ctx.files.asterius_binaries) + for tool, asterius_binary in ahc_binaries.items(): + tools_struct_args[ASTERIUS_BINARIES[tool]] = asterius_binary + else: + ghc_binaries = _lookup_binaries(_GHC_BINARIES, ctx.files.tools, ctx.attr.version) + tools_struct_args = { + name.replace("-", "_"): file + for name, file in ghc_binaries.items() + } # Get the libdir and docdir paths libdir = ctx.files.libdir @@ -172,7 +179,7 @@ def _haskell_toolchain_impl(ctx): fail("One of `docdir` and `docdir_path` is required.") # Get the versions of every prebuilt package. - ghc_pkg = ghc_binaries["ghc-pkg"] + ghc_pkg = tools_struct_args["ghc_pkg"] pkgdb_file = ctx.actions.declare_file("ghc-global-pkgdb") ctx.actions.run_shell( inputs = [ghc_pkg], @@ -185,11 +192,6 @@ def _haskell_toolchain_impl(ctx): ), ) - tools_struct_args = { - name.replace("-", "_"): file - for name, file in ghc_binaries.items() - } - locale_archive = None if ctx.attr.locale_archive != None: @@ -327,6 +329,7 @@ _ahc_haskell_toolchain = rule( "@rules_sh//sh/posix:toolchain_type", "@build_bazel_rules_nodejs//toolchains/node:toolchain_type", "@bazel_tools//tools/cpp:toolchain_type", + "@rules_haskell//haskell:toolchain", ], attrs = dict( common_attrs, From 8f18cd4114e3ac53aae686384c416c5893b34e59 Mon Sep 17 00:00:00 2001 From: Yves-Stan Le Cornec Date: Wed, 27 Oct 2021 14:53:27 +0200 Subject: [PATCH 2/3] Nixpkgs platform constraints fix. --- haskell/nixpkgs.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/haskell/nixpkgs.bzl b/haskell/nixpkgs.bzl index 3cfa88c00..037a124d0 100644 --- a/haskell/nixpkgs.bzl +++ b/haskell/nixpkgs.bzl @@ -145,7 +145,7 @@ def _ghc_nixpkgs_toolchain_impl(repository_ctx): # platform. But they are important to state because Bazel # toolchain resolution prefers other toolchains with more specific # constraints otherwise. - if repository_ctx.attr.target_constraints == None and repository_ctx.attr.exec_constraints == None: + if repository_ctx.attr.target_constraints == [] and repository_ctx.attr.exec_constraints == []: target_constraints = ["@platforms//cpu:x86_64"] if repository_ctx.os.name == "linux": target_constraints.append("@platforms//os:linux") From b64079dbb212fef1f44866f43e8ae866059cf2bf Mon Sep 17 00:00:00 2001 From: Yves-Stan Le Cornec Date: Wed, 27 Oct 2021 15:03:56 +0200 Subject: [PATCH 3/3] Asterius toolchains declaration. --- WORKSPACE | 31 +- constants.bzl | 1 + haskell/asterius/BUILD.bazel | 18 + haskell/asterius/asterius_config.bzl | 18 + ...sitories.bzl => asterius_dependencies.bzl} | 2 +- haskell/asterius/defs.bzl | 33 ++ haskell/asterius/repositories.bzl | 346 ++++++++++++++++++ haskell/ghc.BUILD.tpl | 6 + haskell/ghc_bindist.bzl | 1 + haskell/platforms/BUILD.bazel | 10 + haskell/platforms/list.bzl | 29 ++ haskell/private/dict.bzl | 7 + 12 files changed, 490 insertions(+), 12 deletions(-) rename haskell/asterius/{asterius_repositories.bzl => asterius_dependencies.bzl} (97%) create mode 100644 haskell/asterius/defs.bzl create mode 100644 haskell/asterius/repositories.bzl create mode 100644 haskell/private/dict.bzl diff --git a/WORKSPACE b/WORKSPACE index deea1e4de..bbb9aca2d 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -38,6 +38,7 @@ haskell_cabal_binary( load( "@rules_haskell//:constants.bzl", + "test_asterius_version", "test_ghc_version", "test_stack_snapshot", ) @@ -271,6 +272,25 @@ haskell_register_ghc_nixpkgs( version = test_ghc_version, ) +load( + "//haskell/asterius:repositories.bzl", + "asterius_dependencies_bindist", + "asterius_dependencies_nix", + "rules_haskell_asterius_toolchains", +) + +(asterius_dependencies_nix( + nix_repository = "@nixpkgs_default", + nixpkgs_package_rule = nixpkgs_package, +) if is_nix_shell else asterius_dependencies_bindist()) + +rules_haskell_asterius_toolchains( + cabalopts = test_cabalopts, + ghcopts = test_ghcopts, + repl_ghci_args = test_repl_ghci_args, + version = test_asterius_version, +) + load( "@rules_haskell//haskell:ghc_bindist.bzl", "haskell_register_ghc_bindists", @@ -460,17 +480,6 @@ maybe( urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/3.6.0/rules_nodejs-3.6.0.tar.gz"], ) -load( - "//haskell/asterius:asterius_repositories.bzl", - "asterius_dependencies_bindist", - "asterius_dependencies_nix", -) - -(asterius_dependencies_nix( - nix_repository = "@nixpkgs_default", - nixpkgs_package_rule = nixpkgs_package, -) if is_nix_shell else asterius_dependencies_bindist()) - http_archive( name = "io_bazel_rules_sass", sha256 = "86f734253cb2480acab150f37eb6c5952f33ed463182f77eedf2e41ba2fe2e8f", diff --git a/constants.bzl b/constants.bzl index d695ca3f9..64eef7644 100644 --- a/constants.bzl +++ b/constants.bzl @@ -1,2 +1,3 @@ test_ghc_version = "8.10.4" test_stack_snapshot = "lts-18.0" +test_asterius_version = "0.0.1" diff --git a/haskell/asterius/BUILD.bazel b/haskell/asterius/BUILD.bazel index 344037767..b024c5f38 100644 --- a/haskell/asterius/BUILD.bazel +++ b/haskell/asterius/BUILD.bazel @@ -4,6 +4,24 @@ bzl_library( name = "asterius_bzl", srcs = [ "asterius_config.bzl", + "repositories.bzl", ], visibility = ["//haskell:__pkg__"], + deps = [ + "//haskell/platforms", + ], +) + +platform( + name = "asterius_platform", + constraint_values = [ + "@platforms//cpu:wasm32", + ], +) + +# Toolchain type for asterius specific tools such as ahc-dist, +# which are not part of the regular haskell toolchain. +toolchain_type( + name = "toolchain_type", + visibility = ["//visibility:public"], ) diff --git a/haskell/asterius/asterius_config.bzl b/haskell/asterius/asterius_config.bzl index fb46621dc..d59c09c08 100644 --- a/haskell/asterius/asterius_config.bzl +++ b/haskell/asterius/asterius_config.bzl @@ -1,3 +1,21 @@ +# From the asterius/cabal/config file of asterius and ahc-cabal.hs +asterius_cabalopts = [ + "--enable-library-vanilla", + "--disable-executable-dynamic", + "--disable-profiling", + "-O 2", + "--disable-debug-info", + "--disable-library-for-ghci", + "--disable-split-sections", + "--disable-split-objs", + "--disable-executable-stripping", + "--disable-library-stripping", + "--disable-tests", + "--disable-coverage", + "--disable-benchmarks", + "--hsc2hs-options=--cross-compile", +] + # asterius equivalents of tools from the haskell toolchain. ASTERIUS_BINARIES = { "ahc": "ghc", diff --git a/haskell/asterius/asterius_repositories.bzl b/haskell/asterius/asterius_dependencies.bzl similarity index 97% rename from haskell/asterius/asterius_repositories.bzl rename to haskell/asterius/asterius_dependencies.bzl index 7c215d7ea..4add7ff29 100644 --- a/haskell/asterius/asterius_repositories.bzl +++ b/haskell/asterius/asterius_dependencies.bzl @@ -75,7 +75,7 @@ def asterius_dependencies_nix( nixpkgs_package_rule: The `nixpkgs_package` rule from `rules_nixpkgs`. package_json: The package.json file that will be passed to [yarn_install](https://bazelbuild.github.io/rules_nodejs/Built-ins.html#yarn_install) yarn_lock: The yarn.lock file that will be passed to [yarn_install](https://bazelbuild.github.io/rules_nodejs/Built-ins.html#yarn_install) - nixpkgs_nodejs = The name for the nodejs that will be installed with `nixpkgs_package`. + nixpkgs_nodejs: The name for the nodejs that will be installed with `nixpkgs_package`. """ _nixpkgs_nodejs(nixpkgs_nodejs, nix_repository, nixpkgs_package_rule) node_repositories( diff --git a/haskell/asterius/defs.bzl b/haskell/asterius/defs.bzl new file mode 100644 index 000000000..015b28dd9 --- /dev/null +++ b/haskell/asterius/defs.bzl @@ -0,0 +1,33 @@ +load("@bazel_skylib//lib:paths.bzl", "paths") + +def _asterius_toolchain_impl(ctx): + ahc_dist = None + for file in ctx.files.binaries: + basename_no_ext = paths.split_extension(file.basename)[0] + if basename_no_ext == "ahc-dist": + ahc_dist = file + if ahc_dist == None: + fail("ahc-dist was not found when defining the asterius toolchain") + + return [ + platform_common.ToolchainInfo( + name = ctx.label.name, + ahc_dist = ahc_dist, + tools = ctx.files.tools, + ), + ] + +asterius_toolchain = rule( + _asterius_toolchain_impl, + attrs = { + "binaries": attr.label_list( + mandatory = True, + doc = "The asterius top level wrappers", + ), + "tools": attr.label_list( + mandatory = True, + doc = "The complete asterius bundle, which is needed to execute the wrappers.", + ), + }, + doc = "Toolchain for asterius tools that are not part of the regular haskell toolchain", +) diff --git a/haskell/asterius/repositories.bzl b/haskell/asterius/repositories.bzl new file mode 100644 index 000000000..3066884fe --- /dev/null +++ b/haskell/asterius/repositories.bzl @@ -0,0 +1,346 @@ +load("@bazel_skylib//lib:paths.bzl", "paths") +load( + "//haskell:private/workspace_utils.bzl", + "define_rule", + "execute_or_fail_loudly", + "find_python", + "resolve_labels", +) +load("//haskell:private/validate_attrs.bzl", "check_deprecated_attribute_usage") +load( + "//haskell:private/pkgdb_to_bzl.bzl", + "pkgdb_to_bzl", +) +load( + "//haskell/platforms:list.bzl", + "os_of_constraints", + "platform_of_constraints", +) +load("//haskell:private/versions.bzl", "supports_rules_nodejs_ge_4") +load("//haskell/asterius:asterius_config.bzl", "asterius_cabalopts") +load( + "//haskell/asterius:asterius_dependencies.bzl", + _asterius_dependencies_bindist = "asterius_dependencies_bindist", + _asterius_dependencies_nix = "asterius_dependencies_nix", +) + +# For now the asterius bundle is built and uploaded manually for linux. +# When the asterius build works inside the ci we will be able to download the artifacts from there. +AHC_BINDIST = \ + { + "0.0.1": { + "linux_amd64": ( + "https://github.com/ylecornec/test_bundle/releases/download/test/asterius_bundle.tar.gz", + "0c50415278e14003541697c99818e96d52ba67b1a140ac0eaf89bfb6b751548f", + ), + }, + } + +AHC_DEFAULT_VERSION = "0.0.1" + +def _labels_from_bundle_name(bundle_repo_name, asterius_version): + """ Labels of targets from the external repository extracted from the asterius bundle.""" + return ( + "@{}//:asterius-{}_data/.boot/asterius_lib/settings".format( + bundle_repo_name, + asterius_version, + ), + "@{}//:bazel_build/wrappers/ahc-pkg".format(bundle_repo_name), + "@{}//:asterius_binaries".format(bundle_repo_name), + "@{}//:local_asterius".format(bundle_repo_name), + "@{}//:wasm_cc".format(bundle_repo_name), + ) + +def _asterius_bundle_impl(repository_ctx): + exec_platform = repository_ctx.attr.exec_platform + version = repository_ctx.attr.version + if version not in AHC_BINDIST or AHC_BINDIST[version].get(exec_platform) == None: + fail("Operating system {0} does not have a bindist for Asterius version {1}".format(exec_platform, version)) + else: + url, sha256 = AHC_BINDIST[version][exec_platform] + + repository_ctx.download_and_extract( + url = url, + output = "", + sha256 = sha256, + ) + +_asterius_bundle = repository_rule( + _asterius_bundle_impl, + local = False, + attrs = { + "version": attr.string(), + "exec_platform": attr.string(), + }, + doc = "Downloads and extracts an asterius bundle.", +) + +def _ahc_toolchain_impl(ctx): + exec_platform = platform_of_constraints(ctx.attr.exec_constraints) + exec_constraints_str = [str(c) for c in ctx.attr.exec_constraints] + target_constraints = ["@platforms//cpu:wasm32"] + ctx.file( + "BUILD", + executable = False, + content = """ +toolchain( + name = "toolchain", + toolchain_type = "@rules_haskell//haskell:toolchain", + toolchain = "@{bindist_name}//:toolchain-impl", + exec_compatible_with = {exec_constraints}, + target_compatible_with = {target_constraints}, +) + +toolchain( + name = "asterius_toolchain", + toolchain_type = "@rules_haskell//haskell/asterius:toolchain_type", + toolchain = "@{bindist_name}//:asterius-toolchain-impl", + exec_compatible_with = {exec_constraints}, +) + +toolchain( + name = "wasm_cc_toolchain", + exec_compatible_with = {exec_constraints}, + target_compatible_with = {target_constraints}, + toolchain = "{wasm_cc_toolchain}", + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", +) + """.format( + bindist_name = ctx.attr.bindist_name, + exec_constraints = exec_constraints_str, + target_constraints = target_constraints, + exec_platform = exec_platform, + wasm_cc_toolchain = ctx.attr.wasm_cc_toolchain, + ), + ) + +_ahc_toolchain = repository_rule( + _ahc_toolchain_impl, + local = False, + attrs = { + "bindist_name": attr.string(), + "exec_constraints": attr.label_list(), + "wasm_cc_toolchain": attr.label( + mandatory = True, + doc = "A web assembly cc_toolchain", + ), + }, + doc = "Declares WebAssembly related toolchains from the bindist_name repository.", +) + +def _ahc_impl(ctx): + filepaths = resolve_labels(ctx, [ + "@rules_haskell//haskell:ghc.BUILD.tpl", + "@rules_haskell//haskell:private/pkgdb_to_bzl.py", + ]) + lib_path = str(ctx.path(ctx.attr.asterius_lib_setting_file).dirname) + ahc_pkg_path = ctx.path(ctx.attr.ahc_pkg) + + docdir_path = execute_or_fail_loudly(ctx, [ahc_pkg_path, "field", "base", "haddock-html", "--simple-output"]).stdout.strip() + ctx.symlink(lib_path, "asterius_lib") + + toolchain_libraries = pkgdb_to_bzl(ctx, filepaths, paths.basename(lib_path)) + exec_os = os_of_constraints(ctx.attr.exec_constraints) + locale = ctx.attr.locale or ("en_US.UTF-8" if exec_os == "darwin" else "C.UTF-8") + + toolchain = define_rule( + "haskell_toolchain", + name = "toolchain-impl", + asterius_binaries = repr(str(ctx.attr.asterius_binaries)), + tools = [str(ctx.attr.full_bundle)], + libraries = "toolchain_libraries", + libdir_path = repr(paths.basename(lib_path)), + docdir_path = repr(docdir_path), + version = repr(ctx.attr.version), + static_runtime = True, + fully_static_link = True, + ghcopts = ctx.attr.ghcopts, + repl_ghci_args = ctx.attr.repl_ghci_args, + cabalopts = asterius_cabalopts + ctx.attr.cabalopts, + locale = repr(locale), + ) + + asterius_toolchain = define_rule( + "asterius_toolchain", + name = "asterius-toolchain-impl", + binaries = [str(ctx.attr.asterius_binaries)], + tools = [str(ctx.attr.full_bundle)], + ) + + ctx.template( + "BUILD", + filepaths["@rules_haskell//haskell:ghc.BUILD.tpl"], + substitutions = { + "%{toolchain_libraries}": toolchain_libraries, + "%{toolchain}": toolchain, + "%{asterius_toolchain}": asterius_toolchain, + }, + executable = False, + ) + +_ahc = repository_rule( + _ahc_impl, + local = False, + attrs = { + "version": attr.string( + default = AHC_DEFAULT_VERSION, + values = AHC_BINDIST.keys(), + doc = "The desired Asterius version", + ), + "exec_constraints": attr.label_list(), + "repl_ghci_args": attr.string_list(), + "ghcopts": attr.string_list(), + "cabalopts": attr.string_list(), + "locale": attr.string( + mandatory = False, + ), + "asterius_lib_setting_file": attr.label(), + "ahc_pkg": attr.label(doc = "Label for the ahc_pkg binary"), + "asterius_binaries": attr.label( + doc = "Filegroup with the asterius binaries.", + ), + "full_bundle": attr.label( + doc = "Filegroup with the full bundle, which is necessary for the binaries to run.", + ), + }, + doc = "Defines the haskell toolchain using asterius, as well as the asterius toolchain which contains asterius specific tools.", +) + +def rules_haskell_asterius_toolchain( + name, + version, + exec_constraints, + asterius_lib_setting_file, + ahc_pkg, + asterius_binaries, + full_bundle, + wasm_cc_toolchain, + ghcopts = None, + repl_ghci_args = None, + cabalopts = None, + locale = None): + """ Define and registers asterius related toolchains. + + Args: + name: A unique name for the repository. + version: The asterius version for this toolchain. + exec_constraints: Executions constraints for the toolchain resolution. + asterius_lib_setting_file: Label of the `settings` file in the `asterius_lib` repository of the asterius installation. + ahc_pkg: Label of the `ahc-pkg` binary. + asterius_binaries: Filegroup containing the asterius top-level binaries. + full_bundle: Filegroup with the asterius_binaries and all their dependencies. + wasm_cc_toolchain: A web asssembly cc toolchain. + ghcopts: [see rules_haskell_toolchains](toolchain.html#rules_haskell_toolchains-ghcopts) + haddock_flags: [see rules_haskell_toolchains](toolchain.html#rules_haskell_toolchains-haddock_flags) + repl_ghci_args: [see rules_haskell_toolchains](toolchain.html#rules_haskell_toolchains-repl_ghci_args) + cabalopts: [see rules_haskell_toolchains](toolchain.html#rules_haskell_toolchains-cabalopts) + locale: [see rules_haskell_toolchains](toolchain.html#rules_haskell_toolchains-locale) + """ + + if not supports_rules_nodejs_ge_4(native.bazel_version): + fail("Asterius is only supported starting from bazel 4 (because it depends on rules_nodejs >= 4)") + + _ahc( + name = name, + version = version, + exec_constraints = exec_constraints, + ghcopts = ghcopts, + repl_ghci_args = repl_ghci_args, + cabalopts = cabalopts, + locale = locale, + asterius_lib_setting_file = asterius_lib_setting_file, + ahc_pkg = ahc_pkg, + asterius_binaries = asterius_binaries, + full_bundle = full_bundle, + ) + + toolchain_name = "{}-toolchain".format(name) + + _ahc_toolchain( + name = toolchain_name, + bindist_name = name, + exec_constraints = exec_constraints, + wasm_cc_toolchain = wasm_cc_toolchain, + ) + native.register_toolchains("@{}//:toolchain".format(toolchain_name)) + native.register_toolchains("@{}//:asterius_toolchain".format(toolchain_name)) + native.register_toolchains("@{}//:wasm_cc_toolchain".format(toolchain_name)) + +def rules_haskell_asterius_toolchains( + version = AHC_DEFAULT_VERSION, + ghcopts = [], + cabalopts = [], + repl_ghci_args = [], + locale = None): + """ + Register Asterius related toolchains for all platforms. + + Args: + version: Asterius version. + compiler_flags: [see rules_haskell_toolchains](toolchain.html#rules_haskell_toolchains-compiler_flags) + ghcopts: [see rules_haskell_toolchains](toolchain.html#rules_haskell_toolchains-ghcopts) + cabalopts: [see rules_haskell_toolchains](toolchain.html#rules_haskell_toolchains-cabalopts) + repl_ghci_args: [see rules_haskell_toolchains](toolchain.html#rules_haskell_toolchains-repl_ghci_args) + locale: [see rules_haskell_toolchains](toolchain.html#rules_haskell_toolchains-locale) + """ + if not AHC_BINDIST.get(version): + fail("Binary distribution of Asterius {} not available.".format(version)) + for platform in AHC_BINDIST[version]: + # Download the asterius bundle. + bundle_repo_name = "asterius_bundle_{}".format(platform) + _asterius_bundle( + name = bundle_repo_name, + version = version, + exec_platform = platform, + ) + + os, _, arch = platform.partition("_") + os_constraint = { + "darwin": "@platforms//os:osx", + "linux": "@platforms//os:linux", + "windows": "@platforms//os:windows", + }.get(os) + arch_constraint = { + "amd64": "@platforms//cpu:x86_64", + }.get(arch) + exec_constraints = [os_constraint, arch_constraint] + + # Create and register the asterius toolchains + (asterius_lib_setting_file, ahc_pkg, asterius_binaries, full_bundle, wasm_cc_toolchain) = _labels_from_bundle_name(bundle_repo_name, version) + + rules_haskell_asterius_toolchain( + "{}_asterius".format(platform), + version, + exec_constraints, + asterius_lib_setting_file, + ahc_pkg, + asterius_binaries, + full_bundle, + wasm_cc_toolchain, + ghcopts = ghcopts, + cabalopts = cabalopts, + locale = locale, + ) + +def asterius_dependencies_bindist(**kwargs): + """ Install asterius dependencies for bindists. + + Args: + package_json: The package.json file that will be passed to [yarn_install](https://bazelbuild.github.io/rules_nodejs/Built-ins.html#yarn_install) + yarn_lock: The yarn.lock file that will be passed to [yarn_install](https://bazelbuild.github.io/rules_nodejs/Built-ins.html#yarn_install) + + """ + _asterius_dependencies_bindist(**kwargs) + +def asterius_dependencies_nix(**kwargs): + """ + Install asterius dependencies based on nix. + + Args: + nix_repository: The nix repository from which we try to install node. + nixpkgs_package_rule: The `nixpkgs_package` rule from `rules_nixpkgs`. + package_json: The package.json file that will be passed to [yarn_install](https://bazelbuild.github.io/rules_nodejs/Built-ins.html#yarn_install) + yarn_lock: The yarn.lock file that will be passed to [yarn_install](https://bazelbuild.github.io/rules_nodejs/Built-ins.html#yarn_install) + nixpkgs_nodejs: The name for the nodejs that will be installed with `nixpkgs_package`. + """ + _asterius_dependencies_nix(**kwargs) diff --git a/haskell/ghc.BUILD.tpl b/haskell/ghc.BUILD.tpl index eb5877962..b24fb6351 100644 --- a/haskell/ghc.BUILD.tpl +++ b/haskell/ghc.BUILD.tpl @@ -12,6 +12,10 @@ load( "haskell_import", "haskell_toolchain", ) +load( + "@rules_haskell//haskell/asterius:defs.bzl", + "asterius_toolchain", +) package(default_visibility = ["//visibility:public"]) @@ -19,6 +23,8 @@ package(default_visibility = ["//visibility:public"]) %{toolchain} +%{asterius_toolchain} + filegroup( name = "bin", srcs = glob(["bin/*"]), diff --git a/haskell/ghc_bindist.bzl b/haskell/ghc_bindist.bzl index fd5168559..770c1d4ce 100644 --- a/haskell/ghc_bindist.bzl +++ b/haskell/ghc_bindist.bzl @@ -440,6 +440,7 @@ rm -f substitutions = { "%{toolchain_libraries}": toolchain_libraries, "%{toolchain}": toolchain, + "%{asterius_toolchain}": "", }, executable = False, ) diff --git a/haskell/platforms/BUILD.bazel b/haskell/platforms/BUILD.bazel index a71c0c2d8..8560e38b9 100644 --- a/haskell/platforms/BUILD.bazel +++ b/haskell/platforms/BUILD.bazel @@ -6,6 +6,7 @@ # These can be used in select expressions to choose platform-specifc # sources and dependencies. +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load(":list.bzl", "declare_config_settings") declare_config_settings() @@ -30,6 +31,15 @@ alias( visibility = ["//visibility:public"], ) +bzl_library( + name = "platforms", + srcs = ["list.bzl"], + visibility = [ + "//haskell:__pkg__", + "//haskell/asterius:__pkg__", + ], +) + filegroup( name = "all_files", testonly = True, diff --git a/haskell/platforms/list.bzl b/haskell/platforms/list.bzl index 6f2195d20..8b9dc08f9 100644 --- a/haskell/platforms/list.bzl +++ b/haskell/platforms/list.bzl @@ -1,3 +1,5 @@ +load("//haskell:private/dict.bzl", "find") + OS = { "aix": None, "darwin": "@platforms//os:osx", @@ -42,3 +44,30 @@ def declare_config_settings(): name = arch, constraint_values = [constraint_value], ) + +def os_of_constraints(constraints): + """ Returns the os corresponding to the first os constraint. + If there are none, returns None. + """ + for c in constraints: + if c.package == "os": + return find(OS, str(c)) + +def arch_of_constraints(constraints): + """ Returns the architecture corresponding to the first arch constraint. + If there are none, returns None. + """ + for c in constraints: + if c.package == "cpu": + return find(ARCH, str(c)) + +def platform_of_constraints(constraints): + os = os_of_constraints(constraints) + if os == None: + fail("Could not find os in constraints {}".format(constraints)) + + arch = arch_of_constraints(constraints) + if arch == None: + fail("Could not find arch in constraints {}".format(constraints)) + + return ("{}_{}".format(os, arch)) diff --git a/haskell/private/dict.bzl b/haskell/private/dict.bzl new file mode 100644 index 000000000..61922c808 --- /dev/null +++ b/haskell/private/dict.bzl @@ -0,0 +1,7 @@ +"""Helper functions on dicts.""" + +def find(d, value): + """ Look for the first key correspondind to value `value` in dictionnary `d` """ + for (k, v) in d.items(): + if v == value: + return k