Introduction
Visual Studio をつかった C++ の開発で一番遭遇率が高いのが
xxxxx.lib(alloc.cpp.obj) : error LNK2038: ‘RuntimeLibrary’ の不一致が検出されました。値 ‘MT_StaticRelease’ が MD_DynamicRelease の値 ‘main.obj’ と一致しません。
のようなエラー。
要するに、「main.obj (を生成したプロジェクト) が /MD でビルドされていて、/MT でビルドされている xxxx.lib と RuntimeLibrary が一致していないよ」ということ。
これ、いつも思うけど、どっちがどっちの設定になっているのかとても分かりにくい。げんなりする。
それはともかく、/MT とか /MD は下記の意味。本当に今更過ぎる。
- /MD
- MSVCRT.lib を .obj ファイルに挿入。実行時に MSVCRTXXX.dll が必要。
- /MDd
- MSVCRTD.lib を .obj ファイルに挿入。実行時に MSVCRTXXXd.dll が必要。
- /MT
- LIBCMT.lib を .obj ファイルに挿入。静的リンクされる。
- /MTd
- LIBCMTD.lib を .obj ファイルに挿入。静的リンクされる。
なんで、こんな当たり前なことを確認しているかというと、CMake を使う際、これらの設定を CMakeLists.txt で指定していたのだが、いつも使っていた方法が動かなくて時間を無為にしたため。
無論、Visual Studio ならプロパティを設定すればよいが、CMake を使っている以上、手動で毎回変更するのはありえない。
というわけで、もう二度と迷わないようにちゃんと調べた。
How to resolve?
世の中に流れている情報を見ると、下記みたいな記述を使って対処している事例があまりにも多い。
1 | set(CMAKE_CXX_FLAGS_RELEASE "/MT") |
かく言う自分も、ずっとこれを使っていたのだが、何故だか知らないがこれが動かない。
Visual Studio のバージョンを古くしてもダメ。
思いつくのは CMake のバージョンだが今更戻すわけにもいかず。
というか、set
によって、CMAKE_CXX_FLAGS_XXX
を変更するのは非推奨なので、何が起こっても文句は言えないのだが。
ということで、正しく動くのは下記の二通り
1 | cmake_minimum_required(VERSION 3.0.0) |
または
1 | cmake_minimum_required(VERSION 3.15.0) |
add_executable
の前後のどちらかに記述するべきなのか迷うのもあるが、後者の MSVC_RUNTIME_LIBRARY
は CMake の 3.15.0 以降が必要な点に注意。