回答:
ローダーは、経由で明示的に指示されない限り、共有オブジェクトの現在のディレクトリをチェックしません$LD_LIBRARY_PATH
。詳細については、ld.so(8)
manページを参照してください。
:
は、セミコロンではなくコロン()で区切られます。
LD_LIBRARY_PATHを設定して、動的リンカーに参照先を知らせることができますが、より良いオプションがあります。共有ライブラリを標準の場所のいずれかに配置できます。これらの場所のリストについては/etc/ld.so.conf
、/usr/bin/crle
(Linuxの場合)および(Solarisの場合)を参照してください
-R <path>
バイナリをビルドするときにリンカーに渡すことができます。これ<path>
により、共有ライブラリ用にスキャンされるディレクトリのリストに追加されます。以下に例を示します。最初に、問題を示します。
libtest.h:
void hello_world(void);
libtest.c:
#include <stdio.h>
void hello_world(void) {
printf("Hello world, I'm a library!\n");
}
こんにちはC:
#include "libtest.h"
int main(int argc, char **argv) {
hello_world();
}
Makefile(タブを使用する必要があります):
all: hello
hello: libtest.so.0
%.o: %.c
$(CC) $(CFLAGS) -fPIC -c -o $@ $<
libtest.so.0.0.1: libtest.o
$(CC) -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0.1 libtest.o
libtest.so.0: libtest.so.0.0.1
ln -s $< $@
clean:
rm -f hello libtest.o hello.o libtest.so.0.0.1 libtest.so.0
実行してみましょう:
$ make
cc -fPIC -c -o libtest.o libtest.c
cc -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0.1 libtest.o
ln -s libtest.so.0.0.1 libtest.so.0
cc hello.c libtest.so.0 -o hello
$ ./hello
./hello: error while loading shared libraries: libtest.so.0: cannot open shared object file: No such file or directory
修正方法 -R <path>
リンカーフラグに追加します(ここでは、設定しますLDFLAGS
)。
$ make clean
(...)
$ make LDFLAGS="-Wl,-R -Wl,/home/maciej/src/tmp"
(...)
cc -Wl,-R -Wl,/home/maciej/src/tmp hello.c libtest.so.0 -o hello
$ ./hello
Hello world, I'm a library!
バイナリを見ると、それが必要であることがわかりますlibtest.so.0
:
$ objdump -p hello | grep NEEDED
NEEDED libtest.so.0
NEEDED libc.so.6
バイナリは、指定されたディレクトリで、標準の場所とは別にそのライブラリを探します。
$ objdump -p hello | grep RPATH
RPATH /home/maciej/src/tmp
バイナリで現在のディレクトリを検索する場合は、RPATHをに設定できます$ORIGIN
。ドル記号がmakeによって解釈されないようにする必要があるため、これは少し注意が必要です。これを行う1つの方法を次に示します。
$ make CFLAGS="-fPIC" LDFLAGS="-Wl,-rpath '-Wl,\$\$ORIGIN'"
$ objdump -p hello | grep RPATH
RPATH $ORIGIN
$ ./hello
Hello world, I'm a library!
make
手動で呼び出すときなど、使用しない場合は、空の文字列に展開されないようにしてg++
ください-Wl,-rpath='$ORIGIN'
(一重引用符に注意してください)$ORIGIN
。
ビルドにCMakeを使用している場合はCMAKE_EXE_LINKER_FLAGS
、次を設定できます。
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath='$ORIGIN'")
これにより、すべてのビルドタイプ(Debug、Releaseなど)のリンカーフラグが適切に伝達され、最初に現在の作業ディレクトリで.soファイルが検索されます。
動的リンカーは、ライブラリを探す場所を決定します。Linuxの場合、動的リンカーは通常GNU ld.so
(または互換性の理由で通常同じ動作をする代替手段です)。
ウィキペディアからの引用:
GNU Cライブラリの動的リンカーは、次の場所で共有ライブラリを検索します。
DT_RPATH
バイナリの動的セクション属性に(コロンで区切られた)パスが存在し、そのDT_RUNPATH
属性が存在しない場合。- 環境変数内の(コロンで区切られた)パス。
LD_LIBRARY_PATH
実行可能ファイルがsetuid
/setgid
バイナリでない場合は、無視されます。LD_LIBRARY_PATH
オプション--library-path(例:/lib/ld-linux.so.2 --library-path $ HOME / mylibs myprogram)を指定して動的リンカーを呼び出すと、オーバーライドできます。DT_RUNPATH
存在する場合、バイナリの動的セクション属性の(コロンで区切られた)パス。- ldconfigキャッシュファイル(多くの場合
/etc/ld.so.cache
)に基づく検索。これには、拡張ライブラリパス(で設定/etc/ld.so.conf
)で以前に見つかった候補ライブラリのコンパイル済みリストが含まれます 。ただし、バイナリが-z nodefaultlib
リンカーオプションでリンクされている場合、デフォルトのライブラリパスのライブラリはスキップされます。- 信頼できるデフォルトのパス
/lib
で、次に/usr/lib
。バイナリが-z nodefaultlibリンカーオプションでリンクされた場合、この手順はスキップされます。
echo $LD_LIBRARY_PATH
私のマシンでは空です: