linux_xanmod: 5.11.14 -> 5.11.15
[NixPkgs.git] / pkgs / build-support / build-bazel-package / default.nix
blob988298ac72bfec89f30f052a039636b89114ed1f
1 { stdenv
2 , bazel
3 , cacert
4 , lib
5 }:
7 let
8   bazelPkg = bazel;
9 in
11 args@{
12   name ? "${args.pname}-${args.version}"
13 , bazel ? bazelPkg
14 , bazelFlags ? []
15 , bazelBuildFlags ? []
16 , bazelFetchFlags ? []
17 , bazelTarget
18 , buildAttrs
19 , fetchAttrs
21 # Newer versions of Bazel are moving away from built-in rules_cc and instead
22 # allow fetching it as an external dependency in a WORKSPACE file[1]. If
23 # removed in the fixed-output fetch phase, building will fail to download it.
24 # This can be seen e.g. in #73097
26 # This option allows configuring the removal of rules_cc in cases where a
27 # project depends on it via an external dependency.
29 # [1]: https://github.com/bazelbuild/rules_cc
30 , removeRulesCC ? true
31 , removeLocalConfigCc ? true
32 , removeLocal ? true
34 # Use build --nobuild instead of fetch. This allows fetching the dependencies
35 # required for the build as configured, rather than fetching all the dependencies
36 # which may not work in some situations (e.g. Java code which ends up relying on
37 # Debian-specific /usr/share/java paths, but doesn't in the configured build).
38 , fetchConfigured ? false
40 # Don’t add Bazel --copt and --linkopt from NIX_CFLAGS_COMPILE /
41 # NIX_LDFLAGS. This is necessary when using a custom toolchain which
42 # Bazel wants all headers / libraries to come from, like when using
43 # CROSSTOOL. Weirdly, we can still get the flags through the wrapped
44 # compiler.
45 , dontAddBazelOpts ? false
46 , ...
49 let
50   fArgs = removeAttrs args [ "buildAttrs" "fetchAttrs" "removeRulesCC" ];
51   fBuildAttrs = fArgs // buildAttrs;
52   fFetchAttrs = fArgs // removeAttrs fetchAttrs [ "sha256" ];
54 in stdenv.mkDerivation (fBuildAttrs // {
55   inherit name bazelFlags bazelBuildFlags bazelFetchFlags bazelTarget;
57   deps = stdenv.mkDerivation (fFetchAttrs // {
58     name = "${name}-deps.tar.gz";
59     inherit bazelFlags bazelBuildFlags bazelFetchFlags bazelTarget;
61     impureEnvVars = lib.fetchers.proxyImpureEnvVars;
63     nativeBuildInputs = fFetchAttrs.nativeBuildInputs or [] ++ [ bazel ];
65     preHook = fFetchAttrs.preHook or "" + ''
66       export bazelOut="$(echo ''${NIX_BUILD_TOP}/output | sed -e 's,//,/,g')"
67       export bazelUserRoot="$(echo ''${NIX_BUILD_TOP}/tmp | sed -e 's,//,/,g')"
68       export HOME="$NIX_BUILD_TOP"
69       export USER="nix"
70       # This is needed for git_repository with https remotes
71       export GIT_SSL_CAINFO="${cacert}/etc/ssl/certs/ca-bundle.crt"
72       # This is needed for Bazel fetchers that are themselves programs (e.g.
73       # rules_go using the go toolchain)
74       export SSL_CERT_FILE="${cacert}/etc/ssl/certs/ca-bundle.crt"
75     '';
77     buildPhase = fFetchAttrs.buildPhase or ''
78       runHook preBuild
80       # Bazel computes the default value of output_user_root before parsing the
81       # flag. The computation of the default value involves getting the $USER
82       # from the environment. I don't have that variable when building with
83       # sandbox enabled. Code here
84       # https://github.com/bazelbuild/bazel/blob/9323c57607d37f9c949b60e293b573584906da46/src/main/cpp/startup_options.cc#L123-L124
85       #
86       # On macOS Bazel will use the system installed Xcode or CLT toolchain instead of the one in the PATH unless we pass BAZEL_USE_CPP_ONLY_TOOLCHAIN
88       # We disable multithreading for the fetching phase since it can lead to timeouts with many dependencies/threads:
89       # https://github.com/bazelbuild/bazel/issues/6502
90       BAZEL_USE_CPP_ONLY_TOOLCHAIN=1 \
91       USER=homeless-shelter \
92       bazel \
93         --output_base="$bazelOut" \
94         --output_user_root="$bazelUserRoot" \
95         ${if fetchConfigured then "build --nobuild" else "fetch"} \
96         --loading_phase_threads=1 \
97         $bazelFlags \
98         $bazelFetchFlags \
99         $bazelTarget
101       runHook postBuild
102     '';
104     installPhase = fFetchAttrs.installPhase or ''
105       runHook preInstall
107       # Remove all built in external workspaces, Bazel will recreate them when building
108       rm -rf $bazelOut/external/{bazel_tools,\@bazel_tools.marker}
109       ${if removeRulesCC then "rm -rf $bazelOut/external/{rules_cc,\\@rules_cc.marker}" else ""}
110       rm -rf $bazelOut/external/{embedded_jdk,\@embedded_jdk.marker}
111       ${if removeLocalConfigCc then "rm -rf $bazelOut/external/{local_config_cc,\\@local_config_cc.marker}" else ""}
112       ${if removeLocal then "rm -rf $bazelOut/external/{local_*,\\@local_*.marker}" else ""}
114       # Clear markers
115       find $bazelOut/external -name '@*\.marker' -exec sh -c 'echo > {}' \;
117       # Remove all vcs files
118       rm -rf $(find $bazelOut/external -type d -name .git)
119       rm -rf $(find $bazelOut/external -type d -name .svn)
120       rm -rf $(find $bazelOut/external -type d -name .hg)
122       # Removing top-level symlinks along with their markers.
123       # This is needed because they sometimes point to temporary paths (?).
124       # For example, in Tensorflow-gpu build:
125       # platforms -> NIX_BUILD_TOP/tmp/install/35282f5123611afa742331368e9ae529/_embedded_binaries/platforms
126       find $bazelOut/external -maxdepth 1 -type l | while read symlink; do
127         name="$(basename "$symlink")"
128         rm "$symlink"
129         test -f "$bazelOut/external/@$name.marker" && rm "$bazelOut/external/@$name.marker"
130       done
132       # Patching symlinks to remove build directory reference
133       find $bazelOut/external -type l | while read symlink; do
134         new_target="$(readlink "$symlink" | sed "s,$NIX_BUILD_TOP,NIX_BUILD_TOP,")"
135         rm "$symlink"
136         ln -sf "$new_target" "$symlink"
137       done
139       echo '${bazel.name}' > $bazelOut/external/.nix-bazel-version
141       (cd $bazelOut/ && tar czf $out --sort=name --mtime='@1' --owner=0 --group=0 --numeric-owner external/)
143       runHook postInstall
144     '';
146     dontFixup = true;
147     allowedRequisites = [];
149     outputHashAlgo = "sha256";
150     outputHash = fetchAttrs.sha256;
151   });
153   nativeBuildInputs = fBuildAttrs.nativeBuildInputs or [] ++ [ (bazel.override { enableNixHacks = true; }) ];
155   preHook = fBuildAttrs.preHook or "" + ''
156     export bazelOut="$NIX_BUILD_TOP/output"
157     export bazelUserRoot="$NIX_BUILD_TOP/tmp"
158     export HOME="$NIX_BUILD_TOP"
159   '';
161   preConfigure = ''
162     mkdir -p "$bazelOut"
164     (cd $bazelOut && tar xfz $deps)
166     test "${bazel.name}" = "$(<$bazelOut/external/.nix-bazel-version)" || {
167       echo "fixed output derivation was built for a different bazel version" >&2
168       echo "     got: $(<$bazelOut/external/.nix-bazel-version)" >&2
169       echo "expected: ${bazel.name}" >&2
170       exit 1
171     }
173     chmod -R +w $bazelOut
174     find $bazelOut -type l | while read symlink; do
175       if [[ $(readlink "$symlink") == *NIX_BUILD_TOP* ]]; then
176         ln -sf $(readlink "$symlink" | sed "s,NIX_BUILD_TOP,$NIX_BUILD_TOP,") "$symlink"
177       fi
178     done
179   '' + fBuildAttrs.preConfigure or "";
181   inherit dontAddBazelOpts;
183   buildPhase = fBuildAttrs.buildPhase or ''
184     runHook preBuild
186     # Bazel sandboxes the execution of the tools it invokes, so even though we are
187     # calling the correct nix wrappers, the values of the environment variables
188     # the wrappers are expecting will not be set. So instead of relying on the
189     # wrappers picking them up, pass them in explicitly via `--copt`, `--linkopt`
190     # and related flags.
191     #
192     copts=()
193     host_copts=()
194     linkopts=()
195     host_linkopts=()
196     if [ -z "''${dontAddBazelOpts:-}" ]; then
197       for flag in $NIX_CFLAGS_COMPILE; do
198         copts+=( "--copt=$flag" )
199         host_copts+=( "--host_copt=$flag" )
200       done
201       for flag in $NIX_CXXSTDLIB_COMPILE; do
202         copts+=( "--copt=$flag" )
203         host_copts+=( "--host_copt=$flag" )
204       done
205       for flag in $NIX_LDFLAGS; do
206         linkopts+=( "--linkopt=-Wl,$flag" )
207         host_linkopts+=( "--host_linkopt=-Wl,$flag" )
208       done
209     fi
211     BAZEL_USE_CPP_ONLY_TOOLCHAIN=1 \
212     USER=homeless-shelter \
213     bazel \
214       --output_base="$bazelOut" \
215       --output_user_root="$bazelUserRoot" \
216       build \
217       -j $NIX_BUILD_CORES \
218       "''${copts[@]}" \
219       "''${host_copts[@]}" \
220       "''${linkopts[@]}" \
221       "''${host_linkopts[@]}" \
222       $bazelFlags \
223       $bazelBuildFlags \
224       $bazelTarget
226     runHook postBuild
227   '';