ここの続き。
今回は、共有ライブラリを作る手順と、インストールのターゲットの作成方法。(make install
みたいなの。)
共有ライブラリを作成する
入力パラメータとして渡した名前name
を、"Hello <name>!"
として標準出力する関数を提供するライブラリを作成してみる。
まずはヘッダlibhello.h
。
#ifndef __LIBHELLO_H__
#define __LIBHELLO_H__
void hello(char* in_name);
#endif /* __LIBHELLO_H__ */
次に、ソースlibhello.c
。
#include <stdio.h>
void hello(char* in_name) {
printf("Hello %s!\n", in_name);
}
共有ライブラリを作成するSConstruct
は、以下。SharedLibrary()
関数を使って、共有ライブラリを作成する。
env = Environment()
# Create a shared library
lib_target = "libhello"
lib_sources = ["libhello.c"]
env.SharedLibrary(target=lib_target, source=lib_sources)
ここまでで作成されたファイルは、以下。
$PROJ_ROOT
├── libhello.c
├── libhello.h
└── SConstruct
ここで一度、scons
コマンドを実行すると、$PROJ_ROOT
にlibhello.so
が作成されるはず。
$PROJ_ROOT
├── libhello.c
├── libhello.h
├── libhello.os
├── libhello.so <= (*)
└── SConstruct
共有ライブラリの利用者側プログラム
libhello.so
を利用する側のプログラムhello
を作成する。ライブラリが提供するhello()
を呼び出すだけのプログラム。
#include "libhello.h"
int main(void) {
hello("World");
return 0;
}
hello
を作成するコードを追加したSConstruct
は以下。
env = Environment()
# Create a shared library
lib_target = "libhello"
lib_sources = ["libhello.c"]
env.SharedLibrary(target=lib_target, source=lib_sources)
# Create a exectable using libhello.so
bin_target = "hello"
bin_sources = ["hello.c"]
env.Program(target=bin_target, source=bin_sources, parse_flags="-I. -L. -lhello")
ここまでで、共有ライブラリlibhello.so
と、呼び出し側のhello
プログラムが作成されるはずなので、scons
コマンドを実行する。ビルドが正常に完了すると、以下のように、それぞれのファイルが作成されているはず。
$PROJ_ROOT
├── hello <= 実行可能形式のプログラム
├── hello.c
├── hello.o
├── libhello.c
├── libhello.h
├── libhello.os
├── libhello.so <= 共有ライブラリ
└── SConstruct
実行してみる
libhello.so
のありかをhello
に教えてあげるために、LD_LIBRARY_PATH
にlibhello.so
のパスを設定する。
正常に実行されると、Hello World!
という文字列が標準出力に出力される。
$ LD_LIBRARY_PATH=. ./hello
Hello World!
インストールターゲットを定義する
共有ライブラリをインストールするターゲットを定義してみる。
これまでに作成したSConstruct
を若干いじって以下のようにする。
env = Environment()
# Create a shared library
lib_target = "libhello"
lib_sources = ["libhello.c"]
libhello = env.SharedLibrary(target=lib_target, source=lib_sources)
# Create a exectable using libhello.so
bin_target = "hello"
bin_sources = ["hello.c"]
env.Program(target=bin_target, source=bin_sources, parse_flags="-I. -L. -lhello")
env.Install(dir="/usr/local/lib", source=libhello)
変更したのは、env.SharedLibrary()
の戻り値をlibhello
変数に受けているところと、最後の行である。(差分)
ここで、scons /usr/local/lib
コマンドを実行すると、/usr/local/lib
にlibhello.so
がインストールされているはずである。
$ sudo scons /usr/local/lib
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
Install file: "libhello.so" as "/usr/local/lib/libhello.so"
scons: done building targets.
インストールターゲットを改良する
scons
コマンドのターゲットに、フルパスを渡すのは面倒なので、Alias
という機能を使う。最終行を追加した。(差分)
env = Environment()
# Create a shared library
lib_target = "libhello"
lib_sources = ["libhello.c"]
libhello = env.SharedLibrary(target=lib_target, source=lib_sources)
# Create a exectable using libhello.so
bin_target = "hello"
bin_sources = ["hello.c"]
env.Program(target=bin_target, source=bin_sources, parse_flags="-I. -L. -lhello")
env.Install(dir="/usr/local/lib", source=libhello)
env.Alias("install", ["/usr/local/lib"])
今度は、scons install
コマンドを実行する。先ほどと同様、/usr/local/lib
にインストールされるはずである。
$ sudo scons install
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
Install file: "libhello.so" as "/usr/local/lib/libhello.so"
scons: done building targets.