CMakeで共有ライブラリのRPATHを設定するときに見ること

CMakeで共有ライブラリをリンクした実行ファイルを動かすと、ビルドは通っているのに実行時にライブラリが見つからないことがあります。

Linuxなら error while loading shared libraries、macOSなら Library not loaded のようなエラーです。

このときに見るのがRPATHです。

RPATHとは

RPATHは、実行ファイルが共有ライブラリを探すためのパスです。

リンク時にライブラリが見つかっていても、実行時に同じ場所を探すとは限りません。

CMakeでは、ビルド時とinstall後で別のRPATHを設定できます。

プロパティ 役割
BUILD_RPATH build tree内で実行するときのRPATH
INSTALL_RPATH install後に使うRPATH

https://cmake.org/cmake/help/latest/prop_tgt/BUILD_RPATH.html

https://cmake.org/cmake/help/latest/prop_tgt/INSTALL_RPATH.html

build中に動かす場合

ビルドディレクトリ内で実行ファイルを動かすなら、BUILD_RPATH を設定します。

add_executable(my_app
  src/main.cpp
)

target_link_libraries(my_app
  PRIVATE
    my_shared_lib
)

set_target_properties(my_app PROPERTIES
  BUILD_RPATH "${CMAKE_BINARY_DIR}/lib"
)

ただし、CMakeは同じプロジェクト内の共有ライブラリについて、ある程度自動でRPATHを設定します。

まずは何も設定せずに動かし、外部ライブラリや特殊な配置で必要になったら足すくらいでよいです。

install後に動かす場合

install後の配置で共有ライブラリを見つけたい場合は INSTALL_RPATH を使います。

set_target_properties(my_app PROPERTIES
  INSTALL_RPATH "$ORIGIN/../lib"
)

Linuxでは $ORIGIN が実行ファイルの場所を表します。

dist/
├── bin/
│   └── my_app
└── lib/
    └── libmy_shared_lib.so

この配置なら、bin/my_app から見て ../lib を探せばよいので $ORIGIN/../lib になります。

macOSでは @loader_path を使うことがあります。

set_target_properties(my_app PROPERTIES
  INSTALL_RPATH "@loader_path/../lib"
)

install設定と一緒に見る

RPATHはinstall後の配置とセットで考えます。

install() の基本は CMakeで実行ファイルとライブラリをinstallするときの設定 に分けています。

出力先だけを変えたい場合は CMakeで実行ファイルの出力先を分けるときの設定 が近いです。

まとめ

共有ライブラリが実行時に見つからない場合は、RPATHを確認します。

  • build tree内で動かすなら BUILD_RPATH
  • install後に動かすなら INSTALL_RPATH
  • Linuxでは $ORIGIN を使うことがある
  • macOSでは @loader_path を使うことがある
  • install後の配置とセットで考える

RPATHは最初から細かく触るより、共有ライブラリの配置が決まってから設定する方が分かりやすいです。

関連記事

参考