2019-07-25 09:43:45 +00:00
|
|
|
|
{ stdenv
|
|
|
|
|
, cacert
|
|
|
|
|
, lib
|
2023-04-06 00:23:32 +00:00
|
|
|
|
, writeCBin
|
2019-07-25 09:43:45 +00:00
|
|
|
|
}:
|
2017-11-10 17:06:26 +00:00
|
|
|
|
|
2019-11-24 04:25:02 +00:00
|
|
|
|
args@{
|
2020-10-22 13:43:23 +00:00
|
|
|
|
name ? "${args.pname}-${args.version}"
|
2023-01-11 22:09:55 +00:00
|
|
|
|
, bazel
|
2019-11-24 04:25:02 +00:00
|
|
|
|
, bazelFlags ? []
|
|
|
|
|
, bazelBuildFlags ? []
|
2022-10-03 10:43:33 +00:00
|
|
|
|
, bazelTestFlags ? []
|
2023-06-14 08:18:15 +00:00
|
|
|
|
, bazelRunFlags ? []
|
|
|
|
|
, runTargetFlags ? []
|
2019-11-24 04:25:02 +00:00
|
|
|
|
, bazelFetchFlags ? []
|
2023-06-14 08:18:15 +00:00
|
|
|
|
, bazelTargets ? []
|
2022-10-03 10:43:33 +00:00
|
|
|
|
, bazelTestTargets ? []
|
2023-06-14 08:18:15 +00:00
|
|
|
|
, bazelRunTarget ? null
|
2019-11-24 04:25:02 +00:00
|
|
|
|
, buildAttrs
|
|
|
|
|
, fetchAttrs
|
|
|
|
|
|
2022-10-03 10:43:33 +00:00
|
|
|
|
# Newer versions of Bazel are moving away from built-in rules_cc and instead
|
|
|
|
|
# allow fetching it as an external dependency in a WORKSPACE file[1]. If
|
|
|
|
|
# removed in the fixed-output fetch phase, building will fail to download it.
|
|
|
|
|
# This can be seen e.g. in #73097
|
|
|
|
|
#
|
|
|
|
|
# This option allows configuring the removal of rules_cc in cases where a
|
|
|
|
|
# project depends on it via an external dependency.
|
|
|
|
|
#
|
|
|
|
|
# [1]: https://github.com/bazelbuild/rules_cc
|
2019-11-24 04:25:02 +00:00
|
|
|
|
, removeRulesCC ? true
|
2019-09-23 12:20:59 +00:00
|
|
|
|
, removeLocalConfigCc ? true
|
|
|
|
|
, removeLocal ? true
|
2020-07-04 23:24:35 +00:00
|
|
|
|
|
2022-10-03 10:43:33 +00:00
|
|
|
|
# Use build --nobuild instead of fetch. This allows fetching the dependencies
|
|
|
|
|
# required for the build as configured, rather than fetching all the dependencies
|
|
|
|
|
# which may not work in some situations (e.g. Java code which ends up relying on
|
|
|
|
|
# Debian-specific /usr/share/java paths, but doesn't in the configured build).
|
2021-06-06 21:28:19 +00:00
|
|
|
|
, fetchConfigured ? true
|
2020-07-04 23:24:35 +00:00
|
|
|
|
|
2022-10-03 10:43:33 +00:00
|
|
|
|
# Don’t add Bazel --copt and --linkopt from NIX_CFLAGS_COMPILE /
|
|
|
|
|
# NIX_LDFLAGS. This is necessary when using a custom toolchain which
|
|
|
|
|
# Bazel wants all headers / libraries to come from, like when using
|
|
|
|
|
# CROSSTOOL. Weirdly, we can still get the flags through the wrapped
|
|
|
|
|
# compiler.
|
2020-08-28 20:10:59 +00:00
|
|
|
|
, dontAddBazelOpts ? false
|
2019-11-24 04:25:02 +00:00
|
|
|
|
, ...
|
|
|
|
|
}:
|
2017-11-10 17:06:26 +00:00
|
|
|
|
|
|
|
|
|
let
|
2023-04-05 03:46:39 +00:00
|
|
|
|
fArgs = removeAttrs args [ "buildAttrs" "fetchAttrs" "removeRulesCC" ] // {
|
2023-06-14 08:18:15 +00:00
|
|
|
|
inherit
|
|
|
|
|
name
|
|
|
|
|
bazelFlags
|
|
|
|
|
bazelBuildFlags
|
|
|
|
|
bazelTestFlags
|
|
|
|
|
bazelRunFlags
|
|
|
|
|
runTargetFlags
|
|
|
|
|
bazelFetchFlags
|
|
|
|
|
bazelTargets
|
|
|
|
|
bazelTestTargets
|
|
|
|
|
bazelRunTarget
|
|
|
|
|
dontAddBazelOpts
|
|
|
|
|
;
|
2023-04-05 03:46:39 +00:00
|
|
|
|
};
|
2017-11-10 17:06:26 +00:00
|
|
|
|
fBuildAttrs = fArgs // buildAttrs;
|
|
|
|
|
fFetchAttrs = fArgs // removeAttrs fetchAttrs [ "sha256" ];
|
2023-06-14 08:18:15 +00:00
|
|
|
|
bazelCmd = { cmd, additionalFlags, targets, targetRunFlags ? [ ] }:
|
2022-10-03 10:43:33 +00:00
|
|
|
|
lib.optionalString (targets != [ ]) ''
|
|
|
|
|
# See footnote called [USER and BAZEL_USE_CPP_ONLY_TOOLCHAIN variables]
|
|
|
|
|
BAZEL_USE_CPP_ONLY_TOOLCHAIN=1 \
|
|
|
|
|
USER=homeless-shelter \
|
|
|
|
|
bazel \
|
|
|
|
|
--batch \
|
|
|
|
|
--output_base="$bazelOut" \
|
|
|
|
|
--output_user_root="$bazelUserRoot" \
|
|
|
|
|
${cmd} \
|
|
|
|
|
--curses=no \
|
|
|
|
|
"''${copts[@]}" \
|
|
|
|
|
"''${host_copts[@]}" \
|
|
|
|
|
"''${linkopts[@]}" \
|
|
|
|
|
"''${host_linkopts[@]}" \
|
|
|
|
|
$bazelFlags \
|
|
|
|
|
${lib.strings.concatStringsSep " " additionalFlags} \
|
2023-06-14 08:18:15 +00:00
|
|
|
|
${lib.strings.concatStringsSep " " targets} \
|
|
|
|
|
${lib.optionalString (targetRunFlags != []) " -- " + lib.strings.concatStringsSep " " targetRunFlags}
|
2022-10-03 10:43:33 +00:00
|
|
|
|
'';
|
2023-04-06 00:23:32 +00:00
|
|
|
|
# we need this to chmod dangling symlinks on darwin, gnu coreutils refuses to do so:
|
|
|
|
|
# chmod: cannot operate on dangling symlink '$symlink'
|
|
|
|
|
chmodder = writeCBin "chmodder" ''
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
int main(int argc, char** argv) {
|
|
|
|
|
mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
|
|
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "usage: chmodder file");
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
if (lchmod(argv[1], mode) != 0) {
|
|
|
|
|
fprintf(stderr, "failed to lchmod '%s': %s", argv[0], strerror(errno));
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
'';
|
2022-10-03 10:43:33 +00:00
|
|
|
|
in
|
|
|
|
|
stdenv.mkDerivation (fBuildAttrs // {
|
2017-11-10 17:06:26 +00:00
|
|
|
|
|
|
|
|
|
deps = stdenv.mkDerivation (fFetchAttrs // {
|
2020-05-09 01:48:30 +00:00
|
|
|
|
name = "${name}-deps.tar.gz";
|
2017-11-10 17:06:26 +00:00
|
|
|
|
|
2022-07-04 08:29:23 +00:00
|
|
|
|
impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ fFetchAttrs.impureEnvVars or [];
|
2020-05-09 18:35:47 +00:00
|
|
|
|
|
2017-11-10 17:06:26 +00:00
|
|
|
|
nativeBuildInputs = fFetchAttrs.nativeBuildInputs or [] ++ [ bazel ];
|
|
|
|
|
|
|
|
|
|
preHook = fFetchAttrs.preHook or "" + ''
|
2018-07-09 22:38:45 +00:00
|
|
|
|
export bazelOut="$(echo ''${NIX_BUILD_TOP}/output | sed -e 's,//,/,g')"
|
|
|
|
|
export bazelUserRoot="$(echo ''${NIX_BUILD_TOP}/tmp | sed -e 's,//,/,g')"
|
2017-11-10 17:06:26 +00:00
|
|
|
|
export HOME="$NIX_BUILD_TOP"
|
buildBazelPackage: set $USER environment variable (#74538)
tensorflow assumes $USER to be set to something, otherwise it complains
like this:
```
FATAL: $USER is not set, and unable to look up name of current user: (error: 0): Success
Traceback (most recent call last):
File "./configure.py", line 1602, in <module>
main()
File "./configure.py", line 1399, in main
_TF_MAX_BAZEL_VERSION)
File "./configure.py", line 478, in check_bazel_version
['bazel', '--batch', '--bazelrc=/dev/null', 'version'])
File "./configure.py", line 156, in run_shell
output = subprocess.check_output(cmd)
File "/nix/store/drr8qcgiccfc5by09r5zc30flgwh1mbx-python3-3.7.5/lib/python3.7/subprocess.py", line 411, in check_output
**kwargs).stdout
File "/nix/store/drr8qcgiccfc5by09r5zc30flgwh1mbx-python3-3.7.5/lib/python3.7/subprocess.py", line 512, in run
output=stdout, stderr=stderr)
```
Spotted while changing the hash of its fixed-output derivation on
purpose.
We could also set this in the tensorflow-specific part, but very likely,
other programs will fail as well.
2019-11-29 00:14:45 +00:00
|
|
|
|
export USER="nix"
|
2019-02-01 06:30:36 +00:00
|
|
|
|
# This is needed for git_repository with https remotes
|
|
|
|
|
export GIT_SSL_CAINFO="${cacert}/etc/ssl/certs/ca-bundle.crt"
|
2019-11-28 21:39:20 +00:00
|
|
|
|
# This is needed for Bazel fetchers that are themselves programs (e.g.
|
|
|
|
|
# rules_go using the go toolchain)
|
|
|
|
|
export SSL_CERT_FILE="${cacert}/etc/ssl/certs/ca-bundle.crt"
|
2017-11-10 17:06:26 +00:00
|
|
|
|
'';
|
|
|
|
|
|
|
|
|
|
buildPhase = fFetchAttrs.buildPhase or ''
|
|
|
|
|
runHook preBuild
|
|
|
|
|
|
2023-04-05 02:59:54 +00:00
|
|
|
|
${
|
|
|
|
|
bazelCmd {
|
|
|
|
|
cmd = if fetchConfigured then "build --nobuild" else "fetch";
|
|
|
|
|
additionalFlags = [
|
|
|
|
|
# We disable multithreading for the fetching phase since it can lead to timeouts with many dependencies/threads:
|
|
|
|
|
# https://github.com/bazelbuild/bazel/issues/6502
|
|
|
|
|
"--loading_phase_threads=1"
|
|
|
|
|
"$bazelFetchFlags"
|
2023-04-21 11:49:30 +00:00
|
|
|
|
] ++ (if fetchConfigured then ["--jobs" "$NIX_BUILD_CORES"] else []);
|
2023-04-05 03:46:39 +00:00
|
|
|
|
targets = fFetchAttrs.bazelTargets ++ fFetchAttrs.bazelTestTargets;
|
2023-04-05 02:59:54 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2017-11-10 17:06:26 +00:00
|
|
|
|
|
|
|
|
|
runHook postBuild
|
|
|
|
|
'';
|
|
|
|
|
|
2023-04-26 11:02:00 +00:00
|
|
|
|
installPhase = fFetchAttrs.installPhase or (''
|
2017-11-10 17:06:26 +00:00
|
|
|
|
runHook preInstall
|
|
|
|
|
|
2018-09-11 05:36:11 +00:00
|
|
|
|
# Remove all built in external workspaces, Bazel will recreate them when building
|
|
|
|
|
rm -rf $bazelOut/external/{bazel_tools,\@bazel_tools.marker}
|
2023-02-06 20:49:02 +00:00
|
|
|
|
${lib.optionalString removeRulesCC "rm -rf $bazelOut/external/{rules_cc,\\@rules_cc.marker}"}
|
2018-09-11 05:36:11 +00:00
|
|
|
|
rm -rf $bazelOut/external/{embedded_jdk,\@embedded_jdk.marker}
|
2023-02-06 20:49:02 +00:00
|
|
|
|
${lib.optionalString removeLocalConfigCc "rm -rf $bazelOut/external/{local_config_cc,\\@local_config_cc.marker}"}
|
|
|
|
|
${lib.optionalString removeLocal "rm -rf $bazelOut/external/{local_*,\\@local_*.marker}"}
|
2018-09-11 05:36:11 +00:00
|
|
|
|
|
2019-07-25 11:18:50 +00:00
|
|
|
|
# Clear markers
|
|
|
|
|
find $bazelOut/external -name '@*\.marker' -exec sh -c 'echo > {}' \;
|
2018-09-11 05:36:11 +00:00
|
|
|
|
|
2018-09-11 21:12:31 +00:00
|
|
|
|
# Remove all vcs files
|
|
|
|
|
rm -rf $(find $bazelOut/external -type d -name .git)
|
|
|
|
|
rm -rf $(find $bazelOut/external -type d -name .svn)
|
|
|
|
|
rm -rf $(find $bazelOut/external -type d -name .hg)
|
2017-11-10 17:06:26 +00:00
|
|
|
|
|
2019-08-19 08:21:37 +00:00
|
|
|
|
# Removing top-level symlinks along with their markers.
|
|
|
|
|
# This is needed because they sometimes point to temporary paths (?).
|
|
|
|
|
# For example, in Tensorflow-gpu build:
|
|
|
|
|
# platforms -> NIX_BUILD_TOP/tmp/install/35282f5123611afa742331368e9ae529/_embedded_binaries/platforms
|
|
|
|
|
find $bazelOut/external -maxdepth 1 -type l | while read symlink; do
|
|
|
|
|
name="$(basename "$symlink")"
|
2020-07-04 23:24:35 +00:00
|
|
|
|
rm "$symlink"
|
2021-06-06 21:18:56 +00:00
|
|
|
|
test -f "$bazelOut/external/@$name.marker" && rm "$bazelOut/external/@$name.marker" || true
|
2019-08-19 08:21:37 +00:00
|
|
|
|
done
|
|
|
|
|
|
2018-09-11 05:36:11 +00:00
|
|
|
|
# Patching symlinks to remove build directory reference
|
|
|
|
|
find $bazelOut/external -type l | while read symlink; do
|
2019-06-20 16:35:16 +00:00
|
|
|
|
new_target="$(readlink "$symlink" | sed "s,$NIX_BUILD_TOP,NIX_BUILD_TOP,")"
|
|
|
|
|
rm "$symlink"
|
|
|
|
|
ln -sf "$new_target" "$symlink"
|
2023-04-06 00:23:32 +00:00
|
|
|
|
'' + lib.optionalString stdenv.isDarwin ''
|
|
|
|
|
# on linux symlink permissions cannot be modified, so we modify those on darwin to match the linux ones
|
|
|
|
|
${chmodder}/bin/chmodder "$symlink"
|
|
|
|
|
'' + ''
|
2018-09-11 05:36:11 +00:00
|
|
|
|
done
|
|
|
|
|
|
2020-05-09 01:48:30 +00:00
|
|
|
|
echo '${bazel.name}' > $bazelOut/external/.nix-bazel-version
|
2017-11-10 17:06:26 +00:00
|
|
|
|
|
2020-05-09 01:48:30 +00:00
|
|
|
|
(cd $bazelOut/ && tar czf $out --sort=name --mtime='@1' --owner=0 --group=0 --numeric-owner external/)
|
2020-02-19 13:50:12 +00:00
|
|
|
|
|
2017-11-10 17:06:26 +00:00
|
|
|
|
runHook postInstall
|
2023-04-26 11:02:00 +00:00
|
|
|
|
'');
|
2017-11-10 17:06:26 +00:00
|
|
|
|
|
|
|
|
|
dontFixup = true;
|
2019-07-13 19:40:22 +00:00
|
|
|
|
allowedRequisites = [];
|
|
|
|
|
|
2017-11-10 17:06:26 +00:00
|
|
|
|
outputHashAlgo = "sha256";
|
|
|
|
|
outputHash = fetchAttrs.sha256;
|
|
|
|
|
});
|
|
|
|
|
|
2019-07-13 19:40:22 +00:00
|
|
|
|
nativeBuildInputs = fBuildAttrs.nativeBuildInputs or [] ++ [ (bazel.override { enableNixHacks = true; }) ];
|
2017-11-10 17:06:26 +00:00
|
|
|
|
|
|
|
|
|
preHook = fBuildAttrs.preHook or "" + ''
|
|
|
|
|
export bazelOut="$NIX_BUILD_TOP/output"
|
2018-07-09 22:38:45 +00:00
|
|
|
|
export bazelUserRoot="$NIX_BUILD_TOP/tmp"
|
2017-11-10 17:06:26 +00:00
|
|
|
|
export HOME="$NIX_BUILD_TOP"
|
|
|
|
|
'';
|
|
|
|
|
|
|
|
|
|
preConfigure = ''
|
2019-06-26 13:23:50 +00:00
|
|
|
|
mkdir -p "$bazelOut"
|
2020-02-19 13:50:12 +00:00
|
|
|
|
|
2020-05-09 01:48:30 +00:00
|
|
|
|
(cd $bazelOut && tar xfz $deps)
|
|
|
|
|
|
|
|
|
|
test "${bazel.name}" = "$(<$bazelOut/external/.nix-bazel-version)" || {
|
2020-02-19 13:50:12 +00:00
|
|
|
|
echo "fixed output derivation was built for a different bazel version" >&2
|
2020-05-09 01:48:30 +00:00
|
|
|
|
echo " got: $(<$bazelOut/external/.nix-bazel-version)" >&2
|
2020-02-19 13:50:12 +00:00
|
|
|
|
echo "expected: ${bazel.name}" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-10 17:06:26 +00:00
|
|
|
|
chmod -R +w $bazelOut
|
|
|
|
|
find $bazelOut -type l | while read symlink; do
|
2021-01-08 01:34:58 +00:00
|
|
|
|
if [[ $(readlink "$symlink") == *NIX_BUILD_TOP* ]]; then
|
|
|
|
|
ln -sf $(readlink "$symlink" | sed "s,NIX_BUILD_TOP,$NIX_BUILD_TOP,") "$symlink"
|
|
|
|
|
fi
|
2017-11-10 17:06:26 +00:00
|
|
|
|
done
|
|
|
|
|
'' + fBuildAttrs.preConfigure or "";
|
|
|
|
|
|
|
|
|
|
buildPhase = fBuildAttrs.buildPhase or ''
|
|
|
|
|
runHook preBuild
|
|
|
|
|
|
2019-07-25 09:43:45 +00:00
|
|
|
|
# Bazel sandboxes the execution of the tools it invokes, so even though we are
|
|
|
|
|
# calling the correct nix wrappers, the values of the environment variables
|
|
|
|
|
# the wrappers are expecting will not be set. So instead of relying on the
|
|
|
|
|
# wrappers picking them up, pass them in explicitly via `--copt`, `--linkopt`
|
|
|
|
|
# and related flags.
|
2022-10-03 10:43:33 +00:00
|
|
|
|
|
2019-07-25 09:43:45 +00:00
|
|
|
|
copts=()
|
|
|
|
|
host_copts=()
|
|
|
|
|
linkopts=()
|
|
|
|
|
host_linkopts=()
|
2020-08-28 20:10:59 +00:00
|
|
|
|
if [ -z "''${dontAddBazelOpts:-}" ]; then
|
|
|
|
|
for flag in $NIX_CFLAGS_COMPILE; do
|
|
|
|
|
copts+=( "--copt=$flag" )
|
|
|
|
|
host_copts+=( "--host_copt=$flag" )
|
|
|
|
|
done
|
|
|
|
|
for flag in $NIX_CXXSTDLIB_COMPILE; do
|
|
|
|
|
copts+=( "--copt=$flag" )
|
|
|
|
|
host_copts+=( "--host_copt=$flag" )
|
|
|
|
|
done
|
|
|
|
|
for flag in $NIX_LDFLAGS; do
|
|
|
|
|
linkopts+=( "--linkopt=-Wl,$flag" )
|
|
|
|
|
host_linkopts+=( "--host_linkopt=-Wl,$flag" )
|
|
|
|
|
done
|
|
|
|
|
fi
|
2019-07-25 09:43:45 +00:00
|
|
|
|
|
2022-10-03 10:43:33 +00:00
|
|
|
|
${
|
|
|
|
|
bazelCmd {
|
|
|
|
|
cmd = "test";
|
|
|
|
|
additionalFlags =
|
2023-04-21 11:49:30 +00:00
|
|
|
|
["--test_output=errors"] ++ fBuildAttrs.bazelTestFlags ++ ["--jobs" "$NIX_BUILD_CORES"];
|
2023-04-05 03:46:39 +00:00
|
|
|
|
targets = fBuildAttrs.bazelTestTargets;
|
2022-10-03 10:43:33 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
${
|
|
|
|
|
bazelCmd {
|
|
|
|
|
cmd = "build";
|
2023-04-21 11:49:30 +00:00
|
|
|
|
additionalFlags = fBuildAttrs.bazelBuildFlags ++ ["--jobs" "$NIX_BUILD_CORES"];
|
2023-04-05 03:46:39 +00:00
|
|
|
|
targets = fBuildAttrs.bazelTargets;
|
2022-10-03 10:43:33 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-06-14 08:18:15 +00:00
|
|
|
|
${
|
|
|
|
|
bazelCmd {
|
|
|
|
|
cmd = "run";
|
|
|
|
|
additionalFlags = fBuildAttrs.bazelRunFlags ++ [ "--jobs" "$NIX_BUILD_CORES" ];
|
|
|
|
|
# Bazel run only accepts a single target, but `bazelCmd` expects `targets` to be a list.
|
|
|
|
|
targets = lib.optionals (fBuildAttrs.bazelRunTarget != null) [ fBuildAttrs.bazelRunTarget ];
|
|
|
|
|
targetRunFlags = fBuildAttrs.runTargetFlags;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-11-10 17:06:26 +00:00
|
|
|
|
runHook postBuild
|
|
|
|
|
'';
|
|
|
|
|
})
|
2022-10-03 10:43:33 +00:00
|
|
|
|
|
|
|
|
|
# [USER and BAZEL_USE_CPP_ONLY_TOOLCHAIN variables]:
|
|
|
|
|
# Bazel computes the default value of output_user_root before parsing the
|
|
|
|
|
# flag. The computation of the default value involves getting the $USER
|
|
|
|
|
# from the environment. Code here :
|
|
|
|
|
# https://github.com/bazelbuild/bazel/blob/9323c57607d37f9c949b60e293b573584906da46/src/main/cpp/startup_options.cc#L123-L124
|
|
|
|
|
#
|
|
|
|
|
# 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.
|