Un vecchio ritrovamento
Ho ritrovato un vecchio cubieboard3 (cubietruck) che accumulava polvere in un cassetto, quindi ho colto l’occasione per provare la cross-compilazione con Rust e raccogliere qui alcune note sul processo. Eccolo qui:

Diamogli un pinguino
Prima di tutto, ho installato una distribuzione Linux ARM su una scheda MicroSD e ho avviato il dispositivo:
[user@arm ~]$ cat /proc/cpuinfo
processor : 0
model name : ARMv7 Processor rev 4 (v7l)
BogoMIPS : 50.52
Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xc07
CPU revision : 4
processor : 1
model name : ARMv7 Processor rev 4 (v7l)
BogoMIPS : 50.52
Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xc07
CPU revision : 4
Hardware : Allwinner sun7i (A20) Family
Revision : 0000
Quindi il nostro dispositivo ha una CPU ARM modello v7l; questo significa che si tratta di una CPU a 32 bit, e se siete curiosi esiste anche un manuale di riferimento in circolazione. Ora lavoreremo da una macchina di sviluppo.
Diventiamo "Rustici"
Controlliamo il supporto a Rust:
[x86]$ rustup target list | grep armv7
armv7-linux-androideabi
armv7-unknown-linux-gnueabi
armv7-unknown-linux-gnueabihf
armv7-unknown-linux-musleabi
armv7-unknown-linux-musleabihf
armv7a-none-eabi
armv7r-none-eabi
armv7r-none-eabihf
Un sacco di opzioni! Per ora lascerei da parte le varianti Android e Musl.
[x86]$ cargo init tryarm
Created binary (application) package
[x86]$ cd tryarm
[x86]$ cargo build --target armv7-unknown-linux-gnueabihf
error: could not compile `tryarm` (bin "tryarm") due to 1 previous error
Riprovare, per favore
Sembra non essere sufficiente… Proviamo lo strumento cross del team Rust Embedded:
[x86]$ cargo install cross
[x86]$ /home/andrea/.cargo/bin/cross build --target armv7-unknown-linux-gnueabihf
Trying to pull ghcr.io/cross-rs/armv7-unknown-linux-gnueabihf:0.2.5...
Getting image source signatures
Copying blob 5b4afa60d436 [===============================>------] 146.3MiB / 172.0MiB | 6.6 M
Copying blob 5b4afa60d436 done |
Copying blob 58690f9b18fc done |
Copying blob da8ef40b9eca done |
Copying blob b51569e7c507 done |
Copying blob 6c052f8b0b21 done |
Copying blob fb15d46c38dc done |
Copying blob 5afa4c181482 done |
Copying blob b9d42a766612 done |
Copying blob cc716323c93e done |
Copying blob fe4038eab07b done |
Copying blob 4accd797f995 done |
Copying blob 3db4794ce9a5 done |
Copying blob 8b1f228d2fc0 done |
Copying blob 05f315b1fff9 done |
Copying blob c0190749220c done |
Copying blob 55483985fe64 done |
Copying blob df8b7a9f8281 done |
Copying blob 9de25b0c2608 done |
Copying config 32cf786140 done |
Writing manifest to image destination
Compiling tryarm v0.1.0 (/project)
Finished dev [unoptimized + debuginfo] target(s) in 0.26s
Questo strumento scarica un container con la corretta toolchain del compilatore e lo usa per compilare il progetto. Sembra che il nostro programma sia pronto e compilato!
[x86]$ file target/armv7-unknown-linux-gnueabihf/debug/tryarm
target/armv7-unknown-linux-gnueabihf/debug/tryarm: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=7ff3fc41deb8b4820cc64ff2857cddbfa577111c, with debug_info, not stripped
[x86]$ objdump -d target/armv7-unknown-linux-gnueabihf/debug/tryarm
3428: e59d300c ldr r3, [sp, #12]
342c: e0802080 add r2, r0, r0, lsl #1
3430: e08b108b add r1, fp, fp, lsl #1
3434: e1a09003 mov r9, r3
3438: e1a00003 mov r0, r3
343c: e7b91181 ldr r1, [r9, r1, lsl #3]!
3440: e7b02182 ldr r2, [r0, r2, lsl #3]!
3444: e5993004 ldr r3, [r9, #4]
3448: e5904004 ldr r4, [r0, #4]
344c: e0521001 subs r1, r2, r1
3450: e0d41003 sbcs r1, r4, r3
Corri, piccolo, corri
Quindi, trasferiamo il nostro binario sul dispositivo ed eseguiamolo:
[x86]$ scp target/armv7-unknown-linux-gnueabihf/debug/tryarm user@cubietruck:/home/user
user@cubietruck's password:
tryarm 100% 3443KB 5.3MB/s 00:00
Passando alla shell del dispositivo:
[user@arm ~]$ ./tryarm
Hello, world!
[user@arm ~]$ ldd tryarm
linux-vdso.so.1 (0xbefbd000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0xb6e40000)
librt.so.1 => /usr/lib/librt.so.1 (0xb6e20000)
libpthread.so.0 => /usr/lib/libpthread.so.0 (0xb6e00000)
libdl.so.2 => /usr/lib/libdl.so.2 (0xb6de0000)
libc.so.6 => /usr/lib/libc.so.6 (0xb6c40000)
/lib/ld-linux-armhf.so.3 => /usr/lib/ld-linux-armhf.so.3 (0xb6eda000)
Funziona! 😄
Il futuro ci attende
Siamo in grado di compilare ed eseguire codice Rust sul nostro piccolo dispositivo, quindi questa Proof of Concept (PoC) è conclusa. In futuro lo useremo per sviluppare e testare software su un’architettura diversa.
Alcune risorse per approfondire: