From 48a981c9678e0f3a24e858bf20d945c6ff1e51ed Mon Sep 17 00:00:00 2001 From: ffgan Date: Fri, 25 Sep 2026 16:38:32 +0800 Subject: [PATCH] Add Linux riscv64 musl and glibc toolchains on Zig 0.15.2. Zig 0.15.2 can cross-compile riscv64, with glibc support starting at 2.27 and headers under riscv-linux-* rather than riscv64-linux-*. --- MODULE.bazel | 4 ++++ README.md | 1 + test/glibc_hacks/BUILD | 2 ++ toolchain/defs.bzl | 2 ++ toolchain/ext.bzl | 2 +- toolchain/platform/defs.bzl | 31 +++++++++++++++++++++++++------ toolchain/private/defs.bzl | 17 ++++++++++++++--- toolchain/private/zig_sdk.bzl | 1 + toolchain/zig-wrapper.zig | 2 +- 9 files changed, 51 insertions(+), 11 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 143035bf..0054d5ae 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -53,6 +53,10 @@ register_toolchains( "@zig_sdk//libc_aware/toolchain:linux_arm64_gnu.2.28", "@zig_sdk//libc_aware/toolchain:linux_arm64_musl", + # riscv64 toolchains for libc-aware platforms: + "@zig_sdk//libc_aware/toolchain:linux_riscv64_gnu.2.28", + "@zig_sdk//libc_aware/toolchain:linux_riscv64_musl", + # wasm/wasi toolchains "@zig_sdk//toolchain:wasip1_wasm", "@zig_sdk//toolchain:none_wasm", diff --git a/README.md b/README.md index 9a3f9ad2..397c09a0 100644 --- a/README.md +++ b/README.md @@ -517,6 +517,7 @@ This repository is used on the following (host) platforms: - `linux_amd64`, a.k.a. `x86_64`. - `linux_arm64`, a.k.a. `AArch64`. +- `linux_riscv64`. - `darwin_amd64`, the 64-bit post-PowerPC models. - `darwin_arm64`, the M1. - `windows_amd64`, a.k.a. `x64`. diff --git a/test/glibc_hacks/BUILD b/test/glibc_hacks/BUILD index d830a20c..5951a758 100644 --- a/test/glibc_hacks/BUILD +++ b/test/glibc_hacks/BUILD @@ -21,5 +21,7 @@ cc_binary( ("linux_amd64_musl", "//libc_aware/platform:linux_amd64_musl"), ("linux_amd64_gnu.2.28", "//libc_aware/platform:linux_amd64_gnu.2.28"), ("linux_arm64_musl", "//libc_aware/platform:linux_arm64_musl"), + ("linux_riscv64_musl", "//libc_aware/platform:linux_riscv64_musl"), + ("linux_riscv64_gnu.2.28", "//libc_aware/platform:linux_riscv64_gnu.2.28"), ] ] diff --git a/toolchain/defs.bzl b/toolchain/defs.bzl index 602a42d6..65e96d82 100644 --- a/toolchain/defs.bzl +++ b/toolchain/defs.bzl @@ -22,6 +22,7 @@ _DEFAULT_INCLUDE_DIRECTORIES = [ _HOST_PLATFORM_EXT = { "linux-aarch64": "tar.xz", + "linux-riscv64": "tar.xz", "linux-x86_64": "tar.xz", "macos-aarch64": "tar.xz", "macos-x86_64": "tar.xz", @@ -32,6 +33,7 @@ _HOST_PLATFORM_EXT = { # map bazel's host_platform to zig's -target= and -mcpu= _TARGET_MCPU = { "linux-aarch64": ("aarch64-linux-musl", "baseline"), + "linux-riscv64": ("riscv64-linux-musl", "baseline"), "linux-x86_64": ("x86_64-linux-musl", "baseline"), "macos-aarch64": ("aarch64-macos-none", "apple_a14"), "macos-x86_64": ("x86_64-macos-none", "baseline"), diff --git a/toolchain/ext.bzl b/toolchain/ext.bzl index 9c8d82ec..50136493 100644 --- a/toolchain/ext.bzl +++ b/toolchain/ext.bzl @@ -8,7 +8,7 @@ _exec_platform = tag_class( mandatory = True, ), "arch": attr.string( - values = ["amd64", "arm64"], + values = ["amd64", "arm64", "riscv64"], mandatory = True, ), }, diff --git a/toolchain/platform/defs.bzl b/toolchain/platform/defs.bzl index 3c2896bc..ec1b49ad 100644 --- a/toolchain/platform/defs.bzl +++ b/toolchain/platform/defs.bzl @@ -1,4 +1,4 @@ -load("@hermetic_cc_toolchain//toolchain/private:defs.bzl", "LIBCS") +load("@hermetic_cc_toolchain//toolchain/private:defs.bzl", "LIBCS", "RISCV64_LIBCS") _CPUS = (("x86_64", "amd64"), ("aarch64", "arm64")) _OS = { @@ -18,6 +18,9 @@ def declare_platforms(): declare_platform("wasm", "wasm32", "wasi", "wasip1") declare_platform("wasm", "wasm32", "none", "none") + # gocpu and zigcpu are both riscv64, so this declares a single linux_riscv64 platform. + declare_platform("riscv64", "riscv64", "linux", "linux") + def declare_libc_aware_platforms(): # create @zig_sdk//{os}_{arch}_platform entries with zig and go conventions # with libc specified @@ -32,18 +35,34 @@ def declare_libc_aware_platforms(): extra_constraints = ["//libc:{}".format(libc)], ) + for libc in RISCV64_LIBCS: + declare_platform( + "riscv64", + "riscv64", + "linux", + "linux", + suffix = "_{}".format(libc), + extra_constraints = ["//libc:{}".format(libc)], + ) + def declare_platform(gocpu, zigcpu, bzlos, os, suffix = "", extra_constraints = []): constraint_values = [ "@platforms//os:{}".format(bzlos), "@platforms//cpu:{}".format(zigcpu), ] + extra_constraints - native.platform( - name = "{os}_{zigcpu}{suffix}".format(os = os, zigcpu = zigcpu, suffix = suffix), - constraint_values = constraint_values, - ) + zig_name = "{os}_{zigcpu}{suffix}".format(os = os, zigcpu = zigcpu, suffix = suffix) + go_name = "{os}_{gocpu}{suffix}".format(os = os, gocpu = gocpu, suffix = suffix) native.platform( - name = "{os}_{gocpu}{suffix}".format(os = os, gocpu = gocpu, suffix = suffix), + name = zig_name, constraint_values = constraint_values, ) + + # amd64/arm64 use different Go and Zig arch names, so both aliases exist. + # riscv64 uses the same name in both, and a second platform() would collide. + if go_name != zig_name: + native.platform( + name = go_name, + constraint_values = constraint_values, + ) diff --git a/toolchain/private/defs.bzl b/toolchain/private/defs.bzl index f900205d..e2c1e6d7 100644 --- a/toolchain/private/defs.bzl +++ b/toolchain/private/defs.bzl @@ -37,6 +37,11 @@ _INCLUDE_TAIL = [ LIBCS = ["musl"] + ["gnu.{}".format(glibc) for glibc in _GLIBCS] +# RISC-V was added to glibc in 2.27. Zig 0.15.2 rejects older versions +# (lib/std/zig/target.zig: riscv64 linux gnu glibc_min = 2.27). +_RISCV64_GLIBCS = _GLIBCS[_GLIBCS.index("2.27"):] +RISCV64_LIBCS = ["musl"] + ["gnu.{}".format(glibc) for glibc in _RISCV64_GLIBCS] + def zig_tool_path(os): if os == "windows": return _ZIG_TOOL_PATH + ".exe" @@ -51,6 +56,9 @@ def target_structs(): ret.append(_target_linux_musl(gocpu, zigcpu)) for glibc in _GLIBCS: ret.append(_target_linux_gnu(gocpu, zigcpu, glibc)) + ret.append(_target_linux_musl("riscv64", "riscv64")) + for glibc in _RISCV64_GLIBCS: + ret.append(_target_linux_gnu("riscv64", "riscv64", glibc)) ret.append(_target_wasm()) ret.append(_target_wasm_no_wasi()) return ret @@ -160,8 +168,9 @@ def _target_linux_gnu(gocpu, zigcpu, glibc_version): # x86-linux-gnu dir. x86_64-linux-any never existed and is # likewise covered by x86-linux-any. (["libc/include/x86-linux-gnu", "libc/include/x86-linux-any"] if zigcpu == "x86_64" else [ - "libc/include/{}-linux-gnu".format(zigcpu), - "libc/include/{}-linux-any".format(zigcpu), + # Zig names the RISC-V glibc headers riscv-linux-gnu, not riscv64-linux-gnu. + "libc/include/riscv-linux-gnu" if zigcpu == "riscv64" else "libc/include/{}-linux-gnu".format(zigcpu), + "libc/include/riscv-linux-any" if zigcpu == "riscv64" else "libc/include/{}-linux-any".format(zigcpu), ]) + [ "libc/include/any-linux-any", ] + _INCLUDE_TAIL, @@ -195,7 +204,9 @@ def _target_linux_musl(gocpu, zigcpu): ] + # x86_64-linux-any is x86_64-linux and x86-linux combined. (["libc/include/x86-linux-any"] if zigcpu == "x86_64" else []) + - (["libc/include/{}-linux-any".format(zigcpu)] if zigcpu != "x86_64" else []) + [ + # Zig names the RISC-V asm headers riscv-linux-any, not riscv64-linux-any. + (["libc/include/riscv-linux-any"] if zigcpu == "riscv64" else []) + + (["libc/include/{}-linux-any".format(zigcpu)] if zigcpu not in ("x86_64", "riscv64") else []) + [ "libc/include/any-linux-any", ] + _INCLUDE_TAIL, linkopts = [], diff --git a/toolchain/private/zig_sdk.bzl b/toolchain/private/zig_sdk.bzl index c7b8129e..4da057dd 100644 --- a/toolchain/private/zig_sdk.bzl +++ b/toolchain/private/zig_sdk.bzl @@ -2,6 +2,7 @@ VERSION = "0.15.2" HOST_PLATFORM_SHA256 = { "linux-aarch64": "958ed7d1e00d0ea76590d27666efbf7a932281b3d7ba0c6b01b0ff26498f667f", + "linux-riscv64": "493512bdca485be3c6a9b0f69dcb4cbe4587f3af8e1be282fdd827108ba39930", "linux-x86_64": "02aa270f183da276e5b5920b1dac44a63f1a49e55050ebde3aecc9eb82f93239", "macos-aarch64": "3cc2bab367e185cdfb27501c4b30b1b0653c28d9f73df8dc91488e66ece5fa6b", "macos-x86_64": "375b6909fc1495d16fc2c7db9538f707456bfc3373b14ee83fdd3e22b3d43f7f", diff --git a/toolchain/zig-wrapper.zig b/toolchain/zig-wrapper.zig index 172b5187..c46aac2d 100644 --- a/toolchain/zig-wrapper.zig +++ b/toolchain/zig-wrapper.zig @@ -378,7 +378,7 @@ fn getRunMode(self_exe: []const u8, self_base_noexe: []const u8) error{BadParent var it = mem.splitScalar(u8, triple, '-'); const arch = it.next() orelse return error.BadParent; - if (mem.indexOf(u8, "aarch64,x86_64,wasm32", arch) == null) + if (mem.indexOf(u8, "aarch64,x86_64,wasm32,riscv64", arch) == null) return error.BadParent; const got_os = it.next() orelse return error.BadParent;