g++
とld
を使用してc ++プログラムをコンパイルしています。リンク中に使用したい.so
ライブラリがあります。ただし、/usr/local/lib
には同じ名前のライブラリが存在し、ld
は直接指定しているライブラリよりもそのライブラリを選択しています。どうすれば修正できますか?
以下の例では、ライブラリファイルは/my/dir/libfoo.so.0
です。私が試したことがうまくいかない:
g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp
です/my/dir
ja変数の先頭または末尾に$PATH
を追加する/my/dir/libfoo.so.0
を引数としてg ++に追加する新しいライブラリがある場所へのパスをLD_LIBRARY_PATH
に追加します(Macでは名前が少し異なります...)
ソリューションは、-L/my/dir -lfoo
オプションを使用して動作する必要があります。実行時には、LD_LIBRARY_PATHを使用してライブラリの場所を指定します。
LD_LIBRARY_PATHの使用に注意 -要するに(リンクから):
..implications ..:
Security:LD_LIBRARY_PATHで指定されたディレクトリが標準の場所の前に検索されることに注意してください(!)?そのようにして、悪意のある人は、悪意のあるコードを含む共有ライブラリのバージョンをアプリケーションにロードさせることができます!それが、setuid/setgid実行可能ファイルがその変数を無視する理由の1つです!
パフォーマンス:リンクローダーは、共有ライブラリが存在するディレクトリを見つけるまで、指定されたすべてのディレクトリを検索する必要があります。アプリケーションがリンクされているライブラリ!これは、open()の多くのシステムコールを意味し、「ENOENT(No such file or directory)」で失敗します!パスに多くのディレクトリが含まれている場合、失敗した呼び出しの数は直線的に増加し、アプリケーションの起動時間からそれを知ることができます。ディレクトリの一部(またはすべて)がNFS環境にある場合、アプリケーションの起動時間が非常に長くなる可能性があり、システム全体の速度が低下する可能性があります。
Inconsistency:これは最も一般的な問題です。 LD_LIBRARY_PATHは、アプリケーションに、リンクされていない共有ライブラリを強制的にロードさせます。これは、おそらく元のバージョンと互換性がありません。これは非常に明白である可能性があります。つまり、アプリケーションがクラッシュするか、ピックアップしたライブラリが元のバージョンの動作をまったく実行しない場合、誤った結果につながる可能性があります。特に後者はデバッグが難しい場合があります。
OR
リンカーへのgccを介したrpathオプションの使用-ランタイムライブラリ検索パスは、標準のディレクトリ(gccオプション)を探す代わりに使用されます。
-Wl,-rpath,$(DEFAULT_LIB_INSTALL_PATH)
これは一時的なソリューションに適しています。リンカーは、標準ディレクトリを調べる前に、まずLD_LIBRARY_PATHでライブラリを検索します。
LD_LIBRARY_PATHを永続的に更新したくない場合は、コマンドラインでオンザフライで実行できます。
LD_LIBRARY_PATH=/some/custom/dir ./fooo
リンカが使用について知っているライブラリを確認できます(例):
/sbin/ldconfig -p | grep libpthread
libpthread.so.0 (libc6, OS ABI: Linux 2.6.4) => /lib/libpthread.so.0
また、アプリケーションが使用しているライブラリを確認できます。
ldd foo
linux-gate.so.1 => (0xffffe000)
libpthread.so.0 => /lib/libpthread.so.0 (0xb7f9e000)
libxml2.so.2 => /usr/lib/libxml2.so.2 (0xb7e6e000)
librt.so.1 => /lib/librt.so.1 (0xb7e65000)
libm.so.6 => /lib/libm.so.6 (0xb7d5b000)
libc.so.6 => /lib/libc.so.6 (0xb7c2e000)
/lib/ld-linux.so.2 (0xb7fc7000)
libdl.so.2 => /lib/libdl.so.2 (0xb7c2a000)
libz.so.1 => /lib/libz.so.1 (0xb7c18000)
ライブラリへの絶対パスを指定すると正常に機能するはずです。
g++ /my/dir/libfoo.so.0 ...
絶対パスを追加したら、-lfoo
を忘れずに削除しましたか?
これは古い質問ですが、誰もこれに言及していないようです。
あなたは物事がまったくリンクしていたことが幸運になっていた。
変更する必要がありました
g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp
これに:
g++ -g -Wall -o my_binary -L/my/dir bar.cpp -lfoo
リンカは、解決する必要があるシンボルを追跡します。最初にライブラリを読み取る場合、必要なシンボルがないため、その中のシンボルは無視されます。ライブラリにリンクする必要があるものの後にライブラリを指定して、リンカにシンボルを見つけられるようにします。
また、-lfoo
は、必要に応じてlibfoo.a
またはlibfoo.so
という名前のファイルを特に検索します。 libfoo.so.0
ではありません。したがって、ln
の名前を使用するか、ライブラリの名前を適切に変更します。
Gccのマニュアルページを引用するには:
-l library
...
It makes a difference where in the command you
write this option; the linker searches and processes
libraries and object files in the order they are
specified. Thus, foo.o -lz bar.o searches library z
after file foo.o but before bar.o. If bar.o refers
to functions in z, those functions may not be loaded.
もちろん、g++
のコマンドラインにファイルを直接追加することは機能しているはずです。もちろん、bar.cpp
の前にファイルを配置しない限り、シンボルはまだ必要ないため、リンカーは必要なシンボルがないため無視します。
別の方法として、環境変数LIBRARY_PATH
およびCPLUS_INCLUDE_PATH
を使用できます。これらはそれぞれ、ライブラリの検索場所とヘッダーの検索場所を示します(CPATH
もジョブを実行します)。 -Lおよび-Iオプションを指定します。
編集:CPATH
には、-I
のヘッダーとCPLUS_INCLUDE_PATH
の-isystem
が含まれます。
WindowsでDLLを操作するために使用され、linux/QTで.soバージョン番号をスキップしたい場合、CONFIG += plugin
を追加するとバージョン番号が削除されます。 .soへの絶対パスを使用するために、リンカーに渡すと、Klatchko氏が述べたようにうまく機能します。