From 3537527225adb1df741c790c368d57b0aab1fe55 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Fri, 10 Apr 2026 13:38:28 -0700 Subject: [PATCH 1/5] Improve cross exec platform toolchain selection With bazel 9.x+ we can force the rules being run to be for the target platform using the default_test_toolchain_type. This shouldn't affect behavior for older versions. Also adds a test on CI for this case. Related https://github.com/keith/buildifier-prebuilt/pull/113 https://github.com/keith/buildifier-prebuilt/pull/124 This is trying to work around https://github.com/bazelbuild/bazel/issues/19645 --- .github/workflows/ci.yml | 2 ++ BUILD | 9 +++++++++ MODULE.bazel | 1 + buildifier/buildifier_binary.bzl | 12 +++++++++--- buildifier/factory.bzl | 5 ++++- buildozer/buildozer_binary.bzl | 12 +++++++++--- rules.bzl | 21 ++++++++++++++++++--- 7 files changed, 52 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 167f9d0..23d84e3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,6 +34,8 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: bazelisk test //:all_integration_tests + - name: Run with extra exec platforms + run: bazelisk run //:buildifier --extra_execution_platforms=//:non_host_platform,@platforms//host -- -help example_simple: strategy: diff --git a/BUILD b/BUILD index a498a8f..fcda4a6 100644 --- a/BUILD +++ b/BUILD @@ -58,6 +58,15 @@ alias( # MARK: - Integration Test +# A platform used for tests that must not match the host platform +platform( + name = "non_host_platform", + constraint_values = [ + "@platforms//os:linux", + "@platforms//cpu:riscv64", + ], +) + filegroup( name = "local_repository_files", srcs = [ diff --git a/MODULE.bazel b/MODULE.bazel index eb955b5..adc4c59 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -4,6 +4,7 @@ module( compatibility_level = 1, ) +bazel_dep(name = "bazel_features", version = "1.45.0") bazel_dep(name = "bazel_skylib", version = "1.3.0") bazel_dep(name = "platforms", version = "0.0.11") bazel_dep(name = "rules_shell", version = "0.6.1") diff --git a/buildifier/buildifier_binary.bzl b/buildifier/buildifier_binary.bzl index 6bd8640..638388f 100644 --- a/buildifier/buildifier_binary.bzl +++ b/buildifier/buildifier_binary.bzl @@ -2,8 +2,11 @@ Simple rule for running buildifier from the toolchain config """ +load("@bazel_features//:features.bzl", "bazel_features") load("@platforms//host:constraints.bzl", "HOST_CONSTRAINTS") +_TEST_TOOLCHAIN = bazel_features.toolchains.has_default_test_toolchain_type + def _buildifier_binary(ctx): buildifier = ctx.toolchains["@buildifier_prebuilt//buildifier:toolchain"]._tool script = ctx.actions.declare_file("buildifier") @@ -22,8 +25,11 @@ def _buildifier_binary(ctx): buildifier_binary = rule( implementation = _buildifier_binary, - attrs = {}, - exec_compatible_with = HOST_CONSTRAINTS, - toolchains = ["@buildifier_prebuilt//buildifier:toolchain"], + exec_compatible_with = [] if _TEST_TOOLCHAIN else HOST_CONSTRAINTS, + toolchains = [ + "@buildifier_prebuilt//buildifier:toolchain", + ] + ([ + "@bazel_tools//tools/test:default_test_toolchain_type", + ] if _TEST_TOOLCHAIN else []), executable = True, ) diff --git a/buildifier/factory.bzl b/buildifier/factory.bzl index 40978bc..d8d8bc3 100644 --- a/buildifier/factory.bzl +++ b/buildifier/factory.bzl @@ -142,7 +142,10 @@ def buildifier_impl_factory(ctx, *, test_rule): fail("Cannot use 'no_sandbox' without a 'workspace'") workspace = ctx.file.workspace.path - toolchain = ctx.toolchains["@buildifier_prebuilt//buildifier:toolchain"] + if test_rule: + toolchain = ctx.exec_groups["test"].toolchains["@buildifier_prebuilt//buildifier:toolchain"] + else: + toolchain = ctx.toolchains["@buildifier_prebuilt//buildifier:toolchain"] buildifier = toolchain._tool runner = toolchain._runner diff --git a/buildozer/buildozer_binary.bzl b/buildozer/buildozer_binary.bzl index d6e72bc..684a794 100644 --- a/buildozer/buildozer_binary.bzl +++ b/buildozer/buildozer_binary.bzl @@ -2,8 +2,11 @@ Simple rule for running buildozer from the toolchain config """ +load("@bazel_features//:features.bzl", "bazel_features") load("@platforms//host:constraints.bzl", "HOST_CONSTRAINTS") +_TEST_TOOLCHAIN = bazel_features.toolchains.has_default_test_toolchain_type + def _buildozer_binary(ctx): buildozer = ctx.toolchains["@buildifier_prebuilt//buildozer:toolchain"]._tool script = ctx.actions.declare_file("buildozer") @@ -22,8 +25,11 @@ def _buildozer_binary(ctx): buildozer_binary = rule( implementation = _buildozer_binary, - attrs = {}, - exec_compatible_with = HOST_CONSTRAINTS, - toolchains = ["@buildifier_prebuilt//buildozer:toolchain"], + exec_compatible_with = [] if _TEST_TOOLCHAIN else HOST_CONSTRAINTS, + toolchains = [ + "@buildifier_prebuilt//buildozer:toolchain", + ] + ([ + "@bazel_tools//tools/test:default_test_toolchain_type", + ] if _TEST_TOOLCHAIN else []), executable = True, ) diff --git a/rules.bzl b/rules.bzl index 281d10c..8514c84 100644 --- a/rules.bzl +++ b/rules.bzl @@ -2,6 +2,7 @@ Rules to use the prebuilt buildifier / buildozer binaries """ +load("@bazel_features//:features.bzl", "bazel_features") load("@platforms//host:constraints.bzl", "HOST_CONSTRAINTS") load("//buildifier:buildifier_binary.bzl", _buildifier_binary = "buildifier_binary") load( @@ -11,6 +12,8 @@ load( ) load("//buildozer:buildozer_binary.bzl", _buildozer_binary = "buildozer_binary") +_TEST_TOOLCHAIN = bazel_features.toolchains.has_default_test_toolchain_type + buildifier_binary = _buildifier_binary buildozer_binary = _buildozer_binary @@ -20,8 +23,12 @@ def _buildifier_impl(ctx): buildifier = rule( implementation = _buildifier_impl, attrs = buildifier_attr_factory(test_rule = False), - exec_compatible_with = HOST_CONSTRAINTS, - toolchains = ["@buildifier_prebuilt//buildifier:toolchain"], + exec_compatible_with = [] if _TEST_TOOLCHAIN else HOST_CONSTRAINTS, + toolchains = [ + "@buildifier_prebuilt//buildifier:toolchain", + ] + ([ + "@bazel_tools//tools/test:default_test_toolchain_type", + ] if _TEST_TOOLCHAIN else []), executable = True, ) @@ -32,7 +39,15 @@ _buildifier_test = rule( implementation = _buildifier_test_impl, attrs = buildifier_attr_factory(test_rule = True), exec_compatible_with = HOST_CONSTRAINTS, - toolchains = ["@buildifier_prebuilt//buildifier:toolchain"], + exec_groups = { + "test": exec_group( + toolchains = [ + "@buildifier_prebuilt//buildifier:toolchain", + ] + ([ + "@bazel_tools//tools/test:default_test_toolchain_type", + ] if _TEST_TOOLCHAIN else []), + ), + }, test = True, ) From 3bd714abe359017bc7b592f6364fd42c9c641323 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Fri, 10 Apr 2026 13:44:40 -0700 Subject: [PATCH 2/5] inline --- buildifier/buildifier_binary.bzl | 6 ++---- buildozer/buildozer_binary.bzl | 6 ++---- rules.bzl | 8 +++----- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/buildifier/buildifier_binary.bzl b/buildifier/buildifier_binary.bzl index 638388f..8213df8 100644 --- a/buildifier/buildifier_binary.bzl +++ b/buildifier/buildifier_binary.bzl @@ -5,8 +5,6 @@ Simple rule for running buildifier from the toolchain config load("@bazel_features//:features.bzl", "bazel_features") load("@platforms//host:constraints.bzl", "HOST_CONSTRAINTS") -_TEST_TOOLCHAIN = bazel_features.toolchains.has_default_test_toolchain_type - def _buildifier_binary(ctx): buildifier = ctx.toolchains["@buildifier_prebuilt//buildifier:toolchain"]._tool script = ctx.actions.declare_file("buildifier") @@ -25,11 +23,11 @@ def _buildifier_binary(ctx): buildifier_binary = rule( implementation = _buildifier_binary, - exec_compatible_with = [] if _TEST_TOOLCHAIN else HOST_CONSTRAINTS, + exec_compatible_with = [] if bazel_features.toolchains.has_default_test_toolchain_type else HOST_CONSTRAINTS, toolchains = [ "@buildifier_prebuilt//buildifier:toolchain", ] + ([ "@bazel_tools//tools/test:default_test_toolchain_type", - ] if _TEST_TOOLCHAIN else []), + ] if bazel_features.toolchains.has_default_test_toolchain_type else []), executable = True, ) diff --git a/buildozer/buildozer_binary.bzl b/buildozer/buildozer_binary.bzl index 684a794..25c56e6 100644 --- a/buildozer/buildozer_binary.bzl +++ b/buildozer/buildozer_binary.bzl @@ -5,8 +5,6 @@ Simple rule for running buildozer from the toolchain config load("@bazel_features//:features.bzl", "bazel_features") load("@platforms//host:constraints.bzl", "HOST_CONSTRAINTS") -_TEST_TOOLCHAIN = bazel_features.toolchains.has_default_test_toolchain_type - def _buildozer_binary(ctx): buildozer = ctx.toolchains["@buildifier_prebuilt//buildozer:toolchain"]._tool script = ctx.actions.declare_file("buildozer") @@ -25,11 +23,11 @@ def _buildozer_binary(ctx): buildozer_binary = rule( implementation = _buildozer_binary, - exec_compatible_with = [] if _TEST_TOOLCHAIN else HOST_CONSTRAINTS, + exec_compatible_with = [] if bazel_features.toolchains.has_default_test_toolchain_type else HOST_CONSTRAINTS, toolchains = [ "@buildifier_prebuilt//buildozer:toolchain", ] + ([ "@bazel_tools//tools/test:default_test_toolchain_type", - ] if _TEST_TOOLCHAIN else []), + ] if bazel_features.toolchains.has_default_test_toolchain_type else []), executable = True, ) diff --git a/rules.bzl b/rules.bzl index 8514c84..a058da4 100644 --- a/rules.bzl +++ b/rules.bzl @@ -12,8 +12,6 @@ load( ) load("//buildozer:buildozer_binary.bzl", _buildozer_binary = "buildozer_binary") -_TEST_TOOLCHAIN = bazel_features.toolchains.has_default_test_toolchain_type - buildifier_binary = _buildifier_binary buildozer_binary = _buildozer_binary @@ -23,12 +21,12 @@ def _buildifier_impl(ctx): buildifier = rule( implementation = _buildifier_impl, attrs = buildifier_attr_factory(test_rule = False), - exec_compatible_with = [] if _TEST_TOOLCHAIN else HOST_CONSTRAINTS, + exec_compatible_with = [] if bazel_features.toolchains.has_default_test_toolchain_type else HOST_CONSTRAINTS, toolchains = [ "@buildifier_prebuilt//buildifier:toolchain", ] + ([ "@bazel_tools//tools/test:default_test_toolchain_type", - ] if _TEST_TOOLCHAIN else []), + ] if bazel_features.toolchains.has_default_test_toolchain_type else []), executable = True, ) @@ -45,7 +43,7 @@ _buildifier_test = rule( "@buildifier_prebuilt//buildifier:toolchain", ] + ([ "@bazel_tools//tools/test:default_test_toolchain_type", - ] if _TEST_TOOLCHAIN else []), + ] if bazel_features.toolchains.has_default_test_toolchain_type else []), ), }, test = True, From 4177c0d7d446030b245d90d5d9823506317e270f Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Fri, 10 Apr 2026 13:44:49 -0700 Subject: [PATCH 3/5] workspace --- deps.bzl | 8 ++++++++ examples/simple/WORKSPACE | 4 ++++ examples/specify_assets/WORKSPACE | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/deps.bzl b/deps.bzl index c9718ed..334e14e 100644 --- a/deps.bzl +++ b/deps.bzl @@ -23,3 +23,11 @@ def buildifier_prebuilt_deps(): strip_prefix = "rules_shell-0.6.1", url = "https://github.com/bazelbuild/rules_shell/releases/download/v0.6.1/rules_shell-v0.6.1.tar.gz", ) + + maybe( + http_archive, + name = "bazel_features", + sha256 = "adfdb3cffab3a99a63363d844d559a81965d2b61a6062dd51a3d2478d416768f", + strip_prefix = "bazel_features-1.45.0", + url = "https://github.com/bazel-contrib/bazel_features/releases/download/v1.45.0/bazel_features-v1.45.0.tar.gz", + ) diff --git a/examples/simple/WORKSPACE b/examples/simple/WORKSPACE index 844ee8f..f7a4cf9 100644 --- a/examples/simple/WORKSPACE +++ b/examples/simple/WORKSPACE @@ -9,6 +9,10 @@ load("@buildifier_prebuilt//:deps.bzl", "buildifier_prebuilt_deps") buildifier_prebuilt_deps() +load("@bazel_features//:deps.bzl", "bazel_features_deps") + +bazel_features_deps() + load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") bazel_skylib_workspace() diff --git a/examples/specify_assets/WORKSPACE b/examples/specify_assets/WORKSPACE index 7917008..03ddbb6 100644 --- a/examples/specify_assets/WORKSPACE +++ b/examples/specify_assets/WORKSPACE @@ -9,6 +9,10 @@ load("@buildifier_prebuilt//:deps.bzl", "buildifier_prebuilt_deps") buildifier_prebuilt_deps() +load("@bazel_features//:deps.bzl", "bazel_features_deps") + +bazel_features_deps() + load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") bazel_skylib_workspace() From 6d64d0013feb019e73548f47554874f3dbc5679c Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Fri, 10 Apr 2026 13:57:37 -0700 Subject: [PATCH 4/5] windows --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23d84e3..ddc9498 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: bazelisk test //:all_integration_tests - name: Run with extra exec platforms - run: bazelisk run //:buildifier --extra_execution_platforms=//:non_host_platform,@platforms//host -- -help + run: bazelisk run //:buildifier --extra_execution_platforms=//:non_host_platform,@platforms//host '--' -help example_simple: strategy: From 6242da0c419b882bdf5438094b476d431438af56 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Fri, 10 Apr 2026 14:01:38 -0700 Subject: [PATCH 5/5] windows --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ddc9498..121a8d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: bazelisk test //:all_integration_tests - name: Run with extra exec platforms - run: bazelisk run //:buildifier --extra_execution_platforms=//:non_host_platform,@platforms//host '--' -help + run: bazelisk run //:buildifier --extra_execution_platforms="//:non_host_platform,@platforms//host" '--' -help example_simple: strategy: