アプリで用いるUNIXバイナリがdylibを必要とする場合の対応方法
process()を用いて動作させるUNIXバイナリが、dylib(ダイナミックローダブルライブラリ)を必要とする場合を考える。
この時、Xcode上のBuild Phaseで、dylibの入ったlibディレクトリをContents直下に、また、UNIXバイナリをMacOS直下に配置するものとする。(図を参照)
macOSでは、UNIXバイナリ、及びdylibのバイナリ内部に、自身のパスと、依存するライブラリ達のパスが書き込まれている。
筆者は最初それが分からず、App Storeで配信する自作ソフトウェアで使用するUNIXバイナリ及びdylibのインストール先を/Applications/アプリ名
とすることで対応していた。殆どの場合それでも問題はないが、デバッグなどで不具合があった。
本ブログエントリでは、UNIXバイナリ、及びdylibのバイナリ内部のパス設定を相対パスにすることで、自作ソフトウェアがインストール先に依存せずに動作するようにする方法を説明する。
UNIXバイナリ、及びdylibともにやることは似ている。まず、UNIXバイナリから手を付ける。
-
UNIXバイナリの確認と変更
-
UNIXバイナリ自身のパスの確認
otool -D cdparanoia
このコマンドの実行結果は
cdparanoia:
で、このバイナリの場合、自身のパスは書き込まれていない。
-
UNIXバイナリの依存パスの確認
otool -L cdparanoia
このコマンドの実行結果は
cdparanoia: /Applications/ParanoiaImport.app/Contents/lib/libcdda_interface.0.dylib (compatibility version 0.0.0, current version 0.0.0) /Applications/ParanoiaImport.app/Contents/lib/libcdda_paranoia.0.dylib (compatibility version 0.0.0, current version 0.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.50.2)
上記のようになり、上にも書いたように
lib
の指定が絶対パス/Applications/ParanoiaImport.app/Contents/lib
になっている。(ここは、普通にインストールした場合、/usr/local/lib
である) -
UNIXバイナリの依存ライブラリパスを相対パスに変更
install_name_tool -change \ "/Applications/ParanoiaImport.app/Contents/lib/libcdda_interface.0.dylib" \ "@rpath/lib/libcdda_interface.0.dylib" \ cdparanoia
install_name_tool -change \ "/Applications/ParanoiaImport.app/Contents/lib/libcdda_paranoia.0.dylib" \ "@rpath/lib/libcdda_paranoia.0.dylib" \ cdparanoia
-
UNIXバイナリへのrpath追加
UNIXバイナリ自身が、@rpathを解釈できるようにする。install_name_tool -add_rpath @loader_path/.. cdparanoia
-
-
dylibの確認と変更
今回のdylibは、6ファイルあるが、4個はシンボリックリンクであり、-rwxr-xr-x 1 roushi staff 43792 9 30 00:33 libcdda_interface.0.10.2.dylib lrwxr-xr-x 1 roushi staff 30 1 31 08:49 libcdda_interface.0.dylib -> libcdda_interface.0.10.2.dylib lrwxr-xr-x 1 roushi staff 30 1 31 08:49 libcdda_interface.dylib -> libcdda_interface.0.10.2.dylib -rwxr-xr-x 1 roushi staff 45344 9 30 00:33 libcdda_paranoia.0.10.2.dylib lrwxr-xr-x 1 roushi staff 29 1 31 08:49 libcdda_paranoia.0.dylib -> libcdda_paranoia.0.10.2.dylib lrwxr-xr-x 1 roushi staff 29 1 31 08:49 libcdda_paranoia.dylib -> libcdda_paranoia.0.10.2.dylib
実体ファイルは、以下の2個である。
libcdda_interface.0.10.2.dylib libcdda_paranoia.0.10.2.dylib
-
dylib自身のパスの確認
otool -D libcdda_interface.0.10.2.dylib
このコマンドの実行結果は
libcdda_interface.0.10.2.dylib: /Applications/ParanoiaImport.app/Contents/lib/libcdda_interface.0.dylib
なので、次のように相対パスにする。
install_name_tool -id "@rpath/libcdda_interface.0.dylib" libcdda_interface.0.10.2.dylib
同様に
otool -D libcdda_paranoia.0.10.2.dylib
このコマンドの実行結果は
libcdda_paranoia.0.10.2.dylib: /Applications/ParanoiaImport.app/Contents/lib/libcdda_paranoia.0.dylib
なので、次のように相対パスにする。
install_name_tool -id "@rpath/libcdda_paranoia.0.dylib" libcdda_paranoia.0.10.2.dylib
-
dylibの依存パスの確認
otool -L libcdda_interface.0.10.2.dylib
このコマンドの実行結果は
libcdda_interface.0.10.2.dylib: @rpath/lib/libcdda_interface.0.dylib (compatibility version 0.0.0, current version 0.0.0) (以下省略)
続いて
otool -L libcdda_paranoia.0.10.2.dylib
このコマンドの実行結果は
libcdda_paranoia.0.10.2.dylib: @rpath/lib/libcdda_paranoia.0.dylib (compatibility version 0.0.0, current version 0.0.0) /Applications/ParanoiaImport.app/Contents/lib/libcdda_interface.0.dylib (compatibility version 0.0.0, current version 0.0.0) (以下省略)
上記のようになり、上にも書いたように
lib
の指定が絶対パス/Applications/ParanoiaImport.app/Contents/lib
になっている。(ここは、普通にインストールした場合、/usr/local/lib
である) -
dylibの依存ライブラリパスを相対パスに変更
install_name_tool -change \ "/Applications/ParanoiaImport.app/Contents/lib/libcdda_interface.0.dylib" \ "@rpath/lib/libcdda_interface.0.dylib" \ libcdda_paranoia.0.10.2.dylib
-
このようにUNIXバイナリとdylibバイナリをinstall_name_toolを用いて、自身のパス、依存パスを書き換えれば、例えばXcode上でデバッグビルドしたAppをビルドした場所でそのまま動作させることができる。
参考サイト
- Why is install_name_tool and otool necessary for Mach-O libraries in Mac Os X?
- macOSのコマンドラインアプリでdylibをよろしく扱う方法
Rev.2 第2版(2019.12.3) 誤記訂正と大幅改訂。
Rev.1 初版(2019.6.3)
この投稿へのトラックバック
トラックバックはありません。
- トラックバック URL
この投稿へのコメント