物理シリーズの計算機版 ── 今度は“ソフトの起源”を、一段ずつ降りていく
gcc(や clang)でコンパイルする。ではその gcc は? ── 前の gcc がコンパイルした。ではその前は? この「回り続ける輪」は、いったいどこから始まったのか。
あなたが Linux カーネルをビルドするとき、gcc という C コンパイラを使います。その gcc 自身も C で書かれたプログラムなので、動かすには誰かがコンパイルした gccが必要です。では、その gcc をコンパイルしたのは? ── また gcc。じゃあいちばん最初の gcc は、コンパイラがまだ1つも無い世界で、何が作ったのか。これはニワトリとタマゴの問題です。このシリーズは、この輪を時間の逆向きにたどって、C言語の誕生、初代UNIX、そして“最初の1バイト”まで降りていきます。
「コンパイラをコンパイルする」は、こう書くと目が回ります。
現役のコンパイラは、たいてい自分自身の言語で書かれ、過去の自分がビルドしたものです。これを自己ホスティング(self-hosting)と呼びます。新しい gcc は古い gcc が作り、その古い gcc はもっと古い gcc が作り…と、輪がぐるぐる回り続けている。下の図で、その輪を回してみてください。
自己ホスティングの輪は、それ自身では始められない。「前の自分」が要るのに、最初は「前の自分」が居ないからです。だから輪は必ず、輪の外にある何かによって一度だけ着火される。bootstrap(ブートストラップ)という言葉は、もともと「自分の靴ひもを引っぱって自分を持ち上げる」という物理的に不可能なほら話から来ています。ソフトの世界でも、最初の一回だけは“外の手”が持ち上げた。
時間を巻き戻します。今の Linux は Linux 上でビルドできますが、1991年の最初の Linux は、まだ Linux が無いので Linux 上ではビルドできません。ではどこで? ── 答えは MINIX という別の Unix風OSの上です。当時フィンランドの学生だった Linus Torvalds は、MINIX を積んだ386 PCで開発し、GNUの gcc と bash を MINIX に移植して、その gcc で Linux をコンパイルしました。
v0.01(1991年9月)
単体では起動すらできず、MINIX が無いとコンパイルもテストもできなかった。輪はまだ回っていない ── MINIX という別のOSにおんぶしている状態。
v0.11(1991年12月)
ここで初めて Linux が Linux 自身をコンパイルできた(自己ホスティング達成)。輪が回り始めた瞬間。以後およそ30年以上、その輪はずっと回り続けている。
つまり Linux の輪の“着火”は、MINIX の上の gcc でした。では次の問いは自明です ── その gcc は何が作った? MINIX は何が作った? 輪の外に出ても、また別の「何が作った?」が待っている。この問いを繰り返すのが、このシリーズの背骨です。
clang(LLVM)でもビルドできますが、それは2010年代後半にようやく主流化した後発で、歴史のほぼ全部は gcc の物語です。そして clang 自身も C++ で書かれたプログラムで、やはり別のコンパイラがビルドした自己ホスティングの輪の中にいます。道具が gcc か clang かは、鶏と卵の構造を何も変えません。
「何が作った?」を繰り返すと、下へ下へと階段を降りていきます。この階段こそ、このシリーズの目次そのものです。下の図のスライダーを動かして、時代をさかのぼり、各段で「何が、何を作ったのか」を確かめてください。降り切った底に、鶏と卵の答えがあります。
今の輪(gcc/clang)→ 最初のLinux(1991)はMINIX上のgcc → gccは既存のccで着火 → MINIXはACK → 最初のCコンパイラはBから育てて自己ホスティング → BはBCPLの子 → 最初のUnix(1969)はPDP-7アセンブリ → そのアセンブラは別マシンのクロスアセンブラ+紙テープ → その最初は人間がスイッチで手入力 → 底は配線されたハードウェア。
先回りして、初学者が必ずハマる罠を1つだけ潰しておきます。「Linux は MINIX から来て、MINIX は BSD から来て…」という系譜(血統)の話と、いま見てきた何がコンパイルしたかの話は、別物です。
① コードの血統:実際のソースコードを受け継いだか。
Unix → BSD → NetBSD/FreeBSD… のように遺伝子(コード)が流れる系統樹。
② ツールチェーンのブートストラップ:何が何をコンパイルしたか。
このシリーズが追う、鶏と卵の輪。Linux も MINIX も、実は誰かの血を引いた子ではなく、“Unixらしく振る舞う”白紙からの再実装です(だから①の血統には載らない)。この腑分けは第1回で。
この2つを混ぜると「Linux は MINIX の子だ」といった誤解になります。正しくは、Linux は MINIX という産室(開発環境)を借りて育っただけで、血のつながりは無い。この気持ちよい種明かしは、次回いちばん最初にやります。
このシリーズの合言葉「最初の卵は、手で彫った」は、詩的な比喩に聞こえますが、底の段ではほぼ文字通りの事実です(第9回)。初期の計算機では、人間が命令表を見て機械語の数値を手で作り、トグルスイッチで1語ずつメモリに入れました。一方で「Linux は MINIX の上の gcc がコンパイルした」のような各段の主張は、年号・人物まで出典の取れる史実です。この2種類 ── 検証できる史実と、理解のための言い回し ── を、各話の脚注できちんと分けて示します。
また、v0.01 と v0.11 の線引き(どこから「自己ホスティング」と呼ぶか)や、「gcc か clang か」のように、雑に言うと角が立つ点は、その都度ていねいに区別します。
Linux をコンパイルする gcc は、前の gcc が作った ── コンパイラは自分自身の言語で書かれ、過去の自分がビルドする自己ホスティングの輪の中にいる。だが輪は自力では始まらない。最初は「前の自分」が居ないからだ。Linux の輪は、1991年に MINIX 上の gcc によって着火され(v0.01)、v0.11 で自立した。
「何が作った?」を繰り返すと、gcc → 既存cc → C → B → BCPL → アセンブリ → クロスアセンブラ → 手入力 → ハードウェア、と階段を降りていく。底にあるのは、輪の外から一度だけ持ち上げた人間の手と、配線された機械。それがこのシリーズの答えの形だ ── 最初の卵は、手で彫った。 なお「何がコンパイルしたか(ブートストラップ)」と「誰の遺伝子か(血統)」は別問題で、混ぜないこと。次回はまずその腑分けから。
印刷 / PDF 化:⌘+P(Windows は Ctrl+P)。画面では図1の「▶ 輪を回す」で自己ホスティングを回し、図2のスライダーで時代をさかのぼれます。「答えを見る」で解答が開きます。