web-dev-qa-db-ja.com

コンパイル段階でライブラリの場所をすでにリンクしているのに、プログラムを実行する前にLD_LIBRARY_PATHを設定する必要があるのはなぜですか?

makeを使用してモデルをコンパイルしています。モデルにはMakefileがあり、-L/lib1 -L/lib2のようなフラグを介してソースコードを依存ライブラリに接続します。しかし、そのモデルを実行しようとすると、環境変数を確認しない限り失敗しますまた

export LD_LIBRARY_PATH=/lib1:/lib2

まったく同じライブラリを指します。これは私には冗長に思えます。

ここでボンネットの下で何が起こっているのでしょうか?コンパイル前と実行前にライブラリの場所を効果的に指定する必要があるのはなぜですか?

これはばかげた質問かもしれません。私は機械語へのコンパイルの経験があまりなく、通常はスクリプト言語を使用します。

2
Luke Davis

誰もがソースコードを実行可能ファイルに変換するという口語的な意味でコンパイルを使用しますが、技術的にはかなり長いパイプラインの1つのステップです。

  1. 入力ファイルはプリプロセッサを介して実行され、単一の変換ユニットになります。
  2. プリプロセッサの出力はアセンブリにコンパイルされます。
  3. アセンブラはそれを入力として受け取り、オブジェクトファイルを出力します。
  4. リンカはオブジェクトファイルをつなぎ合わせて実行可能ファイルを生成します。

[衒学者であるために、ステップが別々である必要はなく、最近のコンパイラーは通常、効率のためにそれらを組み合わせます。 ]

私たちの懸念は、コードを標準のシステムライブラリと組み合わせるリンクステップです。リンカは、静的ライブラリから実行可能ファイルにオブジェクトを直接コピーします。ただし、共有ライブラリの場合は、ライブラリへの参照のみを提供します。

共有ライブラリには多くの利点があります。プログラムを再コンパイルせずに更新でき、プログラムが共通のコードを共有できるため、メモリの使用量が少なくなります。また、コードが実行可能ファイルに含まれていないという明らかな欠点もあります。

その解決策は、実行時にすべての共有ライブラリ参照を解決する役割を担うダイナミックローダーです。ローダーは自動的に実行されます。そのための指示は、リンカーが実行可能ファイルに含めるものの1つです。もちろん、これはローダーがライブラリーを見つけることができることを前提としています。

システムライブラリは標準のディレクトリにあり、簡単です。そうでない場合、ローダーはLD_LIBRARY_PATHを検索します。リンカが実行可能ファイルにパスを配置しないのはなぜですか?そうすると、ライブラリを移動したり変更したりできなくなります。

ライブラリはシステム検索パスの外にあるため、実際には実行可能ファイルを実際に移動することもできませんでした。ライブラリが〜luke/libにあるときにのみ実行された場合は、ファイルを読み取れない限り、joeに渡すことはできません。あなたが新しい仕事に移るならば、ジョーのために吸います。

参考までに、それは他の無数の方法でも同様に吸い込むでしょう。とりわけ、コンパイル時にライブラリの場所を指定することしかできなければ、デバッグは永遠の悪夢になります。

5