CMake を使って複数のバージョンの VisualC++ をターゲットとしたライブラリのビルドを自動化する

VisualC++ でスタティックライブラリを使うときは、ライブラリを作る側と使う側のバージョンを合わせておく必要があります。
(厳密にはランタイム関数を使う場合に合わせておく必要がある。例えば STL を使ったライブラリを作ったなんていうとき)
つまり、VisualStudio2008 以降を対象として、ビルド済みのバイナリを配布したいというときは、
対応するすべてのソリューションファイルやプロジェクトファイルを作る必要があります。

例えば、以下のプロジェクトファイルから成るプロジェクトがあるとします。
・ライブラリ本体
単体テスト
・サンプル

対象のバージョンは、VS2008、2010、2012、2013、(2015)。
プレビュー版の2015を含めても 5バージョン×3プロジェクトファイル で、計15個の .vcproj や .vcxproj を管理する必要があります。
仕事でなければ 2008 はもう切りたいところなんだけどね。

一時は全部手動で管理しようとしたのですが、2008 ⇔ 2010 の "継続的な" 同期だけでも手を焼きました。
というか、作業は単純なのですが非常にめんどくさい。
これを全部、管理するのはあまりにも非効率で胃とか痛くなっちゃう原因になりかねません。

やりたいこと

  • VS2008 ~ 2013 までのプロジェクトファイルの生成
  • 生成したプロジェクトファイルのビルド
  • 単体テストの実行
  • ひとつのバッチファイルを叩くだけでこれらを自動化

準備

  • プロジェクトファイルを作れる CMakeLists.txt を用意しておく。
  • 対象のVisualStudio が全てインストールされていること。(多分 Express でも大丈夫)
  • VisualStudio のツールセットをロードするバッチファイルのパスを確認。(vcvarsall.bat や VsDevCmd.bat)
  • MSBuild のパスを確認。

vcvarsall.bat や VsDevCmd.bat のパスは、スタートメニューにある VisualStudio フォルダ内の「開発者コマンドプロンプト」みたいな名前のショートカットのプロパティから確認できます。

少し厄介なのは MSBuild で、.NET のパッケージに入っているものや VisualStudio に付属しているもの等、色々なところに存在しています。
ググって最初に見つかるのは "C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" あたりかな。
しかし、私の環境ではこの exe で VS2010 がビルドできませんでした。
ということで、使うのはこちらの exe → "C:\Program Files\MSBuild\12.0\Bin"
このあたりが参考になるかも → http://lalupin4.hatenablog.jp/entry/2014/01/03/003156

コマンドラインから CMake で VisualStudio プロジェクトを作る

cmake -G "ジェネレータ名"

"ジェネレータ名" には "Visual Studio 10" 等を入れます。
どんなものが使えるのかは本家ヘルプを参照。
http://www.cmake.org/cmake/help/v2.8.8/cmake.html#opt:-Ggenerator-name

※上記ヘルプにはありませんが、VS2013 を使いたいときは "Visual Studio 12" とします。

MSBuild でビルドする

MSBuild を実行する前に、現在のコマンドプロンプトに VisualStudio のツールセットをロードする必要があります。
と言っても、vcvarsall.bat または VsDevCmd.bat を実行するだけ。

call VsDevCmd.bat

ロードしたら、MSBuild を実行します。
Debug 版と Release 版 両方作りたいので、以下のように2回実行します。

MSBuild "XXXX.sln" /p:Configuration=Debug
MSBuild "XXXX.sln" /p:Configuration=Release

単体テストを実行する

ビルドして出来た exe を実行するだけです。
テストに失敗したら終了コードを 0 以外の値にしておき、エラー処理へジャンプさせています。

"Debug\UnitTest.exe"
if "ERRORLEVEL" LEQ "0" goto UNITTEST_FAILED
"Release\UnitTest.exe"
if "ERRORLEVEL" LEQ "0" goto UNITTEST_FAILED

繰り返す

CMake ~ 単体テスト実行までを、対応したいバージョンごとに繰り返します。

ここまででとりあえず動くようにはなったかな。

まとめと今後

ということで、cmake の -G オプションと MSBuild のパスあたりに気をつければ何とかできます。
記事にすると前書きの割りにあっさりしてます。

ただ、できればレジストリからインストール済みのVisualStudioのパスなりMSBuildのパスなりを取ってこれればベストなんだけど、
まずは自分の家で胃を痛めずにデプロイできればいいかなと。


今回のノリで実際に作ったプロジェクトはこちらに置いてあります。
https://github.com/lriki/Lumino.Math