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

# 概要
RustでのLinux上でのWindowsへのクロスコンパイル

環境は以下

 - debian 10
 - Rust 1.21.1

## TL;DR
[https://github.com/jacob327/rust-debian2windows](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`ファイルを生成すれば良いです。

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

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

```bash: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の生成問題があります。

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

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

fn main() {
    println!("{:?}", add(3.0, 2.0));
}
```

```rs:呼び出される側;lib.rs
#[no_mangle]
pub extern fn add(a: f64, b: f64) -> f64 {
    a + b
}
```

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

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

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

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

```bash: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
```

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

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

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

```bash:temrinal
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install -y wine32
```

```bash:terminal
$ 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

```