AutotoolsでHello World!

AutotoolsでHelloWorldをやってみたのでメモしておきます。GNU Autotoolsとはautoconf、automake、libtoolといったC/C++プログラムを容易にかつポータブルにビルド可能にするためのツール群の呼び名とのことです。

分かりやすく言うと、自分のプログラムを↓↓↓でビルド&インストールできるようにしてくれるすごい奴らということです。

./configure
make
sudo make install

上記コマンド実行時にはconfigureスクリプトMakefileなどが活躍するわけですが、これらは大抵、プログラマの手作業で作られたファイルではありません。規模の大きなソフトウェアほどこういったファイルを手作業で作るのは無理なので、代わりにもっとプログラマに優しいAutotools用の入力ファイルを作って、そこから自動生成させるのが良いということになります。

hello.cの作成

とりあえずhello.cを作りました。

#include <stdio.h>

int main()
{
  printf("Hello World!\n");
  return 0;
}

しかしこのあと以下のコマンドを叩いてはいけません。

gcc -o hello hello.c
./hello

それではAutotoolsを使う意味がなくなってしまいます。実用上はHelloWorldプログラムにAutotoolsはまったく不要ですが、今回は使うのが前提。

最低限必要な設定ファイル

この2つが最低限必要です。

Makefile.amの作成

まずMakefile.amを作ります。

bin_PROGRAMS = hello

この1行だけです。MySQLなどの大規模なソフトウェアののMakefile.amとかを見ると量も多く複雑で分かりにくいですが、最小限必要なのはコンパイル時に作る実行モジュールの名前だけなのです。

ソースファイルを指定する場合には、以下のように書き足します。複数のソースファイルがある場合には半角スペースで区切って列挙します。

bin_PROGRAMS = hello
hello_SOURCES = hello.c world.c ...

configure.inの作成

続いてconfigure.inを作ります。

AC_INIT()
AM_INIT_AUTOMAKE(hello, 0.1)
AC_PROG_CC
AC_OUTPUT(Makefile)

マクロ説明

  • AC_INITマクロはconfigureスクリプトのための初期化を行います。
  • AM_INIT_AUTOMAKEマクロはAutomakeのための初期化を行うマクロです。引数にパッケージ名とバージョンを最低限指定する必要があります。ここではパッケージ名"hello"、バージョンは0.1としました。
  • AC_PROG_CCマクロはCコンパイラのチェックを行い、シェル変数CCを設定します。
  • AC_OUTPUTマクロはconfigure.inの最後に書くマクロで引数で指定されたファイルが生成されます。

これで準備が整いました。いま作業ディレクトリはこんな感じです。

mir@oss-xeon:~/scratch/hello$ ll
合計 12
-rw-r--r--  1 mir mir 22  8月 22 17:48 Makefile.am
-rw-r--r--  1 mir mir 70  8月 22 17:48 configure.in
-rw-r--r--  1 mir mir 75  8月 22 17:48 hello.c

aclocalとautoconfの実行

まずautoconfを実行しますが、aclocalを先に実行してからautoconfを実行します。

aclocalを実行せずにautoconfを実行すると、、、

mir@oss-xeon:~/scratch/hoge$ autoconf
configure.in:2: error: possibly undefined macro: AM_INIT_AUTOMAKE
      If this token and others are legitimate, please use m4_pattern_allow.
      See the Autoconf documentation.

こんな感じでAM_INIT_AUTOMAKEというマクロが定義されてないよというエラーが出ます。

aclocalは、こういったautoconfの処理に必要なマクロを全て事前に収集してくれるツールです。aclocalを実行すると作業ディレクトリは以下のようになります。

mir@oss-xeon:~/scratch/hello$ aclocal
mir@oss-xeon:~/scratch/hello$ ll
合計 56
-rw-r--r--  1 mir mir    22  8月 22 17:22 Makefile.am
-rw-r--r--  1 mir mir 38499  8月 22 17:51 aclocal.m4
drwxr-xr-x  2 mir mir  4096  8月 22 17:51 autom4te.cache/
-rw-r--r--  1 mir mir    70  8月 22 17:45 configure.in
-rw-r--r--  1 mir mir    75  8月 22 17:03 hello.c

aclocal.m4ファイルとautom4te.cacheディレクトリが生成されます。autoconfの入力ファイルはconfigure.inですが、aclocal.m4も読み込みます。aclocalを実行すると、先ほど未定義エラーになってしまったマクロAM_INIT_AUTOMAKEなどがaclocal.m4の中で定義されている状態になります。

続いてautoconfを実行します。

mir@oss-xeon:~/scratch/hello$ autoconf
mir@oss-xeon:~/scratch/hello$ ll
合計 180
-rw-r--r--  1 mir mir     22  8月 22 17:22 Makefile.am
-rw-r--r--  1 mir mir  38499  8月 22 17:51 aclocal.m4
drwxr-xr-x  2 mir mir   4096  8月 22 17:55 autom4te.cache/
-rwxr-xr-x  1 mir mir 121589  8月 22 17:55 configure*
-rw-r--r--  1 mir mir     70  8月 22 17:45 configure.in
-rw-r--r--  1 mir mir     75  8月 22 17:03 hello.c

おおぉぉぉ! configureスクリプトが生成されました。

automakeを実行

次はautomakeです。先ほどの作業でconfigureはできましたが、まだconfigureを実行できる段階にではありません。configureの実行に必要な、Makefile.inが無いためです。automakeを実行してMakefile.amからMakefile.inを作りましょう。

mir@oss-xeon:~/scratch/hello$ automake
configure.in: required file `./install-sh' not found
configure.in: required file `./missing' not found
Makefile.am: required file `./INSTALL' not found
Makefile.am: required file `./NEWS' not found
Makefile.am: required file `./README' not found
Makefile.am: required file `./AUTHORS' not found
Makefile.am: required file `./ChangeLog' not found
Makefile.am: required file `./COPYING' not found
Makefile.am: required file `./depcomp' not found

エラーが出てしまいました。各種ファイルが無いと怒られています。これらは自前で用意してもいいのですが、面倒なのでオプション指定で逃げましょう。

mir@oss-xeon:~/scratch/hello$ automake -a -c
configure.in: installing `./install-sh'
configure.in: installing `./missing'
Makefile.am: installing `./INSTALL'
Makefile.am: required file `./NEWS' not found
Makefile.am: required file `./README' not found
Makefile.am: required file `./AUTHORS' not found
Makefile.am: required file `./ChangeLog' not found
Makefile.am: installing `./COPYING'
Makefile.am: installing `./depcomp'
mir@oss-xeon:~/scratch/hello$ ls -CF
COPYING  INSTALL  Makefile.am  aclocal.m4  autom4te.cache/  configure*  configure.in  depcomp*  hello.c  install-sh*  missing*

COPYING、INSTALL、depcomp、install-sh、missingが生成されました。これはautomakeが持っているデフォルトファイルをコピーして作成されたものです。COPYINGの中身は、GPL v2でした。

しかしまだMakefile.inは生成されていません。オプションを指定しても尚、いくつかのファイルは自分で用意する必要があるようです。

mir@oss-xeon:~/scratch/hello$ touch NEWS README AUTHORS ChangeLog
mir@oss-xeon:~/scratch/hello$ automake
mir@oss-xeon:~/scratch/hello$ ls -CF
AUTHORS  ChangeLog  Makefile.am  NEWS    aclocal.m4       configure*    depcomp*  install-sh*
COPYING  INSTALL    Makefile.in  README  autom4te.cache/  configure.in  hello.c   missing*

おおぉぉぉ! Makefile.inができています。

ビルドしてみる

ではさっそくやってみましょう。

mir@oss-xeon:~/scratch/hello$ ./configure && make && sudo make install
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables... 
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ANSI C... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
configure: creating ./config.status
config.status: creating Makefile
config.status: executing depfiles commands
if gcc -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE=\"hello\" -DVERSION=\"0.1\"  -I. -I.     -g -O2 -MT hello.o -MD -MP -MF ".deps/hello.Tpo" -c -o hello.o hello.c; \
then mv -f ".deps/hello.Tpo" ".deps/hello.Po"; else rm -f ".deps/hello.Tpo"; exit 1; fi
gcc  -g -O2   -o hello  hello.o  
make[1]: Entering directory `/home/mir/scratch/hello'
test -z "/usr/local/bin" || mkdir -p -- "/usr/local/bin"
  /usr/bin/install -c 'hello' '/usr/local/bin/hello'
make[1]: `install-data-am' に対して行うべき事はありません。
make[1]: Leaving directory `/home/mir/scratch/hello'

無事ビルドできたような気配ですが、、、

mir@oss-xeon:~/scratch/hello$ which hello
/usr/local/bin/hello
mir@oss-xeon:~/scratch/hello$ hello
Hello World!
mir@oss-xeon:~/scratch/hello$ 

おおおぉぉぉぉぉ! "Hello World!"来ましたね! /usr/local/binにインストールされてますね。

ここで、./configure --helpとかやるとおなじみのhelp出力がでてきます。prefixとかを指定すると、ちゃんとそこに入るようです。すごいですね、autotools。

というわけで久々に○○ de HelloWorldさん風に書いてみましたたた。

Autotoolsについて興味を持った方は以下の本が良いかも。というかめっさお世話になってます。

GNU Autoconf/Automake/Libtool

GNU Autoconf/Automake/Libtool