2013-10-13 13 views
11

私はプロトコルバッファファイルがサブディレクトリにあるプロジェクトでFindProtobufモジュールを使用しています。そのサブディレクトリにあるCMakeLists.txtファイルにprotocを呼び出してCPPファイルを生成させます。マイプロジェクトフォルダ構造は次のようである:CMakeとFindProtobuf

cammy/CMakeLists.txt # Root CMakeLists.txt 
cammy/protofiles/test.proto # protofile 
cammy/protofiles/CMakeLists.txt 

私は(FindProtobuf)、find_package呼び出しといるProtobufフォルダ内のCMakeLists.txtファイル内PROTOBUF_GENERATE_CPPへの呼び出しが含まれています。

実行可能なビルドステップはルートCMakeLists.txtファイルにあり、生成されたファイル をこのファイルの実行可能ファイルに追加します ie。私はcmakeのを実行すると

add_executable(${EXEC} ${SRCS} ${PROTO_SRC} ${PROTO_HEADER}) 
target_link_libraries(${EXEC} ${PROTOBUF_LIBRARIES}) 

が両方のルートCMakeLists.txtに

を定義している、それはソースが私がexpilicitlyことにより、依存関係を作成する実行可能ファイルに生成されたソースを結ぶにもかかわらず、ファイルを生成するprotocを実行しません。

protofilesフォルダ内のCMakeLists.txtのすべての内容をルートCMakeLists.txtに移動すると、protoファイルがコンパイルされます。

誰もがこれを手伝ってくれますか? protofilesフォルダに作成されたCMakeLists.txtファイルに、すべてのプロトコルバッファビルド用のものが必要です。

私はまた、内部のCMakeLists.txt(PROTO_SRCのような)で生成された変数が、印刷時に内側のファイルに定義されていることに気付きました(つまり、正しいCPPファイル名を取得します)。 。 それは空です。そのほとんどは、私が "export"(cmakeの方法があれば)の変数をルートフォルダにエクスポートする必要があるかのようです。

ご協力いただければ幸いです。

おかげ Kartik

答えて

19

私はFindProtobufは本当にこの方法を使用するためのものではないと思います。そのドキュメントから:

注:PROTOBUF_GENERATE_CPPマクロ& add_executable()またはadd_library() 呼び出しは、同じディレクトリに正常に動作。

あなたはサブディレクトリにPROTOBUF_GENERATE_CPPマクロを使用しようとしている、とCMakeのドキュメントは本当にそれを明確にしませんが、サブディレクトリは、変数のための新しいスコープが導入されました。つまり、サブディレクトリ範囲で設定または変更された変数は、親スコープ内の同様の名前の変数には影響しません。したがって、PROTO_SRCの理由は、あなたのprotofilesディレクトリで利用可能ですが、親ではありません。

範囲を変数を渡す方法は、あなたができるprotofiles/CMakeLists.txtにおけるので、set(... PARENT_SCOPE)を使用することです:

PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_HEADER test.proto) 

set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIRS} PARENT_SCOPE) 
set(PROTOBUF_LIBRARIES ${PROTOBUF_LIBRARIES} PARENT_SCOPE) 
set(PROTO_SRC ${PROTO_SRC} PARENT_SCOPE) 
set(PROTO_HEADER ${PROTO_HEADER} PARENT_SCOPE) 

しかし、これはまだ私たちにすべての方法を取得していません!

CMakeは実際にprotocコンパイラを呼び出して.pb.hファイルと.pb.ccファイルを生成しません。これはadd_custom_commandを使用します。カスタムコマンドは.pb.hと.pbを指定します。これらのファイルに依存する後続のターゲットが構築される場合にのみ、カスタムコマンドが呼び出される(すなわち、protocが実行される)。

したがって、設定時(CMakeが実行されるとき)には、これらのファイルは存在しません。 add_libraryまたはadd_executableコマンドにソースとして追加しようとすると問題になります - 実行時にこれらのファイルが存在しないことをCMakeに伝える必要がありますが、作成時にはになります。

これを行う方法は、GENERATEDプロパティをTRUEに設定することです。 PROTOBUF_GENERATE_CPPマクロはそれを自動的に行いますが、変数と同様に、プロパティは親スコープに読み込まれません。だからあなたのトップレベルのCMakeLists.txtに、あなたも追加する必要があります。対応add_library/add_executableコマンドに異なるディレクトリで使用して

set_source_files_properties(${PROTO_SRC} ${PROTO_HEADER} PROPERTIES 
          GENERATED TRUE) 

あなたが見ることができるように、PROTOBUF_GENERATE_CPPビット壊れやすいれます。 の場合はにすることを避けてください。

+0

ありがとうございます。要約すると、ネストされたprotoコンパイルがうまくいかない理由は、生成された変数がルークの範囲にないためです。また、親スコープ変数をルートファイルで設定する代わりにローカルスコープ変数を設定するときに、GENERATEDフラグをマークすることは可能ですか?最後に、protobufのものをライブラリとして構築し、それをルート実行可能ファイルにリンクする代わりの方法がありますか? –

+0

@ KartikAiyer "ルークの範囲にない"という意味は分かりませんが、 "トップレベルのCMakeLists.txt"の範囲にない場合は、はいです。 Q2の場合は、親スコープで定義されているファイルにプロパティを設定する方法がないということは分かっています。 Q3のために、はい - 私はそれが良いアプローチだと信じています。 – Fraser

+0

@Fraserあなたの答えをありがとう、私は似たような質問があります、私はプロジェクトを調整し、まだ動作しない、それは私にもっと提案を与える可能ですか? ref:http://stackoverflow.com/questions/29720410/no-member-found-when-use-cmake-construct-proto、サンプルプロジェクト:https://github.com/yuikns/cmake-proto –