Skip to content

Rust programming

Programming


Install and rustup

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  • rustup: toolchain manager
  • rustc: compiler
  • cargo: build & package manager
  • crate: smallest compilation unit in Rust (lib/bin)
  • crates.io: rust's official package registry
load rust into shell
source ~/.cargo/env

rust toolchain

A toolchain is a complete Rust environment consisting: - rustc - cargo - Rust standard library - optional components (clippy, rustfmt)

rustup

rustup manages Rust versions, targets, and components on your system.

autocomplete

Add rustup autocomplete

1
2
3
source <(rustup completions bash)
# add to bashrc
echo 'source <(rustup completions bash)' >> ~/.bashrc

update

update and upgrade toolchain and components

rustup update
# its like apt update + apt upgrade

Components

A component is an optional tool that plugs into a Rust toolchain.

  • rustfmt: Formatting
  • clippy: Linting
1
2
3
4
# add to active toolchain
rustup component add rustfmt
# for specific toolchain
rustup component add rustfmt --toolchain nightly

Hello world

Simple hello world build and run - Add aarch target and build it for ARM

cargo new hello_world
1
2
3
4
5
cargo run        # build + run
cargo build      # build only
cargo check      # fast compile check
cargo fmt        # format code
cargo clippy     # lint code

Add target (cross compile)

Cross compilation builds a binary for a different CPU or OS than the machine running cargo build.

Rust needs two things:

  • Rust target: standard library for the target platform.
  • Linker / C toolchain: only needed when the crate links C code, system libraries, or uses a target that needs an external linker.

Target name format:

<cpu>-<vendor>-<os>-<abi>

Common Linux targets:

Target Use case libc Static friendly
x86_64-unknown-linux-gnu normal Linux x86_64 glibc partial
aarch64-unknown-linux-gnu 64-bit ARM Linux glibc partial
x86_64-unknown-linux-musl portable Linux x86_64 musl yes
aarch64-unknown-linux-musl portable 64-bit ARM Linux musl yes

GNU target example: build for ARM64 Linux

GNU targets use glibc. The binary usually depends on shared libraries from the target system.

install rust target
rustup target add aarch64-unknown-linux-gnu
install cross compiler
sudo apt update
sudo apt install gcc-aarch64-linux-gnu
./.cargo/config.toml
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"
build with aarch target
cargo build --release --target aarch64-unknown-linux-gnu

The output binary will be here:

target/aarch64-unknown-linux-gnu/release/hello_world

Check the binary:

file target/aarch64-unknown-linux-gnu/release/hello_world

musl target: create static Linux binary

musl is an alternative C standard library.

Why use musl:

  • Produces mostly or fully static Linux binaries.
  • Easier to copy one executable to another Linux machine.
  • Good for containers, small deployments, and servers without matching glibc.

Install musl tools:

install musl compiler
sudo apt update
sudo apt install musl-tools

Add the Rust musl target:

x86_64 static binary target
rustup target add x86_64-unknown-linux-musl

Build:

build static binary
cargo build --release --target x86_64-unknown-linux-musl

Output:

target/x86_64-unknown-linux-musl/release/hello_world

Check if the binary is static:

file target/x86_64-unknown-linux-musl/release/hello_world
ldd target/x86_64-unknown-linux-musl/release/hello_world

For a static binary, ldd usually prints:

not a dynamic executable

ARM64 static binary with musl

For ARM64 Linux:

rustup target add aarch64-unknown-linux-musl

On Ubuntu/Debian, the native musl-tools package usually gives a musl compiler for the host architecture. For cross-compiling musl to ARM64, the easiest practical option is often cross, which builds inside a prepared container.

Install cross:

cargo install cross

Build:

cross build --release --target aarch64-unknown-linux-musl

Output:

target/aarch64-unknown-linux-musl/release/hello_world

Strip and reduce binary size

Strip debug symbols:

strip target/x86_64-unknown-linux-musl/release/hello_world

Or configure release builds in Cargo.toml:

Cargo.toml
1
2
3
4
5
[profile.release]
strip = true
lto = true
codegen-units = 1
panic = "abort"

Important notes

  • Pure Rust crates are easiest to cross compile.
  • Crates using C libraries may need matching target libraries and headers.
  • musl-tools is the musl compiler package on Ubuntu/Debian.
  • cross is usually simpler when building for another CPU architecture.
  • Use file and ldd to verify what kind of binary was produced.

Reference