I’ve been fiddling with cross compiling Rust to our ARM-64 platforms. I’m hitting a wall because Rust elfs require the system loader and C libs. I’m writing these notes to document what I’ve found so far. Would like to come back and discover how to build a static ARM-64 executable. Started here: https://github.com/japaric/rust-cross
Step 1. Install Rust. https://www.rust-lang.org/tools/install
Step2. Install a C cross compiler. Rust uses the C linker.
% sudo apt install gcc-aarch64-linux-gnu or % sudo dnf install gcc-aarch64-linux-gnu
Step 3. Add the cross compiler targets to Rust.
rustup target add aarch64-unknown-linux-gnu rustup target add aarch64-unknown-linux-musl
Step 4. Add to the cargo config
…marvin:hello-rust% cat ~/.cargo/config [target.aarch64-unknown-linux-gnu] linker = "aarch64-linux-gnu-gcc" [target.aarch64-unknown-linux-musl] linker = "aarch64-linux-gcc"
Step 5. Create a simple new project.
cargo new --bin hello
-rust
cd hello-rust
Step 6. Build
cross build --target aarch64-unknown-linux-gnu
Now examining the final executable, I’m finding it requires the glibc loader and libraries. We’re using uClibc because historical reasons.
% file ./target/aarch64-unknown-linux-gnu/debug/hello-rust ./target/aarch64-unknown-linux-gnu/debug/hello-rust: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=f62e92025124bc8018570c700b6e5faeecfdd671, for GNU/Linux 3.7.0, with debug_info, not stripped % readelf -a ./target/aarch64-unknown-linux-gnu/debug/hello-rust Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040 0x0000000000000230 0x0000000000000230 R 0x8 INTERP 0x0000000000000270 0x0000000000000270 0x0000000000000270 0x000000000000001b 0x000000000000001b R 0x1 [Requesting program interpreter: /lib/ld-linux-aarch64.so.1] [snip] Dynamic section at offset 0x3aac8 contains 30 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libdl.so.2] 0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0] 0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
I tried the Rust musl cross compiler but hit a wall with some compile errors around, I think, hard/soft floats. The musl cross compiler I found here: https://toolchains.bootlin.com/releases_aarch64.html
There are notes explaining musl can be static linked. https://github.com/japaric/rust-cross#how-do-i-compile-a-fully-statically-linked-rust-binaries
I should google those errors. Found:
https://github.com/rust-lang/rust/issues/46651
Looks like it might be fixed but not in a released Rust? Need to investigate further.
Update: Installed the nightly build and voila! static link musl elf.
% rustup toolchain install nightly % rustup default nightly-x86_64-unknown-linux-gnu % cross build --target aarch64-unknown-linux-musl % file ./target/aarch64-unknown-linux-musl/debug/hello-rust ./target/aarch64-unknown-linux-musl/debug/hello-rust: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, with debug_info, not stripped
Copied the resulting elf to my firmware. IT WORKS! It’s big, but it works.
/var/tmp # ls -l hello-rust -rwxr--r-- 1 root root 3878608 Oct 26 12:55 hello-rust* /var/tmp # ./hello-rust Hello, world!