web-dev-qa-db-ja.com

リンク時のLD_LIBRARY_PATHと-Lの違いは何ですか?

link時間にLD_LIBRARY_PATHに問題があります(この質問は実行時間とは関係ありません)。

Makeを実行すると、リンク行は次のようになります(これは、g ++バージョン4.1.xを使用するLinuxシステムです)。

g++ a.o b.o c.o -o myapp \
 -L/long/path/to/libs/ \
 -L/another/long/path/ \
 -labc -ldef -lghi

-lオプションは、-Lオプションで指定されたディレクトリに存在する共有ライブラリ(libabc.soなど)を参照します。これらのディレクトリはLD_LIBRARY_PATHにも表示されます。その構成で、リンクは成功し、アプリケーションを実行できます。

LD_LIBRARY_PATHからディレクトリを削除すると、次のような単一のエラー行が表示されます。

/usr/bin/ld: cannot find -labc

一方、-Lオプションのリストからディレクトリを削除すると、次のような多くの警告が表示されます。

/usr/bin/ld: warning: libabc.so, needed by /long/path/to/libs/libxyz.so,
    not found (try using -rpath or -rpath-link)

そして、次のようなさらに多くのエラーが発生します。

/long/path/to/libs/libdef.so: undefined reference to `Foo::Bar<Baz>::junk(Fred*)'

誰かがLD_LIBRARY_PATH-Lの違いを説明できますか?このことを深く理解したいので、参考にしていただければ幸いです。

また、LD_LIBRARY_PATHの使用を避けるために、リンク行に何を追加する必要がありますか?

EDIT:ディレクトリが-Lにない場合、コンパイラは「-rpathまたは-rpath-linkを使用してみてください」と提案しました。私はこれまでメイクファイルでこれらのオプションを見たことがないと思います。ありますか?しかし、それがLD_LIBRARY_PATHの問題に役立つかどうかはわかりません。

24
Dan

LD_LIBRARY_PATHの設定が最も優先されるため、設定すると、標準セットの前であっても、LD_LIBRARY_PATHで指定されたディレクトリのセットが最初に検索されます。
のディレクトリ。したがって、あなたの場合、LD_LIBRARY_PATHの設定はのルックアップに影響を与えています
-lオプションで言及されているライブラリ。 LD_LIBRARY_PATHなしでいくつかの依存関係
標準のディレクトリセットから解決された可能性があります。

LD_LIBRARY_PATHの設定はデバッグに役立ち、の新しいバージョンを試すのに役立ちますが
一般的な開発環境のセットアップとデプロイメントでのライブラリの使用は悪いと見なされます。

共有ライブラリの詳細については、Linuxドキュメントの this HOWTO も参照してください。

20
sateesh

この質問には2つの答えがあります。答えの一部は、コンパイル時のリンク(つまり、gcc -lfoo -L/usr/lib...はldを呼び出します)と実行時のリンカールックアップにあります。

プログラムをコンパイルすると、コンパイラは構文をチェックし、リンカは実行に必要なシンボル(つまり、変数/メソッドなど)が存在することを確認します。 LD_LIBRARY_PATHには、前述のように、検索を変更することにより、gcc/ldの動作とランタイムリンカの動作を変更するという副作用があります。道。

プログラムを実行すると、ランタイムリンカは実際に共有ライブラリを(ディスク上または可能であればメモリから)フェッチし、共有シンボル/コードなどをロードします。繰り返しますが、LD_LIBRARY_PATHはこの検索パスに暗黙的に影響します(すでに述べたように、時には良くないこともあります。)

ほとんどのLinuxシステムでLD_LIBRARY_PATHを使用しない場合のこれに対する正しい修正は、共有ライブラリを含むパスを/etc/ld.so.confに追加することです(または一部のディストリビューションでは、パスを使用して/etc/ld.so.conf.d/にファイルを作成しますその中で)そしてldconfig(rootとして/sbin/ldconfig)を実行して、ランタイムリンカーバインディングキャッシュを更新します。

Debianの例:

jewart@dorfl:~$ cat /etc/ld.so.conf.d/usrlocal.conf 
/usr/local/lib

次に、プログラムが実行されると、ランタイムリンカはそれらのディレクトリで、バイナリがリンクされているライブラリを探します。

ランタイムリンカが​​認識しているライブラリを知りたい場合は、次を使用できます。

jewart@dorfl:~$ ldconfig -v 

/usr/lib:
libbfd-2.18.0.20080103.so -> libbfd-2.18.0.20080103.so
libkdb5.so.4 -> libkdb5.so.4.0
libXext.so.6 -> libXext.so.6.4.0

また、バイナリがリンクされているライブラリを知りたい場合は、lddをそのように使用できます。これにより、ランタイムリンカーが選択するライブラリがわかります。

jewart@dorfl:~$ ldd /bin/ls
linux-vdso.so.1 =>  (0x00007fffda1ff000)
librt.so.1 => /lib/librt.so.1 (0x00007f5d2149b000)
libselinux.so.1 => /lib/libselinux.so.1 (0x00007f5d2127f000)
libacl.so.1 => /lib/libacl.so.1 (0x00007f5d21077000)
libc.so.6 => /lib/libc.so.6 (0x00007f5d20d23000)
32
John Ewart

LD_LIBRARY_PATHは、アプリケーションの実行時に共有ライブラリを見つけることを目的としています。それがあなたのリンクに影響を与えることは副作用であり、あなたはそれに頼るべきではありません。

しばしば望ましくない副作用として、LD_LIBRARY_PATHは、-Lで指定されたディレクトリの後のリンク(ld)ステージでも検索されます(-Lフラグが指定されていない場合も同様です)。

LD_LIBRARY_PATHが悪い理由

8
Don Neufeld

推測すると、リンカはLD_LIBRARY_PATHを使用して、直接リンクしているライブラリ(libabc.solibdef.solibghi.soなど)を解決することにフォールバックしていると言えます。 )に対して動的にリンクされます。 ldのマニュアルページを見ると、.soを使用して構築された-rpathに対してリンクすると、動的にバインドされたシンボルのルックアップがどのように機能するかに影響するようです。

3
D.Shawley

男性のg ++​​を確認したところ、-lxxxxxオプションが指定されたパスlibxxxxx.a-Lを探していることがわかりました。そのため、リンク時に.aファイルのみが読み込まれます。実行時に、ライブラリが欠落している場合は、共有オブジェクトとしてのライブラリのみがロードされるため、.soがロードされ、LD_LIBRARY_PATHが検索されます。私が取り組んでいる実行可能ファイルでは、ライブラリディレクトリにバージョンlibxxxx.alibxxxx.soがあることがわかります。したがって、ライブラリはリンク時にリンクできるか、リンク時にリンクできると思います。共有オブジェクトとしてのランタイム。

ライブラリが共有オブジェクトとしてのみ存在する場合は、実行時にライブラリディレクトリパスをLD_LIBRARY_PATHで見つける必要があることを意味します。ライブラリがアーカイブとしてのみ存在する場合は、実行可能ファイルのビルド時にリンクする必要があり、コンパイル時に-Lディレクトリパスと-lxxxxxをg ++で指定する必要があります。

これは私の理解です....そして少なくともそれはあなたの観察と一致しています

1
serge imbert