【Visual C++】自己完結型バイナリの作り方
Visual C++ には再頒布可能パッケージが必要
Visual C++で作成したEXEやDLLは、デフォルトだとランタイムDLLが動的リンクされるようになっています。
起動するにはユーザーに再頒布可能パッケージをインストールしてもらう必要があり、ちょっとした用途のソフトを配布するときには煩雑です。
作業環境
- Windows 10
- Visual Studio 2022
解決方法
ハイブリッドCRT[1]を使います。
ターゲットが Windows 10 以前の場合
Windows 10以前はハイブリッドCRTに必要なUCRTが同梱されていません。
手順2のみを行い、完全な静的リンクにしてください。
-
プロジェクトプロパティを開きます。
-
構成プロパティ > C/C++ > コード生成 > ランタイム ライブラリ
をマルチスレッド(/MT)
に変更。
-
構成プロパティ > リンカー > 入力 > 特定の既定のライブラリの無視
にlibucrt.lib
を追加。
-
構成プロパティ > リンカー > コマンドライン > 追加のオプション
に/DEFAULTLIB:ucrt.lib
を追加。
以上で完了です。
デバッグ構成の場合
それぞれ、マルチスレッド デバッグ(/MTd)
、libucrtd.lib
、/DEFAULTLIB:ucrtd.lib
に変更してください。
ハイブリッドCRTとは
ハイブリッドCRTとは、Universal CRT(UCRT)を動的リンク、Visual C++ CRTを静的リンクするハイブリット方式のことです。
ハイブリッドCRTには以下のメリットがあります。
- 自己完結型になる
- 完全な静的リンクに比べ、バイナリサイズが小さい
- UCRTにセキュリティアップデートが適応される
UCRTとVisual C++ CRT
Visual C++のCRTは元々一つでしたが、Visual Studio 2015のリファクタリングでUCRTとVisual C++ CRTに分けられました。
UCRTには標準Cライブラリ、Visual C++ CRTにはVisual C++固有の機能が含まれます。
また、UCRTはWindows 10以降、OSの一部として同梱されています。
他リンク方法との比較
Visual Studioのコンソールアプリテンプレートを作成し、Release構成(x64)を元に比較します。
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
CRTのリンク方法 | 依存関係[2] | バイナリサイズ |
---|---|---|
静的リンク | KERNEL32.dll | 202 KB (207,360 バイト) |
動的リンク | KERNEL32.dll MSVCP140.dll VCRUNTIME140.dll VCRUNTIME140_1.dll api-ms-win-crt-runtime-l1-1-0.dll api-ms-win-crt-stdio-l1-1-0.dll api-ms-win-crt-heap-l1-1-0.dll api-ms-win-crt-math-l1-1-0.dll api-ms-win-crt-locale-l1-1-0.dll |
12.0 KB (12,288 バイト) |
ハイブリッド | KERNEL32.dll api-ms-win-crt-runtime-l1-1-0.dll api-ms-win-crt-stdio-l1-1-0.dll api-ms-win-crt-heap-l1-1-0.dll api-ms-win-crt-math-l1-1-0.dll api-ms-win-crt-locale-l1-1-0.dll api-ms-win-crt-string-l1-1-0.dll api-ms-win-crt-filesystem-l1-1-0.dll |
72.5 KB (74,240 バイト) |
ハイブリッドはVisual C++ CRTへ依存がなく、UCRT[3]を動的リンクすることでバイナリサイズも縮小しています。
Visual C++が依存するDLL
Visual C++で作成したアプリは、Win32 APIやUCRTの他に以下のDLLに依存しています。
-
VCRUNTIME140.dll
(旧msvcr<version>.dll
):Visual C++ CRT -
MSVCP<version>.dll
:C++ STL
それぞれ、d
がつくデバッグ用や、clr
がつくCLR用があります。
また、末尾に_<数字>
がつくDLL(VCRUNTIME140_1.dllなど)は、既存のDLLを変更せずに機能を追加するためのDLLです。特定の機能を利用すると追加で参照されます。
これらのDLLもUCRTに依存しています。ハイブリッドCRTを使ったときに依存するUCRT APIが増えるのはそのためです。
Reference
Discussion