./configureとは何か
連載ナビ
この連載は「Linuxを使えるようになる」ではなく、「Linuxがどう動いているのか」を理解するための実践シリーズです。
今回は Linuxを理解する 〜 LFSで学ぶLinux内部構造 〜 の Part 4 / 第1回として、仕組みのつながりを意識しながら学びます。
- 前回: binutilsとは何か
- 次回: makeとは何か
—
./configureは「この環境でビルドできるか」を検査し、Makefileを生成するスクリプト
ソースコードからソフトウェアを入れるときの定番手順 ./configure && make && make install。その先頭に立つ ./configure の正体を先に言ってしまうと、ビルドに入る前に「コンパイラはあるか」「必要なライブラリやヘッダはあるか」「どこにインストールするか」を検査し、その結果を埋め込んだMakefileを生成するシェルスクリプトです。
つまり ./configure 自体は1行もコンパイルしません。仕事は「環境調査」と「ビルド計画書(Makefile)の作成」だけです。LFSでは約90個のパッケージすべてでこのコマンドを打つことになるので、ここで仕組みを押さえておくと後の工程全体の見通しが良くなります。
ソースコードは、どの環境でビルドされるかを知らないから
なぜこんな前工程が必要なのでしょうか。理由は、同じソースコードでも、ビルドされる環境は千差万別だからです。
C言語で書かれたソフトウェアをビルドするには、少なくとも次の情報が環境ごとに違ってきます。
- コンパイラ:
gccなのかclangなのか、そもそも入っているのか - ライブラリ: たとえば圧縮機能を使うソフトなら、
zlibのヘッダ(zlib.h)とライブラリ本体がホストにあるか - OSやCPUの違い: Linuxかそれ以外か、x86_64かARM64か
- インストール先:
/usrに入れるのか/usr/localに入れるのか、ユーザーのホーム以下なのか
開発者がこれらを全部決め打ちにすると、環境が少し違うだけでビルドが壊れます。そこでGNUプロジェクトは Autoconf という仕組みを作りました。開発者は「何をチェックすべきか」を記述し(configure.ac)、Autoconfがそれを巨大なシェルスクリプト configure に変換します。利用者側はシェルさえあれば実行できるので、「ビルド前の環境差異の吸収」がどのUNIX系環境でも動く形で配布できる、というわけです。
実際に動かすと、3つのファイルが生まれる
理屈だけでは掴みにくいので、小さな実物で試します。GNU hello(動作確認用の最小プログラム)を使うと、壊しても困らない環境で一連の流れを体験できます。
curl -LO https://ftp.gnu.org/gnu/hello/hello-2.12.1.tar.gz
tar xf hello-2.12.1.tar.gz
cd hello-2.12.1
./configure --prefix=$HOME/local
実行すると、次のような行が延々と流れます。
checking for gcc... gcc
checking whether the C compiler works... yes
checking for stdio.h... yes
...
config.status: creating Makefile
checking for ... の1行1行が「環境検査」です。gccは動くか、標準ヘッダはあるか、といった項目を実際に小さなテストプログラムをコンパイルしながら確認しています。そして完走すると、ディレクトリに主に3つのファイルができています。
Makefile— 検査結果(コンパイラ名、インストール先など)が埋め込まれたビルド手順書。テンプレートであるMakefile.inの変数部分を、検査結果で置換して生成されますconfig.log— すべての検査の詳細ログ。configureが失敗したとき最初に読むべきファイルですconfig.status— 同じ設定でMakefileを再生成するためのスクリプト
また、ここで指定した --prefix=$HOME/local が「インストール先は $HOME/local 以下」という宣言で、この値がそのままMakefileに書き込まれます。省略時の既定値は /usr/local です。どんなオプションがあるかは ./configure --help | head -n 40 で確認できます。
失敗したら、エラー行ではなくconfig.logを読む
configureはよく失敗します。代表的なのがこれです。
configure: error: C compiler cannot create executables
See `config.log' for more details
このメッセージ自体は「Cコンパイラで実行ファイルが作れなかった」としか言っておらず、原因(gcc未導入なのか、リンカが壊れているのか、フラグ指定ミスなのか)は分かりません。本当の原因は config.log に残っています。
grep -n -B2 -A5 "cannot create executables" config.log
config.logには「configureが実際に実行したコマンド」と「その生のエラー出力」が記録されているので、たとえば gcc: command not found が出ていればコンパイラ未導入、cannot find -lc ならCライブラリの開発ファイル不足、と一次情報から切り分けられます。エラーメッセージを検索する前にconfig.logを開く癖をつけるだけで、原因特定の速度が大きく変わります。
configureは「環境調査とMakefile生成」まで、ビルドはここから
./configure は環境を検査してMakefileを生成する前工程であり、コンパイルは一切しない——これが今回の結論です。失敗したときの一次情報は config.log にあります。
LFSでは、この --prefix や --host / --target(どの環境向けのバイナリを作るかの指定)を毎回意識的に指定することになり、「configureに何を教えるか=どんなシステムを作るか」を自分で決める感覚が身につきます。次回は、生成されたMakefileを受け取って実際にビルドを実行するコマンド、make の仕組みを見ていきます。
図解テキスト
source + configure.ac
-> (開発者がAutoconfで生成) configure スクリプト
-> 利用者が ./configure --prefix=... を実行
├─ 環境検査 (checking for gcc... など)
├─ config.log (検査の詳細ログ)
├─ config.status (再生成用スクリプト)
└─ Makefile.in + 検査結果 -> Makefile 生成
-> make (次回)
この回で実行するコマンド
上から順番に実行すれば、この回の内容を体験できます。
まずはそのままコピペして実行し、次に1行ずつ意味を確認してください。
curl -LO https://ftp.gnu.org/gnu/hello/hello-2.12.1.tar.gz
tar xf hello-2.12.1.tar.gz
cd hello-2.12.1
./configure --help | head -n 40
./configure --prefix=$HOME/local
ls -l Makefile config.log config.status
grep "^CC = " Makefile
ハンズオン手順
1. ターミナルを開いて、上のコマンドを1行ずつ実行する
2. checking for ... の行を3つ選び、何を検査しているか説明してみる
3. grep "^CC = " Makefile の出力で、検査結果がMakefileに埋め込まれていることを確認する
4. エラーが出たら、config.log を開いて該当箇所を探し、メッセージをそのまま残す
チェックポイント
- コマンドが最後まで実行できた
--prefixが何を決めるオプションか説明できる- configureが失敗したとき、最初に見るファイル名を言える
- 次の回に進む前に、分からない単語を1つ調べた
今回理解できたこと
- configureは環境検査とMakefile生成を行う前工程で、コンパイルはしない
- 検査結果は
Makefileに埋め込まれ、詳細ログはconfig.logに残る --prefixでインストール先を宣言する(既定は/usr/local)- 失敗時はエラーメッセージ検索より先にconfig.logを読む