Can't cross compile from Linux to Windows (i686) #32859

Open
bozaro opened this Issue Apr 9, 2016 · 16 comments

Projects

None yet

7 participants

@bozaro
bozaro commented Apr 9, 2016

Environment:

  • Ubuntu 16.04 LTS final beta (lxc-create -n rust -t ubuntu -- --release xenial)
  • Mingw (apt install mingw-w64)
  • rustup tool (curl https://sh.rustup.rs -sSf | sh)
  • Rust 1.8 and nightly (rustup default beta/rustup default nightly)
  • Rust windows i686 toolchain (rustup target add i686-pc-windows-gnu)

I create a sample file hello.rs:

fn main() {
    println!("Hello, world!");
}

And run compilation:

rustc -v -C linker=i686-w64-mingw32-ld --target i686-pc-windows-gnu hello.rs

I expected hello.exe file, but has error:

error: linking with `i686-w64-mingw32-ld` failed: exit code: 1
note: "i686-w64-mingw32-ld" "-Wl,--enable-long-section-names" "-fno-use-linker-plugin" "-Wl,--nxcompat" "-nostdlib" "-Wl,--large-address-aware" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/crt2.o" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/rsbegin.o" "-L" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib" "hello.0.o" "-o" "hello.exe" "-Wl,--gc-sections" "-nodefaultlibs" "-L" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib" "-Wl,-Bstatic" "-Wl,-Bdynamic" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libstd-18402db3.rlib" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libcollections-18402db3.rlib" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/librustc_unicode-18402db3.rlib" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/librand-18402db3.rlib" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/liballoc-18402db3.rlib" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/liballoc_system-18402db3.rlib" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/liblibc-18402db3.rlib" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libcore-18402db3.rlib" "-l" "gcc_eh" "-l" "gcc_eh" "-l" "ws2_32" "-l" "userenv" "-l" "shell32" "-l" "advapi32" "-l" "compiler-rt" "-lmingwex" "-lmingw32" "-lgcc" "-lmsvcrt" "-luser32" "-lkernel32" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/rsend.o"
note: i686-w64-mingw32-ld: unrecognized option '-Wl,--enable-long-section-names'
i686-w64-mingw32-ld: use the --help option for usage information

error: aborting due to previous error
@bozaro
bozaro commented Apr 9, 2016

Same issue with Ubuntu 14.04.4 LTS

@alexcrichton
Member

Thanks for the report! Like with #32858 you'll want to pass gcc instead of ld, but unfortunately i686 probably won't work because the threading model of the compiler on Ubuntu is pthreads where we target the Windows threading model (an alternate mingw toolchain). As a result you'll probably still get link failures :(

@bozaro
bozaro commented Apr 9, 2016

I try command:

rustc -v -C linker=i686-w64-mingw32-gcc --target x86_64-pc-windows-gnu hello.rs

But it don't work :(

error: linking with `i686-w64-mingw32-gcc` failed: exit code: 1
note: "i686-w64-mingw32-gcc" "-Wl,--enable-long-section-names" "-fno-use-linker-plugin" "-Wl,--nxcompat" "-nostdlib" "-Wl,--large-address-aware" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/crt2.o" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/rsbegin.o" "-L" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib" "hello.0.o" "-o" "hello.exe" "-Wl,--gc-sections" "-nodefaultlibs" "-L" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib" "-Wl,-Bstatic" "-Wl,-Bdynamic" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libstd-18402db3.rlib" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libcollections-18402db3.rlib" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/librustc_unicode-18402db3.rlib" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/librand-18402db3.rlib" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/liballoc-18402db3.rlib" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/liballoc_system-18402db3.rlib" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/liblibc-18402db3.rlib" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libcore-18402db3.rlib" "-l" "gcc_eh" "-l" "gcc_eh" "-l" "ws2_32" "-l" "userenv" "-l" "shell32" "-l" "advapi32" "-l" "compiler-rt" "-lmingwex" "-lmingw32" "-lgcc" "-lmsvcrt" "-luser32" "-lkernel32" "/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/rsend.o"
note: /home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libstd-18402db3.rlib(std-18402db3.0.o):(.text+0xa9): undefined reference to `_Unwind_Resume'
/home/ubuntu/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libstd-18402db3.rlib(std-18402db3.0.o):(.text+0x1d163): undefined reference to `_Unwind_RaiseException'
collect2: error: ld returned 1 exit status

error: aborting due to previous error
@alexcrichton
Member

Yep that's the expected error! Those two symbols aren't defined in all mingw toolchains, but they're the ones that we want. I'm not entirely sure what the best course of action here is for this cross-compilation scenario...

cc @vadimcn

@vadimcn
Contributor
vadimcn commented Apr 10, 2016

Yeah, these are symbols from the DWARF unwinder, which we use on Windows. For some reason Linux distros prefer to configure cross-mingw toolchain for SJLJ unwinding, so these symbols are missing.

As for what can be done...
I did a quick experiment and copied libgcc_eh.a that comes with Windows mingw-w64 toolchain into Rust's lib/rustlib/i686-pc-windows-gnu/lib directory on my Linux box, and was able to link a simple Rust program for the windows target. I suppose we could bundle libgcc_eh with the rust-std component, at least for -pc-windows-gnu targets.
However I am not entirely sure that it won't clash with the cross-mingw's own libgcc, especially if C/C++ libs are involved. I'd be much more comfortable if we could figure out a way to restrict the visibility of the dwarf unwinder symbols to libstd only.

@vadimcn
Contributor
vadimcn commented Apr 11, 2016

... and was able to link a simple Rust program for the windows target

On second look, it didn't work out as well as I had thought: unwinding on panic! doesn't work. I guess the stack unwinding tables are getting registered with the wrong unwinder. Or something. :-(

Edit: nevermind, it did work after all :-)

@palazzo-train
palazzo-train commented Apr 15, 2016 edited

I got the same problem but i resolve it now. It seems the lib/rustlib/i686-pc-windows-gnu/lib from multirust is not the good one.

If I download the native windows package http://static.rust-lang.org/dist/2016-04-14/rust-nightly-i686-pc-windows-gnu.exe, (for rustc 1.9.0-nightly (2b60207 2016-04-13)) and install in windows, I get the lib\rustlib\i686-pc-windows-gnu\lib there.

You can find there are more files from windows lib then from linux multirust lib for i686-pc-windows-gnu. I copy . from windows lib to linux multirust lib. Then it works.

Perhaps multirust is not picking good source of files when it adds target? I don't know.

@alexcrichton
Member
alexcrichton commented Apr 15, 2016 edited

Hm that may actually be because the rust-* package is an assembly of a bunch of components, namely the rust-mingw components. I think that rust-mingw actually has the right set of libraries, so now that you mention it that should work!

So basically if you install both the rust-std and rust-mingw package then cross-compilation should work out of the box (I think).

cc @brson, seems... an interesting insight! Also another reason to control components, we'd probably want to actually install the rust-mingw package by default on Linux perhaps?

@steveklabnik steveklabnik added the A-cross label Jun 6, 2016
@lunemec
lunemec commented Oct 26, 2016

I'm experiencing the same issue on x86_64-pc-windows-gnu.

What I tried:

  • compiling on macos
    • installing the windows-gnu toolchain
    • activating the toolchain as default
    • installing target platform windows-gnu for this toolchain
    • checked components for present rust-mingw (it is installed)
    • still got linker error.
  • compiling inside docker on linux
    • same procedure - tried with both linux-gnu and windows-gnu toolchains
    • the same linker error.

Rustup show:

$ rustup show
Default host: x86_64-unknown-linux-gnu

installed toolchains
--------------------

stable-x86_64-pc-windows-gnu (default)
stable-x86_64-unknown-linux-gnu

active toolchain
----------------

stable-x86_64-pc-windows-gnu (default)
(rustc does not exist)

Target list:

$ rustup target list
x86_64-pc-windows-gnu (default)

Component list:

$ rustup component list
cargo-x86_64-pc-windows-gnu (default)
rust-docs-x86_64-pc-windows-gnu (default)
rust-mingw-x86_64-pc-windows-gnu (default)
rust-std-x86_64-pc-windows-gnu (default)
rustc-x86_64-pc-windows-gnu (default)

Error I got: (the error is the same if I use target stable)

$ rustup run x86_64-pc-windows-gnu cargo build --target=x86_64-pc-windows-gnu --release
   Compiling rust-birkana v0.1.1 (file:///home/developer)
error: linking with `gcc` failed: exit code: 1
  |
  = note: "gcc" "-Wl,--enable-long-section-names" "-fno-use-linker-plugin" "-Wl,--nxcompat" "-nostdlib" "-m64" "/home/developer/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/crt2.o" "/home/developer/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/rsbegin.o" "-L" "/home/developer/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib" "/home/developer/target/x86_64-pc-windows-gnu/release/rust_birkana.0.o" "-o" "/home/developer/target/x86_64-pc-windows-gnu/release/rust_birkana.exe" "-Wl,--gc-sections" "-nodefaultlibs" "-L" "/home/developer/target/x86_64-pc-windows-gnu/release/deps" "-L" "/home/developer/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib" "-Wl,-Bstatic" "-Wl,-Bdynamic" "/home/developer/target/x86_64-pc-windows-gnu/release/deps/libsvg-e43e83b8936467b2.rlib" "/home/developer/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/libstd-5c6cf767.rlib" "/home/developer/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/libpanic_unwind-5c6cf767.rlib" "/home/developer/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/libunwind-5c6cf767.rlib" "/home/developer/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/librand-5c6cf767.rlib" "/home/developer/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/libcollections-5c6cf767.rlib" "/home/developer/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/librustc_unicode-5c6cf767.rlib" "/home/developer/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/liblibc-5c6cf767.rlib" "/home/developer/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/liballoc-5c6cf767.rlib" "/home/developer/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/liballoc_system-5c6cf767.rlib" "/home/developer/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/libcore-5c6cf767.rlib" "-l" "ws2_32" "-l" "userenv" "-l" "shell32" "-l" "advapi32" "-l" "gcc_eh" "-l" "compiler-rt" "-lmingwex" "-lmingw32" "-lgcc" "-lmsvcrt" "-luser32" "-lkernel32" "/home/developer/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/rsend.o"
  = note: /usr/bin/ld: unrecognized option '--enable-long-section-names'
/usr/bin/ld: use the --help option for usage information
collect2: error: ld returned 1 exit status

what I find strange, is even when default toolchain is set to windows-gnu, in the command passed to gcc contains the path to linux-gnu toolchain. But not all commands, some are windows-gnu, but some not. I'm not sure if this is by design, or some bug.

But I tried everything I could think of and find on the internet, but it is impossible right now to cross-compile from mac or linux -> windows.

@bozaro
bozaro commented Oct 26, 2016

As workaround you can create .cargo/config with content like (it works on my Linux host):

[target.i686-pc-windows-gnu]
linker = "i686-w64-mingw32-gcc"

[target.x86_64-pc-windows-gnu]
linker = "x86_64-w64-mingw32-gcc"

Directory .cargo can be located near Cargo.toml file.

@lunemec
lunemec commented Oct 26, 2016

I added the second line and now it can't find the linker. Do I need to install it from somewhere?

error: could not exec the linker `x86_64-w64-mingw32-gcc`: No such file or directory (os error 2)
@retep998
Member

@lunemec If you're on Linux and trying to cross compile to Windows, yes you need to install the appropriate MinGW toolchain.

@bozaro
bozaro commented Oct 26, 2016

I don't known. I have not a Mac OS :(

@lunemec
lunemec commented Oct 26, 2016

I was running this command inside debian jessie inside docker on my macbook. I also installed the toolchain with rustup. It is shown in my previous post. Is this separate toolchain from rustup's toolchain (and components)? Where do I find it?

@bozaro
bozaro commented Oct 26, 2016

May be:

sudo apt update && sudo apt install mingw-w64
@lunemec
lunemec commented Oct 26, 2016

Yes! this indeed was the last step to getting it to compile. However, this is really terrible user experience with cross-compilation (yes I know it is difficult problem to solve right), but Golang is much much easier with their GOOS= ... setting (and 1 tar.gz download). I very much hope Rust will get there someday :)

Also, I'll open issue of this in rustup project, since none of this is documented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment