web-dev-qa-db-ja.com

ライブラリパスの設定を指定する方法は?

g++ldを使用してc ++プログラムをコンパイルしています。リンク中に使用したい.soライブラリがあります。ただし、/usr/local/libには同じ名前のライブラリが存在し、ldは直接指定しているライブラリよりもそのライブラリを選択しています。どうすれば修正できますか?

以下の例では、ライブラリファイルは/my/dir/libfoo.so.0です。私が試したことがうまくいかない:

  • 私のg ++​​コマンドは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)
83
stefanB

ライブラリへの絶対パスを指定すると正常に機能するはずです。

g++ /my/dir/libfoo.so.0  ...

絶対パスを追加したら、-lfooを忘れずに削除しましたか?

20

これは古い質問ですが、誰もこれに言及していないようです。

あなたは物事がまったくリンクしていたことが幸運になっていた。

変更する必要がありました

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の前にファイルを配置しない限り、シンボルはまだ必要ないため、リンカーは必要なシンボルがないため無視します。

17
Michael Speer

別の方法として、環境変数LIBRARY_PATHおよびCPLUS_INCLUDE_PATHを使用できます。これらはそれぞれ、ライブラリの検索場所とヘッダーの検索場所を示します(CPATHもジョブを実行します)。 -Lおよび-Iオプションを指定します。

編集:CPATHには、-IのヘッダーとCPLUS_INCLUDE_PATH-isystemが含まれます。

11
Alexandre Hamez

WindowsでDLLを操作するために使用され、linux/QTで.soバージョン番号をスキップしたい場合、CONFIG += pluginを追加するとバージョン番号が削除されます。 .soへの絶対パスを使用するために、リンカーに渡すと、Klatchko氏が述べたようにうまく機能します。

0