MinGW-w64クロスコンパイラ

# 概要

Linux上でWindowsバイナリを生成する[MinGW-w64](http://mingw-w64.org)のクロスコンパイラをソースからビルドします。

# 必要なソースコード

以下は2020年4月時点の最新のソースコードです。

- [GNU ftpサイト](https://ftp.gnu.org/)から
    - binutils-2.34
    - gcc-9.3.0
    - gmp-6.2.0
    - mpfr-4.0.2
    - mpc-1.1.0

- SourceForgeの[MinGW-w64プロジェクトサイト](https://sourceforge.net/projects/mingw-w64/)から
    - mingw-w64-v7.0.0

# 準備

- `${CONFIG_BUILD}`
    ビルドに使用するgccのマシンタイプ。
    `gcc -dumpmachine`の結果。
    【x86_64-pc-linux】など。

- `${CONFIG_TARGET64}`
    クロスコンパイルのターゲットの64bitマシンタイプ。
    【x86_64-w64-mingw32】とします。

- `${CONFIG_TARGET32}`
    クロスコンパイルのターゲットの32bitマシンタイプ。
    【i686-w64-mingw32】とします。

- `${SRCDIR}`
    ソースコードを展開するディレクトリ。

- `${BUILDDIR}`
    ビルド用のディレクトリ。

- `${DESTDIR}`
    ビルド結果を一時的にインストールする疑似的なルートディレクトリ。
    既存ファイルの上書きなどシステムに影響がないか確認した上で本当のルートディレクトリに展開します。
    `${DESTDIR}`配下をアーカイブすることで他のシステムに適用することができます。

- `${MINGW64DIR}`
    インストールディレクトリ。
    例えば/opt/mingw64とすることで/opt/mingw64/binに実行バイナリがインストールされます。

- `${PATH}`
    `${MINGW64DIR}/bin`がPATHに含まれていない場合は以下を実行しておきます。

    ```
    $ export PATH=${MINGW64DIR}/bin:${PATH}
    ```

# ソースコードの展開

1. ソースコードをすべて`${SRCDIR}`に展開します。

1. gmp、mpfr、mpcについて、gccディレクトリにシンボリックリンクを張ります。

    ```
    ln -s ../gmp-6.2.0 "${SRCDIR}/gcc-9.3.0/gmp"
    ln -s ../mpfr-4.0.2 "${SRCDIR}/gcc-9.3.0/mpfr"
    ln -s ../mpc-1.1.0 "${SRCDIR}/gcc-9.3.0/mpc"
    ```

1. mingw-w64-v7.0.0から以下のシンボリックリンクを張ります。

    ```
    ln -s mingw-w64-v7.0.0/mingw-w64-crt "${SRCDIR}/mingw-w64-crt-7.0.0"
    ln -s mingw-w64-v7.0.0/mingw-w64-headers "${SRCDIR}/mingw-w64-headers-7.0.0"
    ln -s mingw-w64-v7.0.0/mingw-w64-libraries/libmangle "${SRCDIR}/mingw-w64-libmangle-7.0.0"
    ln -s mingw-w64-v7.0.0/mingw-w64-libraries/winpthreads "${SRCDIR}/mingw-w64-winpthreads-7.0.0"
    ln -s mingw-w64-v7.0.0/mingw-w64-libraries/winstorecompat "${SRCDIR}/mingw-w64-winstorecompat-7.0.0"
    ```

# ビルド手順

1. binutils-2.34

    ```
    rm -rf "${BUILDDIR}" "${DESTDIR}"
    mkdir "${BUILDDIR}"
    cd "${BUILDDIR}"
    "${SRCDIR}/binutils-2.34/configure" \
         --build="${CONFIG_BUILD}" \
          --host="${CONFIG_BUILD}" \
        --target="${CONFIG_TARGET64}" \
              --prefix="${MINGW64DIR}" \
        --with-sysroot="${MINGW64DIR}" \
        --enable-targets="${CONFIG_TARGET64},${CONFIG_TARGET32}"
    make
    make install "DESTDIR=${DESTDIR}"
    ln -s "${CONFIG_TARGET64}" "${DESTDIR}${MINGW64DIR}/mingw"
    ln -s lib "${DESTDIR}${MINGW64DIR}/${CONFIG_TARGET64}/lib64"
    ```

1. mingw-w64-headers-7.0.0

    ```
    rm -rf "${BUILDDIR}" "${DESTDIR}"
    mkdir "${BUILDDIR}"
    cd "${BUILDDIR}"
    "${SRCDIR}/mingw-w64-headers-7.0.0/configure" \
         --build="${CONFIG_BUILD}" \
          --host="${CONFIG_TARGET64}" \
        --target="${CONFIG_TARGET64}" \
        --prefix="${MINGW64DIR}/${CONFIG_TARGET64}"
    make
    make install "DESTDIR=${DESTDIR}"
    ```

1. gcc-9.3.0 （1回目）

    ```
    rm -rf "${BUILDDIR}" "${DESTDIR}"
    mkdir "${BUILDDIR}"
    cd "${BUILDDIR}"
    "${SRCDIR}/gcc-9.3.0/configure" \
         --build="${CONFIG_BUILD}" \
          --host="${CONFIG_BUILD}" \
        --target="${CONFIG_TARGET64}" \
              --prefix="${MINGW64DIR}" \
        --with-sysroot="${MINGW64DIR}" \
        --enable-languages=c,c++ \
        --enable-tagets=all
    make all-gcc
    make install-gcc "DESTDIR=${DESTDIR}"
    ```

1. mingw-w64-crt-7.0.0

    ```
    rm -rf "${BUILDDIR}" "${DESTDIR}"
    mkdir "${BUILDDIR}"
    cd "${BUILDDIR}"
    "${SRCDIR}/mingw-w64-headers-7.0.0/configure" \
         --build="${CONFIG_BUILD}" \
          --host="${CONFIG_TARGET64}" \
        --target="${CONFIG_TARGET64}" \
              --prefix="${MINGW64DIR}/${CONFIG_TARGET64}" \
        --with-sysroot="${MINGW64DIR}/${CONFIG_TARGET64}" \
        --enable-lib32 \
        --enable-lib64
    make
    make install "DESTDIR=${DESTDIR}"
    ```

1. gcc-9.3.0 （2回目）

    ```
    rm -rf "${BUILDDIR}" "${DESTDIR}"
    mkdir "${BUILDDIR}"
    cd "${BUILDDIR}"
    "${SRCDIR}/gcc-9.3.0/configure" \
         --build="${CONFIG_BUILD}" \
          --host="${CONFIG_BUILD}" \
        --target="${CONFIG_TARGET64}" \
              --prefix="${MINGW64DIR}" \
        --with-sysroot="${MINGW64DIR}" \
        --enable-languages=c,c++ \
        --enable-tagets=all
    make
    make install "DESTDIR=${DESTDIR}"
    ```

1. gmp-6.2.0

    ```
    rm -rf "${BUILDDIR}" "${DESTDIR}"
    mkdir "${BUILDDIR}"
    cd "${BUILDDIR}"
    "${SRCDIR}/gmp-6.2.0/configure" \
         --build="${CONFIG_BUILD}" \
          --host="${CONFIG_TARGET64}" \
        --target="${CONFIG_TARGET64}" \
        --prefix="${MINGW64DIR}/${CONFIG_TARGET64}" \
        --enable-static \
        --disable-shared
    make
    make install "DESTDIR=${DESTDIR}"
    ```

1. mpfr-4.0.2
    gmp-6.2.0と同じです。

1. mpc-1.1.0
    gmp-6.2.0と同じです。

1. mingw-w64-libmangle-7.0.0
    mingw-w64-headers-7.0.0と同じです。

1. mingw-w64-winpthreads-7.0.0
    mingw-w64-headers-7.0.0と同じです。

1. mingw-w64-winstorecompat-7.0.0
    mingw-w64-headers-7.0.0と同じです。

# 動作確認

- コンソールプログラム
    - hello.c

        ```
        #include <stdio.h>

        int main(void)
        {
            printf("hello, world\n");
            return 0;
        }
        ```

    - コンパイル

        ```
        "${MINGW64DIR}/bin/${CONFIG_TARGET64}-gcc" -o hello.exe hello.c
        ```

    - 実行結果

        ```
        C:> hello.exe
        hello, world
        ```

- ウィンドウプログラム
    - hellow.c

        ```
        #include <windows.h>

        int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
        {
            MessageBox(NULL, "hello, world", "hellow", MB_OK);
            return 0;
        }
        ```

    - コンパイル

        ```
        "${MINGW64DIR}/bin/${CONFIG_TARGET64}-gcc" -mwindows -o hellow.exe hellow.c
        ```

    - 実行結果
        ![hellow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628049/9bd74532-9c38-2153-2a06-30382ae8811d.png)