buildRustCrate: use less bash for the build script

We can get rid of a bunch of workarounds that were in the build script
before by just passing on the `crateBin` attribute.

Before we converted the list of attributes to a string only to convert
it back in bash during the build phase. We can do the entire looping
through builds in Nix and thus need no conversion and parsing of
attributes over and over again.

The big part that still remains bash is the heuristic that cargo
introduced and that we can't do at eval time.
wip/yesman
Andreas Rammhold 5 years ago
parent 5ad83267ed
commit 6ad22f5b4d
No known key found for this signature in database
GPG Key ID: E432E410B5E48C86
  1. 28
      pkgs/build-support/rust/build-rust-crate/build-crate.nix
  2. 22
      pkgs/build-support/rust/build-rust-crate/default.nix

@ -6,7 +6,6 @@
extraRustcOpts, verbose, colors }:
let
deps = mkRustcDepArgs dependencies crateRenames;
rustcOpts =
lib.foldl' (opts: opt: opts + " " + opt)
@ -54,7 +53,7 @@
EXTRA_LIB=""
CRATE_NAME=$(echo ${libName} | tr '-' '_')
CRATE_NAME='${lib.replaceStrings ["-"] ["_"] libName}'
if [[ -e target/link_ ]]; then
EXTRA_BUILD="$(cat target/link_) $EXTRA_BUILD"
@ -95,20 +94,16 @@
tr '\n' ' ' < target/link > target/link_
LINK=$(cat target/link_)
fi
${lib.optionalString (crateBin != "") ''
printf "%s\n" "${crateBin}" | head -n1 | tr -s ',' '\n' | while read -r BIN_NAME BIN_PATH; do
mkdir -p target/bin
# filter empty entries / empty "lines"
if [[ -z "$BIN_NAME" ]]; then
continue
fi
if [[ -z "$BIN_PATH" ]]; then
${lib.optionalString (lib.length crateBin > 0) (lib.concatMapStringsSep "\n" (bin: ''
mkdir -p target/bin
BIN_NAME='${bin.name or crateName}'
${if !bin ? path then ''
# heuristic to "guess" the correct source file as found in cargo:
# https://github.com/rust-lang/cargo/blob/90fc9f620190d5fa3c80b0c8c65a1e1361e6b8ae/src/cargo/util/toml/targets.rs#L308-L325
# the first two cases are the "new" default IIRC
BIN_NAME_=$(echo $BIN_NAME | tr '-' '_')
BIN_NAME_='${lib.replaceStrings ["-"] ["_"] bin.name}'
FILES=( "src/bin/$BIN_NAME.rs" "src/bin/$BIN_NAME/main.rs" "src/bin/$BIN_NAME_.rs" "src/bin/$BIN_NAME_/main.rs" "src/bin/main.rs" "src/main.rs" )
if ! [ -e "${libPath}" -o -e src/lib.rs -o -e "src/${libName}.rs" ]; then
@ -130,12 +125,15 @@
echo "failed to find file for binary target: $BIN_NAME" >&2
exit 1
fi
fi
'' else ''
BIN_PATH='${bin.path}'
''}
build_bin "$BIN_NAME" "$BIN_PATH"
done
''}
'') crateBin)}
${lib.optionalString (crateBin == "" && !hasCrateBin) ''
# If crateBin is empty and hasCrateBin is not set then we must try to
# detect some kind of bin target based on some files that might exist.
${lib.optionalString (lib.length crateBin == 0 && !hasCrateBin) ''
if [[ -e src/main.rs ]]; then
mkdir -p target/bin
build_bin ${crateName} src/main.rs

@ -59,6 +59,15 @@ let crate = crate_ // (lib.attrByPath [ crate_.crateName ] (attr: {}) crateOverr
extraDerivationAttrs = lib.filterAttrs (n: v: ! lib.elem n processedAttrs) crate;
buildInputs_ = buildInputs;
extraRustcOpts_ = extraRustcOpts;
# take a list of crates that we depend on and override them to fit our overrides, rustc, release, …
makeDependencies = map (dep: lib.getLib (dep.override { inherit release verbose crateOverrides; }));
# crate2nix has a hack for the old bash based build script that did split
# entries at `,`. No we have to work around that hack.
# https://github.com/kolloch/crate2nix/blame/5b19c1b14e1b0e5522c3e44e300d0b332dc939e7/crate2nix/templates/build.nix.tera#L89
crateBin = lib.filter (bin: !(bin ? name && bin.name == ",")) (crate.crateBin or []);
hasCrateBin = crate ? crateBin;
in
stdenv.mkDerivation (rec {
@ -102,17 +111,6 @@ stdenv.mkDerivation (rec {
(crateName + "-" + crateVersion + "___" + toString crateFeatures + "___" + depsMetadata);
in lib.substring 0 10 hashedMetadata;
crateBin = if crate ? crateBin then
lib.foldl' (bins: bin: let
name = if bin ? name then bin.name else crateName;
path = if bin ? path then bin.path else "";
in
bins + (if bin == "" then "" else ",") + "${name} ${path}"
) "" crate.crateBin
else "";
hasCrateBin = crate ? crateBin;
build = crate.build or "";
workspace_member = crate.workspace_member or ".";
crateVersion = crate.version;
@ -140,7 +138,7 @@ stdenv.mkDerivation (rec {
buildPhase = buildCrate {
inherit crateName dependencies
crateFeatures crateRenames libName release libPath crateType
metadata crateBin hasCrateBin verbose colors
metadata hasCrateBin crateBin verbose colors
extraRustcOpts;
};
installPhase = installCrate crateName metadata;

Loading…
Cancel
Save