GNU/Linux >> Linux の 問題 >  >> Linux

共有ライブラリを構築するための「soname」オプションは何ですか?

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}

Linux
  1. コマンド単一引数の最大サイズを定義するものは何ですか?

  2. 特定のプロセスの実行時にどの共有ライブラリがロードされているかを確認する方法は?

  3. Linux での AutoResetEvent に相当する C++ は何ですか?

  1. MySQL 5.7 のデフォルトの root パスワードは何ですか?

  2. rmdir(1) と rm(1) が共存する理由は何ですか?

  3. 「影」グループは何に使用されますか?

  1. 切り取りコマンドの「フィールド」を構成するものは何ですか?

  2. useradd コマンドでオプション -o を使用するとは何ですか?

  3. `hostname` のデフォルトのファイルは何ですか?