LoginSignup
8
10

More than 3 years have passed since last update.

WSL の MinGW-w64 で Windows 用の実行バイナリを作成する

Last updated at Posted at 2021-03-25

Windows 上で Linux を動かすのが Windows Subsystem for Linux (WSL) ですが、その上で、Linux 上で Windows 用の実行バイナリを生成できる MinGW-w64 を使ってみました。

よくある記事だと「WSL と MinGW-w64 のどちらを使うか」のような内容が書かれていますが、本記事では「WSL 上で MinGW-w64 を使用」します。

1. WSL で MinGW-w64 をインストール

例えば Ubuntu であれば apt install でインストールできます。
環境に応じたパッケージ管理システムを使用してください。

ここでは簡単のために 64bit 版の g++ とその依存パッケージのみインストールします (状況に応じて必要なパッケージをインストールしてください) 。

x86-64 が 64bit 用で i686 が 32bit 用です。

sudo apt install g++-mingw-w64-x86-64

2. 依存ライブラリを静的リンクする (状況に応じて)

実行ファイルを複数含むようなソフトウェアを公開する場合には、DLL を付属した方が合計の容量を小さくできると思いますが、単一の実行ファイルの場合は静的リンクした方が単純にファイル数を少なくできます。

まず、libgcc は (おそらく) 絶対必要になります。また、状況に応じて他のライブラリも必要になります。

一度コンパイルして、依存ライブラリを調べる
x86_64-w64-mingw32-g++ -o main.exe main.cpp
x86_64-w64-mingw32-objdump -p main.exe | grep 'DLL Name'
出力の例
        DLL Name: KERNEL32.dll
        DLL Name: msvcrt.dll
        DLL Name: libstdc++-6.dll

(※ libgcc はこの方法では確認できない?)

KERNEL32.dllmsvcrt.dll は Windows に標準で含まれる DLL のため、ここでは libgcclibstdc++ を静的リンクすることにします。

依存ライブラリを静的リンクしてコンパイル
x86_64-w64-mingw32-g++ -static-libgcc -static-libstdc++ -o main.exe main.cpp

これで、DLL を付属しなくてもエラーが出ずに実行できる Windows 用の実行バイナリを生成できます。

3. おまけ: WSL 上でも Windows 用の実行バイナリを実行できる

拡張子 .exe を付けることで、WSL 上でも exe ファイルを実行できます

自身で作成したアプリケーションに限らず、Windows 用の CUI アプリケーションを実行して、そこから Linux のコマンドで grep するといった使い方ができ、便利です。

CUI アプリケーションを作成する場合は、そのまま WSL 上で動作確認を行うことができます。

※文字コードが合わず文字化けする場合は nkf コマンド等で対処してください。
※システムの情報にアクセスする必要があるなど、高度なことをする場合には WSL 上で動作しないことがあります。

4. その他注意点

4.1. ソースコードの文字コードが Shift_JIS (CP932) 以外の場合

ソースコードの文字コードが CP932 以外の場合、実行時に、GUI のテキスト等で日本語等が文字化けするので、コマンドラインオプションで文字コードを指定します。

g++ で UTF-8 のソースコードを使用する例
x86_64-w64-mingw32-g++ -finput-charset=UTF-8 -fexec-charset=CP932 \
    -static-libgcc -static-libstdc++ -o main.exe main.cpp

g++ では -finput-charset=UTF-8 -fexec-charset=CP932 のように指定できます。

4.2. MinGW-w64 で wmainwWinMain を使いたい場合

MinGW-w64 では、g++ のコマンドライン引数で -municode を指定することで、wmainwWinMain を使用することができます。

※無印の MinGW では (おそらく) -municode を使用できないので注意。

また、マルイバイト文字列のコマンドライン引数は、GetCommandLineW() 関数と CommandLineToArgvW() 関数を使って便利に取得することができます。

4.3. MinGW-w64 の std::wcout で日本語等の文字列が出力されない問題

#include <fcntl.h> して _setmode(fileno(stdout), _O_U8TEXT); すると出力できます (コンパイルオプションにより異なる?) 。

MinGW-w64 では std::basic_ios::imbue()std::locale() で対処できないようです…。

MinGW-w64 で std::wcout を使用する例
#include <iostream>
#include <fcntl.h>

int wmain() {

    _setmode(fileno(stdout), _O_U8TEXT);

    std::wcout << L"にゃ" << std::endl;

    return 0;

}

参考「_setmode | Microsoft Docs

8
10
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
8
10