ビルドシステムを作る
これまでの経験上、ビルドシステムをちゃんとつくらなかったプロジェクトはどれも途中で投げ出していたので、autotools を使って環境をちゃんとつくるところから始めていくことにしました。
ディレクトリ構成
ざっと以下のような形にすることをイメージしました。
-+- src/ (ソースコードを置く) | +- doc/ (Doxygen で生成したドキュメントなどを置く) | +- config.h | +- configure | :
configure.in を書く。
autoconf や automake の info を見ながらこつこつと書きました。とりあえずは以下のようになりました。
AC_PREREQ(2.57) AC_INIT(mod_mysql, 0.0, moriyoshi@users.sourceforge.net) AM_INIT_AUTOMAKE(mod_mysql, 0.0) AC_CONFIG_SRCDIR([src/mod_mysql.cpp]) AM_CONFIG_HEADER(config.h) AM_MAINTAINER_MODE AC_SUBST(PACKAGE_VERSION) AC_SUBST(PACKAGE_NAME) AC_SUBST(PACKAGE_TARNAME) enable_static=no AC_PROG_CXX AC_PROG_CC AC_PROG_LN_S AC_PROG_INSTALL AM_PROG_LIBTOOL AC_CHECK_PROGS([DOXYGEN], [doxygen]) AC_SUBST(DOXYGEN) AC_HEADER_STDC AC_CHECK_HEADERS([string.h]) AC_HEADER_STDBOOL AC_C_CONST AC_C_INLINE AC_TYPE_SIZE_T AC_FUNC_MEMCMP AC_CHECK_FUNCS([memmove memset strrchr]) AC_DEFUN([MOD_MYSQL_CHECK_APXS], [ APXS= AC_MSG_CHECKING([apxs location]) for _path in m4_translit($1, [ ], [ ]); do if test -x "$_path"; then APXS="$_path" break fi done if test -z "$APXS"; then AC_MSG_RESULT([not found]) $3 else AC_MSG_RESULT([$APXS]) $2 fi ]) AC_ARG_WITH([apxs], [ --with-apxs=PATH-TO-APXS specify APXS location], [ MOD_MYSQL_CHECK_APXS(["$withval"], [], [ AC_MSG_ERROR([could not find apxs in "$withval"]) ]) ], [ MOD_MYSQL_CHECK_APXS([ /usr/sbin/apxs /usr/local/sbin/apxs /usr/bin/apxs /usr/local/bin/apxs /opt/apache/bin/apxs /usr/local/apache/bin/apxs /usr/sbin/apxs2 /usr/local/sbin/apxs2 /usr/bin/apxs2 /usr/local/bin/apxs2 /opt/apache/bin/apxs2 /usr/local/apache/bin/apxs2 ], [], [ AC_MSG_ERROR([could not determine apxs location]) ]) ]) CFLAGS="$CFLAGS `$APXS -q CFLAGS`" INCLUDES="$INCLUDES -I`$APXS -q INCLUDEDIR`" MODULEDIR="`$APXS -q LIBEXECDIR`" AC_SUBST(APXS) AC_SUBST(INCLUDES) AC_SUBST(MODULEDIR) AC_OUTPUT([Makefile src/Makefile])
MOD_MYSQL_CHECK_APXS は、apxs を見つけるための関数です。m4_translit で改行をスペースに変換するということをやっている以外は普通のシェルスクリプトです。
Makefile.am を書く
ビルドに必要な各ディレクトリに Makefile.am を置く必要があります。以下のような感じにしました。
- /Makefile.am:
SUBDIRS=src
- /src/Makefile.am:
lib_LTLIBRARIES=mod_mysql.la mod_mysql_la_LDFLAGS=-module -avoid-version mod_mysql_la_SOURCES= \ mod_mysql.cpp mod_mysql_la_LIBADD=@LIBS@ NOINST=mod_mysql.la INCLUDES=@INCLUDES@ libdir=@MODULEDIR@
autotools の実行
- autoconf は automake と aclocal と autoheader に依存する。
- automake は autoheader と libtoolize に依存する。
- libtoolize は aclocal に依存する。
という状況なので、
aclocal → libtoolize → autoheader → automake → autoconf
の順番で呼び出せば OK でした。
試行錯誤した結果、各ツールのオプションでいくつか重要なものがあることに気づいたのでメモしておきます。
libtoolize:
--automake work silently, and assume that Automake is in use -c, --copy copy files rather than symlinking them
automake:
--include-deps enable dependency tracking code --foreign set strictness to foreign -a, --add-missing add missing standard files to package -c, --copy with -a, copy missing files (default is symlink)
- -c を付け忘れるとファイルが /usr/share 以下の autotools のディレクトリから symlink されてしまい「うっ」ということになります。automake で -a がないとビルドに必要なスクリプトがインストールされませんでした。
- --foreign を付けないと勝手に GPL が記載された COPYING ファイルとかがインストールされてしまいます。
autogen.sh
autotools を使ってビルドシステムを実現しているプロジェクトは大抵 autogen.sh というスクリプトをプロジェクトのルートディレクトリに置いています *1が、これは上記の autotools の呼出を自動的にやってくれるものと暗に期待されています。
この流儀にしたがって autogen.sh を作ることにしました。中身は以下です。
aclocal libtoolize -c --force autoheader automake -c -a --foreign autoconf