aboutsummaryrefslogblamecommitdiff
path: root/_posts/2020-10-05-cargo2nix-dramatically-simpler-rust-in-nix.md
blob: a7d6850779c2a531de23414f354c059af5f22dc7 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14













                                                                               
                                                                 

































                                                                                                           
                                                                              
                                                                                

                                                                             

                                               



                                                                                
 



                                                                            










                                                     
---
title: "cargo2nix: Dramatically simpler Rust inside Nix"
date: 2020-10-05
layout: post
lang: en
ref: cargo2nix-dramatically-simpler-rust-in-nix
---

In the same vein of my earlier post on
[swift2nix]({% post_url 2020-10-05-swift2nix-run-swift-inside-nix-builds %}), I
was able to quickly prototype a Rust and Cargo variation of it:
[cargo2nix][cargo2nix].


The initial prototype is even smaller than swift2nix: it has only
[37 lines of code][37-lines].

[cargo2nix]: https://git.euandreh.xyz/cargo2nix/about/
[37-lines]: https://git.euandreh.xyz/cargo2nix/tree/default.nix?id=472dde8898296c8b6cffcbd10b3b2c3ba195846d

Here's how to use it (snippet taken from the repo's README):

```nix
let
  niv-sources = import ./nix/sources.nix;
  pkgs = import niv-sources.nixpkgs { };
  src = pkgs.nix-gitignore.gitignoreSource [ ] ./.;
  cargo2nix = pkgs.callPackage niv-sources.cargo2nix {
    lockfile = ./Cargo.lock;
  };
in pkgs.stdenv.mkDerivation {
  inherit src;
  name = "swift-test";
  buildInputs = with pkgs; [ cargo ];
  phases = [ "unpackPhase" "buildPhase" ];
  buildPhase = ''
    # Setup dependencies path to satisfy Cargo
    mkdir .cargo/ vendor/
    ln -s ${cargo2nix.env.cargo-config} .cargo/config
    ln -s ${cargo2nix.env.vendor} vendor

    # Run the tests
    cargo test
    touch $out
  '';
}
```

That `cargo test` part on line 20 is what I have been fighting with every
"\*2nix" available for Rust out there. I don't want to bash any of them. All I
want is to have full control of what Cargo commands to run, and the "*2nix" tool
should only setup the environment for me. Let me run Cargo however I want, no
need to parameterize how the tool runs Cargo for me, or even replicate Cargo
commands by calling the Rust compiler directly.

Sure it doesn't support private registries or Git dependencies, but how much
bigger does it has to be to support it? Also, it doesn't support those **yet**,
there's no reason it can't be extended to support them. I just haven't needed it
yet, so I haven't added. Patches welcome.

The layout of the `vendor/` directory is more explicit and public then what
swift2nix does: it is whatever the command `cargo vendor` returns. However I
haven't checked if the shape of the `.cargo-checksum.json` is specified, or
internal to Cargo.

Try out the demo (also taken from the repo's README):

```shell
pushd "$(mktemp -d)"
git clone https://git.euandreh.xyz/cargo2nix-demo
cd cargo2nix-demo/
nix-build
```

Report back if you wish. Again, patches welcome.