Cross-compiling Rust from Windows to ARM Linux - windows

I'm using Windows 10. I would like to cross-compile a Rust program to run on armv7-unknown-linux-gnueabihf. (armv7-unknown-linux-muscl would also be acceptable but it doesn't seem to be available.)
Here are my steps:
Install rustup
rustup toolchain install stable-x86_64-pc-windows-gnu
rustup toolchain default stable-x86_64-pc-windows-gnu
rustup target add armv7-unknown-linux-gnueabihf
Edit my ./cargo/config file to contain:
[build]
target = "armv7-unknown-linux-gnueabihf"
cargo build
This compiles everything fine, but when it comes to linking it gives this error:
error: could not exec the linker `cc`: The system cannot find the file specified. (os error 2)
As far as I have been able to determine, this is because Rust doesn't have its own linker and uses GCC instead. Apparently I need to provide this myself and add this to the ./cargo/config file:
[target.armv7-unknown-linux-gnueabihf]
linker = "c:/path/to/my/gcc/cross/compiler"
Is that right? If so where on Earth can I download such a cross-compiler for Windows and why doesn't rustup install it? Having to compile a cross-compiling version of GCC yourself is the biggest pain of cross-compiling C/C++ programs. Does Rustup really not make this any easier?

Thanks to #Notlikethat's comment:
a) Yes you need to provide your own GCC cross-compiler.
b) You can get one here (select a mingw32 build).
Just unzip linaro's GCC then point cargo to it:
[target.armv7-unknown-linux-gnueabihf]
linker = "C:/Users/me/gcc-linaro-5.3.1-2016.05-i686-mingw32_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc.exe"
It seems to work even though it is arm- and not armv7-. I guess linking doesn't depend on the ISA. Actually I haven't run it yet, but it builds without errors!
Edit:
You can now use armv7-unknown-linux-musleabihf instead and get an actually portable binary (i.e. it doesn't depend on the GNU C library which often causes compatibility issues).

For MacOS better use: musleabihf, for Windows you can use gnueabihf as bellow:
Mac
$ brew install arm-linux-gnueabihf-binutils
$ rustup target add armv7-unknown-linux-musleabihf
In .cargo/config
[build]
target = "armv7-unknown-linux-musleabihf"
[target.armv7-unknown-linux-c]
linker = "arm-linux-gnueabihf-ld"
With simple src/main.rs
fn main() {
println!("Hello, Raspberry!");
}
Then things are fine:
Hasans-Air:rpi hasan$ cargo build
Compiling rpi v0.1.0 (/Users/hasan/PycharmProjects/rpi)
Finished dev [unoptimized + debuginfo] target(s) in 0.41s
Hasans-Air:rpi hasan$ scp target/armv7-unknown-linux-musleabihf/debug/rpi pi#192.168.1.43:
pi#192.168.1.43's password:
rpi 100% 2702KB 2.6MB/s 00:01
Hasans-Air:rpi hasan$ ssh pi#192.168.1.43 'chmod +x ~/rpi && ~/rpi'
pi#192.168.1.43's password:
Hello, Raspberry!
Win 10
Get the linker from here, and run:
rustup target add armv7-unknown-linux-gnueabihf
Creating file .cargo/config with content:
[build]
target = "armv7-unknown-linux-gnueabihf"
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
And with simple src/main.rs:
fn main() {
println!("Hello, Raspberry! from Win 10");
}
I was able to get things done

Related

Compile a Rust program to an exe using an M1 mac?

I have written a program in Rust on my M1 Mac, and compiled it to a Unix executable just fine. Now I want to compile it to a Windows executable as well. I first tried
$ cargo target add x86_64-pc-windows-gnu
$ cargo build --release --target=x86_64-pc-windows-gnu
I got the error message:
error: linker x86_64-w64-mingw32-gcc not found
so I tried
$ brew install mingw-w64
according to this, and got the error:
Error: mingw-w64: no bottle available!
I looked on formulae.brew.sh and it seems that mingw-w64 isn't supported for M1, only Intel.
How can I compile an exe from rust using my M1 Mac?
Solution 1:
You can install/add the targets using these commands :
rustup target add x86_64-pc-windows-gnu
rustup toolchain install stable-x86_64-pc-windows-gnu
then you can target windows from your mac:
cargo build --release --target=x86_64-pc-windows-gnu
Solution 2:
Simply use docker!
FROM mcr.microsoft.com/windows/servercore:ltsc2019
// install rust
COPY project c:/project
RUN cd c:/project && cargo build --release
Solution 3:
there is also Cross. you can use this for cross-compilation:
https://github.com/rust-embedded/cross
I'm going to jump in with a couple newer solutions that worked really well for me:
cargo-zigbuild
Targets (*-pc-windows-gnu afaik):
i686-pc-windows-gnu
x86_64-pc-windows-gnu
cargo-zigbuild also supports cross-compiling to other platforms out of the box as well, with no containerization needed!
Quick example:
brew install zig
cargo install cargo-zigbuild
cargo zigbuild --target x86_64-pc-windows-gnu -r
cargo-xwin
Targets (*-msvc afaik):
aarch64-pc-windows-msvc
i586-pc-windows-msvc
i686-pc-windows-msvc
x86_64-pc-windows-msvc
Quick example:
cargo install cargo-xwin
cargo xwin build --target x86_64-pc-windows-msvc -r
Which one do I pick?
See: Difference between the gnu and msvc toolchains?
TL;DR: Use msvc/cargo-xwin for "more native" windows binaries (that are smaller in size) & use gnu/cargo-zigbuild to help porting over a linux-specific application.

Go/Golang Cross-Compile from Mac to Windows: fatal error: 'windows.h' file not found

Summary: when I try cross-compiling a .go source file that includes a C file somewhere in the file chain, targeting Windows AMD64 from a Mac host, I get:
/usr/local/go/src/runtime/cgo/gcc_windows_amd64.c:8:10: fatal error: 'windows.h' file not found
Purely Go code seems to cross compile without error; is there a way to get the proper header files for cross compilation when C files are involved?
More details: I installed LiteIDE on my Mac for working on some .go projects, and LiteIDE makes it relatively simple to target other platforms as build targets. I tested it on a small test project I had, purely Go, and it seemed to run without error.
Later I tried it on a current, larger project and had to adjust several env settings in the IDE to get it to work (complaints about C files without CGO enabled, and GOPATH not set properly even though it's set in .bash_profile and verified in echo $VARIABLE just fine.) The result is
/usr/local/go/src/runtime/cgo/gcc_windows_amd64.c:8:10: fatal error: 'windows.h' file not found
Trying to target Linux (os linux, arch amd64) gives
# runtime/cgo
ld: unknown option: --build-id=none
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I've double checked I have XCode installed; gcc is installed:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr with-gxx-include- dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/c++/4.2.1
Apple LLVM version 7.3.0 (clang-703.0.29)
Target: x86_64-apple-darwin15.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
...and Go is the latest version:
go version go1.6.2 darwin/amd64
I also checked that this isn't just from LiteIDE (since LiteIDE seems to override env settings and ignore what's in the terminal?); an example attempt at the console gives:
MyUsername$ env GOOS=windows GOARCH=amd64 CGO_ENABLED=1 go build -v
golang.org/x/net/html/atom
runtime/cgo
golang.org/x/crypto/ssh/terminal
golang.org/x/net/html
github.com/howeyc/gopass
# runtime/cgo
/usr/local/go/src/runtime/cgo/gcc_windows_amd64.c:8:10: fatal error: 'windows.h' file not found
github.com/andybalholm/cascadia
github.com/PuerkitoBio/goquery
I suspect this is because the application uses networking libraries in Go and I think the native libraries are still calling some C files to fill in gaps. Is there a way to get the proper libraries for building on Linux/Windows or does this need to be done on the target platforms in order to work?
Building native applications on the host platform seems to work without issue.
To enable cross-compiling for CGO you need to have a local toolchain that can compile C code for that target.
I'm not very familiar with Mac OS X, but on Arch Linux all I had to do was install mingw-w64-toolchain and compile my go code with:
env GOOS="windows" GOARCH="386" CGO_ENABLED="1" CC="i686-w64-mingw32-gcc" go build
// or to target win 64
env GOOS="windows" GOARCH="amd64" CGO_ENABLED="1" CC="x86_64-w64-mingw32-gcc" go build
On OSX, you can install mingw with homebrew: brew install mingw-w64
About the other error message though, ld: unknown option: --build-id=none seems like a bug, you might want to report that on the Go issue tracker.

GCC /clang not present on BSD, and unable to install it

I have a freebsd 8.4 machine. I want to use to use pyinstaller to create a binary for freebsd. However it looks like pyinstaller does not support freebsd by default so i have to go in the bootloader and create stuff specific to the target system.
This is giving me errors that gcc/cc is not found on the system. Here is the first error message
Platform : FreeBSD-64bit detected
Checking for 'gcc' (C compiler) : not found
Checking for 'clang' (C compiler) : not found
So then i try to install gcc via ports. I do this
cd /usr/ports/lang/gcc49
make install
It fails :
checking whether the C compiler works... no
So i checked in the file system and there is no gcc or clang or cc. It only has ccache. Here are the details from /usr/bin
CC -> /usr/local/bin/ccache
gcc -> /usr/local/bin/ccache
There is nothing in /usr/local/bin (either CC or GCC)
so if i just do gcc at the command line i get this :
ccache: FATAL: Could not find compiler "gcc" in PATH
how do i fix this. This thing is driving me nuts. pkg install is also not working with error "No repositories found "
On FreeBSD 8.4 the standard compiler is gcc (4.2), and it's located in /usr/bin. It has to be there.
It seems that ccache installation created some problem removing/overwriting something. ccache package installs compiler links in /usr/local/libexec/ccache, but if you installed it manually I'm not sure what happened.
FreeBSD 8.4 is not maintained anymore and there's no package repository anymore for it.
My suggestion is to update your system to FreeBSD 10.2 and use clang, that's the new standard compiler.

How to override default linker compiling with configure?

I need to install a package (ROOT) from source on OSX using GCC 4.7.3 as a compiler. Default compiler on OSX is clang, so I look to configure command options to change it. I see that I can change it:
with compiler options, prefix with --with-, overrides default value
cc alternative C compiler and options to be used
cxx alternative C++ compiler and options to be used
But when I run:
./configure --with-cxx=g++ --with-cc=gcc
I see:
Checking for C compiler ... gcc
Checking for C++ compiler ... g++
Checking for linker (LD) ... clang++
So it trying to compile with gcc and link with clang, this obviously leads to failure. But I can't find an option in configure how to change linker used by make.
Is there a default options of configure to change linker? Something like --with-cxxlinker.
If not - how can I find and change the linker used by specific package?
The recommended way of building ROOT from source is to use git and obtain the most recent production version available. As of today that is version 5.34.19.
Open Terminal.app (then use each of the commands in succession):
cd ~/desktop && mkdir root
git clone http://root.cern.ch/git/root.git && cd root
./configure
make
make install
The nice thing about using git is that it contains a complete source tree for all systems (72 MB). You shouldn't need to use any special ./configure commands (unless you want to use add-on components).
You could also install the Mac Ports version by using the command:
sudo port install root

cross compile opencv for porting to TI DM6446

I have set up target fs on
/home/myself/filesys/bin..etc//
GCC
compile:
host $ arm_v5t_le-gcc hello.c -o hello
run:
target $ cd /opt/hello
target $./hello
I have installed opencv2.3 on host ubuntu machine now I want opencv to be ported to DM6446
so i follow
uncompress opencv2.3 tarball
sudo cmake OpenCV-2.3.1
sudo make ARCH=arm CROSS_COMPILE=arm_v5t_le-
but when I run the sample test from bin it runs on x86 machine which was made for ARM
I think I am not following the correct procedure to make opencv.
Is there anything I have to do to make opencv for ARM architecture,
what are the steps to follow in cross compiling?
The 2nd command you executed should provide a clue as to whether you are cross-compiling or not. If you look closely it would have shown that it was building for the i686 and not for the ARM platform.
This blog discusses how to Cross Compile using cmake.
cmake uses different environment variables from standard make (so don't use ARCH, and CROSS-COMPILE).

Resources