web-dev-qa-db-ja.com

CMake:ソースディレクトリ自体またはそのサブディレクトリの1つを追加しようとすると、target_include_directories()がエラーを出力します

私はC++ライブラリ(ヘッダーのみ)を作成しており、CMakeを使用して(Visual Studio)プロジェクトとソリューションファイルを生成しています。同じCMakeプロジェクトの一部であるテストスイートも作成しています。

自分のヘッダーのみのライブラリを表すターゲットでtarget_include_directories()を呼び出すと問題が発生し、ライブラリのコンシューマーがヘッダーファイルを見つけることができます。次のエラーメッセージが表示されます(生成は中止されませんが)。

CMake Error in CMakeLists.txt:
  Target "Fonts" INTERFACE_INCLUDE_DIRECTORIES property contains path:

    "D:/Projects/GPC/fonts/include"

  which is prefixed in the source directory.

(D:/ Projects/GPC/Fontsはライブラリプロジェクトの最上位ディレクトリです。ヘッダーファイルを最上位ディレクトリに移動しても問題は解決しません。)

私のCMakeLists.txtの問題のある行は次のとおりです(簡単にするために適合させています)。

target_include_directories(Fonts INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include")

何が悪いのか理解できません。 target_include_directories()がないと、コンシューマープロジェクトのコードはヘッダーファイルを単純に含めることができません(インストールされている形式でない限り、まだそれに達していません。いずれにしても、ビルドツリーからライブラリを使用できるようにしたいです。 、インストールなし。)

ここには基本的なものが欠けているような気がします。それでも、解決策や説明を見つけることなく、何時間も検索してきました。

24
JPNotADragon

問題の原因はtarget_include_directoriesコマンド自体ではなく、ソースパスに接頭辞が付いたパブリックまたはインターフェイスのインクルードディレクトリを持つターゲット install の試みです。

ライブラリを最初から構築する場合は絶対パスを使用することが完全に適切であり望ましいですが、そのライブラリのビルド済みバージョンを取り込むサードパーティのライブラリでは、おそらく別のインクルードパスを使用する必要があります。結局のところ、すべてのユーザーがビルドマシンのディレクトリ構造をミラーリングするのではなく、最終的に正しいインクルードパスになるようにする必要があります。

CMakeのパッケージメカニズム は、これらの両方の使用例をサポートします。ビルドツリーからライブラリを直接プルすることができます(つまり、ソースをチェックアウトしてビルドし、find_package()をポイントします。ディレクトリに)、またはインストールディレクトリから(make INSTALLを実行して、ビルド済みのものをインストールディレクトリにコピーし、find_package()thatディレクトリ)。後者のアプローチは再配置可能である必要があります(つまり、自分のマシンにビルドしてインストールし、結果のディレクトリを送信すると、別のディレクトリ構造からマシンで使用できるようになります)。前者はそうではありません。

これは非常に優れた機能ですが、インクルードディレクトリを設定するときに考慮する必要があります。マニュアルの引用 target_include_directories

インクルードディレクトリの使用要件は、通常、ビルドツリーとインストールツリーで異なります。 BUILD_INTERFACEおよびINSTALL_INTERFACEジェネレーター式を使用して、使用場所に基づいて個別の使用要件を記述することができます。相対パスはINSTALL_INTERFACE式内で許可され、インストールプレフィックスに関連して解釈されます。例えば:

target_include_directories(mylib PUBLIC  
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/mylib>  
    $<INSTALL_INTERFACE:include/mylib>  # <prefix>/include/mylib
)

BUILD_INTERFACEおよびINSTALL_INTERFACEジェネレータ式 はすべての魔法を実行します。

$<INSTALL_INTERFACE:...>

プロパティがinstall(EXPORT)を使用してエクスポートされる場合の...のコンテンツ、それ以外の場合は空。

$<BUILD_INTERFACE:...>

プロパティがexport()を使用してエクスポートされる場合、またはターゲットが同じビルドシステム内の別のターゲットによって使用される場合の...の内容。それ以外の場合は、空の文字列に展開されます。

55
ComicSansMS