rust-cross icon indicating copy to clipboard operation
rust-cross copied to clipboard

Cross compiling from Windows to Linux

Open philippkeller opened this issue 8 years ago • 8 comments

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.

philippkeller avatar May 07 '17 11:05 philippkeller

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 avatar Dec 03 '17 18:12 rkarp

@rkarp

That sounds awesome!!!

Is there a similar linker that can be used to produce Windows binaries from Linux hosts?

mcandre avatar Mar 14 '18 02:03 mcandre

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.

rkarp avatar Mar 15 '18 21:03 rkarp

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!

fulara avatar Jun 04 '19 12:06 fulara

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"

rkarp avatar Jun 08 '19 09:06 rkarp

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?

Daijobou avatar Aug 24 '19 16:08 Daijobou

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.

topin89 avatar Dec 20 '19 21:12 topin89

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.

schungx avatar Jan 26 '20 08:01 schungx