diff --git a/.github/workflows/build-runai-model-streamer.yml b/.github/workflows/build-runai-model-streamer.yml index 6b6e41478457..79fd1483a0de 100644 --- a/.github/workflows/build-runai-model-streamer.yml +++ b/.github/workflows/build-runai-model-streamer.yml @@ -189,6 +189,54 @@ jobs: [ -n "$native" ] && ln -sf "$native" "/usr/bin/riscv64-linux-gnu-$tool" done + # cpp/WORKSPACE (0.17.0+) points the @cuda repository at /usr/local/cuda and + # device/cuda compiles against include/cuda.h (headers only: libcuda.so is + # dlopen()ed at run time and nothing links it). The image has no CUDA toolkit + # and NVIDIA ships none for riscv64, so take the arch-independent driver-API + # header from the nvidia-cuda-runtime-cu12 wheel. Nothing from it is packaged. + /opt/python/cp312-cp312/bin/pip download -q --no-deps --only-binary=:all: \ + --platform manylinux2014_x86_64 --python-version 3.12 \ + -d /tmp/cudart nvidia-cuda-runtime-cu12==12.9.79 + mkdir -p /usr/local/cuda/include + /opt/python/cp312-cp312/bin/python - /tmp/cudart/*.whl <<'PY' + import sys, zipfile + with zipfile.ZipFile(sys.argv[1]) as zf: + with open("/usr/local/cuda/include/cuda.h", "wb") as out: + out.write(zf.read("nvidia/cuda_runtime/include/cuda.h")) + PY + + # cpp/WORKSPACE (0.17.0+) links liburing (the io_uring engine) and libaio (its + # fallback) statically from /opt/-uring and /opt/-aio, which upstream's + # .devcontainer/Dockerfile builds for x86_64 and aarch64 only. Build the same pinned + # releases for riscv64 here (cpp/third_party/*.BUILD select them via a patch). + if [ -f cpp/third_party/uring.BUILD ]; then + ( + cd /tmp + curl -fsSL -o liburing-2.14.tar.gz https://github.com/axboe/liburing/archive/refs/tags/liburing-2.14.tar.gz + echo "5f80964108981c6ad979c735f0b4877d5f49914c2a062f8e88282f26bf61de0c liburing-2.14.tar.gz" | sha256sum -c - + tar zxf liburing-2.14.tar.gz + cd liburing-liburing-2.14 + ./configure --use-libc --prefix=/opt/riscv64-uring --libdir=/opt/riscv64-uring/lib + make -C src -j"$(nproc)" ENABLE_SHARED=0 CFLAGS="-fPIC -O2" > /dev/null + make install ENABLE_SHARED=0 > /dev/null + cd /tmp + # Upstream pins releases.pagure.org (pagure.io was sunset in 2026 and that host now + # 404s from here); the same tarball is mirrored by Debian, and the checksum rejects + # anything else. + for url in https://releases.pagure.org/libaio/libaio-0.3.113.tar.gz \ + https://deb.debian.org/debian/pool/main/liba/libaio/libaio_0.3.113.orig.tar.gz; do + curl -fsSL -o libaio-0.3.113.tar.gz "$url" && break + done + echo "2c44d1c5fd0d43752287c9ae1eb9c023f04ef848ea8d4aafa46e9aedb678200b libaio-0.3.113.tar.gz" | sha256sum -c - + tar zxf libaio-0.3.113.tar.gz + cd libaio-0.3.113 + make -C src CFLAGS="-fPIC -O2 -I." > /dev/null + mkdir -p /opt/riscv64-aio/lib /opt/riscv64-aio/include + cp src/libaio.a /opt/riscv64-aio/lib/ + cp src/libaio.h /opt/riscv64-aio/include/ + ) + fi + cd cpp bazel build streamer:libstreamer.so --config=riscv64 diff --git a/docs/packages/runai-model-streamer.yaml b/docs/packages/runai-model-streamer.yaml index 6f5e4a176c58..af43a3477638 100644 --- a/docs/packages/runai-model-streamer.yaml +++ b/docs/packages/runai-model-streamer.yaml @@ -12,3 +12,4 @@ versions: gpl-sources: filename: gpl-sources.tar description: gcc +- version: 0.17.0 diff --git a/patches/runai-model-streamer/0.17.0/0001-toolchain-add-riscv64-as-a-supported-architecture.patch b/patches/runai-model-streamer/0.17.0/0001-toolchain-add-riscv64-as-a-supported-architecture.patch new file mode 100644 index 000000000000..f465ca4124ad --- /dev/null +++ b/patches/runai-model-streamer/0.17.0/0001-toolchain-add-riscv64-as-a-supported-architecture.patch @@ -0,0 +1,50 @@ +From 820707245ffc7f9f363fc5de3f5375daacb0a8b9 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Thu, 24 Sep 2026 03:32:40 +0000 +Subject: [PATCH] toolchain: add riscv64 as a supported architecture + +configure_toolchain() and its per-arch .bazelrc block are already fully +generic over the arch string (native.platform constraint is +@platforms//cpu:, gcc tools are resolved as +/usr/bin/-linux-gnu-) -- riscv64 was simply never added to +either list. + +No -march flag is added for riscv64 (unlike aarch64's, which exists only +for a google-cloud-cpp ARM dependency libstreamer.so does not build +against): a native riscv64 build uses the compiler's own default target. + +Upstream-Status: To upstream [this port does not open issues/PRs against third-party repos; riscv64 toolchain support is exactly the kind of change upstream would want once a downstream build proves it works] +--- + cpp/.bazelrc | 3 +++ + cpp/toolchain/configure.bzl | 2 +- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/cpp/.bazelrc b/cpp/.bazelrc +index 4dc8e85..1e7f877 100644 +--- a/cpp/.bazelrc ++++ b/cpp/.bazelrc +@@ -47,5 +47,8 @@ test:tsan --run_under='setarch --addr-no-randomize' + # its RUNPATH, so the plugin is not found - a harness limit, not a property of the code under test. + test:tsan --test_tag_filters=-no_tsan + ++build:riscv64 --platform_suffix=riscv64 ++build:riscv64 --platforms=@toolchain//:riscv64 ++ + # Azurite testing support (enables AZURE_STORAGE_ACCOUNT_KEY for local testing) + build:azurite --define azurite_testing=true +diff --git a/cpp/toolchain/configure.bzl b/cpp/toolchain/configure.bzl +index 7e2e95e..b389879 100644 +--- a/cpp/toolchain/configure.bzl ++++ b/cpp/toolchain/configure.bzl +@@ -7,7 +7,7 @@ load("//toolchain:rules.bzl", "get_target_triplet", "runai_crosstool_tools") + + # This should map to the devcontainer Dockerfile + # We install gcc-x86-64-linux-gnu and gcc-aarch64-linux-gnu toolchains +-ARCHITECTURES = ["x86_64", "aarch64"] ++ARCHITECTURES = ["x86_64", "aarch64", "riscv64"] + OS = "linux-gnu" + + def _get_gcc_version(repository_ctx, arch): +-- +2.43.0 + diff --git a/patches/runai-model-streamer/0.17.0/0002-toolchain-use-gcc-s-own-dumpmachine-triplet-for-builtin-include-dirs.patch b/patches/runai-model-streamer/0.17.0/0002-toolchain-use-gcc-s-own-dumpmachine-triplet-for-builtin-include-dirs.patch new file mode 100644 index 000000000000..367c1fc785ba --- /dev/null +++ b/patches/runai-model-streamer/0.17.0/0002-toolchain-use-gcc-s-own-dumpmachine-triplet-for-builtin-include-dirs.patch @@ -0,0 +1,134 @@ +From 75c45793987328b8011252f0f24950e94456b336 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Thu, 24 Sep 2026 08:01:06 +0000 +Subject: [PATCH] toolchain: use gcc's own -dumpmachine triplet for builtin + include dirs + +configure_toolchain()'s cxx_builtin_include_directories are built from the +same os+arch naming-convention triplet (-linux-gnu) used to resolve +tool paths (/usr/bin/-linux-gnu-). That equivalence holds for a +genuine Debian cross-toolchain package (a real x86_64-linux-gnu-gcc reports +exactly that as its own -dumpmachine), but not when the tool path is a +same-arch *native* compiler reachable only via a symlink under the expected +name -- its own compiled-in builtin search path (/usr/lib/gcc///include, etc.) still uses its real vendor triplet regardless +of what name it is invoked under. + +This is exactly riscv64's manylinux_riscv64 image: gcc is Red Hat's native +riscv64-redhat-linux build, symlinked to /usr/bin/riscv64-linux-gnu-gcc so +runai_crosstool_tools() finds it. Bazel's own absolute-path sandboxing then +rejects gcc's builtin headers (e.g. stddef.h) because +/usr/lib/gcc/riscv64-redhat-linux//include is not in the declared +riscv64-linux-gnu-based list. + +Thread the compiler's actual -dumpmachine output down as gcc_machine and use +it (falling back to the naming-convention triplet when unset, so x86_64 and +aarch64 are unaffected) for cxx_builtin_include_directories specifically, +while tool_paths keeps using the naming-convention triplet the workflow's +symlinks provide. + +Upstream-Status: To upstream [this port does not open issues/PRs against third-party repos; making cxx_builtin_include_directories match the compiler's own reported triplet is a general robustness fix upstream would likely want] +--- + cpp/toolchain/configure.bzl | 7 ++++++- + cpp/toolchain/template/toolchain.bzl | 23 ++++++++++++++++++++--- + 2 files changed, 26 insertions(+), 4 deletions(-) + +diff --git a/cpp/toolchain/configure.bzl b/cpp/toolchain/configure.bzl +index 9a04125..510ef90 100644 +--- a/cpp/toolchain/configure.bzl ++++ b/cpp/toolchain/configure.bzl +@@ -11,6 +11,10 @@ def _get_gcc_version(repository_ctx, arch): + gcc_tool = runai_crosstool_tools(get_target_triplet(OS, arch))["gcc"] + return repository_ctx.execute([gcc_tool, "-dumpversion"]).stdout.strip() + ++def _get_gcc_machine(repository_ctx, arch): ++ gcc_tool = runai_crosstool_tools(get_target_triplet(OS, arch))["gcc"] ++ return repository_ctx.execute([gcc_tool, "-dumpmachine"]).stdout.strip() ++ + def _get_host_arch(repository_ctx): + return repository_ctx.execute(["/usr/bin/uname", "-m"]).stdout.strip() + +@@ -18,9 +22,10 @@ def _cc_autoconf_toolchain_impl(repository_ctx): + define_statements = [] + for arch in ARCHITECTURES: + gcc_version = _get_gcc_version(repository_ctx, arch) ++ gcc_machine = _get_gcc_machine(repository_ctx, arch) + host_arch = _get_host_arch(repository_ctx) + toolchain_name = arch +- define_statements.append('define_toolchain(name = "%s", os = "%s", host_arch = "%s", arch = "%s", gcc_version = "%s")' % (toolchain_name, OS, host_arch, arch, gcc_version)) ++ define_statements.append('define_toolchain(name = "%s", os = "%s", host_arch = "%s", arch = "%s", gcc_version = "%s", gcc_machine = "%s")' % (toolchain_name, OS, host_arch, arch, gcc_version, gcc_machine)) + + repository_ctx.template( + "BUILD", +diff --git a/cpp/toolchain/template/toolchain.bzl b/cpp/toolchain/template/toolchain.bzl +index 6a4c6cf..36daffc 100644 +--- a/cpp/toolchain/template/toolchain.bzl ++++ b/cpp/toolchain/template/toolchain.bzl +@@ -73,6 +73,15 @@ def _impl(ctx): + target_triplet = get_target_triplet(ctx.attr.os, ctx.attr.arch) + tool_paths = [tool_path(name = k, path = v) for k, v in runai_crosstool_tools(target_triplet).items()] + ++ # gcc_machine is the triplet gcc itself reports (`gcc -dumpmachine`), which is ++ # what its own builtin include search path is actually built from. It is ++ # normally identical to target_triplet (a real x86_64-linux-gnu/aarch64-linux-gnu ++ # cross-gcc reports exactly that), but differs when the "gcc" behind ++ # target_triplet's tool path is a same-arch native compiler under a different ++ # vendor triplet (e.g. Red Hat's riscv64-redhat-linux) made reachable only by a ++ # symlink under the expected name. ++ include_triplet = ctx.attr.gcc_machine if ctx.attr.gcc_machine else target_triplet ++ + # Documented at + # https://docs.bazel.build/versions/main/skylark/lib/cc_common.html#create_cc_toolchain_config_info. + # +@@ -89,7 +98,7 @@ def _impl(ctx): + abi_version = "unknown", + abi_libc_version = "unknown", + tool_paths = tool_paths, +- cxx_builtin_include_directories = _get_include_directories(target_triplet, ctx.attr.gcc_version, ctx.attr.use_cross), ++ cxx_builtin_include_directories = _get_include_directories(include_triplet, ctx.attr.gcc_version, ctx.attr.use_cross), + features = features + ) + +@@ -111,6 +120,11 @@ _toolchain_config = rule( + mandatory = True, + doc = "GCC major version to use (eg: 9)", + ), ++ "gcc_machine": attr.string( ++ mandatory = False, ++ default = "", ++ doc = "The triplet `gcc -dumpmachine` reports, if it differs from os/arch's own naming convention", ++ ), + "use_cross": attr.bool( + mandatory = False, + default = False, +@@ -121,7 +135,7 @@ _toolchain_config = rule( + ) + + +-def define_toolchain(name, os, host_arch, arch, gcc_version): ++def define_toolchain(name, os, host_arch, arch, gcc_version, gcc_machine = ""): + """"define_toolchain creates rules for a cc_toolchain. + + This expects toolchain tools to exist at a canonical path. +@@ -134,6 +148,9 @@ def define_toolchain(name, os, host_arch, arch, gcc_version): + host_arch: The host architecture for this toolchain + arch: The target architecture for this toochain + gcc_version: The GCC version of this toolchain ++ gcc_machine: The triplet `gcc -dumpmachine` reports for this toolchain's ++ compiler, if it differs from the os/arch naming convention used for ++ the tool paths themselves + """ + + native.platform( +@@ -145,7 +162,7 @@ def define_toolchain(name, os, host_arch, arch, gcc_version): + ) + + toolchain_config_name = "%s_toolchain_config" % name +- _toolchain_config(name = toolchain_config_name, os = os, arch = arch, gcc_version = gcc_version, use_cross = host_arch != arch) ++ _toolchain_config(name = toolchain_config_name, os = os, arch = arch, gcc_version = gcc_version, gcc_machine = gcc_machine, use_cross = host_arch != arch) + + empty_target_name = "%s_empty" % name + empty_target_label = ":%s" % empty_target_name +-- +2.43.0 + diff --git a/patches/runai-model-streamer/0.17.0/0003-third_party-add-riscv64-to-the-liburing-and-libaio-targets.patch b/patches/runai-model-streamer/0.17.0/0003-third_party-add-riscv64-to-the-liburing-and-libaio-targets.patch new file mode 100644 index 000000000000..5b65973a3db4 --- /dev/null +++ b/patches/runai-model-streamer/0.17.0/0003-third_party-add-riscv64-to-the-liburing-and-libaio-targets.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Fri, 30 Oct 2026 12:40:00 +0000 +Subject: [PATCH] third_party: add riscv64 to the liburing and libaio targets + +0.17.0 links liburing (the io_uring engine) and libaio (its fallback) +statically from /opt/-uring and /opt/-aio. Both repositories' +BUILD files select the library by target CPU and list only x86_64 and +aarch64, so analysis of //streamer:libstreamer.so on riscv64 fails with +"configurable attribute "actual" in @@uring//:uring doesn't match this +configuration". uring_library()/aio_library() are generic over the arch +string; add the riscv64 config_setting, library and select branch. + +Upstream-Status: To upstream [this port does not open issues/PRs against third-party repos; riscv64 support in these select()s is exactly the kind of change upstream would want once a downstream build proves it works] +--- + cpp/third_party/aio.BUILD | 9 +++++++++ + cpp/third_party/uring.BUILD | 9 +++++++++ + 2 files changed, 18 insertions(+) + +diff --git a/cpp/third_party/aio.BUILD b/cpp/third_party/aio.BUILD +index 8f844b8..1823578 100644 +--- a/cpp/third_party/aio.BUILD ++++ b/cpp/third_party/aio.BUILD +@@ -29,13 +29,22 @@ config_setting( + ], + ) + ++config_setting( ++ name = "target_riscv64", ++ constraint_values = [ ++ "@platforms//cpu:riscv64", ++ ], ++) ++ + aio_library(name = "aio_aarch", arch = "aarch64") + aio_library(name = "aio_x86_64", arch = "x86_64") ++aio_library(name = "aio_riscv64", arch = "riscv64") + + alias( + name = "aio", + actual = select({ + ":target_x86_64": ":aio_x86_64", + ":target_aarch64": ":aio_aarch", ++ ":target_riscv64": ":aio_riscv64", + }), + ) +diff --git a/cpp/third_party/uring.BUILD b/cpp/third_party/uring.BUILD +index f3c0056..2c74e89 100644 +--- a/cpp/third_party/uring.BUILD ++++ b/cpp/third_party/uring.BUILD +@@ -29,13 +29,22 @@ config_setting( + ], + ) + ++config_setting( ++ name = "target_riscv64", ++ constraint_values = [ ++ "@platforms//cpu:riscv64", ++ ], ++) ++ + uring_library(name = "uring_aarch", arch = "aarch64") + uring_library(name = "uring_x86_64", arch = "x86_64") ++uring_library(name = "uring_riscv64", arch = "riscv64") + + alias( + name = "uring", + actual = select({ + ":target_x86_64": ":uring_x86_64", + ":target_aarch64": ":uring_aarch", ++ ":target_riscv64": ":uring_riscv64", + }), + )