web-dev-qa-db-ja.com

デフォルトでCMakeで最適化する

CMakeをビルドシステムとして使用するC++プロジェクトがあります。次の動作が欲しい:

Cmakeがcmake ..として呼び出される場合、CMAKE_CXX_FLAGS-O3 -Wall -Wextraです

Cmakeがcmake .. -DCMAKE_BUILD_TYPE=Debugとして呼び出される場合、CMAKE_CXX_FLAGS-g -Wall -Wextraです

私は次を試しました

message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")

set(CMAKE_CXX_FLAGS "-O3 -Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra")

しかし、これには大きな問題があります。まず、2番目の呼び出しが使用される場合、-O3フラグと-gフラグの両方がコンパイラーに渡されます。さらに、2番目の呼び出しとその後の最初の呼び出しを使用すると、CMAKE_BUILD_TYPEDebugのままになりますが、明示的に順序付けされていません。

どうして?目的の動作を得るにはどうすればよいですか?

20
marmistrz

まず、CMakeの推奨される使用法は、コマンドラインで常に明示的にCMAKE_BUILD_TYPEを指定することです(単一構成ジェネレーターを使用する場合のみ)。ユースケースはこのベストプラクティスから逸脱しているため、この答えを「どのように行うことができるか」ではなく、「どのように行うべきか」として扱う必要はありません。

最初の問題に対処するには、CMakeListの早い段階でこれを行うことができるはずです。

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Release)
endif()

set(CMAKE_CXX_FLAGS "-Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")

これにより、ビルドタイプをまったく指定しない場合、デフォルトで「リリース」になり、CMAKE_CXX_FLAGS_RELEASEが使用されるようになります。

2番目の方法は対処が困難です。コマンドラインから渡された変数(CMAKE_BUILD_TYPE=Debugなど)は、CMakeによってcachedであり、したがって後続の呼び出しで再利用されます(CMakeを変更するとCMake自体が再トリガーされるため、必要です)ビルド間の入力)。

唯一の解決策は、cmake .. -DCMAKE_BUILD_TYPE=Releaseを使用して、ユーザーがビルドタイプを再度明示的に切り替えることです。

なぜこれが必要なのかを考えてみてください。私が言ったように、CMakeの入力(CMakeLists.txtファイルまたはその依存関係)が最後のCMakeの実行以降に変更された場合、CMakeはビルドの一部として自分自身を再トリガーできます。そのような場合、-DCMAKE_BUILD_TYPE=whateverなどのコマンドライン引数なしで実行され、前回と同じ値を提供するためにキャッシュに依存します。このシナリオは、追加の引数なしでcmake ..を手動で実行することと区別できません。

コマンドラインで明示的に指定されていない場合は、CMAKE_BUILD_TYPEReleaseに常にリセットするためのハッキングソリューションを提供できます。ただし、自動再生成が発生した場合、Debugとして生成されたビルドシステムがReleaseとして再生成されることも意味します。それはあなたが望んでいるものではないと確信しています。

40
Angew

リリースターゲット固有のCXXフラグについては、設定する必要があります
CMAKE_CXX_FLAGS_RELEASE
の代わりに
CMAKE_CXX_FLAGS

あなたの場合、次を使用できます:

set(CMAKE_CXX_FLAGS "-Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")

より最新のCMakeアプローチ(CMakeバージョン2.8.12以降を使用している場合、これをお勧めします)は このStackOverflowの回答 で詳しく説明されており、 target_compile_options の使用が含まれます。

8
roalz