相対パスを使用して共有ライブラリに接続するには?

相対パスを使用して共有ライブラリに接続するには?

内部にld.so(8) のマニュアルページ、それは言う

ライブラリの依存関係を解決するとき、動的リンカはまず各依存関係文字列にスラッシュが含まれていることを確認します。これは、スラッシュを含むライブラリパス名がリンク時に指定された場合に発生します。スラッシュが見つかると、依存関係文字列は(相対または絶対)パス名として解釈され、そのパス名を使用してライブラリがロードされます。

gccスラッシュパスでライブラリをリンクする方法は?私はそれを試しましたが、-lパスパラメータ自体ではなく、さまざまなパスを取得するために使用するライブラリ名でのみ機能するようです。

次の質問:この方法で相対パスに接続するときの相対パスは何ですか(たとえば、バイナリを含むディレクトリまたは実行時の作業ディレクトリ)。

検索中に見つかったすべてのリンクされたガイドは、およびをRPATH使用LD_LIBRARY_PATHして議論されましたRUNPATH。 .で始まるパスは廃止され、RPATHほとんどの議論では相対パスへの接続を許可しますが、上書きされる可能性がある点でわずかに脆弱ですLD_LIBRARY_PATH。相対パスがより強力であるかどうか疑問に思います(これについて議論する内容が見つからないため、おそらくパスがランタイムディレクトリに相対的であるため)。RUNPATH$ORIGINLD_LIBRARY_PATH

答え1

(今は)gcc質問のまたはリンク部分を無視し、代わりに次のようにバイナリを修正した場合patchelfLinuxシステムでは

$ 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

パスがプロセスの作業ディレクトリに相対的であることがわかりました。、これは特にさまざまな問題を引き起こすでしょう。安全 質問。これはおそらく、異なるバージョンのライブラリをテストするなど、生産的な用途に使用できます。patchelf相対的な作業ディレクトリを複雑にすることなく、2つの異なるバイナリをコンパイルしたり、必要なライブラリからコンパイルする方が簡単になる可能性があります。

コンパイルステップ

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

答え2

リンカーにオプションを渡すだけです。たとえば、ncursesビルドディレクトリ(削除されたライブラリに依存)からテストプログラムを実行するには、次のオプションを使用します(gccコマンドラインから)。

-Wl,-rpath,../lib

相対パス名が含まれています。同じオプションで絶対パス名を含めることができます。

-Wl,-rpath,../lib:/usr/local/ncurses6/lib

これはローカルテストには役立ちますが、さまざまな理由でシステムにインストールするのには適していません。 Debian は 1990 年代からこれに反対する政策を持っていますが、一貫した議論はほとんどありません (例:RPATHの問題一部の情報を収集します。)

答え3

gccを使って簡単にコンパイルする場合は、次のようにします。

gcc -o prog main.c ./liblib.so

コンパイル後、プログラムはthrigの答えと同じように動作します。このコマンドはテスト環境でのみ使用する必要があると思います。

関連情報