-L、-rpath、-rpath-linkの違い



Difference Between L

これら3つのパラメータの説明についてはたくさんの情報がありますが、それを読んだ後でも、私はまだ漠然としていて、それらの違いがわかりません。この記事では、実験的な方法を使用して、これら3つのパラメーターの違いを探ります。

1.3つの.cファイル



1.1 world.c

ubuntu $ gcc -shared -o libworld.so world.o -lhello -L .
  1. 含める
  2. ボイド 世界((ボイド)。 {{
  3. printf((「世界。 n」)。
  4. }
1.2 hello.c
ubuntu $ gcc test.c -lhello -L .
  1. 含める&ltstdio.h&gt
  2. ボイド 世界((ボイド)。
  3. ボイド こんにちは((ボイド)。 {{
  4. printf((「こんにちは n」)。
  5. 世界()
  6. }
1.3 test.cubuntu $ gcc test.c -lhello -lworld -L .
  1. ボイド メイン((ボイド)。 {{
  2. こんにちは()
  3. }
2.ダイナミックライブラリを生成します

参照する ' Linux静的ライブラリと動的ライブラリの作成 》、hello.cとworld.cからそれぞれダイナミックライブラリを生成します



ubuntu export LD_LIBRARY_PATH=/home/liyihai/documents
  1. ubuntu $ gcc-cこんにちは。c世界。c
  2. ubuntu $ gcc -shared -o libhello.so hello.o
  3. ubuntu $ gcc -shared -o libworld.so world.o

このとき、生成されるファイルとその依存関係は次のとおりです。


上の図から、libhello.soとlibworldはどちらもlinux-gate.so.1、libc.so.6、/ lib / ld-linux.so.2に依存しており、これら3つのライブラリのパスは次のようになっていることがわかります。ハードコードされたlibhello.soおよびlibworld.so(=>右側の部分)。



ただし、libworld.so関数はlibhello.soで呼び出されますが、この関係は上の図には示されていません。 libhello.soをlibworld.soに依存させるには、libhello.soを生成するときにlibworld.soにリンクします。

ubuntu $ export LD_LIBRARY_PATH=./lib_tmpこのとき、lddを使用してlibhello.soの依存関係を確認します。


上の図からわかるように、現時点ではlibhello.soはすでにlibworld.soに依存しています。

3.test.cをコンパイルします

3.1 -L

test.cはlibhello.soに直接依存しているため、-lhello-Lを使用します

ubuntu $ export LD_LIBRARY_PATH=./lib_tmp/結果は次のとおりです。

上の図から、libhello.soが-Lで指定されたパスで見つかったことがわかりますが、libhello.soにはlibworld.soも必要です。同じディレクトリにありますが、libworld.soを自動的に見つける方法はありません。

では、-lworldを使用してlibworld.soをtest.cにもリンクできますか?以下を試してみましょう。

ubuntu $ gcc test.c -lhello -L . -Wl,-rpath-link ./lib_tmp

エラーは報告されず、a.outが正常に生成されます。

a.outを実行し、lddを使用してa.outの依存関係を表示します。

上の図から、libworld.soは-lworldパラメーターを使用してa.outにリンクされていますが、上記はa.outがlibhello.soに依存していることを示しているだけであることがわかります。 libhello.so(=> not found)へのパスが見つからないため、環境変数を設定する必要があります LD_LIBRARY_PATH

a.outを再度実行し、lddコマンドを使用してa.outの依存ライブラリを表示します。 

上の図からわかるように、libhello.soはLD_LIBRARY_PATH環境変数を介して検出されており、libworld.soもa.out!の依存関係に表示されます。

結論:-Lはリンク時のライブラリパスを指定し、実行時ライブラリで生成された実行可能ファイルのパスは次のように決定されます。 LD_LIBRARY_PATH 環境変数の仕様。

3.2 -rpath

3.1の最初の図のヒントによると、libhello.soはlibworld.soに依存しているため、-rpathまたは-rpath-linkでのみ指定できます。最初に-rpathを使用します。

最初にLD_LIBRARY_PATH環境変数をクリアしてから、test.cを再コンパイルし、-rpathパラメーターを指定します。

  1. ubuntu $ export LD_LIBRARY_PATH =
  2. ubuntu $ gcc test.c -lhello-L。 -Wl、-rpath。
a.outを実行し、lddコマンドを使用してa.outの依存関係を表示します。


上の図から、libworld.soへの明示的なリンクはありませんが、libworld.soはa.outの依存関係に表示されていることがわかります。

さらに、LD_LIBRARY_PATHがクリアされていても、a.outを実行できます。これは、ライブラリパスがa.outにコンパイルされたことを示しています。 libhello.soとlibworld.soのパスは、-rpathで指定されたパスを介して検出されることに注意してください。

3.2.1実験1

このとき、libhello.soとlibworld.soのパスを変更するとどうなりますか?以下の実験をしてみましょう。

lib_tmpディレクトリを作成してから、libhello.soとlibworld.soをこのディレクトリに移動します。

  1. ubuntu $ mdir lib_tmp
  2. ubuntu $ mv libhello.so lib_tmp /
  3. ubuntu $ mv libworld.so lib_tmp /
このとき、a.outを再度実行すると、ダイナミックライブラリが見つからないというプロンプトが表示されます。 lddコマンドを使用して、a.outのライブラリパスを表示します。


上の図の赤い円からわかるように、libhello.soのパスが見つからず、libworld.soが表示されていません。これは3.1と同じです。

libhello.soはlibworld.soに依存し、a.outはlibworld.soに依存しないため、理由は最初にlibhello.soを検索し、次にlibworl.soを検索するためです。

-rpathパラメーターを使用してライブラリーのパスを指定した後、生成された実行可能ファイルの依存ライブラリー・パスが固定されていないことがわかります。代わりに、最初に-rpathで指定されたパスから依存ライブラリを検索します。見つからない場合でも、資金提供を受けていない場合は報告されます。

したがって、現時点では、LD_LIBRARY_PATHはa.outに影響しますか?次に、LD_LIBRARY_PATHを現在のlibhello.soとlibworld.soが配置されているパスに設定します

a.outを再度実行し、lddを使用して、この時点でa.outの依存ライブラリパスを表示します。 


上の画像から、LD_LIBRARY_PATHが引き続き機能していることがわかります。上の図から、-rpathでパスを指定した場合の効果は同じであることがわかります。

3.2.2実験2

LD_LIBRARY_PATHをクリアしてから、libhello.soをlib_tmpに移動します。その間、libworld.soはドキュメントディレクトリに残ります。

この時点でa.outを実行し、lddを使用してa.outの依存ライブラリを表示します。


上の写真から、libhello.soが見つからないことがわかります。このとき、libhello.soが配置されているパスとしてLD_LIBRARY_PATHのパスを指定します。

|_+_|
a.outを再度実行し、lddを使用して依存ライブラリを表示します。

上の写真からわかるように、すべてが正常に戻っています。このとき、libhello.soはLD_LIBRARY_PATHを介して検出され、libworld.soは-rpathで指定されたパスを介して検出されます。

3.2.3レビュー

実際、テスト後、セクション3.1で、最初にLD_LIBRARY_PATHの値をlibhello.soとlibworld.soが配置されているパスとして指定し、次にtest.cをコンパイルすると(セクション3.1の最初のコンパイルコマンドを実行)、コンパイルできます、そしてセクション3.1の最初の画像のエラーを報告しません。つまり、LD_LIBRARY_PATHは、実行可能ファイルのライブラリパスを指定するだけでなく、ライブラリが他のライブラリに依存するパスも指定します。

3.2.4結論

-rpathパラメーターが指定されていない場合、LD_LIBRARY_PATH環境変数は破棄され、オプションの依存ライブラリパスのみが追加されます。

3.3-rpath-link

最初にLD_LIBRARY_PATHの値をクリアしてから、libworld.soをlib_tmpディレクトリに移動し、libhello.soをドキュメントディレクトリに残して、次のコマンドを使用してtest.cをコンパイルします。

|_+_|
a.outを実行し、lddを使用してa.outの依存ライブラリを表示します。


libhello.soが見つかるとは予想されていませんでした。次に、LD_LIBRARY_PATHの値をlibhello.soのパスとして指定し、a.outを実行して、a.outの依存関係を確認します。


上の図から、libhello.soはLD_LIBRARY_PATHを介して検出されたことがわかりますが、libworld.soはLD_LIBRARY_PATHで指定されたパスになく、a.outにはコンパイル時にライブラリのパスが含まれていないため、見つかりました。この

3.2.2と比較すると、-rpathと-rpath-linkの両方でリンク時にライブラリのパスを指定できますが、実行可能ファイルを実行すると、-rpath-linkで指定されたパスは無効になります(リンカは有効ではありません)。ライブラリを変更しないパスは実行可能ファイルに含まれています)、-rpathで指定されたパスは引き続き有効です(リンカが実行可能ファイルにライブラリのパスを含めているため)。

最後に、-rpathまたは-rpath-linkのどちらが使用されているかに関係なく、LD_LIBRARY_PATHは引き続き有効です。

4.ldコマンドのマニュアル

4.1 -rpath = dir

|_+_|
  1. ディレクトリを追加するランタイムライブラリの検索パス。このです中古いつELF実行可能ファイルのリンク 共有オブジェクト。
  2. すべての-rpath引数は連結されますそして合格しましたそれらを使用するランタイムリンカー見つける共有のオブジェクト
  3. ランタイム。 -rpathオプション ですまた使用いつ見つける共有必要なオブジェクト沿って 共有オブジェクトを明示的に
  4. 含まれていますリンクは説明を参照してください-rpath-linkオプション場合-rpathです ない中古いつELFをリンクする
  5. 実行可能ファイル、コンテンツ環境変数'LD_RUN_PATH'使用されますもしそれです定義されています。
  6. -rpathオプション使用することもできますオンSunOS。沿って デフォルトオンSunOS、リンカーは実行時の検索パスを形成します
  7. すべての-Lオプションそれです与えられた。場合-rpathオプション です使用すると、ランタイム検索パスが排他的に形成されますを使用して
  8. -Lオプションを無視して、-rpathオプション。これは便利ですいつ を使用してgccは、多くの-Lオプションを追加します。
  9. ありますオンNFSマウントされたファイルシステム。
  10. ために互換性他のELFリンカー、もし-Rオプション です続いて沿ってファイル名ではなくディレクトリ名、
  11. です扱われるなので-rpathオプション

4.2 -rpath-link = dir

|_+_|
  1. いつ を使用して妖精またはSunOS、1つ共有ライブラリには別のものが必要な場合があります。これが起こりますいつAN'ld-shared'リンクには
  2. 共有図書館なので1入力ファイル。
  3. いつリンカはそのような依存関係に遭遇しますいつ共有、再配置不可能なリンク、自動的に試してみてください
  4. 必要なものを見つける共有図書館そしてそれを含めるリンク、もしそれです ない明示的に含まれています。そのような場合
  5. -rpath-linkオプション最初を指定しますセットする ディレクトリ探す。 -rpath-linkオプションシーケンスを指定できます
  6. ディレクトリ名のいずれか沿ってリストを指定する区切られた名前沿って入植者、または 沿って複数回出現します。
  7. このオプション使用すべきです注意なのでそれオーバーライドハードコンパイルされた可能性のある検索パス共有
  8. 図書館。そのような場合それです可能ランタイムリンカーとは意図せずに異なる検索パスを使用する行う

4.3検索パス

  1. リンカは次の検索パスを使用します必要な場所を探す共有ライブラリ:
  2. 1.1。指定されたディレクトリ沿って-rpath-linkオプション。
  3. 二。指定されたディレクトリ沿って-rpathオプション。 -rpathの違いそして-rpath-linkですそのディレクトリ
  4. 指定沿って-rpathオプションが含まれています実行可能ファイルそして実行時に使用されますが、-rpath-linkオプション です
  5. リンク時にのみ有効です。 -rpathを検索していますこちらですですサポートされているのみ沿ってネイティブリンカーそしてクロスリンカー
  6. 構成されている--sysrootオプション
  7. 3.3。 オンELFシステム、ためにネイティブリンカー、もし-rpathそして-rpath-linkオプションはない使用、内容を検索
  8. 環境変数'LD_RUN_PATH'
  9. 四。 オンSunOS、もし-rpathオプションだったない使用済み、指定されたディレクトリを検索を使用して-Lオプション。
  10. 5.5。 ためにネイティブリンカー、コンテンツを検索環境変数'LD_LIBRARY_PATH'
  11. 6.6。 ためにネイティブELFリンカー、ディレクトリ 'DT_RUNPATH' または 「DT_RPATH」 共有ライブラリが検索されますために 共有
  12. 必要なライブラリ沿ってそれ。ザ・「DT_RPATH」エントリは無視されますもし 'DT_RUNPATH'エントリが存在します。
  13. 7。ザ・デフォルトディレクトリ、通常/lib そして/ usr /lib
  14. 8.8。 ためにネイティブリンカーオンELFシステム、もしファイル/etc/ld.so.confが存在し、リスト見つかったディレクトリそれ
  15. ファイル。

参考文献

[1] ダイナミックライブラリのリンクおよびリンクオプション-L、-rpath-link、-rpath

[二] ld-rpathおよび-rpath-linkオプション