From 1d8128b2f5e50d817d25281b532ebfede0fee5f2 Mon Sep 17 00:00:00 2001 From: Gunnar Wagenknecht Date: Tue, 19 Aug 2025 15:13:12 +0200 Subject: [PATCH 1/2] Set target_compatible_with for host execution toolchain Fixes #3854 --- nodejs/private/nodejs_toolchains_repo.bzl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/nodejs/private/nodejs_toolchains_repo.bzl b/nodejs/private/nodejs_toolchains_repo.bzl index 7758f3edb4..888ec05231 100644 --- a/nodejs/private/nodejs_toolchains_repo.bzl +++ b/nodejs/private/nodejs_toolchains_repo.bzl @@ -107,9 +107,27 @@ resolved_toolchain(name = "resolved_toolchain", visibility = ["//visibility:publ for [platform, meta] in PLATFORMS.items(): build_content += """ +# Toolchain resolution is quite complex when it has to choose between both target and exec platform. +# When building any target it has both exec and target platform set. +# On the other hand the toolchain resolution tries to find the first one that matches. The order is lexicographical +# based on native.toolchain's name. +# This means that when you build a target for linux-arm64 on linux-amd64 +# toolchain resolution would match following toolchains: +# toolchain(name=linux-amd64, exec_compatible_with==linux-amd64) +# toolchain(name=linux-arm64, target_compatible_with=linux-arm64) +# and "linux-amd64" would be chosen as the first one lexicographically. +# Such result would lead to issues for cross platform builds, for example amd64 choosing wrongling for arm64 target. +# To circumvent this, we define 2 types of toolchains: +# - target toolchain that matches target platform constraint (but doesn't bother about exec). +# - exec toolchain that must match both exec and target platform. +# As a result, targets that have target platform different from exec platform will only be able to pick +# target toolchains. +# On the other hand we assume that if one wants to execute the rule, target platform should match exec platform. +# In such cases it doesn't matter whether the target or exec toolchain is picked. toolchain( name = "{platform}_toolchain", exec_compatible_with = {compatible_with}, + target_compatible_with = {compatible_with}, toolchain = "@{user_node_repository_name}_{platform}//:toolchain", toolchain_type = "@rules_nodejs//nodejs:toolchain_type", ) From d3ad84e95c3ba3d527223b399d5ee32d1c61c183 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Fri, 22 Aug 2025 10:52:08 -0700 Subject: [PATCH 2/2] Update nodejs_toolchains_repo.bzl I think it's what @jbedard was asking for --- nodejs/private/nodejs_toolchains_repo.bzl | 34 +++++++++++------------ 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/nodejs/private/nodejs_toolchains_repo.bzl b/nodejs/private/nodejs_toolchains_repo.bzl index 888ec05231..4e066b00fb 100644 --- a/nodejs/private/nodejs_toolchains_repo.bzl +++ b/nodejs/private/nodejs_toolchains_repo.bzl @@ -106,24 +106,24 @@ resolved_toolchain(name = "resolved_toolchain", visibility = ["//visibility:publ """ for [platform, meta] in PLATFORMS.items(): + # Toolchain resolution is quite complex when it has to choose between both target and exec platform. + # When building any target it has both exec and target platform set. + # On the other hand the toolchain resolution tries to find the first one that matches. The order is lexicographical + # based on native.toolchain's name. + # This means that when you build a target for linux-arm64 on linux-amd64 + # toolchain resolution would match following toolchains: + # toolchain(name=linux-amd64, exec_compatible_with==linux-amd64) + # toolchain(name=linux-arm64, target_compatible_with=linux-arm64) + # and "linux-amd64" would be chosen as the first one lexicographically. + # Such result would lead to issues for cross platform builds, for example amd64 choosing wrongling for arm64 target. + # To circumvent this, we define 2 types of toolchains: + # - target toolchain that matches target platform constraint (but doesn't bother about exec). + # - exec toolchain that must match both exec and target platform. + # As a result, targets that have target platform different from exec platform will only be able to pick + # target toolchains. + # On the other hand we assume that if one wants to execute the rule, target platform should match exec platform. + # In such cases it doesn't matter whether the target or exec toolchain is picked. build_content += """ -# Toolchain resolution is quite complex when it has to choose between both target and exec platform. -# When building any target it has both exec and target platform set. -# On the other hand the toolchain resolution tries to find the first one that matches. The order is lexicographical -# based on native.toolchain's name. -# This means that when you build a target for linux-arm64 on linux-amd64 -# toolchain resolution would match following toolchains: -# toolchain(name=linux-amd64, exec_compatible_with==linux-amd64) -# toolchain(name=linux-arm64, target_compatible_with=linux-arm64) -# and "linux-amd64" would be chosen as the first one lexicographically. -# Such result would lead to issues for cross platform builds, for example amd64 choosing wrongling for arm64 target. -# To circumvent this, we define 2 types of toolchains: -# - target toolchain that matches target platform constraint (but doesn't bother about exec). -# - exec toolchain that must match both exec and target platform. -# As a result, targets that have target platform different from exec platform will only be able to pick -# target toolchains. -# On the other hand we assume that if one wants to execute the rule, target platform should match exec platform. -# In such cases it doesn't matter whether the target or exec toolchain is picked. toolchain( name = "{platform}_toolchain", exec_compatible_with = {compatible_with},