2019-11-18 13:49:27 +00:00
|
|
|
{ src
|
|
|
|
, preBuild
|
2019-09-04 10:14:36 +00:00
|
|
|
#| What command to run during the build phase
|
|
|
|
, cargoBuild
|
2020-02-06 17:31:34 +00:00
|
|
|
, cargoBuildOptions
|
2019-06-28 09:43:47 +00:00
|
|
|
, #| What command to run during the test phase
|
2019-09-09 09:21:51 +00:00
|
|
|
cargoTestCommands
|
2020-02-06 17:31:34 +00:00
|
|
|
, cargoTestOptions
|
2019-11-18 15:16:46 +00:00
|
|
|
, copyTarget
|
2019-11-13 14:18:08 +00:00
|
|
|
#| Whether or not to compress the target when copying it
|
|
|
|
, compressTarget
|
2019-09-04 15:34:14 +00:00
|
|
|
#| Whether or not to copy binaries to $out/bin
|
2019-11-18 15:16:46 +00:00
|
|
|
, copyBins
|
2020-02-10 11:51:32 +00:00
|
|
|
, copyBinsFilter
|
2019-11-18 15:16:46 +00:00
|
|
|
, doCheck
|
|
|
|
, doDoc
|
|
|
|
, doDocFail
|
|
|
|
, copyDocsToSeparateOutput
|
2019-08-23 13:09:38 +00:00
|
|
|
#| Whether to remove references to source code from the generated cargo docs
|
|
|
|
# to reduce Nix closure size. By default cargo doc includes snippets like the
|
|
|
|
# following in the generated highlighted source code in files like: src/rand/lib.rs.html:
|
|
|
|
#
|
|
|
|
# <meta name="description" content="Source to the Rust file `/nix/store/mdwpqciww926xayfasl85i4wvvpbgb9a-crates-io/rand-0.7.0/src/lib.rs`.">
|
|
|
|
#
|
|
|
|
# The reference to /nix/store/...-crates-io/... causes a run-time dependency
|
|
|
|
# to the complete source code blowing up the Nix closure size for no good
|
|
|
|
# reason. If this argument is set to true (which is the default) the latter
|
|
|
|
# will be replaced by:
|
|
|
|
#
|
|
|
|
# <meta name="description" content="Source to the Rust file removed to reduce Nix closure size.">
|
|
|
|
#
|
|
|
|
# Which drops the run-time dependency on the crates-io source thereby
|
|
|
|
# significantly reducing the Nix closure size.
|
2019-11-18 15:16:46 +00:00
|
|
|
, removeReferencesToSrcFromDocs
|
2019-12-13 15:37:19 +00:00
|
|
|
, gitDependencies
|
2019-10-30 14:45:53 +00:00
|
|
|
, pname
|
2019-07-11 09:39:40 +00:00
|
|
|
, version
|
2019-07-02 10:50:32 +00:00
|
|
|
, rustc
|
|
|
|
, cargo
|
2019-11-18 15:16:46 +00:00
|
|
|
, override
|
|
|
|
, buildInputs
|
|
|
|
, builtDependencies
|
|
|
|
, release
|
2019-12-13 14:12:08 +00:00
|
|
|
, cargoOptions
|
2019-06-25 15:36:22 +00:00
|
|
|
, stdenv
|
|
|
|
, lib
|
2019-06-27 10:43:01 +00:00
|
|
|
, rsync
|
2019-06-25 15:36:22 +00:00
|
|
|
, jq
|
|
|
|
, darwin
|
|
|
|
, writeText
|
|
|
|
, symlinkJoin
|
|
|
|
, runCommand
|
2019-06-27 15:49:59 +00:00
|
|
|
, remarshal
|
2019-07-04 14:34:33 +00:00
|
|
|
, crateDependencies
|
2019-11-13 14:18:08 +00:00
|
|
|
, zstd
|
2019-11-21 09:34:16 +00:00
|
|
|
, fetchurl
|
2019-06-25 15:36:22 +00:00
|
|
|
}:
|
|
|
|
|
2019-11-18 15:16:46 +00:00
|
|
|
let
|
2019-11-19 19:28:02 +00:00
|
|
|
builtinz =
|
2019-11-19 19:30:49 +00:00
|
|
|
builtins // import ./builtins
|
|
|
|
{ inherit lib writeText remarshal runCommand; };
|
2019-11-19 19:28:02 +00:00
|
|
|
|
2019-12-17 16:03:10 +00:00
|
|
|
# All the git dependencies, as a list
|
|
|
|
gitDependenciesList =
|
|
|
|
lib.concatLists (lib.mapAttrsToList (_: ds: ds) gitDependencies);
|
2019-12-17 15:55:52 +00:00
|
|
|
|
2019-12-17 16:20:47 +00:00
|
|
|
# This unpacks all git dependencies:
|
|
|
|
# $out/rand
|
|
|
|
# $out/rand/Cargo.toml
|
|
|
|
# $out/rand_core
|
|
|
|
# ...
|
|
|
|
# It does so by discovering all the `Cargo.toml`s and creating a directory in
|
|
|
|
# $out for each one.
|
|
|
|
# NOTE:
|
|
|
|
# Only non-virtual manifests are taken into account. That is, only cargo
|
|
|
|
# tomls that have a [package] sections with a `name = ...`. The
|
|
|
|
# implementation is a bit tricky and basically akin to parsing TOML with
|
|
|
|
# bash. The reason is that there is no lightweight jq-equivalent available
|
|
|
|
# in nixpkgs (rq fails to build).
|
|
|
|
# We discover the name (in any) in three steps:
|
|
|
|
# * grab anything that comes after `[package]`
|
|
|
|
# * grab the first line that contains `name = ...`
|
|
|
|
# * grab whatever is surrounded with `"`s.
|
|
|
|
# The last step is very, very slow.
|
2019-12-17 15:55:52 +00:00
|
|
|
unpackedGitDependencies = runCommand "git-deps"
|
|
|
|
{ nativeBuildInputs = [ jq ]; }
|
|
|
|
''
|
2020-02-07 17:48:01 +00:00
|
|
|
log() {
|
|
|
|
>&2 echo "[naersk]" "$@"
|
|
|
|
}
|
|
|
|
|
2019-12-17 15:55:52 +00:00
|
|
|
mkdir -p $out
|
|
|
|
|
|
|
|
while read -r dep; do
|
|
|
|
checkout=$(echo "$dep" | jq -cMr '.checkout')
|
|
|
|
url=$(echo "$dep" | jq -cMr '.url')
|
|
|
|
tomls=$(find $checkout -name Cargo.toml)
|
2020-01-10 10:32:09 +00:00
|
|
|
rev=$(echo "$dep" | jq -cMr '.rev')
|
2019-12-17 15:55:52 +00:00
|
|
|
while read -r toml; do
|
|
|
|
name=$(cat $toml \
|
|
|
|
| sed -n -e '/\[package\]/,$p' \
|
|
|
|
| grep -m 1 "^name\W" \
|
|
|
|
| grep -oP '(?<=").+(?=")' \
|
|
|
|
|| true)
|
|
|
|
if [ -n "$name" ]; then
|
2020-01-10 10:32:09 +00:00
|
|
|
key="$name-$rev"
|
2020-02-07 17:48:01 +00:00
|
|
|
log "$url Found crate '$name' ($rev)"
|
2020-01-10 10:32:09 +00:00
|
|
|
if [ -d "$out/$key" ]; then
|
2020-02-07 17:48:01 +00:00
|
|
|
log "Crate was already unpacked at $out/$key"
|
2020-01-10 10:32:09 +00:00
|
|
|
else
|
|
|
|
cp -r $(dirname $toml) $out/$key
|
|
|
|
chmod +w "$out/$key"
|
|
|
|
echo '{"package":null,"files":{}}' > $out/$key/.cargo-checksum.json
|
2020-02-07 17:48:01 +00:00
|
|
|
log "Crate unpacked at $out/$key"
|
2020-01-10 10:32:09 +00:00
|
|
|
fi
|
2019-12-17 15:55:52 +00:00
|
|
|
fi
|
|
|
|
done <<< "$tomls"
|
2019-12-17 16:03:10 +00:00
|
|
|
done < <(cat ${
|
2020-02-07 17:48:01 +00:00
|
|
|
builtins.toFile "git-deps-json" (builtins.toJSON gitDependenciesList)
|
|
|
|
} | jq -cMr '.[]')
|
2019-12-17 15:55:52 +00:00
|
|
|
'';
|
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
drv = stdenv.mkDerivation {
|
|
|
|
name = "${pname}-${version}";
|
|
|
|
inherit
|
|
|
|
src
|
|
|
|
doCheck
|
|
|
|
version
|
|
|
|
preBuild
|
|
|
|
;
|
|
|
|
|
2019-12-17 16:20:47 +00:00
|
|
|
# The cargo config with source replacement. Replaces both crates.io crates
|
|
|
|
# and git dependencies.
|
2019-11-19 20:10:53 +00:00
|
|
|
cargoconfig = builtinz.toTOML {
|
|
|
|
source = {
|
|
|
|
crates-io = { replace-with = "nix-sources"; };
|
|
|
|
nix-sources = {
|
|
|
|
directory = symlinkJoin {
|
|
|
|
name = "crates-io";
|
|
|
|
paths = map (v: unpackCrate v.name v.version v.sha256)
|
2020-02-07 17:48:01 +00:00
|
|
|
crateDependencies ++ [ unpackedGitDependencies ];
|
2019-11-19 20:10:53 +00:00
|
|
|
};
|
2019-11-18 15:16:46 +00:00
|
|
|
};
|
2020-02-07 17:48:01 +00:00
|
|
|
} // lib.listToAttrs (
|
|
|
|
map
|
|
|
|
(
|
|
|
|
e:
|
|
|
|
{
|
|
|
|
name = "${e.url}?rev=${e.rev}";
|
|
|
|
value =
|
|
|
|
{
|
|
|
|
git = e.url;
|
|
|
|
rev = e.rev;
|
|
|
|
replace-with = "nix-sources";
|
|
|
|
};
|
|
|
|
}
|
|
|
|
)
|
2019-12-17 16:03:10 +00:00
|
|
|
gitDependenciesList
|
2020-02-07 17:48:01 +00:00
|
|
|
);
|
2019-11-19 20:10:53 +00:00
|
|
|
};
|
2019-10-30 14:45:53 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
outputs = [ "out" ] ++ lib.optional (doDoc && copyDocsToSeparateOutput) "doc";
|
|
|
|
preInstallPhases = lib.optional doDoc [ "docPhase" ];
|
2019-06-27 10:43:01 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
# Otherwise specifying CMake as a dep breaks the build
|
|
|
|
dontUseCmakeConfigure = true;
|
2019-11-13 14:18:08 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
nativeBuildInputs = [
|
|
|
|
cargo
|
|
|
|
# needed at various steps in the build
|
|
|
|
jq
|
|
|
|
rsync
|
|
|
|
];
|
2019-06-25 15:36:22 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
buildInputs = stdenv.lib.optionals stdenv.isDarwin [
|
|
|
|
darwin.Security
|
|
|
|
darwin.apple_sdk.frameworks.CoreServices
|
|
|
|
darwin.cf-private
|
|
|
|
] ++ buildInputs;
|
2019-06-25 15:36:22 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
inherit builtDependencies;
|
2019-06-25 15:36:22 +00:00
|
|
|
|
2020-02-06 17:31:34 +00:00
|
|
|
# some environment variables
|
2019-11-19 20:10:53 +00:00
|
|
|
RUSTC = "${rustc}/bin/rustc";
|
2020-02-06 17:31:34 +00:00
|
|
|
cargo_release = lib.optionalString release "--release";
|
|
|
|
cargo_options = cargoOptions;
|
|
|
|
cargo_build_options = cargoBuildOptions;
|
|
|
|
cargo_test_options = cargoTestOptions;
|
2020-02-10 11:51:32 +00:00
|
|
|
cargo_bins_jq_filter = copyBinsFilter;
|
2019-06-25 15:36:22 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
configurePhase = ''
|
|
|
|
runHook preConfigure
|
2019-06-25 15:36:22 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
logRun() {
|
2020-02-07 17:48:01 +00:00
|
|
|
>&2 echo "$@"
|
2019-11-19 20:10:53 +00:00
|
|
|
eval "$@"
|
|
|
|
}
|
2019-06-25 15:36:22 +00:00
|
|
|
|
2020-02-07 17:48:01 +00:00
|
|
|
log() {
|
|
|
|
>&2 echo "[naersk]" "$@"
|
|
|
|
}
|
|
|
|
|
|
|
|
cargo_build_output_json=$(mktemp)
|
|
|
|
|
|
|
|
log "cargo_release: $cargo_release"
|
|
|
|
log "cargo_options: $cargo_options"
|
|
|
|
log "cargo_build_options: $cargo_build_options"
|
|
|
|
log "cargo_test_options: $cargo_test_options"
|
2020-02-10 11:51:32 +00:00
|
|
|
log "cargo_bins_jq_filter: $cargo_bins_jq_filter"
|
2020-02-07 17:48:01 +00:00
|
|
|
log "cargo_build_output_json (created): $cargo_build_output_json"
|
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
mkdir -p target
|
2019-06-25 15:36:22 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
for dep in $builtDependencies; do
|
2020-02-07 17:48:01 +00:00
|
|
|
log "pre-installing dep $dep"
|
2019-11-19 20:10:53 +00:00
|
|
|
if [ -d "$dep/target" ]; then
|
|
|
|
rsync -rl \
|
|
|
|
--no-perms \
|
|
|
|
--no-owner \
|
|
|
|
--no-group \
|
|
|
|
--chmod=+w \
|
|
|
|
--executability $dep/target/ target
|
|
|
|
fi
|
|
|
|
if [ -f "$dep/target.tar.zst" ]; then
|
|
|
|
${zstd}/bin/zstd -d "$dep/target.tar.zst" --stdout | tar -x
|
|
|
|
fi
|
2019-06-25 15:36:22 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
if [ -d "$dep/target" ]; then
|
|
|
|
chmod +w -R target
|
|
|
|
fi
|
|
|
|
done
|
2019-06-25 15:36:22 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
export CARGO_HOME=''${CARGO_HOME:-$PWD/.cargo-home}
|
|
|
|
mkdir -p $CARGO_HOME
|
2019-06-25 15:36:22 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
echo "$cargoconfig" > $CARGO_HOME/config
|
2019-07-16 09:06:29 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
# TODO: figure out why "1" works whereas "0" doesn't
|
|
|
|
find . -type f -exec touch --date=@1 {} +
|
2019-07-16 09:06:29 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
runHook postConfigure
|
|
|
|
'';
|
2019-07-16 09:06:29 +00:00
|
|
|
|
2020-02-07 17:48:01 +00:00
|
|
|
buildPhase =
|
2019-08-23 13:09:38 +00:00
|
|
|
|
2020-02-07 17:48:01 +00:00
|
|
|
''
|
|
|
|
runHook preBuild
|
2019-07-16 09:06:29 +00:00
|
|
|
|
2020-02-07 17:48:01 +00:00
|
|
|
cargo_ec=0
|
|
|
|
logRun ${cargoBuild} || cargo_ec="$?"
|
|
|
|
|
|
|
|
if [ "$cargo_ec" -ne "0" ]
|
|
|
|
then
|
2020-02-10 19:06:21 +00:00
|
|
|
cat $cargo_build_output_json | jq -cMr 'select(.message.rendered != null) | .message.rendered'
|
2020-02-07 17:48:01 +00:00
|
|
|
log "cargo returned with exit code $cargo_ec, exiting"
|
|
|
|
exit "$cargo_ec"
|
|
|
|
fi
|
|
|
|
|
|
|
|
runHook postBuild
|
|
|
|
'';
|
2019-11-18 15:16:46 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
checkPhase = ''
|
|
|
|
runHook preCheck
|
2019-11-18 15:16:46 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
${lib.concatMapStringsSep "\n" (cmd: "logRun ${cmd}") cargoTestCommands}
|
2019-11-18 15:16:46 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
runHook postCheck
|
|
|
|
'';
|
2019-11-18 15:16:46 +00:00
|
|
|
|
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
docPhase = lib.optionalString doDoc ''
|
|
|
|
runHook preDoc
|
2019-11-18 15:16:46 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
logRun cargo doc --offline "''${cargo_release[*]}" || ${if doDocFail then "false" else "true" }
|
2019-11-18 15:16:46 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
${lib.optionalString removeReferencesToSrcFromDocs ''
|
|
|
|
# Remove references to the source derivation to reduce closure size
|
|
|
|
match='<meta name="description" content="Source to the Rust file `${builtins.storeDir}[^`]*`.">'
|
|
|
|
replacement='<meta name="description" content="Source to the Rust file removed to reduce Nix closure size.">'
|
|
|
|
find target/doc -name "*\.rs\.html" -exec sed -i "s|$match|$replacement|" {} +
|
|
|
|
''}
|
|
|
|
|
|
|
|
runHook postDoc
|
|
|
|
'';
|
|
|
|
|
|
|
|
installPhase =
|
|
|
|
''
|
|
|
|
runHook preInstall
|
|
|
|
|
|
|
|
${lib.optionalString copyBins ''
|
2020-02-07 17:48:01 +00:00
|
|
|
mkdir -p $out/bin
|
|
|
|
if [ -f "$cargo_build_output_json" ]
|
|
|
|
then
|
|
|
|
log "Using file $cargo_build_output_json to retrieve build products"
|
|
|
|
while IFS= read -r to_copy; do
|
|
|
|
bin_path=$(jq -cMr '.executable' <<<"$to_copy")
|
|
|
|
bin_name=$(jq -cMr '.target.name' <<<"$to_copy")
|
|
|
|
log "found executable $bin_name -> $out/bin/$bin_name"
|
|
|
|
cp "$bin_path" "$out/bin/$bin_name"
|
2020-02-10 11:51:32 +00:00
|
|
|
done < <(jq -cMr "$cargo_bins_jq_filter" <"$cargo_build_output_json")
|
2020-02-07 17:48:01 +00:00
|
|
|
else
|
|
|
|
log "$cargo_build_output_json: file wasn't written, using less reliable copying method"
|
2020-01-10 19:54:52 +00:00
|
|
|
find out -type f -executable \
|
|
|
|
-not -name '*.so' -a -not -name '*.dylib' \
|
|
|
|
-exec cp {} $out/bin \;
|
2019-11-19 20:10:53 +00:00
|
|
|
fi
|
|
|
|
''}
|
2019-11-18 15:16:46 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
${lib.optionalString copyTarget ''
|
|
|
|
mkdir -p $out
|
|
|
|
${if compressTarget then
|
|
|
|
''
|
|
|
|
tar -c target | ${zstd}/bin/zstd -o $out/target.tar.zst
|
|
|
|
'' else
|
|
|
|
''
|
|
|
|
cp -r target $out
|
2019-11-19 19:30:49 +00:00
|
|
|
''}
|
2019-11-19 20:10:53 +00:00
|
|
|
''}
|
2019-11-18 15:16:46 +00:00
|
|
|
|
2019-11-19 20:10:53 +00:00
|
|
|
${lib.optionalString (doDoc && copyDocsToSeparateOutput) ''
|
|
|
|
cp -r target/doc $doc
|
|
|
|
''}
|
|
|
|
|
|
|
|
runHook postInstall
|
|
|
|
'';
|
|
|
|
passthru = {
|
|
|
|
# Handy for debugging
|
|
|
|
inherit builtDependencies;
|
|
|
|
};
|
|
|
|
};
|
2019-11-18 15:16:46 +00:00
|
|
|
|
|
|
|
# XXX: the actual crate format is not documented but in practice is a
|
|
|
|
# gzipped tar; we simply unpack it and introduce a ".cargo-checksum.json"
|
|
|
|
# file that cargo itself uses to double check the sha256
|
|
|
|
unpackCrate = name: version: sha256:
|
2019-11-19 19:28:02 +00:00
|
|
|
let
|
2019-11-21 09:34:16 +00:00
|
|
|
crate = fetchurl {
|
2019-11-19 20:10:53 +00:00
|
|
|
url = "https://crates.io/api/v1/crates/${name}/${version}/download";
|
|
|
|
inherit sha256;
|
2020-02-06 17:31:34 +00:00
|
|
|
name = "download-${name}-${version}";
|
2019-11-19 20:10:53 +00:00
|
|
|
};
|
2019-11-19 19:28:02 +00:00
|
|
|
in
|
2019-11-19 19:30:49 +00:00
|
|
|
runCommand "unpack-${name}-${version}" {}
|
|
|
|
''
|
|
|
|
mkdir -p $out
|
|
|
|
tar -xzf ${crate} -C $out
|
|
|
|
echo '{"package":"${sha256}","files":{}}' > $out/${name}-${version}/.cargo-checksum.json
|
|
|
|
'';
|
2019-11-18 15:16:46 +00:00
|
|
|
in
|
|
|
|
drv.overrideAttrs override
|