本ページはプロモーションが含まれています

Linux共有ライブラリ「.so」の作り方


Linuxでは、C/C++プログラムの実行時に動的にリンク(または実行後にロード)するライブラリを、「共有ライブラリ」と呼んでいます。WindowsでのDLLファイル(ダイナミック・リンクライブラリ)に相当するものです。共有ライブラリの拡張子は「.so」となっています。
Linuxの共有ライブラリ「.so」ファイルの作り方と、リンクさせるための設定や手続きを簡単にまとめました。

共有ライブラリ(.so)の作成

次のような、main()の中でshowmsg()を呼び出すだけのC言語コードを例として、showmsg()message.cに書いて、それを動的にリンクする共有ライブラリlibmessage.soとして作成してみます。
test.c
#include "message.h"
int main(int argc, char *argv[])
{
    return showmsg();
}
共有ライブラリにするmessage.cを次のように書きます。
message.c
#include <stdio.h>
int showmsg(void)
{
    printf("Hello so Test\n");
    return 0;
}
message.h
int showmsg(void);
最後にこれらをmakeするMakefileです。
Makefile
all: libmessage.so test

libmessage.so: message.c
    gcc -shared -fPIC -o $@ $^
        
test: test.o
    gcc -L./ -o $@ $^ -lmessage

%.o : %.c
    gcc -o $@ -c $<

clean:
    -rm -f *.so *.o
message.cから共有ライブラリ「libmessage.so」を作成するルールを説明します。
libmessage.so: message.c
    gcc -shared -fPIC -o $@ $^
ライブラリの名前に「lib〜」をつけるのはライブラリの決まりです。リンクする側が-lオプションでライブラリ名を指定するときは「lib」を除いたファイル名を指定することになっています。
共有ライブラリを作成する場合は、gccオプションに、
-shared
を付けます。このとき通常のコンパイルを指示する-cは付けません(これらは同時に付けられません)。次の
-fPIC
も共有ライブラリのためのオプションで、位置独立コード(PIC= Position-Independent Code)の生成を指示します。位置独立とは、メモリのどこに配置されても絶対的アドレスに関係なくリンクできるコードのことです。このオプションは必須ではなく、付けないで作成しても問題なく動きます。ただし、その場合は実行時にバイナリコードのアドレス再配置処理が余計に動くので、効率が悪くなります。位置独立に加え、より小さい高速なコードの生成を指示する-fpicという小文字にしたものがありますが、プロセッサによって制限されることがあるので汎用的ではありません。
次に、リンクする側のtest.cのルールを見ます。
test: test.o
    gcc -L./ -o $@ $^ -lmessage
-Lオプションに続き、ライブラリファイルのパスを指定します。これは静的ライブラリと同じです。
-lmessage
は、共有ライブラリ名を指定します。-lに続けてlibの部分を除いたsoファイル名を指定します。
makeを実行すると、testlibmessage.soが作成されます。
$ make
gcc -shared -o libmessage.so message.c
gcc -o test.o -c test.c
gcc -L./ -o test test.o -lmessage

動的リンクのための設定

作成したtestは、まだこの状態では動きません。libmessage.soの場所がわからないからです。
上記の「-L」のライブラリの場所というのは、-lに指定するファイルの場所であり、つまり、コンパイル時の場所のことです。実行時のsoの在り処を設定する手続きはそれとは別に必要なのです。
動的リンク時には、次の順番で共有ライブラリを探します。
① 環境変数LD_LIBRARY_PATHに設定されている場所
② /etc/ld.so.confに書いてある場所
③ /usr/lib /lib /lib64
環境変数LD_LIBRARY_PATHlibmessage.soファイルが置かれているディレクトリパスを指定すると、その環境では正しくリンクされ動作します。
export LD_LIBRARY_PATH=/home/usrt/mysodir
$ ./test
Hello so Test
環境変数を使わずに特定の環境以外で利用する場合は、/etc/ld.so.confに登録します。/etc/ld.so.confはテキストファイルで、
/home/user/mysodir
のように共有ファイルが置いてあるディレクトリのパスを行ごとに書きます。Linuxによっては/etc/ld.so.conf.dのディレクトリ以下に、任意にxxx.confを書く方法があります。実際のリンク時には、/etc/ld.so.confをもとに生成された/etc/ld.so.casheというバイナリファイルが参照されます。ld.so.casheを更新するには編集後に、
$ sudo ldconfig
を実行する必要があります(編集もコマンドもルート権限が必要です)。
全てのユーザから利用するには、③のように/usr/lib /lib /lib64以下にsoファイルをコピーします。

コンパイル時にパスを指定してしまう方法

コンパイル時のリンカオプションで、共有ライブラリの場所を事前に指定しておく方法があります。この方法ならば、「共有」という目的から少し外れますが、環境変数や/etc/ld.so.confの手続きは不要です。
上記のMakefileにて、リンクする側のtestのコンパイル・リンクルールを次のようにします。
    gcc -L./ -Wl,-rpath=./ -o $@ $^ -lmessage
-Wl,-rpath=〜」にsoファイルのパスを指定します。上記の場合はカレントディレクトリを指定しています。