CMakeでインクルードディレクトリを適切に追加する方法


243

1年ほど前に、CMakeのヘッダーの依存関係について質問しました

最近問題が発生したのは、CMakeがこれらのヘッダーファイルをプロジェクトの外部にあると見なしていたことが問題であることに気付きました。少なくとも、Code :: Blocksプロジェクトを生成する場合、ヘッダーファイルはプロジェクト内に表示されません(ソースファイルは表示されます)。したがって、CMakeはこれらのヘッダーをプロジェクトの外部にあると見なし、依存関係でそれらを追跡しないように思えます。

CMakeチュートリアルでのクイック検索で、include_directories私が望んでいるようには見えないものを指摘しただけです...

特定のディレクトリに含まれるヘッダーが含まれ、それらのヘッダーが生成されたMakefileによって追跡される必要があることをCMakeに通知する適切な方法は何ですか?


この質問に対する編集は混乱を招きます。元の質問と回答は、IDEでヘッダーファイルを追跡する方法でした。これは、生成されたMakefileでヘッダーファイルの依存関係が欠落していることや、その問題を解決する方法とはかなり異なります。
fdk1342

@フレッド:私はあなたが何について話しているのか分かりません。編集リビジョンが明確に示すように、最後の文は常にそこにありました。この質問に対しては、表面的な編集のみが行われ、単語は導入(または削除)されませんでした。
Matthieu M.

それが私の誤解です。気に入ったようで、段落全体が追加されました。 stackoverflow.com/questions/13703647/…共通の理解は、IDEでヘッダーファイルをリストする方法であると述べています。これは.cbpプロジェクトファイルを参照しているはずです。これで、cmake依存関係スキャナーがヘッダーファイルをMakefileの依存関係として正しく識別できない場合、それを修正する方法がありますが、完全なプリプロセッサーが含まれていないために、正しくない場合があります。
fdk1342

回答:


267

2つのことを行う必要があります。

まず、含めるディレクトリを追加します。

target_include_directories(test PRIVATE ${YOUR_DIRECTORY})

をサポートしていない非常に古いCMakeバージョン(2.8.10以前)でスタックしている場合はtarget_include_directoriesinclude_directories代わりにレガシーを使用することもできます。

include_directories(${YOUR_DIRECTORY})

次に、現在のターゲットのソースファイルのリストにヘッダーファイルを追加する必要もあります。次に例を示します。

set(SOURCES file.cpp file2.cpp ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)
add_executable(test ${SOURCES})

このようにして、ヘッダーファイルはMakefileの依存関係として表示されます。たとえば、生成された場合、生成されたVisual Studioプロジェクトにも表示されます。

複数のターゲットでこれらのヘッダーファイルを使用する方法:

set(HEADER_FILES ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)

add_library(mylib libsrc.cpp ${HEADER_FILES})
target_include_directories(mylib PRIVATE ${YOUR_DIRECTORY})
add_executable(myexec execfile.cpp ${HEADER_FILES})
target_include_directories(myexec PRIVATE ${YOUR_DIRECTORY})

ああ!私はそれが愚かであるに違いないことを知っていました。実際、私はヘッダーをリストしていません...このライブラリだけのヘッダー、またはそれが依存する可能性のあるすべてのヘッダーをリストする必要がありますか(ライブラリへの依存関係の宣言に加えて)?これは成長しているプロジェクトであり、ルートライブラリにヘッダーを追加するときに、すべての依存関係にヘッダーを追加するという考えは非常に怖いものです。
Matthieu M.

依存関係の追跡を改善するには(たとえば、ヘッダーファイルを変更すると、影響を受けるすべてのターゲットのコンパイルがトリガーされるようにするため)、はい。ただし、cmake変数を使用してヘッダーファイルを1回だけリストし、いくつかの場所で使用することができます。私の編集を参照してください。
SirDarius

1
私の質問は、相互に依存しているいくつかのライブラリーがあるという意味でした。libroot、libaはlibrootに依存し、libbはlibrootに依存しています。私は使用することができますLIBROOT_HEADER_FILESで変数をliba/CMakefileし、libb/CMakefileその後?
Matthieu M.12年

2
これは間違っています。overを使用include_directoriesないでくださいtarget_include_directories。前者は、そのディレクトリ内のすべてのターゲットに対して再帰的に設定します。後者はターゲットに設定します。前者を実行すると、CMakeのターゲットグラフの概念が崩れ、代わりにファイル階層への副作用に依存します。
アンディ

1
答えを編集して、target_include_directories最新のCMakeコードを優先するという現在の概念を反映しました。変更に同意できない場合は、お気軽にチャットに招待してください。
ComicSansMS 2018

74

まず、コンパイルコマンドラインに関してinclude_directories()ディレクトリを追加するようにCMakeに指示するために使用します-I。次に、add_executable()またはadd_library()呼び出しでヘッダーをリストします。

例として、プロジェクトのソースがにありsrc、からのヘッダーが必要includeな場合は、次のようにします。

include_directories(include)

add_executable(MyExec
  src/main.c
  src/other_source.c
  include/header1.h
  include/header2.h
)

19
本当にヘッダーを追加する必要がありadd_executableますか?CMakeはインクルードファイルの依存関係を自動的に把握していると思いました。
Colin D Bennett、

57
@ColinDBennett依存関係の理由でそれらをリストする必要はありません-CMakeは、ビルドの依存関係がない場合でも問題なく計算します。しかし、それらをリストすると、それらはプロジェクトの一部と見なされ、IDEにそのようにリストされます(これは問題のトピックでした)。
Angewは、2013

少なくともQtCreatorでは、class.cppが存在する場合にclass.hを追加する必要はありません。lonely.hだけをソースに追加する必要があります。www.th-thielemann.de/cmakeのチュートリアルを参照してください
Thの。ティーレマン2018年

19

CMakeは、Makefileを作成する他の方法(makeやqmakeなど)と比較すると、スクリプト言語に似ています。Pythonのようにクールではありませんが、それでもまだです。

「のようなものはありません人々がどのようにディレクトリをインクルードするかをさまざまなオープンソースプロジェクトで見る場合適切な方法」の。しかし、それを行うには2つの方法があります。

  1. 粗いinclude_directoriesは、現在のプロジェクトと、一連のadd_subdirectoryコマンドを介して追加する他のすべての子孫プロジェクトにディレクトリを追加します。時々人々はそのようなアプローチが遺産であると言います。

  2. よりエレガントな方法は、target_include_directoriesを使用することです。これにより、(おそらく)不必要な継承やさまざまなインクルードディレクトリの衝突なしに、特定のプロジェクト/ターゲットのディレクトリを追加できます。また、微妙な構成を実行し、このコマンドに次のマーカーのいずれかを追加することもできます。

PRIVATE-この指定されたビルドターゲットのみに使用

PUBLIC-指定されたターゲットと、このプロジェクトにリンクするターゲットに使用します

インターフェース現在のプロジェクトにリンクするターゲットにのみ使用します

PS:

  1. どちらのコマンドでも、ディレクトリにSYSTEMのマークを付けて、指定したディレクトリに警告が含まれるのはビジネスではないというヒントを与えることができます。

  2. 同様の答えは、他のコマンドの組み合わせtarget_compile_definitions / add_definitionstarget_compile_options / CMAKE_C_FLAGSです。


13

を追加しinclude_directories("/your/path/here")ます。

これはgcc-I/your/path/here/オプション付きの呼び出しに似ています。

パスを二重引用符で囲んでください。他の人はそれについて言及しなかった、そしてそれは私を2日間立ち往生させた。したがって、この答えは、CMakeに非常に慣れておらず、非常に混乱している人向けです。


7

私も同じ問題を抱えていました。

私のプロジェクトディレクトリは次のようでした:

    --project
    ---Classes
    ----Application
    -----.h and .c files
    ----OtherFolders
    --main.cpp

そして、私がそれらすべてのフォルダにファイルを含めるために使用したもの:

    file(GLOB source_files
            "*.h"
            "*.cpp"
            "Classes/*/*.cpp"
            "Classes/*/*.h"
    )

    add_executable(Server ${source_files})

そして、それは完全に機能しました。


ファイルグロブは「ビルド」時に評価され、「ビルド」時に評価されないため、cmakeは「ビルドシステムジェネレーター」であり、ファイルグロブを使用する「ビルドシステム」ではないことは、最新のcmake(バージョン3.0以降のCMake)ではお勧めできません。システム生成の時間。リンクを参照してください:gist.github.com/mbinna/c61dbb39bca0e4fb7d1f73b0d66a4fd1
ggulgulia
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.