このメモはGNU Autotoolsのautoconfとautomakeとを使って フリーソフトウェアの配布用パッケージを作る方法を解説している。 FortranのプロジェクトにAutotoolsを使う場合の注意点も書いてある。
たいていのGNUのフリーソフトウェアは次のようにtar ballを展開して、 ./configure && make && make installとすることで簡単にソースからインストールすることができる。
$ tar xf feram-X.YY.ZZ.tar.xz $ cd feram-X.YY.ZZ $ mkdir build # Use build directory. $ cd build $ ../configure --help $ ../configure $ make $ make check $ sudo make install $ make installcheck
AutotoolsはそんなGNU流のフリーソフトウェアパッケージの 構築を半自動化するための開発者用のツールである。最終目的はmake distcheck で foo-1.2.tar.gzなどという[パッケージ名]-[version].tar.gz 形式のパッケージが自動生成できるようになること。
注意: Autotoolsは開発者用のツールである。パッケージfoo-1.2.tar.gzのユーザは そのマシンにAutotoolsをインストールする必要はないし、Autotoolsについて知っている必要もない。
GNUの2つのパッケージautoconfとautomakeとを開発用のマシン にインストールしておく必要がある。また、GNU makeやbashそして GNU M4も最新のものを用意したほうがよい。
たいていのLinuxディストリビューションにはこれらのツールの パッケージがある。たとえばDebianやUbuntuなら
$ sudo apt-get install autoconf automake libtool autoconf-doc libtool-doc
でインストールできる。Mac OS X で Mac Ports https://www.macports.org を使っているなら
$ sudo port install automake autoconf
でインストールできる。
Autotools (autoconf and automake) では Fig. 1 に示すとおり いくつかのコマンドとファイルとによって処理が進む。 前半の茶色の太い破線で囲まれた部分をautoreconfが自動的にやってくれる。 以下に関連すコマンドとファイルを列挙した。
autoscan Autotoolsの利用を開始するときに1回だけ実行するコマンド。 configure.acの雛形configure.scanを生成してくれる。 autoreconf 定番。-vオプションを付けて実行すれば何をしているのかがわかる。 以下のコマンド自動的に再実行してくれる。 autoconf configure.ac を元に configure を生成。 automake Makefile.amからMakefile.inを生成。 オプション --add-missing を付けて実行すると install-sh, missing, test-driver などの必要なスクリプトを /usr/share/automake-1.14/ からシンボリックリンクしてくれる。 autoheader config.h.in を作ってくれる。 aclocal aclocal.m4を作ってくれる。
configure.ac configureの雛型。自分で書く。 Makefile.am Makefileの雛型のMakefile.inの雛型。自分で書く。 config/gnu/ ファイルがごちゃごちゃ出来てイヤな場合はMakefile.amに AC_CONFIG_AUX_DIR(config/gnu)と指定するとmissing等がそこに置かれる。 config.guess Makefile.amにAC_CANONICAL_TARGETなどと書くとautomake --add-missingが 用意してくれるOSやCPUの自動判別をしてくれるスクリプト。 config.h.in config.hの雛型。autoheaderによりMakefile.amやconfigure.acから自動的に作られる。 config.h configure.acにAC_CONFIG_HEADERS([config.h])と指定。 ないとコンパイルオプションが長くややこしくなるので、使ったほうがよい。 config.log configure の実行時のログ。問題が起きたら読む。 config.status configure を実行すると出来るスクリプト。foo.in から foo を作るのは実はこいつ。 install-sh automake --add-missing が用意してくれるスクリプト。make installのときに使われることがある。 missing automake --add-missing が用意してくれるスクリプト。忘れ物を教えてくれる。 depcomp automake --add-missing が用意してくれることのあるスクリプト。ファイルの依存関係を自動的に調べてくれる。 test-driver Makefile.amにTESTSの項目がある場合、automake --add-missing が用意するスクリプト。 make checkのときに使われ、カラフルな表示やログファイルの書き出しをしてくれる。
configure.ac, Makefile.am, src/Makefile.amを書いて、
$ autoreconf -v $ automake --add-missing # 初回にautoreconfで実行を要求されたとき。Cygwinの場合は--copyもつけた方がよい。 $ autoreconf -v # ☆ $ ./configure $ make # ソースの編集など開発を進め、最後にmakeでコンパイルできることを確認 $ make distclean # Makefileなどをきれいさっぱり消す $ ./configure $ make distcheck # 配布用パッケージをテストしてから作成(オプションは DISTCHECK_CONFIGURE_FLAGS で指定できる) $ make dist # 配布用パッケージの作成
新たにconfigure.ac, Makefile.am, src/Makefile.amを書き変えたら☆からやり直す。 実際は☆からやり直さずとも、Makefile に Fig. 1 にある依存関係が書き込まれているので、 make だけで Makefile そのものがうまい具合に更新される。他に
$ make clean # makeでできたファイルを消去 $ make check # コンパイルしたバイナリをテスト(後述) $ sudo make install $ make installcheck # インストールしたバイナリをテスト(後述) $ sudo make uninstall # make installしたファイルの消去
などが便利。
src/Makefile.amに
TESTS=foo.sh bar baz
と書いておけば
$ make check
でsrc/の中でfoo.shとbarとbazとがテストとして実行される。 ソフトウェアのテストを自動化できる。 foo.shとbarとbazとはカレントディレクトリになければsrcdirの中も探されるので、 build directoryの中でもテストができる。 ただし、foo.shは自動的にパッケージに入れてくれるわけではないので、 Makefile.amの中のEXTRA_DISTに次のように加えておく必要がある。
EXTRA_DIST = README foo.sh
テストのログがfoo.sh.logとbar.logとbaz.logとに、 テストの結果がfoo.sh.trsとbar.trsとbaz.trsとに保存される。 テスト全体のまとめがtest-suite.logに保存される。
一部のテストだけを選択的に行いたい場合は
$ make check TESTS='foo.sh bar'
とTESTS変数で指定するする。
テストスクリプトの中でsrcdirを明示的に参照する必要がある場合は$srcdirを用いる。
make distcheck とすると、上記テストとさらにファイルの過不足のチェックして、最終的にパッケージを作ることができる。 make distcheck で作るパッケージは、簡単かつ自動的に in-source build, out-of-source build のどちらも可能になる。
automakeのオプションはconfigure.acの中にAM_INIT_AUTOMAKEで指定する。例えば
AM_INIT_AUTOMAKE([1.14.1 no-dist-gzip dist-xz tar-pax foreign])
では、automakeのバージョン1.14.1以上を使用することを強制し、 パッケージをtar.gzでなくtar.xzで作るように指定している。 また、長いディレクトリ名/ファイル名でもパッケージに入るようなtarのオプションを指定している。 foreignを指定しておけば、NEWS, COPYING, AUTHORS, ChangeLog, READMEのファイルが勝手に作られるのを防ぐことができる。 ライセンスとしてGLPを採用するとしても、ここにforeignを指定して、 パッケージに含めたいファイルはMakefile.amのEXTRA_DISTに明示的にリストアップするのがよいだろう。
Autotools Mythbuster の該当ページ https://autotools.io/automake/options.html が詳しい。
さらにAM_INIT_AUTOMAKEにstd-optionsを加えておけば
$ sudo make install
でバイナリをインストールした後に
$ make installcheck
とすると、そのインストールしたバイナリで GNU的なコマンドラインオプションの--helpと--versionとをテストできる。 エラーが起きればログが残こされ、テストが成功したなら何も残らない。
Makefile.amの中にinstallcheck-local:ルールを書いておけばそれも実行される。
installcheckは一般的なテストではないので、make installcheckとしても何も実行されないパッケージも多い。
C, Fortran, C++コンパイラとそのオプションはそれぞれ AC_PROG_CC(), AC_PROG_FC(), AC_PROG_CXX() が configure.ac の中で決定する。コンパイラは CC, FC, CXX に、 コンパイラオプションは CFLAGS, FCFLAGS, CXXFLAGS に セットされる。 コンパイラオプションのデフォルトはたいてい -g -O2 または -O2 である。configure.ac の中で デフォルト以外に独自に設定したい場合には
cflags_save="$CFLAGS" AC_PROG_CC() CFLAGS="$cflags_save" test -n "$CFLAGS" || CFLAGS="-g -Wall -O3"
などとAC_PROG_*()の前後でsave/restoreし、その後に独自設定をする。
configureにオプションや変数を与える方法は
$ ./configure --help
で表示されるように、
$ ./configure --enable-openmp --with-lapack=mkl CPPFLAGS=-I/home/t-nissie/include
などと
の3つがある。それぞれconfigure.acの中で
と宣言しておく。設定される変数はconfig.hを通してプログラム内で参照できる。
注意:CPPFLAGS変数はC/C++のプロジェクトの場合は自動的に使用されるので宣言の必要はない。 Fortranのプロジェクトの場合は明示的に宣言してはじめてconfigure --helpで説明が表示されるようになる。
configureに与えられた引数はconfig.logの先頭に記録されるので、後々の再確認に便利である。 ただし、''や""のクォーテイションは消えてしまう。
パッケージにUNIXのmanシステムの流儀に則って書いたmanpageを同梱する場合は、Makefile.amに
man_MANS = xtalgrowth.1 crystal_growth.7 EXTRA_DIST = README COPYING $(man_MANS)
などと書く。ここで数字の1や7はmanpageのセクション番号で1〜9の値をとり、 その番号にしたがってmanpageは/usr/local/share/man/man1/などにmake installでインストールされる。 manpageはデフォルトでパッケージに同梱されないのでEXTRA_DISTに加えておく。
マニュアルなどドキュメントを (prefix)/share/doc/(パッケージ名)/ にインストールするには Makefile.am の中の dist_doc_DATA にインストールしたいファイルを指定する。 さらに例えば figures/ サブディレクトリを作ってその中にJPEGファイルなどをインストールしたい場合は次の通り。
docfiguresdir = $(docdir)/figures dist_doc_DATA = index.en.html index.es.html index.ja.html COPYING style.css favicon.ico README.md EXTRA_DIST = index.en.html index.es.html index.ja.html COPYING style.css favicon.ico figures\ CMakeLists.txt ChangeLog.md $(man_MANS) dist_docfigures_DATA = figures/cd.jpg figures/example.jpg figures/large.jpg figures/xtals.jpg
dist_doc_DATAに指定してもREADME.md以外はソースパッケージに自動で同梱されないのでEXTRA_DISTに加えておく。
PREFIX/bin/やPREFIX/share/ではない任意のディレクトリへファイルをインストールしたい場合は https://stackoverflow.com/questions/3538705 とその中のproski氏のアドバイスを参考に configure.ac には
AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir=DIR], [pkgconfig files [LIBDIR/pkgconfig]])], [pkgconfigdir=$withval], [pkgconfigdir='${libdir}/pkgconfig']) AC_SUBST(pkgconfigdir)
Makefile.am には
dist_pkgconfig_DATA = mylibrary.pc
と書く。`--pkgconfigdir`のような新しいconfigureオプションを作るのは難しそう。
テキストファイルの中にconfogureで決定された変数を挿入したいことはしばしばある。 たとえば、foo.1.inに
This is a manpage of foo version @PACAGE_VERSION@.
と書いておき、configure.acの中で
AC_CONFIG_FILES([Makefile src/Makefile foo.1])
とAC_CONFIG_FILESにMakefileに加えてfoo.1を指定しておく。 config.statusがMakefile.in→Makefileと同様にfoo.1.in→foo.1の変換もするようになる。
シンプル。 https://github.com/jca02266/lha
大規模。libtoolも使われている。 http://support.ntp.org/bin/view/Main/WebHome
小規模。Cで書かれたX Window Systemのアプリケーション。 http://loto.sourceforge.net/xtalgrowth/
小規模。Fortranで書かれている。 http://loto.sourceforge.net/feram/
Rubyは独特で高度な方法でconfigureを生成している。安易に真似すべきではないかもしれない。 configure.inとMakefile.inそしていくつかのツールが独自に書かれていて、autoconfのみを使う。 configureでGNU makeでもBSD makeでもnmakeでも有効なポータブルなMakefile(とGNUmakefile)が生成される。 ソースは、src/サブディレクトリではなく、メインディレクトリに置かれている。 make V=1とverbosityを指定することで、makeの実行するコマンドの詳細が表示されるようになっている。 https://github.com/ruby/ruby 。
Autotoolsは強力なツールで、make distcheckがエラーなく成功するようになればほぼすべてがうまく進むようになる。 しかしながら、トラブルに遭遇する場合もある。 Autotoolsやconfigure, makeに関連するバグの発見方法をいくつか紹介する。
大規模なプロジェクトではconfigureとmakeとにかかる時間が増大し、開発者をイライラさせる。 特にconfigureスクリプトは並列化が難しく、簡単には高速化できない。 以下にconfigureとmakeとの高速化の手法とそれらを解説しているページへのリンクを揚げた。
改良版のAutotoolsやより高速なmakeを目指していくつかのパッケージングツール/ビルドシステムが開発されている。
CMake, SCons, Meson, WafではFortranのプロジェクトもサポートされている。
Autotoolsに限らずこれらのビルドシステムを使うことによって ユーザーも他の開発者も何がどこにあってどうしたらよいかを容易に推測しやすくなる。 それぞれのビルドシステムの流儀に従えば、いくつかのプラットフォームに対応したバイナリやライブラリの コンパイル、リンク、テスト、インストール、パッケージングの自動化を簡単かつ忘れ物なく実現できる。 先人の知恵をおろそかにして独自のスクリプトでこれらをやろうとすると とんでもない我流に陥って悲惨な結果を招きがちである。
Autotoolsの仲間には他に libtool http://www.gnu.org/software/libtool/ がある。 共有ライブラリをビルドするときにautoconfとautomakeとともに使ってマシン依存性を解決する。 参考: http://klabgames.tech.blog.jp.klab.com/archives/1047107113.html
なお、Mac OS X の Mac Ports https://www.macports.org で
$ sudo port install libtool
としてインストールされるGNU libtoolはglibtool/glibtoolizeとしてインストールされる。 Xcodeの /usr/bin/libtool (BSD origin) との衝突を避けるためのようである。
autoconfとautomakeとの使い方を説明した。 configure.acとMakefile.amとを書くことによりパッケージの自動生成が可能になる。 複数のプラットフォームでMakefileを共通化できる。 これらGNU Autotoolsを活用すれば、簡単に配布用のフリーソフトウェアパッケージを作ることができる。
西松 毅 (t_nissie{at}yahoo.co.jp)