summary refs log tree commit diff
path: root/doc/languages-frameworks
diff options
context:
space:
mode:
authorPierre-Étienne Meunier <pierre-etienne.meunier@inria.fr>2017-12-12 04:55:15 -0600
committerJörg Thalheim <joerg@thalheim.io>2017-12-12 04:58:45 -0600
commit5a0d954156a26853dc0b5f301e839360289f880a (patch)
tree829ad6d32ac7599595093dd32a66bb092eb68025 /doc/languages-frameworks
parentea232fe29d055f9680a8501ef8d209e70e40f689 (diff)
downloadnixpkgs-5a0d954156a26853dc0b5f301e839360289f880a.tar
nixpkgs-5a0d954156a26853dc0b5f301e839360289f880a.tar.gz
nixpkgs-5a0d954156a26853dc0b5f301e839360289f880a.tar.bz2
nixpkgs-5a0d954156a26853dc0b5f301e839360289f880a.tar.lz
nixpkgs-5a0d954156a26853dc0b5f301e839360289f880a.tar.xz
nixpkgs-5a0d954156a26853dc0b5f301e839360289f880a.tar.zst
nixpkgs-5a0d954156a26853dc0b5f301e839360289f880a.zip
add buildRustCrate function to build rust crates
Diffstat (limited to 'doc/languages-frameworks')
-rw-r--r--doc/languages-frameworks/rust.md163
1 files changed, 162 insertions, 1 deletions
diff --git a/doc/languages-frameworks/rust.md b/doc/languages-frameworks/rust.md
index bedda76a306..aa6a7d65410 100644
--- a/doc/languages-frameworks/rust.md
+++ b/doc/languages-frameworks/rust.md
@@ -20,7 +20,7 @@ For daily builds (beta and nightly) use either rustup from
 nixpkgs or use the [Rust nightlies
 overlay](#using-the-rust-nightlies-overlay).
 
-## Packaging Rust applications
+## Compiling Rust applications with Cargo
 
 Rust applications are packaged by using the `buildRustPackage` helper from `rustPlatform`:
 
@@ -56,6 +56,167 @@ checksum can be then take from the failed build.
 To install crates with nix there is also an experimental project called
 [nixcrates](https://github.com/fractalide/nixcrates).
 
+## Compiling Rust crates using Nix instead of Cargo
+
+When run, `cargo build` produces a file called `Cargo.lock`,
+containing pinned versions of all dependencies. Nixpkgs contains a
+tool called `carnix` (`nix-env -iA nixos.carnix`), which can be used
+to turn a `Cargo.lock` into a Nix expression.
+
+That Nix expression calls `rustc` directly (hence bypassing Cargo),
+and can be used to compile a crate and all its dependencies. Here is
+an example for a minimal `hello` crate:
+
+
+    $ cargo new hello
+    $ cd hello
+    $ cargo build
+     Compiling hello v0.1.0 (file:///tmp/hello)
+      Finished dev [unoptimized + debuginfo] target(s) in 0.20 secs
+    $ carnix -o hello.nix --src ./. Cargo.lock --standalone
+    $ nix-build hello.nix
+
+Now, the file produced by the call to `carnix`, called `hello.nix`, looks like:
+
+```
+with import <nixpkgs> {};
+let kernel = buildPlatform.parsed.kernel.name;
+    # ... (content skipped)
+    hello_0_1_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "hello";
+      version = "0.1.0";
+      authors = [ "Authorname <user@example.com>" ];
+      src = ./.;
+      inherit dependencies buildDependencies features;
+    };
+in
+rec {
+  hello_0_1_0 = hello_0_1_0_ rec {};
+}
+```
+
+In particular, note that the argument given as `--src` is copied
+verbatim to the source. If we look at a more complicated
+dependencies, for instance by adding a single line `libc="*"` to our
+`Cargo.toml`, we first need to run `cargo build` to update the
+`Cargo.lock`. Then, `carnix` needs to be run again, and produces the
+following nix file:
+
+```
+with import <nixpkgs> {};
+let kernel = buildPlatform.parsed.kernel.name;
+    # ... (content skipped)
+    hello_0_1_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "hello";
+      version = "0.1.0";
+      authors = [ "Jörg Thalheim <joerg@thalheim.io>" ];
+      src = ./.;
+      inherit dependencies buildDependencies features;
+    };
+    libc_0_2_34_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "libc";
+      version = "0.2.34";
+      authors = [ "The Rust Project Developers" ];
+      sha256 = "11jmqdxmv0ka10ay0l8nzx0nl7s2lc3dbrnh1mgbr2grzwdyxi2s";
+      inherit dependencies buildDependencies features;
+    };
+in
+rec {
+  hello_0_1_0 = hello_0_1_0_ rec {
+    dependencies = [ libc_0_2_34 ];
+  };
+  libc_0_2_34_features."default".from_hello_0_1_0__default = true;
+  libc_0_2_34 = libc_0_2_34_ rec {
+    features = mkFeatures libc_0_2_34_features;
+  };
+  libc_0_2_34_features."use_std".self_default = hasDefault libc_0_2_34_features;
+}
+```
+
+Here, the `libc` crate has no `src` attribute, so `buildRustCrate`
+will fetch it from [crates.io](https://crates.io). A `sha256`
+attribute is still needed for Nix purity.
+
+Some crates require external libraries. For crates from
+[crates.io](https://crates.io), such libraries can be specified in
+`defaultCrateOverrides` package in nixpkgs itself.
+
+Starting from that file, one can add more overrides, to add features
+or build inputs by overriding the hello crate in a seperate file.
+
+```
+with import <nixpkgs> {};
+(import ./hello.nix).hello_0_1_0.override {
+  crateOverrides = defaultCrateOverrides // {
+    hello = attrs: { buildInputs = [ openssl ]; };
+  };
+}
+```
+
+Here, `crateOverrides` is expected to be a attribute set, where the
+key is the crate name without version number and the value a function.
+The function gets all attributes passed to `buildRustCrate` as first
+argument and returns a set that contains all attribute that should be
+overwritten.
+
+For more complicated cases, such as when parts of the crate's
+derivation depend on the the crate's version, the `attrs` argument of
+the override above can be read, as in the following example, which
+patches the derivation:
+
+```
+with import <nixpkgs> {};
+(import ./hello.nix).hello_0_1_0.override {
+  crateOverrides = defaultCrateOverrides // {
+    hello = attrs: lib.optionalAttrs (lib.versionAtLeast attrs.version "1.0")  {
+      postPatch = ''
+        substituteInPlace lib/zoneinfo.rs \
+          --replace "/usr/share/zoneinfo" "${tzdata}/share/zoneinfo"
+      '';
+    };
+  };
+}
+```
+
+Another situation is when we want to override a nested
+dependency. This actually works in the exact same way, since the
+`crateOverrides` parameter is forwarded to the crate's
+dependencies. For instance, to override the build inputs for crate
+`libc` in the example above, where `libc` is a dependency of the main
+crate, we could do:
+
+```
+with import <nixpkgs> {};
+(import hello.nix).hello_0_1_0.override {
+  crateOverrides = defaultCrateOverrides // {
+    libc = attrs: { buildInputs = []; };
+  };
+}
+```
+
+Three more parameters can be overridden:
+
+- The version of rustc used to compile the crate:
+
+  ```
+  hello_0_1_0.override { rust = pkgs.rust; };
+  ```
+
+- Whether to build in release mode or debug mode (release mode by
+  default):
+
+  ```
+  hello_0_1_0.override { release = false; };
+  ```
+
+- Whether to print the commands sent to rustc when building
+  (equivalent to `--verbose` in cargo:
+
+  ```
+  hello_0_1_0.override { verbose = false; };
+  ```
+
+
 ## Using the Rust nightlies overlay
 
 Mozilla provides an overlay for nixpkgs to bring a nightly version of Rust into scope.