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
の問題に役立つかどうかはわかりません。
LD_LIBRARY_PATH
の設定が最も優先されるため、設定すると、標準セットの前であっても、LD_LIBRARY_PATH
で指定されたディレクトリのセットが最初に検索されます。
のディレクトリ。したがって、あなたの場合、LD_LIBRARY_PATH
の設定はのルックアップに影響を与えています-l
オプションで言及されているライブラリ。 LD_LIBRARY_PATH
なしでいくつかの依存関係
標準のディレクトリセットから解決された可能性があります。
LD_LIBRARY_PATH
の設定はデバッグに役立ち、の新しいバージョンを試すのに役立ちますが
一般的な開発環境のセットアップとデプロイメントでのライブラリの使用は悪いと見なされます。
共有ライブラリの詳細については、Linuxドキュメントの this HOWTO も参照してください。
この質問には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)
LD_LIBRARY_PATH
は、アプリケーションの実行時に共有ライブラリを見つけることを目的としています。それがあなたのリンクに影響を与えることは副作用であり、あなたはそれに頼るべきではありません。
しばしば望ましくない副作用として、LD_LIBRARY_PATHは、-Lで指定されたディレクトリの後のリンク(ld)ステージでも検索されます(-Lフラグが指定されていない場合も同様です)。
推測すると、リンカはLD_LIBRARY_PATH
を使用して、直接リンクしているライブラリ(libabc.so
、libdef.so
、libghi.so
など)を解決することにフォールバックしていると言えます。 )に対して動的にリンクされます。 ld
のマニュアルページを見ると、.so
を使用して構築された-rpath
に対してリンクすると、動的にバインドされたシンボルのルックアップがどのように機能するかに影響するようです。
男性のg ++を確認したところ、-lxxxxx
オプションが指定されたパスlibxxxxx.a
で-L
を探していることがわかりました。そのため、リンク時に.a
ファイルのみが読み込まれます。実行時に、ライブラリが欠落している場合は、共有オブジェクトとしてのライブラリのみがロードされるため、.soがロードされ、LD_LIBRARY_PATH
が検索されます。私が取り組んでいる実行可能ファイルでは、ライブラリディレクトリにバージョンlibxxxx.a
とlibxxxx.so
があることがわかります。したがって、ライブラリはリンク時にリンクできるか、リンク時にリンクできると思います。共有オブジェクトとしてのランタイム。
ライブラリが共有オブジェクトとしてのみ存在する場合は、実行時にライブラリディレクトリパスをLD_LIBRARY_PATH
で見つける必要があることを意味します。ライブラリがアーカイブとしてのみ存在する場合は、実行可能ファイルのビルド時にリンクする必要があり、コンパイル時に-Lディレクトリパスと-lxxxxx
をg ++で指定する必要があります。
これは私の理解です....そして少なくともそれはあなたの観察と一致しています