Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1{
2 stdenv,
3 callPackage,
4 lib,
5 fetchurl,
6 fetchFromGitHub,
7 installShellFiles,
8 runCommand,
9 runCommandCC,
10 makeWrapper,
11 # this package (through the fixpoint glass)
12 bazel_self,
13 lr,
14 xe,
15 zip,
16 unzip,
17 bash,
18 coreutils,
19 which,
20 gawk,
21 gnused,
22 gnutar,
23 gnugrep,
24 gzip,
25 findutils,
26 # updater
27 python3,
28 writeScript,
29 # Apple dependencies
30 cctools,
31 sigtool,
32 # Allow to independently override the jdks used to build and run respectively
33 buildJdk,
34 runJdk,
35 runtimeShell,
36 # Always assume all markers valid (this is needed because we remove markers; they are non-deterministic).
37 # Also, don't clean up environment variables (so that NIX_ environment variables are passed to compilers).
38 enableNixHacks ? false,
39 file,
40 replaceVars,
41 writeTextFile,
42}:
43
44let
45 version = "5.4.1";
46 sourceRoot = ".";
47
48 src = fetchurl {
49 url = "https://github.com/bazelbuild/bazel/releases/download/${version}/bazel-${version}-dist.zip";
50 hash = "sha256-3P9pNXVqp6yk/Fabsr0m4VN/Cx9tG9pfKyAPqDXMUH8=";
51 };
52
53 # Update with
54 # 1. export BAZEL_SELF=$(nix-build -A bazel_5)
55 # 2. update version and hash for sources above
56 # 3. `eval $(nix-build -A bazel_5.updater)`
57 # 4. add new dependencies from the dict in ./src-deps.json if required by failing build
58 srcDeps = lib.attrsets.attrValues srcDepsSet;
59 srcDepsSet =
60 let
61 srcs = lib.importJSON ./src-deps.json;
62 toFetchurl =
63 d:
64 lib.attrsets.nameValuePair d.name (fetchurl {
65 urls = d.urls;
66 sha256 = d.sha256;
67 });
68 in
69 builtins.listToAttrs (
70 map toFetchurl [
71 srcs.desugar_jdk_libs
72 srcs.io_bazel_skydoc
73 srcs.bazel_skylib
74 srcs.bazelci_rules
75 srcs.io_bazel_rules_sass
76 srcs.platforms
77 srcs."remote_java_tools_for_testing"
78 srcs."coverage_output_generator-v2.5.zip"
79 srcs.build_bazel_rules_nodejs
80 srcs."android_tools_pkg-0.23.0.tar.gz"
81 srcs.bazel_toolchains
82 srcs.com_github_grpc_grpc
83 srcs.upb
84 srcs.com_google_protobuf
85 srcs.rules_pkg
86 srcs.rules_cc
87 srcs.rules_java
88 srcs.rules_proto
89 srcs.com_google_absl
90 srcs.com_googlesource_code_re2
91 srcs.com_github_cares_cares
92 ]
93 );
94
95 distDir = runCommand "bazel-deps" { } ''
96 mkdir -p $out
97 for i in ${builtins.toString srcDeps}; do cp $i $out/$(stripHash $i); done
98 '';
99
100 defaultShellUtils =
101 # Keep this list conservative. For more exotic tools, prefer to use
102 # @rules_nixpkgs to pull in tools from the nix repository. Example:
103 #
104 # WORKSPACE:
105 #
106 # nixpkgs_git_repository(
107 # name = "nixpkgs",
108 # revision = "def5124ec8367efdba95a99523dd06d918cb0ae8",
109 # )
110 #
111 # # This defines an external Bazel workspace.
112 # nixpkgs_package(
113 # name = "bison",
114 # repositories = { "nixpkgs": "@nixpkgs//:default.nix" },
115 # )
116 #
117 # some/BUILD.bazel:
118 #
119 # genrule(
120 # ...
121 # cmd = "$(location @bison//:bin/bison) -other -args",
122 # tools = [
123 # ...
124 # "@bison//:bin/bison",
125 # ],
126 # )
127 [
128 bash
129 coreutils
130 file
131 findutils
132 gawk
133 gnugrep
134 gnused
135 gnutar
136 gzip
137 python3
138 unzip
139 which
140 zip
141 ];
142
143 defaultShellPath = lib.makeBinPath defaultShellUtils;
144
145 platforms = lib.platforms.linux ++ lib.platforms.darwin;
146
147 system = if stdenv.hostPlatform.isDarwin then "darwin" else "linux";
148
149 # on aarch64 Darwin, `uname -m` returns "arm64"
150 arch = with stdenv.hostPlatform; if isDarwin && isAarch64 then "arm64" else parsed.cpu.name;
151
152 bazelRC = writeTextFile {
153 name = "bazel-rc";
154 text = ''
155 startup --server_javabase=${runJdk}
156
157 # Can't use 'common'; https://github.com/bazelbuild/bazel/issues/3054
158 # Most commands inherit from 'build' anyway.
159 build --distdir=${distDir}
160 fetch --distdir=${distDir}
161 query --distdir=${distDir}
162
163 build --extra_toolchains=@bazel_tools//tools/jdk:nonprebuilt_toolchain_definition
164 build --tool_java_runtime_version=local_jdk_11
165 build --java_runtime_version=local_jdk_11
166
167 # load default location for the system wide configuration
168 try-import /etc/bazel.bazelrc
169 '';
170 };
171
172in
173stdenv.mkDerivation rec {
174 pname = "bazel";
175 inherit version;
176
177 meta = with lib; {
178 homepage = "https://github.com/bazelbuild/bazel/";
179 description = "Build tool that builds code quickly and reliably";
180 sourceProvenance = with sourceTypes; [
181 fromSource
182 binaryBytecode # source bundles dependencies as jars
183 ];
184 license = licenses.asl20;
185 teams = [ lib.teams.bazel ];
186 mainProgram = "bazel";
187 inherit platforms;
188 };
189
190 inherit src;
191 inherit sourceRoot;
192 patches = [
193 ./upb-clang16.patch
194
195 # On Darwin, the last argument to gcc is coming up as an empty string. i.e: ''
196 # This is breaking the build of any C target. This patch removes the last
197 # argument if it's found to be an empty string.
198 ../trim-last-argument-to-gcc-if-empty.patch
199
200 # On Darwin, using clang 6 to build fails because of a linker error (see #105573),
201 # but using clang 7 fails because libarclite_macosx.a cannot be found when linking
202 # the xcode_locator tool.
203 # This patch removes using the -fobjc-arc compiler option and makes the code
204 # compile without automatic reference counting. Caveat: this leaks memory, but
205 # we accept this fact because xcode_locator is only a short-lived process used during the build.
206 (replaceVars ./no-arc.patch {
207 multiBinPatch = if stdenv.hostPlatform.system == "aarch64-darwin" then "arm64" else "x86_64";
208 })
209
210 # --experimental_strict_action_env (which may one day become the default
211 # see bazelbuild/bazel#2574) hardcodes the default
212 # action environment to a non hermetic value (e.g. "/usr/local/bin").
213 # This is non hermetic on non-nixos systems. On NixOS, bazel cannot find the required binaries.
214 # So we are replacing this bazel paths by defaultShellPath,
215 # improving hermeticity and making it work in nixos.
216 (replaceVars ../strict_action_env.patch {
217 strictActionEnvPatch = defaultShellPath;
218 })
219
220 (replaceVars ./actions_path.patch {
221 actionsPathPatch = defaultShellPath;
222 })
223
224 # bazel reads its system bazelrc in /etc
225 # override this path to a builtin one
226 (replaceVars ../bazel_rc.patch {
227 bazelSystemBazelRCPath = bazelRC;
228 })
229
230 # disable suspend detection during a build inside Nix as this is
231 # not available inside the darwin sandbox
232 ./bazel_darwin_sandbox.patch
233 ]
234 ++ lib.optional enableNixHacks ../nix-hacks.patch;
235
236 # Additional tests that check bazel’s functionality. Execute
237 #
238 # nix-build . -A bazel_5.tests
239 #
240 # in the nixpkgs checkout root to exercise them locally.
241 passthru.tests =
242 let
243 runLocal =
244 name: attrs: script:
245 let
246 attrs' = removeAttrs attrs [ "buildInputs" ];
247 buildInputs = attrs.buildInputs or [ ];
248 in
249 runCommandCC name (
250 {
251 inherit buildInputs;
252 preferLocalBuild = true;
253 meta.platforms = platforms;
254 }
255 // attrs'
256 ) script;
257
258 # bazel wants to extract itself into $install_dir/install every time it runs,
259 # so let’s do that only once.
260 extracted =
261 bazelPkg:
262 let
263 install_dir =
264 # `install_base` field printed by `bazel info`, minus the hash.
265 # yes, this path is kinda magic. Sorry.
266 "$HOME/.cache/bazel/_bazel_nixbld";
267 in
268 runLocal "bazel-extracted-homedir" { passthru.install_dir = install_dir; } ''
269 export HOME=$(mktemp -d)
270 touch WORKSPACE # yeah, everything sucks
271 install_base="$(${bazelPkg}/bin/bazel info | grep install_base)"
272 # assert it’s actually below install_dir
273 [[ "$install_base" =~ ${install_dir} ]] \
274 || (echo "oh no! $install_base but we are \
275 trying to copy ${install_dir} to $out instead!"; exit 1)
276 cp -R ${install_dir} $out
277 '';
278
279 bazelTest =
280 {
281 name,
282 bazelScript,
283 workspaceDir,
284 bazelPkg,
285 buildInputs ? [ ],
286 }:
287 let
288 be = extracted bazelPkg;
289 in
290 runLocal name { inherit buildInputs; } (
291 # skip extraction caching on Darwin, because nobody knows how Darwin works
292 (lib.optionalString (!stdenv.hostPlatform.isDarwin) ''
293 # set up home with pre-unpacked bazel
294 export HOME=$(mktemp -d)
295 mkdir -p ${be.install_dir}
296 cp -R ${be}/install ${be.install_dir}
297
298 # https://stackoverflow.com/questions/47775668/bazel-how-to-skip-corrupt-installation-on-centos6
299 # Bazel checks whether the mtime of the install dir files
300 # is >9 years in the future, otherwise it extracts itself again.
301 # see PosixFileMTime::IsUntampered in src/main/cpp/util
302 # What the hell bazel.
303 ${lr}/bin/lr -0 -U ${be.install_dir} | ${xe}/bin/xe -N0 -0 touch --date="9 years 6 months" {}
304 '')
305 + ''
306 # Note https://github.com/bazelbuild/bazel/issues/5763#issuecomment-456374609
307 # about why to create a subdir for the workspace.
308 cp -r ${workspaceDir} wd && chmod u+w wd && cd wd
309
310 ${bazelScript}
311
312 touch $out
313 ''
314 );
315
316 bazelWithNixHacks = bazel_self.override { enableNixHacks = true; };
317
318 bazel-examples = fetchFromGitHub {
319 owner = "bazelbuild";
320 repo = "examples";
321 rev = "4183fc709c26a00366665e2d60d70521dc0b405d";
322 sha256 = "1mm4awx6sa0myiz9j4hwp71rpr7yh8vihf3zm15n2ii6xb82r31k";
323 };
324
325 in
326 (lib.optionalAttrs (!stdenv.hostPlatform.isDarwin) {
327 # `extracted` doesn’t work on darwin
328 shebang = callPackage ../shebang-test.nix {
329 inherit
330 runLocal
331 extracted
332 bazelTest
333 distDir
334 ;
335 bazel = bazel_self;
336 };
337 })
338 // {
339 bashTools = callPackage ../bash-tools-test.nix {
340 inherit runLocal bazelTest distDir;
341 bazel = bazel_self;
342 };
343 cpp = callPackage ../cpp-test.nix {
344 inherit
345 runLocal
346 bazelTest
347 bazel-examples
348 distDir
349 ;
350 bazel = bazel_self;
351 };
352 java = callPackage ../java-test.nix {
353 inherit
354 runLocal
355 bazelTest
356 bazel-examples
357 distDir
358 ;
359 bazel = bazel_self;
360 };
361 protobuf = callPackage ../protobuf-test.nix {
362 inherit runLocal bazelTest distDir;
363 bazel = bazel_self;
364 };
365 pythonBinPath = callPackage ../python-bin-path-test.nix {
366 inherit runLocal bazelTest distDir;
367 bazel = bazel_self;
368 };
369
370 bashToolsWithNixHacks = callPackage ../bash-tools-test.nix {
371 inherit runLocal bazelTest distDir;
372 bazel = bazelWithNixHacks;
373 };
374
375 cppWithNixHacks = callPackage ../cpp-test.nix {
376 inherit
377 runLocal
378 bazelTest
379 bazel-examples
380 distDir
381 ;
382 bazel = bazelWithNixHacks;
383 };
384 javaWithNixHacks = callPackage ../java-test.nix {
385 inherit
386 runLocal
387 bazelTest
388 bazel-examples
389 distDir
390 ;
391 bazel = bazelWithNixHacks;
392 };
393 protobufWithNixHacks = callPackage ../protobuf-test.nix {
394 inherit runLocal bazelTest distDir;
395 bazel = bazelWithNixHacks;
396 };
397 pythonBinPathWithNixHacks = callPackage ../python-bin-path-test.nix {
398 inherit runLocal bazelTest distDir;
399 bazel = bazelWithNixHacks;
400 };
401 };
402
403 src_for_updater = stdenv.mkDerivation {
404 name = "updater-sources";
405 inherit src;
406 nativeBuildInputs = [ unzip ];
407 inherit sourceRoot;
408 installPhase = ''
409 runHook preInstall
410
411 cp -r . "$out"
412
413 runHook postInstall
414 '';
415 };
416 # update the list of workspace dependencies
417 passthru.updater = writeScript "update-bazel-deps.sh" ''
418 #!${runtimeShell}
419 (cd "${src_for_updater}" &&
420 BAZEL_USE_CPP_ONLY_TOOLCHAIN=1 \
421 "$BAZEL_SELF"/bin/bazel \
422 query 'kind(http_archive, //external:*) + kind(http_file, //external:*) + kind(distdir_tar, //external:*) + kind(git_repository, //external:*)' \
423 --loading_phase_threads=1 \
424 --output build) \
425 | "${python3}"/bin/python3 "${./update-srcDeps.py}" \
426 "${builtins.toString ./src-deps.json}"
427 '';
428
429 # Necessary for the tests to pass on Darwin with sandbox enabled.
430 # Bazel starts a local server and needs to bind a local address.
431 __darwinAllowLocalNetworking = true;
432
433 postPatch =
434 let
435
436 darwinPatches = ''
437 bazelLinkFlags () {
438 eval set -- "$NIX_LDFLAGS"
439 local flag
440 for flag in "$@"; do
441 printf ' -Wl,%s' "$flag"
442 done
443 }
444
445 # Disable Bazel's Xcode toolchain detection which would configure compilers
446 # and linkers from Xcode instead of from PATH
447 export BAZEL_USE_CPP_ONLY_TOOLCHAIN=1
448
449 # Explicitly configure gcov since we don't have it on Darwin, so autodetection fails
450 export GCOV=${coreutils}/bin/false
451
452 # libcxx includes aren't added by libcxx hook
453 # https://github.com/NixOS/nixpkgs/pull/41589
454 export NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -isystem ${lib.getInclude stdenv.cc.libcxx}/include/c++/v1"
455 # for CLang 16 compatibility in external/{absl,upb} dependencies and in execlog
456 export NIX_CFLAGS_COMPILE+=" -Wno-deprecated-builtins -Wno-gnu-offsetof-extensions -Wno-implicit-function-declaration"
457
458 # don't use system installed Xcode to run clang, use Nix clang instead
459 sed -i -E "s;/usr/bin/xcrun (--sdk macosx )?clang;${stdenv.cc}/bin/clang $NIX_CFLAGS_COMPILE $(bazelLinkFlags) -framework CoreFoundation;g" \
460 scripts/bootstrap/compile.sh \
461 tools/osx/BUILD
462
463 substituteInPlace scripts/bootstrap/compile.sh --replace ' -mmacosx-version-min=10.9' ""
464
465 # nixpkgs's libSystem cannot use pthread headers directly, must import GCD headers instead
466 sed -i -e "/#include <pthread\/spawn.h>/i #include <dispatch/dispatch.h>" src/main/cpp/blaze_util_darwin.cc
467
468 # clang installed from Xcode has a compatibility wrapper that forwards
469 # invocations of gcc to clang, but vanilla clang doesn't
470 sed -i -e 's;_find_generic(repository_ctx, "gcc", "CC", overriden_tools);_find_generic(repository_ctx, "clang", "CC", overriden_tools);g' tools/cpp/unix_cc_configure.bzl
471 sed -i -e 's;env -i codesign --identifier $@ --force --sign;env -i CODESIGN_ALLOCATE=${cctools}/bin/${cctools.targetPrefix}codesign_allocate ${sigtool}/bin/codesign --identifier $@ --force -s;g' tools/osx/BUILD
472 sed -i -e 's;"/usr/bin/libtool";_find_generic(repository_ctx, "libtool", "LIBTOOL", overriden_tools);g' tools/cpp/unix_cc_configure.bzl
473 wrappers=( tools/cpp/osx_cc_wrapper.sh tools/cpp/osx_cc_wrapper.sh.tpl )
474 for wrapper in "''${wrappers[@]}"; do
475 sed -i -e "s,/usr/bin/gcc,${stdenv.cc}/bin/clang,g" $wrapper
476 sed -i -e "s,/usr/bin/install_name_tool,${cctools}/bin/install_name_tool,g" $wrapper
477 done
478 '';
479
480 genericPatches = ''
481 # Substitute j2objc and objc wrapper's python shebang to plain python path.
482 substituteInPlace tools/j2objc/j2objc_header_map.py --replace "$!/usr/bin/python2.7" "#!${python3.interpreter}"
483 substituteInPlace tools/j2objc/j2objc_wrapper.py --replace "$!/usr/bin/python2.7" "#!${python3.interpreter}"
484 substituteInPlace tools/objc/j2objc_dead_code_pruner.py --replace "$!/usr/bin/python2.7" "#!${python3.interpreter}"
485
486 # md5sum is part of coreutils
487 sed -i 's|/sbin/md5|md5sum|g' \
488 src/BUILD third_party/ijar/test/testenv.sh tools/objc/libtool.sh
489
490 # replace initial value of pythonShebang variable in BazelPythonSemantics.java
491 substituteInPlace src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonSemantics.java \
492 --replace '"#!/usr/bin/env " + pythonExecutableName' "\"#!${python3}/bin/python\""
493
494 substituteInPlace src/main/java/com/google/devtools/build/lib/starlarkbuildapi/python/PyRuntimeInfoApi.java \
495 --replace '"#!/usr/bin/env python3"' "\"#!${python3}/bin/python\""
496
497 # substituteInPlace is rather slow, so prefilter the files with grep
498 grep -rlZ /bin/ src/main/java/com/google/devtools | while IFS="" read -r -d "" path; do
499 # If you add more replacements here, you must change the grep above!
500 # Only files containing /bin are taken into account.
501 substituteInPlace "$path" \
502 --replace /bin/bash ${bash}/bin/bash \
503 --replace "/usr/bin/env bash" ${bash}/bin/bash \
504 --replace "/usr/bin/env python" ${python3}/bin/python \
505 --replace /usr/bin/env ${coreutils}/bin/env \
506 --replace /bin/true ${coreutils}/bin/true
507 done
508
509 grep -rlZ /bin/ tools/python | while IFS="" read -r -d "" path; do
510 substituteInPlace "$path" \
511 --replace "/usr/bin/env python2" ${python3.interpreter} \
512 --replace "/usr/bin/env python3" ${python3}/bin/python \
513 --replace /usr/bin/env ${coreutils}/bin/env
514 done
515
516 # bazel test runner include references to /bin/bash
517 substituteInPlace tools/build_rules/test_rules.bzl \
518 --replace /bin/bash ${bash}/bin/bash
519
520 for i in $(find tools/cpp/ -type f)
521 do
522 substituteInPlace $i \
523 --replace /bin/bash ${bash}/bin/bash
524 done
525
526 # Fixup scripts that generate scripts. Not fixed up by patchShebangs below.
527 substituteInPlace scripts/bootstrap/compile.sh \
528 --replace /bin/bash ${bash}/bin/bash
529
530 # add nix environment vars to .bazelrc
531 cat >> .bazelrc <<EOF
532 # Limit the resources Bazel is allowed to use during the build to 1/2 the
533 # available RAM and 3/4 the available CPU cores. This should help avoid
534 # overwhelming the build machine.
535 build --local_ram_resources=HOST_RAM*.5
536 build --local_cpu_resources=HOST_CPUS*.75
537
538 build --distdir=${distDir}
539 fetch --distdir=${distDir}
540 build --copt="$(echo $NIX_CFLAGS_COMPILE | sed -e 's/ /" --copt="/g')"
541 build --host_copt="$(echo $NIX_CFLAGS_COMPILE | sed -e 's/ /" --host_copt="/g')"
542 build --linkopt="$(echo $(< ${stdenv.cc}/nix-support/libcxx-ldflags) | sed -e 's/ /" --linkopt="/g')"
543 build --host_linkopt="$(echo $(< ${stdenv.cc}/nix-support/libcxx-ldflags) | sed -e 's/ /" --host_linkopt="/g')"
544 build --linkopt="-Wl,$(echo $NIX_LDFLAGS | sed -e 's/ /" --linkopt="-Wl,/g')"
545 build --host_linkopt="-Wl,$(echo $NIX_LDFLAGS | sed -e 's/ /" --host_linkopt="-Wl,/g')"
546 build --extra_toolchains=@bazel_tools//tools/jdk:nonprebuilt_toolchain_definition
547 build --verbose_failures
548 build --curses=no
549 build --features=-layering_check
550 EOF
551
552 cat >> tools/jdk/BUILD.tools <<EOF
553 load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "default_java_toolchain", "NONPREBUILT_TOOLCHAIN_CONFIGURATION")
554 default_java_toolchain(
555 name = "nonprebuilt_toolchain",
556 configuration = NONPREBUILT_TOOLCHAIN_CONFIGURATION,
557 java_runtime = "@local_jdk//:jdk",
558 )
559 EOF
560
561 cat >> third_party/grpc/bazel_1.41.0.patch <<EOF
562 diff --git a/third_party/grpc/BUILD b/third_party/grpc/BUILD
563 index 39ee9f97c6..9128d20c85 100644
564 --- a/third_party/grpc/BUILD
565 +++ b/third_party/grpc/BUILD
566 @@ -28,7 +28,6 @@ licenses(["notice"])
567 package(
568 default_visibility = ["//visibility:public"],
569 features = [
570 - "layering_check",
571 "-parse_headers",
572 ],
573 )
574 EOF
575
576 # add the same environment vars to compile.sh
577 sed -e "/\$command \\\\$/a --copt=\"$(echo $NIX_CFLAGS_COMPILE | sed -e 's/ /" --copt=\"/g')\" \\\\" \
578 -e "/\$command \\\\$/a --host_copt=\"$(echo $NIX_CFLAGS_COMPILE | sed -e 's/ /" --host_copt=\"/g')\" \\\\" \
579 -e "/\$command \\\\$/a --linkopt=\"$(echo $(< ${stdenv.cc}/nix-support/libcxx-ldflags) | sed -e 's/ /" --linkopt=\"/g')\" \\\\" \
580 -e "/\$command \\\\$/a --host_linkopt=\"$(echo $(< ${stdenv.cc}/nix-support/libcxx-ldflags) | sed -e 's/ /" --host_linkopt=\"/g')\" \\\\" \
581 -e "/\$command \\\\$/a --linkopt=\"-Wl,$(echo $NIX_LDFLAGS | sed -e 's/ /" --linkopt=\"-Wl,/g')\" \\\\" \
582 -e "/\$command \\\\$/a --host_linkopt=\"-Wl,$(echo $NIX_LDFLAGS | sed -e 's/ /" --host_linkopt=\"-Wl,/g')\" \\\\" \
583 -e "/\$command \\\\$/a --tool_java_runtime_version=local_jdk_11 \\\\" \
584 -e "/\$command \\\\$/a --java_runtime_version=local_jdk_11 \\\\" \
585 -e "/\$command \\\\$/a --verbose_failures \\\\" \
586 -e "/\$command \\\\$/a --curses=no \\\\" \
587 -e "/\$command \\\\$/a --features=-layering_check \\\\" \
588 -i scripts/bootstrap/compile.sh
589
590 # This is necessary to avoid:
591 # "error: no visible @interface for 'NSDictionary' declares the selector
592 # 'initWithContentsOfURL:error:'"
593 # This can be removed when the apple_sdk is upgraded beyond 10.13+
594 sed -i '/initWithContentsOfURL:versionPlistUrl/ {
595 N
596 s/error:nil\];/\];/
597 }' tools/osx/xcode_locator.m
598
599 # append the PATH with defaultShellPath in tools/bash/runfiles/runfiles.bash
600 echo "PATH=\$PATH:${defaultShellPath}" >> runfiles.bash.tmp
601 cat tools/bash/runfiles/runfiles.bash >> runfiles.bash.tmp
602 mv runfiles.bash.tmp tools/bash/runfiles/runfiles.bash
603
604 patchShebangs .
605 '';
606 in
607 lib.optionalString stdenv.hostPlatform.isDarwin darwinPatches + genericPatches;
608
609 buildInputs = [ buildJdk ] ++ defaultShellUtils;
610
611 # when a command can’t be found in a bazel build, you might also
612 # need to add it to `defaultShellPath`.
613 nativeBuildInputs = [
614 installShellFiles
615 makeWrapper
616 python3
617 unzip
618 which
619 zip
620 python3.pkgs.absl-py # Needed to build fish completion
621 ]
622 ++ lib.optionals (stdenv.hostPlatform.isDarwin) [
623 cctools
624 ];
625
626 # Bazel makes extensive use of symlinks in the WORKSPACE.
627 # This causes problems with infinite symlinks if the build output is in the same location as the
628 # Bazel WORKSPACE. This is why before executing the build, the source code is moved into a
629 # subdirectory.
630 # Failing to do this causes "infinite symlink expansion detected"
631 preBuildPhases = [ "preBuildPhase" ];
632 preBuildPhase = ''
633 mkdir bazel_src
634 shopt -s dotglob extglob
635 mv !(bazel_src) bazel_src
636 '';
637 buildPhase = ''
638 runHook preBuild
639
640 # Increasing memory during compilation might be necessary.
641 # export BAZEL_JAVAC_OPTS="-J-Xmx2g -J-Xms200m"
642
643 # If EMBED_LABEL isn't set, it'd be auto-detected from CHANGELOG.md
644 # and `git rev-parse --short HEAD` which would result in
645 # "3.7.0- (@non-git)" due to non-git build and incomplete changelog.
646 # Actual bazel releases use scripts/release/common.sh which is based
647 # on branch/tag information which we don't have with tarball releases.
648 # Note that .bazelversion is always correct and is based on bazel-*
649 # executable name, version checks should work fine
650 export EMBED_LABEL="${version}- (@non-git)"
651 ${bash}/bin/bash ./bazel_src/compile.sh
652 ./bazel_src/scripts/generate_bash_completion.sh \
653 --bazel=./bazel_src/output/bazel \
654 --output=./bazel_src/output/bazel-complete.bash \
655 --prepend=./bazel_src/scripts/bazel-complete-header.bash \
656 --prepend=./bazel_src/scripts/bazel-complete-template.bash
657 ${python3}/bin/python3 ./bazel_src/scripts/generate_fish_completion.py \
658 --bazel=./bazel_src/output/bazel \
659 --output=./bazel_src/output/bazel-complete.fish
660
661 # need to change directory for bazel to find the workspace
662 cd ./bazel_src
663 # build execlog tooling
664 export HOME=$(mktemp -d)
665 ./output/bazel build src/tools/execlog:parser_deploy.jar
666 cd -
667
668 runHook postBuild
669 '';
670
671 installPhase = ''
672 runHook preInstall
673
674 mkdir -p $out/bin
675
676 # official wrapper scripts that searches for $WORKSPACE_ROOT/tools/bazel
677 # if it can’t find something in tools, it calls $out/bin/bazel-{version}-{os_arch}
678 # The binary _must_ exist with this naming if your project contains a .bazelversion
679 # file.
680 cp ./bazel_src/scripts/packages/bazel.sh $out/bin/bazel
681 wrapProgram $out/bin/bazel $wrapperfile --suffix PATH : ${defaultShellPath}
682 mv ./bazel_src/output/bazel $out/bin/bazel-${version}-${system}-${arch}
683
684 mkdir $out/share
685 cp ./bazel_src/bazel-bin/src/tools/execlog/parser_deploy.jar $out/share/parser_deploy.jar
686 cat <<EOF > $out/bin/bazel-execlog
687 #!${runtimeShell} -e
688 ${runJdk}/bin/java -jar $out/share/parser_deploy.jar \$@
689 EOF
690 chmod +x $out/bin/bazel-execlog
691
692 # shell completion files
693 installShellCompletion --bash \
694 --name bazel.bash \
695 ./bazel_src/output/bazel-complete.bash
696 installShellCompletion --zsh \
697 --name _bazel \
698 ./bazel_src/scripts/zsh_completion/_bazel
699 installShellCompletion --fish \
700 --name bazel.fish \
701 ./bazel_src/output/bazel-complete.fish
702
703 runHook postInstall
704 '';
705
706 # Install check fails on `aarch64-darwin`
707 # https://github.com/NixOS/nixpkgs/issues/145587
708 doInstallCheck = stdenv.hostPlatform.system != "aarch64-darwin";
709 installCheckPhase = ''
710 runHook preInstallCheck
711
712 export TEST_TMPDIR=$(pwd)
713
714 hello_test () {
715 $out/bin/bazel test \
716 --test_output=errors \
717 examples/cpp:hello-success_test \
718 examples/java-native/src/test/java/com/example/myproject:hello
719 }
720
721 cd ./bazel_src
722 rm .bazelversion # this doesn't necessarily match the version we built
723
724 # test whether $WORKSPACE_ROOT/tools/bazel works
725
726 mkdir -p tools
727 cat > tools/bazel <<"EOF"
728 #!${runtimeShell} -e
729 exit 1
730 EOF
731 chmod +x tools/bazel
732
733 # first call should fail if tools/bazel is used
734 ! hello_test
735
736 cat > tools/bazel <<"EOF"
737 #!${runtimeShell} -e
738 exec "$BAZEL_REAL" "$@"
739 EOF
740
741 # second call succeeds because it defers to $out/bin/bazel-{version}-{os_arch}
742 hello_test
743
744 runHook postInstallCheck
745 '';
746
747 # Save paths to hardcoded dependencies so Nix can detect them.
748 # This is needed because the templates get tar’d up into a .jar.
749 postFixup = ''
750 mkdir -p $out/nix-support
751 echo "${defaultShellPath}" >> $out/nix-support/depends
752 # The string literal specifying the path to the bazel-rc file is sometimes
753 # stored non-contiguously in the binary due to gcc optimisations, which leads
754 # Nix to miss the hash when scanning for dependencies
755 echo "${bazelRC}" >> $out/nix-support/depends
756 ''
757 + lib.optionalString stdenv.hostPlatform.isDarwin ''
758 echo "${cctools}" >> $out/nix-support/depends
759 '';
760
761 dontStrip = true;
762 dontPatchELF = true;
763}