Skip to content

Instantly share code, notes, and snippets.

@alekseysidorov
Created January 28, 2023 11:24
Rust cross-compilation shell based on Nix Package Manager
# A standalone nix shell file to setup Rust cross-compilation toolchain.
#
# This file does not have any additional dependencies and is completely self-sufficient.
# You can use the `nix-shell` command and get the working cross-compilation toolchain.
# By default, it produces completely static binaries, which can be placed into the
# Alpine Linux container as is.
#
# # Usage:
#
# `nix-shell ./shell-rust-cross.nix`
#
# # Tips:
#
# - You can attach a binary cache by running the command `nix-shell -p cachix --run "cachix use nixpkgs-cross-overlay"`
# - If you have compilation issues, try to add `--pure` argument to the `nix-shell`.
{ localSystem ? builtins.currentSystem
# Default cross-compilation configuration, you may override it by passing the
# `--arg crossSystem '<our-own-config>'` to `nix-shell`.
, crossSystem ? { config = "x86_64-unknown-linux-musl"; isStatic = true; useLLVM = true; }
# Override nixpkgs-cross-overlay branch
, branch ? "main"
}:
let
# Fetch the latest nixpkgs snapshot.
src = builtins.fetchTarball "channel:nixpkgs-unstable";
# Setup local Nix packages to get the `mkCrossPkgs` function.
localPkgs = (import src {
config = {
inherit localSystem;
};
overlays = [
# Fetch the latest nixpkgs-cross-overlay snapshot.
(import
(builtins.fetchTarball "http://github.com/alekseysidorov/nixpkgs-cross-overlay/tarball/${branch}")
)
];
});
# Make cross system packages.
pkgs = localPkgs.mkCrossPkgs {
inherit src localSystem crossSystem;
overlays = [
# Fetch the latest rust-overlay snapshot.
(import
(builtins.fetchTarball "http://github.com/oxalica/rust-overlay/tarball/master")
)
# Setup Rust toolchain.
(final: prev:
{
rustToolchain = prev.rust-bin.stable.latest.default;
}
)
# <- You may add your extra overlays here.
];
};
in
# And now, with the resulting packages, we can describe the cross-compilation shell.
pkgs.mkShell {
# Native project dependencies like build utilities and additional routines
# like container building, linters, etc.
nativeBuildInputs = with pkgs.pkgsBuildHost; [
pkg-config
git
cmake
perl
python3
# Comment this line if you want to use an external Rust toolchain.
rustToolchain
# Will add some dependencies like libiconv.
rustBuildHostDependencies
];
# Libraries essential to build the service binaries.
buildInputs = with pkgs; [
# Enable cross-compilation mode in Rust.
rustCrossHook
# Add crate dependencies.
cargoDeps.rocksdb-sys
cargoDeps.rdkafka-sys
# Some native libraries.
openssl.dev
];
# Prettify shell prompt.
shellHook = "${pkgs.crossBashPrompt}";
}
@alekseysidorov
Copy link
Author

Example usage

# Enter cross-shell
nix-shell shell-rust-cross.nix
# Clone and build example
git clone https://github.com/alekseysidorov/nixpkgs-rust-service-example.git
cd nixpkgs-rust-service-example
cargo build
# Make sure that the resulting binary is ELF and doesn't contain dynamic dependencies.
nix-shell -p binutils --run "readelf -d ./target/x86_64-unknown-linux-musl/debug/axum_example_service"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment