2017-06-20 5 views
2

誰もCMakeファイルに "一度"パターンを適用する簡単な方法を知っていますか? C/C++では、以前は#pragmaが共通化されるまでヘッダファイルの先頭と末尾に#ifdef/#endifの組が必要でした。もちろん、CMakeで同じことをすることは可能ですが、明示的な条件文を必要としないならいいと思いました。cmakeファイルのinclude onceコマンドはありますか?

リビジョン:return()コマンドを実行する必要があります。そして、私はこのようなマクロを定義します:

macro(include_once) 
    if (INCLUDED_${CMAKE_CURRENT_LIST_FILE}) 
    return() 
    endif() 
    set(INCLUDED_${CMAKE_CURRENT_LIST_FILE} true) 
endmacro() 

マクロを引数なしで使用してください。それはマクロなので、ファイル自体のインクルードコマンドではなく、インクルードコマンドからの戻り値です。

作成された変数には奇妙な名前がありますが、CMakeはこれを受け入れるようです。

+1

でなければならないことあなたの設定は何ですか?複数の組み込みに対する保護が必要ですか?個人的には、私は通常、「メイン」のCMakeLists.txt(「インクルード」を取得しない)とヘルパー機能を持つモジュール(最初は複数のインクルードについては不平を言う)を持っています。私は、ここでユースケースが何であるかはよく分かりません。 – DevSolar

+0

これが必要な場合はさまざまです。具体的には、私はサブディレクトリを持つトッププロジェクトを持っており、各サブディレクトリをスタンドアロンプ​​ロジェクトにするオプションが必要です。したがって、トッププロジェクトとすべてのサブディレクトリにはすべて共有定義ファイルが含まれています。定義ファイルが物を印刷すると、それは私が望むよりもはるかに多く印刷されます。それは処理のオーバーヘッドです。それで、はい、私はこれを求める良い理由があると思います。 –

+0

サブディレクトリがスタンドアロンプ​​ロジェクトとして構築されている - 各プロジェクトの出力がスタンドアロンで完了する必要がある場合、または処理オーバーヘッドの影響(私が最も関与しているプロジェクトであっても無視できると考えられる場合)私はCMakeで処理していますが、私は1つのCMakeLists.txt(インクルード付き)からビルドしています。しかし、私はこれを休みにして、Tsyvarevの優れた答えを「方法」と「理由」の両方で指摘しています。 – DevSolar

答えて

0

ITSは明らかに詳細hereため Refer Hereを定義しました。

include(<file|module> [OPTIONAL] [RESULT_VARIABLE <VAR>] 
        [NO_POLICY_SCOPE]) 
+4

質問は「一回**一回**」に関するものでした。これは質問に答えません。 – DevSolar

3

複数のモジュールのインクルージョンに対する最も簡単なガードパターンは、あなたのcmakeのモジュールが機能foo_funcを定義している場合、あなたはこのガードを使用することができ、

if(<something-which-is-defined-in-your-module>) 
    return() 
endif() 

例:次のようになります。

if(COMMAND foo_func) 
    return() 
endif() 

実際にガードが必要ですか?

モジュールに定義されているものに依存して、モジュールは複数の包含を保護する必要があります。

多くの単純なケースでは、ガードはが不要です。:モジュールのコードは複数回含まれていても動作します。

しかし、他の場合では、間違った保護がプロポジテッドモジュールの使用を壊すことがあります。

  1. モジュールは機能又はマクロを定義:ガードがが必要とされません。

    CMakeでは、関数とマクロを何度も定義することができます。

  2. モジュールは定数変数を定義:ガードがが必要とされません。

    関数と同様に、CMakeは変数を何度も定義することができます。

    しかし、あなたが、その場合にはガードを使用している場合、それべきチェック変数、ない機能:

    if(foo_var) 
        return() 
    endif() 
    

    機能がグローバル可視性を持っているので、これはですが、変数はローカル可視性を持っています。つまり、モジュールが他のサブツリーに含まれる場合、関数はそのサブツリーに既に表示されますが、変数は表示されません。

  3. モジュールはset(CACHE)を介してグローバル変数を定義:ガード変数がset(CACHE INTERNAL)として定義されている場合にのみ必要あります。

    たとえば、set(CACHE STRING)またはfind_libraryで定義された変数には、ガードが必要ありません。ガードがが必要とされている:

  4. モジュールは、グローバルプロパティを定義します。

注意、あなたのモジュールは、グローバルのような簡単な(ないCACHE)変数を使用している場合、それは複数のサブツリーで作業することはできませんので、ガードはあなたがCMakeのファイルには何

if(foo_var) 
     message(SEND_ERROR "Module <...> cannot be included twice") 
    endif() 
関連する問題