Automake を使った実行ファイルの作成
このページでは,Automake マニュアルの「2.4 A Small Hello World」の例を参考にし,実行ファイルの配布パッケージの作り方を勉強します.
素材は,端末に「Hello world.」と出力する定番のプログラムです.C++ 言語を使っています.
ここで言う配布パッケージとは,./configure; make; sudo make install" でビルドとインストースでき,GNU 配布物を梱包したアーカイブファイルくらいの意味です.
マニュアルは C 言語用ですが,ここでは C++ 言語に変更しています.
インフォメーション
目次(ページ内リンク)
- 定番の実行ファイル:まず復習.端末に「Hello world.」と出力するプログラムを作成します
- Makefile を書いてみる:これも復習.Makefile をテキストエディタで作成します
- Automake によるビルド:本題.実行ファイルだけでなく,配布パッケージも簡単に作成できます
- 配布パッケージからのビルドとインストール:Automake で作成した配布パッケージの動作確認です
- autoscan による configure.ac の雛形の作成:ビルドに必要な configure.ac の雛形を自動作成します
- configure.ac のノート
- Makefile.am のノート
参考にしたページ
- GNU Automake:種々の形式のマニュアルへのリンクページ.マニュアルの "2.4 A Small Hello World" は,実践的な,C 言語版の実行ファイル配布パッケージの作り方
- Autotools FAQ
- GNU Autoconf - Creating Automatic Configuration Scripts:種々の形式のマニュアルへのリンクページ
- GNU Libtool - Portable Dynamic Shared Object Management:種々の形式のマニュアルへのリンクページ
Debian パッケージ
このページは,Debian GNU/Linux バージョン 13 "trixie" で作成しました.
インストールしている主なパッケージを示します.
| パッケージ名(バージョン) | 注 |
| g++ (14.2.0) | GNU C++ コンパイラ |
| make (4.4.1) | コンパイルを制御するユーティリティ |
| automake (1.17) | GNU標準準拠のMakefile生成ツール |
| autoconf (2.72) | configure スクリプト自動作成プログラム |
GNU Autotools について
このページで利用しているツールについて,まとめておきます.
Autotools FAQ によると,GNU Autotools という名前は、一般的に Autoconf, Automake, Libtool というソフトウェアパッケージを指します.これらのパッケージは開発者が使用するいくつかのプログラムで構成されており,その中には autoreconf,autoconf,autoheader,autoscan(Autoconf パッケージ由来),aclocal と automake(Automake パッケージ由来),および libtoolize (Libtool パッケージ由来)を指し示すものということです.
- Autoconf:移植性の高い configure や testsuite スクリプトの作成を支援します
- Automake:GNU Coding Standards で文書化されたすべてのターゲットをサポートする移植性の高い Makefile の作成を支援します
定番の実行ファイル
まず,復習です.プログラミング入門の定番,端末に 「Hello World.」 と出力する実行ファイル hello を作成します,
コンパイル,リンク,およびインストール用のコマンドを使い分けます.ビルドシステムはこの作業を高度にしたものです.
ソースコード
下は実行ファイル hello のソースファイル main.cc です,
main.cc
#include <iostream>
int main() {
std::cout << "Hello World." << std::endl;
return 0;
}
ビルドとインストール
ここでの作業は単純で,端末にコマンドを 3 行入力するだけです,
ソースファイル main.cc をコンパイルして,オブジェクトファイル main.o を作成します,
$ g++ -c main.cc
オブジェクトファイル main.o をリンクして実行ファイル hello を生成します,
ここでは main.o しかありませんが,一般に,複数のオブジェクトファイルやライブラリとリンクします
$ g++ -o hello main.o
実行ファイル hello を /usr/local/bin/ にインストールします,これはスーパーユーザー権限で.
$ sudo install -s hello /usr/local/bin/
実行
端末に
$ ./hello
と入力したら,
Hello World.
と表示されました,どうやら成功したようです,
Makefile を書いてみる
もう一つ復習です.
上ではビルドとインストールをコマンドでおこないました.実際の開発では,これらの作業を自動化するスクリプト Makefile を作成します.
もちろん Makefile はテキストエディタで作成可能であり,上のセクションで使ったコマンドを Makefile の文法に従って書き記せば,とりあえず動作します,
Automake のようなMakefile 作成ツールはこの作業を高度化したものです.
自作 Makefile の作成
下にコードの例を記します.例では,"#" を使ってコメントを付しました.また,make clean と make install コマンドも追加してあります,
hello : main.o #オブジェクトファイル main.o から実行ファイル hello を作成
(ここは TAB)g++ -o hello main.o
main.o : main.cc #ソースファイル main.cc からオブジェクトファイル main.o を作成
(ここは TAB)g++ -c main.cc
clean: #実行ファイルとオブジェクトファイルの削除
(ここは TAB)rm -f hello main.o
install: #/usr/local/bin にインストール
(ここは TAB)install -s hello /usr/local/bin/
自作 Makefile の動作確認
作成した Makefile を上述の hello.cc と同じディレクトリにおいて,
$ make
とすれば,端末に
g++ -c main.cc g++ -o hello main.o
と出力されて実行ファイル hello が作成されます,
$ sudo make install
とすれば,実行ファイル hello が /usr/local/bin/ にインストールされます,
$ sudo make clean
とすれば,実行ファイルとオブジェクトファイルが削除されます,
ここまでで,実行ファイルの作成,Makefile を使った実行ファイルの作成が可能になりました.
Automake によるビルド
このセクションが本題です.Autotools を使ってビルドシステムを構築します.
元ネタは GNU Automake の "2.4 A Small Hello World" です.これは C 言語版のプログラムの実行ファイル配布パッケージの作り方そ記したドキュメントです.
ここでは,C 言語を C++ 言語に改変し,配布パッケージを作成します.この系はそのままで配布パッケージの作成も可能です.
ソースファイルの作成
まず作業用のディレクトリを作成します.名前は何でも構いません.ここでは,amhello というディレクトリを作成し,そのなかに src というディレクトリを作成しました.
作成したディレクトリのなかに,以下に示すファイルを作成します.
ツリー構造で記します.
プログラムのソースファイルを src/ サブディレクトリに格納するのは,後でパッケージが進化したときに,man ページ用の man/ ディレクトリやデータファイル用の data/ ディレクトリなどの追加が容易になるからだそうです.
amhello
├── README
├── Makefile.am
├── configure.ac
└─ src
├── main.cc
└── Makefile.am
amhello/README
下記の内容を記しています.Automake マニュアルの内容を多少改変したものです.
これは GNU Automake のデモパッケージです.
info パッケージがインストールされていれば,端末に info Automake と打ち込むと,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" に変更しています.
AC_CONFIG_FILES([ Makefile src/Makefile ]) と 1 行にすることもできます.
1 行めの 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
autoreconf コマンドでビルドシステムのインスタンス化
上記 5 つのファイルができたら,Autotools を使ってビルドシステムを作成します.
ビルドシステムとは,「configure スクリプトと make コマンドが実行できる状態にしたソースファイル」くらいの理解で良さそうです.
autoreconf --install をを実行するだけで「ビルドシステムのインスタンス化」が完了します.
なお,autoreconf を実行する必要があるのは,ビルドシステムが存在しない場合の最初,あるいは,Makefile.am や configure.ac などを変更した場合です.
~/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 というファイルが作成されたことが読み取れます.
他にファイルとディレクトリがいくつか作成されました.
そのうち,config.h.in, Makefile.in, および src/Makefile.in は,configure によってシステムに合わせて作成される config.h,Makefile,src/Makefile のテンプレートです.
configure コマンドで Makefile を作成
次に,configure を実行します.
~/amhello$ ./configure
これで,configure がシステムを調査し,システムに合わせた Makefile,src/Makefile,config.h が作成されます.
このようにして作成される Makefile は汎用性がなければならないので,ファイルサイスが大きくなっています.
amhello ディレクトリに作成された Makefile は 839 行,src ディレクトリの Makefile は 580 行ありました.
この段階で,マニュアルには「希望するすべてのターゲットを実行できるようになりました」と書いてあります.
ターゲットとは,make に渡す引数のことで,つまり,make コマンドが使えるようになったということです.
ちなみに,今読んでいる 2.4 章に先だつ 2.2.2 章のタイトルは「標準的な Makefile のターゲット」で,以下のターゲットが紹介されています.
- make all:プログラム,ライブラリ,ドキュメントなどをビルドします.(make と同じ)
- make install:インストールが必要なものをインストールし,パッケージのツリーからシステム全体のディレクトリにファイルをコピーします
- make uninstall:make install の反対で,インストールしたファイルを消去します.(インストールしたのと同じビルドツリーから実行する必要があります.)
- make clean:make all でビルドしたファイルをビルドツリーから消去します
- make distclean:さらに,./configure で作成されたものをすべて消去します
- make check:テスト・スイートがあれば,それを実行します
- make installcheck:インストールされているプログラムやライブラリをチェックします(サポートされている場合)
- make dist:すべてのソースファイルから package-version.tar.gz を再作成します
make コマンドで実行ファイル生成
~/amhello$ make
としたら,ビルドが始まります.
ビルドに成功したら src ディレクトリに hello という実行ファイルが生成します.
試しに実行してみます.端末に,
~/amhello$ src/hello
とすると,端末に以下の内容が出力されました.
Hello World! This is amhello 1.0.
「This is amhello 1.0.」というのは,config.h に記述した #define PACKAGE_STRING "amhello 1.0" という部分に由来します.
ここで,
~/amhello$ sudo make install
とすれば,実行ファイルが /usr/local/bin にインストールされます.
配布パッケージの作成を意図しないなら,これで充分かもしれません.
make コマンドで配布パッケージを作成
~/amhello$ make distcheck
とすれば,配布パッケージの作成が始まります.
成功すれば,配布パッケージ amhello-1.0.tar.gz が amhello ディレクトリに作成されます.
ファイル名は,configure.ac の AC_INIT([amhello], [1.0], [bug-automake@gnu.org]) に由来します.
コマンドのまとめ
解説を加えているのでコマンドが散在してしまいました.ここでまとめます.最初から 3 コマンドは共通です.
ビルドとインストールなら,
~/amhello$ autoreconf --install
~/amhello$ ./configure
~/amhello$ make
~/amhello$ sudo make install
配布パッケージを作成するなら.
~/amhello$ autoreconf --install
~/amhello$ ./configure
~/amhello$ make
~/amhello$ make distcheck
当然,ビルドとインストールをした上で配布パッケージを作成できます.すなわち,
~/amhello$ autoreconf --install
~/amhello$ ./configure
~/amhello$ make
~/amhello$ sudo make install
~/amhello$ make distcheck
配布パッケージからのビルドとインストール
上の作業で,配布パッケージ amhello-1.0.tar.gz が amhello ディレクトリに作成されました.
amhello-1.0.tar.gz をウェブサイトで公開すれば,訪問者がダウンロードして,自分のマシンでビルドして使えるというわけです,
配布パッケージをインストールしてみます.定番の作業です.
~/amhello$ tar -xzvf amhello-1.0.tar.gz
~/amhello$ cd amhello-1.0
~/amhello/amhello-1.0$ ./configure
~/amhello/amhello-1.0$ make
~/amhello/amhello-1.0$ sudo make install
実行ファイル hello が,/usr/local/bin にインストールされます.
~/amhello/amhello-1.0$ hello
と実行すると,端末に以下の内容が出力されました.
Hello World! This is amhello 1.0.
なお,アンインストールは,
~/amhello/amhello-1.0$ sudo make uninstall
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.72])
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.72])
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
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 の説明部分を箇条書きにまとめてみました.
- このファイルは,autoconf(configureの作成)と automake(様々な Makefile.in の作成)の両方で読まれます
- このファイルには一連の M4 マクロが含まれており,シェルコードとして展開され,最終的に configure スクリプトを形成します
- AC_で始まるマクロは,Autoconf マニュアルに記載されている autoconf マクロです
- AM_ で始まるマクロは automake のマクロです
- 最初の2行は,autoconf と automake を初期化します
- AC_INIT は,パラメータとして,パッケージの名前,バージョン番号,パッケージに関するバグ報告のための連絡先を受け取ります
- この連絡先は,例えば,./configure --help の最後に出力されます
- AM_INIT_AUTOMAKE の引数は,automake のオプションのリストです
- -Wall と -Werror は automake にすべての警告をオンにして,エラーとして報告するように指示します.コンパイラの呼び出し方とは全く関係ありません
- foreign オプションは,このパッケージが GNU Standard に従わないことを automake に伝えます(GNU パッケージに含まれる ChangeLog や AUTHORS などがなくても処理してきくれます
- AC_PROG_CXX 行は,configure スクリプトに C++ コンパイラを検索させ,変数 CXX にその名前を定義します
- 変数変数 CXX は,src/Makefile.in から src/Makefile を作成する際に利用されます
- AC_CONFIG_HEADERS([config.h]) の呼び出しにより,configure.ac の他のマクロで定義された '#define' を集めた config.h ファイルが configure スクリプトにより作成されます
- src/main.c はPACKAGE_STRING を使用できるように config.h をインクルードしています
- AC_CONFIG_FILES マクロは,configure が *.in テンプレートから作成すべきファイルのリストを宣言します
- automake はこのリストをスキャンして,処理すべき Makefile.am ファイルを探します
- AC_OUTPUT 行は,AC_CONFIG_HEADERS と AC_CONFIG_FILES で登録されたファイルの作成を担当するスクリプトの部分を実際に生成する終了コマンドです
C++ のバージョン
例えば C++11 を利用する場合には,configure.ac に下の行を追加します.
CXXFLAGS='-std=gnu++0x'
チェックすべきライブラリの記述
昔 gtkmm を使っていたのですが,その場合,
PKG_CHECK_MODULES([GTKMM], [gtkmm-3.0])
行を追加する必要がありました.
これは,Gtkmm マニュアルのトップベージに記載されていました.
Windows 環境で MinGW でビルドしたときにコマンドプロンプトを開かないようにする
configure.ac に下の行を追加します.
LDFLAGS=-mwindows
AC_SUBST(LDFLAGS)
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 は,通常の Makefile と同じ構文です
- 定義されている変数に反応して,ビルドルールや他の変数を生成します
- automake が解釈せずに渡す他の変数やルールの定義が含まれていることもあります
- PROGRAMS で終わる変数は,Makefile がビルドすべきプログラムをリストアップする特別な変数です
- automake では,この _PROGRAMS という接尾辞をプライマリと呼んでいます
- automake は他にも _SCRIPTS, _DATA, _LIBRARIES などのプライマリを認識し,それぞれ異なる種類のファイルに対応しています
- bin_PROGRAMS の 'bin' 部分は automake に,生成されたプログラムを bindir にインストールするように指示します
- _PROGRAMS 変数にリストアップされている各プログラム prog に対して,automake はそのソースファイルをリストアップした prog_SOURCES という変数を探します
- ソースファイルが複数ある場合は,それらはすべて一緒にコンパイル,リンクされます
- hello_SOURCES 宣言の他の作用として,main.cc は make dist で作成される配布パッケージ(tarball)の一部となります
Makefile.am
Autotools によって読み取られる トップレベルの Makefile.am に関する説明をまとめます.
SUBDIRS = src
dist_doc_DATA = README
- SUBDIRS は,カレントディレクトリを処理する前に,make が再帰するべきすべてのディレクトリをリストアップした特別な変数です
- これにより,make がトップレベルから実行されても,src/hello を構築,インストールすることができます
- dist_doc_DATA = README という行は,README を docdir にインストールするための指示です
- _DATA という接頭辞を持つファイルは,make dist でビルドされた tarball には自動的に含まれません
- dist_ という接頭辞を追加することで配布物に含めることができます
- 自動的に配布される他のファイルのリストは automake --help で表示されます