soname は、ライブラリがサポートするバイナリ API の互換性を示すために使用されます。
SONAME
リンカーによってコンパイル時に使用され、ライブラリ ファイルから実際のターゲット ライブラリのバージョンが決定されます。 gcc -lNAME
libNAME
を探します .so リンクまたはファイルは、確実により具体的な SONAME をキャプチャします (例 libnuke.so は SONAME libnuke.so.0 を含む libnuke.so.0.1.4 にリンクします)。
実行時にこれとリンクし、ELF 動的セクション NEEDED
に設定されます の場合、この名前 (またはそれへのリンク) を持つライブラリが存在する必要があります。実行時 SONAME
は無視されるので、リンクまたはファイルの存在だけで十分です。
備考:SONAME はリンク/ビルド時にのみ適用され、実行時には適用されません。
ライブラリの「SONAME」は、「objdump -p file |grep SONAME」で確認できます。バイナリの「NEEDED」は、「objdump -p file |grep NEEDED」で確認できます。
[編集] 警告 以下は一般的な意見であり、Linux に展開されたものではありません。最後に見てください。
libnuke.so.1.2 という名前のライブラリがあり、新しい libnuke ライブラリを開発するとします:
- 新しいライブラリが、API を変更せずに以前のものから修正したものである場合は、同じ soname を保持し、ファイル名のバージョンを上げる必要があります。つまり、ファイルは libnuke.so.1.2.1 になりますが、soname は libnuke.so.1.2 のままです。
- 新しい機能を追加しただけで機能を壊さず、以前と互換性がある新しいライブラリがある場合は、以前と同じ soname に .1 のような新しい接尾辞を付けて使用したいと考えています。つまり、ファイルと soname は libnuke.so.1.2.1 になります。 libnuke.1.2 にリンクされたプログラムは、そのプログラムでも動作します。 libnuke.1.2.1 にリンクされた新しいプログラムは、そのプログラムでのみ動作します (新しいサブバージョンが libnuke.1.2.1.1 のようになるまで)。
- 新しいライブラリが libnuke と互換性がない場合:libnuke.so.2
- 新しいライブラリが古いバージョンと互換性がある場合:libnuke.so.1.3 [つまり、libnuke.so.1 と互換性がある]
[編集] 完了:Linux ケース。
特定の形式としてのLinuxの実際のSONAME :lib[NAME][API-VERSION].so.[major-version]major-version は、主要なライブラリの変更ごとに増加する1つの整数値のみです.API-VERSIONはデフォルトで空です
ex libnuke.so.0
次に、実際のファイル名にはマイナー バージョンとサブバージョンが含まれます。例:libnuke.so.0.1.5
ファイルの名前を変更すると動作が変わるため、soname を指定しないことは悪い習慣だと思います。
伝統的な 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 の機能です。
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}