Rust: Difference between revisions
imported>Proski m ldd -> lld (lld is a linker, ldd is a tool to list shared library dependencies) |
Phanirithvij (talk | contribs) m dream2nix update link |
||
(9 intermediate revisions by 7 users not shown) | |||
Line 5: | Line 5: | ||
# or with unofficial overlays on nixpkgs. | # or with unofficial overlays on nixpkgs. | ||
Installing via nixpkgs is the | 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 | 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 21: | Line 21: | ||
in pkgs.mkShell { | in pkgs.mkShell { | ||
buildInputs = [ pkgs.cargo pkgs.rustc ]; | buildInputs = [ pkgs.cargo pkgs.rustc ]; | ||
} | |||
</syntaxHighlight> | |||
== Installating with bindgen support == | |||
By default crates using <code>bindgen</code> will not compile. To add bindegen support add the <code>rustPlatform.bindegenHook</code> to your <code>nativeBuildInputs</code>. | |||
Here's an example <code>shell.nix</code>: | |||
<syntaxHighlight lang="nix"> | |||
{ pkgs ? import <nixpkgs> {} }: | |||
pkgs.mkShell { | |||
nativeBuildInputs = [ | |||
pkgs.cargo | |||
pkgs.rustc | |||
pkgs.rustPlatform.bindgenHook | |||
# optional: add pkg-config support | |||
pkgs.pkg-config | |||
]; | |||
buildInputs = [ | |||
# add desired native packages | |||
# ... | |||
]; | |||
# ... | |||
} | |||
</syntaxHighlight> | |||
This also works, when compiling rust crates: | |||
<syntaxHighlight lang="nix"> | |||
{ | |||
rustPlatform, | |||
pkg-config, | |||
... | |||
}: | |||
rustPlatform.buildRustPackage { | |||
# ... | |||
nativeBuildInputs = [ | |||
rustPlatform.bindgenHook | |||
pkg-config | |||
]; | |||
buildInputs = [ | |||
# add desired native packages | |||
# ... | |||
]; | |||
} | } | ||
</syntaxHighlight> | </syntaxHighlight> | ||
== Installation via rustup == | == Installation via rustup == | ||
The rustup tool is maintained by the Rust community and offers | 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 | 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 87: | ||
rustup | rustup | ||
]; | ]; | ||
RUSTC_VERSION = | 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 98: | ||
# 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 | 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 112: | ||
''-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. | ||
Rust already has a standardized way of pinning a toolchain version for a workspace or a project. | |||
< | See [https://rust-lang.github.io/rustup/overrides.html#the-toolchain-file the Rustup book] for its syntax. | ||
nightly- | A minimal example of the <code>rust-toolchain.toml</code>: | ||
</ | <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 143: | ||
== devenv.sh support == | == devenv.sh support == | ||
# https://github.com/cachix/devenv/blob/main/examples/rust/devenv.nix and | # https://github.com/cachix/devenv/blob/main/examples/rust/devenv.nix and <code>devenv shell</code> | ||
== Developing Rust projects using Nix == | == Developing Rust projects using Nix == | ||
Line 176: | Line 225: | ||
| Inspired by naersk, with [https://discourse.nixos.org/t/introducing-crane-composable-and-cacheable-builds-with-cargo/17275/4 better support for composing Cargo invocations as completely separate derivations] | | Inspired by naersk, with [https://discourse.nixos.org/t/introducing-crane-composable-and-cacheable-builds-with-cargo/17275/4 better support for composing Cargo invocations as completely separate derivations] | ||
|- | |- | ||
| [https:// | | [https://dream2nix.dev/reference/rust-crane <code>dream2nix</code>] | ||
| Codegen | | Codegen | ||
| 1 or 2 | | 1 or 2 | ||
| cargo (via <code>buildRustPackage</code> or <code>crane</code>) | | cargo (via <code>buildRustPackage</code> or <code>crane</code>) | ||
| Yes | | Yes | ||
| A framework for unifying 2nix converters across languages | | A framework for unifying 2nix converters across languages (Experimental) | ||
|} | |} | ||
Line 220: | Line 269: | ||
extensions = [ | extensions = [ | ||
"rust-src" # for rust-analyzer | "rust-src" # for rust-analyzer | ||
"rust-analyzer" | |||
]; | ]; | ||
}; | }; | ||
Line 227: | Line 277: | ||
rust | rust | ||
] ++ (with pkgs; [ | ] ++ (with pkgs; [ | ||
pkg-config | pkg-config | ||
# other dependencies | # other dependencies | ||
Line 241: | Line 290: | ||
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. | ||
== FAQ == | == FAQ == | ||
Line 291: | Line 314: | ||
</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> [ | 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 | 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"> |