nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{
2 stdenv,
3 callPackage,
4 # nix tooling and utilities
5 darwin,
6 lib,
7 fetchzip,
8 fetchpatch,
9 makeWrapper,
10 writeTextFile,
11 replaceVars,
12 # native build inputs
13 runtimeShell,
14 zip,
15 unzip,
16 bash,
17 coreutils,
18 which,
19 gawk,
20 gnused,
21 gnutar,
22 gnugrep,
23 gzip,
24 findutils,
25 diffutils,
26 gnupatch,
27 file,
28 installShellFiles,
29 python3,
30 # Apple dependencies
31 cctools,
32 # Allow to independently override the jdks used to build and run respectively
33 jdk_headless,
34 version ? "8.5.0",
35}:
36
37let
38 inherit (callPackage ./build-support/patching.nix { }) addFilePatch;
39 inherit (stdenv.hostPlatform) isDarwin isAarch64;
40
41 bazelSystem = if isDarwin then "darwin" else "linux";
42
43 # on aarch64 Darwin, `uname -m` returns "arm64"
44 bazelArch = if isDarwin && isAarch64 then "arm64" else stdenv.hostPlatform.parsed.cpu.name;
45
46 src = fetchzip {
47 url = "https://github.com/bazelbuild/bazel/releases/download/${version}/bazel-${version}-dist.zip";
48 hash = "sha256-L8gnWpQAeHMUbydrrEtZ6WGIzhunDBWCNWMA+3dAKT0=";
49 stripRoot = false;
50 };
51
52 defaultShellUtils =
53 # Keep this list conservative. For more exotic tools, prefer to use
54 # @rules_nixpkgs to pull in tools from the nix repository. Example:
55 #
56 # WORKSPACE:
57 #
58 # nixpkgs_git_repository(
59 # name = "nixpkgs",
60 # revision = "def5124ec8367efdba95a99523dd06d918cb0ae8",
61 # )
62 #
63 # # This defines an external Bazel workspace.
64 # nixpkgs_package(
65 # name = "bison",
66 # repositories = { "nixpkgs": "@nixpkgs//:default.nix" },
67 # )
68 #
69 # some/BUILD.bazel:
70 #
71 # genrule(
72 # ...
73 # cmd = "$(location @bison//:bin/bison) -other -args",
74 # tools = [
75 # ...
76 # "@bison//:bin/bison",
77 # ],
78 # )
79 [
80 coreutils
81 diffutils
82 file
83 findutils
84 gawk
85 gnugrep
86 gnupatch
87 gnused
88 gnutar
89 gzip
90 unzip
91 which
92 zip
93 ];
94 defaultShell = callPackage ./defaultShell.nix { } { inherit defaultShellUtils; };
95
96 commandArgs = [
97 "--nobuild_python_zip"
98 "--features=-module_maps"
99 "--host_features=-module_maps"
100 "--announce_rc"
101 "--verbose_failures"
102 "--curses=no"
103 ]
104 ++ lib.optionals isDarwin [
105 "--macos_sdk_version=${stdenv.hostPlatform.darwinMinVersion}"
106 "--cxxopt=-isystem"
107 "--cxxopt=${lib.getDev stdenv.cc.libcxx}/include/c++/v1"
108 "--host_cxxopt=-isystem"
109 "--host_cxxopt=${lib.getDev stdenv.cc.libcxx}/include/c++/v1"
110 "--copt=-isystem"
111 "--copt=${lib.getDev darwin.libresolv}/include"
112 "--host_copt=-isystem"
113 "--host_copt=${lib.getDev darwin.libresolv}/include"
114 ];
115
116in
117stdenv.mkDerivation rec {
118 pname = "bazel";
119 inherit version src;
120
121 darwinPatches = [
122 # Bazel integrates with apple IOKit to inhibit and track system sleep.
123 # Inside the darwin sandbox, these API calls are blocked, and bazel
124 # crashes. It seems possible to allow these APIs inside the sandbox, but it
125 # feels simpler to patch bazel not to use it at all. So our bazel is
126 # incapable of preventing system sleep, which is a small price to pay to
127 # guarantee that it will always run in any nix context.
128 #
129 # See also ./bazel_darwin_sandbox.patch in bazel_5. That patch uses
130 # NIX_BUILD_TOP env var to conditionnally disable sleep features inside the
131 # sandbox.
132 #
133 # If you want to investigate the sandbox profile path,
134 # IORegisterForSystemPower can be allowed with
135 #
136 # propagatedSandboxProfile = ''
137 # (allow iokit-open (iokit-user-client-class "RootDomainUserClient"))
138 # '';
139 #
140 # I do not know yet how to allow IOPMAssertion{CreateWithName,Release}
141 ./patches/darwin_sleep.patch
142
143 # Fix DARWIN_XCODE_LOCATOR_COMPILE_COMMAND by removing multi-arch support.
144 # Nixpkgs toolcahins do not support that (yet?) and get confused.
145 # Also add an explicit /usr/bin prefix that will be patched below.
146 (replaceVars ./patches/xcode.patch {
147 clangDarwin = "${stdenv.cc}/bin/clang";
148 })
149
150 # Revert preference for apple_support over rules_cc toolchain for now
151 # will need to figure out how to build with apple_support toolchain later
152 ./patches/apple_cc_toolchain.patch
153
154 # On Darwin, the last argument to gcc is coming up as an empty string. i.e: ''
155 # This is breaking the build of any C target. This patch removes the last
156 # argument if it's found to be an empty string.
157 ./patches/trim-last-argument-to-gcc-if-empty.patch
158 ];
159
160 patches = lib.optionals isDarwin darwinPatches ++ [
161 # patch that propagates rules_* patches below
162 # patches need to be within source root and can't be absolute paths in Nix store
163 # so rules_* patches are injected via addFilePatch
164 ./patches/deps_patches.patch
165 (addFilePatch {
166 path = "b/third_party/rules_python.patch";
167 file = replaceVars ./patches/rules_python.patch {
168 usrBinEnv = "${coreutils}/bin/env";
169 };
170 })
171 (addFilePatch {
172 path = "b/third_party/rules_java.patch";
173 file = replaceVars ./patches/rules_java.patch {
174 defaultBash = "${defaultShell.bashWithDefaultShellUtils}/bin/bash";
175 };
176 })
177 # Suggested for upstream in https://github.com/bazelbuild/bazel/pull/25936
178 ./patches/build_execlog_parser.patch
179 # Part of suggestion for upstream in https://github.com/bazelbuild/bazel/pull/25934
180 ./patches/env_bash.patch
181 # Suggested for upstream in https://github.com/bazelbuild/bazel/pull/25935
182 ./patches/gen_completion.patch
183
184 # --experimental_strict_action_env (which may one day become the default
185 # see bazelbuild/bazel#2574) hardcodes the default
186 # action environment to a non hermetic value (e.g. "/usr/local/bin").
187 # This is non hermetic on non-nixos systems. On NixOS, bazel cannot find the required binaries.
188 # So we are replacing this bazel paths by defaultShellPath,
189 # improving hermeticity and making it work in nixos.
190 (replaceVars ./patches/strict_action_env.patch {
191 strictActionEnvPatch = defaultShell.defaultShellPath;
192 })
193
194 (replaceVars ./patches/default_bash.patch {
195 defaultBash = "${defaultShell.bashWithDefaultShellUtils}/bin/bash";
196 })
197
198 (replaceVars ./patches/md5sum.patch {
199 md5sum = "${coreutils}/bin/md5sum";
200 })
201
202 # Nix build sandbox can configure custom PATH but doesn't have
203 # /usr/bin/env which is unfortunate https://github.com/NixOS/nixpkgs/issues/6227
204 # and we need to do a silly patch
205 (replaceVars ./patches/usr_bin_env.patch {
206 usrBinEnv = "${coreutils}/bin/env";
207 })
208
209 # Provide default JRE for Bazel process by setting --server_javabase=
210 # in a new default system bazelrc file
211 (replaceVars ./patches/bazel_rc.patch {
212 bazelSystemBazelRCPath = replaceVars ./system.bazelrc {
213 serverJavabase = jdk_headless;
214 };
215 })
216 ];
217
218 meta = {
219 homepage = "https://github.com/bazelbuild/bazel/";
220 description = "Build tool that builds code quickly and reliably";
221 sourceProvenance = with lib.sourceTypes; [
222 fromSource
223 binaryBytecode # source bundles dependencies as jars
224 ];
225 license = lib.licenses.asl20;
226 teams = [ lib.teams.bazel ];
227 mainProgram = "bazel";
228 platforms = lib.platforms.linux ++ lib.platforms.darwin;
229 };
230
231 nativeBuildInputs = [
232 makeWrapper
233 jdk_headless
234 python3
235 unzip
236 which
237
238 # Shell completion
239 installShellFiles
240 python3.pkgs.absl-py # Needed to build fish completion
241 ]
242 # Needed for execlog
243 ++ lib.optional (!stdenv.hostPlatform.isDarwin) stdenv.cc
244 ++ lib.optional (stdenv.hostPlatform.isDarwin) cctools.libtool;
245
246 buildPhase = ''
247 runHook preBuild
248 export HOME=$(mktemp -d)
249
250 # If EMBED_LABEL isn't set, it'd be auto-detected from CHANGELOG.md
251 # and `git rev-parse --short HEAD` which would result in
252 # "3.7.0- (@non-git)" due to non-git build and incomplete changelog.
253 # Actual bazel releases use scripts/release/common.sh which is based
254 # on branch/tag information which we don't have with tarball releases.
255 # Note that .bazelversion is always correct and is based on bazel-*
256 # executable name, version checks should work fine
257 export EMBED_LABEL="${version}- (@non-git)"
258
259 echo "Stage 1 - Running bazel bootstrap script"
260 # Note: can't use lib.escapeShellArgs here because it will escape arguments
261 # with = using single quotes. This is fine for command invocations,
262 # but for string variable they become literal single quote chars,
263 # compile.sh will not unquote them either and command will be invalid.
264 export EXTRA_BAZEL_ARGS="${lib.strings.concatStringsSep " " commandArgs}"
265
266 ${bash}/bin/bash ./compile.sh
267
268 # XXX: get rid of this, or move it to another stage.
269 # It is plain annoying when builds fail.
270 echo "Stage 2 - Generate bazel completions"
271 ${bash}/bin/bash ./scripts/generate_bash_completion.sh \
272 --bazel=./output/bazel \
273 --output=./output/bazel-complete.bash \
274 --prepend=./scripts/bazel-complete-header.bash \
275 --prepend=./scripts/bazel-complete-template.bash
276 ${python3}/bin/python3 ./scripts/generate_fish_completion.py \
277 --bazel=./output/bazel \
278 --output=./output/bazel-complete.fish
279
280 runHook postBuild
281 '';
282
283 installPhase = ''
284 runHook preInstall
285
286 # Bazel binary contains zip archive, which contains text files and a jar
287 # both of which can have store references that might be obscured to Nix
288 # builder in packaged form, so we unpack and extract those references
289
290 # Note: grep isn't necessarily 100% accurate, other approaches could be
291 # to disassemble Jar (slow) or hardcode known references
292 mkdir -p $out/nix-support
293 INSTALL_BASE=$(./output/bazel --batch info install_base)
294 find "$INSTALL_BASE" -type f -exec \
295 ${gnugrep}/bin/grep --text --only-matching --no-filename "$NIX_STORE/[^/]*" '{}' \; \
296 | sort -u >> $out/nix-support/depends
297
298 mkdir -p $out/bin
299
300 # official wrapper scripts that searches for $WORKSPACE_ROOT/tools/bazel if
301 # it can’t find something in tools, it calls
302 # $out/bin/bazel-{version}-{os_arch} The binary _must_ exist with this
303 # naming if your project contains a .bazelversion file.
304 cp ./scripts/packages/bazel.sh $out/bin/bazel
305 versioned_bazel="$out/bin/bazel-${version}-${bazelSystem}-${bazelArch}"
306 mv ./output/bazel "$versioned_bazel"
307 wrapProgram "$versioned_bazel" --suffix PATH : ${defaultShell.defaultShellPath}
308
309 mkdir $out/share
310 cp ./output/parser_deploy.jar $out/share/parser_deploy.jar
311 substitute ${./bazel-execlog.sh} $out/bin/bazel-execlog \
312 --subst-var out \
313 --subst-var-by runtimeShell ${runtimeShell} \
314 --subst-var-by binJava ${jdk_headless}/bin/java
315 chmod +x $out/bin/bazel-execlog
316
317 # shell completion files
318 installShellCompletion --bash \
319 --name bazel.bash \
320 ./output/bazel-complete.bash
321 installShellCompletion --zsh \
322 --name _bazel \
323 ./scripts/zsh_completion/_bazel
324 installShellCompletion --fish \
325 --name bazel.fish \
326 ./output/bazel-complete.fish
327 '';
328
329 postFixup =
330 # verify that bazel binary still works post-fixup
331 ''
332 USE_BAZEL_VERSION=${version} $out/bin/bazel --batch info release
333 '';
334
335 # Bazel binary includes zip archive at the end that `strip` would end up discarding
336 stripExclude = [ "bin/.bazel-${version}-*-wrapped" ];
337
338 passthru = {
339 tests = {
340 inherit (callPackage ./examples.nix { }) cpp java rust;
341 };
342 };
343}