web-dev-qa-db-ja.com

動的ライブラリの検索パスをLD_LIBRARY_PATHで上書きできないのはなぜですか?

編集:私はこの問題を解決しました、解決策は以下の通りです。

私は科学計算専用の共有コンピューティングクラスターでコードを構築しているため、ホームフォルダー内のファイルしか制御できません。例としてfftwを使用していますが、LD_LIBRARY_PATHをセットアップしようとしても機能しない特定の理由を理解したいと思います。

このようにホームフォルダーにfftwおよびfftw_mpiライブラリを構築します

./configure --prefix=$HOME/install/fftw --enable-mpi --enable-shared
make install

正常にビルドされますが、install/fftw/libで、新しくビルドされたlibfftw3_mpi.soが間違ったバージョンのfftwライブラリにリンクしていることがわかりました。

$ ldd libfftw3_mpi.so |grep fftw
  libfftw3.so.3 => /usr/lib64/libfftw3.so.3 (0x00007f7df0979000)

このディレクトリを正しく指すようにLD_LIBRARY_PATHを設定しようとしても、間違ったライブラリが優先されます。

$ export LD_LIBRARY_PATH=$HOME/install/fftw/lib
$ ldd libfftw3_mpi.so |grep fftw
    libfftw3.so.3 => /usr/lib64/libfftw3.so.3 (0x00007f32b4794000)

LD_PRELOADを明示的に使用する場合にのみ、この動作をオーバーライドできます。しかし、LD_PRELOADは適切な解決策ではないと思います。

$ export LD_PRELOAD=$HOME/install/fftw/lib/libfftw3.so.3 
$ ldd libfftw3_mpi.so |grep fftw
   $HOME/install/fftw/lib/libfftw3.so.3 (0x00007f5ca3d14000)

これは私が期待していたもので、Ubuntuデスクトップで行われる小さなテストです。最初にfftwを/ usr/libにインストールし、次にこの検索パスをLD_LIBRARY_PATHで上書きします。

$ export LD_LIBRARY_PATH=
$ ldd q0test_mpi |grep fftw3
    libfftw3.so.3 => /usr/lib/x86_64-linux-gnu/libfftw3.so.3
$ export LD_LIBRARY_PATH=$HOME/install/fftw-3.3.4/lib
$ ldd q0test_mpi |grep fftw3
    libfftw3.so.3 => $HOME/install/fftw-3.3.4/lib/libfftw3.so.3

要するに、なぜlibfft3_mpiライブラリは依然として間違った動的fftw3ライブラリを見つけているのですか?この検索パスは、LD_LIBARY_PATHよりも優先されるようにハードコードされていますか?なぜこれが別のコンピュータに当てはまらないのですか?

これが重要な場合は、インテルコンパイラー13.1.2、mkl 11.0.4.183、openmpi 1.6.2を使用しています。

編集:すべての答えをありがとう。これらの助けを借りて、問題をRPATHに特定し、そこからクラスターサポートが問題を特定することができました。私は最初の答えを受け入れましたが、どちらの答えも良かったです。

これがわかりにくい理由は、コンパイラが実際にラッパースクリプトであり、コンパイラのコマンドラインに何かを追加していることを知らなかったためです。サポートからの返信の一部:

[]コンパイルは、コンパイララッパーを経由します。ほとんどのユーザーがLD-LIBRARY_PATHなどをロードせずにジョブを正しく実行できるように、デフォルトでRPATHを実行します。ただし、/ lib、/ lib64/proj/homeなどを含む特定のライブラリパスをデフォルトのRPATHから除外します。以前は/ usr/lib64は誤って除外されませんでした(ほとんど)。これで、そのパスが除外リストに追加されました。

12
Mikael Kuisma

から http://man7.org/linux/man-pages/man8/ld.so.8.html

共有オブジェクトの依存関係を解決するとき、ダイナミックリンカーは最初に各依存関係文字列を検査して、スラッシュが含まれているかどうかを確認します(これは、スラッシュを含む共有オブジェクトのパス名がリンク時に指定された場合に発生します)。スラッシュが見つかった場合、依存文字列は(相対または絶対)パス名として解釈され、共有オブジェクトはそのパス名を使用してロードされます。

共有オブジェクトの依存関係にスラッシュが含まれていない場合は、次の順序で検索されます。

o(ELFのみ)存在する場合はバイナリのDT_RPATH動的セクション属性で指定され、DT_RUNPATH属性が存在しないディレクトリを使用します。 DT_RPATHの使用は非推奨です。

o環境変数LD_LIBRARY_PATHを使用します。実行可能ファイルがset-user-ID/set-group-IDバイナリである場合を除いて、その場合は無視されます。

o(ELFのみ)存在する場合、バイナリのDT_RUNPATH動的セクション属性で指定されたディレクトリを使用します。

oキャッシュファイル/etc/ld.so.cacheから。これには、拡張ライブラリパスで以前に見つかった候補共有オブジェクトのコンパイル済みリストが含まれています。ただし、バイナリが-z nodeflibリンカーオプションでリンクされている場合、デフォルトパスの共有オブジェクトはスキップされます。ハードウェア機能ディレクトリ(以下を参照)にインストールされた共有オブジェクトは、他の共有オブジェクトよりも優先されます。

oデフォルトのパス/ lib、次に/ usr/lib。 (一部の64ビットアーキテクチャでは、64ビット共有オブジェクトのデフォルトパスは/ lib64、次に/ usr/lib64です。)バイナリが-z nodeflibリンカーオプションでリンクされている場合、この手順はスキップされます。

  • readelf readelf -d libfftw3_mpi.so libの動的セクションにそのような属性が含まれているかどうかを確認できます。

  • export LD_DEBUG=libsライブラリの検索に使用する検索パスをデバッグできます

  • chrpath -r<new_path> <executable> rpathは変更できます

16
Martin Bonetti

これには2つの理由が考えられます。

まず、libfftw3_mpi.so/usr/lib64/RPATHとしてリンクできます。その場合、LD_LIBRARY_PATHを指定しても効果はありません。それがあなたのケースであるかどうかを確認するには、readelf -d libfftw3_mpi.so | grep RPATHを実行して、ライブラリパスとして/usr/lib64/があるかどうかを確認します。存在する場合は、chrpathユーティリティを使用して変更または削除してください。

または、LD_LIBRARY_PATHをまったくサポートしていないシステム(HP-UXなど)を実行している可能性があります。

3
Nikita Kakuev