LoginSignup
4
2

More than 3 years have passed since last update.

Rust Linux上でWindows用のDLLを生成する

Last updated at Posted at 2020-01-22

概要

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ファイルを生成すれば良いです。

.cargo/config
[build]
target = "x86_64-pc-windows-gnu"

[target.x86_64-pc-windows-gnu]
linker = "x86_64-w64-mingw32-gcc"
terminal
$ 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の生成問題があります。

今回は呼び出す側と呼び出される側で次のような内容で実際に作ってみます。

呼び出す側;main.rs
mod lib;
use crate::lib::*;

fn main() {
    println!("{:?}", add(3.0, 2.0));
}
呼び出される側;lib.rs
#[no_mangle]
pub extern fn add(a: f64, b: f64) -> f64 {
    a + b
}

'1. 動的ライブラリにしたいのでcargo.tomldylibである旨を追記します。cdylibでもよいはずです。

cargo.toml
[lib]
crate-type = ["dylib"]

'2. .cargo/config は次のようにi386に変更します。

.cargo/config
[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. 使用するオブジェクトファイルを入れ替えます。

terminal
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

これで正常にコンパイルできるはずです。

terminal
$ cargo build
    Finished dev [unoptimized + debuginfo] target(s) in 0.00s

実行

実行するにはwineを入れましょう(mingwでやるのが王道ぽい気がしますが)。

temrinal
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install -y wine32
terminal
$ wine ./target/i686-pc-windows-gnu/debug/mt4_dll.exe 
5.0

エラー内容

  • .cargo/configrustflags="-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

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2