Cross compile macOS and MS Windows

Can I cross compile rust between macOS and MS Windows, i.e.
Can I build .exe for windows from macOS and vice versa, is there any special requirement or limitations?

I haven't actually tried this (I'm on Linux) so someone else may be able to give you better advice. That said, I've found cross-compiling Rust code for Windows on Linux to be quite easy, and I imagine you can take the same approach on macOS. rustup supports x86_64-pc-windows-gnu and x86_64-pc-windows-msvc targets; I found using them on Linux to be as easy as rustup target add x86_64-pc-windows-gnu followed by cargo build --target=x86_64-pc-windows-gnu, and I imagine the same would be true under macOS. I think you would probably need to install the MinGW cross-compiler, which you can do easily with brew install mingw-w64 if you have Homebrew installed. It might be possible that you could run into trouble with crates that package C dependencies if their build.rs scripts aren't written well enough, but if you have some experience with cross-compiling C you could probably work out any issues like that if you care to do so.

As far as cross-compiling for macOS on Windows, I haven't tried cross-compiling for macOS in general so I can't speak from experience, but I have done some native macOS development so I know a bit about it from that angle. Reading about cross-compiling Rust, I get the impression that the best (currently only?) option is to use Linux⟶macOS cross compilation tools from something like the WSL or a Linux VM. This post suggests installing osxcross and then using Rust's x86_64-apple-darwin target. There's a big caveat though: Apple wants all new macOS applications to be signed and notarized, and although people have figured out some ways to sign macOS apps outside of macOS I don't think the same is true for notarization since it partially happens on Apple's servers. Right now it's possible for users to run applications that haven't been signed and notarized if they jump through some hoops, but I'm not sure even that will be possible in the future given the direction Apple seems to be going. Given all this, your best option might be to use a service like Travis instead if you don't have access to a macOS environment. In any case, you'll have to pay Apple $99/year for Developer Program membership if you're doing this on your own time and money—it's needed to get a certificate from them.

2 Likes

Rust by itself can cross-compile static libraries, so if that's all you need, it's as easy as adding target in rustup and --target to compilation.

But Rust can't cross-compile executables or dynamic libraries without help of target-specific linker and libraries for the target system.

In my experience cross-linkers and cross-libraries are obtainable for various flavors of Linux targets, but for macOS and Windows it sucks and just doesn't work.

1 Like

the x86_64-pc-windows-gnu target should be painless to set up. I don't use macos, but for example on ubuntu the dev dependencies are:

sudo apt install -y gdb-mingw-w64 gcc-mingw-w64-x86-64
rustup target add x86_64-pc-windows-gnu

You might try

brew install mingw-w64
rustup target add x86_64-pc-windows-gnu
cargo build --target x86_64-pc-windows-gnu

Hi, In macOS Catalina, I added the toolchain as:

% rustup target add x86_64-pc-windows-gnu

installed mingw-w64 as:

brew install mingw-w64

Also I've CMake installed (do not know if it is required here), while running:

 % cargo build --target=x86_64-pc-windows-gnu

I got error:

   Compiling win v0.1.0 (/Users/hasan/AndroidStudioProjects/win)
error: linking with `gcc` failed: exit code: 1
  |
   = note: ld: unknown option: --nxcompat
          clang: error: linker command failed with exit code 1 (use -v to see invocation)

I don't any Windows around to test it, but command:

rustup run stable cargo rustc --release --target=x86_64-pc-windows-gnu -- -C linker=x86_64-w64-mingw32-gcc

seems to run fine.

Got the below error"

error: linking with `/usr/local/bin/x86_64-w64-mingw32-gcc` failed: exit code: 1
  |

  = note: /usr/local/Cellar/mingw-w64/7.0.0_1/toolchain-x86_64/bin/x86_64-w64-mingw32-ld: /Users/hasan/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-pc-windows-gnu/lib/crt2.o:crtexe.c:(.text+0x7d): undefined reference to `_encode_pointer'
          /usr/local/Cellar/mingw-w64/7.0.0_1/toolchain-x86_64/bin/x86_64-w64-mingw32-ld: /Users/hasan/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-pc-windows-gnu/lib/crt2.o:crtexe.c:(.rdata$.refptr.__onexitbegin[.refptr.__onexitbegin]+0x0): undefined reference to `__onexitbegin'
          /usr/local/Cellar/mingw-w64/7.0.0_1/toolchain-x86_64/bin/x86_64-w64-mingw32-ld: /Users/hasan/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-pc-windows-gnu/lib/crt2.o:crtexe.c:(.rdata$.refptr.__onexitend[.refptr.__onexitend]+0x0): undefined reference to `__onexitend'
          collect2: error: ld returned 1 exit status

As an alternative to cross-compiling that may work for some projects, https://github.com/japaric/trust has ready-made scripts for compiling Rust projects on multiple platforms (including Mac and Windows) using Travis CI and Appveyor.

You can also specify the location of ld and ar in ~/.cargo/config, such as:

[target.x86_64-pc-windows-gnu]
linker = "/usr/bin/x86_64-w64-mingw32-gcc"
ar = "/usr/x86_64-w64-mingw32/bin/ar"

This is the one of the things I double check during cross compile setup when ld fails.

Added .cargo/config file. Still it has same error. Testing this on MAC.

1 Like

Still same error, no changes

May be this helps: https://github.com/rust-lang/rust/issues/49078