ld.so(8)のmanページ では、
ライブラリの依存関係を解決するとき、ダイナミックリンカーはまず各依存関係文字列を検査してスラッシュが含まれているかどうかを確認します(これは、スラッシュを含むライブラリパス名がリンク時に指定された場合に発生します)。スラッシュが見つかった場合、依存文字列は(相対または絶対)パス名として解釈され、ライブラリはそのパス名を使用してロードされます。
スラッシュ付きのパスを持つライブラリに対してgcc
をリンクするにはどうすればよいですか?私は-l
を試してみましたが、それはパス引数自体ではなく、さまざまなパスの検索に使用するライブラリ名でのみ機能するようです。
次の質問:この方法で相対パスにリンクする場合、相対パスは何ですか(たとえば、バイナリを含むディレクトリまたは実行時の作業ディレクトリ)?
検索時に見つけたすべてのリンクガイドは、RPATH
、LD_LIBRARY_PATH
、RUNPATH
を使用して議論しています。 RPATH
は非推奨であり、ほとんどの議論ではLD_LIBRARY_PATH
の使用を推奨していません。 $Origin
で始まるパスを含むRUNPATH
は、相対パスへのリンクを許可しますが、LD_LIBRARY_PATH
によってオーバーライドされる可能性があるため、少し脆弱です。相対パスの方が堅牢であるかどうかを知りたいと思っていました(これについて説明していることが見つからないので、おそらくパスがランタイムディレクトリからの相対パスであるため、そうではないと思います)。
(今のところ)gcc
または質問のリンク部分を無視し、代わりにLinuxシステムでバイナリを patchelf
で変更する場合
$ ldd hello
linux-vdso.so.1 => (0x00007ffd35584000)
libhello.so.1 => not found
libc.so.6 => /lib64/libc.so.6 (0x00007f02e4f6f000)
/lib64/ld-linux-x86-64.so.2 (0x00007f02e533c000)
$ patchelf --remove-needed libhello.so.1 hello
$ patchelf --add-needed ./libhello.so.1 hello
$ ldd hello
linux-vdso.so.1 => (0x00007ffdb74fc000)
./libhello.so.1 => not found
libc.so.6 => /lib64/libc.so.6 (0x00007f2ad5c28000)
/lib64/ld-linux-x86-64.so.2 (0x00007f2ad5ff5000)
これで、相対パスライブラリを含むバイナリが作成されました。これには、libhello.so.1
ファイルが存在します
$ cd english/
$ ../hello
hello, world
$ cd ../lojban/
$ ../hello
coi rodo
パスがプロセスの作業ディレクトリからの相対パスであることがわかります。これにより、あらゆる種類の問題、特に security が開かれます。 問題 。おそらく、ライブラリのさまざまなバージョンをテストするなど、生産的な使用法があるかもしれません。相対作業ディレクトリを複雑にすることなく、2つの異なるバイナリをコンパイルするか、必要なライブラリでpatchelf
をコンパイルする方が簡単です。
libhello
にはhelloworld
呼び出しのみがあります
$ cat libhello.c
#include <stdio.h>
void helloworld(void)
{
printf("coi rodo\n");
}
経由でコンパイルされました
CFLAGS="-fPIC" make libhello.o
gcc -shared -fPIC -Wl,-soname,libhello.so.1 -o libhello.so.1.0.0 libhello.o -lc
ln -s libhello.so.1.0.0 libhello.so.1
ln -s libhello.so.1.0.0 libhello.so
hello
呼び出しを行うhelloworld
は、
$ cat hello.c
int main(void)
{
helloworld();
return 0;
}
$ CFLAGS="-lhello -L`pwd`/english" make hello
後から、相対ディレクトリパスを使用するようにgcc
コマンドを変更します。
$ gcc -shared -fPIC -Wl,-soname,./libhello.so.1 -o libhello.so.1.0.0 libhello.o -lc
$ cd ..
$ rm hello
$ CFLAGS="-lhello -L`pwd`/lojban" make hello
$ ldd hello | grep hello
./libhello.so.1 => not found
$ english
$ ../hello
hello, world
通常の方法でライブラリをコンパイルしてから、必要に応じてpatchelf
を使用してバイナリをいじるほうが賢明でしょう。
リンカーにオプションを渡すことによってこれを行います。たとえば、ncursesのビルドディレクトリ(インストールされていないライブラリに依存する)からテストプログラムを実行するには、次のようなオプションを使用します(gccコマンドラインで)。
-Wl,-rpath,../lib
これは相対パス名を埋め込みます。同じオプションで絶対パス名を埋め込むことができます。
-Wl,-rpath,../lib:/usr/local/ncurses6/lib
これはローカルテストには役立ちますが、さまざまな理由でシステムにインストールする場合には役立ちません。 Debianにはそれに対するポリシーがあります。1990年代にさかのぼりますが、首尾一貫した議論はまれです(たとえば、一部の情報を収集する RPATHの問題 を参照)。