「Program Library HOWTO ()」を学びました。 soname
を使用して、次のようにバージョンを管理することに言及しています。
gcc -shared -fPIC -Wl,-soname,libfoo.so.1 -o libfoo.so.1.0.0 foo.c
ln -s libfoo.so.1.0.0 libfoo.so.1
ln -s libfoo.so.1 libfoo.so
そして、soname
が設定されていないという情報を取得します。 libfoo.so.1.0.0と等しくなります。 here からの回答を参照してください。
そして、次のようにsonameなしでも動作することがわかります
gcc -shared -fPIC -o libfoo.so.1.0.0 foo.c
ln -s libfoo.so.1.0.0 libfoo.so.1
ln -s libfoo.so.1 libfoo.so
そのため、readelf -d libfoo.so
コマンドを使用してチェックするときに、soname
オプションが共有ライブラリのバージョンを通知できることが唯一の有用なポイントだと思います。
他に何ができますか?
sonameは、ライブラリがサポートするバイナリAPIの互換性を示すために使用されます。
SONAME
は、コンパイル時にリンカーによって使用され、ライブラリファイルから実際のターゲットライブラリのバージョンを判別します。 gcc -l NAME
はlib NAME
。soリンクまたはファイルを探してから、より具体的になるSONAMEをキャプチャします(ex libnuke.so SONAME libnukeを含むlibnuke.so.0.1.4へのリンク) .so.0)。
実行時にリンクされ、これがELF動的セクションNEEDED
に設定され、この名前のライブラリ(またはそのリンク)が存在するはずです。実行時にはSONAME
は無視されるため、リンクまたはファイルの存在だけで十分です。
注:SONAMEは、実行時ではなく、リンク/ビルド時にのみ適用されます。
ライブラリの「SONAME」は「objdump -p file | grep SONAME」で確認できます。バイナリの「必要」は、「objdump -p file | grep NEEDED」で確認できます。
[編集]警告以下は一般的な意見であり、Linuxにデプロイされたものではありません。最後に参照してください。
Libnuke.so.1.2という名前のライブラリがあり、新しいlibnukeライブラリを開発するとします。
[編集]完了:Linuxケース。
Linuxの実生活では、SONAMEを特定の形式として:lib [NAME] [API-VERSION] .so。[major-version] major-versionは、メジャーライブラリが変更されるたびに増加する1つの整数値です。 API-VERSIONはデフォルトでは空です
ex libnuke.so.0
次に、実際のファイル名には、マイナーバージョンとサブバージョンexが含まれます:libnuke.so.0.1.5
ファイルの名前を変更すると動作が変わるため、sonameを指定しないことは悪い習慣だと思います。
LibA.soがlibB.soに依存しており、それらがすべてディレクトリ内にあると仮定しましょう(もちろん、ディレクトリは動的リンカーによって見つけることができません)。 soname
を設定しなかった場合、dlopen
は機能しません。
auto pB = dlopen("./libB.so", RTLD_LAZY | RTLD_GLOBAL);
auto pA = dlopen("./libA.so", RTLD_LAZY | RTLD_GLOBAL);
実行時リンカーはlibB.so
を見つけることができないため、pA
はNULL
に設定されます。
この場合、soname
はあなたを地獄から救います...
Johann Klasekの答え をサポートする例を次に示します。
つまり、実行時にSONAMEが必要です。コンパイル時には、リンカー名または実名のみが必要です(例:g++ main.cpp -L. -ladd
またはg++ main.cpp -L. -l:libadd.so.1.1
)。リンカ名と実名の定義は Program Library HOWTO:3. Shared Libraries に従います。
ソースツリー:
├── add.cpp
├── add.h
├── main.cpp
└── Makefile
メイクファイル:
SOURCE_FILE=add.cpp
# main.cpp includes `add.h`, whose implementation is `add.cpp`
MAIN_FILE=main.cpp
SONAME=libadd.so.1
REAL_NAME=libadd.so.1.1
LINKER_NAME=libadd.so
OUTPUT_FILE=a.out
all:
g++ -shared -fPIC -Wl,-soname,${SONAME} -o ${REAL_NAME} ${SOURCE_FILE}
ln -s ${REAL_NAME} ${LINKER_NAME}
g++ main.cpp -I. -L. -ladd -o ${OUTPUT_FILE}
# Same as `ldconfig -n .`, creates a symbolic link
ln -s ${REAL_NAME} ${SONAME}
#./a.out: error while loading shared libraries: libadd.so.1: cannot open
# shared object file: No such file or directory
LD_LIBRARY_PATH=. ./${OUTPUT_FILE}
clean:
rm ${SONAME} ${REAL_NAME} ${LINKER_NAME} ${OUTPUT_FILE}
命名規則libname。{a}。{b}。{c}にlibx.1.0.0という名前の動的ライブラリを作成しました
{a} stand for primary version, should changes when APIs changes(which making things incompatible).
{b} stand for sub version, should changes by adding APIs.
{c} stand for mirror version, should changes by bug fixing or optimizing
これでlibx.1.2.0がリリースされます。関数を追加するだけで、人々の実行可能ファイルがクラッシュしないため、libx.1.2.0がlibx.1.0.0と互換性があることを宣言する必要があります。
Libx.1.0.0とlibx.1.2.0を同じsonameに設定する(例:libx.1)
これがsonameの機能です。
別の側面:少なくともLinuxでは、SONAMEエントリは、/ lib、/ lib64などに適切なリンクを作成する方法に関するランタイムリンカーシステムのヒントを提供します。コマンドldconfigを実行すると、SONAMEという名前のシンボリックリンクが作成されます実行時リンカーキャッシュに。同じSONAMEをタグ付けするライブラリの最新のものがリンク競合に勝ちます。一部のソフトウェアが特定のSONAMEに依存しており、ライブラリを更新する場合は、このSONAMEを指定して、この新しいライブラリにldconfigスティックを取得する必要があります(ldconfigを使用してキャッシュとリンクを再構築する場合)。例えば。 libssl.so.6とlibcrypto.so.6はそのような場合です。