はじめに
オープンソースソフトウェアをビルドするとき、こんなコマンドを実行したことがあるはずです。
./configure
make
make install
make は分かる。でも ./configure は何をしているのか? なぜ必要なのか? 本記事ではその正体を、実際に動くサンプルを使いながら整理します。
本記事はシリーズの第2回です。
- 第1回:Makefileをちゃんと理解する
-
第2回:
./configureの正体——autoconf/automake入門(本記事) - 第3回:CMake入門——Autotoolsとの比較で理解する
./configure の正体はシェルスクリプト
./configure の実体は、プロジェクトに同梱されたシェルスクリプトです。実行すると以下のような出力が流れます。
checking for gcc... gcc
checking whether the C compiler works... yes
checking for suffix of object files... o
checking whether we are cross compiling... no
checking for gawk... no
checking for mawk... mawk
...
config.status: creating Makefile
config.status: creating src/Makefile
「checking for ...」というメッセージが続きますが、これはシステムの環境を調査しています。調査が終わると最後に Makefile を生成して終了します。
つまり ./configure の仕事は、環境を調査して Makefile を生成することです。
なぜ ./configure が必要なのか
Cのプログラムはコンパイラの種類、ライブラリのインストール場所、OSの機能の有無によってビルド方法が変わります。
例えば以下のような違いがあります。
| 環境 | コンパイラ | インストール先 |
|---|---|---|
| Linux(GCC) | gcc |
/usr/local |
| macOS(Xcode) | clang |
/usr/local or /opt/homebrew
|
| クロスコンパイル環境 | arm-linux-gnueabihf-gcc |
任意 |
これらの差異を吸収して、その環境に合った Makefile を自動生成するのが ./configure の役割です。
Autotoolsとは
./configure は手書きするものではありません。Autotoolsと呼ばれるツール群が自動生成します。Autotoolsは主に以下の2つから構成されます。
| ツール | 役割 |
|---|---|
| autoconf |
configure.ac を読んで ./configure スクリプトを生成する |
| automake |
Makefile.am を読んで Makefile.in(テンプレート)を生成する |
そして ./configure を実行すると、Makefile.in を読んでプレースホルダーを環境の値で埋め、Makefile を生成します。
ファイルの全体像
登場するファイルが多いので、整理します。
【開発者が書くファイル】
configure.ac → autoconf → configure (環境調査スクリプト)
Makefile.am → automake → Makefile.in (Makefileのテンプレート)
【ユーザーが実行する】
./configure → Makefile (環境に合わせた完成品)
make → バイナリ
Makefile.in はカスタマイズするもの?
ここで疑問が生じます。「Makefile.in をユーザーに渡すなら、ユーザーが編集してもいいのか?」——答えはノーです。
Makefile.in の中身はこのようになっています。
CC = @CC@
prefix = @prefix@
CFLAGS = @CFLAGS@
@CC@ や @prefix@ は ./configure が値を埋めるプレースホルダーです。./configure は Makefile.in を読んで別ファイル Makefile として書き出すだけであり、Makefile.in 自体は変更しません。
Makefile.in ──(読み込む)──→ ./configure ──(書き出す)──→ Makefile
変更されない 新規生成
ユーザーがビルドをカスタマイズしたい場合は、Makefile.in を触るのではなく ./configure のオプションを使います。
./configure --prefix=/opt/myapp --enable-debug
なぜ configure だけでなく Makefile.in も必要なのか
./configure は「環境を調査する」ことが仕事であり、何をビルドするかの情報は持っていません。ソースファイルの一覧やビルドルールは Makefile.in が持っています。両者がそろって初めて Makefile が生成できます。
この「2ファイル必要問題」は設計上の課題であり、後継のCMakeはこれを CMakeLists.txt 1ファイルに統合することで解決しています(第3回で解説します)。
ツールのインストール
macOS
brew install autoconf automake
インストール後、Homebrew版が優先されているか確認します。
which autoconf automake aclocal
# /opt/homebrew/bin/autoconf ← Apple Silicon
# /usr/local/bin/autoconf ← Intel Mac
システム版(/usr/bin/)が表示される場合はシェルの設定ファイル(.zshrc など)に以下を追加してください。
# Apple Silicon の場合
export PATH="/opt/homebrew/bin:$PATH"
# Intel Mac の場合
export PATH="/usr/local/bin:$PATH"
Ubuntu / Debian
sudo apt install autoconf automake
インストール確認
autoconf --version
automake --version
aclocal --version
サンプルで試す
第1回と同じプロジェクト構成を使い、Autotoolsでビルドできるようにします。
sample/
├── include/
│ └── greet.h
├── src/
│ ├── main.c
│ ├── greet.c
│ └── Makefile.am ← 追加
├── configure.ac ← 追加
└── Makefile.am ← 追加
Cのソースコードは第1回と同じです。追加するのは3つのファイルだけです。
configure.ac
# autoconfの最低バージョンと、プロジェクト名・バージョン・連絡先を宣言
AC_INIT([hello], [1.0.0], [your@email.com])
# automakeと連携することを宣言
AM_INIT_AUTOMAKE([foreign])
# Cコンパイラを探す
AC_PROG_CC
# 出力ファイルを指定(Makefile.in → Makefile を生成するディレクトリ)
AC_CONFIG_FILES([Makefile src/Makefile])
AC_OUTPUT
AC_ で始まるのが autoconf のマクロ、AM_ で始まるのが automake のマクロです。AC_PROG_CC は「Cコンパイラを探して変数 CC に設定する」という意味です。
[foreign] オプションについて
AM_INIT_AUTOMAKE([foreign]) の foreign は、GNU コーディング標準が要求する NEWS、README、AUTHORS などのファイルがなくてもエラーにしない指定です。小規模なプロジェクトやサンプルではよく使います。
Makefile.am(トップレベル)
# サブディレクトリをビルド対象に含める
SUBDIRS = src
src/Makefile.am
# bin_PROGRAMS: インストール先(bin)と生成するバイナリ名
bin_PROGRAMS = hello
# hello_SOURCES: helloバイナリのソースファイル一覧
hello_SOURCES = main.c greet.c
# ヘッダファイルの検索パス
hello_CPPFLAGS = -I$(top_srcdir)/include
bin_PROGRAMS は「bin ディレクトリにインストールするプログラム」という意味の automake の変数です。プログラム名 hello を先頭に付けた hello_SOURCES でソースファイルを指定します。
ビルド手順
ステップ1:開発者側の準備(configure と Makefile.in を生成)
aclocal # マクロライブラリの準備
autoconf # configure.ac → configure
automake --add-missing # Makefile.am → Makefile.in
これで configure と Makefile.in が生成されます。通常これらはソースコードと一緒にリポジトリに含めて配布します。
autoreconf -i という便利コマンド
上記3コマンドは autoreconf -i の1コマンドにまとめられます。実際の開発現場ではこちらがよく使われます。
ステップ2:ユーザー側の作業
mkdir build && cd build # out-of-sourceビルド推奨
../configure # 環境を調査してMakefileを生成
make # ビルド
./src/hello # 実行
実行結果:
checking for gcc... gcc
checking whether the C compiler works... yes
...
config.status: creating Makefile
config.status: creating src/Makefile
$ ./src/hello
Hello, World!
Hello, Qiita!
./configure のオプションでインストール先を変更することもできます。
../configure --prefix=/opt/hello
make
make install # /opt/hello/bin/hello にインストールされる
Makefile編との比較
第1回で手書きした Makefile と今回の Autotools を比べると、何が自動化されているかが分かります。
| 項目 | 手書きMakefile | Autotools |
|---|---|---|
| コンパイラの検出 | 手書き(CC = gcc) |
AC_PROG_CC が自動検出 |
| ヘッダ依存関係の追跡 |
-MMD -MP を自分で書く |
automake が自動で組み込む |
| インストールターゲット | 自分で書く |
make install が自動生成 |
| 配布パッケージ作成 | 自分で書く |
make dist が自動生成 |
| クロスコンパイル対応 | 自分で対応 |
./configure が吸収 |
Autotoolsは手書きMakefileで自分が対処しなければならなかった多くの問題を自動化してくれます。ただし学習コストが高く、ファイル数も増えるため、小規模プロジェクトではオーバースペックになることもあります。
まとめ
| 項目 | ポイント |
|---|---|
./configure の正体 |
シェルスクリプト。環境を調査して Makefile を生成する |
| autoconf の役割 |
configure.ac → configure を生成する |
| automake の役割 |
Makefile.am → Makefile.in を生成する |
Makefile.in の扱い |
テンプレートであり、ユーザーは触らない |
| カスタマイズの方法 |
./configure --prefix=... のオプションで行う |
次回は同じサンプルプロジェクトをCMakeでビルドし、Autotoolsとの設計の違いを比較します。