CMakeはC/C++製のプログラムをビルドする際にほぼ必須と言っても良いツールだが、ビルドしたものを配布する際の注意点というものはあまり共有されていないように思う。
まさか万人がソフトウェアをソースコードからビルドするという訳にも行くまい。この記事ではCMakeを利用してソフトウェアを開発し、そのバイナリを配布する際の注意点について書きたいと思う。環境はWindowsに絞る。
とりあえずWindows向けのビルドでは殆どの場合においてMSVCかMinGWを用いるものと思うので、その2ツールを対象に解説する。
注意点1. リリースビルド
当然のことながら、ソフトウェアを一般に配布する場合はリリースビルドで配布するべきだ。デバッグビルドはサイズが多少大きく、遅い可能性があり、また開発者のPCの情報も含まれる可能性がある。性能的にも情報保護のためにもリリースビルドしたものを配布するようにしよう。
MSVCの場合
CMakeで使うビルドツールとしてMSVCを用いる場合、いわゆるマルチコンフィギュレーション・ビルドになる。速い話がcmake .
とかやった後にデバッグビルドかリリースビルドか選ぶということだ。
リリースビルドの場合はこのようにする。
# ビルドディレクトリのパスが「./build」の場合
cmake --build ./build --config Release
こうすると./build/Debug/
下ではなく./build/Release/
の下にビルド成果物が生成されるはずだ。
MinGWの場合
MinGWを用いる場合はシングルコンフィギュレーションなので、ビルド時ではなくコンフィギュレーション時にデバッグビルドかリリースビルドかを指定する。
これはCMAKE_BUILD_TYPE
の値で指定する。
cmake . -B ./build -DCMAKE_BUILD_TYPE=Release
cmake --build ./build
注意点2. VC++再頒布可能パッケージ問題
MSVCでビルドしたソフトには1つ大きな罠がある。
何の設定もなくMSVCでビルドしたアプリケーションは、基本的にVC++再頒布可能パッケージに依存するのである。 これはMicrosoftが用意しているいわゆるランタイムライブラリで、無設定のMSVC製のプログラムはこれがないと動かない。
これの対処法には主に2つある。
対処法A. 再頒布可能パッケージの頒布
再頒布可能パッケージは再頒布可能だから再頒布可能と銘打っているのである。
自分の開発したソフトと一緒に、「このソフトを動かすにはこのパッケージをインストールしてください」という形でインストーラ(vc_redist.x64.exe
など)を同梱する。もしくはREADMEなどにMicrosoft公式配布のリンクを書くとかしてしまえばよい。実際、そうしたソフトは世の中によくある。
再頒布可能パッケージのインストーラは以下の記事にリンクがある。
https://learn.microsoft.com/ja-jp/cpp/windows/latest-supported-vc-redist
ユーザーには多少面倒をかけるかもしれないが、例えばRPGツクール製ソフトもRTPのインストールを求めるし、そんなものだろう。
対処法B. 再頒布可能パッケージに依存しない形でビルド
設定次第では再頒布可能パッケージに依存しないようにビルドすることもできる。 これはつまりEXEファイルに組み込むということであって、その分バイナリのサイズはやや大きくなる(+200KB程度)。そこはトレードオフだ。
この方法はVisual Studio自体に慣れている人であれば知っている通り、Visual Studioで開いてプロジェクトのC/C++
>コード生成
>ランタイム ライブラリ
の設定でマルチスレッド DLL(/MD)
をマルチスレッド(/MT)
に変えるだけだ。だがもちろんいちいちVisual Studioを開くのは手間がかかる。
この設定はCMake越しでも行えるようになっている。 具体的にはCMakeプロパティのMSVC_RUNTIME_LIBRARY
の値を設定することによって行える。
set_target_properties(main PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded")
実際にはリリースビルドのときMultiThreaded
、デバッグビルドのときMultiThreadedDebug
にしたいので、以下のようになるだろう。
set_target_properties(main PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
参考: https://cmake.org/cmake/help/latest/prop_tgt/MSVC_RUNTIME_LIBRARY.html
なお、MSVC_RUNTIME_LIBRARY
の内容はCMake変数CMAKE_MSVC_RUNTIME_LIBRARY
の値で初期化される。CMakeLists.txt
には手を加えず、ビルド時に指定する運用にしても良いだろう。
cmake . -B ./build -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded
再頒布可能パッケージ依存の確認
Visual Studioを起動してプロジェクトを開き、「コード生成>ランタイム ライブラリ」の設定項目を直接確認すればよい。
また、Visual Studio付属のdumpbin
でEXEファイルを確認しても良い。
# 依存がある場合
> dumpbin /DEPENDENTS C:\hoge\hoge\build\Release\app.exe
Microsoft (R) COFF/PE Dumper Version 14.42.34436.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file C:\hoge\build\Release\app.exe
File Type: EXECUTABLE IMAGE
Image has the following dependencies:
KERNEL32.dll
MSVCP140.dll
VCRUNTIME140.dll
VCRUNTIME140_1.dll
api-ms-win-crt-runtime-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-stdio-l1-1-0.dll
api-ms-win-crt-locale-l1-1-0.dll
# 依存がない場合
> dumpbin /DEPENDENTS C:\hoge\build\Release\app.exe
Microsoft (R) COFF/PE Dumper Version 14.42.34436.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file C:\hoge\build\Release\app.exe
File Type: EXECUTABLE IMAGE
Image has the following dependencies:
KERNEL32.dll
(重要補足)CMakeのバージョン指定について
重要な注意点だが、MSVC_RUNTIME_LIBRARY
に対応するのはCMake 3.15からである。ビルドに使うCMakeはこれ以上のバージョンでなくてはならず、また最新のCMakeを使っていても適切なcmake_minimum_required
の設定がなければ有効にならない。
cmake_minimum_required(VERSION 3.15) # 3.15以上のバージョンを設定する
これはかなり忘れがちなので、もしもMSVC_RUNTIME_LIBRARY
またはCMAKE_MSVC_RUNTIME_LIBRARY
の指定をしているのに再頒布可能パッケージ依存がなくならなかったら、CMakeLists.txt
を確認して見るとよい。
おわりに
Windowsアプリ開発でVisual Studioの重さに辟易している人は多いと思う。VSCodeなどへ乗り換えている人も多いだろう。
VSCodeと組み合わせるC++環境としてはWSL&GCCやMinGW&GCCという選択肢もあり、C++の基礎の勉強が目的であればこれで事欠かないかもしれない。しかしこと一般向けのWindowsネイティブアプリ開発となると、WSLは論外だしMinGWはMicrosoft公式でないという心許なさがある。やはりMSVCのツールチェインをVSCodeから使いたくなる。
この目的においてCMakeはかなり強い選択肢で、Visual Studioのインストールさえしておけばあとは任意のテキストエディタと任意のシェルで開発を完結できる。ぜひCMake+MSVCをWindowsアプリ開発の有力な手段として検討してみてはいかがだろうか。Meson?あれはPythonアンチとしては勧める訳に行かないから...