Apache HTTP Server 2.x系でプラットフォーム依存部分を吸収し、一貫したAPIを提供するために利用されているライブラリAPR - Apache Portable Runtimeを、Apache以外のプロジェクトで利用するための方法。
Apache module APIの美味しいドコ取り
APRを使用するとApache module APIで利用できていたしかしASFの他のプロジェクトと同様に、APIのリファレンスマニュアルはあれど、その利用方法やサンプルに関するドキュメントは貧弱です。というわけで、あなたのプロジェクトでAPRを利用する(取り込む)ための手順と、それを簡略化するツールについて書いてみます。
ここで説明するビルド環境を構築するためにはAPRの他に
APRを取り込む手順
APRは単なるライブラリなので、あなたのプログラムからリンクすれば利用できます。終了というのもナンなので、次のような要件を満たすための手順を考えてみます。
- プロジェクトの配付パッケージにAPRをバンドルしたい
- GNU Automake/Autoconf/libtoolなどのGNU Autotoolsをプロジェクトで使用したい
$ wget http://www.apache.org/dist/apr/apr-0.9.3.tar.gz $ tar zxvf apr-0.9.3.tar.gz $ cd apr-0.9.3/ $ ./configure $ make $ sudo make install詳細なコンパイルオプションなどは割愛します。この場合おそらく次のようなレイアウトで、APRがインストールされたと思います。
/usr/local/apr/bin/apr-config /usr/local/apr/build/apr_rules.mk /usr/local/apr/build/libtool /usr/local/apr/lib/libapr-0.a /usr/local/apr/lib/libapr-0.*次にAPRを利用するプロジェクトmyprojectを作成し、取り込みの手順を見てみましょう。プロジェクトに必要なファイルは
ディレクトリとソースコードの用意
では実際にプロジェクトのディレクトリと、ソースコードmyproject.cを用意します。$ mkdir myproject $ cd myproject $ vi myproject.c
#include "apr_errno.h" #include "apr_general.h" #include "apr_strings.h" #include "apr_file_io.h" #include "apr_pools.h" #include <stdlib.h> #include <unistd.h> static apr_file_t *local_stdout, *local_stdin, *local_stderr; int main(int argc, const char * const *argv) { apr_pool_t *p; apr_status_t rc; char *str; /* initialize */ apr_app_initialize(&argc, &argv, NULL); apr_pool_create(&p, NULL); apr_file_open_stdout(&local_stdout, p); apr_file_open_stdin(&local_stdin, p); apr_file_open_stderr(&local_stderr, p); str = apr_pstrcat(p, "myproject", ": ", "Hello World", NULL); apr_file_printf(local_stdout, "\n", str); return EXIT_SUCCESS; }いくつかのAPRの関数を使用しているほかは、普通のCのソースコードと同じです。このソースコードは
- APR環境の初期化
- リソースプールの生成
- stdout, stdin, stderrのオープン
- 文字列"myproject: Hello World"を結合
- stdoutに文字列を出力
さらにプロジェクト内にAPRのコードツリーへのシンボリックリンクを作成します。APRのコードツリーのパスや各種設定値は、
/usr/local/apr/bin/apr-configを使用して調べることができます。コードツリーのパスは--srcdirオプションで得ることが出来るので、次のようにシンボリックリンクを作成します。シンボリックリンクではなくコードツリー全体をmyprojectにコピーしても構いません。
$ ln -s `/usr/local/apr/bin/apr-config --srcdir` apr $ ls -F apr@ myproject.c
Makefile.amの用意
次に、プロジェクト内で使用するソースコードのビルド方法などを指定するMakefile.amを用意します。Makefie.amはGNU Automakeプログラムが使用する定義ファイルで、Makefile.amファイルを設置したディレクトリでautomakeコマンドを実行すると、Makefileの雛型となるMakefile.inを生成します。$ vi Makefile.am
INCLUDES = -I$(srcdir)/apr/include SUBDIRS = apr bin_PROGRAMS = myproject myproject_SOURCE = myproject.c myproject_LDADD = apr/libapr-0.laこのプロジェクトではAPRを使用するので、プロジェクト内のAPRのヘッダファイルのディレクトリへのパスを
INCLUDES = -I$(srcdir)/apr/includeで指定します。またAPRをビルドする必要があるので、APRのコードツリーへのパスを
SUBDIRS = aprで指定します。
このプロジェクトでは実行ファイルmyprojectをビルドします。ビルドする実行ファイルの名称を
bin_PROGRAMS = myprojectで指定し、そのソースコードを
myproject_SOURCE = myproject.cに列挙します。またmyprojectプログラムはAPRをリンクする必要があるので
myproject_LDADD = apr/libapr-0.laでAPRのLibtoolライブラリlibapr-0.laのパスを指定します。Libtoolライブラリにつて詳細は
GNU Autoconf/Automake/Libtoolを参照して、私に聞かないでください :)
configure.inの用意
次に、ビルド環境のチェックや調整を行うconfigureスクリプトの処理内容を定義するconfigure.inファイルを用意します。configure.inファイルはGNU Autoconfプログラムが使用する定義ファイルで、configure.inファイルを設置したディレクトリでautoconfコマンドを実行すると、configureスクリプトを生成します。$ vi configure.in
AC_INIT() AC_CONFIG_AUX_DIR(build) AM_INIT_AUTOMAKE(myproject, 0.0.0, no-define) sinclude(build/apr_common.m4) sinclude(build/find_apr.m4) echo $ac_n "${nl}Configuring Apache Portable Runtime library ...${nl}" APR_FIND_APR("$srcdir/apr", "./apr", 1) if test "$apr_found" = "reconfig"; then APR_SUBDIR_CONFIG(apr) fi AC_PROG_CC AC_PROG_LIBTOOL AC_OUTPUT(Makefile)configure.inの内容については割愛します。また、configureスクリプトへの変換に使用するAPR固有のマクロファイルを、下記のとおりプロジェクト内に設置します。
$ mkdir build $ ln -s `/usr/local/apr/bin/apr-config --srcdir`/build/apr_common.m4 build/apr_common.m4 $ ln -s `/usr/local/apr/bin/apr-config --srcdir`/build/find_apr.m4 build/find_apr.m4 $ ls -F build apr_common.m4@ find_apr.m4@最後にGNU Autoconf, Automakeが要求する各ファイルを設置します。とりあえずは空のファイルを作成しておきます。
$ touch NEWS README AUTHORS ChangeLog最終的にmyprojectは次のようなファイルのレイアウトになりました。
$ ls -F AUTHORS Makefile.am README build/ myproject.c ChangeLog NEWS apr@ configure.in
ビルド用ファイルの生成
プロジェクトのソースコード及び各定義ファイルの用意ができたので、最後にMakefile.inやconfigureスクリプトなどのビルド用のファイルを生成しす。まず、configure.inで使用するマクロから非標準のものを検索し、aclocal.m4に追加するaclocalコマンドを実行します。$ aclocalaclocalコマンドを実行すると、aclocal.m4ファイルが生成されます。
$ ls -F AUTHORS Makefile.am README apr@ configure.in ChangeLog NEWS aclocal.m4 build/ myproject.c次にソースコードのコンパイルやリンクに使用するlibtoolスクリプトを生成するために、libtoolizeコマンドを実行します。
$ libtoolize You should update your `aclocal.m4' by running aclocal. Putting files in AC_CONFIG_AUX_DIR, `build'.libtoolizeコマンドを実行するとプロジェクトの buildディレクトリにconfig.guess,config.sub,ltmain.shの各ファイルが作成されます。(正確には既にインストールされているファイルへのシンボリックリンクです)
$ ls -F build apr_common.m4@ config.guess@ config.sub@ find_apr.m4@ ltmain.sh@次にMakefileの雛型となるMakefile.inファイルを生成するために、automakeコマンドを実行します。automakeコマンドはMakefile.am等の定義を元にMakefile.inファイルを生成します。
$ automake --add-missing configure.in: installing `build/install-sh' configure.in: installing `build/mkinstalldirs' configure.in: installing `build/missing' Makefile.am: installing `./COPYING' Makefile.am: installing `./INSTALL' Makefile.am: installing `build/depcomp'automakeコマンドの--add-missingオプションは、必要なファイルをインストールしてくれます。
最後にautoconfコマンドを実行すると、configure.inファイルからconfigureスクリプトを生成します。
$ autoconf最終的にプロジェクト内に次のようなファイルを設置・生成しました。
$ ls -F AUTHORS INSTALL@ NEWS apr@ configure* COPYING@ Makefile.am README autom4te.cache/ configure.in ChangeLog Makefile.in aclocal.m4 build/ myproject.cこのうち aclocal.m4ファイルと autom4te.cachディレクトリは不要になったので削除しておいても構いません。
$ rm -rf aclocal.m4 autom4te.cache
プロジェクトのビルド
用意したプロジェクトをビルドしてみましょう。一般的なオープンソースプロジェクトのソースパッケージと同様の手順でビルドできます。$ ./configure $ makeconfigureスクリプトはサブディレクトリapr/内のconfigureスクリプトも実行します。makeするとapr/ディレクトリ内のライブラリもビルドされます。
ビルドが成功すると、カレントディレクトリに実行ファイルmyprojectが生成されますが、これはビルド環境内で正しくライブラリを見つけられるように、必要な環境設定などを行った上でプログラムを実行するshellスクリプトによるラッパーです。
$ ./myproject myproject: Hello World $ file ./myproject myproject: Bourne shell script text実行ファイルの実体は.libs/myprojectに在り、make installするとこちらの実行ファイルがインストールされます。
プロジェクトのメンテナンス
以上でGNU Autotoolの元でAPRを利用する環境を構築(APRizeというらしい)することができました。プロジェクトにソースコードを追加する場合はMakefile.amにそのファイル名を追加した上で、automakeコマンドを再度実行して最新のMakefile.inを生成する必要があります。これらの作業は定型的なものなんで、次のようなshellスクリプトbuildconfなどを用意し、定義ファイルを更新した際に実行してプロジェクトをメンテナンスします。$ vi buildconf
#!/bin/sh aclocal libtoolize automake --add-missing autoconf rm -rf aclocal.m4 autom4te.cache
まとめ
APRをプロジェクトに取り込み、オープンソースプロジェクトっぽくGNU Autotoolsを利用したビルド環境を構築する手順を説明しました。手数が多く少々面倒に思えるかもしれませんが、Automakeは高度なMakefileの雛型を生成してくれ、Libtoolはコンパイラの種類を問わない一貫したコンパイルやリンクのコマンドインターフェイスを提供してくれます。ちなみにこれらの手順を自動化するスクリプト aprize を作成してAPRの開発者メーリングリストにpostしてみたのですが、今のところ完全に無視されているようです :-) APRはライブラリなので、雑多なツールは必要ないのかもしれません。もしご入用でしたならばダウンロードして、スクリプト中の
my $installbuilddir = "/usr/local/apr/build"; # @installbuilddir@の部分を
$ /usr/local/apr/bin/apr-config --installbuilddirの実行結果のパスに書き換えた上で利用してください。(APRのパッケージに取り込んでもらえれば、APRのconfigure実行時にaprize.inから適切に置換させる事ができるんですけどね) 次のように -g -nオプションとプロジェクト名を指定して実行すれば、APRizeされたプロジェクトの雛型を生成します。
$ aprize -g -n myproject Creating [DIR] myproject Creating [DIR] myproject/build Creating [FILE] myproject/configure.in Creating [FILE] myproject/Makefile.am Creating [FILE] myproject/myproject.c Creating [FILE] myproject/buildconf Creating [LINK] myproject/apr Creating [LINK] myproject/build/apr_common.m4 Creating [LINK] myproject/build/find_apr.m4 Creating [FILE] myproject/NEWS Creating [FILE] myproject/README Creating [FILE] myproject/AUTHORS Creating [FILE] myproject/ChangeLog Creating [FILE] myproject/configure You should update your `aclocal.m4' by running aclocal. Putting files in AC_CONFIG_AUX_DIR, `build'. configure.in: installing `build/install-sh' configure.in: installing `build/mkinstalldirs' configure.in: installing `build/missing' Makefile.am: installing `./COPYING' Makefile.am: installing `./INSTALL' Makefile.am: installing `build/depcomp'これだけ。ちなみにAPRはAutomakeを使っていないので、make distなどのターゲットを持っていません。そのため配布用のtar.gz等のパッケージを作成する場合は、別途スクリプトを用意した方が良いかもしれません。←だめじゃん
APRを使って気持ちよくなる方法は、また日を改めて書いてみたいと思います。