diff options
author | Alyssa Ross <hi@alyssa.is> | 2019-01-07 02:18:36 +0000 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2019-01-07 02:18:47 +0000 |
commit | 36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2 (patch) | |
tree | b3faaf573407b32aa645237a4d16b82778a39a92 /nixpkgs/doc/languages-frameworks/rust.section.md | |
parent | 4e31070265257dc67d120c27e0f75c2344fdfa9a (diff) | |
parent | abf060725d7614bd3b9f96764262dfbc2f9c2199 (diff) | |
download | nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.gz nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.bz2 nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.lz nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.xz nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.zst nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.zip |
Add 'nixpkgs/' from commit 'abf060725d7614bd3b9f96764262dfbc2f9c2199'
git-subtree-dir: nixpkgs git-subtree-mainline: 4e31070265257dc67d120c27e0f75c2344fdfa9a git-subtree-split: abf060725d7614bd3b9f96764262dfbc2f9c2199
Diffstat (limited to 'nixpkgs/doc/languages-frameworks/rust.section.md')
-rw-r--r-- | nixpkgs/doc/languages-frameworks/rust.section.md | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/nixpkgs/doc/languages-frameworks/rust.section.md b/nixpkgs/doc/languages-frameworks/rust.section.md new file mode 100644 index 000000000000..4549bbd1686b --- /dev/null +++ b/nixpkgs/doc/languages-frameworks/rust.section.md @@ -0,0 +1,395 @@ +--- +title: Rust +author: Matthias Beyer +date: 2017-03-05 +--- + +# User's Guide to the Rust Infrastructure + +To install the rust compiler and cargo put + +``` +rustc +cargo +``` + +into the `environment.systemPackages` or bring them into +scope with `nix-shell -p rustc cargo`. + +> If you are using NixOS and you want to use rust without a nix expression you +> probably want to add the following in your `configuration.nix` to build +> crates with C dependencies. +> +> environment.systemPackages = [binutils gcc gnumake openssl pkgconfig] + +For daily builds (beta and nightly) use either rustup from +nixpkgs or use the [Rust nightlies +overlay](#using-the-rust-nightlies-overlay). + +## Compiling Rust applications with Cargo + +Rust applications are packaged by using the `buildRustPackage` helper from `rustPlatform`: + +``` +rustPlatform.buildRustPackage rec { + name = "ripgrep-${version}"; + version = "0.4.0"; + + src = fetchFromGitHub { + owner = "BurntSushi"; + repo = "ripgrep"; + rev = "${version}"; + sha256 = "0y5d1n6hkw85jb3rblcxqas2fp82h3nghssa4xqrhqnz25l799pj"; + }; + + cargoSha256 = "0q68qyl2h6i0qsz82z840myxlnjay8p1w5z7hfyr8fqp7wgwa9cx"; + + meta = with stdenv.lib; { + description = "A fast line-oriented regex search tool, similar to ag and ack"; + homepage = https://github.com/BurntSushi/ripgrep; + license = licenses.unlicense; + maintainers = [ maintainers.tailhook ]; + platforms = platforms.all; + }; +} +``` + +`buildRustPackage` requires a `cargoSha256` attribute which is computed over +all crate sources of this package. Currently it is obtained by inserting a +fake checksum into the expression and building the package once. The correct +checksum can be then take from the failed build. + +When the `Cargo.lock`, provided by upstream, is not in sync with the +`Cargo.toml`, it is possible to use `cargoPatches` to update it. All patches +added in `cargoPatches` will also be prepended to the patches in `patches` at +build-time. + +## Compiling Rust crates using Nix instead of Cargo + +### Simple operation + +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 -A hello_0_1_0 + +Now, the file produced by the call to `carnix`, called `hello.nix`, looks like: + +``` +# Generated by carnix 0.6.5: carnix -o hello.nix --src ./. Cargo.lock --standalone +{ lib, stdenv, buildRustCrate, fetchgit }: +let kernel = stdenv.buildPlatform.parsed.kernel.name; + # ... (content skipped) +in +rec { + hello = f: hello_0_1_0 { features = hello_0_1_0_features { hello_0_1_0 = f; }; }; + hello_0_1_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate { + crateName = "hello"; + version = "0.1.0"; + authors = [ "pe@pijul.org <pe@pijul.org>" ]; + src = ./.; + inherit dependencies buildDependencies features; + }; + hello_0_1_0 = { features?(hello_0_1_0_features {}) }: hello_0_1_0_ {}; + hello_0_1_0_features = f: updateFeatures f (rec { + hello_0_1_0.default = (f.hello_0_1_0.default or true); + }) [ ]; +} +``` + +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: + +``` +# Generated by carnix 0.6.5: carnix -o hello.nix --src ./. Cargo.lock --standalone +{ lib, stdenv, buildRustCrate, fetchgit }: +let kernel = stdenv.buildPlatform.parsed.kernel.name; + # ... (content skipped) +in +rec { + hello = f: hello_0_1_0 { features = hello_0_1_0_features { hello_0_1_0 = f; }; }; + hello_0_1_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate { + crateName = "hello"; + version = "0.1.0"; + authors = [ "pe@pijul.org <pe@pijul.org>" ]; + src = ./.; + inherit dependencies buildDependencies features; + }; + libc_0_2_36_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate { + crateName = "libc"; + version = "0.2.36"; + authors = [ "The Rust Project Developers" ]; + sha256 = "01633h4yfqm0s302fm0dlba469bx8y6cs4nqc8bqrmjqxfxn515l"; + inherit dependencies buildDependencies features; + }; + hello_0_1_0 = { features?(hello_0_1_0_features {}) }: hello_0_1_0_ { + dependencies = mapFeatures features ([ libc_0_2_36 ]); + }; + hello_0_1_0_features = f: updateFeatures f (rec { + hello_0_1_0.default = (f.hello_0_1_0.default or true); + libc_0_2_36.default = true; + }) [ libc_0_2_36_features ]; + libc_0_2_36 = { features?(libc_0_2_36_features {}) }: libc_0_2_36_ { + features = mkFeatures (features.libc_0_2_36 or {}); + }; + libc_0_2_36_features = f: updateFeatures f (rec { + libc_0_2_36.default = (f.libc_0_2_36.default or true); + libc_0_2_36.use_std = + (f.libc_0_2_36.use_std or false) || + (f.libc_0_2_36.default or false) || + (libc_0_2_36.default or false); + }) []; +} +``` + +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. + +### Handling external dependencies + +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 {}).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 {}).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 {}).override { + crateOverrides = defaultCrateOverrides // { + libc = attrs: { buildInputs = []; }; + }; +} +``` + +### Options and phases configuration + +Actually, the overrides introduced in the previous section are more +general. A number of other parameters can be overridden: + +- The version of rustc used to compile the crate: + + ``` + (hello {}).override { rust = pkgs.rust; }; + ``` + +- Whether to build in release mode or debug mode (release mode by + default): + + ``` + (hello {}).override { release = false; }; + ``` + +- Whether to print the commands sent to rustc when building + (equivalent to `--verbose` in cargo: + + ``` + (hello {}).override { verbose = false; }; + ``` + +- Extra arguments to be passed to `rustc`: + + ``` + (hello {}).override { extraRustcOpts = "-Z debuginfo=2"; }; + ``` + +- Phases, just like in any other derivation, can be specified using + the following attributes: `preUnpack`, `postUnpack`, `prePatch`, + `patches`, `postPatch`, `preConfigure` (in the case of a Rust crate, + this is run before calling the "build" script), `postConfigure` + (after the "build" script),`preBuild`, `postBuild`, `preInstall` and + `postInstall`. As an example, here is how to create a new module + before running the build script: + + ``` + (hello {}).override { + preConfigure = '' + echo "pub const PATH=\"${hi.out}\";" >> src/path.rs" + ''; + }; + ``` + +### Features + +One can also supply features switches. For example, if we want to +compile `diesel_cli` only with the `postgres` feature, and no default +features, we would write: + +``` +(callPackage ./diesel.nix {}).diesel { + default = false; + postgres = true; +} +``` + +Where `diesel.nix` is the file generated by Carnix, as explained above. + + +## Setting Up `nix-shell` +Oftentimes you want to develop code from within `nix-shell`. Unfortunately +`buildRustCrate` does not support common `nix-shell` operations directly +(see [this issue](https://github.com/NixOS/nixpkgs/issues/37945)) +so we will use `stdenv.mkDerivation` instead. + +Using the example `hello` project above, we want to do the following: +- Have access to `cargo` and `rustc` +- Have the `openssl` library available to a crate through it's _normal_ + compilation mechanism (`pkg-config`). + +A typical `shell.nix` might look like: + +``` +with import <nixpkgs> {}; + +stdenv.mkDerivation { + name = "rust-env"; + buildInputs = [ + rustc cargo + + # Example Additional Dependencies + pkgconfig openssl + ]; + + # Set Environment Variables + RUST_BACKTRACE = 1; +} +``` + +You should now be able to run the following: +``` +$ nix-shell --pure +$ cargo build +$ cargo test +``` + +### Controlling Rust Version Inside `nix-shell` +To control your rust version (i.e. use nightly) from within `shell.nix` (or +other nix expressions) you can use the following `shell.nix` + +``` +# Latest Nightly +with import <nixpkgs> {}; +let src = fetchFromGitHub { + owner = "mozilla"; + repo = "nixpkgs-mozilla"; + # commit from: 2018-03-27 + rev = "2945b0b6b2fd19e7d23bac695afd65e320efcebe"; + sha256 = "034m1dryrzh2lmjvk3c0krgip652dql46w5yfwpvh7gavd3iypyw"; + }; +in +with import "${src.out}/rust-overlay.nix" pkgs pkgs; +stdenv.mkDerivation { + name = "rust-env"; + buildInputs = [ + # Note: to use use stable, just replace `nightly` with `stable` + latest.rustChannels.nightly.rust + + # Add some extra dependencies from `pkgs` + pkgconfig openssl + ]; + + # Set Environment Variables + RUST_BACKTRACE = 1; +} +``` + +Now run: +``` +$ rustc --version +rustc 1.26.0-nightly (188e693b3 2018-03-26) +``` + +To see that you are using nightly. + + +## Using the Rust nightlies overlay + +Mozilla provides an overlay for nixpkgs to bring a nightly version of Rust into scope. +This overlay can _also_ be used to install recent unstable or stable versions +of Rust, if desired. + +To use this overlay, clone +[nixpkgs-mozilla](https://github.com/mozilla/nixpkgs-mozilla), +and create a symbolic link to the file +[rust-overlay.nix](https://github.com/mozilla/nixpkgs-mozilla/blob/master/rust-overlay.nix) +in the `~/.config/nixpkgs/overlays` directory. + + $ git clone https://github.com/mozilla/nixpkgs-mozilla.git + $ mkdir -p ~/.config/nixpkgs/overlays + $ ln -s $(pwd)/nixpkgs-mozilla/rust-overlay.nix ~/.config/nixpkgs/overlays/rust-overlay.nix + +The latest version can be installed with the following command: + + $ nix-env -Ai nixos.latest.rustChannels.stable.rust + +Or using the attribute with nix-shell: + + $ nix-shell -p nixos.latest.rustChannels.stable.rust + +To install the beta or nightly channel, "stable" should be substituted by +"nightly" or "beta", or +use the function provided by this overlay to pull a version based on a +build date. + +The overlay automatically updates itself as it uses the same source as +[rustup](https://www.rustup.rs/). |