CMakeでコンパイルオプションをtargetごとに設定する方法
CMakeでコンパイルオプションを足すとき、つい全体に add_compile_options() を書きたくなります。
小さいプロジェクトなら動きます。ただ、ライブラリ、アプリ、テストが増えてくると、どのターゲットにどのオプションが効いているのか分かりづらくなります。
新しく書くなら、まず target_compile_options() に寄せるのが扱いやすいです。
https://cmake.org/cmake/help/latest/command/target_compile_options.html
基本形
add_library(my_lib
src/lib.cpp
)
target_compile_options(my_lib
PRIVATE
-Wall
-Wextra
)
PRIVATE にすると、my_lib 自身のコンパイルにだけ効きます。
利用側にも伝える必要があるオプションは多くありません。警告オプションなら、まず PRIVATE でよいことが多いです。
PUBLICにする場面
ヘッダーの都合で、利用側にも同じコンパイル定義やオプションが必要な場合は PUBLIC を考えます。
ただし、警告オプションを PUBLIC にすると、利用側のターゲットにも伝播します。
target_compile_options(my_lib
PUBLIC
-Wall
)
これは便利な反面、依存先の都合でアプリ側の警告設定まで変わることになります。基本は控えめに使います。
コンパイラごとに分ける
GCC/ClangとMSVCでオプションは違います。
target_compile_options(my_app
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/W4>
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -Wpedantic>
)
このような条件付きの書き方には generator expressions を使います。
https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html
最初は読みにくく感じますが、CMakeLists.txtをOSやコンパイラごとに分岐させるよりは管理しやすいです。
add_compile_optionsとの違い
add_compile_options() は現在のディレクトリ以下に効きます。
https://cmake.org/cmake/help/latest/command/add_compile_options.html
add_compile_options(-Wall -Wextra)
簡単ですが、影響範囲が広くなりがちです。
ターゲットごとにオプションを変えたいなら、target_compile_options() の方が追いやすくなります。
まとめ
CMakeでコンパイルオプションを設定するなら、まずターゲット単位で考えます。
- 警告オプションは
target_compile_options(... PRIVATE ...) - 利用側にも必要なものだけ
PUBLIC - コンパイラ差分は generator expressions で分ける
- 全体に効かせる
add_compile_options()は影響範囲に注意する
src、app、tests のようにターゲットが分かれているなら、オプションもターゲットごとに持たせる方が後から読みやすいです。


