Jump to content

Rust: Difference between revisions

238 bytes removed ,  29 April
Remove Rust Nightlies section. This section had no information that wasn't found on the rest of the page (only having two bullet points referring to other sections of the page). Instead, modify the page to elaborate more in the respective sections.
imported>Nilstrieb
m (Add note about using the latest llvmPackages. llvmPackages as at LLVM 11, which is outdated and caused LLD segfaults for me when running the test suite for rust-lang/rust. llvmPackages_16 worked just fine.)
(Remove Rust Nightlies section. This section had no information that wasn't found on the rest of the page (only having two bullet points referring to other sections of the page). Instead, modify the page to elaborate more in the respective sections.)
 
(13 intermediate revisions by 11 users not shown)
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 best 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. 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.  
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 switch 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:


== 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 an 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 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> {} }:
  let
    overrides = (builtins.fromTOML (builtins.readFile ./rust-toolchain.toml));
    libPath = with pkgs; lib.makeLibraryPath [
      # load external libraries that you need in your rust project here
    ];
in
   pkgs.mkShell rec {
   pkgs.mkShell rec {
     buildInputs = with pkgs; [
     buildInputs = with pkgs; [
Line 37: Line 43:
       rustup
       rustup
     ];
     ];
     RUSTC_VERSION = pkgs.lib.readFile ./rust-toolchain;
     RUSTC_VERSION = overrides.toolchain.channel;
     # 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 ];
Line 48: Line 54:
       # add libraries here (e.g. pkgs.libvmi)
       # add libraries here (e.g. pkgs.libvmi)
     ]);
     ]);
     # Add glibc, clang, glib and other headers to bindgen search path
    LD_LIBRARY_PATH = libPath;
     BINDGEN_EXTRA_CLANG_ARGS =  
     # Add glibc, clang, glib, and other headers to bindgen search path
     # Includes with normal include path
     BINDGEN_EXTRA_CLANG_ARGS =
     # Includes normal include path
     (builtins.map (a: ''-I"${a}/include"'') [
     (builtins.map (a: ''-I"${a}/include"'') [
       # add dev libraries here (e.g. pkgs.libvmi.dev)
       # add dev libraries here (e.g. pkgs.libvmi.dev)
       pkgs.glibc.dev  
       pkgs.glibc.dev
     ])
     ])
     # Includes with special directory paths
     # Includes with special directory paths
Line 61: Line 68:
       ''-I${pkgs.glib.out}/lib/glib-2.0/include/''
       ''-I${pkgs.glib.out}/lib/glib-2.0/include/''
     ];
     ];
   }
   }
</syntaxHighlight>
</syntaxHighlight>


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.toml</code> lying in the same directory as the shell.nix.
Its purpose is to pin the version of the used Rust compiler.
Rust already has a standardized way of pinning a toolchain version for a workspace or a project.
<syntaxHighlight lang="shell-session">
See [https://rust-lang.github.io/rustup/overrides.html#the-toolchain-file the Rustup book] for its syntax.
$ cat rust-toolchain
 
nightly-2021-09-19
A minimal example of the <code>rust-toolchain.toml</code>:
</syntaxHighlight>
<syntaxhighlight lang="toml">
[toolchain]
channel = "stable" # This can also be "nightly" if you want a nightly rust
                  # or nightly-20XX-XX-XX for a specific nightly.
</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>
Line 89: Line 99:
== devenv.sh support ==
== devenv.sh support ==


# https://github.com/cachix/devenv/blob/main/examples/rust/devenv.nix and `devenv shell`
# https://github.com/cachix/devenv/blob/main/examples/rust/devenv.nix and <code>devenv shell</code>
 
== Rust Nightlies ==
 
# Use one of the overlays above,
# Or, use rustup


== Developing Rust projects using Nix ==
== Developing Rust projects using Nix ==
Line 100: Line 105:
The [https://nixos.org/manual/nixpkgs/stable/#rust Nixpkgs manual] uses <code>buildRustPackage</code>.
The [https://nixos.org/manual/nixpkgs/stable/#rust Nixpkgs manual] uses <code>buildRustPackage</code>.


[https://www.srid.ca/rust-nix This] blog post shows how to do it using <code>crate2nix</code>.
[https://srid.ca/rust-nix This] blog post shows how to do it using <code>dream2nix</code>. A template repo is available here: https://github.com/srid/rust-nix-template


== Using overrideAttrs with Rust Packages ==
== Using overrideAttrs with Rust Packages ==
Line 140: Line 145:
| Yes
| Yes
| Built into nixpkgs
| Built into nixpkgs
|-
| <code>carnix</code>
| Codegen
| Many
| <code>buildRustCrate</code>
| No?
| Unmaintained, AFAICT; [https://nest.pijul.com/pmeunier/carnix:master repository] is gone
|-
|-
| [https://github.com/kolloch/crate2nix <code>crate2nix</code>]
| [https://github.com/kolloch/crate2nix <code>crate2nix</code>]
Line 153: Line 151:
| <code>buildRustCrate</code>
| <code>buildRustCrate</code>
| [https://github.com/kolloch/crate2nix/commit/8bfeb42bda097e0bdf5452691a5e157aad3cc11f experimental]
| [https://github.com/kolloch/crate2nix/commit/8bfeb42bda097e0bdf5452691a5e157aad3cc11f experimental]
| Spiritual successor to carnix
| Spiritual successor to [https://github.com/nix-community/carnix <code>carnix</code>]
|-
|-
| [https://github.com/nmattia/naersk/ <code>naersk</code>]
| [https://github.com/nmattia/naersk/ <code>naersk</code>]
Line 159: Line 157:
| 2
| 2
| cargo
| cargo
| [https://github.com/nmattia/naersk/issues/79 No?]
| Yes
| [https://github.com/nmattia/naersk/blob/22b96210b2433228d42bce460f3befbdcfde7520/rust/rustc.nix#L22-L29 Seems to only support building on x86]
| [https://github.com/nmattia/naersk/blob/22b96210b2433228d42bce460f3befbdcfde7520/rust/rustc.nix#L22-L29 Seems to only support building on x86]
|-
|-
Line 227: Line 225:
     extensions = [
     extensions = [
       "rust-src" # for rust-analyzer
       "rust-src" # for rust-analyzer
      "rust-analyzer"
     ];
     ];
   };
   };
Line 234: Line 233:
     rust
     rust
   ] ++ (with pkgs; [
   ] ++ (with pkgs; [
    rust-analyzer
     pkg-config
     pkg-config
     # other dependencies
     # other dependencies
Line 248: Line 246:


You can use the [https://marketplace.visualstudio.com/items?itemName=arrterian.nix-env-selector arrterian.nix-env-selector] extension to enable your nix-shell inside VSCode and have these settings picked up by other extensions.
You can use the [https://marketplace.visualstudio.com/items?itemName=arrterian.nix-env-selector arrterian.nix-env-selector] extension to enable your nix-shell inside VSCode and have these settings picked up by other extensions.
=== Neovim Completion ===
Racer completion can be configured using the following snippet:
<syntaxHighlight lang="nix">
(neovim.override {
  configure = {
    customRC = ''
      if filereadable($HOME . "/.vimrc")
        source ~/.vimrc
      endif
      let $RUST_SRC_PATH = '${stdenv.mkDerivation {
        inherit (rustc) src;
        inherit (rustc.src) name;
        phases = ["unpackPhase" "installPhase"];
        installPhase = ''cp -r library $out'';
      }}'
    '';
    packages.nixbundle.start = with vimPlugins; [
      nvim-completion-manager
      nvim-cm-racer
    ];
  };
})
</syntaxHighlight>


== FAQ ==
== FAQ ==
Line 298: Line 270:
</syntaxHighlight>
</syntaxHighlight>


Note that you need to use a <code>nix-shell</code> environment. Installing the Nix packages <code>openssl</code> or <code>sqlite</code> globally under <code>systemPackages</code> in NixOS or in <code>nix-env</code> [https://nixos.wiki/wiki/FAQ/I_installed_a_library_but_my_compiler_is_not_finding_it._Why%3F is discouraged] and doesn't always work (<code>pkg-config</code> may not be able to locate the libraries).
Note that you need to use a <code>nix-shell</code> environment. Installing the Nix packages <code>openssl</code> or <code>sqlite</code> globally under <code>systemPackages</code> in NixOS or in <code>nix-env</code> [[FAQ/I installed a library but my compiler is not finding it. Why? | is discouraged]] and doesn't always work (<code>pkg-config</code> may not be able to locate the libraries).


=== Building with a different Rust version than the one in Nixpkgs ===
=== Building with a different Rust version than the one in Nixpkgs ===


The following uses the [https://github.com/nix-community/fenix fenix] overlay and <code>makeRustPlatform</code> to build a crate with Rust nightly:
The following uses the [https://github.com/nix-community/fenix fenix] overlay and <code>makeRustPlatform</code> to build a crate with Rust Nightly:


<syntaxHighlight lang="nix">
<syntaxHighlight lang="nix">
Line 331: Line 303:
</syntaxHighlight>
</syntaxHighlight>


=== Using LDD instead of LD ===
=== Using LLD instead of LD ===
 
If you want to use <code>lld</code>, then the correct way to do this is to use <code>pkgs.llvmPackages.bintools</code>, <em>not</em> <code>pkgs.lld</code>. This is because the former uses a wrapper script that correctly sets <code>rpath</code>. You can find more information about this [https://matklad.github.io/2022/03/14/rpath-or-why-lld-doesnt-work-on-nixos.html here].


If you want to use <code>ldd</code>, then the correct way to do this is to use <code>pkgs.llvmPackages.bintools</code>, <em>not</em> <code>pkgs.ldd</code>. This is because the former uses a wrapper script that correctly sets <code>rpath</code>. You can find more information about this [https://matklad.github.io/2022/03/14/rpath-or-why-lld-doesnt-work-on-nixos.html here].
[[Category:Languages]]
3

edits