1

Fooと呼ばれる新しい言語を設計し、そのためのコンパイラを作成しているとします。その長所は、コンパイラの実装に特に適していることを目的としています。古典的なアプローチは、コンパイラの最初のバージョンをCで記述し、それを使用して2番目のバージョンをFooで記述し、その後、自己コンパイルすることです。

これは、バイナリのバックアップコピーを保持するように注意する必要があることを意味します(ソースのバックアップコピーのみを保持する必要があるほとんどのプログラムとは対照的です)。言語が最初のバージョンから進化した後、バイナリのすべてのコピーを失った場合、現在のバージョンをコンパイルできるものは何もありません。だからそれでいい。

ただし、LinuxとWindowsの両方をサポートすることを目的としているとします。実際に両方のプラットフォームで実行されている限り、各プラットフォームでコンパイルできます。問題はありません。ただし、1つのプラットフォームでバイナリを失った(または攻撃者によって侵害されたと疑う理由があった)とします。今問題があります。また、サポートされているすべてのプラットフォームのバイナリを保護する必要があることは、私が満足しているよりも少なくとも1つ多くの障害点です。

1つの解決策は、どちらかのプラットフォームのバイナリが両方のプラットフォームをターゲットにできるように、クロスコンパイラにすることです。

これは思ったほど簡単ではありません-バイナリ出力形式の選択に問題はありませんが、各プラットフォームはCヘッダーファイルの形式でシステムAPIを提供します。これは通常、ネイティブプラットフォームにのみ存在します。たとえば、保証コードはありません。 Windowsに対してstdio.hコンパイルされたものは、Linuxバイナリ形式にコンパイルされた場合でもLinux上で機能します。

おそらく、この問題は、LinuxヘッダーファイルをWindowsボックスにダウンロードし、Windowsバイナリを使用してLinuxバイナリをクロスコンパイルすることで解決できる可能性があります。

私が見逃しているその解決策に関する警告はありますか?

別の解決策は、FooをポータブルCにコンパイルし、メインのFooコンパイラに必要な言語のサブセットのみを受け入れ、最小のエラーチェックを実行し、最適化を行わない、Pythonで個別の最小ブートストラップコンパイラを維持することです。したがって、後続の言語バージョン間でそれを維持するのにそれほど費用がかからないほど単純なままです。

繰り返しますが、私が見逃しているそのソリューションに関する警告はありますか?

過去にこの問題を解決するために人々はどのような方法を使用しましたか?

4

1 に答える 1

3

これは、Cコンパイラ自体の問題です。それは通常、あなたが提案するように、クロスコンパイラを使用することによって解決されます。

コンパイラーをクロスコンパイルするプロセスは、他のプロジェクトをクロスコンパイルするのと同じくらい難しいことではありません。つまり、あなたが望むよりもトリッキーですが、決して不可能ではありません。

もちろん、最初にクロスコンパイラ自体が必要です。これはおそらく、ビルド構成システムに対するいくつかの大規模な手術を意味し、ターゲットから取得したある種の「sysroot」(ヘッダー、ライブラリ、ビルドで参照する必要があるその他のもの)が必要になります。

したがって、最終的には、コンパイラがどのように構造化されているかによって異なります。履歴ソースを使用して再ブートストラップする方が簡単で、最初に経験した言語互換性の各フェーズを繰り返すか(ソース管理を使用しましたか?)、クロスコンパイラ構成を実装する方が簡単です。ここからどちらかわかりません。

長年にわたり、GCCコンパイラは、まさにこの理由から、常に標準準拠のCコードでのみ記述されていました。つまり、そのシステムのネイティブCコンパイラのみを前提として、どのOSでもGCCコンパイラを起動できるようにしたかったのです。2012年になって初めて、C ++が十分に普及し、コンパイラ自体を記述できるようになったと判断されました。それでも、彼らは自分たちに言語のサブセットしか許可していません。将来、GCCをまだC ++がないプラットフォームに移植したい場合は、クロスコンパイラーを使用するか、最初の移植GCC 4.7(最後のメジャーCのみのバージョン)を使用してから最新のものに移行する必要があります。 。

さらに、GCCビルドプロセスは、ビルドに使用されたコンパイラを「信頼」しません。「make」と入力すると、最初にそれ自体の縮小バージョンがビルドされ、次にそれを使用してフルバージョンがビルドされます。最後に、フルバージョンを使用してのフルバージョンを再構築し、2つのバイナリを比較します。2つが一致しない場合は、元のコンパイラにバグがあり、不正なコードが導入され、ビルドが失敗したことがわかります。

于 2013-02-04T15:25:40.380 に答える