Jump to content

Rust: Difference between revisions

10 bytes added ,  26 July 2022
m
Minor language improvements.
imported>Dmarcoux
m (Update link to VS Code extension for rust-analyzer)
imported>Torhovland
m (Minor language improvements.)
Line 1: Line 1:
This article is about the [https://www.rust-lang.org Rust programming language]. There are 3 methods to use the rust compiler and toolchain in Nix/NixOS:  
This article is about the [https://www.rust-lang.org Rust programming language]. There are 3 methods to use the Rust compiler and toolchain in Nix/NixOS:  


# via nixpkgs,  
# via nixpkgs,  
Line 5: Line 5:
# or with unofficial overlays on nixpkgs.  
# or with unofficial overlays on nixpkgs.  


Installing via nixpkgs is the nix-iest way to use rust, but there are valid reasons to use any approach.
Installing via nixpkgs is the nix-iest way to use Rust, but there are valid reasons to use any approach.


== Installing via nixpkgs ==
== Installing via nixpkgs ==
The <code>cargo</code> and <code>rustc</code> derivations provide the rust toolchain in nixpkgs. A pro of using nixpkgs is that it's dead-simple and you get pinned versions, deterministic builds in nix-shell, etc. However, nixpkgs only maintains a single version of the rust stable toolchain, so if you require a nightly toolchain or require switching between multiple toolchains then this approach may not be for you.  
The <code>cargo</code> and <code>rustc</code> derivations provide the Rust toolchain in nixpkgs. An advantage of using nixpkgs is that it's dead simple and you get pinned versions, deterministic builds in nix-shell, etc. However, nixpkgs only maintains a single version of the Rust stable toolchain, so if you require a nightly toolchain or require switching between multiple toolchains then this approach may not be for you.  


Here's an example <code>shell.nix</code>:
Here's an example <code>shell.nix</code>:
Line 25: Line 25:


=== VSCode integration ===
=== VSCode integration ===
The [https://marketplace.visualstudio.com/items?itemName=rust-lang.rust rust-lang.rust] and [https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer rust-lang.rust-analyzer] VSCode extensions offer rust support. However, you'll need a few more ingredients to get everything working:
The [https://marketplace.visualstudio.com/items?itemName=rust-lang.rust rust-lang.rust] and [https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer rust-lang.rust-analyzer] VSCode extensions offer Rust support. However, you'll need a few more ingredients to get everything working:
<syntaxHighlight lang="nix">
<syntaxHighlight lang="nix">
let
let
Line 50: Line 50:


== Installation via rustup ==
== Installation via rustup ==
The rustup tool is maintained by the rust community and offers and interface to install and switch between rust toolchains. In this scenario, rustup handles the "package management" of rust toolchains and places them in <code>$PATH</code>. Nixpkgs offers rustup via the <code>rustup</code> derivation. More info on using rustup can be found on their official website: https://rustup.rs/.
The rustup tool is maintained by the Rust community and offers and interface to install and switch between Rust toolchains. In this scenario, rustup handles the "package management" of Rust toolchains and places them in <code>$PATH</code>. Nixpkgs offers rustup via the <code>rustup</code> derivation. More info on using rustup can be found on their official website: https://rustup.rs/.


If you want to have the most "normal" rust experience I recommend using rustup with the following example shell.nix:
If you want to have the most "normal" Rust experience I recommend using rustup with the following example shell.nix:
<syntaxHighlight lang="nix">
<syntaxHighlight lang="nix">
{ pkgs ? import <nixpkgs> {} }:
{ pkgs ? import <nixpkgs> {} }:
Line 69: Line 69:
     RUSTC_VERSION = pkgs.lib.readFile ./rust-toolchain;
     RUSTC_VERSION = pkgs.lib.readFile ./rust-toolchain;
     # https://github.com/rust-lang/rust-bindgen#environment-variables
     # https://github.com/rust-lang/rust-bindgen#environment-variables
     LIBCLANG_PATH= pkgs.lib.makeLibraryPath [ pkgs.llvmPackages_latest.libclang.lib ];
     LIBCLANG_PATH = pkgs.lib.makeLibraryPath [ pkgs.llvmPackages_latest.libclang.lib ];
     HISTFILE=toString ./.history;
     HISTFILE = toString ./.history;
     shellHook = ''
     shellHook = ''
       export PATH=$PATH:~/.cargo/bin
       export PATH=$PATH:~/.cargo/bin
Line 97: Line 97:


It's important to have a file named <code>rust-toolchain</code> lying in the same directory as the shell.nix.
It's important to have a file named <code>rust-toolchain</code> lying in the same directory as the shell.nix.
Its purpose is to pin the version of the used rust compiler.
Its purpose is to pin the version of the used Rust compiler.
<syntaxHighlight lang="shell-session">
<syntaxHighlight lang="shell-session">
$ cat rust-toolchain
$ cat rust-toolchain
Line 103: Line 103:
</syntaxHighlight>
</syntaxHighlight>


The important part is that this also works with complex setups using bindgen and precompiled c libraries. To add a new c library in the search path of bindgen and rustc edit the variables <code>BINDGEN_EXTRA_CLANG_ARGS</code> and <code>RUSTFLAGS</code>
The important part is that this also works with complex setups using bindgen and precompiled C libraries. To add a new C library in the search path of bindgen and rustc edit the variables <code>BINDGEN_EXTRA_CLANG_ARGS</code> and <code>RUSTFLAGS</code>


== Cross-compiling ==
== Cross-compiling ==


=== To windows via rustup ===
=== To Windows via rustup ===


* [https://github.com/jraygauthier/jrg-rust-cross-experiment/tree/master/simple-static-rustup-target-windows simple-static-rustup-target-windows]
* [https://github.com/jraygauthier/jrg-rust-cross-experiment/tree/master/simple-static-rustup-target-windows simple-static-rustup-target-windows]
Line 233: Line 233:


* '''Cargo.lock solution:''' How does this solution handle reproducibly determining what crates need to be downloaded from the Cargo.lock file? “Checksum” means it requires you to specify the checksum of all the downloaded dependencies. “Import” means it dynamically imports and parses Cargo.lock from a Nix expression, which means Cargo.lock needs to be present in the same repository as the nix expressions (or IFD must be used). “Codegen” means it generates a .nix file from the Cargo.lock, which is then committed to source control.
* '''Cargo.lock solution:''' How does this solution handle reproducibly determining what crates need to be downloaded from the Cargo.lock file? “Checksum” means it requires you to specify the checksum of all the downloaded dependencies. “Import” means it dynamically imports and parses Cargo.lock from a Nix expression, which means Cargo.lock needs to be present in the same repository as the nix expressions (or IFD must be used). “Codegen” means it generates a .nix file from the Cargo.lock, which is then committed to source control.
* '''Derivations:''' How many derivations does this solution use to compile rust code? “1” means the project and all its dependencies are compiled in one derivation. “2” means all dependencies are moved into a separate derivation, so the project can be updated independently, but any change to the set of dependencies rebuilds everything. “Many” means each dependency is built in its own derivation, so changes to dependencies only do the minimal amount of rebuilding necessary (and, ideally, different projects can share dependencies, although I haven’t checked if this works in practice).
* '''Derivations:''' How many derivations does this solution use to compile Rust code? “1” means the project and all its dependencies are compiled in one derivation. “2” means all dependencies are moved into a separate derivation, so the project can be updated independently, but any change to the set of dependencies rebuilds everything. “Many” means each dependency is built in its own derivation, so changes to dependencies only do the minimal amount of rebuilding necessary (and, ideally, different projects can share dependencies, although I haven’t checked if this works in practice).
* '''Build logic:''' How does this solution orchestrate building of crates? “Cargo” means it relies on Cargo; <code>buildRustCrate</code> means it uses Nixpkgs’ <code>buildRustCrate</code>; “custom” means it uses its own custom logic (in Nix)
* '''Build logic:''' How does this solution orchestrate building of crates? “Cargo” means it relies on Cargo; <code>buildRustCrate</code> means it uses Nixpkgs’ <code>buildRustCrate</code>; “custom” means it uses its own custom logic (in Nix)
* '''Supports cross:''' Does the solution allow for cross-compilation of crates?
* '''Supports cross:''' Does the solution allow for cross-compilation of crates?
Line 247: Line 247:
}
}
</syntaxHighlight>
</syntaxHighlight>
This will have the stable rust compiler + the official formatter and linter inside the ephemeral shell. It'll also set the RUST_SRC_PATH environment variable to point to the right location, which tools, such as rust-analyzer, require to be set.
This will have the stable Rust compiler + the official formatter and linter inside the ephemeral shell. It'll also set the RUST_SRC_PATH environment variable to point to the right location, which tools, such as rust-analyzer, require to be set.


== FAQ ==
== FAQ ==
Anonymous user