diff options
author | Georges Dubus <georges.dubus@numergy.com> | 2014-10-10 16:59:37 +0200 |
---|---|---|
committer | Ricardo M. Correia <rcorreia@wizy.org> | 2015-04-21 19:46:29 +0200 |
commit | 7d67efa3f23f7d5c494c90b79a63756a3917be6e (patch) | |
tree | fc8e6121cc18c9d26bba5107a903a8a499501e2a /pkgs/build-support/rust | |
parent | c55c7e1c1e09dfa57e1a44d08c777f995493d2c9 (diff) | |
download | nixlib-7d67efa3f23f7d5c494c90b79a63756a3917be6e.tar nixlib-7d67efa3f23f7d5c494c90b79a63756a3917be6e.tar.gz nixlib-7d67efa3f23f7d5c494c90b79a63756a3917be6e.tar.bz2 nixlib-7d67efa3f23f7d5c494c90b79a63756a3917be6e.tar.lz nixlib-7d67efa3f23f7d5c494c90b79a63756a3917be6e.tar.xz nixlib-7d67efa3f23f7d5c494c90b79a63756a3917be6e.tar.zst nixlib-7d67efa3f23f7d5c494c90b79a63756a3917be6e.zip |
Add support for building cargo'ed Rust programs
Diffstat (limited to 'pkgs/build-support/rust')
-rw-r--r-- | pkgs/build-support/rust/default.nix | 52 | ||||
-rw-r--r-- | pkgs/build-support/rust/fetch-builder.sh | 17 | ||||
-rwxr-xr-x | pkgs/build-support/rust/fetch-cargo-deps | 119 | ||||
-rw-r--r-- | pkgs/build-support/rust/fetchcargo.nix | 19 |
4 files changed, 207 insertions, 0 deletions
diff --git a/pkgs/build-support/rust/default.nix b/pkgs/build-support/rust/default.nix new file mode 100644 index 000000000000..a02163f73faf --- /dev/null +++ b/pkgs/build-support/rust/default.nix @@ -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; + ''; +}) diff --git a/pkgs/build-support/rust/fetch-builder.sh b/pkgs/build-support/rust/fetch-builder.sh new file mode 100644 index 000000000000..faa17e653289 --- /dev/null +++ b/pkgs/build-support/rust/fetch-builder.sh @@ -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 diff --git a/pkgs/build-support/rust/fetch-cargo-deps b/pkgs/build-support/rust/fetch-cargo-deps new file mode 100755 index 000000000000..d6579fe94bda --- /dev/null +++ b/pkgs/build-support/rust/fetch-cargo-deps @@ -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 diff --git a/pkgs/build-support/rust/fetchcargo.nix b/pkgs/build-support/rust/fetchcargo.nix new file mode 100644 index 000000000000..cd5d69e06d0d --- /dev/null +++ b/pkgs/build-support/rust/fetchcargo.nix @@ -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; +} |