CMake: find_library()とtarget_link_directories()の連携

2024-04-02

CMakeにおけるtarget_link_directories()コマンドの詳細解説

target_link_directories()コマンドは、CMakeプロジェクト内のターゲットに対して、リンカがライブラリを検索するディレクトリを指定するために使用されます。これは、ターゲットがリンクするライブラリが標準の検索パスに存在しない場合に特に重要です。

コマンドの構成

target_link_directories(<target> [BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...] [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
  • <target>: ターゲットの名前。add_executable()add_library()コマンドによって作成されたターゲットである必要があります。
  • BEFORE: オプション。指定されたディレクトリを既存の検索パスの前に追加します。
  • <INTERFACE|PUBLIC|PRIVATE>: 続く項目のスコープを指定します。
    • INTERFACE: インターフェーススコープ。このターゲットに依存する他のターゲットに対してのみディレクトリが公開されます。
    • PUBLIC: パブリックスコープ。このターゲットと、このターゲットに依存する他のターゲットに対してディレクトリが公開されます。
    • PRIVATE: プライベーツコープ。このターゲットに対してのみディレクトリが公開されます。
  • <items>: ディレクトリ名のリスト。絶対パスまたは相対パスを指定できます。相対パスの場合は、現在のソースディレクトリを基準として解釈されます。

コマンドの例

add_executable(my_app main.cpp)

# ライブラリ `libmylib` が `/usr/local/lib` ディレクトリにある場合
target_link_directories(my_app PUBLIC /usr/local/lib)

# ライブラリ `libfoo` が `build/lib` ディレクトリにある場合
target_link_directories(my_app PRIVATE build/lib)

# インターフェーススコープでディレクトリを追加する場合
target_link_directories(my_app INTERFACE /opt/include)

注意事項

  • 同じターゲットに対してtarget_link_directories()コマンドを複数回呼び出すと、指定されたディレクトリは追加されます。
  • リンカは、最初に指定されたディレクトリからライブラリを検索します。
  • ライブラリ名が完全なパス名で指定されている場合は、target_link_directories()コマンドは必要ありません。
  • 多くの場合、find_library()コマンドを使用してライブラリを見つけ、その結果をtarget_link_libraries()コマンドに渡す方が効率的です。

補足

  • 上記の説明は、CMakeバージョン3.13以降に基づいています。古いバージョンのCMakeでは、target_link_directories()コマンドの動作が異なる場合があります。
  • target_link_directories()コマンドは、Windows、Mac OS X、Linuxなど、さまざまなプラットフォームで動作します。


CMakeにおけるtarget_link_directories()コマンドのサンプルコード

add_executable(my_app main.cpp)

# ライブラリ `libmylib` が `/usr/local/lib` ディレクトリにある場合
target_link_directories(my_app PUBLIC /usr/local/lib)

# ライブラリ `libfoo` が `build/lib` ディレクトリにある場合
target_link_directories(my_app PRIVATE build/lib)

# インターフェーススコープでディレクトリを追加する場合
target_link_directories(my_app INTERFACE /opt/include)

複数のディレクトリ指定

add_executable(my_app main.cpp)

target_link_directories(my_app
  PUBLIC /usr/local/lib
  PRIVATE build/lib
  INTERFACE /opt/include
)

BEFORE オプションの使用

add_executable(my_app main.cpp)

# 既存の検索パスよりも前に `/usr/local/lib` ディレクトリを追加
target_link_directories(my_app BEFORE PUBLIC /usr/local/lib)

find_library()コマンドとの組み合わせ

add_executable(my_app main.cpp)

find_library(LIBMYLIB mylib)

target_link_libraries(my_app PUBLIC ${LIBMYLIB})

システムライブラリのリンク

add_executable(my_app main.cpp)

target_link_libraries(my_app PUBLIC pthread)

静的ライブラリと共有ライブラリのリンク

add_executable(my_app main.cpp)

# 静的ライブラリ
target_link_libraries(my_app PUBLIC /path/to/libmylib.a)

# 共有ライブラリ
target_link_libraries(my_app PUBLIC /path/to/libmylib.so)

異なるコンパイル環境での使用

if(CMAKE_COMPILER_IS_GNUCXX)
  target_link_directories(my_app PUBLIC /usr/local/lib/gcc)
else()
  target_link_directories(my_app PUBLIC /usr/local/lib/clang)
endif()

デバッグとリリースビルドでの使用

set(CMAKE_BUILD_TYPE Debug)

target_link_directories(my_app PUBLIC /path/to/debug/lib)

set(CMAKE_BUILD_TYPE Release)

target_link_directories(my_app PUBLIC /path/to/release/lib)

インクルードパス設定

target_include_directories(my_app PUBLIC /opt/include)

キャッシュのクリア

target_link_directories()コマンドの呼び出し後にCMakeキャッシュをクリアする必要がある場合があります。これは、cmake --clean-cacheコマンドを実行することで行えます。

  • 上記のサンプルコードは、あくまでも参考として使用してください。
  • 具体的な使用方法については、CMakeのドキュメントを参照してください。


CMakeでターゲットにライブラリをリンクする他の方法

find_library()コマンドを使用して、システムまたはプロジェクト内のライブラリを見つけ、その結果をtarget_link_libraries()コマンドに渡すことができます。

find_library(LIBMYLIB mylib)

target_link_libraries(my_app PUBLIC ${LIBMYLIB})

pkg-configを使用して、システムにインストールされているライブラリに関する情報を取得し、その情報をtarget_link_libraries()コマンドに渡すことができます。

pkg_check_modules(LIBMYLIB REQUIRED mylib)

target_link_libraries(my_app PUBLIC ${LIBMYLIB_LIBRARIES})

手動でライブラリパスとライブラリ名を指定

target_link_libraries()コマンドに、ライブラリパスとライブラリ名を直接指定することができます。

target_link_libraries(my_app PUBLIC /usr/local/lib/libmylib.a)

外部プロジェクトとしてビルドされたライブラリをリンクするには、add_library()コマンドを使用して外部プロジェクトをインポートし、その結果をtarget_link_libraries()コマンドに渡すことができます。

add_library(mylib SHARED IMPORTED)

set_target_properties(mylib PROPERTIES IMPORTED_LOCATION /path/to/libmylib.so)

target_link_libraries(my_app PUBLIC mylib)

まとめ

  • システムにインストールされているライブラリをリンクする場合は、find_library()コマンドまたはpkg-configを使用するのが一般的です。
  • プロジェクト内のライブラリをリンクする場合は、target_link_directories()コマンドまたはadd_library()コマンドを使用するのが一般的です。
  • 手動でライブラリパスとライブラリ名を指定する方法は、特殊な状況でのみ使用されます。



CMakeのCommandsにおけるuse_mangled_mesa()

use_mangled_mesa() は CMake の Commands における関数で、Mesa ライブラリの mangled シンボル名を解決するために使用されます。Mesa は OpenGL の実装であり、古いバージョンの Mesa ではシンボル名が mangled されるため、use_mangled_mesa() を使用してこれらのシンボル名を解決する必要があります。



CMake で変数を削除する3つの方法:unset() 以外にも使えるテクニック

<variable_name> は、削除したい変数の名前です。変数の名前は、文字、数字、下線(_)で構成され、先頭に数字以外のアクティブ文字が来る必要があります。変数の削除この例では、MY_VAR という変数を作成し、"Hello, world!" という値を設定します。その後、unset() コマンドを使用して MY_VAR を削除します。2番目の message() コマンドは、MY_VAR が削除されたことを確認するために使用されます。


CMake try_compile() を使って特定のライブラリがインストールされているかどうかを確認する方法

try_compile() は、CMake の強力なコマンドの一つで、コードを実際にコンパイルすることなく、コンパイルが成功するかどうかを確認することができます。これは、特定のコンパイラやオプションがシステム上で使用可能かどうかをテストしたり、コードの移植性を検証したりする際に非常に便利です。


CMakeの依存関係を使用したプログラミング

CMakeで依存関係を使用するには、以下の2つの方法があります。find_packageコマンドは、特定のライブラリやフレームワークがインストールされているかどうかを検出し、その場所と設定情報を提供します。外部プロジェクトを参照するadd_subdirectoryコマンドを使用して、外部プロジェクトを現在のプロジェクトに組み込むことができます。外部プロジェクトは、CMakeLists


サブディレクトリ、custom_command、ExternalProject:USE_FOLDERSプロパティの代替手段

USE_FOLDERS プロパティは、CMakeLists. txt ファイル内で以下の方法で設定できます。上記のように ON に設定すると、CMake はソースファイルとヘッダーファイルをフォルダ階層に基づいてグループ化します。デフォルトでは OFF に設定されており、フォルダ階層は考慮されません。



最適化された Release ビルドを実現: CMAKE_LANG_FLAGS_RELEASE_INIT の活用

CMAKE_LANG_FLAGS_RELEASE_INIT は、CMake の "Variables" における変数のひとつです。これは、Release ビルド設定におけるコンパイラフラグを初期化する際に使用されます。詳細CMake バージョン 3.7 で導入されました。


CMakeの CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION 変数:Windows 10 SDKのバージョンを指定する方法

CMake 変数 CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION は、Visual Studio 2015 以降で Windows 10 以上のターゲットをビルドする場合、使用する Windows SDK のバージョンを指定するために使用されます。


JOB_POOL_PRECOMPILE_HEADER プロパティ徹底解説

JOB_POOL_PRECOMPILE_HEADER は、Ninja マルチビルドシステムを使用する場合、プリコンパイル済みヘッダー生成の並列処理を制御する CMake プロパティです。このプロパティを設定することで、ビルド時間の短縮を期待できます。


CMakeポリシー CMP0097 を使用せずにターゲットのソースツリー内に存在しないファイルをソースファイルリストに追加する方法

CMakeポリシーCMP0097は、target_sources コマンドでソースファイルのリストに追加されたファイルが、ターゲットのソースツリー内に存在することを必須とするポリシーです。このポリシーは、CMakeがソースファイルを見つけるのを容易にし、ビルドエラーを防ぐために役立ちます。


CMAKE_DISABLE_PRECOMPILE_HEADERS を使用したサンプルコード

CMAKE_DISABLE_PRECOMPILE_HEADERS は、CMake でプリコンパイルされたヘッダーファイルの生成を無効にするブール型の変数です。デフォルトでは OFF に設定されており、プロジェクト内のすべてのターゲットに対してプリコンパイルされたヘッダーファイルが生成されます。