nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{
2 stdenv,
3 # nix tooling and utilities
4 lib,
5 fetchurl,
6 makeWrapper,
7 writeTextFile,
8 replaceVars,
9 fetchpatch,
10 writeShellApplication,
11 makeBinaryWrapper,
12 autoPatchelfHook,
13 buildFHSEnv,
14 # this package (through the fixpoint glass)
15 # TODO probably still need for tests at some point
16 bazel_7,
17 bazel_self ? bazel_7,
18 # native build inputs
19 runtimeShell,
20 zip,
21 unzip,
22 bash,
23 coreutils,
24 which,
25 gawk,
26 gnused,
27 gnutar,
28 gnugrep,
29 gzip,
30 findutils,
31 diffutils,
32 gnupatch,
33 file,
34 installShellFiles,
35 lndir,
36 python3,
37 # Apple dependencies
38 cctools,
39 libtool,
40 darwin,
41 # Allow to independently override the jdks used to build and run respectively
42 jdk21_headless,
43 buildJdk ? jdk21_headless,
44 runJdk ? jdk21_headless,
45 # Toggle for hacks for running bazel under buildBazelPackage:
46 # Always assume all markers valid (this is needed because we remove markers; they are non-deterministic).
47 # Also, don't clean up environment variables (so that NIX_ environment variables are passed to compilers).
48 enableNixHacks ? false,
49 version ? "7.6.0",
50}:
51
52let
53 sourceRoot = ".";
54
55 src = fetchurl {
56 url = "https://github.com/bazelbuild/bazel/releases/download/${version}/bazel-${version}-dist.zip";
57 hash = "sha256-eQKNB38G8ziDuorzoj5Rne/DZQL22meVLrdK0z7B2FI=";
58 };
59
60 defaultShellUtils =
61 # Keep this list conservative. For more exotic tools, prefer to use
62 # @rules_nixpkgs to pull in tools from the nix repository. Example:
63 #
64 # WORKSPACE:
65 #
66 # nixpkgs_git_repository(
67 # name = "nixpkgs",
68 # revision = "def5124ec8367efdba95a99523dd06d918cb0ae8",
69 # )
70 #
71 # # This defines an external Bazel workspace.
72 # nixpkgs_package(
73 # name = "bison",
74 # repositories = { "nixpkgs": "@nixpkgs//:default.nix" },
75 # )
76 #
77 # some/BUILD.bazel:
78 #
79 # genrule(
80 # ...
81 # cmd = "$(location @bison//:bin/bison) -other -args",
82 # tools = [
83 # ...
84 # "@bison//:bin/bison",
85 # ],
86 # )
87 [
88 bash
89 coreutils
90 diffutils
91 file
92 findutils
93 gawk
94 gnugrep
95 gnupatch
96 gnused
97 gnutar
98 gzip
99 python3
100 unzip
101 which
102 zip
103 makeWrapper
104 ];
105
106 # Bootstrap an existing Bazel so we can vendor deps with vendor mode
107 bazelBootstrap = stdenv.mkDerivation rec {
108 name = "bazelBootstrap";
109
110 src =
111 if stdenv.hostPlatform.system == "x86_64-linux" then
112 fetchurl {
113 url = "https://github.com/bazelbuild/bazel/releases/download/${version}/bazel_nojdk-${version}-linux-x86_64";
114 hash = "sha256-94KFvsS7fInXFTQZPzMq6DxnHQrRktljwACyAz8adSw=";
115 }
116 else if stdenv.hostPlatform.system == "aarch64-linux" then
117 fetchurl {
118 url = "https://github.com/bazelbuild/bazel/releases/download/${version}/bazel_nojdk-${version}-linux-arm64";
119 hash = "sha256-wfuZLSHa77wr0A4ZLF5DqH7qyOljYNXM2a5imoS+nGQ";
120 }
121 else if stdenv.hostPlatform.system == "x86_64-darwin" then
122 fetchurl {
123 url = "https://github.com/bazelbuild/bazel/releases/download/${version}/bazel-${version}-darwin-x86_64";
124 hash = "sha256-qAb9s6R5+EbqVfWHUT7sk1sOrbDEPv4EhgXH7nC46Zw=";
125 }
126 else
127 fetchurl {
128 # stdenv.hostPlatform.system == "aarch64-darwin"
129 url = "https://github.com/bazelbuild/bazel/releases/download/${version}/bazel-${version}-darwin-arm64";
130 hash = "sha256-4bRp4OvkRIvhpZ2r/eFJdwrByECHy3rncDEM1tClFYo=";
131 };
132
133 nativeBuildInputs = defaultShellUtils;
134 buildInputs = [
135 stdenv.cc.cc
136 ]
137 ++ lib.optional (!stdenv.hostPlatform.isDarwin) autoPatchelfHook;
138
139 dontUnpack = true;
140 dontPatch = true;
141 dontBuild = true;
142 dontStrip = true;
143 installPhase = ''
144 runHook preInstall
145
146 mkdir -p $out/bin
147 install -Dm755 $src $out/bin/bazel
148
149 runHook postInstall
150 '';
151
152 postFixup = ''
153 wrapProgram $out/bin/bazel \
154 --prefix PATH : ${lib.makeBinPath nativeBuildInputs}
155 '';
156
157 meta.sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ];
158 };
159
160 bazelFhs = buildFHSEnv {
161 pname = "bazel";
162 inherit version;
163 targetPkgs = _: [ bazelBootstrap ];
164 runScript = "bazel";
165 };
166
167 # A FOD that vendors the Bazel dependencies using Bazel's new vendor mode.
168 # See https://bazel.build/versions/7.3.0/external/vendor for details.
169 # Note that it may be possible to vendor less than the full set of deps in
170 # the future, as this is approximately 16GB.
171 bazelDeps =
172 let
173 bazelForDeps = if stdenv.hostPlatform.isDarwin then bazelBootstrap else bazelFhs;
174 in
175 stdenv.mkDerivation {
176 name = "bazelDeps";
177 inherit src version;
178 sourceRoot = ".";
179 patches = [
180 # The repo rule that creates a manifest of the bazel source for testing
181 # the cli is not reproducible. This patch ensures that it is by sorting
182 # the results in the repo rule rather than the downstream genrule.
183 ./test_source_sort.patch
184 ];
185 patchFlags = [
186 "--no-backup-if-mismatch"
187 "-p1"
188 ];
189 nativeBuildInputs = [
190 unzip
191 runJdk
192 bazelForDeps
193 ]
194 ++ lib.optional (stdenv.hostPlatform.isDarwin) libtool;
195 configurePhase = ''
196 runHook preConfigure
197
198 mkdir bazel_src
199 shopt -s dotglob extglob
200 mv !(bazel_src) bazel_src
201 mkdir vendor_dir
202
203 runHook postConfigure
204 '';
205 dontFixup = true;
206 buildPhase = ''
207 runHook preBuild
208 export HOME=$(mktemp -d)
209 (cd bazel_src; ${bazelForDeps}/bin/bazel --server_javabase=${runJdk} mod deps --curses=no;
210 ${bazelForDeps}/bin/bazel --server_javabase=${runJdk} vendor src:bazel_nojdk \
211 --curses=no \
212 --vendor_dir ../vendor_dir \
213 --verbose_failures \
214 --experimental_strict_java_deps=off \
215 --strict_proto_deps=off \
216 --tool_java_runtime_version=local_jdk_21 \
217 --java_runtime_version=local_jdk_21 \
218 --tool_java_language_version=21 \
219 --java_language_version=21)
220
221 # Some post-fetch fixup is necessary, because the deps come with some
222 # baggage that is not reproducible. Luckily, this baggage does not factor
223 # into the final product, so removing it is enough.
224
225 # the GOCACHE is poisonous!
226 rm -rf vendor_dir/gazelle~~non_module_deps~bazel_gazelle_go_repository_cache/gocache
227
228 # as is the go versions file (changes when new versions show up)
229 rm -f vendor_dir/rules_go~~go_sdk~go_default_sdk/versions.json
230
231 # and so are .pyc files
232 find vendor_dir -name "*.pyc" -type f -delete
233
234 # bazel-external is auto-generated and should be removed
235 # see https://bazel.build/external/vendor#vendor-symlinks for more details
236 rm vendor_dir/bazel-external
237
238 runHook postBuild
239 '';
240
241 installPhase = ''
242 mkdir -p $out/vendor_dir
243 cp -r --reflink=auto vendor_dir/* $out/vendor_dir
244 '';
245
246 outputHashMode = "recursive";
247 outputHash =
248 if stdenv.hostPlatform.system == "x86_64-linux" then
249 "sha256-yKy6IBIkjvN413kFMgkWCH3jAgF5AdpxrVnQyhgfWPA="
250 else if stdenv.hostPlatform.system == "aarch64-linux" then
251 "sha256-NW/JMVC7k2jBW+d8syMl9L5tDB7SQENJtlMFjAKascI="
252 else if stdenv.hostPlatform.system == "aarch64-darwin" then
253 "sha256-QVk0Qr86U350oLJ5P50SE6CUYqn5XEqgGCXVf+89wVY="
254 else
255 # x86_64-darwin
256 "sha256-VDrqS9YByYxboF6AcjAR0BRZa5ioGgX1pjx09zPfWTE=";
257 outputHashAlgo = "sha256";
258
259 };
260
261 defaultShellPath = lib.makeBinPath defaultShellUtils;
262
263 bashWithDefaultShellUtilsSh = writeShellApplication {
264 name = "bash";
265 runtimeInputs = defaultShellUtils;
266 text = ''
267 if [[ "$PATH" == "/no-such-path" ]]; then
268 export PATH=${defaultShellPath}
269 fi
270 exec ${bash}/bin/bash "$@"
271 '';
272 };
273
274 # Script-based interpreters in shebangs aren't guaranteed to work,
275 # especially on MacOS. So let's produce a binary
276 bashWithDefaultShellUtils = stdenv.mkDerivation {
277 name = "bash";
278 src = bashWithDefaultShellUtilsSh;
279 nativeBuildInputs = [ makeBinaryWrapper ];
280 buildPhase = ''
281 makeWrapper ${bashWithDefaultShellUtilsSh}/bin/bash $out/bin/bash
282 '';
283 };
284
285 platforms = lib.platforms.linux ++ lib.platforms.darwin;
286
287 inherit (stdenv.hostPlatform) isDarwin isAarch64;
288
289 system = if isDarwin then "darwin" else "linux";
290
291 # on aarch64 Darwin, `uname -m` returns "arm64"
292 arch = with stdenv.hostPlatform; if isDarwin && isAarch64 then "arm64" else parsed.cpu.name;
293
294 bazelRC = writeTextFile {
295 name = "bazel-rc";
296 text = ''
297 startup --server_javabase=${runJdk}
298
299 # Register nix-specific nonprebuilt java toolchains
300 build --extra_toolchains=@bazel_tools//tools/jdk:all
301 # and set bazel to use them by default
302 build --tool_java_runtime_version=local_jdk
303 build --java_runtime_version=local_jdk
304
305 # load default location for the system wide configuration
306 try-import /etc/bazel.bazelrc
307 '';
308 };
309
310in
311stdenv.mkDerivation rec {
312 pname = "bazel";
313 inherit version src;
314 inherit sourceRoot;
315
316 patches = [
317 # Remote java toolchains do not work on NixOS because they download binaries,
318 # so we need to use the @local_jdk//:jdk
319 # It could in theory be done by registering @local_jdk//:all toolchains,
320 # but these java toolchains still bundle binaries for ijar and stuff. So we
321 # need a nonprebult java toolchain (where ijar and stuff is built from
322 # sources).
323 # There is no such java toolchain, so we introduce one here.
324 # By providing no version information, the toolchain will set itself to the
325 # version of $JAVA_HOME/bin/java, just like the local_jdk does.
326 # To ensure this toolchain gets used, we can set
327 # --{,tool_}java_runtime_version=local_jdk and rely on the fact no java
328 # toolchain registered by default uses the local_jdk, making the selection
329 # unambiguous.
330 # This toolchain has the advantage that it can use any ambient java jdk,
331 # not only a given, fixed version. It allows bazel to work correctly in any
332 # environment where JAVA_HOME is set to the right java version, like inside
333 # nix derivations.
334 # However, this patch breaks bazel hermeticity, by picking the ambient java
335 # version instead of the more hermetic remote_jdk prebuilt binaries that
336 # rules_java provide by default. It also requires the user to have a
337 # JAVA_HOME set to the exact version required by the project.
338 # With more code, we could define java toolchains for all the java versions
339 # supported by the jdk as in rules_java's
340 # toolchains/local_java_repository.bzl, but this is not implemented here.
341 # To recover vanilla behavior, non NixOS users can set
342 # --{,tool_}java_runtime_version=remote_jdk, effectively reverting the
343 # effect of this patch and the fake system bazelrc.
344 ./java_toolchain.patch
345
346 # Bazel integrates with apple IOKit to inhibit and track system sleep.
347 # Inside the darwin sandbox, these API calls are blocked, and bazel
348 # crashes. It seems possible to allow these APIs inside the sandbox, but it
349 # feels simpler to patch bazel not to use it at all. So our bazel is
350 # incapable of preventing system sleep, which is a small price to pay to
351 # guarantee that it will always run in any nix context.
352 #
353 # See also ./bazel_darwin_sandbox.patch in bazel_5. That patch uses
354 # NIX_BUILD_TOP env var to conditionally disable sleep features inside the
355 # sandbox.
356 #
357 # If you want to investigate the sandbox profile path,
358 # IORegisterForSystemPower can be allowed with
359 #
360 # propagatedSandboxProfile = ''
361 # (allow iokit-open (iokit-user-client-class "RootDomainUserClient"))
362 # '';
363 #
364 # I do not know yet how to allow IOPMAssertion{CreateWithName,Release}
365 ./darwin_sleep.patch
366
367 # Fix DARWIN_XCODE_LOCATOR_COMPILE_COMMAND by removing multi-arch support.
368 # Nixpkgs toolcahins do not support that (yet?) and get confused.
369 # Also add an explicit /usr/bin prefix that will be patched below.
370 ./xcode_locator.patch
371
372 # On Darwin, the last argument to gcc is coming up as an empty string. i.e: ''
373 # This is breaking the build of any C target. This patch removes the last
374 # argument if it's found to be an empty string.
375 ./trim-last-argument-to-gcc-if-empty.patch
376
377 # --experimental_strict_action_env (which may one day become the default
378 # see bazelbuild/bazel#2574) hardcodes the default
379 # action environment to a non hermetic value (e.g. "/usr/local/bin").
380 # This is non hermetic on non-nixos systems. On NixOS, bazel cannot find the required binaries.
381 # So we are replacing this bazel paths by defaultShellPath,
382 # improving hermeticity and making it work in nixos.
383 (replaceVars ./strict_action_env.patch {
384 strictActionEnvPatch = defaultShellPath;
385 })
386
387 # bazel reads its system bazelrc in /etc
388 # override this path to a builtin one
389 (replaceVars ./bazel_rc.patch {
390 bazelSystemBazelRCPath = bazelRC;
391 })
392
393 # Fix build with gcc 15 by adding missing headers
394 (fetchpatch {
395 url = "https://github.com/bazelbuild/bazel/commit/1d206cac050b6c7d9ce65403e6a9909a49bfe4bc.patch";
396 hash = "sha256-Tg5o1Va7dd5hvXbWhZiog+VtuiqngqbbYOkCafVudDs=";
397 })
398 ]
399 # See enableNixHacks argument above.
400 ++ lib.optional enableNixHacks ./nix-build-bazel-package-hacks.patch;
401
402 postPatch =
403 let
404 darwinPatches = ''
405 bazelLinkFlags () {
406 eval set -- "$NIX_LDFLAGS"
407 local flag
408 for flag in "$@"; do
409 printf ' -Wl,%s' "$flag"
410 done
411 }
412
413 # Explicitly configure gcov since we don't have it on Darwin, so autodetection fails
414 export GCOV=${coreutils}/bin/false
415
416 # libcxx includes aren't added by libcxx hook
417 # https://github.com/NixOS/nixpkgs/pull/41589
418 export NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -isystem ${lib.getInclude stdenv.cc.libcxx}/include/c++/v1"
419 # for CLang 16 compatibility in external/upb dependency
420 export NIX_CFLAGS_COMPILE+=" -Wno-gnu-offsetof-extensions"
421
422 # This variable is used by bazel to propagate env vars for homebrew,
423 # which is exactly what we need too.
424 export HOMEBREW_RUBY_PATH="foo"
425
426 # don't use system installed Xcode to run clang, use Nix clang instead
427 sed -i -E \
428 -e "s;/usr/bin/xcrun (--sdk macosx )?clang;${stdenv.cc}/bin/clang $NIX_CFLAGS_COMPILE $(bazelLinkFlags) -framework CoreFoundation;g" \
429 -e "s;/usr/bin/codesign;CODESIGN_ALLOCATE=${cctools}/bin/${cctools.targetPrefix}codesign_allocate ${darwin.sigtool}/bin/codesign;" \
430 scripts/bootstrap/compile.sh \
431 tools/osx/BUILD
432
433 # nixpkgs's libSystem cannot use pthread headers directly, must import GCD headers instead
434 sed -i -e "/#include <pthread\/spawn.h>/i #include <dispatch/dispatch.h>" src/main/cpp/blaze_util_darwin.cc
435
436 # XXX: What do these do ?
437 sed -i -e 's;"/usr/bin/libtool";_find_generic(repository_ctx, "libtool", "LIBTOOL", overriden_tools);g' tools/cpp/unix_cc_configure.bzl
438 wrappers=( tools/cpp/osx_cc_wrapper.sh.tpl )
439 for wrapper in "''${wrappers[@]}"; do
440 sedVerbose $wrapper \
441 -e "s,/usr/bin/xcrun install_name_tool,${cctools}/bin/install_name_tool,g"
442 done
443
444 # set --macos_sdk_version to make utimensat visible:
445 sedVerbose compile.sh \
446 -e "/bazel_build /a\ --macos_sdk_version=${stdenv.hostPlatform.darwinMinVersion} \\\\" \
447
448 '';
449
450 genericPatches = ''
451 # unzip builtins_bzl.zip so the contents get patched
452 builtins_bzl=src/main/java/com/google/devtools/build/lib/bazel/rules/builtins_bzl
453 unzip ''${builtins_bzl}.zip -d ''${builtins_bzl}_zip >/dev/null
454 rm ''${builtins_bzl}.zip
455 builtins_bzl=''${builtins_bzl}_zip/builtins_bzl
456
457 # md5sum is part of coreutils
458 sed -i 's|/sbin/md5|md5sum|g' src/BUILD third_party/ijar/test/testenv.sh
459
460 echo
461 echo "Substituting */bin/* hardcoded paths in src/main/java/com/google/devtools"
462 # Prefilter the files with grep for speed
463 grep -rlZ /bin/ \
464 src/main/java/com/google/devtools \
465 src/main/starlark/builtins_bzl/common/python \
466 tools \
467 | while IFS="" read -r -d "" path; do
468 # If you add more replacements here, you must change the grep above!
469 # Only files containing /bin are taken into account.
470 sedVerbose "$path" \
471 -e 's!/usr/local/bin/bash!${bashWithDefaultShellUtils}/bin/bash!g' \
472 -e 's!/usr/bin/bash!${bashWithDefaultShellUtils}/bin/bash!g' \
473 -e 's!/bin/bash!${bashWithDefaultShellUtils}/bin/bash!g' \
474 -e 's!/usr/bin/env bash!${bashWithDefaultShellUtils}/bin/bash!g' \
475 -e 's!/usr/bin/env python2!${python3}/bin/python!g' \
476 -e 's!/usr/bin/env python!${python3}/bin/python!g' \
477 -e 's!/usr/bin/env!${coreutils}/bin/env!g' \
478 -e 's!/bin/true!${coreutils}/bin/true!g'
479 done
480
481 # Fixup scripts that generate scripts. Not fixed up by patchShebangs below.
482 sedVerbose scripts/bootstrap/compile.sh \
483 -e 's!/bin/bash!${bashWithDefaultShellUtils}/bin/bash!g' \
484 -e 's!shasum -a 256!sha256sum!g'
485
486 # Add required flags to bazel command line.
487 # XXX: It would suit a bazelrc file better, but I found no way to pass it.
488 # It seems that bazel bootstrapping ignores it.
489 # Passing EXTRA_BAZEL_ARGS is tricky due to quoting.
490 sedVerbose compile.sh \
491 -e "/bazel_build /a\ --verbose_failures \\\\" \
492 -e "/bazel_build /a\ --curses=no \\\\" \
493 -e "/bazel_build /a\ --toolchain_resolution_debug='@bazel_tools//tools/jdk:(runtime_)?toolchain_type' \\\\" \
494 -e "/bazel_build /a\ --tool_java_runtime_version=local_jdk_21 \\\\" \
495 -e "/bazel_build /a\ --java_runtime_version=local_jdk_21 \\\\" \
496 -e "/bazel_build /a\ --tool_java_language_version=21 \\\\" \
497 -e "/bazel_build /a\ --java_language_version=21 \\\\" \
498 -e "/bazel_build /a\ --extra_toolchains=@bazel_tools//tools/jdk:all \\\\" \
499 -e "/bazel_build /a\ --vendor_dir=../vendor_dir \\\\" \
500 -e "/bazel_build /a\ --repository_disable_download \\\\" \
501 -e "/bazel_build /a\ --announce_rc \\\\" \
502 -e "/bazel_build /a\ --nobuild_python_zip \\\\" \
503
504 # Also build parser_deploy.jar with bootstrap bazel
505 # TODO: Turn into a proper patch
506 sedVerbose compile.sh \
507 -e 's!bazel_build !bazel_build src/tools/execlog:parser_deploy.jar !' \
508 -e 's!clear_log!cp $(get_bazel_bin_path)/src/tools/execlog/parser_deploy.jar output\nclear_log!'
509
510 # append the PATH with defaultShellPath in tools/bash/runfiles/runfiles.bash
511 echo "PATH=\$PATH:${defaultShellPath}" >> runfiles.bash.tmp
512 cat tools/bash/runfiles/runfiles.bash >> runfiles.bash.tmp
513 mv runfiles.bash.tmp tools/bash/runfiles/runfiles.bash
514
515 # reconstruct the now patched builtins_bzl.zip
516 pushd src/main/java/com/google/devtools/build/lib/bazel/rules/builtins_bzl_zip &>/dev/null
517 zip ../builtins_bzl.zip $(find builtins_bzl -type f) >/dev/null
518 rm -rf builtins_bzl
519 popd &>/dev/null
520 rmdir src/main/java/com/google/devtools/build/lib/bazel/rules/builtins_bzl_zip
521
522 patchShebangs . >/dev/null
523 '';
524 in
525 ''
526 function sedVerbose() {
527 local path=$1; shift;
528 sed -i".bak-nix" "$path" "$@"
529 diff -U0 "$path.bak-nix" "$path" | sed "s/^/ /" || true
530 rm -f "$path.bak-nix"
531 }
532 ''
533 + lib.optionalString stdenv.hostPlatform.isDarwin darwinPatches
534 + genericPatches;
535
536 meta = {
537 homepage = "https://github.com/bazelbuild/bazel/";
538 description = "Build tool that builds code quickly and reliably";
539 sourceProvenance = with lib.sourceTypes; [
540 fromSource
541 binaryBytecode # source bundles dependencies as jars
542 ];
543 license = lib.licenses.asl20;
544 teams = [ lib.teams.bazel ];
545 mainProgram = "bazel";
546 inherit platforms;
547 };
548
549 # Bazel starts a local server and needs to bind a local address.
550 __darwinAllowLocalNetworking = true;
551
552 buildInputs = [
553 buildJdk
554 bashWithDefaultShellUtils
555 ]
556 ++ defaultShellUtils;
557
558 # when a command can’t be found in a bazel build, you might also
559 # need to add it to `defaultShellPath`.
560 nativeBuildInputs = [
561 installShellFiles
562 makeWrapper
563 python3
564 unzip
565 which
566 zip
567 python3.pkgs.absl-py # Needed to build fish completion
568 ]
569 ++ lib.optionals (stdenv.hostPlatform.isDarwin) [
570 cctools
571 ];
572
573 # Bazel makes extensive use of symlinks in the WORKSPACE.
574 # This causes problems with infinite symlinks if the build output is in the same location as the
575 # Bazel WORKSPACE. This is why before executing the build, the source code is moved into a
576 # subdirectory.
577 # Failing to do this causes "infinite symlink expansion detected"
578 preBuildPhases = [ "preBuildPhase" ];
579 preBuildPhase = ''
580 mkdir bazel_src
581 shopt -s dotglob extglob
582 mv !(bazel_src) bazel_src
583 # Augment bundled repository_cache with our extra paths
584 mkdir vendor_dir
585 ${lndir}/bin/lndir ${bazelDeps}/vendor_dir vendor_dir
586 rm vendor_dir/VENDOR.bazel
587 find vendor_dir -maxdepth 1 -type d -printf "pin(\"@@%P\")\n" > vendor_dir/VENDOR.bazel
588 '';
589 buildPhase = ''
590 runHook preBuild
591 export HOME=$(mktemp -d)
592
593 # If EMBED_LABEL isn't set, it'd be auto-detected from CHANGELOG.md
594 # and `git rev-parse --short HEAD` which would result in
595 # "3.7.0- (@non-git)" due to non-git build and incomplete changelog.
596 # Actual bazel releases use scripts/release/common.sh which is based
597 # on branch/tag information which we don't have with tarball releases.
598 # Note that .bazelversion is always correct and is based on bazel-*
599 # executable name, version checks should work fine
600 export EMBED_LABEL="${version}- (@non-git)"
601
602 echo "Stage 1 - Running bazel bootstrap script"
603 ${bash}/bin/bash ./bazel_src/compile.sh
604
605 # XXX: get rid of this, or move it to another stage.
606 # It is plain annoying when builds fail.
607 echo "Stage 2 - Generate bazel completions"
608 ${bash}/bin/bash ./bazel_src/scripts/generate_bash_completion.sh \
609 --bazel=./bazel_src/output/bazel \
610 --output=./bazel_src/output/bazel-complete.bash \
611 --prepend=./bazel_src/scripts/bazel-complete-header.bash \
612 --prepend=./bazel_src/scripts/bazel-complete-template.bash
613 ${python3}/bin/python3 ./bazel_src/scripts/generate_fish_completion.py \
614 --bazel=./bazel_src/output/bazel \
615 --output=./bazel_src/output/bazel-complete.fish
616
617 runHook postBuild
618 '';
619
620 installPhase = ''
621 runHook preInstall
622
623 mkdir -p $out/bin
624
625 # official wrapper scripts that searches for $WORKSPACE_ROOT/tools/bazel if
626 # it can’t find something in tools, it calls
627 # $out/bin/bazel-{version}-{os_arch} The binary _must_ exist with this
628 # naming if your project contains a .bazelversion file.
629 cp ./bazel_src/scripts/packages/bazel.sh $out/bin/bazel
630 versionned_bazel="$out/bin/bazel-${version}-${system}-${arch}"
631 mv ./bazel_src/output/bazel "$versionned_bazel"
632 wrapProgram "$versionned_bazel" --suffix PATH : ${defaultShellPath}
633
634 mkdir $out/share
635 cp ./bazel_src/output/parser_deploy.jar $out/share/parser_deploy.jar
636 cat <<EOF > $out/bin/bazel-execlog
637 #!${runtimeShell} -e
638 ${runJdk}/bin/java -jar $out/share/parser_deploy.jar \$@
639 EOF
640 chmod +x $out/bin/bazel-execlog
641
642 # shell completion files
643 installShellCompletion --bash \
644 --name bazel.bash \
645 ./bazel_src/output/bazel-complete.bash
646 installShellCompletion --zsh \
647 --name _bazel \
648 ./bazel_src/scripts/zsh_completion/_bazel
649 installShellCompletion --fish \
650 --name bazel.fish \
651 ./bazel_src/output/bazel-complete.fish
652
653 runHook postInstall
654 '';
655
656 installCheckPhase = ''
657 runHook preInstallCheck
658
659 export TEST_TMPDIR=$(pwd)
660
661 hello_test () {
662 $out/bin/bazel test \
663 --test_output=errors \
664 examples/cpp:hello-success_test \
665 examples/java-native/src/test/java/com/example/myproject:hello
666 }
667
668 cd ./bazel_src
669
670 # If .bazelversion file is present in dist files and doesn't match `bazel` version
671 # running `bazel` command within bazel_src will fail.
672 # Let's remove .bazelversion within the test, if present it is meant to indicate bazel version
673 # to compile bazel with, not version of bazel to be built and tested.
674 rm -f .bazelversion
675
676 # test whether $WORKSPACE_ROOT/tools/bazel works
677
678 mkdir -p tools
679 cat > tools/bazel <<"EOF"
680 #!${runtimeShell} -e
681 exit 1
682 EOF
683
684 chmod +x tools/bazel
685
686 # first call should fail if tools/bazel is used
687 ! hello_test
688
689 cat > tools/bazel <<"EOF"
690 #!${runtimeShell} -e
691 exec "$BAZEL_REAL" "$@"
692 EOF
693
694 # second call succeeds because it defers to $out/bin/bazel-{version}-{os_arch}
695 hello_test
696
697 ## Test that the GSON serialisation files are present
698 gson_classes=$(unzip -l $(bazel info install_base)/A-server.jar | grep GsonTypeAdapter.class | wc -l)
699 if [ "$gson_classes" -lt 10 ]; then
700 echo "Missing GsonTypeAdapter classes in A-server.jar. Lockfile generation will not work"
701 exit 1
702 fi
703
704 runHook postInstallCheck
705 '';
706
707 # Save paths to hardcoded dependencies so Nix can detect them.
708 # This is needed because the templates get tar’d up into a .jar.
709 postFixup = ''
710 mkdir -p $out/nix-support
711 echo "${defaultShellPath}" >> $out/nix-support/depends
712 # The string literal specifying the path to the bazel-rc file is sometimes
713 # stored non-contiguously in the binary due to gcc optimisations, which leads
714 # Nix to miss the hash when scanning for dependencies
715 echo "${bazelRC}" >> $out/nix-support/depends
716 ''
717 + lib.optionalString stdenv.hostPlatform.isDarwin ''
718 echo "${cctools}" >> $out/nix-support/depends
719 '';
720
721 dontStrip = true;
722 dontPatchELF = true;
723
724 # Work around an issue with the old vendored zlib and modern versions
725 # of Clang on macOS.
726 #
727 # Fixed in newer versions of Bazel and rules_java; see
728 # <https://github.com/bazelbuild/bazel/issues/25124>.
729 #
730 # Credit to Homebrew for the hack:
731 # <https://github.com/Homebrew/homebrew-core/blob/b61d1f7d7963c08c472d829b25de5d0a06dc4b3d/Formula/b/bazel.rb#L55-L60>
732 env.NIX_CFLAGS_COMPILE = lib.optionalString stdenv.hostPlatform.isDarwin "-fno-define-target-os-macros";
733
734 passthru = {
735 # TODO add some tests to cover basic functionality, and also tests for enableNixHacks=true (buildBazelPackage tests)
736 # tests = ...
737
738 # For ease of debugging
739 inherit bazelDeps bazelFhs bazelBootstrap;
740 };
741}