C言語などのコンパイラはどのようにしてコンパイルされたのですか？


C言語などのプログラミングにはGCCなどのコンパイラが必要ですよね。ですが、そもそもの話、コンパイラというプログラムを作るためにコンパイラが必要になるわけで、ここにパラドックスが生じてしまいます。

コンパイラをコンパイルするためのコンパイラはどのようにして開発されたのですか？
すべての源となるコンパイラはアセンブリ言語やマシン語で開発されたのでしょうか？




## GCCについて

GCC登場以前からCコンパイラーは存在していました。そのため、GCCは既存のCコンパイラーを使ってコンパイルされることを前提に設計されています。例えばビルド方法も

  1. stage1: 既存のCコンパイラーでGCCをビルドする  
既存のCコンパイラーがコード生成したGCC

  2. stage2: stage1のGCCでGCCをビルドする  
既存のCコンパイラーがコード生成したGCCがコード生成したGCC

  3. stage3: stage2のGCCでGCCをビルドする  
完全にGCCのみでコード生成したGCC

と３回ビルドを行い、最終的にstage3のGCCが使われます。

## クロスコンパイル

そうはいっても既存のCコンパイラーが存在しない環境ではどう作るのかというと、クロスコンパイルという技術があります。別のプラットフォームのCコンパイラーでビルドを行いコード生成します。

  * ホスト： コンパイラーが動作する環境
  * ターゲット： 実行ファイルを作成したい環境

と呼び、ホスト上でターゲット向け実行ファイルを生成できるクロスコンパイラーを用意します。

## 最初の１つ

C言語は[UNIX](https://ja.wikipedia.org/wiki/UNIX)を記述するために設計されました。

> 当初はアセンブリ言語のみで開発されたが、1973年にほぼ全体をC言語で書き直した。

とも説明されています。UNIXでは小さなツールを組み合わせて構築されますがCコンパイラーも例外ではなく`cc`は次のツールを呼び出すことで成り立っています。

  * `cpp`; Cプリプロセッサー。`.c`ソースファイルから`#include`、`#define`などのプリプロセッサディレクティブを処理し`.i`ファイルを生成する。
  * `cc1`; 狭義のCコンパイラー。`.i`ファイルをコンパイルし、`.s`アセンブリソースを生成する。
  * `as`; アセンブラー。`.s`ファイルから`.o`オブジェクトファイルを生成する。
  * `ar`; アーカイバー。複数の`.o`ファイルをまとめて`.a`ライブラリファイルを生成する。
  * `ld`; リンカー。複数の`.o`ファイルと`.a`ファイルをまとめて実行ファイルを生成する。

UNIX OS全てをC言語で書き直すプロジェクトにおいて、Cコンパイラーもその一部でしかなく、一緒に書き直されたのかな、と想像しています。

## C++

C++コンパイラーも大きなものですが、C++コンパイラーの元祖[Cfront](https://ja.wikipedia.org/wiki/Cfront)はC++ソースからCソースへ変換するツールだったりします。




## GCCについて

GCC登場以前からCコンパイラーは存在していました。そのため、GCCは既存のCコンパイラーを使ってコンパイルされることを前提に設計されています。例えばビルド方法も

  1. stage1: 既存のCコンパイラーでGCCをビルドする  
既存のCコンパイラーがコード生成したGCC

  2. stage2: stage1のGCCでGCCをビルドする  
既存のCコンパイラーがコード生成したGCCがコード生成したGCC

  3. stage3: stage2のGCCでGCCをビルドする  
完全にGCCのみでコード生成したGCC

と３回ビルドを行い、最終的にstage3のGCCが使われます。

## クロスコンパイル

そうはいっても既存のCコンパイラーが存在しない環境ではどう作るのかというと、クロスコンパイルという技術があります。別のプラットフォームのCコンパイラーでビルドを行いコード生成します。

  * ホスト： コンパイラーが動作する環境
  * ターゲット： 実行ファイルを作成したい環境

と呼び、ホスト上でターゲット向け実行ファイルを生成できるクロスコンパイラーを用意します。

## 最初の１つ

C言語は[UNIX](https://ja.wikipedia.org/wiki/UNIX)を記述するために設計されました。

> 当初はアセンブリ言語のみで開発されたが、1973年にほぼ全体をC言語で書き直した。

とも説明されています。UNIXでは小さなツールを組み合わせて構築されますがCコンパイラーも例外ではなく`cc`は次のツールを呼び出すことで成り立っています。

  * `cpp`; Cプリプロセッサー。`.c`ソースファイルから`#include`、`#define`などのプリプロセッサディレクティブを処理し`.i`ファイルを生成する。
  * `cc1`; 狭義のCコンパイラー。`.i`ファイルをコンパイルし、`.s`アセンブリソースを生成する。
  * `as`; アセンブラー。`.s`ファイルから`.o`オブジェクトファイルを生成する。
  * `ar`; アーカイバー。複数の`.o`ファイルをまとめて`.a`ライブラリファイルを生成する。
  * `ld`; リンカー。複数の`.o`ファイルと`.a`ファイルをまとめて実行ファイルを生成する。

UNIX OS全てをC言語で書き直すプロジェクトにおいて、Cコンパイラーもその一部でしかなく、一緒に書き直されたのかな、と想像しています。

## C++

C++コンパイラーも大きなものですが、C++コンパイラーの元祖[Cfront](https://ja.wikipedia.org/wiki/Cfront)はC++ソースからCソースへ変換するツールだったりします。

