web-dev-qa-db-ja.com

単一ファイルのコンパイルフラグをオーバーライドする

プロジェクトのコンパイルにフラグのグローバルセットを使用したいと思います。つまり、トップレベルのCMakeLists.txtファイルで次のように指定します。

ADD_DEFINITIONS ( -Wall -Weffc++ -pedantic -std=c++0x )

ただし、サブディレクトリ内の特定のファイル(たとえば "foo.cpp")については、-Weffc ++(変更できない商用ライブラリを含む)を適用しないようにコンパイルフラグを切り替えたいと思います。 -Wallのみを使用するように状況を単純化するために、私は試しました:

 SET_SOURCE_FILES_PROPERTIES( foo.cpp PROPERTIES COMPILE_FLAGS -Wall )
 ADD_EXECUTABLE( foo foo.cpp )

、機能しませんでした。私も試しました

SET_PROPERTY( SOURCE foo.cpp PROPERTY COMPILE_FLAGS -Wall )
ADD_EXECUTABLE( foo foo.cpp )

そして

ADD_EXECUTABLE( foo foo.cpp )
SET_TARGET_PROPERTIES( foo PROPERTIES COMPILE_FLAGS -Wall )

、どちらも機能しませんでした。

最後に、この定義を削除してみました。

REMOVE_DEFINITIONS( -Weffc++ )
ADD_EXECUTABLE( foo foo.cpp )
ADD_DEFINITIONS( -Weffc++ )

、これも機能しませんでした(つまり、私は商用ライブラリについて多くのスタイル警告を受け取ります)。 (**注:実行可能ファイルのビルド後に-Weffc ++ディレクティブを再含めない場合、警告は抑制されます。)

また、コンパイルフラグを一時的に削除しようとしました: http://www.cmake.org/pipermail/cmake/2007-June/014614.html 、しかしそれは助けにはなりませんでした。

これに対するエレガントな解決策はありませんか?

93
J.B. Brown

上記の試みは、予想どおりに上書きするのではなく、ファイル/ターゲットにさらにフラグを追加することです。たとえば、 ソースファイルのプロパティ-COMPILE_FLAGS のドキュメントから:

これらのフラグは、このソースファイルのビルド時にコンパイルフラグのリストに追加されます。

Foo.cppの-Weffc++フラグを打ち消すことができるはずです。

set_source_files_properties(foo.cpp PROPERTIES COMPILE_FLAGS -Wno-effc++)

これには、コンパイラコマンドの-Wno-effc++の後に-Weffc++を追加する効果があり、後者の設定が優先されます。完全なコマンドを表示して、これが実際にそうであることを確認するには、次のようにします。

make VERBOSE=1

余談ですが、GNU C++標準ライブラリのメンテナーの一人は、 この回答-Weffc++についてかなり否定的な意見を述べています。

もう1つのポイントは、意図したプリプロセッサ定義ではなく、コンパイラフラグにこれを使用しているという意味で、 add_definitions を誤用していることです。

add_compile_options を使用することをお勧めします

add_compile_options(-Wall -Weffc++ -pedantic -std=c++0x)

または、CMakeバージョン<3.0の場合は、次のようにします。

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Weffc++ -pedantic -std=c++0x")

以下のコメントのさらなる質問に答えて、単一ファイルのフラグを確実にremoveすることは不可能だと思います。理由は、特定のソースファイルについて、 COMPILE_OPTIONS および COMPILE_FLAGS を持っているためです。1 ターゲットの適用されますが、これらはそのソースファイルのどのプロパティにも表示されません。

ターゲットのCOMPILE_OPTIONSから問題フラグを取り除き、それをターゲットの各ソースに個別に適用し、必要に応じて特定のソースファイルから除外することを検討できます。

ただし、これは多くのシナリオで機能しますが、いくつかの問題があります。

まず- ソースファイルのプロパティCOMPILE_OPTIONSを含めず、COMPILE_FLAGSのみを含めます。これは、ターゲットのCOMPILE_OPTIONSgenerator expression を含めることができますが、COMPILE_FLAGSはそれらをサポートしないため、問題です。したがって、フラグを検索する際にジェネレーター式に対応する必要があります。実際、フラグが1つ以上に含まれている場合は、ジェネレーター式を「解析」して、残りに再適用する必要があるかどうかを確認する必要がありますソースファイル。

2番目-CMake v3.0以降、ターゲットは INTERFACE_COMPILE_OPTIONS を指定できます。これは、ターゲットの依存関係が、ターゲットのCOMPILE_OPTIONSを介してターゲットのINTERFACE_COMPILE_OPTIONSを追加またはオーバーライドできることを意味します。したがって、ターゲットのすべての依存関係を再帰的に反復処理する必要があります(ターゲットの LINK_LIBRARIES のリストにもジェネレーター式を含めることができるため、特に簡単なタスクではありません)。 、それらのターゲットのINTERFACE_COMPILE_OPTIONSからも削除してみてください。

複雑さのこの段階で、ソースファイルから特定のフラグを無条件に削除する機能を提供するために、CMakeにパッチを提出したいと考えています。


1:ソースファイルのCOMPILE_FLAGSプロパティとは異なり、ターゲットのCOMPILE_FLAGSプロパティは廃止されることに注意してください。

112
Fraser

@Fraserの正解に追加するだけです。

特定のフォルダに特別なフラグを追加する場合は、次のようにします。

file(GLOB SPECIAL_SRC_FILES
        "path/one/src/*.cpp"
        "path/two/src/*.cpp")
set_property(SOURCE ${SPECIAL_SRC_FILES} PROPERTY COMPILE_FLAGS -Wno-effc++)

または

file(GLOB SPECIAL_SRC_FILES
        "path/one/src/*.cpp"
        "path/two/src/*.cpp")
set_source_files_properties(${SPECIAL_SRC_FILES} PROPERTIES COMPILE_FLAGS -Wno-effc++)

here のようにGLOBを使用することはお勧めしません。

3
Levon