Building for Raspberry from Windows 10

I just got my Raspberry Pi 3 and wanted to run simple Rust app on it, I understood from different resources that the command line to execute it, should be:

cargo +nightly build --target=armv7-unknown-linux-gnueabihf

But I got the below error:

Compiling semver-parser v0.7.0
Compiling void v1.0.2
Compiling rand_core v0.3.0
error[E0463]: can’t find crate for core
|
= note: the armv7-unknown-linux-gnueabihf target may not be installed

error: aborting due to previous error

For more information about this error, try rustc --explain E0463.
error: Could not compile void.
warning: build failed, waiting for other jobs to finish…
error[E0463]: can’t find crate for std
|
= note: the armv7-unknown-linux-gnueabihf target may not be installed

error: aborting due to previous error

For more information about this error, try rustc --explain E0463.
error: Could not compile rand_core.
warning: build failed, waiting for other jobs to finish…
error: build failed

The compiler is giving you a note/suggestion:

You'll want to read the rustup documentation page, specifically the section on managing targets:

https://rust-lang-nursery.github.io/edition-guide/rust-2018/rustup-for-managing-rust-versions.html#installing-other-targets

P.s. is there a guide you are following? I'd like to have a look at it, because I am surprised you could discover the (detailed, very specific) information which target you need, but not the (very general) information how to install that target.

I run:

rustup target add armv7-unknown-linux-gnueabihf

But got the below new error regarding linker:

PS D:\rocket4_prv> cargo build --target=armv7-unknown-linux-gnueabihf
Compiling rocket4_prv v0.1.0 (file:///D:/rocket4_prv)
error: linker cc not found
|
= note: The system cannot find the file specified. (os error 2)

error: aborting due to previous error

The references I read before starting are: this for iOS and this for raspberry

Rust is unable to create executables or dynamic libraries itself. The compiler can only build static libraries, and then needs help of a linker — not included with Rust — to finish creating the executable.

This means you need to somehow find ARM-compatible linker for Windows, and most likely Linux system libraries for that linker to link to. Rust doesn’t come with these. I don’t know where to get these for Windows. People usually give up and switch to a Linux VM :slight_smile: I know Debian has packages for cross-linker for ARM.

Another option is to test and develop on another machine for speed, but compile the final executable on RPI itself, natively. It takes ages to compile of course, but I’ve tried it and it works.

2 Likes

There seem to be instructions for doing cross-compiling for Raspberry Pi on Windows here:

If you’re running Windows 10, you may be able to skip the Vagrant step and use Windows Subsystem for Linux instead.

Key point is that you’ll probably need to build from a Linux environment (be it a VM, or WSL), using a cross-compiler for ARM.

2 Likes

Thanks.
As I’m new to linux, and may be others will face the same issue, I’m detailing below the steps had been taken.

I added Ubunto to Win 10 as below:

In the powershel I wrote:
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

Then installed Ubuntu from Win 10 store

Then installed rust using the shell command:
curl https://sh.rustup.rs -sSf | sh

The I added the Raspberry target by:
rustup target add armv7-unknown-linux-gnueabihf

Initially I got the below error to install the gcc:

Failed to fetch http://security.ubuntu.com/ubuntu/pool/main/l/linux/linux-libc-dev_4.15.0-29.31_amd64.deb

So, I solved it as explained here by writting the below commands:

sudo -i
apt-get clean
cd /var/lib/apt
mv lists lists.old
mkdir -p lists/partial
apt-get clean
apt-get update

Then installed gcc as explained here, to be in the safe side I installed build-essential as below:
sudo apt install build-essential

Then created the app, from the linux shell:
cd …/…
cd mnt
ls
cd d
cargo new raspberry

Opened the folder from Windows, using Atom as I like the rsl

Then back to the ubuntu shell and compiled it as:

cargo build --target=armv7-unknown-linux-gnueabihf

But I got an error about the linker

Once I tried;
sudo apt-get install gcc-4.7-multilib-arm-linux-gnueabihf

I got the below:

Reading package lists… Done
Building dependency tree
Reading state information… Done
E: Unable to locate package gcc-4.7-multilib-arm-linux-gnueabihf
E: Couldn’t find any package by glob ‘gcc-4.7-multilib-arm-linux-gnueabihf’
E: Couldn’t find any package by regex ‘gcc-4.7-multilib-arm-linux-gnueabihf’

The error I got about the linker is:

error: linking with cc failed: exit code: 1
|
= note: “cc” “-Wl,–as-needed” “-Wl,-z,noexecstack” “-L” “/home/hyousef/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/armv7-unknown-linux-gnueabihf/lib” “/mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.12xnp4ar90c67nbz.rcgu.o” “/mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.1glupf3n1lagubns.rcgu.o” “/mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.2qs9zrklyufaiuv7.rcgu.o” “/mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.3sw26n6mxwu6t82q.rcgu.o” “/mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.3ul3359qbyljmdnk.rcgu.o” “/mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.5ctyx3l4x1507duc.rcgu.o” “-o” “/mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5” “/mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.2ics1nl8sd2hfdfe.rcgu.o” “-Wl,–gc-sections” “-pie” “-Wl,-zrelro” “-Wl,-znow” “-nodefaultlibs” “-L” “/mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps” “-L” “/mnt/d/raspberry/target/debug/deps” “-L” “/home/hyousef/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/armv7-unknown-linux-gnueabihf/lib” “-Wl,–start-group” “-Wl,-Bstatic” “/home/hyousef/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libstd-26790dce90d0fe6d.rlib” “/home/hyousef/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libpanic_unwind-a5cee6db9acbf011.rlib” “/home/hyousef/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/liballoc_jemalloc-9840acadca9bde9c.rlib” “/home/hyousef/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libunwind-39e43f615b6f2306.rlib” “/home/hyousef/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/liballoc_system-25d597b777206248.rlib” “/home/hyousef/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/liblibc-606804d39647c276.rlib” “/home/hyousef/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/liballoc-3f0e239bf2ed5cd4.rlib” “/home/hyousef/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libcore-62177162265c5821.rlib” “-Wl,–end-group” “/home/hyousef/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libcompiler_builtins-f946e458612ced9a.rlib” “-Wl,-Bdynamic” “-ldl” “-lrt” “-lpthread” “-lpthread” “-lgcc_s” “-lc” “-lm” “-lrt” “-lpthread” “-lutil” “-lutil”
= note: /usr/bin/ld: /mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.12xnp4ar90c67nbz.rcgu.o: Relocations in generic ELF (EM: 40)
/usr/bin/ld: /mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.12xnp4ar90c67nbz.rcgu.o: Relocations in generic ELF (EM: 40)
/usr/bin/ld: /mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.12xnp4ar90c67nbz.rcgu.o: Relocations in generic ELF (EM: 40)
/usr/bin/ld: /mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.12xnp4ar90c67nbz.rcgu.o: Relocations in generic ELF (EM: 40)
/usr/bin/ld: /mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.12xnp4ar90c67nbz.rcgu.o: Relocations in generic ELF (EM: 40)
/usr/bin/ld: /mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.12xnp4ar90c67nbz.rcgu.o: Relocations in generic ELF (EM: 40)
/usr/bin/ld: /mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.12xnp4ar90c67nbz.rcgu.o: Relocations in generic ELF (EM: 40)
/usr/bin/ld: /mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.12xnp4ar90c67nbz.rcgu.o: Relocations in generic ELF (EM: 40)
/usr/bin/ld: /mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.12xnp4ar90c67nbz.rcgu.o: Relocations in generic ELF (EM: 40)
/usr/bin/ld: /mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.12xnp4ar90c67nbz.rcgu.o: Relocations in generic ELF (EM: 40)
/mnt/d/raspberry/target/armv7-unknown-linux-gnueabihf/debug/deps/raspberry-480844df3cc933d5.12xnp4ar90c67nbz.rcgu.o: error adding symbols: File in wrong format
collect2: error: ld returned 1 exit status

error: aborting due to previous error

error: Could not compile raspberry.

To learn more, run the command again with --verbose.

1 Like

gcc version 4.7 is super old, so your apt source probably only has a newer version. Find what version you have with apt-cache search multilib.

You also must edit .cargo/config and set the path to the linker there. Without config file Cargo will use native (incompatible) linker.

Thanks, I found he below:
gcc-8-multilib-arm-linux-gnueabihf - GNU C compiler (multilib support)

I’m running Ubuntu shell from Win 10, how can I edit this file, how can I open it from Win 10!

I don’t know Windows. You can install nano and edit the file with it from Linux :slight_smile:

Just found it here, and added the below to the .cargo/config:

[target.armv7-unknown-linux-gnueabihf]
linker = "gcc-8-multilib-arm-linux-gnueabihf"

But got the below:

hyousef@DESKTOP-KPD1Q5Q:/mnt/d/raspberry$ cargo build --target=armv7-unknown-linux-gnueabihf
Compiling raspberry v0.1.0 (/mnt/d/raspberry)
error: linker arm-linux-gnueabihf-gcc-8 not found
|
= note: No such file or directory (os error 2)

error: aborting due to previous error

error: Could not compile raspberry.

To learn more, run the command again with --verbose.

It’s odd, the error doesn’t match what the config says. Are you sure you don’t have another config file somewhere else?

Here cargo expects to be able to run a command called arm-linux-gnueabihf-gcc-8. Your config file says it should be running a command called gcc-8-multilib-arm-linux-gnueabihf.

The path I've is below, and I modified the content to be:

[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc-8"

and got the below error:

hyousef@DESKTOP-KPD1Q5Q:/mnt/d/raspberry$ cargo build --target=armv7-unknown-linux-gnueabihf
Compiling raspberry v0.1.0 (/mnt/d/raspberry)
error: linker arm-linux-gnueabihf-gcc-8 not found
|
= note: No such file or directory (os error 2)

error: aborting due to previous error

error: Could not compile raspberry.

To learn more, run the command again with --verbose.

But do you have this command? Does running arm-linux-gnueabihf-gcc-8 in terminal run this command, or show an error that there’s no such command?

The one you specify in cargo config must be a real command in your PATH that you can run in terminal.

It looks it is not :frowning:

I’m trying now installing Ubunto 16.04 shell, as it looks gcc-4.8 is supported there, and not yet supporting Ubuntu 18.04 shell that I installed, will do the process from zero again with this shell and see what could I got :slight_smile:

hyousef@DESKTOP-KPD1Q5Q:/mnt/d/raspberry$ arm-linux-gnueabihf-gcc-8

Command ‘arm-linux-gnueabihf-gcc-8’ not found, but can be installed with:

sudo apt install gcc-8-arm-linux-gnueabihf

hyousef@DESKTOP-KPD1Q5Q:/mnt/d/raspberry$ sudo apt install arm-linux-gnueabihf-gcc-8
[sudo] password for hyousef:
Reading package lists… Done
Building dependency tree
Reading state information… Done
E: Unable to locate package arm-linux-gnueabihf-gcc-8
hyousef@DESKTOP-KPD1Q5Q:/mnt/d/raspberry$

apt doesn’t install commands by name, but packages that contain (possibly many) commands. In your case commands and packages will have different names. Use apt-cache search command-here to find which package has this command.

Also you seem to be mixing names of packages/commands, and instructions for different versions of Ubuntu or different operating systems. It should work on either one, but you have to use right ones for your specific version of your OS. If your OS has gcc-4.7, then use commands for gcc-4.7. If your OS has gcc-8, then you can’t copy verbatim instructions for gcc-4.7.

As it took so much time and effort from me to get this issue solved, I'd like to share my solution below with the community.

Before starting, you need to enable WSL (Windows Subsystem for Linux), so in the powershel I wrote:
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

  1. Install ubuntu-1604-lts shell, run it and create user name and password
  2. Run ~$ sudo apt-get update
  3. Install Rust by running: ~$ curl https://sh.rustup.rs -sSf | sh
  4. Add the env to path by running ~$ source $HOME/.cargo/env or by restarting the shell
  5. Confirm rust installation, by running ~$ rustc -V, [If you are interetsed in adding the nightly edition, it can be installed by running rustup install nightly]
  6. Add the Rasbperry target: ~$ rustup target add armv7-unknown-linux-gnueabihf
  7. Install the linker gcc-4.8-multilib-arm-linux-gnueabihf by running: ~$ sudo apt-get install gcc-4.8-multilib-arm-linux-gnueabihf [for Ubuntu 18.04, you can install gcc-8 using command ~$ sudo apt-get install gcc-8-multilib-arm-linux-gnueabihf]
  8. Create the ~/.cargo/config by going to ~$ cd ~/.cargo then run ~,cargo$ cat > config then ^z, the file will be created and saved [note: I tried using touch but the file created was having lack of permissions], the created file can be opened from the following path in Windows explorer:
    C:\Users\ [user - WindowsUser] \AppData \Local \Packages \CanonicalGroupLimited.Ubuntu16.04onWindows_79rhkp1fndgsc \LocalState \rootfs \home \[user - LinuxUser]\.cargo
    r

[Important: from time to time I was getting an error messege about the permission of ~/.cargo/config, so I kept fixing it by: ~/.cargo$ chmod +rw config]
09. Write the below in the ~/.cargo/config:
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc-4.8"
// If you installer gcc-8, then the linker should be: linker = "arm-linux-gnueabihf-gcc-8"]
10. In the shell go the folder you need to create your app, by ~$ cd ../.. then ~$ cd mnt by running ~$ ls you can se your folders c, d, ..., so you can go for the location you want.
11. Create your new rust app ~$ cargo new raspberry
12. Get inside the root of the app: ~$ cd raspberry
13. Build the executable file: ~$ cargo build --target=armv7-unknown-linux-gnueabihf
14. Edit your app folder in Windows using atom ide with rust package
15. Minimize the file size by adding #[global_allocator] so your main.rs became like:

    use std::alloc::System;

    #[global_allocator]
    static A: System = System;

    fn main() {
        println!("Hello, world!");
    }
  1. Minimize the executable file size by adding opt-level to the Cargo.toml so it became like:
    [package]
    name = "raspberry"
    version = "0.1.0"
    authors = ["hyousef"]

    # The release profile, used for `cargo build --release`.
    [profile.release]
    opt-level = 'z'  # Optimize for size.
    lto = true       # Enable Link Time Optimization
    panic = 'abort'  # Abort on panic

    [dependencies]

17.Build the release executable file as: ~$ cargo build --target=armv7-unknown-linux-gnueabihf --release
18. Strip the build executable by: ~$ strip target\armv7-unknown-linux-gnueabihf/release/raspberry
19. Check the final executable file by running: ~$ ls -S -lh | awk '{print $5, $9}'
20. The finale size had been is 862K (optimized from 4.5M), for furthure size optimizaation see this

4 Likes

I’m glad that you got it working in the end, and thank you for posting the complete steps you ended up using! I’m sure this will help others in the future! :heart:

1 Like

I’m not sure why I keep getting permission issue for the ~/.cargo/config from time to time!!:

hyousef@DESKTOP-KPD1Q5Q:/mnt/d/raspberry$ cargo build --target=armv7-unknown-linux-gnueabihf
error: could not load Cargo configuration

Caused by:
Permission denied (os error 13)

> hyousef@DESKTOP-KPD1Q5Q:~/.cargo$ ls -la
> total 0
> drwxrwxrwx 1 hyousef hyousef 512 Oct 29 19:33 .
> drwxr-xr-x 1 hyousef hyousef 512 Oct 29 21:19 ..
> drwxrwxrwx 1 hyousef hyousef 512 Oct 29 18:29 bin
> ---------- 1 hyousef hyousef  78 Oct 29 19:10 config
> -rw-rw-rw- 1 hyousef hyousef  37 Oct 29 18:47 env
> drwxrwxrwx 1 hyousef hyousef 512 Oct 29 19:34 registry

So, I keep fixing it by:
hyousef@DESKTOP-KPD1Q5Q:~/.cargo$ chmod +rw config

Today I found a better solution, when the toolchain can be installed using rustup and without the need of wsl following the below sequence of comands:

// Add target
PS C:\Users\Hasan Yousef> rustup target add armv7-unknown-linux-gnueabihf
// Install toolchain
PS C:\Users\Hasan Yousef> rustup toolchain install stable-armv7-unknown-linux-gnueabihf
// Create new project - if required
PS D:\> cargo new rb_101
// Navigae to the Raspberry Pi project folder
PS D:\> cd rb_101
// Set the toolchain of this foldr
PS D:\rb_101> rustup override set stable-armv7-unknown-linux-gnueabihf
// Confirm active toolchain had been set correctly
PS D:\rb_101> rustup show
// If you found you navigated to wrong folder, and need to fix the toolchain, use:
PS D:\rb_101> rustup override unset

2 Likes