rust-cross
rust-cross copied to clipboard
Cross compiling from Windows to Linux
Because of work I needed to switch to a Windows laptop and now look into a good way to build linux executables on Windows 10. Basicall I'd like to build the binaries in IntelliJ (or Visual Studio), so on Windows itself and not in the Linux Subsystem (which I could but then I'd have the wrong "environment" in my IntelliJ and would get suggestions for Windows instead of Linux specific features)
Now, I'm stuck on the "C cross toolchain": I've looked into crosstool-ng but that seems linux only. It also supports cygwin but that sounds a) like a very old method and b) looking at this stackoverflow thread sounds that I need to compile in the cygwin environment
On the other hand I found targeting the windows subsystem for Linux from Visual Studio which looks like it's going into the right direction but it's Visual Studio specific.
Generally I'm a bit lost as cross compilers are new ground for me. If anybody could just give me some directions I could figure out the nitty gritty details myself.
Thanks to rust-lang/rust#40018 you can crosscompile Rust programs (on nightly) from Windows to Linux using the linux-musl target as long as none of the crates you use have any C dependencies / sources. You'll need to add this to your .cargo/config:
[target.x86_64-unknown-linux-musl]
rustflags = ["-Z", "linker-flavor=ld"]
You can then (after rustup target add x86_64-unknown-linux-musl) build with cargo build --release --target x86_64-unknown-linux-musl. This will produce static binaries which should run on any recent Linux variant.
@rkarp
That sounds awesome!!!
Is there a similar linker that can be used to produce Windows binaries from Linux hosts?
With rust-lang/rust#48125 LLD is now part of nightly, so there's no need to even install LLVM anymore. It can simply be used like this:
[target.x86_64-unknown-linux-musl]
rustflags = ["-Z", "linker-flavor=ld.lld"]
@mcandre: LLD is a cross-linker and can also link for Windows targets with linker-flavor=lld-link, though that may require additional libraries to be present. I haven't tried using it, so I don't know any specifics.
Just for anyone that stumbles upon this today:
a) -C today rather than -Z, cargo/config should be:
[target.x86_64-unknown-linux-musl]
rustflags = ["-C", "linker-flavor=ld.lld"]
https://github.com/rust-lang/rust/issues/52501
b) you need to instlal lld for this to work, there are prebuilt binaries available: https://releases.llvm.org/download.html
make sure that bin directory is added in path and this works.
c) either i missed something or you need to use nightly for musl
With these 3 things above i was able to cross compile from windows to centos7.
cargo build --target x86_64-unknown-linux-musl
Finished dev [unoptimized + debuginfo] target(s) in 0.02s
yey!
Actually, rustflags = ["-C", "linker-flavor=ld.lld"] isn't even necessary anymore, it seems to be inferred by the linker name. Also, there's no need to install LLVM since LLD is already part of nightly rust. The only thing you need anymore is this entry:
[target.x86_64-unknown-linux-musl]
linker = "rust-lld"
I'm too have problems to compile my project under windows 10 for linux. I tried target as "x86_64-unknown-linux-musl" and "x86_64-unknown-linux-gnu". With "gnu" its ask for "cc" and under "musl" its ask for "musl-gcc". I have cygwin installed.
I have created in my project a folder named ".cargo" with file "config":
[target.x86_64-unknown-linux-musl]
linker = "C:/cygwin64/bin/gcc.exe"
Compile with
# cargo build --release --target=x86_64-unknown-linux-musl
Result:
TARGET = Some("x86_64-unknown-linux-musl")
OPT_LEVEL = Some("3")
HOST = Some("x86_64-pc-windows-msvc")
CC_x86_64-unknown-linux-musl = None
CC_x86_64_unknown_linux_musl = None
TARGET_CC = None
CC = None
CROSS_COMPILE = None
CFLAGS_x86_64-unknown-linux-musl = None
CFLAGS_x86_64_unknown_linux_musl = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
DEBUG = Some("false")
Error occurred: Failed to find tool. Is `musl-gcc` installed?
# rustup show
Default host: x86_64-pc-windows-msvc
installed toolchains
--------------------
stable-x86_64-pc-windows-msvc
nightly-2019-08-01-x86_64-pc-windows-msvc
nightly-x86_64-pc-windows-msvc (default)
installed targets for active toolchain
--------------------------------------
x86_64-pc-windows-msvc
x86_64-unknown-linux-gnu
x86_64-unknown-linux-musl
active toolchain
----------------
nightly-x86_64-pc-windows-msvc (default)
rustc 1.39.0-nightly (9eae1fc0e 2019-08-23)
Whats my big mistake?
WSL is not Visual Studio specific. It's like reverse Wine. You can install e.g. Ubuntu for WSL, then install rust using instruction from https://www.rust-lang.org/tools/install and use cargo just like on Linux.
I am successful with first installing LLVM for Windows from https://releases.llvm.org/download.html, making sure that C:\Program Files\LLVM\bin is in PATH, then adding linker = "rust-lld" in my .cargo/config.
I cross-compiled a binary to armv5tel-unknown-linux-musleabi and it works fine on the target machine. Only pity is no support for the VFP unit... maybe next I'll try to make a custom target profile with hard floating point turned on.