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 から抜粋します.
- Autoconf:移植性の高い configure や testsuite スクリプトの作成を支援します
- Automake:GNU Coding Standards で文書化されたすべてのターゲットをサポートする移植性の高い Makefile の作成を支援します
インストールした 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.amamhello/README
Automake マニュアルの内容を改変して,下記の内容を記しています.
これは GNU Automake のデモパッケージです.
amhello/ ディレクトリに対する automake への指示を記述します.
これも Automake マニュアルのままです.
SUBDIRS = src
dist_doc_data = README
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
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/ ディレクトリに対する 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 all:プログラム,ライブラリ,ドキュメントなどをビルドします.(make と同じ)
- make install:インストールが必要なものをインストールし,パッケージのツリーからシステム全体のディレクトリにファイルをコピーします
- make install-strip: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 という実行ファイルが生成します.
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 の説明部分を箇条書きにまとめてみました.
- このファイルは,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++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 は,通常の 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 で表示されます
参考書の検索
- Amazon の「コンピュータ・IT」本カテゴリーでの,「C++」での検索結果です