├── README.md └── flake.nix /README.md: -------------------------------------------------------------------------------- 1 | # `import-cargo` 2 | 3 | Simple [flake](https://www.tweag.io/blog/2020-05-25-flakes/) to import all dependencies from 4 | a [`Cargo.lock`](https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html) 5 | as [fixed-output derivation](https://nixos.org/nix/manual/#fixed-output-drvs) using the 6 | checksum and URL from the lockfile. 7 | 8 | ## Usage 9 | 10 | This example demonstrates how to build a local Cargo project with a 11 | `flake.nix`: 12 | 13 | ``` nix 14 | { 15 | description = "My Rust project"; 16 | 17 | inputs = { 18 | nixpkgs.url = github:NixOS/nixpkgs/nixos-20.03; 19 | import-cargo.url = github:edolstra/import-cargo; 20 | }; 21 | 22 | outputs = { self, nixpkgs, import-cargo }: let 23 | 24 | inherit (import-cargo.builders) importCargo; 25 | 26 | in { 27 | 28 | defaultPackage.x86_64-linux = 29 | with import nixpkgs { system = "x86_64-linux"; }; 30 | stdenv.mkDerivation { 31 | name = "testrust"; 32 | src = self; 33 | 34 | nativeBuildInputs = [ 35 | # setupHook which makes sure that a CARGO_HOME with vendored dependencies 36 | # exists 37 | (importCargo { lockFile = ./Cargo.lock; inherit pkgs; }).cargoHome 38 | 39 | # Build-time dependencies 40 | rustc cargo 41 | ]; 42 | 43 | buildPhase = '' 44 | cargo build --release --offline 45 | ''; 46 | 47 | installPhase = '' 48 | install -Dm775 ./target/release/testrust $out/bin/testrust 49 | ''; 50 | 51 | }; 52 | 53 | }; 54 | } 55 | ``` 56 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "A function for fetching the crates listed in a Cargo lock file"; 3 | 4 | outputs = { self }: rec { 5 | 6 | builders.importCargo = 7 | { lockFile, pkgs }: 8 | let lockFile' = builtins.fromTOML (builtins.readFile lockFile); in 9 | rec { 10 | 11 | # Fetch and unpack the crates specified in the lock file. 12 | unpackedCrates = map 13 | (pkg: 14 | 15 | let 16 | isGit = builtins.match ''git\+(.*)\?rev=([0-9a-f]+)(#.*)?'' pkg.source; 17 | registry = "registry+https://github.com/rust-lang/crates.io-index"; 18 | in 19 | 20 | if pkg.source == registry then 21 | let 22 | sha256 = pkg.checksum or lockFile'.metadata."checksum ${pkg.name} ${pkg.version} (${registry})"; 23 | tarball = import { 24 | url = "https://crates.io/api/v1/crates/${pkg.name}/${pkg.version}/download"; 25 | inherit sha256; 26 | }; 27 | in pkgs.runCommand "${pkg.name}-${pkg.version}" {} 28 | '' 29 | mkdir $out 30 | 31 | tar xvf ${tarball} -C $out --strip-components=1 32 | 33 | # Add just enough metadata to keep Cargo happy. 34 | printf '{"files":{},"package":"${sha256}"}' > "$out/.cargo-checksum.json" 35 | '' 36 | 37 | else if isGit != null then 38 | let 39 | rev = builtins.elemAt isGit 1; 40 | url = builtins.elemAt isGit 0; 41 | tree = builtins.fetchGit { inherit url rev; }; 42 | in pkgs.runCommand "${pkg.name}-${pkg.version}" {} 43 | '' 44 | tree=${tree} 45 | 46 | if grep --quiet '\[workspace\]' $tree/Cargo.toml; then 47 | if [[ -e $tree/${pkg.name} ]]; then 48 | tree=$tree/${pkg.name} 49 | fi 50 | fi 51 | 52 | cp -prvd $tree/ $out 53 | chmod u+w $out 54 | 55 | # Add just enough metadata to keep Cargo happy. 56 | printf '{"files":{},"package":null}' > "$out/.cargo-checksum.json" 57 | 58 | cat > $out/.cargo-config < $out/vendor/config <> $out/vendor/config 95 | fi 96 | fi 97 | done 98 | ''; 99 | 100 | # Create a setup hook that will initialize CARGO_HOME. Note: 101 | # we don't point CARGO_HOME at the vendor tree directly 102 | # because then we end up with a runtime dependency on it. 103 | cargoHome = pkgs.makeSetupHook {} 104 | (pkgs.writeScript "make-cargo-home" '' 105 | if [[ -z "''${CARGO_HOME-}" || "''${CARGO_HOME-}" = /build ]]; then 106 | export CARGO_HOME=$TMPDIR/vendor 107 | # FIXME: work around Rust 1.36 wanting a $CARGO_HOME/.package-cache file. 108 | #ln -s ${vendorDir}/vendor $CARGO_HOME 109 | cp -prd ${vendorDir}/vendor $CARGO_HOME 110 | chmod -R u+w $CARGO_HOME 111 | fi 112 | ''); 113 | }; 114 | 115 | }; 116 | 117 | } 118 | --------------------------------------------------------------------------------