|
| 1 | +From 75c45793987328b8011252f0f24950e94456b336 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Ludovic Henry <git@ludovic.dev> |
| 3 | +Date: Thu, 24 Sep 2026 08:01:06 +0000 |
| 4 | +Subject: [PATCH] toolchain: use gcc's own -dumpmachine triplet for builtin |
| 5 | + include dirs |
| 6 | + |
| 7 | +configure_toolchain()'s cxx_builtin_include_directories are built from the |
| 8 | +same os+arch naming-convention triplet (<arch>-linux-gnu) used to resolve |
| 9 | +tool paths (/usr/bin/<arch>-linux-gnu-<tool>). That equivalence holds for a |
| 10 | +genuine Debian cross-toolchain package (a real x86_64-linux-gnu-gcc reports |
| 11 | +exactly that as its own -dumpmachine), but not when the tool path is a |
| 12 | +same-arch *native* compiler reachable only via a symlink under the expected |
| 13 | +name -- its own compiled-in builtin search path (/usr/lib/gcc/<real |
| 14 | +triplet>/<ver>/include, etc.) still uses its real vendor triplet regardless |
| 15 | +of what name it is invoked under. |
| 16 | + |
| 17 | +This is exactly riscv64's manylinux_riscv64 image: gcc is Red Hat's native |
| 18 | +riscv64-redhat-linux build, symlinked to /usr/bin/riscv64-linux-gnu-gcc so |
| 19 | +runai_crosstool_tools() finds it. Bazel's own absolute-path sandboxing then |
| 20 | +rejects gcc's builtin headers (e.g. stddef.h) because |
| 21 | +/usr/lib/gcc/riscv64-redhat-linux/<ver>/include is not in the declared |
| 22 | +riscv64-linux-gnu-based list. |
| 23 | + |
| 24 | +Thread the compiler's actual -dumpmachine output down as gcc_machine and use |
| 25 | +it (falling back to the naming-convention triplet when unset, so x86_64 and |
| 26 | +aarch64 are unaffected) for cxx_builtin_include_directories specifically, |
| 27 | +while tool_paths keeps using the naming-convention triplet the workflow's |
| 28 | +symlinks provide. |
| 29 | + |
| 30 | +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] |
| 31 | +--- |
| 32 | + cpp/toolchain/configure.bzl | 7 ++++++- |
| 33 | + cpp/toolchain/template/toolchain.bzl | 23 ++++++++++++++++++++--- |
| 34 | + 2 files changed, 26 insertions(+), 4 deletions(-) |
| 35 | + |
| 36 | +diff --git a/cpp/toolchain/configure.bzl b/cpp/toolchain/configure.bzl |
| 37 | +index 9a04125..510ef90 100644 |
| 38 | +--- a/cpp/toolchain/configure.bzl |
| 39 | ++++ b/cpp/toolchain/configure.bzl |
| 40 | +@@ -11,6 +11,10 @@ def _get_gcc_version(repository_ctx, arch): |
| 41 | + gcc_tool = runai_crosstool_tools(get_target_triplet(OS, arch))["gcc"] |
| 42 | + return repository_ctx.execute([gcc_tool, "-dumpversion"]).stdout.strip() |
| 43 | + |
| 44 | ++def _get_gcc_machine(repository_ctx, arch): |
| 45 | ++ gcc_tool = runai_crosstool_tools(get_target_triplet(OS, arch))["gcc"] |
| 46 | ++ return repository_ctx.execute([gcc_tool, "-dumpmachine"]).stdout.strip() |
| 47 | ++ |
| 48 | + def _get_host_arch(repository_ctx): |
| 49 | + return repository_ctx.execute(["/usr/bin/uname", "-m"]).stdout.strip() |
| 50 | + |
| 51 | +@@ -18,9 +22,10 @@ def _cc_autoconf_toolchain_impl(repository_ctx): |
| 52 | + define_statements = [] |
| 53 | + for arch in ARCHITECTURES: |
| 54 | + gcc_version = _get_gcc_version(repository_ctx, arch) |
| 55 | ++ gcc_machine = _get_gcc_machine(repository_ctx, arch) |
| 56 | + host_arch = _get_host_arch(repository_ctx) |
| 57 | + toolchain_name = arch |
| 58 | +- 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)) |
| 59 | ++ 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)) |
| 60 | + |
| 61 | + repository_ctx.template( |
| 62 | + "BUILD", |
| 63 | +diff --git a/cpp/toolchain/template/toolchain.bzl b/cpp/toolchain/template/toolchain.bzl |
| 64 | +index 6a4c6cf..36daffc 100644 |
| 65 | +--- a/cpp/toolchain/template/toolchain.bzl |
| 66 | ++++ b/cpp/toolchain/template/toolchain.bzl |
| 67 | +@@ -73,6 +73,15 @@ def _impl(ctx): |
| 68 | + target_triplet = get_target_triplet(ctx.attr.os, ctx.attr.arch) |
| 69 | + tool_paths = [tool_path(name = k, path = v) for k, v in runai_crosstool_tools(target_triplet).items()] |
| 70 | + |
| 71 | ++ # gcc_machine is the triplet gcc itself reports (`gcc -dumpmachine`), which is |
| 72 | ++ # what its own builtin include search path is actually built from. It is |
| 73 | ++ # normally identical to target_triplet (a real x86_64-linux-gnu/aarch64-linux-gnu |
| 74 | ++ # cross-gcc reports exactly that), but differs when the "gcc" behind |
| 75 | ++ # target_triplet's tool path is a same-arch native compiler under a different |
| 76 | ++ # vendor triplet (e.g. Red Hat's riscv64-redhat-linux) made reachable only by a |
| 77 | ++ # symlink under the expected name. |
| 78 | ++ include_triplet = ctx.attr.gcc_machine if ctx.attr.gcc_machine else target_triplet |
| 79 | ++ |
| 80 | + # Documented at |
| 81 | + # https://docs.bazel.build/versions/main/skylark/lib/cc_common.html#create_cc_toolchain_config_info. |
| 82 | + # |
| 83 | +@@ -89,7 +98,7 @@ def _impl(ctx): |
| 84 | + abi_version = "unknown", |
| 85 | + abi_libc_version = "unknown", |
| 86 | + tool_paths = tool_paths, |
| 87 | +- cxx_builtin_include_directories = _get_include_directories(target_triplet, ctx.attr.gcc_version, ctx.attr.use_cross), |
| 88 | ++ cxx_builtin_include_directories = _get_include_directories(include_triplet, ctx.attr.gcc_version, ctx.attr.use_cross), |
| 89 | + features = features |
| 90 | + ) |
| 91 | + |
| 92 | +@@ -111,6 +120,11 @@ _toolchain_config = rule( |
| 93 | + mandatory = True, |
| 94 | + doc = "GCC major version to use (eg: 9)", |
| 95 | + ), |
| 96 | ++ "gcc_machine": attr.string( |
| 97 | ++ mandatory = False, |
| 98 | ++ default = "", |
| 99 | ++ doc = "The triplet `gcc -dumpmachine` reports, if it differs from os/arch's own naming convention", |
| 100 | ++ ), |
| 101 | + "use_cross": attr.bool( |
| 102 | + mandatory = False, |
| 103 | + default = False, |
| 104 | +@@ -121,7 +135,7 @@ _toolchain_config = rule( |
| 105 | + ) |
| 106 | + |
| 107 | + |
| 108 | +-def define_toolchain(name, os, host_arch, arch, gcc_version): |
| 109 | ++def define_toolchain(name, os, host_arch, arch, gcc_version, gcc_machine = ""): |
| 110 | + """"define_toolchain creates rules for a cc_toolchain. |
| 111 | + |
| 112 | + This expects toolchain tools to exist at a canonical path. |
| 113 | +@@ -134,6 +148,9 @@ def define_toolchain(name, os, host_arch, arch, gcc_version): |
| 114 | + host_arch: The host architecture for this toolchain |
| 115 | + arch: The target architecture for this toochain |
| 116 | + gcc_version: The GCC version of this toolchain |
| 117 | ++ gcc_machine: The triplet `gcc -dumpmachine` reports for this toolchain's |
| 118 | ++ compiler, if it differs from the os/arch naming convention used for |
| 119 | ++ the tool paths themselves |
| 120 | + """ |
| 121 | + |
| 122 | + native.platform( |
| 123 | +@@ -145,7 +162,7 @@ def define_toolchain(name, os, host_arch, arch, gcc_version): |
| 124 | + ) |
| 125 | + |
| 126 | + toolchain_config_name = "%s_toolchain_config" % name |
| 127 | +- _toolchain_config(name = toolchain_config_name, os = os, arch = arch, gcc_version = gcc_version, use_cross = host_arch != arch) |
| 128 | ++ _toolchain_config(name = toolchain_config_name, os = os, arch = arch, gcc_version = gcc_version, gcc_machine = gcc_machine, use_cross = host_arch != arch) |
| 129 | + |
| 130 | + empty_target_name = "%s_empty" % name |
| 131 | + empty_target_label = ":%s" % empty_target_name |
| 132 | +-- |
| 133 | +2.43.0 |
| 134 | + |
0 commit comments