Add support for building cargo'ed Rust programs
This commit is contained in:
committed by
Ricardo M. Correia
parent
c55c7e1c1e
commit
7d67efa3f2
@@ -0,0 +1,52 @@
|
||||
{ stdenv, cacert, git, rustc, cargo, rustRegistry }:
|
||||
{ name, src, depsSha256, buildInputs ? [], ... } @ args:
|
||||
|
||||
let
|
||||
fetchDeps = import ./fetchcargo.nix {
|
||||
inherit stdenv cacert git rustc cargo rustRegistry;
|
||||
};
|
||||
|
||||
cargoDeps = fetchDeps {
|
||||
inherit name src;
|
||||
sha256 = depsSha256;
|
||||
};
|
||||
|
||||
in stdenv.mkDerivation (args // {
|
||||
inherit cargoDeps rustRegistry;
|
||||
|
||||
buildInputs = [ git cargo rustc ] ++ buildInputs;
|
||||
|
||||
configurePhase = args.configurePhase or "true";
|
||||
|
||||
postUnpack = ''
|
||||
echo "Using rust registry from $rustRegistry"
|
||||
(
|
||||
cd $sourceRoot
|
||||
ln -s $rustRegistry ./cargo-rust-registry
|
||||
cargo clean
|
||||
cargo fetch
|
||||
)
|
||||
'' + (args.postUnpack or "");
|
||||
|
||||
# TODO: Probably not the best way to do this, but it should work for now
|
||||
prePatch = ''
|
||||
for dir in ../deps/registry/src/*/pkg-config-*; do
|
||||
[ -d "$dir" ] || continue
|
||||
|
||||
substituteInPlace "$dir/src/lib.rs" \
|
||||
--replace '"/usr"' '"/nix/store/"'
|
||||
done
|
||||
'' + (args.prePatch or "");
|
||||
|
||||
buildPhase = args.buildPhase or ''
|
||||
echo "Running cargo build"
|
||||
cargo build --release
|
||||
'';
|
||||
|
||||
installPhase = args.installPhase or ''
|
||||
mkdir -p $out/bin
|
||||
for f in $(find target/release -maxdepth 1 -type f); do
|
||||
cp $f $out/bin
|
||||
done;
|
||||
'';
|
||||
})
|
||||
@@ -0,0 +1,17 @@
|
||||
source $stdenv/setup
|
||||
|
||||
# cargo-fetch needs to write to Cargo.lock, even to do nothing. We
|
||||
# create a fake checkout with symlinks and and editable Cargo.lock.
|
||||
mkdir copy
|
||||
cd copy
|
||||
for f in $(ls $src); do
|
||||
ln -s $src/"$f" .
|
||||
done
|
||||
rm Cargo.lock
|
||||
cp $src/Cargo.lock .
|
||||
chmod +w Cargo.lock
|
||||
|
||||
$fetcher . $out
|
||||
|
||||
cd ..
|
||||
rm -rf copy
|
||||
Executable
+119
@@ -0,0 +1,119 @@
|
||||
#! /bin/sh -eu
|
||||
|
||||
set -o pipefail
|
||||
|
||||
src=$(realpath $1)
|
||||
out=$(realpath $2)
|
||||
|
||||
echo "Fetching $src to $out"
|
||||
|
||||
mkdir $out
|
||||
|
||||
# Configure cargo to fetch from a local copy of the crates.io registry
|
||||
#
|
||||
# Unfortunately, `cargo fetch` will create an output directory named after a
|
||||
# hash of the registry index URL.
|
||||
#
|
||||
# This makes things difficult for us because we don't want our output to change
|
||||
# just because the path to the registry changed, otherwise we'd have to update
|
||||
# all deps' SHA256 hashes whenever we simply update the registry to a newer
|
||||
# commit.
|
||||
#
|
||||
# Also, since cargo doesn't seem to support relative URLs in the format
|
||||
# file://../path, we use a hack to make sure the registry index path/URL is
|
||||
# always the same: we'll create a symlink in the current working directory to
|
||||
# the real registry path, while pointing cargo to the following fixed absolute
|
||||
# path:
|
||||
#
|
||||
# file:///proc/self/cwd/symlink-name
|
||||
|
||||
ln -s $rustRegistry $src/cargo-rust-registry
|
||||
|
||||
# TODO: replace /proc/self/cwd hack with normal relative path. Probably
|
||||
# needs cargo fix.
|
||||
cat <<EOF > $out/config
|
||||
[registry]
|
||||
index = "file:///proc/self/cwd/cargo-rust-registry"
|
||||
EOF
|
||||
|
||||
export CARGO_HOME=$out
|
||||
cd $src
|
||||
cargo fetch --verbose
|
||||
|
||||
# TODO: check that Cargo.lock exists, and hasn't changed
|
||||
# TODO: this should be done by cargo itself
|
||||
|
||||
# Make it deterministic
|
||||
|
||||
# The registry index changes all the time, so it's not deterministic
|
||||
rm -rf $out/registry/index
|
||||
|
||||
# Make git DBs deterministic
|
||||
# TODO: test with git submodules
|
||||
[[ ! -d $out/git/checkouts ]] || (cd $out/git/checkouts && for name in *; do
|
||||
cd "$out/git/checkouts/$name"
|
||||
revs=""
|
||||
for branch in *; do
|
||||
cd "$branch"
|
||||
rev="$(git rev-parse HEAD)"
|
||||
revs="$revs $rev"
|
||||
cd ..
|
||||
done
|
||||
|
||||
(
|
||||
# The following code was adapted from nix-prefetch-git
|
||||
|
||||
cd "$out/git/db/$name"
|
||||
|
||||
export GIT_DIR=.
|
||||
|
||||
# Remove all remote branches
|
||||
git branch -r | while read branch; do
|
||||
git branch -rD "$branch" >&2
|
||||
done
|
||||
|
||||
# Remove tags that don't point to any HEAD
|
||||
git tag | while read tag; do
|
||||
rev="$(git rev-parse $tag)"
|
||||
if [[ $revs != *" $rev"* ]]; then
|
||||
git tag -d "$tag" >&2
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove branches that don't point to any HEAD
|
||||
branchrefs=()
|
||||
eval "$(git for-each-ref --shell --format='branchrefs+=(%(refname))' refs/heads/)"
|
||||
|
||||
for branchref in "${branchrefs[@]}"; do
|
||||
echo "Examining $branchref"
|
||||
rev="$(git rev-parse "$branchref")"
|
||||
echo "Has rev $rev"
|
||||
echo "List of revs: $revs"
|
||||
if [[ $revs != *" $rev"* ]]; then
|
||||
echo "Deleting $branchref"
|
||||
git update-ref -d "$branchref" >&2
|
||||
fi
|
||||
done
|
||||
|
||||
echo "$revs" | while read rev; do
|
||||
echo "git branch b_$rev $rev"
|
||||
git branch b_$rev $rev
|
||||
done
|
||||
|
||||
# Remove files that have timestamps or otherwise have non-deterministic
|
||||
# properties.
|
||||
rm -rf logs/ hooks/ index FETCH_HEAD ORIG_HEAD refs/remotes/origin/HEAD config
|
||||
|
||||
# Do a full repack. Must run single-threaded, or else we lose determinism.
|
||||
git config pack.threads 1
|
||||
git repack -A -d -f
|
||||
rm -f config
|
||||
|
||||
# Garbage collect unreferenced objects.
|
||||
git gc --prune=all
|
||||
)
|
||||
done)
|
||||
|
||||
# Remove unneeded outputs
|
||||
[[ ! -d $out/registry/src ]] || rm -rf $out/registry/src
|
||||
[[ ! -d $out/git/checkouts ]] || rm -rf $out/git/checkouts
|
||||
@@ -0,0 +1,19 @@
|
||||
{ stdenv, cacert, git, rustc, cargo, rustRegistry }:
|
||||
{ name ? "cargo-deps", src, sha256 }:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "${name}-fetch";
|
||||
buildInputs = [ rustc cargo git ];
|
||||
builder = ./fetch-builder.sh;
|
||||
fetcher = ./fetch-cargo-deps;
|
||||
inherit src rustRegistry;
|
||||
|
||||
outputHashAlgo = "sha256";
|
||||
outputHashMode = "recursive";
|
||||
outputHash = sha256;
|
||||
|
||||
SSL_CERT_FILE = "${cacert}/etc/ca-bundle.crt";
|
||||
|
||||
impureEnvVars = [ "http_proxy" "https_proxy" "ftp_proxy" "all_proxy" "no_proxy" ];
|
||||
preferLocalBuild = true;
|
||||
}
|
||||
Reference in New Issue
Block a user