Rust Crosscompiling on Linux
Tested on Manjaro Linux 5.6.12
(2020-05-26).
Rust
Install native Linux rust
and i686-pc-windows-gnu
target.
Currently (as of 2020-05) Windows version of cargo
doesn’t run on Wine (NtLockFile from ntdll
is not implemented). Rustc
alone seems to be working. Fortunately, you can use linux version of rustc
and cargo
with i686-pc-windows-gnu
target installed.
GCC (option 1 - Linux binaries)
You can install mingw-w64-gcc
natively on Linux. Make sure that the i686
version is configured with dwarf2
exception handling. Otherwise, it won’t link the rust code. Also install i686-w64-mingw32-wine
package.
Look at the PKGBUILD
(you need to also verify it for every library). Make sure there are flags:
--disable-sjlj-exceptions --with-dwarf2
However, the sjlj
version may also work (not tested) if you add rustflags
to the .cargo/config
:
[target.i686-pc-windows-gnu]
rustflags = "-C panic=abort"
Add to your .cargo/config
:
[target.i686-pc-windows-gnu]
linker = "/usr/bin/i686-w64-mingw32-gcc"
ar = "/usr/i686-w64-mingw32/bin/ar"
runner = "/usr/bin/i686-w64-mingw32-wine"
rustflags = [
]
[target.x86_64-pc-windows-gnu]
linker = "/usr/bin/x86_64-w64-mingw32-gcc"
ar = "/usr/x86_64-w64-mingw32/bin/ar"
runner = "/usr/bin/x86_64-w64-mingw32-wine"
rustflags = [
]
GCC (option 2 - Windows binaries)
It works through Wine.
You can either download gcc from: https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/. Tested with i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z
.
Or you can install msys2-i686 from: https://sourceforge.net/projects/msys2/files/Base/i686/. The only problem with it is that bash
and pacman
commands are crashing on Wine
, but the gcc compiler works great. And it is very easy to install libraries. So this is a great option if you can update and install libraries from real Windows.
Let’s assume you’ve installed msys2-i686
somewhere in msys2-x32
folder. Now you can create following scripts at the same level:
wine-mingw-command.sh
- base script to call GCC tools:
#!/bin/bash
# folders
BASE_DIR=$(dirname $0)
MSYS_DIR=$BASE_DIR/msys2-x32
MINGW_DIR=$MSYS_DIR/mingw32
# GCC
export WINEPATH=$MINGW_DIR/bin
export CC=i686-w64-mingw32-gcc
export CXX=i686-w64-mingw32-g++
export AR=i686-w64-mingw32-ar
# make sure that crt2.o come from MINGW_DIR
# cargo is trying to use it's own version which won't work
declare -a new_args=()
for var in "${@:2}"
do
if [[ "$var" == */lib/crt2.o ]]
then
new_args+=("$MINGW_DIR/i686-w64-mingw32/lib/crt2.o")
elif [[ "$var" == */lib/dllcrt2.o ]]
then
new_args+=("$MINGW_DIR/i686-w64-mingw32/lib/dllcrt2.o")
else
new_args+=($var)
fi
done
# call command provided as the first parameter
$MINGW_DIR/bin/$1 "${new_args[@]}"
wine-runner.sh
- allows to run final .exe files with access to all required dlls:
#!/bin/bash
# folders
BASE_DIR=$(dirname $0)
MSYS_DIR=$BASE_DIR/msys2-x32
MINGW_DIR=$MSYS_DIR/mingw32
# GCC
export WINEPATH=$MINGW_DIR/bin
/usr/bin/wine "$@"
Now you are ready to create following shortcuts. Put them somewhere that they are available in one of the PATH environment’s folder. For example in `~/.cargo/bin”. The scripts are:
i686-w64-mingw32-ar
:
/mnt/aplikacje/Uzytkowe/dev/compilers/native-x32/wine-mingw-command.sh ar.exe "$@"
i686-w64-mingw32-g++
:
/mnt/aplikacje/Uzytkowe/dev/compilers/native-x32/wine-mingw-command.sh g++.exe "$@"
i686-w64-mingw32-gcc
:
/mnt/aplikacje/Uzytkowe/dev/compilers/native-x32/wine-mingw-command.sh gcc.exe "$@"
i686-w64-mingw32-pkg-config
:
/mnt/aplikacje/Uzytkowe/dev/compilers/native-x32/wine-mingw-command.sh pkg-config.exe "$@"
Note! I had problems with building freetype for rust when I rename i686-w64-mingw32-ar
to i686-w64-mingw32-gcc-ar
. The reason is not clear to me and it is related with cmake
that cannot find ar
command.
Finally, you can update cargo
configuration in ~/.cargo/config
file:
[target.i686-pc-windows-gnu]
linker = "i686-w64-mingw32-gcc"
ar = "i686-w64-mingw32-ar"
runner = "/mnt/aplikacje/Uzytkowe/dev/compilers/native-x32/wine-runner.sh"
rustflags = [
]