実行時リンカーには、必要な依存関係のパス名を発見するための柔軟性が備わっています。デフォルトでは、実行時リンカーは /usr/lib を検索することだけを知っています。このディレクトリは、通常、記録された「実行パス」によって拡張されます。これらのパスは構築時にイメージに記録され、一般に、すべての依存関係の標準インストール場所を指します。この節では、「実行パス」を $ORIGIN によって拡張して、アプリケーションがリンク編集時に構築されるときに、その最終インストール場所を知らなくてもすむようにする方法を説明します。
通常、バンドルされていない製品は、独立した固有の場所にインストールされるように設計されています。この製品は、バイナリ、共有オブジェクト、および関連構成ファイルからなります。たとえば、バンドルされていない製品 ABC は、次の配置をとる場合があります。
製品が、/opt のもとにインストールされるように設計されていると想定します。通常、ユーザーは、PATH に製品バイナリの位置を示す /opt/ABC/bin を追加する必要があります。各バイナリは、バイナリ内に直接記録された実行パスを使用して、その依存する相手を探します。アプリケーション abc
の場合、これは次のようになります。
% dump -Lv abc [1] NEEDED libA.so.1 [2] RPATH /opt/ABC/lib |
また、libA.so.1 の依存関係でも同様にこれは次のようになります。
% dump -Lv libA.so.1 [1] NEEDED libB.so.1 [2] RPATH /opt/ABC/lib |
この依存関係の表現は、製品が推奨されているデフォルト以外のディレクトリにインストールされるまで正常に作動します。異なるインストール環境が作成された場合、ユーザーは LD_LIBRARY_PATH を使用して、製品アプリケーションを実行しなければなりません。通常、これは、バイナリごとにラッパーを作って対応しますが、場合によっては、適切なオブジェクト内の実行パスを変更しようとするユーザーもいます。
$ORIGIN は、オブジェクトが存在するディレクトリを表わします。この機能は、カーネルによってプロセス開始時に実行時リンカーに提供されたる新しい補助ベクトルに対応しています。この機構を使用すると、バンドルされていないアプリケーションを再定義して、$ORIGIN との相対位置で依存対象の位置を示すことができます。
% dump -Lv abc [1] NEEDED libA.so.1 [2] RPATH $ORIGIN/../lib |
また、$ORIGIN との関係で libA.so.1 の依存関係を定義することもできます。
% dump -Lv libA.so.1 [1] NEEDED libB.so.1 [2] RPATH $ORIGIN |
したがって、この製品が /usr/local/ABC のもとにインストールされて、ユーザーの PATH にアプリケーション abc
用の /usr/local/ABC/bin が追加されると、次のように、パス名検索でその依存関係が探されます。
% ldd -s abc find library=libA.so.1; required by abc search path=$ORIGIN/../lib (RPATH from file abc) trying path=/usr/local/ABC/lib/libA.so.1 libA.so.1 => /usr/local/ABC/lib/libA.so.1 find library=libB.so.1; required by /usr/local/ABC/lib/libA.so.1 search path=$ORIGIN (RPATH from file /usr/local/ABC/lib/libA.so.1) trying path=/usr/local/ABC/lib/libB.so.1 libB.so.1 => /usr/local/ABC/lib/libB.so.1 |
依存関係の場所に関する次の問題としては、バンドルされていない製品が別のバンドルされていない製品の共有オブジェクトに対して依存関係を持つときの、基本となるモデルを作成する方法が挙げられます。
たとえば、バンドルされていない製品 XYZ は製品 ABC に対して依存関係を持つ場合があります。この依存関係は、ost パッケージインストールスクリプトによって ABC 製品のインストール位置へのシンボルリンクを生成することで確立できます。
XYZ 製品のバイナリと共有オブジェクトは安定した参照位置としてシンボルリンクを使用して、ABC 製品への依存関係を表わします。アプリケーション xyz
の場合、これは次のようになります。
% dump -Lv xyz [1] NEEDED libX.so.1 [2] NEEDED libA.so.1 [3] RPATH $ORIGIN/../lib:$ORIGIN/../ABC/lib |
libX.so.1 の依存関係でも同様に、これは次のようになります。
% dump -Lv libX.so.1 [1] NEEDED libY.so.1 [2] NEEDED libC.so.1 [3] RPATH $ORIGIN:$ORIGIN/../ABC/lib |
したがって、この製品が /usr/local/XYZ のもとにインストールされている場合は、次のシンボルリンクを確立するために、そのインストール後実行スクリプトが必要です。
% ln -s ../ABC /usr/local/XYZ/ABC |
ユーザーの PATH に /usr/local/XYZ/bin
が追加される場合、アプリケーション xyz
の呼び出しによって、次のようにパス名検索でその依存関係が探されます。
% ldd -s xyz find library=libX.so.1; required by xyz search path=$ORIGIN/../lib:$ORIGIN/../ABC/lib (RPATH from file xyz) trying path=/usr/local/XYZ/lib/libX.so.1 libX.so.1 => /usr/local/XYZ/lib/libX.so.1 find library=libA.so.1; required by xyz search path=$ORIGIN/../lib:$ORIGIN/../ABC/lib (RPATH from file xyz) trying path=/usr/local/XYZ/lib/libA.so.1 trying path=/usr/local/ABC/lib/libA.so.1 libA.so.1 => /usr/local/ABC/lib/libA.so.1 find library=libY.so.1; required by /usr/local/XYZ/lib/libX.so.1 search path=$ORIGIN:$ORIGIN/../ABC/lib ¥ (RPATH from file /usr/local/XYZ/lib/libX.so.1) trying path=/usr/local/XYZ/lib/libY.so.1 libY.so.1 => /usr/local/XYZ/lib/libY.so.1 find library=libC.so.1; required by /usr/local/XYZ/lib/libX.so.1 search path=$ORIGIN:$ORIGIN/../ABC/lib ¥ (RPATH from file /usr/local/XYZ/lib/libX.so.1) trying path=/usr/local/XYZ/lib/libC.so.1 trying path=/usr/local/ABC/lib/libC.so.1 libC.so.1 => /usr/local/ABC/lib/libC.so.1 find library=libB.so.1; required by /usr/local/ABC/lib/libA.so.1 search path=$ORIGIN (RPATH from file /usr/local/ABC/lib/libA.so.1) trying path=/usr/local/ABC/lib/libB.so.1 libB.so.1 => /usr/local/ABC/lib/libB.so.1 |