From 47c01bc9f284f3d1ddaab05a3ffef6301a8ca819 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Tue, 12 Dec 2023 16:39:36 -0700 Subject: [PATCH 1/7] Add bazel_platforms module to derive values for OS and CPU. --- haskell/ghc_bindist.bzl | 61 ++++++++++++++--------------- haskell/private/bazel_platforms.bzl | 32 +++++++++++++++ 2 files changed, 62 insertions(+), 31 deletions(-) create mode 100644 haskell/private/bazel_platforms.bzl diff --git a/haskell/ghc_bindist.bzl b/haskell/ghc_bindist.bzl index a33f08195..0423939a2 100644 --- a/haskell/ghc_bindist.bzl +++ b/haskell/ghc_bindist.bzl @@ -3,8 +3,10 @@ load("@bazel_skylib//lib:paths.bzl", "paths") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "patch") load("@bazel_tools//tools/cpp:lib_cc_configure.bzl", "get_cpu_value") -load("@rules_sh//sh:posix.bzl", "sh_posix_configure") load("@rules_cc//cc:find_cc_toolchain.bzl", "CC_TOOLCHAIN_TYPE") +load("@rules_sh//sh:posix.bzl", "sh_posix_configure") +load("//haskell:ghc.bzl", "DEFAULT_GHC_VERSION") +load(":private/bazel_platforms.bzl", "bazel_platforms") load( ":private/pkgdb_to_bzl.bzl", "pkgdb_to_bzl", @@ -17,7 +19,6 @@ load( "find_python", "resolve_labels", ) -load("//haskell:ghc.bzl", "DEFAULT_GHC_VERSION") _GHC_DEFAULT_VERSION = DEFAULT_GHC_VERSION @@ -86,7 +87,7 @@ def _ghc_bindist_impl(ctx): if GHC_BINDIST_STRIP_PREFIX.get(version) != None and GHC_BINDIST_STRIP_PREFIX[version].get(target) != None: stripPrefix = GHC_BINDIST_STRIP_PREFIX[version][target] else: - arch_suffix = {"arm64": "aarch64", "amd64": "x86_64"}.get(arch) + arch_suffix = {"amd64": "x86_64", "arm64": "aarch64"}.get(arch) if os == "windows" and version_tuple >= (9, 0, 1): stripPrefix += "-{}-unknown-mingw32".format(arch_suffix) @@ -262,10 +263,10 @@ rm -f "BUILD", filepaths["@rules_haskell//haskell:ghc.BUILD.tpl"], substitutions = { - "%{toolchain_libraries}": toolchain_libraries, - "%{toolchain}": toolchain, "%{docdir}": docdir, "%{is_clang}": str(is_clang), + "%{toolchain_libraries}": toolchain_libraries, + "%{toolchain}": toolchain, }, executable = False, ) @@ -274,24 +275,11 @@ _ghc_bindist = repository_rule( _ghc_bindist_impl, local = False, attrs = { - "version": attr.string( - default = _GHC_DEFAULT_VERSION, - doc = "The desired GHC version", - ), - "target": attr.string(), + "cabalopts": attr.string_list(), "ghcopts": attr.string_list(), "haddock_flags": attr.string_list(), - "repl_ghci_args": attr.string_list(), - "cabalopts": attr.string_list(), - "patches": attr.label_list( - default = [], - doc = - "A list of files that are to be applied as patches afer " + - "extracting the archive.", - ), - "patch_tool": attr.string( - default = "patch", - doc = "The patch(1) utility to use.", + "locale": attr.string( + mandatory = False, ), "patch_args": attr.string_list( default = ["-p0"], @@ -301,8 +289,21 @@ _ghc_bindist = repository_rule( default = [], doc = "Sequence of commands to be applied after patches are applied.", ), - "locale": attr.string( - mandatory = False, + "patch_tool": attr.string( + default = "patch", + doc = "The patch(1) utility to use.", + ), + "patches": attr.label_list( + default = [], + doc = + "A list of files that are to be applied as patches afer " + + "extracting the archive.", + ), + "repl_ghci_args": attr.string_list(), + "target": attr.string(), + "version": attr.string( + default = _GHC_DEFAULT_VERSION, + doc = "The desired GHC version", ), "_relpath_script": attr.label( allow_single_file = True, @@ -474,7 +475,7 @@ def ghc_bindist( "9.2.1": ["@rules_haskell//haskell:assets/ghc_9_2_1_mac.patch"], }.get(version) - extra_attrs = {"patches": patches, "patch_args": ["-p0"]} if patches else {} + extra_attrs = {"patch_args": ["-p0"], "patches": patches} if patches else {} # We want the toolchain definition to be tucked away in a separate # repository, that way `bazel build //...` will not match it (and @@ -567,7 +568,7 @@ def haskell_register_ghc_bindists( configure_python3_toolchain(name = LOCAL_PYTHON_REPO_NAME, register = register) def _configure_python3_toolchain_impl(repository_ctx): - cpu = get_cpu_value(repository_ctx) + os_cpu = get_cpu_value(repository_ctx) python3_path = find_python(repository_ctx) if check_bazel_version("4.2.0")[0]: stub_shebang = """stub_shebang = "#!{python3_path}",""".format( @@ -595,20 +596,18 @@ toolchain( toolchain = ":py_runtime_pair", toolchain_type = "@bazel_tools//tools/python:toolchain_type", exec_compatible_with = [ - "@platforms//cpu:x86_64", + "@platforms//cpu:{cpu}", "@platforms//os:{os}", ], target_compatible_with = [ - "@platforms//cpu:x86_64", + "@platforms//cpu:{cpu}", "@platforms//os:{os}", ], ) """.format( python3 = python3_path, - os = { - "darwin": "osx", - "x64_windows": "windows", - }.get(cpu, "linux"), + os = bazel_platforms.get_os(os_cpu), + cpu = bazel_platforms.get_cpu(os_cpu), stub_shebang = stub_shebang, )) diff --git a/haskell/private/bazel_platforms.bzl b/haskell/private/bazel_platforms.bzl new file mode 100644 index 000000000..ec2268f2a --- /dev/null +++ b/haskell/private/bazel_platforms.bzl @@ -0,0 +1,32 @@ +"""Module for managing/deriving official Bazel platform values.""" + +# The expected values for os_cpu can be found by looking at the +# implementation for get_cpu_value in lib_cc_configure.bzl. +# https://github.com/bazelbuild/bazel/blob/e11506feaea7401c3d27f55b47183ef49bd1d5a8/tools/cpp/lib_cc_configure.bzl#L186 + +def _get_os(os_cpu): + if os_cpu.find("darwin") >= 0: + return "osx" + if os_cpu.find("windows") >= 0: + return "windows" + return "linux" + +def _get_cpu(os_cpu): + # This value could appear in older versions of Bazel. + if os_cpu == "darwin": + return "x86_64" + + # This handles modern os-cpu values like darwin_arm64 or darwin_x86_64. + if os_cpu.startswith("darwin_"): + return os_cpu.removeprefix("darwin_") + if os_cpu == "arm64_windows": + return "arm64" + if os_cpu == "x64_windows": + return "x86_64" + + return "linux" + +bazel_platforms = struct( + get_os = _get_os, + get_cpu = _get_cpu, +) From 873de9e77bf7c53abd69f72e3d4b498c3dda599a Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 13 Dec 2023 12:24:55 -0700 Subject: [PATCH 2/7] Add TODO --- haskell/private/bazel_platforms.bzl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/haskell/private/bazel_platforms.bzl b/haskell/private/bazel_platforms.bzl index ec2268f2a..d7fc74db7 100644 --- a/haskell/private/bazel_platforms.bzl +++ b/haskell/private/bazel_platforms.bzl @@ -4,6 +4,8 @@ # implementation for get_cpu_value in lib_cc_configure.bzl. # https://github.com/bazelbuild/bazel/blob/e11506feaea7401c3d27f55b47183ef49bd1d5a8/tools/cpp/lib_cc_configure.bzl#L186 +# TODO(chuck): Add unit tests. + def _get_os(os_cpu): if os_cpu.find("darwin") >= 0: return "osx" From 3d13ae8375b2f406914573ec98ce6a61f53f426c Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 13 Dec 2023 14:07:34 -0700 Subject: [PATCH 3/7] Fix default for CPU --- haskell/private/bazel_platforms.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/haskell/private/bazel_platforms.bzl b/haskell/private/bazel_platforms.bzl index d7fc74db7..64fee53db 100644 --- a/haskell/private/bazel_platforms.bzl +++ b/haskell/private/bazel_platforms.bzl @@ -26,7 +26,7 @@ def _get_cpu(os_cpu): if os_cpu == "x64_windows": return "x86_64" - return "linux" + return "x86_64" bazel_platforms = struct( get_os = _get_os, From b7b17c41470251a0135f2c2c0c29f77b99733b12 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Tue, 19 Dec 2023 17:24:32 -0700 Subject: [PATCH 4/7] Start adding tests for bazel_platforms --- haskell/private/bazel_platforms.bzl | 2 - rules_haskell_nix/shell.nix | 57 ----------- tests/haskell_tests/BUILD.bazel | 3 + tests/haskell_tests/bazel_platforms_tests.bzl | 97 +++++++++++++++++++ 4 files changed, 100 insertions(+), 59 deletions(-) delete mode 100644 rules_haskell_nix/shell.nix create mode 100644 tests/haskell_tests/BUILD.bazel create mode 100644 tests/haskell_tests/bazel_platforms_tests.bzl diff --git a/haskell/private/bazel_platforms.bzl b/haskell/private/bazel_platforms.bzl index 64fee53db..3377eaf9d 100644 --- a/haskell/private/bazel_platforms.bzl +++ b/haskell/private/bazel_platforms.bzl @@ -4,8 +4,6 @@ # implementation for get_cpu_value in lib_cc_configure.bzl. # https://github.com/bazelbuild/bazel/blob/e11506feaea7401c3d27f55b47183ef49bd1d5a8/tools/cpp/lib_cc_configure.bzl#L186 -# TODO(chuck): Add unit tests. - def _get_os(os_cpu): if os_cpu.find("darwin") >= 0: return "osx" diff --git a/rules_haskell_nix/shell.nix b/rules_haskell_nix/shell.nix deleted file mode 100644 index d040173ab..000000000 --- a/rules_haskell_nix/shell.nix +++ /dev/null @@ -1,57 +0,0 @@ -{ pkgs ? import ./nixpkgs { }, docTools ? true, ghcVersion ? "9.2.8" }: - -with pkgs; -mkShell { - # XXX: hack for macosX, this flags disable bazel usage of xcode - # Note: this is set even for linux so any regression introduced by this flag - # will be catched earlier - # See: https://github.com/bazelbuild/bazel/issues/4231 - BAZEL_USE_CPP_ONLY_TOOLCHAIN = 1; - TMPDIR = "/tmp"; - - GHC_VERSION = ghcVersion; - - # Set UTF-8 local so that run-tests can parse GHC's unicode output. - LANG = "C.UTF-8"; - - buildInputs = [ - go - nix - which - perl - python3 - jdk11 - # For stack_install. - stack - # Needed for ghcide which expects ghc in PATH. - haskell.packages."ghc${ builtins.replaceStrings [ "." ] [ "" ] ghcVersion }".ghc - # Needed for @com_github_golang_protobuf, itself needed by buildifier. - git - # Needed to get correct locale for tests with encoding - glibcLocales - # to avoid CA certificate failures on macOS CI - cacert - # Needed for debug/linking_utils - binutils - # check the start script for problems - shellcheck - file - ] ++ lib.optionals docTools [ graphviz python39Packages.sphinx zip unzip ]; - - packages = [ bazel_6 ]; - - shellHook = '' - # Add nix config flags to .bazelrc.local. - # - BAZELRC_LOCAL=".bazelrc.local" - if [ ! -e "$BAZELRC_LOCAL" ] - then - echo "[!] It looks like you are using a Nix-based system." - echo "In order to build this project, you need to add the two" - echo "following host_platform entries to your .bazelrc.local file:" - echo - echo "build --host_platform=@rules_nixpkgs_core//platforms:host" - echo "run --host_platform=@rules_nixpkgs_core//platforms:host" - fi - ''; -} diff --git a/tests/haskell_tests/BUILD.bazel b/tests/haskell_tests/BUILD.bazel new file mode 100644 index 000000000..8c4ffa0d4 --- /dev/null +++ b/tests/haskell_tests/BUILD.bazel @@ -0,0 +1,3 @@ +load(":bazel_platforms_tests.bzl", "bazel_platforms_test_suite") + +bazel_platforms_test_suite() diff --git a/tests/haskell_tests/bazel_platforms_tests.bzl b/tests/haskell_tests/bazel_platforms_tests.bzl new file mode 100644 index 000000000..78e851623 --- /dev/null +++ b/tests/haskell_tests/bazel_platforms_tests.bzl @@ -0,0 +1,97 @@ +"""Tests for `bazel_platforms` module.""" + +load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest") +load("//haskell:private/bazel_platforms.bzl", "bazel_platforms") + +def _get_os_test(ctx): + env = unittest.begin(ctx) + + tests = [ + struct( + msg = "darwin (legacy MacOS on x86_64)", + os_cpu = "darwin", + exp = "osx", + ), + struct( + os_cpu = "darwin_x86_64", + exp = "osx", + ), + struct( + os_cpu = "darwin_arm64", + exp = "osx", + ), + struct( + os_cpu = "arm64_windows", + exp = "windows", + ), + struct( + os_cpu = "x64_windows", + exp = "windows", + ), + struct( + os_cpu = "freebsd", + exp = "linux", + ), + struct( + os_cpu = "openbsd", + exp = "linux", + ), + ] + for t in tests: + actual = bazel_platforms.get_os(t.os_cpu) + msg = getattr(t, "msg", t.os_cpu) + asserts.equals(env, t.exp, actual, msg) + + return unittest.end(env) + +get_os_test = unittest.make(_get_os_test) + +def _get_cpu_test(ctx): + env = unittest.begin(ctx) + + tests = [ + struct( + msg = "darwin (legacy MacOS on x86_64)", + os_cpu = "darwin", + exp = "x86_64", + ), + struct( + os_cpu = "darwin_x86_64", + exp = "x86_64", + ), + struct( + os_cpu = "darwin_arm64", + exp = "arm64", + ), + struct( + os_cpu = "arm64_windows", + exp = "arm64", + ), + struct( + os_cpu = "x64_windows", + exp = "x86_64", + ), + struct( + os_cpu = "freebsd", + exp = "x86_64", + ), + struct( + os_cpu = "openbsd", + exp = "x86_64", + ), + ] + for t in tests: + actual = bazel_platforms.get_cpu(t.os_cpu) + msg = getattr(t, "msg", t.os_cpu) + asserts.equals(env, t.exp, actual, msg) + + return unittest.end(env) + +get_cpu_test = unittest.make(_get_cpu_test) + +def bazel_platforms_test_suite(name = "bazel_platforms_tests"): + return unittest.suite( + name, + get_os_test, + get_cpu_test, + ) From fc76c6ea3e42d3bc93d81c101e501da9f91fa240 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Tue, 19 Dec 2023 17:39:46 -0700 Subject: [PATCH 5/7] Remove unintended formatting changes. --- haskell/ghc_bindist.bzl | 51 +++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/haskell/ghc_bindist.bzl b/haskell/ghc_bindist.bzl index 0423939a2..119a866d0 100644 --- a/haskell/ghc_bindist.bzl +++ b/haskell/ghc_bindist.bzl @@ -3,10 +3,8 @@ load("@bazel_skylib//lib:paths.bzl", "paths") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "patch") load("@bazel_tools//tools/cpp:lib_cc_configure.bzl", "get_cpu_value") -load("@rules_cc//cc:find_cc_toolchain.bzl", "CC_TOOLCHAIN_TYPE") load("@rules_sh//sh:posix.bzl", "sh_posix_configure") -load("//haskell:ghc.bzl", "DEFAULT_GHC_VERSION") -load(":private/bazel_platforms.bzl", "bazel_platforms") +load("@rules_cc//cc:find_cc_toolchain.bzl", "CC_TOOLCHAIN_TYPE") load( ":private/pkgdb_to_bzl.bzl", "pkgdb_to_bzl", @@ -19,6 +17,8 @@ load( "find_python", "resolve_labels", ) +load("//haskell:ghc.bzl", "DEFAULT_GHC_VERSION") +load(":private/bazel_platforms.bzl", "bazel_platforms") _GHC_DEFAULT_VERSION = DEFAULT_GHC_VERSION @@ -87,7 +87,7 @@ def _ghc_bindist_impl(ctx): if GHC_BINDIST_STRIP_PREFIX.get(version) != None and GHC_BINDIST_STRIP_PREFIX[version].get(target) != None: stripPrefix = GHC_BINDIST_STRIP_PREFIX[version][target] else: - arch_suffix = {"amd64": "x86_64", "arm64": "aarch64"}.get(arch) + arch_suffix = {"arm64": "aarch64", "amd64": "x86_64"}.get(arch) if os == "windows" and version_tuple >= (9, 0, 1): stripPrefix += "-{}-unknown-mingw32".format(arch_suffix) @@ -263,10 +263,10 @@ rm -f "BUILD", filepaths["@rules_haskell//haskell:ghc.BUILD.tpl"], substitutions = { - "%{docdir}": docdir, - "%{is_clang}": str(is_clang), "%{toolchain_libraries}": toolchain_libraries, "%{toolchain}": toolchain, + "%{docdir}": docdir, + "%{is_clang}": str(is_clang), }, executable = False, ) @@ -275,11 +275,24 @@ _ghc_bindist = repository_rule( _ghc_bindist_impl, local = False, attrs = { - "cabalopts": attr.string_list(), + "version": attr.string( + default = _GHC_DEFAULT_VERSION, + doc = "The desired GHC version", + ), + "target": attr.string(), "ghcopts": attr.string_list(), "haddock_flags": attr.string_list(), - "locale": attr.string( - mandatory = False, + "repl_ghci_args": attr.string_list(), + "cabalopts": attr.string_list(), + "patches": attr.label_list( + default = [], + doc = + "A list of files that are to be applied as patches afer " + + "extracting the archive.", + ), + "patch_tool": attr.string( + default = "patch", + doc = "The patch(1) utility to use.", ), "patch_args": attr.string_list( default = ["-p0"], @@ -289,21 +302,8 @@ _ghc_bindist = repository_rule( default = [], doc = "Sequence of commands to be applied after patches are applied.", ), - "patch_tool": attr.string( - default = "patch", - doc = "The patch(1) utility to use.", - ), - "patches": attr.label_list( - default = [], - doc = - "A list of files that are to be applied as patches afer " + - "extracting the archive.", - ), - "repl_ghci_args": attr.string_list(), - "target": attr.string(), - "version": attr.string( - default = _GHC_DEFAULT_VERSION, - doc = "The desired GHC version", + "locale": attr.string( + mandatory = False, ), "_relpath_script": attr.label( allow_single_file = True, @@ -475,7 +475,7 @@ def ghc_bindist( "9.2.1": ["@rules_haskell//haskell:assets/ghc_9_2_1_mac.patch"], }.get(version) - extra_attrs = {"patch_args": ["-p0"], "patches": patches} if patches else {} + extra_attrs = {"patches": patches, "patch_args": ["-p0"]} if patches else {} # We want the toolchain definition to be tucked away in a separate # repository, that way `bazel build //...` will not match it (and @@ -611,6 +611,7 @@ toolchain( stub_shebang = stub_shebang, )) + _config_python3_toolchain = repository_rule( _configure_python3_toolchain_impl, configure = True, From b1f6c913842b14952e1e67276dc65501e99f877e Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Tue, 19 Dec 2023 17:48:02 -0700 Subject: [PATCH 6/7] Fix formatting --- haskell/ghc_bindist.bzl | 1 - 1 file changed, 1 deletion(-) diff --git a/haskell/ghc_bindist.bzl b/haskell/ghc_bindist.bzl index 119a866d0..9e4313900 100644 --- a/haskell/ghc_bindist.bzl +++ b/haskell/ghc_bindist.bzl @@ -611,7 +611,6 @@ toolchain( stub_shebang = stub_shebang, )) - _config_python3_toolchain = repository_rule( _configure_python3_toolchain_impl, configure = True, From c220b710a5825a737c373e129fec3eeece63650d Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Tue, 19 Dec 2023 18:07:52 -0700 Subject: [PATCH 7/7] Add darwin_x86_64 to os_info.bzl. --- tools/os_info.bzl | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/os_info.bzl b/tools/os_info.bzl index 7fc127b27..1e9090481 100644 --- a/tools/os_info.bzl +++ b/tools/os_info.bzl @@ -16,6 +16,7 @@ def _os_info_impl(repository_ctx): "aarch64", "darwin", "darwin_arm64", + "darwin_x86_64", "k8", "x64_windows", ]