Skip to content

Commit 0a3c520

Browse files
committed
nixos/bazelisk: add NixOS module
Add a programs.bazelisk NixOS module that installs bazelisk with a bazel symlink, enables envfs for /bin/bash compatibility, and writes /etc/bazel.bazelrc with Nix store paths for common Bazel action tools. The module also supports optional CC/CXX settings for rules_cc detection, extra action PATH packages, and extra bazelrc lines. Add a NixOS test covering the generated bazelrc, envfs fallback, and bazel symlink, and link it from bazelisk.passthru.tests.
1 parent 10fa2c9 commit 0a3c520

6 files changed

Lines changed: 211 additions & 1 deletion

File tree

nixos/modules/module-list.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@
180180
./programs/bash/undistract-me.nix
181181
./programs/bat.nix
182182
./programs/bazecor.nix
183+
./programs/bazelisk.nix
183184
./programs/bcc.nix
184185
./programs/benchexec.nix
185186
./programs/browserpass.nix

nixos/modules/programs/bazelisk.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Bazelisk {#module-programs-bazelisk}
2+
3+
The `programs.bazelisk` module installs Bazelisk as both `bazelisk` and
4+
`bazel`, enables envfs so unpatched Bazel binaries can resolve `/bin/bash`,
5+
and writes `/etc/bazel.bazelrc` with Nix store paths for common action tools.
6+
7+
Set `programs.bazelisk.cc` and `programs.bazelisk.cxx` when a project needs C
8+
or C++ toolchain detection through `rules_cc`.
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
{
2+
config,
3+
lib,
4+
pkgs,
5+
...
6+
}:
7+
8+
let
9+
cfg = config.programs.bazelisk;
10+
11+
# Build a PATH containing common tools that Bazel actions need.
12+
defaultActionPath = lib.makeBinPath (
13+
with pkgs;
14+
[
15+
bash
16+
binutils
17+
coreutils
18+
findutils
19+
gawk
20+
gnugrep
21+
gnused
22+
gnutar
23+
gzip
24+
which
25+
unzip
26+
]
27+
++ cfg.extraPackages
28+
);
29+
30+
bazelrc = pkgs.writeText "bazel.bazelrc" ''
31+
# Generated by NixOS programs.bazelisk module.
32+
# NixOS needs an explicit PATH for Bazel actions since tools live in the
33+
# Nix store and are not at standard FHS locations.
34+
build --action_env=PATH=${defaultActionPath}
35+
build --host_action_env=PATH=${defaultActionPath}
36+
37+
${lib.optionalString (cfg.cc != null) ''
38+
build --repo_env=CC=${cfg.cc}
39+
build --action_env=CC=${cfg.cc}
40+
''}
41+
${lib.optionalString (cfg.cxx != null) ''
42+
build --repo_env=CXX=${cfg.cxx}
43+
build --action_env=CXX=${cfg.cxx}
44+
''}
45+
${cfg.extraBazelrc}
46+
'';
47+
in
48+
{
49+
options.programs.bazelisk = {
50+
enable = lib.mkEnableOption ''
51+
bazelisk, a version-switching launcher for Bazel.
52+
53+
Enabling this module installs bazelisk with a `bazel` symlink, enables
54+
envfs (so unpatched Bazel binaries can find `/bin/bash`), and writes a
55+
system-wide `/etc/bazel.bazelrc` that sets `--action_env=PATH` and
56+
`--host_action_env=PATH` to Nix store paths for common tools.
57+
58+
Per-project settings (e.g. extra rustc flags, pkg-config paths) still
59+
belong in `.bazelrc.user`
60+
'';
61+
62+
package = lib.mkPackageOption pkgs "bazelisk" { };
63+
64+
cc = lib.mkOption {
65+
type = lib.types.nullOr lib.types.str;
66+
default = null;
67+
example = lib.literalExpression ''"''${pkgs.clang}/bin/clang"'';
68+
description = ''
69+
Path to the C compiler. Set via `--repo_env=CC` and `--action_env=CC`
70+
in the system bazelrc so that rules_cc toolchain detection works.
71+
'';
72+
};
73+
74+
cxx = lib.mkOption {
75+
type = lib.types.nullOr lib.types.str;
76+
default = null;
77+
example = lib.literalExpression ''"''${pkgs.clang}/bin/clang++"'';
78+
description = ''
79+
Path to the C++ compiler. Set via `--repo_env=CXX` and `--action_env=CXX`
80+
in the system bazelrc so that rules_cc toolchain detection works.
81+
'';
82+
};
83+
84+
extraPackages = lib.mkOption {
85+
type = lib.types.listOf lib.types.package;
86+
default = [ ];
87+
description = ''
88+
Additional packages to include in the Bazel action PATH.
89+
'';
90+
};
91+
92+
extraBazelrc = lib.mkOption {
93+
type = lib.types.lines;
94+
default = "";
95+
description = ''
96+
Extra lines appended to the system `/etc/bazel.bazelrc`.
97+
'';
98+
};
99+
};
100+
101+
config = lib.mkIf cfg.enable {
102+
# Install bazelisk with a `bazel` symlink so it's a drop-in replacement.
103+
environment.systemPackages = [
104+
(pkgs.symlinkJoin {
105+
name = "bazelisk-with-bazel";
106+
paths = [ cfg.package ];
107+
postBuild = "ln -sf $out/bin/bazelisk $out/bin/bazel";
108+
})
109+
];
110+
111+
# envfs provides /bin/bash and /usr/bin/env for unpatched Bazel binaries.
112+
services.envfs.enable = true;
113+
services.envfs.extraFallbackPathCommands = ''
114+
ln -s ${pkgs.bash}/bin/bash $out/bash
115+
'';
116+
117+
# System-wide bazelrc with NixOS-compatible defaults.
118+
environment.etc."bazel.bazelrc".source = bazelrc;
119+
};
120+
121+
meta = {
122+
doc = ./bazelisk.md;
123+
maintainers = with lib.maintainers; [ dhashs ];
124+
};
125+
}

nixos/tests/all-tests.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ in
254254
ayatana-indicators = runTest ./ayatana-indicators.nix;
255255
babeld = runTest ./babeld.nix;
256256
bazarr = runTest ./bazarr.nix;
257+
bazelisk = runTest ./bazelisk.nix;
257258
bcache = runTestOn [ "x86_64-linux" "aarch64-linux" ] ./bcache.nix;
258259
bcachefs = runTestOn [ "x86_64-linux" "aarch64-linux" ] ./bcachefs.nix;
259260
beanstalkd = runTest ./beanstalkd.nix;

nixos/tests/bazelisk.nix

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{
2+
pkgs,
3+
...
4+
}:
5+
6+
let
7+
fakeBazelisk = pkgs.writeShellScriptBin "bazelisk" ''
8+
echo "fake bazelisk $*"
9+
'';
10+
11+
fakeCc = pkgs.writeShellScriptBin "bazelisk-test-cc" ''
12+
exit 0
13+
'';
14+
15+
fakeCxx = pkgs.writeShellScriptBin "bazelisk-test-cxx" ''
16+
exit 0
17+
'';
18+
19+
extraTool = pkgs.writeShellScriptBin "bazelisk-extra-tool" ''
20+
echo "extra tool"
21+
'';
22+
in
23+
{
24+
name = "bazelisk";
25+
26+
nodes.machine = {
27+
programs.bazelisk = {
28+
enable = true;
29+
package = fakeBazelisk;
30+
cc = "${fakeCc}/bin/bazelisk-test-cc";
31+
cxx = "${fakeCxx}/bin/bazelisk-test-cxx";
32+
extraPackages = [ extraTool ];
33+
extraBazelrc = ''
34+
build --action_env=BAZELISK_TEST=1
35+
'';
36+
};
37+
};
38+
39+
testScript = ''
40+
start_all()
41+
42+
machine.wait_until_succeeds("mountpoint -q /usr/bin")
43+
machine.wait_until_succeeds("test -e /bin/bash")
44+
45+
machine.succeed("test -x /run/current-system/sw/bin/bazelisk")
46+
machine.succeed("test -x /run/current-system/sw/bin/bazel")
47+
machine.succeed("bazel --version | grep 'fake bazelisk --version'")
48+
machine.succeed("PATH= /bin/bash --version")
49+
50+
bazelrc = machine.succeed("cat /etc/bazel.bazelrc")
51+
for expected in [
52+
"build --action_env=PATH=",
53+
"build --host_action_env=PATH=",
54+
"${pkgs.bash}/bin",
55+
"${pkgs.binutils}/bin",
56+
"${pkgs.coreutils}/bin",
57+
"${extraTool}/bin",
58+
"build --repo_env=CC=${fakeCc}/bin/bazelisk-test-cc",
59+
"build --action_env=CC=${fakeCc}/bin/bazelisk-test-cc",
60+
"build --repo_env=CXX=${fakeCxx}/bin/bazelisk-test-cxx",
61+
"build --action_env=CXX=${fakeCxx}/bin/bazelisk-test-cxx",
62+
"build --action_env=BAZELISK_TEST=1",
63+
]:
64+
assert expected in bazelrc, f"{expected!r} missing from bazelrc"
65+
'';
66+
}

pkgs/by-name/ba/bazelisk/package.nix

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
lib,
33
buildGoModule,
44
fetchFromGitHub,
5+
nixosTests,
56
}:
67

78
buildGoModule (finalAttrs: {
@@ -23,11 +24,19 @@ buildGoModule (finalAttrs: {
2324
"-X github.com/bazelbuild/bazelisk/core.BazeliskVersion=v${finalAttrs.version}"
2425
];
2526

27+
passthru.tests = {
28+
inherit (nixosTests) bazelisk;
29+
};
30+
2631
meta = {
2732
description = "User-friendly launcher for Bazel";
2833
mainProgram = "bazelisk";
2934
longDescription = ''
30-
BEWARE: This package does not work on NixOS.
35+
A user-friendly launcher for Bazel that automatically downloads and
36+
runs the correct Bazel version for a given project.
37+
38+
On NixOS, enable the `programs.bazelisk` module to set up envfs and
39+
a system bazelrc with the correct tool paths.
3140
'';
3241
homepage = "https://github.com/bazelbuild/bazelisk";
3342
changelog = "https://github.com/bazelbuild/bazelisk/releases/tag/v${finalAttrs.version}";

0 commit comments

Comments
 (0)