CMAKE_BUILD_TYPE とは
cmake
を用いてビルドするとき、-DCMAKE_BUILD_TYPE
を指定すると、(きちんとCMakeLists.txt
が書かれているプロジェクトなら)適切なオプションを付けてビルドが行われる。
$ cmake -DCMAKE_BUILD_TYPE=Release # -O2 とか -DNDEBUG とかが付く
$ cmake -DCMAKE_BUILD_TYPE=Debug # -O0 とか -g とかが付く
ここによると、値としてはempty
, Debug
, Release
, RelWithDebInfo
, MinSizeRel
などが許されているらしい。
事実1: 値はcase insensitive
$ cmake -DCMAKE_BUILD_TYPE=Debug # -g が付く
$ cmake -DCMAKE_BUILD_TYPE=debug # -g が付く
$ cmake -DCMAKE_BUILD_TYPE=DEBUG # -g が付く
$ cmake -DCMAKE_BUILD_TYPE=DeBuG # -g が付く
大文字小文字は区別されず、Debug
でもDEBUG
でも通ってしまう。
事実2: Invalid valueに対して警告が出ない
$ cmake -DCMAKE_BUILD_TYPE=Dedug # typoだが、警告は出ない
cmake
の-DCMAKE_BUILD_TYPE
は、<Option>
が指定されるとCMAKE_C((XX)?)_FLAGS_<OPTION>
に含まれるオプションをコンパイルオプションに追加する。
つまり、
set(CMAKE_CXX_FLAGS "-std=c++14 -Wall")
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
となっていた場合、
$ cmake # gcc <target> -std=c++14 -Wall
$ cmake -DCMAKE_BUILD_TYPE=Debug # gcc <target> -std=c++14 -Wall -g -O0
$ cmake -DCMAKE_BUILD_TYPE=Release # gcc <target> -std=c++14 -Wall -O3 -DNDEBUG
のようにオプションが決まる。
ここで、例えば
$ cmake -DCMAKE_BUILD_TYPE=Dedug # ...?
のように存在しないオプションを指定した場合、cmake
はエラーを出してはくれず、単に
$ cmake -DCMAKE_BUILD_TYPE=Dedug # gcc <target> -std=c++14 -Wall
と、あたかも
set(CMAKE_CXX_FLAGS_DEDUG "")
何も指定しない変数が定義されているかのように振る舞ってくれる。
事実3: CMakeLists.txt 内で複雑な処理をする奴がいる
CMakeLists.txt
内では単にコンパイル対象を指定するだけでなく、cmake languageに従って様々な操作を行うことができる。
例えば、pybind11の/tools/pybind11Tools.cmakeの中では、
...
if (NOT MSVC AND NOT ${CMAKE_BUILD_TYPE} MATCHES Debug)
# Strip unnecessary sections of the binary on Linux/Mac OS
...
という操作が行われている。
${MSVC}
がFALSE
で、かつ${CMAKE_BUILD_TYPE}
が正規表現Debug
にマッチしないなら、実行ファイルのstrip
を行うセクションだ。
見ると分かる通り、この部分はcase sensitiveである。Debug
と正確に一致するかどうかのみを見ており、DEBUG
やdebug
では通らない。
結果: エラーも出ないのに、-g
も付いているのに、なぜかデバッグシンボルが付かない
$ cmake -DCMAKE_BUILD_TYPE=DEBUG
とすると、
-
cmake
- case insensitiveなので、
-DCMAKE_BUILD_TYPE=Debug
と認識し、エラーや警告は出ない。仮にそう認識しなかったとしてもどちらにせよcmake
はエラーや警告を出さない。
- case insensitiveなので、
-
CMakeLists.txt
- 各自が勝手に書いているので、case sensitiveかもしれない。その場合
-DCMAKE_BUILD_TYPE=Debug
とは区別される。もちろんそんなtypoでエラーを出すような機構は基本的にない。
- 各自が勝手に書いているので、case sensitiveかもしれない。その場合
となって、結局想定外の挙動になってしまう。
まとめ
-DCMAKE_BUILD_TYPE
の値はDebug
など、大文字から始まるcamel case。
間違えてもcmake
は怒ってはくれないし、DEBUG
とかdebug
とか書いててもほとんどの環境で通じてしまうので、問題が発生するまで気づけない(そして問題が発生しても表面には出てこない)。
十分注意して使用してほしい。