CMakeプログラミング:link_directories()の基本と非推奨の理由

2025-05-27

  1. ライブラリ検索パスの追加:

    • このコマンドに指定したディレクトリが、リンカがライブラリを探すパスのリストに追加されます。
    • 例: link_directories(/usr/local/lib /opt/mylibs/lib) これにより、リンカは/usr/local/lib/opt/mylibs/libの順でライブラリを探すようになります。
  2. 相対パス:

    • 相対パスを指定した場合、それは現在のCMakeLists.txtファイルがあるディレクトリからの相対パスとして解釈されます。
  3. 適用範囲:

    • link_directories()が呼び出された後に作成されるターゲット(実行可能ファイルやライブラリ)にのみ適用されます。それ以前に作成されたターゲットには影響しません。
  4. 推奨されない理由 (モダンCMake):

    • 現在のCMakeのベストプラクティスでは、link_directories()の使用は推奨されていません
    • 代わりに、target_link_directories()またはtarget_link_libraries()を使用することが推奨されます。
    • なぜ推奨されないのか?
      • link_directories()はグローバルな設定に近い挙動をします。つまり、一度設定すると、その設定が現在のCMakeLists.txtファイルとそのサブディレクトリに影響を与え、意図しないライブラリがリンクされたり、異なるバージョンのライブラリが意図せず使われたりする可能性があります。
      • プロジェクトが大きくなると、どのライブラリがどのターゲットにリンクされているのかを追跡するのが困難になります。
      • ライブラリの検索パスがプロジェクト全体に影響を与えるため、他のプロジェクトとの競合が発生する可能性もあります。
  5. target_link_directories()target_link_libraries() の利点:

    • これらは特定のターゲットに対してライブラリの検索パスやライブラリ自体を明示的に指定します。
    • これにより、ビルドシステムがよりモジュール化され、依存関係が明確になります。
    • ターゲットごとに必要なライブラリと検索パスを管理できるため、大規模なプロジェクトでの管理が容易になります。


link_directories()に関する一般的なエラーとトラブルシューティング

リンカがライブラリを見つけられない(undefined reference または cannot find -l<library_name>)

これは最もよくあるエラーです。リンカが、プログラムが依存するライブラリのファイル(.lib.a.so.dylibなど)を見つけられない場合に発生します。

原因

  • ライブラリ名が間違っている。例えば、libmylib.soというファイル名なのにtarget_link_libraries(my_exe mylib)ではなくtarget_link_libraries(my_exe libmylib)と書いている、など。CMakeは通常libプレフィックスと拡張子を自動的に処理しますが、場合によっては問題になることもあります。
  • link_directories()の呼び出しが、ライブラリをリンクするターゲット(add_executable()add_library())の後に行われている。link_directories()は、呼び出し後に作成されるターゲットにのみ影響します。
  • ライブラリファイル自体が、指定したパスに存在しないか、名前が間違っている。
  • link_directories()で指定したパスが間違っている。

トラブルシューティング

  • デバッグ出力の活用
    • message("Checking library path: ${YOUR_LIBRARY_PATH}") のようにして、CMakeが実際に認識しているパスを確認します。
    • CMAKE_C_LINK_FLAGSCMAKE_CXX_LINK_FLAGS といった変数に-Lオプションが適切に追加されているかを、ビルドシステムのログや生成されたMakefile(またはVisual Studioプロジェクトファイル)で確認します。
    • cmake --build . --verbose を実行して、コンパイルとリンクのコマンドラインを確認し、-Lオプションと-lオプションが正しいかを確認します。
  • ライブラリ名の確認
    target_link_libraries()で指定しているライブラリ名が正しいことを確認します。通常、lib<name>.soの場合は<name>を指定します(例: libfoo.soならfoo)。
  • 呼び出し順序の確認
    link_directories()の行が、対象のadd_executable()add_library()の行よりも前に来ていることを確認します。
  • ファイル存在の確認
    指定したディレクトリに、目的のライブラリファイルが実際に存在するかどうかをファイルシステムで確認します。
  • パスの確認
    link_directories()に指定したパスが正しいことを確認します。絶対パスを使用し、タイポがないか注意深く確認してください。

相対パスに関する問題

link_directories()で相対パスを使用すると、予期せぬ動作をすることがあります。

原因

  • CMakeのポリシーCMP0015が古い設定になっている場合、相対パスの解釈が変わる可能性があります。
  • 相対パスは、link_directories()が呼び出されたCMakeLists.txtファイルからの相対パスとして解釈されます。しかし、サブディレクトリでの処理や異なるビルドツリーの構造によっては、この解釈が期待通りにならないことがあります。

トラブルシューティング

  • cmake_policy(SET CMP0015 NEW)
    相対パスの解釈が一貫しない場合は、プロジェクトのルートCMakeLists.txtでこのポリシーを設定することを検討します。ただし、これは他の挙動にも影響を与える可能性があるため、注意が必要です。
  • 絶対パスの使用
    可能な限り、link_directories()には絶対パスを使用することを強く推奨します。CMAKE_SOURCE_DIRCMAKE_BINARY_DIRなどのCMake変数と/を組み合わせて絶対パスを構築します。 例: link_directories(${CMAKE_SOURCE_DIR}/libs)

グローバルな影響と競合

link_directories()は、一度設定されるとそれ以降のすべてのターゲットに影響を与えるため、大規模なプロジェクトで予期せぬ競合を引き起こすことがあります。

原因

  • 誤って広範囲にわたるディレクトリを追加してしまい、意図しないライブラリが選択されてしまう。
  • 異なるモジュールやサードパーティライブラリが、同じ名前の異なるバージョンのライブラリを依存している場合。

トラブルシューティング

  • link_directories()の使用を避ける(推奨)
    根本的な解決策は、link_directories()の使用を段階的に廃止し、より現代的なCMakeのプラクティスに移行することです。
    • target_link_libraries(<target> PRIVATE|PUBLIC|INTERFACE <library>): ライブラリをリンクする際に、そのライブラリの絶対パスを直接指定するか、find_package()find_library()で取得した絶対パスを使用します。これが最も推奨される方法です。 例: target_link_libraries(my_exe PRIVATE /path/to/my/libmylib.so)
    • target_link_directories(<target> PRIVATE|PUBLIC|INTERFACE <dir>): 特定のターゲットに対してのみライブラリの検索パスを追加したい場合にこれを使用します。link_directories()よりもスコープが限定されます。 例: target_link_directories(my_exe PRIVATE ${CMAKE_SOURCE_DIR}/my_custom_libs)
    • find_package() / find_library()の使用: 外部ライブラリを使用する場合、CMakeのfind_package()コマンド(もしライブラリがCMakeモジュールを提供していれば)やfind_library()コマンドを使用して、ライブラリのパスを自動的に見つけさせます。これにより、システムごとに異なるパスに対応しやすくなります。

ビルドシステム固有の問題(例: Visual Studio)

WindowsのVisual StudioのようなIDEでは、CMakeが生成するプロジェクトファイルが、期待通りのリンカ設定になっていない場合があります。

原因

  • 特定のビルド設定(Debug/Releaseなど)でパスの解釈が異なる。
  • CMakeとVisual Studioのバージョンの不一致。
  • CMakeの変数を利用した条件分岐
    CMAKE_BUILD_TYPEなどの変数を使用して、Debug/Releaseビルドで異なるライブラリパスを指定する必要がある場合は、CMakeLists.txt内で条件分岐を行います。 例:
    if(CMAKE_BUILD_TYPE STREQUAL "Debug")
        link_directories(${CMAKE_CURRENT_BINARY_DIR}/Debug/libs)
    else()
        link_directories(${CMAKE_CURRENT_BINARY_DIR}/Release/libs)
    endif()
    
    (これもtarget_link_directoriesや絶対パスで代替可能です)
  • 生成されたプロジェクトファイルの確認
    Visual Studioでプロジェクトを開き、プロジェクトのプロパティからリンカの検索パスを確認します。CMakeが生成した内容と期待値が一致しているかを確認します。
  • CMakeのドキュメントを参照する
    公式ドキュメントは、各コマンドの挙動や推奨される使い方について最も正確な情報源です。
  • CMakeキャッシュのクリア
    問題が解決しない場合、buildディレクトリを削除し、CMakeキャッシュをクリアしてから再度設定(cmake ..)してみるのも有効です。
  • シンプルに始める
    まずは最小限のCMakeLists.txtで問題のライブラリだけをリンクしてみて、それが機能するかどうかを確認します。
  • エラーメッセージをよく読む
    リンカエラーは詳細な情報を提供することが多いです。どのライブラリが見つからないのか、どのシンボルがundefinedなのかを特定することが重要です。


シナリオ: カスタムライブラリ my_library とそれを使用する実行可能ファイル my_executable

ここでは、以下のようなディレクトリ構造を仮定します。

.
├── CMakeLists.txt
├── lib
│   ├── CMakeLists.txt
│   └── my_library.cpp
└── src
    ├── CMakeLists.txt
    └── main.cpp
  • src/main.cpp: my_libraryを使用する実行可能ファイルmy_executableのソースコード。
  • lib/my_library.cpp: my_libraryという名前の共有ライブラリ(またはスタティックライブラリ)をビルドするためのソースコード。

link_directories() を使用した例 (非推奨な方法)

これは、最も基本的なlink_directories()の使用例ですが、現代のCMakeでは推奨されません。

lib/my_library.cpp

// my_library.cpp
#include <iostream>

void hello_from_library() {
    std::cout << "Hello from my_library!" << std::endl;
}

src/main.cpp

// main.cpp
#include <iostream>

// my_library.h がないため、外部宣言で対応 (実際のプロジェクトではヘッダファイルを用意します)
extern void hello_from_library();

int main() {
    std::cout << "Starting my_executable..." << std::endl;
    hello_from_library();
    std::cout << "Exiting my_executable." << std.endl;
    return 0;
}

lib/CMakeLists.txt

# lib/CMakeLists.txt
add_library(my_library SHARED my_library.cpp) # 共有ライブラリとしてビルド

src/CMakeLists.txt

# src/CMakeLists.txt
add_executable(my_executable main.cpp)

# my_executable が my_library に依存することを宣言
# my_library がどこにあるかは、親の CMakeLists.txt で link_directories() を使って指定されると仮定
target_link_libraries(my_executable my_library)

. (ルート)CMakeLists.txt

# . (ルート)CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MyProject CXX)

# CMAKE_BINARY_DIR はビルドディレクトリのパスを示す
# ここでビルドされる my_library が格納されるディレクトリをリンカに教えています。
# 通常は、CMAKE_BINARY_DIR/lib のようなパスになります。
link_directories(${CMAKE_BINARY_DIR}/lib) # !!! 非推奨 !!!

# サブディレクトリを追加
add_subdirectory(lib)
add_subdirectory(src)

説明

  • ルートのCMakeLists.txtlink_directories(${CMAKE_BINARY_DIR}/lib)が重要です。 これにより、リンカはmy_libraryを探す際に、ビルドディレクトリ直下のlibディレクトリ(CMakeが共有ライブラリをデフォルトで配置する場所)を検索パスに含めます。
  • src/CMakeLists.txtmy_executableという実行可能ファイルを定義し、my_libraryにリンクしています。
  • lib/CMakeLists.txtmy_libraryという共有ライブラリを定義しています。

ビルド手順

mkdir build
cd build
cmake ..
cmake --build .

./bin/my_executableを実行すると、"Hello from my_library!" と出力されます。

問題点

  • ライブラリの依存関係が暗黙的になり、追跡が困難になります。
  • link_directories()は、そのコマンドが呼び出された後に定義されるすべてのターゲットに影響を与えます。もし他に複数のライブラリや実行可能ファイルがあり、それぞれ異なるカスタムライブラリのパスが必要な場合、このアプローチは混乱を招き、意図しないライブラリがリンクされる可能性があります。

target_link_directories() を使用した例 (より良い方法)

link_directories()の代わりに、特定のターゲットにのみ検索パスを追加するtarget_link_directories()を使用します。

lib/my_library.cpp
(変更なし) src/main.cpp: (変更なし) lib/CMakeLists.txt: (変更なし)

src/CMakeLists.txt

# src/CMakeLists.txt
add_executable(my_executable main.cpp)

# my_library のビルドディレクトリへのパスを明示的に指定
# PRIVATE はこのターゲットが内部的にこのパスを必要とすることを示す
target_link_directories(my_executable PRIVATE ${CMAKE_BINARY_DIR}/lib)

# my_executable が my_library に依存することを宣言
target_link_libraries(my_executable my_library)

. (ルート)CMakeLists.txt

# . (ルート)CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MyProject CXX)

# link_directories() を使用しない!
# add_subdirectory の順序は重要: my_library がビルドされる前に my_executable が依存することはできない
add_subdirectory(lib)
add_subdirectory(src)

説明

  • PRIVATEキーワードは、この検索パスがmy_executable自身にのみ適用され、my_executableをリンクする他のターゲットには引き継がれないことを意味します。
  • src/CMakeLists.txtで、my_executableという特定のターゲットに対してのみtarget_link_directories(my_executable PRIVATE ${CMAKE_BINARY_DIR}/lib)を用いて検索パスを追加しています。
  • ルートのCMakeLists.txtからlink_directories()が削除されました。

利点

  • プロジェクトが大きくなっても、依存関係の管理が容易になります。
  • 検索パスが特定のターゲットに限定されるため、グローバルな汚染が防がれます。

link_directories()target_link_directories()を使わずに、直接ライブラリのターゲット名を指定してリンクするのが、最も現代的で推奨される方法です。これはCMakeが内部的にライブラリの場所を解決してくれるため、検索パスを明示的に指定する必要がありません。

lib/my_library.cpp
(変更なし) src/main.cpp: (変更なし)

lib/CMakeLists.txt

# lib/CMakeLists.txt
add_library(my_library SHARED my_library.cpp)

# my_library がビルドされるディレクトリを PUBLIC として指定 (オプション)
# これは、他のターゲットが my_library をリンクする際に、
# my_library が見つかる場所を知る必要がある場合に有用です。
# ただし、同じCMakeプロジェクト内で my_library がビルドされる場合は通常不要です。
# set_target_properties(my_library PROPERTIES LINK_INTERFACE_LIBRARIES "${CMAKE_BINARY_DIR}/lib")
# または target_link_directories(my_library INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)

src/CMakeLists.txt

# src/CMakeLists.txt
add_executable(my_executable main.cpp)

# my_executable が my_library に依存することを宣言
# CMakeは my_library というターゲットを見つけて、そのビルドパスを自動的に解決します。
# my_library は現在のプロジェクト内で定義されているため、CMakeがその場所を知っています。
target_link_libraries(my_executable PRIVATE my_library)

. (ルート)CMakeLists.txt

# . (ルート)CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MyProject CXX)

# link_directories() も target_link_directories() も使用しない!
add_subdirectory(lib)
add_subdirectory(src)

説明

  • PRIVATEキーワードは、my_executablemy_libraryに内部的に依存していることを意味し、my_executableをリンクする別のターゲットがmy_libraryにも自動的にリンクされるわけではありません。
  • CMakeは、my_libraryが現在のCMakeプロジェクト内で定義されているターゲットであることを認識し、そのビルド出力パス(この場合はCMAKE_BINARY_DIR/lib)を自動的に解決してリンカに伝えます。
  • src/CMakeLists.txttarget_link_libraries(my_executable PRIVATE my_library)と記述するだけで十分です。
  • link_directories()target_link_directories()も使用していません。
  • 他のプロジェクトがこのライブラリを使用する場合でも、find_package()などを通じて依存関係を明確に定義できます。
  • グローバルな状態変更がないため、予期せぬ副作用を防ぎます。
  • ビルドパスの管理をCMakeに任せられるため、パスの指定ミスによるエラーが減少します。
  • 最もクリーンで保守が容易な方法です。
  • target_link_libraries(<target> <library_target>): 同じCMakeプロジェクト内で定義されたライブラリターゲットを直接リンクする。最も推奨されるアプローチで、CMakeが自動的にパスを解決してくれる。
  • target_link_directories(): 特定のターゲットにローカルな検索パスを追加する。特定の状況で有用だが、通常は直接ライブラリをリンクする方が良い。
  • link_directories(): グローバルな検索パスを追加する。非推奨。


link_directories()は、リンカがライブラリを検索するパスを追加するコマンドですが、そのグローバルな性質から様々な問題を引き起こす可能性があるため、現代のCMakeでは使用が推奨されていません。

以下に、推奨される代替方法を挙げます。

target_link_libraries() を使用する (最も推奨される方法)

これは、特定のターゲット(実行可能ファイルやライブラリ)が依存するライブラリを直接指定する最も一般的な方法です。

仕組み

  • システムにインストールされているライブラリや外部のライブラリの場合
    • find_package()find_library()といったコマンドを使ってライブラリのパスを特定し、その結果得られた変数(通常は絶対パス)をtarget_link_libraries()に渡します。
    • 例: target_link_libraries(my_executable PRIVATE ${OpenCV_LIBRARIES})
  • 同じCMakeプロジェクト内でビルドされるライブラリの場合
    • add_library()で定義されたライブラリターゲット名を直接指定します。CMakeは、そのライブラリのビルド出力パスを自動的に解決し、リンカに渡します。
    • 例: target_link_libraries(my_executable PRIVATE my_custom_library)

シナリオ
my_custom_libraryという共有ライブラリがあり、my_executableがそれに依存している。

lib/CMakeLists.txt

add_library(my_custom_library SHARED my_custom_library.cpp)

src/CMakeLists.txt

add_executable(my_executable main.cpp)
# my_custom_library は同じプロジェクト内で定義されたターゲット名なので、CMakeが自動的にパスを解決する
target_link_libraries(my_executable PRIVATE my_custom_library)

利点

  • Public/Private/Interfaceの指定
    ライブラリの依存関係が、そのライブラリを利用する他のターゲットに公開されるべきか(PUBLIC/INTERFACE)そうでないか(PRIVATE)を制御できます。これにより、より正確な依存関係グラフを構築できます。
  • 自動パス解決
    CMakeがライブラリのビルドパスを自動的に解決するため、手動でlink_directories()を指定する必要がありません。
  • スコープの限定
    依存関係が特定のターゲットに限定されるため、グローバルな状態汚染がありません。
  • 明確な依存関係
    どのターゲットがどのライブラリに依存しているかが明確になります。

欠点

  • CMakeの基本概念(ターゲットプロパティ、依存関係のタイプ)を理解する必要があります。

target_link_directories() を使用する

これはlink_directories()と似ていますが、検索パスを追加するスコープを特定のターゲットに限定する点で優れています。

  • PRIVATEPUBLICINTERFACEのキーワードを使用して、パスがリンカにどのように伝播されるかを制御できます。
    • PRIVATE: 指定されたターゲットのみがそのディレクトリを検索パスとして使用します。
    • PUBLIC: 指定されたターゲットとそのターゲットをリンクする他のターゲットがそのディレクトリを検索パスとして使用します。
    • INTERFACE: 指定されたターゲットをリンクする他のターゲットのみがそのディレクトリを検索パスとして使用します(指定されたターゲット自身は使用しない)。
  • 特定のターゲットに対してのみ、ライブラリの検索パスを追加します。

シナリオ
特定のディレクトリに配置されたサードパーティのライブラリ(libfoo.aなど)をリンクしたいが、find_library()を使いたくない、または使えない場合。

src/CMakeLists.txt

add_executable(my_executable main.cpp)

# my_executable が特定のサードパーティライブラリのパスを必要とする場合
# ここでは、プロジェクトのルートディレクトリ下の 'external_libs' ディレクトリにあると仮定
target_link_directories(my_executable PRIVATE ${CMAKE_SOURCE_DIR}/external_libs)

# 実際にライブラリをリンク
target_link_libraries(my_executable PRIVATE foo) # libfoo.a または foo.lib をリンク

利点

  • 特定のターゲットが必要とするカスタムのライブラリパスを柔軟に指定できる。
  • link_directories()よりもスコープが限定され、安全性が高い。

欠点

  • find_package()find_library()と組み合わせる方が、より堅牢なソリューションになることが多い。
  • 手動でパスを指定する必要があるため、ビルド環境が変わるとパスの調整が必要になる可能性がある。

find_package() および find_library() を使用する

システムにインストールされているライブラリや外部のライブラリを見つけるための標準的な方法です。link_directories()で手動でパスを追加する代わりに、CMakeの強力な検索機能を活用します。

  • find_library(<VAR> NAMES name1 [name2...])
    • 特定の名前のライブラリファイルを検索します。link_directories()で追加されたパスも検索対象に含まれますが、このコマンド自体がパスを検索し、結果を変数に格納します。
    • 例: find_library(MY_FOO_LIB NAMES foo HINTS /opt/foo/lib)
  • find_package(<PackageName>)
    • CMakeに組み込まれている、またはユーザーが提供したFind<PackageName>.cmakeモジュールを使って、特定のライブラリ(例: OpenCV, Boost, ZLib)のヘッダファイル、ライブラリファイル、コンポーネントなどを検索します。
    • 成功すると、<PackageName>_FOUND<PackageName>_INCLUDE_DIRS<PackageName>_LIBRARIESなどの変数(またはよりモダンな方式ではインポートされたターゲット)が設定されます。

シナリオ
システムにインストールされているOpenCVライブラリを使用する。

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(MyOpenCVProject CXX)

# OpenCVパッケージを検索
find_package(OpenCV REQUIRED)

# OpenCVが見つかったら
if(OpenCV_FOUND)
    message(STATUS "OpenCV found. Version: ${OpenCV_VERSION}")
    message(STATUS "OpenCV Include Dirs: ${OpenCV_INCLUDE_DIRS}")
    message(STATUS "OpenCV Libraries: ${OpenCV_LIBRARIES}")

    add_executable(my_opencv_app main.cpp)

    # OpenCVのヘッダファイルパスを追加
    target_include_directories(my_opencv_app PRIVATE ${OpenCV_INCLUDE_DIRS})

    # OpenCVのライブラリをリンク
    target_link_libraries(my_opencv_app PRIVATE ${OpenCV_LIBRARIES})
else()
    message(FATAL_ERROR "OpenCV not found!")
endif()

利点

  • 標準的
    外部ライブラリを扱う際の業界標準的なアプローチです。
  • 堅牢性
    多くのfind_packageモジュールは、ライブラリの依存関係やコンポーネントも考慮してくれます。
  • 移植性
    異なるシステム間でライブラリのインストールパスが異なっても、CMakeが自動的に見つけてくれるため、CMakeLists.txtを変更する必要がありません。

欠点

  • find_library()は特定のライブラリファイルを見つけるだけなので、ヘッダファイルパスは別途target_include_directories()で指定する必要がある。
  • Find<PackageName>.cmakeモジュールが存在しないライブラリの場合、自分で作成する必要がある。

これは、ビルド済みのライブラリや外部にインストールされているライブラリをCMakeプロジェクトに組み込む、非常に強力でモダンな方法です。find_package()が提供するインポートされたターゲットと密接に関連しています。

  • インポートされたターゲットには、そのライブラリのパス、依存関係、コンパイラオプションなどのプロパティを設定できます。
  • このインポートされたターゲットを、通常のCMakeターゲット(my_executableなど)と同じようにtarget_link_libraries()で参照できます。
  • 実際のライブラリファイルが存在する場所を明示的に指定して、CMakeプロジェクト内に「インポートされたターゲット」を作成します。

シナリオ
ビルド済みのサードパーティライブラリmylib.lib (Windows) または libmylib.so (Linux) がvendor/mylib/libにあり、対応するヘッダがvendor/mylib/includeにある。

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(MyImportedLibProject CXX)

# OSに応じてライブラリのフルパスを決定
if(WIN32)
    set(MYLIB_FULL_PATH "${CMAKE_SOURCE_DIR}/vendor/mylib/lib/mylib.lib")
else()
    set(MYLIB_FULL_PATH "${CMAKE_SOURCE_DIR}/vendor/mylib/lib/libmylib.so")
endif()

# インポートされた共有ライブラリターゲットを作成
add_library(MyVendorLib SHARED IMPORTED)

# 実際のライブラリファイルへのパスを設定
set_target_properties(MyVendorLib PROPERTIES
    IMPORTED_LOCATION "${MYLIB_FULL_PATH}"
    INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/vendor/mylib/include"
)

add_executable(my_app main.cpp)

# インポートされたターゲットをリンク
# INTERFACE_INCLUDE_DIRECTORIES が自動的に my_app の include パスに追加される
target_link_libraries(my_app PRIVATE MyVendorLib)

利点

  • 非常にクリーンで、target_link_libraries()の恩恵を最大限に活かせる。
  • find_package()が利用できない場合に、手動で同様の仕組みを構築できる。

欠点

  • ライブラリが複数あり、それぞれ複雑な依存関係を持つ場合、設定が面倒になる可能性がある。
  • 設定が少し複雑になる場合がある。

link_directories()は単純に検索パスを追加するだけですが、その影響範囲の広さから問題を引き起こしやすいため、避けるべきです。

現代のCMakeでは、以下の代替方法を優先的に検討してください。

  1. target_link_libraries(): 同じプロジェクト内のターゲットや、find_package()/find_library()で見つけたライブラリをリンクする際の第一選択肢。
  2. target_link_directories(): 特定のターゲットのみにカスタムのライブラリ検索パスを追加する必要がある場合に限って使用。
  3. find_package() / find_library(): システムや外部にインストールされたライブラリを検出する標準的な方法。
  4. IMPORTED ターゲット: ビルド済みライブラリをプロジェクトに組み込む、より構造化された方法。