アプリで用いるUNIXバイナリがdylibを必要とする場合の対応方法

process()を用いて動作させるUNIXバイナリが、dylib(ダイナミックローダブルライブラリ)を必要とする場合を考える。
この時、Xcode上のBuild Phaseで、dylibの入ったlibディレクトリをContents直下に、また、UNIXバイナリをMacOS直下に配置するものとする。(図を参照)

App構造

macOSでは、UNIXバイナリ、及びdylibのバイナリ内部に、自身のパスと、依存するライブラリ達のパスが書き込まれている。
筆者は最初それが分からず、App Storeで配信する自作ソフトウェアで使用するUNIXバイナリ及びdylibのインストール先を/Applications/アプリ名とすることで対応していた。殆どの場合それでも問題はないが、デバッグなどで不具合があった。

本ブログエントリでは、UNIXバイナリ、及びdylibのバイナリ内部のパス設定を相対パスにすることで、自作ソフトウェアがインストール先に依存せずに動作するようにする方法を説明する。

UNIXバイナリ、及びdylibともにやることは似ている。まず、UNIXバイナリから手を付ける。

  1. UNIXバイナリの確認と変更

    1. UNIXバイナリ自身のパスの確認

      otool -D cdparanoia

      このコマンドの実行結果は

      cdparanoia:

      で、このバイナリの場合、自身のパスは書き込まれていない。

    2. 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である)

    3. 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
    4. UNIXバイナリへのrpath追加
      UNIXバイナリ自身が、@rpathを解釈できるようにする。

      install_name_tool -add_rpath @loader_path/.. cdparanoia
  2. 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
    1. 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
    2. 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である)

    3. 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をビルドした場所でそのまま動作させることができる。

参考サイト

Rev.2 第2版(2019.12.3) 誤記訂正と大幅改訂。
Rev.1 初版(2019.6.3)

この投稿へのコメント

コメントはありません。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

この投稿へのトラックバック

トラックバックはありません。

トラックバック URL