How to cross-compile Linux binaries with Rust from Windows hosts?


#1

Hi, I am trying to configure Rust in Windows to enable cross-compilation of generic Rust binaries (think Hello World) for Linux targets. I installed the x86_64-unknown-linux-gnu target with rustup, but when I try to build my application, I get an error about a missing cc program. Well, cc isn’t normally available in Windows, that would be more like cl from Visual Studio.

$ cargo build --target x86_64-unknown-linux-gnu
   Compiling hello v0.0.1 (file:///C:/Users/a_pen/go/src/github.com/mcandre/toys/rust/hello)
error: could not exec the linker `cc`: The system cannot find the file specified. (os error 2)
  |
  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "C:\\Users\\a_pen\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-unknown-linux-gnu\\lib" "C:\\Users\\a_pen\\go\\src\\github.com\\mcandre\\toys\\rust\\hello\\target\\x86_64-unknown-linux-gnu\\debug\\deps\\hello-b48813c72b5be0f1.hello0.rcgu.o" "C:\\Users\\a_pen\\go\\src\\github.com\\mcandre\\toys\\rust\\hello\\target\\x86_64-unknown-linux-gnu\\debug\\deps\\hello-b48813c72b5be0f1.hello1.rcgu.o" "-o" "C:\\Users\\a_pen\\go\\src\\github.com\\mcandre\\toys\\rust\\hello\\target\\x86_64-unknown-linux-gnu\\debug\\deps\\hello-b48813c72b5be0f1" "C:\\Users\\a_pen\\go\\src\\github.com\\mcandre\\toys\\rust\\hello\\target\\x86_64-unknown-linux-gnu\\debug\\deps\\hello-b48813c72b5be0f1.crate.allocator.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "-L" "C:\\Users\\a_pen\\go\\src\\github.com\\mcandre\\toys\\rust\\hello\\target\\x86_64-unknown-linux-gnu\\debug\\deps" "-L" "C:\\Users\\a_pen\\go\\src\\github.com\\mcandre\\toys\\rust\\hello\\target\\debug\\deps" "-L" "C:\\Users\\a_pen\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-unknown-linux-gnu\\lib" "-Wl,-Bstatic" "C:\\Users\\a_pen\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-unknown-linux-gnu\\lib\\libstd-58a9e2944951d97f.rlib" "C:\\Users\\a_pen\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-unknown-linux-gnu\\lib\\libpanic_unwind-167b5e977a2ab35c.rlib" "C:\\Users\\a_pen\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-unknown-linux-gnu\\lib\\libunwind-b8892ba833aa6677.rlib" "C:\\Users\\a_pen\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-unknown-linux-gnu\\lib\\liballoc_system-17235785be0fea01.rlib" "C:\\Users\\a_pen\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-unknown-linux-gnu\\lib\\liblibc-2e9b8cf09e3563de.rlib" "C:\\Users\\a_pen\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-unknown-linux-gnu\\lib\\liballoc-d7195d5e94bc6586.rlib" "C:\\Users\\a_pen\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-unknown-linux-gnu\\lib\\libstd_unicode-963f18f265d9b8d3.rlib" "C:\\Users\\a_pen\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-unknown-linux-gnu\\lib\\libcore-48934815da5d2bfb.rlib" "C:\\Users\\a_pen\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-unknown-linux-gnu\\lib\\libcompiler_builtins-a6b6fad6cc543169.rlib" "-Wl,-Bdynamic" "-l" "dl" "-l" "rt" "-l" "pthread" "-l" "pthread" "-l" "gcc_s" "-l" "c" "-l" "m" "-l" "rt" "-l" "pthread" "-l" "util" "-l" "util"

error: aborting due to previous error

error: Could not compile `hello`.

Does cross-compilation require a cc compiler from Cygwin, or is there some other way to fix the Rust system so that it can successfully build Linux binaries from Windows? I’d prefer to perform this compilation natively on the host, without fussing with dual booting Linux or setting up virtual machines.


#2

When compiling, Rust shells out to the system linker for that particular target. If you’re cross compiling to linux then you’ll need to have a linker which can work with ELF executables.

@japaric wrote up a bunch of info about cross compilation in Rust. I don’t have the answer for you, but hopefully that article will be able to point you in the right direction.


#3

I know you asked specifically about cross-compiling, but the new linux subsystem in Windows 10 might be useful for you (aka “Ubuntu On Windows” or “WLS”) . You’ll be able to follow the normal install-rust-on-linux instruction, and for the most part just pretend you are on linux. A normal “cargo build” will produce an ELF binary that should be runnable on real linux machines.


#4

Noted. bash on Ubuntu on Windows is okay for some development work, though I am actually interested in building binaries for several kernels, in addition to GNU/Linux. I am interested in a cross-compiler setup that can build FreeBSD binaries for Rust application as well, from Windows, without resorting to virtual machines, just like Go works out of the box.


#5

Cross-compiling from Windows to Linux is actually quite easy now as long as there are no C sources in any of your dependencies. You can use the linux-musl target and the LLD linker from LLVM as described here.
This has the advantage of not needing WSL plus you don’t have to install anything else besides LLVM.


#6

Although good advice, this does come at the price of binary size inflation, since you statically link to the musl libc, instead of dynamically to the host libc.