From 6707a6456254775d252257ac69e2862e6cfa9c3f Mon Sep 17 00:00:00 2001 From: Luke Peterson Date: Fri, 29 Aug 2025 22:14:34 -0700 Subject: [PATCH] Fix NixOS specific build issues /bin/bash is unavailable on NixOS by default. This breaks many bazel assumptions and causes build failures such as: ``` ... process-wrapper-legacy.cc:80: "execvp(/bin/bash, ...)": No such file or directory ... ``` By unsetting `incompatible_strict_action_env` [0], conditionally (on NixOS) setting `shell_executable` [1] to the bash in the Nix store, and by setting the `bazel-wrapper` PATH with `writeShellApplication.runtimeInputs` we are able to avoid these errors. Finally, tag several targets in //example as "manual" so they are not automatically built with the host toolchain, since this currently fails on NixOS. This should be addressed in a follow-up commit. Testing was performed using nixpkgs supplied bazelisk [3] on Luke Peterson's and Michael Schneider's NixOS machines. This itself presented issues, as this package is documented with `BEWARE: This package does not work on NixOS.` Out of the box this is true, but can be worked around with `programs.nix-ld.enable = true` [4] in `configuration.nix`. Special thanks to Oliver Lee and Michael Schneider during the final day of Nixcademy NixOS training. This was a great collaboration! [0]: https://bazel.build/reference/command-line-reference#flag--incompatible_strict_action_env [1]: https://bazel.build/reference/command-line-reference#flag--shell_executable [2]: https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeShellApplication [3]: https://github.com/NixOS/nixpkgs/blob/nixos-25.05/pkgs/by-name/ba/bazelisk/package.nix [4]: https://github.com/nix-community/nix-ld --- .bazelrc | 2 +- .gitignore | 3 +++ README.md | 5 ++++- example/minimal/BUILD.bazel | 3 +++ example/semihosting/BUILD.bazel | 6 +++++ example/unit_test/BUILD.bazel | 3 +++ tools/BUILD.bazel | 4 ++-- tools/bazel | 40 ++++++++++++++++++++++++--------- tools/bazel-wrapper/flake.nix | 8 ++++++- 9 files changed, 58 insertions(+), 16 deletions(-) diff --git a/.bazelrc b/.bazelrc index 1eecdc3..8beb51f 100644 --- a/.bazelrc +++ b/.bazelrc @@ -8,7 +8,6 @@ common --action_env="BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1" common --announce_rc common --color=yes common --curses=yes -common --incompatible_strict_action_env common --ui_actions_shown=20 common --progress_in_terminal_title common --enable_platform_specific_config @@ -40,4 +39,5 @@ test --test_output=errors test --test_summary=detailed test --test_verbose_timeout_warnings +try-import %workspace%/.nixos-autoconfig/bazelrc try-import %workspace%/user.bazelrc diff --git a/.gitignore b/.gitignore index f083386..d293bc2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ # ignore Nix out links to dev shell application /.bazel-wrapper/ + +# ignore NixOS specific bazelrc +/.nixos-autoconfig/ diff --git a/README.md b/README.md index 5419954..ab43bf4 100644 --- a/README.md +++ b/README.md @@ -94,4 +94,7 @@ transition_config_test( # developing Developing requires `bash`, `nix`, and coreutils on the `$PATH` to bootstrap -the Nix shell application used in `tools/bazel`. +the Nix shell application used in `tools/bazel`. On NixOS, [nix-ld][nix-ld] is +required. + +[nix-ld]: https://github.com/nix-community/nix-ld diff --git a/example/minimal/BUILD.bazel b/example/minimal/BUILD.bazel index 0b7dcba..e65eda2 100644 --- a/example/minimal/BUILD.bazel +++ b/example/minimal/BUILD.bazel @@ -3,4 +3,7 @@ load("@rules_cc//cc:defs.bzl", "cc_binary") cc_binary( name = "minimal", srcs = ["main.cpp"], + # This fails since the only registered host toolchain is from + # toolchains_llvm which doesn't currently work on NixOS. + tags = ["manual"], ) diff --git a/example/semihosting/BUILD.bazel b/example/semihosting/BUILD.bazel index f171eb7..6843d19 100644 --- a/example/semihosting/BUILD.bazel +++ b/example/semihosting/BUILD.bazel @@ -4,6 +4,9 @@ load("@rules_cc//cc:defs.bzl", "cc_binary") cc_binary( name = "binary", srcs = ["main.cpp"], + # This fails since the only registered host toolchain is from + # toolchains_llvm which doesn't currently work on NixOS. + tags = ["manual"], ) # `transition_config_binary` must be run with @@ -14,6 +17,9 @@ transition_config_binary( name = "semihosting", src = ":binary", semihosting = "enabled", + # This fails since the only registered host toolchain is from + # toolchains_llvm which doesn't currently work on NixOS. + tags = ["manual"], ) transition_config_binary( diff --git a/example/unit_test/BUILD.bazel b/example/unit_test/BUILD.bazel index 477e7e2..c39a048 100644 --- a/example/unit_test/BUILD.bazel +++ b/example/unit_test/BUILD.bazel @@ -4,6 +4,9 @@ load("@rules_cc//cc:defs.bzl", "cc_test") cc_test( name = "test", srcs = ["main.cpp"], + # This fails since the only registered host toolchain is from + # toolchains_llvm which doesn't currently work on NixOS. + tags = ["manual"], ) transition_config_test( diff --git a/tools/BUILD.bazel b/tools/BUILD.bazel index e1c20da..969b5c5 100644 --- a/tools/BUILD.bazel +++ b/tools/BUILD.bazel @@ -44,7 +44,7 @@ genrule( name = "gen-clang-format", outs = ["clang-format.bash"], cmd = """ -echo "#!/bin/bash" > $@ +echo "#!/usr/bin/env bash" > $@ echo "cd \\$$BUILD_WORKSPACE_DIRECTORY" >> $@ echo "exec bazelisk build \\$$@ //..." >> $@ """, @@ -93,7 +93,7 @@ genrule( name = "gen-clang-tidy", outs = ["clang-tidy.bash"], cmd = """ -echo "#!/bin/bash" > $@ +echo "#!/usr/bin/env bash" > $@ echo "cd \\$$BUILD_WORKSPACE_DIRECTORY" >> $@ echo "exec bazelisk build {options} \\$${{@:-//...}}" >> $@ """.format( diff --git a/tools/bazel b/tools/bazel index 032fd73..535083c 100755 --- a/tools/bazel +++ b/tools/bazel @@ -18,17 +18,35 @@ bazel_wrapper_hash=$(cat "${bazel_wrapper}"/* | sha1sum | cut -d' ' -f1) hashed_out_link="${workspace_root}/.bazel-wrapper/${bazel_wrapper_hash}" if [[ ! -e "$hashed_out_link" ]]; then - rm -rf "${workspace_root}/.bazel-wrapper" - store_path=$( - nix \ - --option warn-dirty false \ - build \ - --verbose \ - --out-link "$hashed_out_link" \ - --print-out-paths \ - "path:$bazel_wrapper" - ) - echo "caching store path $store_path to $hashed_out_link" + rm -rf "${workspace_root}/.bazel-wrapper" + store_path=$( + nix \ + --option warn-dirty false \ + build \ + --verbose \ + --out-link "$hashed_out_link" \ + --print-out-paths \ + "path:$bazel_wrapper" + ) + echo "cached store path $store_path to $hashed_out_link" +fi + +# NixOS doesn't have /bin/bash so we need to set --shell_executable +nixos_bazelrc_dir="${workspace_root}/.nixos-autoconfig" +if [[ ! -e /bin/bash && ! -e "${nixos_bazelrc_dir}/${bazel_wrapper_hash}" ]]; then + echo "generating/updating nixos specific bazelrc" + + rm -rf "$nixos_bazelrc_dir" + nix \ + --option warn-dirty false \ + build \ + --verbose \ + --out-link "${nixos_bazelrc_dir}/${bazel_wrapper_hash}" \ + "path:${bazel_wrapper}#nixos-bazelrc" + cat > ${nixos_bazelrc_dir}/bazelrc << EOF +import %workspace%/.nixos-autoconfig/${bazel_wrapper_hash} +EOF + fi exec "$hashed_out_link/bin/bazel-wrapper" "$@" diff --git a/tools/bazel-wrapper/flake.nix b/tools/bazel-wrapper/flake.nix index a2fd2b3..b4403d2 100644 --- a/tools/bazel-wrapper/flake.nix +++ b/tools/bazel-wrapper/flake.nix @@ -1,5 +1,5 @@ { - description = "flake defining the repo dev shell"; + description = "flake defining files needed to bootstrap bazelisk"; inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05"; @@ -28,6 +28,7 @@ bash bazelisk coreutils + diffutils findutils gnugrep gnused @@ -36,8 +37,13 @@ ++ lib.optionals stdenv.isDarwin [ darwin.cctools ]; + rc_line = '' + common --shell_executable ${pkgs.lib.getExe pkgs.bash} + ''; in { + nixos-bazelrc = pkgs.writeText "nixos-${system}.bazelrc" "${rc_line}"; + default = pkgs.writeShellApplication { name = "bazel-wrapper"; runtimeInputs = tools;