概要
RustでのLinux上でのWindowsへのクロスコンパイル
環境は以下
- debian 10
- Rust 1.21.1
TL;DR
https://github.com/jacob327/rust-debian2windows
用途
Windowsのバイナリを生成する場合、次の2つが主な用途になりそうです。
- 実行ファイル (.exe)
- 動的ライブラリ (.dll)
実行ファイルを新たに生成する場合は64bit環境一択で良いのですが、他のプログラムからdllとして呼び出す場合は32bit環境を考慮する必要がある場合があります。
Linux上にWindowsのコンパイル環境を作る
toolchainとtargetとmingwが必要です。
toolchain:
- stable-i686-pc-windows-gnu
- stable-x86_64-pc-windows-gnu
target:
- i686-pc-windows-gnu
- x86_64-pc-windows-gnu
つまり次のようにそれぞれインストールすれば良いです。
rustup toolchain install stable-i686-pc-windows-gnu stable-x86_64-pc-windows-gnu
rustup target add i686-pc-windows-gnu x86_64-pc-windows-gnu
sudo apt-get install -y mingw-w64
64bit環境でexeを生成する場合
この場合は比較的簡単でcargo.toml
があるディレクトリに.cargo
ディレクトリとその中にconfig
ファイルを生成すれば良いです。
[build]
target = "x86_64-pc-windows-gnu"
[target.x86_64-pc-windows-gnu]
linker = "x86_64-w64-mingw32-gcc"
$ cargo build
Compiling mt4_dll v0.1.0 (/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL)
Finished dev [unoptimized + debuginfo] target(s) in 0.34s
32bit環境でdllを生成する場合
この場合は32bit環境でのコンパイル自体の問題とdllの生成問題があります。
今回は呼び出す側と呼び出される側で次のような内容で実際に作ってみます。
mod lib;
use crate::lib::*;
fn main() {
println!("{:?}", add(3.0, 2.0));
}
# [no_mangle]
pub extern fn add(a: f64, b: f64) -> f64 {
a + b
}
'1. 動的ライブラリにしたいのでcargo.toml
にdylib
である旨を追記します。cdylib
でもよいはずです。
[lib]
crate-type = ["dylib"]
'2. .cargo/config
は次のようにi386に変更します。
[build]
# target = "x86_64-pc-windows-gnu"
target = "i686-pc-windows-gnu"
[target.x86_64-pc-windows-gnu]
linker = "x86_64-w64-mingw32-gcc"
[target.i686-pc-windows-gnu]
linker = "i686-w64-mingw32-gcc"
rustflags = "-C panic=abort"
'3. 使用するオブジェクトファイルを入れ替えます。
cd ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib
cp crt2.o crt2.o.bak
cp /usr/i686-w64-mingw32/lib/crt2.o crt2.o
cp dllcrt2.o dllcrt2.o.bak
cp /usr/i686-w64-mingw32/lib/dllcrt2.o dllcrt2.o
これで正常にコンパイルできるはずです。
$ cargo build
Finished dev [unoptimized + debuginfo] target(s) in 0.00s
実行
実行するにはwineを入れましょう(mingwでやるのが王道ぽい気がしますが)。
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install -y wine32
$ wine ./target/i686-pc-windows-gnu/debug/mt4_dll.exe
5.0
エラー内容
-
.cargo/config
のrustflags="-C panic=abort"
がない場合は次のようなエラーがでます。
$ cargo build
Compiling mt4_dll v0.1.0 (/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL)
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/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/dllcrt2.o" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/rsbegin.o" "-L" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/i686-pc-windows-gnu/debug/deps/mt4_dll.4jj8cggy17wroq5l.rcgu.o" "-o" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/i686-pc-windows-gnu/debug/deps/mt4_dll.dll" "-Wl,--version-script=/tmp/rustc6GNGJA/list" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/i686-pc-windows-gnu/debug/deps/mt4_dll.5e7u1yd21s9rzl5z.rcgu.o" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/i686-pc-windows-gnu/debug/deps/mt4_dll.1osk0zeab4eylqmu.rcgu.o" "-nodefaultlibs" "-L" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/i686-pc-windows-gnu/debug/deps" "-L" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/debug/deps" "-L" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib" "-Wl,--start-group" "-Wl,-Bstatic" "-Wl,--whole-archive" "/tmp/rustc6GNGJA/libstd-9d01ece378a391cf.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc6GNGJA/libpanic_unwind-0c029c00da54fbf5.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc6GNGJA/libhashbrown-88fcc0245bd24629.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc6GNGJA/librustc_std_workspace_alloc-f12aad15d8a75f72.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc6GNGJA/libbacktrace-55381df32023f6e1.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc6GNGJA/libbacktrace_sys-8dfa5f2af7948d79.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc6GNGJA/librustc_demangle-3c26c70d611bf813.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc6GNGJA/libunwind-a515e8a3aaec53f5.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc6GNGJA/libcfg_if-ea28d0cc615ab33b.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc6GNGJA/liblibc-397d570cca7da304.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc6GNGJA/liballoc-6c3a8a4f0068446e.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc6GNGJA/librustc_std_workspace_core-067eca854694af12.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc6GNGJA/libcore-82b4242551359f3e.rlib" "-Wl,--no-whole-archive" "-Wl,--end-group" "/tmp/rustc6GNGJA/libcompiler_builtins-22c0c99dab989005.rlib" "-Wl,-Bdynamic" "-ladvapi32" "-lws2_32" "-luserenv" "-Wl,-Bstatic" "-lgcc_eh" "-lpthread" "-shared" "-Wl,--out-implib,/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/i686-pc-windows-gnu/debug/deps/mt4_dll.dll.lib" "-Wl,-Bdynamic" "-lmingwex" "-lmingw32" "-lgcc" "-lmsvcrt" "-lmsvcrt" "-luser32" "-lkernel32" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/rsend.o"
= note: /usr/bin/i686-w64-mingw32-ld: /tmp/rustc6GNGJA/libpanic_unwind-0c029c00da54fbf5.rlib(panic_unwind-0c029c00da54fbf5.panic_unwind.2hgzd7yq-cgu.0.rcgu.o): in function `ZN12panic_unwind3imp5panic17h03027a0e504502cdE':
/rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14\/src\libpanic_unwind/gcc.rs:73: undefined reference to `_Unwind_RaiseException'
/usr/bin/i686-w64-mingw32-ld: /tmp/rustc6GNGJA/libpanic_unwind-0c029c00da54fbf5.rlib(panic_unwind-0c029c00da54fbf5.panic_unwind.2hgzd7yq-cgu.0.rcgu.o): in function `rust_eh_unwind_resume':
/rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14\/src\libpanic_unwind/gcc.rs:327: undefined reference to `_Unwind_Resume'
collect2: error: ld returned 1 exit status
- オブジェクトファイルが古い場合のエラーは次のようなエラーがでます。
$ cargo build
Compiling mt4_dll v0.1.0 (/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL)
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/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/crt2.o" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/rsbegin.o" "-L" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/i686-pc-windows-gnu/debug/deps/mt4_dll-300ee3bf26711df8.12x1c16zdc8jvebv.rcgu.o" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/i686-pc-windows-gnu/debug/deps/mt4_dll-300ee3bf26711df8.17z2r1etgfgqhz1e.rcgu.o" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/i686-pc-windows-gnu/debug/deps/mt4_dll-300ee3bf26711df8.1oq40yr5ubbihise.rcgu.o" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/i686-pc-windows-gnu/debug/deps/mt4_dll-300ee3bf26711df8.215db9r17sgnchnc.rcgu.o" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/i686-pc-windows-gnu/debug/deps/mt4_dll-300ee3bf26711df8.25ql4imwrk7n0w5l.rcgu.o" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/i686-pc-windows-gnu/debug/deps/mt4_dll-300ee3bf26711df8.2d0k8096jfym2til.rcgu.o" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/i686-pc-windows-gnu/debug/deps/mt4_dll-300ee3bf26711df8.4ge0fd26jn5tl9xo.rcgu.o" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/i686-pc-windows-gnu/debug/deps/mt4_dll-300ee3bf26711df8.9hr4z7rhdfhbgr7.rcgu.o" "-o" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/i686-pc-windows-gnu/debug/deps/mt4_dll-300ee3bf26711df8.exe" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/i686-pc-windows-gnu/debug/deps/mt4_dll-300ee3bf26711df8.2tnyezrpsl3lelsr.rcgu.o" "-Wl,--gc-sections" "-nodefaultlibs" "-L" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/i686-pc-windows-gnu/debug/deps" "-L" "/home/jacob/Documents/copyTradeMt4/dev/client/MT4DLL/target/debug/deps" "-L" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib" "-Wl,--start-group" "-Wl,-Bstatic" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libstd-9d01ece378a391cf.rlib" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libpanic_abort-989d5d635b77fed7.rlib" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libhashbrown-88fcc0245bd24629.rlib" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/librustc_std_workspace_alloc-f12aad15d8a75f72.rlib" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libbacktrace-55381df32023f6e1.rlib" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libbacktrace_sys-8dfa5f2af7948d79.rlib" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/librustc_demangle-3c26c70d611bf813.rlib" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libunwind-a515e8a3aaec53f5.rlib" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libcfg_if-ea28d0cc615ab33b.rlib" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/liblibc-397d570cca7da304.rlib" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/liballoc-6c3a8a4f0068446e.rlib" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/librustc_std_workspace_core-067eca854694af12.rlib" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libcore-82b4242551359f3e.rlib" "-Wl,--end-group" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libcompiler_builtins-22c0c99dab989005.rlib" "-Wl,-Bdynamic" "-ladvapi32" "-lws2_32" "-luserenv" "-Wl,-Bstatic" "-lgcc_eh" "-lpthread" "-Wl,-Bdynamic" "-lmingwex" "-lmingw32" "-lgcc" "-lmsvcrt" "-lmsvcrt" "-luser32" "-lkernel32" "/home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/rsend.o"
= note: /usr/bin/i686-w64-mingw32-ld: /home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/crt2.o:crtexe.c:(.text+0x75): undefined reference to `__onexitend'
/usr/bin/i686-w64-mingw32-ld: /home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/crt2.o:crtexe.c:(.text+0x7a): undefined reference to `__onexitbegin'
collect2: error: ld returned 1 exit status