web-dev-qa-db-ja.com

cmakeでヘッダーファイルの依存関係を処理する

私は小さなC++プロジェクトでCMakeを使用していますが、これまでのところうまくいきます...

ヘッダーファイルを変更すると、通常、多数のソースファイル(直接または間接的にそれを含むファイル)を再コンパイルする必要がありますが、cmakeはソースのsomeのみを検出するようですファイルが再コンパイルされ、破損した状態になります。これを回避するには、プロジェクトを一掃し、ゼロから再構築しますが、makeユーティリティを使用するという目標を回避します。必要なものだけを再コンパイルします。

したがって、私は何か間違ったことをしていると思います。

私のプロジェクトは非常に単純に構成されています:

  • すべてのリソースが配置されるトップディレクトリ、メインのCMakeLists.txtが配置されます
  • すべてのパブリックヘッダーが存在する「インクルード」ディレクトリ(さまざまなサブディレクトリ内)
  • ソースファイルのすべてのサブディレクトリがある「src」ディレクトリ。srcCMakeLists.txtがそこにあります。
  • 「src」ディレクトリのサブディレクトリごとにCMakeLists.txt

メインディレクトリには次のものがあります。

cmake_minimum_required(VERSION 2.8)

project(FOO)

set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)

# Compiler Options
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=c++0x -Wall -Wextra -Werror")

include_directories($(FOO_SOURCE_DIR)/include)

add_subdirectory(src)

「src」ディレクトリ:

add_subdirectory(sub1)
add_subdirectory(sub2)
add_subdirectory(sub3)
add_subdirectory(sub4)

add_executable(foo main.cpp)

target_link_libraries(foo sub1 sub2 sub3 sub4)

sub4sub3に依存し、sub2sub1に依存します

そして、サブディレクトリ(sub3)の例:

set(SUB3_SRCS
    File1.cpp
    File2.cpp
    File3.cpp
    File4.cpp
    File5.cpp
    File6.cpp
    )

add_library(sub3 ${SUB3_SRCS})

target_link_libraries(sub3 sub1 sub2)

誰かが私の間違いを指摘してくれて、ここまたはCMakeで検索しても何も得られなかったので、私はとても簡単だと思います。

(参考のため、MSYSでcmakeバージョン2.8.2を使用しています)

[〜#〜] edit [〜#〜]

Billの提案のおかげで、CMakeによって生成されたdepend.makeファイルをチェックしましたが、実際には(かなり)欠けています。以下に例を示します。

src/sub3/CMakeFiles/sub3.dir/File1.cpp.obj: ../src/sub3/File1.cpp

うん、それだけです、インクルードのどれもまったく参照されませんでした:x

45
Matthieu M.

バイナリツリーのdepend.makeファイルを確認する必要があります。 CMakeFiles/target.dir/depend.makeにあります。 .hファイルが欠落していると思われるファイルを見つけてください。次に、cmakeのバグレポートを作成するか、cmakeメーリングリストにメールを送信します。

15
Bill Hoffman

私はちょうど同じ問題にぶつかりました。 include_directories()のパスを絶対パスから相対パスに変更した後、適切な依存関係が追加されました。

CMakeは、どのヘッダーがシステムであり、どのヘッダーがプロジェクトに関連するかを推測しようとしているように見えます。 /で始まるディレクトリが-isystem /some/pathとして渡されたため、生成された依存関係に表示されないのではないかと考えています。

${FOO_SOURCE_DIR}を相対パスに置き換えることができない場合は、適切なCMake関数を使用して相対パスを計算してみてください。つまり:

file(RELATIVE_PATH FOO_SOURCE_REL_DIR
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${FOO_SOURCE_DIR}/.)
include_directories(${FOO_SOURCE_REL_DIR}/include)
9
ony

Cppファイルにインクルードを追加する前または後にcmakeを実行しましたか?

この問題にぶつかり、cmakeを再実行すると修正されました。インクルードpost-cmakeを追加しました。

3
Edward Strange

明らかにcmakeは依存ツリーからシステムインクルードパスを削除します(このヒントをありがとう@ony)。ほとんどの場合これはおそらく理にかなっていますが、コンパイラがシステムパスであるかどうかをcmakeが認識しない場合があります。 /usr/includeを無視するカスタムgccビルドを使用していますが、cmakeはそれを無視しないと考えています。 cmakeが/usr/includeを最適化されていない依存関係にするように強制するには、次のトリックを試してください:/.をパスの前に追加します。

すべてのライブラリの依存関係でcmakeの依存関係機能を使用するようにしようとしています。これには、Linuxにデフォルトでインストールされない、または使用できない特定の「サードパーティ」ライブラリも含まれます。たとえば、Z-lib圧縮。

次のインターフェイスターゲットは、Z libインクルードが/usr/includeにない場合は正常に機能しましたが、含まれている場合は破損します。

find_package(ZLIB REQUIRED)
message(status "found zlib ${ZLIB_LIBRARIES}")
message(status "found zlib includes ${ZLIB_INCLUDE_DIRS}")
target_link_libraries(zlib_target INTERFACE ${ZLIB_LIBRARIES})
target_include_directories(zlib_target INTERFACE ${ZLIB_INCLUDE_DIRS})

最後の行を

target_include_directories(zlib_target INTERFACE /.${ZLIB_INCLUDE_DIRS})

そしてそれは働いた。現在、zlib_targetに依存するターゲットは、コンパイル中に-I/./usr/includeを自動的に取得します。

2
Mark Lakata