Automake を使った実行ファイルの作成

このページでは,Automake マニュアルの「2.4 A Small Hello World」の例を参考にし,実行ファイルの配布パッケージの作り方を勉強します.
素材は,端末に「Hello world.」と出力する定番のプログラムです.C++ 言語を使っています.
ここで言う配布パッケージとは,./configure; make; sudo make install" でビルドとインストースでき,GNU 配布物を梱包したアーカイブファイルくらいの意味です.
マニュアルは C 言語用ですが,ここでは C++ 言語に変更しています.

このページは,プログラミング -自作ソフトウェアと環境- ページのプログラミングの練習セクションの「Hello World もの」のひとつです.

インフォメーション

目次(ページ内リンク)


実行ファイルの配布パッケージ amhello の作成:マニュアルに準拠して作成します
配布パッケージのビルドとインストール:動作確認です
autoscan による configure.ac の雛形の作成:マニュアルでは configure.ac をエディタで作成しています.configure.ac の雛形を自動作成します
amhello の configure.ac のノート:configure.ac を最初に勉強したときのノートです
amhello の Makefile.am のノート:Makefile.am を最初に勉強したときのノートです

参考にしたページ


Automake - GNU Project - Free Software Foundation:このサイトに置いてあるマニュアルの「2.4 A Small Hello World」は,C 言語を使った実行ファイルの配布パッケージの作り方
Autotools FAQ
GNU Autoconf - Creating Automatic Configuration Scripts - GNU Project - Free Software Foundation
GNU Libtool - Portable Dynamic Shared Object Management - GNU Project - Free Software Foundation

GNU Autotools について

Autotools FAQ によると,GNU Autotools という名前は、一般的に Autoconf, Automake, Libtool というソフトウェアパッケージを指します.これらのパッケージは開発者が使用するいくつかのプログラムで構成されており,その中には autoreconf,autoconf,autoheader,autoscan(Autoconf パッケージ由来),aclocal と automake(Automake パッケージ由来),および libtoolize (Libtool パッケージ由来)を指し示すものということです.

このページで利用しているツールについて,上の FAQ から抜粋します.

インストールした Debian パッケージ

パッケージ名(バージョン)
g++ (12.2.0)GNU C++ コンパイラ
make (4.3)コンパイルを制御するユーティリティ
automake (1.16.6)GNU標準準拠のMakefile生成ツール
autoconf (2.71)configure スクリプト自動作成プログラム
libtool (2.4.7)汎用ライブラリサポートスクリプト

実行ファイルの配布パッケージ amhello の作成

上で示したマニュアルの例を C++ に改変し,配布パッケージを作成します.

ソースファイルの作成

まず amhello ディレクトリを作成し,そのなかに src ディレクトリを作成しました.
すなわち,~/amhello/src
ディレクトリのなかに,下に示す 5 つのファイルを作成します.
プログラムのソースファイルを src/ サブディレクトリに格納するのは,後でパッケージが進化したときに,man ページ用の man/ ディレクトリやデータファイル用の data/ ディレクトリなどの追加が容易になるからだそうです.

amhello
├── README
├── Makefile.am
├── configure.ac
└─ src
      ├── main.cc
      └── Makefile.am
amhello/README

Automake マニュアルの内容を改変して,下記の内容を記しています.


これは GNU Automake のデモパッケージです.
amhello/Makefile.am

amhello/ ディレクトリに対する automake への指示を記述します.
これも Automake マニュアルのままです.


SUBDIRS = src
dist_doc_data = README
amhello/configure.ac

configure スクリプトを作成するための autoconf への指示が含まれています.
すなわちここでは C++ を使っているので,Automake マニュアルの例の C 用マクロ "AC_PROG_CC" を C++ 用マクロ "AC_PROG_CXX" に変更しています.


#下の 1.0 という数字は,配布パッケージのファイル名に使われる
AC_INIT([amhello], [1.0], [bug-automake@gnu.org])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_PROG_CXX
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([ Makefile src/Makefile ])
AC_OUTPUT
amhello/src/main.cc

Automake マニュアルの例を C++ に改変しています.
作業の過程で config.h というファイルが生成するのですが,Automake マニュアルの例では,config.h で設定された変数 PACKAGE_STRING の値も端末に出力しています.
この場合,#include "config.h" ではなくて #include <config.h> とするのだそうです.


#include <config.h>
#include <iostream>

int main(void) {
 std::cout << "Hello World!" << std::endl;
 std::cout << "This is " PACKAGE_STRING "." << std::endl;
 return 0;
}
amhello/src/Makefile.am

amhello/src/ ディレクトリに対する automake への指示を記述します.
拡張子を変更した以外は Automake マニュアルのままです.


bin_PROGRAMS = hello
hello_SOURCES = main.cc

ビルドシステムのインスタンス化

上記 5 つのファイルができたら,Autotools を使ってビルドシステムを作成します.
ビルドシステムとは,「configure スクリプトと make コマンドが実行できる状態にしたソースファイル」くらいの理解で良さそうです.
autoreconf --install をを実行するだけで「ビルドシステムのインスタンス化」が完了します.

~/amhello$ autoreconf --install
としたら,端末に以下の内容が出力されました.

configure.ac:2: installing './install-sh'
configure.ac:2: installing './missing'
src/Makefile.am: installing './depcomp'

ここで使ったコマンド autoreconf は,autoconf や automake,その他多くのコマンドを正しい順序で呼び出すスクリプトです.
autoconf は configure.ac から configure を作成することを担当し,automake は Makefile.am と configure.ac から Makefile.in を作成することを担当しています.

端末への出力から,新たに,install-sh,missing,および depcomp というファイルが作成されたことが読み取れます.
他に,configure, config.h.in, Makefile.in, および src/Makefile.in という 4 個のファイルが作成されました.
後者の3つのファイルは,configure によってシステムに合わせて作成される config.h,Makefile,src/Makefile のテンプレートです.

autoreconf を実行する必要があるのは,ビルドシステムが存在しない場合の最初,あるいは,Makefile.am や configure.ac などを変更した場合です.

configure の実行

次に,configure を実行します.
configure がシステムを調査した後,システムに合わせた Makefile,src/Makefile,config.h が作成されます.

~/amhello$ ./configure
としたら,以下の内容が端末に出力されました.

checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
(中略)
config.status: creating config.h
config.status: executing depfiles commands

この段階で,マニュアルには「希望するすべてのターゲットを実行する準備が整いました」という意味のことが書いてあります.
ターゲットとは,make に渡す引数のことで,つまり,make コマンドが使えるようになったということです.
ちなみに,今読んでいる 2.4 章に先だつ 2.2.2 章のタイトルは「標準的な Makefile のターゲット」で,以下のターゲットが紹介されています.

マニュアルではビルド,動作確認,配布パッケージの作成と続きます.

make

~/amhello$ make
としたら,ビルドが始まります.下がそのときの出力です.
ビルドに成功したら src ディレクトリに hello という実行ファイルが生成します.

make  all-recursive
make[1]: ディレクトリ '/home/keiji/amhello' に入ります
Making all in src
make[2]: ディレクトリ '/home/keiji/amhello/src' に入ります
g++ -DHAVE_CONFIG_H -I. -I..     -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.cc
mv -f .deps/main.Tpo .deps/main.Po
g++  -g -O2   -o hello main.o  
make[2]: ディレクトリ '/home/keiji/amhello/src' から出ます
make[2]: ディレクトリ '/home/keiji/amhello' に入ります
make[2]: ディレクトリ '/home/keiji/amhello' から出ます
make[1]: ディレクトリ '/home/keiji/amhello' から出ます

ちなみに,ここで
~/amhello$ sudo make install
とすれば,実行ファイルが /usr/local/bin にインストールされます.
配布パッケージの作成を意図しないなら,こちらです.

配布パッケージの作成

~/amhello$ make distcheck
とすれば,配布パッケージの作成が始まります.
出力内容が多いので,最後の 4 行のみ記します.

=============================================
amhello-1.0 archives ready for distribution:
amhello-1.0.tar.gz
=============================================

配布パッケージ amhello-1.0.tar.gz が amhello ディレクトリに作成されていました.
この 1.0 という数字は,configure.ac の AC_INIT([amhello], [1.0], [bug-automake@gnu.org])に記したのでした.

コマンドのまとめ

解説を加えているのでコマンドが散在してしまいました.ここでまとめます.
ソースファイルを正しく作成したら以下のコマンドで配布パッケージが作成できます.

~/amhello$ autoreconf --install
~/amhello$ ./configure
~/amhello$ make
~/amhello$ make distcheck


配布パッケージのビルドとインストール

上で作成した配布パッケージを常法どおり処理してみます.
実行ファイル hello が,/usr/local/bin にインストールされます.
~/amhello$ tar -xzvf amhello-1.0.tar.gz
~/amhello$ cd amhello-1.0
~/amhello$ ./configure
~/amhello$ make
~/amhello$ sudo make install

なお,アンインストールは,
~/amhello$ sudo make uninstall

~/amhello$ hello
と実行すると,端末に以下の内容が出力されました.

Hello World!
This is amhello 1.0.

「This is amhello 1.0.」というのは,config.h に記述した #define PACKAGE_STRING "amhello 1.0" という部分に由来します.


autoscan による configure.ac の雛形の作成

上のセクションでは,configure.ac をエディタで作成しています.
このセクションでは,autoscan を使って,configure.ac の雛形を自動作成してみます.

ソースファイルの作成

上のセクションで作成したソースファイルから configure.ac を除いたソースファイルを作成しました.
ファイルの内容は同じです.

amhello
├── Makefile.am
├── README
└─ src
      ├── main.cc
      └── Makefile.am

autoscan の実行

~/amhello$ autoscan
としたら,autoscan.log と configure.scan というファイルが生成しました.

amhello
├── Makefile.am
├── README
├── autoscan.log
├── configure.scan
└─ src
      ├── main.cc
      └── Makefile.am

configure.scan が configure.ac の雛形です.
ここでは間違えても修正が可能なように,configure.ac という名前でコピーを作成して configure.ac を編集します.

~/amhello$ cp configure.scan configure.ac

configure.ac(== configure.scan)の内容を示します.


#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.71])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([src/main.cc])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_CXX

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile
                 src/Makefile])
AC_OUTPUT

上のセクションで手書きで作成した configure.ac と比較すると,2 か所書き換えれば良さそうです.

AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS]) 行の編集

上のセクションと揃えるなら,
AC_INIT([amhello], [1.0], [bug-automake@gnu.org])
マニュアルには "Exactly package" などと書いてあります.これが何を意味するのかは調べていません.

AM_INIT_AUTOMAKE 行の追加

上のセクションと揃えるなら,
AM_INIT_AUTOMAKE([-Wall -Werror foreign])

編集後の configure.ac は,次のようになります.変更箇所を赤色で示します.


#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.71])
AC_INIT([amhello], [1.0], [bug-automake@gnu.org])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_CONFIG_SRCDIR([src/main.cc])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_CXX

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile
                 src/Makefile])
AC_OUTPUT

後は上と同じ手順で配布パッケージが作成できます.
~/amhello$ autoreconf --install
~/amhello$ ./configure
~/amhello$ make
~/amhello$ make distcheck

補注

チェックすべきライブラリの記述が必要な場合があります.
昔 gtkmm を使っていたのですが,その場合,
PKG_CHECK_MODULES([GTKMM], [gtkmm-3.0])
行を追加していました.
これは,Gtkmm マニュアルのトップベージに記載されていました.


amhello の configure.ac のノート

Autotools によって読み取られる configure.ac の内容を引用します.
configure.ac を再掲します.


AC_INIT([amhello], [1.0], [bug-automake@gnu.org])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_PROG_CXX
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([ Makefile src/Makefile ])
AC_OUTPUT

configure.ac の説明部分を箇条書きにまとめてみました.

補遺

例えば C++11 を利用する場合には,configure.ac に下の行を追加します.


CXXFLAGS='-std=gnu++0x'

Windows 環境で MinGW でビルドしたときにコマンドプロンプトを開かないようにするためには,configure.ac に下の行を追加します.


LDFLAGS=-mwindows
AC_SUBST(LDFLAGS)

amhello の Makefile.am のノート

src/Makefile.am

Makefile.am を基にして automake は Makefile.in を作成します.Makefile.in は,configure によって Makefile に変換されます.
Makefile.am には,hello をビルドしてインストールするための automake の手順が書かれています. 再掲します.


bin_PROGRAMS = hello
hello_SOURCES = main.cc

箇条書きにまとめてみました.

Makefile.am

Autotools によって読み取られる トップレベルの Makefile.am に関する説明をまとめます.

SUBDIRS = src
dist_doc_DATA = README

参考書の検索