[インデックス 153] ファイルの概要
このコミットは、Go言語の初期開発段階におけるビルドシステム、特にコンパイラツールチェーンに関連するMakefileの変更を扱っています。具体的には、src/cmd/6c/Makefile
、src/cmd/6g/Makefile
、src/cmd/cc/Makefile
、src/cmd/gc/Makefile
の4つのMakefileが修正されています。これらのファイルは、それぞれamd64
アーキテクチャ向けのCコンパイラ(6c)、Goコンパイラ(6g)、汎用Cコンパイラ(cc)、およびGoコンパイラ(gc)のビルドプロセスを定義しています。
コミット
commit 2694a85a52f9515ee330fd3e78294183caf9835c
Author: Rob Pike <r@golang.org>
Date: Wed Jun 11 18:01:45 2008 -0700
tweaks in clean rules and dependencies
SVN=122274
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/2694a85a52f9515ee330fd3e78294183caf9835c
元コミット内容
tweaks in clean rules and dependencies
SVN=122274
変更の背景
このコミットは、Go言語の初期のビルドシステムにおける依存関係とクリーンアップルールの微調整を目的としています。Go言語は、その開発初期において、Rob Pikeを含むPlan 9の設計思想を強く受け継いでいました。ビルドシステムも例外ではなく、Unix系のmake
ユーティリティとPlan 9由来のツールチェイン(例: 6c
, 6g
など、数字はターゲットアーキテクチャを示す)が用いられていました。
変更の背景には、以下の2つの主要な課題があったと推測されます。
- ビルド依存関係の不備:
6c
と6g
のMakefileにおいて、最終的な実行可能ファイル($(TARG)
)をビルドする際に、必要なライブラリ($(LIB)
)が明示的な依存関係として指定されていませんでした。これにより、ライブラリがまだビルドされていない状態で実行可能ファイルのリンクが試みられ、ビルドエラーや不整合が発生する可能性がありました。 - クリーンアップ動作の調整:
cc
とgc
のMakefileのclean
ルールにおいて、最終的な実行可能ファイル($(TARG)
)も削除対象に含まれていました。開発プロセスやCI/CDの文脈において、make clean
コマンドが実行された際に、コンパイラやリンカといった主要なツール自体が削除されてしまうのは不便であるか、意図しない動作である場合があります。例えば、ビルド後にテストを実行する際に、clean
が先に走るとテストに必要な実行ファイルが消えてしまう、といったシナリオが考えられます。この変更は、clean
コマンドのスコープを中間生成物や一時ファイルに限定し、主要なバイナリは残すように調整することを意図しています。
これらの変更は、ビルドプロセスの堅牢性と開発者の利便性を向上させるための、典型的なビルドシステムメンテナンスの一環と考えられます。
前提知識の解説
Makefileとmake
ユーティリティ
Makefile
は、プログラムのコンパイルやその他のタスクを自動化するためのルールを記述するファイルです。make
ユーティリティは、このMakefile
を読み込み、記述されたルールに従ってコマンドを実行します。
- ターゲット (Target): ビルドしたいファイルや実行したいアクションの名前(例:
all
,clean
,program
)。 - 依存関係 (Prerequisites): ターゲットをビルドするために必要となるファイルや他のターゲット。依存関係が更新されている場合、またはターゲットが存在しない場合に、ルールが実行されます。
- コマンド (Commands): ターゲットをビルドするために実行されるシェルコマンド。
例: target: dependencies
\tcommands
(コマンド行はタブで始まる必要があります)
変数
Makefileでは変数が使われます。
$(VAR)
: 変数VAR
の値を参照します。$(TARG)
: このコンテキストでは、最終的に生成される実行可能ファイルの名前を指します。$(OFILES)
: オブジェクトファイル(.o
など)のリストを指します。$(LIB)
: リンクされるライブラリファイル(.a
など)のリストを指します。
clean
ルール
多くのMakefileには、ビルドプロセスで生成された中間ファイルや最終的なバイナリを削除するための慣習的なclean
ターゲットが含まれています。これにより、クリーンな状態から再ビルドを開始したり、ディスクスペースを解放したりできます。
Go言語の初期ツールチェインとPlan 9の影響
Go言語は、その初期段階でPlan 9オペレーティングシステムの設計哲学とツールチェインから大きな影響を受けました。
6c
,6g
: Goの初期のコンパイラは、特定のアーキテクチャ(例:6
はamd64
、8
はarm
、5
は386
など)ごとに命名されていました。6c
はamd64
向けのCコンパイラ、6g
はamd64
向けのGoコンパイラを指します。gc
: "Go Compiler"の略で、Go言語の主要なコンパイラを指します。初期のgc
はC言語で書かれていました。cc
: 汎用的なCコンパイラを指します。$O
: Plan 9の慣習で、オブジェクトファイルの拡張子(例:.o
)を表す変数です。
これらのツールは、Go言語のソースコードをコンパイルし、実行可能なバイナリを生成するために連携して動作します。
技術的詳細
このコミットで行われた変更は、Makefileの依存関係とclean
ルールの2つの側面に関わっています。
1. 依存関係の追加 (src/cmd/6c/Makefile
, src/cmd/6g/Makefile
)
変更前:
$(TARG): $(OFILES)
cc -o $(TARG) -L/home/r/plan9/lib $(OFILES) $(LIB) -lbio -l9
変更後:
$(TARG): $(OFILES) $(LIB)
cc -o $(TARG) -L/home/r/plan9/lib $(OFILES) $(LIB) -lbio -l9
この変更は、$(TARG)
ターゲットの依存関係リストに$(LIB)
を追加しています。
- 変更の意図: 最終的な実行可能ファイル
$(TARG)
をリンクする際に、その実行ファイルが依存するライブラリ$(LIB)
が事前にビルドされていることを保証するためです。make
は、ターゲットをビルドする前にその依存関係がすべて最新であることを確認します。もし$(LIB)
が依存関係として明示されていなければ、$(LIB)
がまだ存在しないか、古い状態であっても$(TARG)
のビルドが開始され、リンク時にライブラリが見つからない、または古いライブラリがリンクされるといった問題が発生する可能性がありました。この修正により、ビルドの順序が正しく保証され、より堅牢なビルドプロセスが実現されます。
2. clean
ルールからの$(TARG)
の削除 (src/cmd/cc/Makefile
, src/cmd/gc/Makefile
)
変更前:
clean:
rm -f $(OFILES) $(TARG) *.6 enam.c 6.out a.out y.tab.h y.tab.c $(LIB)
変更後:
clean:
rm -f $(OFILES) *.6 enam.c 6.out a.out y.tab.h y.tab.c $(LIB)
この変更は、clean
ターゲットのコマンドから$(TARG)
(最終的な実行可能ファイル)の削除を削除しています。
- 変更の意図:
make clean
を実行した際に、コンパイラやリンカといった主要なツール自体が削除されないようにするためです。これにより、開発者は中間ファイルや一時ファイルのみをクリーンアップし、ビルドされたツールはそのまま残しておくことができます。これは、例えば、ビルド後にすぐにツールを実行してテストする場合や、ツールを頻繁に再ビルドせずに利用したい場合に便利です。install
ターゲットが存在する場合、通常はinstall
が最終的なバイナリを適切な場所に配置し、clean
はビルドディレクトリ内の一時ファイルを対象とすることが多いため、この変更はより標準的なMakefileの慣習に沿ったものと言えます。
コアとなるコードの変更箇所
src/cmd/6c/Makefile
および src/cmd/6g/Makefile
--- a/src/cmd/6c/Makefile
+++ b/src/cmd/6c/Makefile
@@ -31,7 +31,7 @@ OFILES=\
LIB=\
../cc/cc.a$O
-$(TARG): $(OFILES)
+$(TARG): $(OFILES) $(LIB)
cc -o $(TARG) -L/home/r/plan9/lib $(OFILES) $(LIB) -lbio -l9
$(OFILES): $(HFILES)
src/cmd/cc/Makefile
および src/cmd/gc/Makefile
--- a/src/cmd/cc/Makefile
+++ b/src/cmd/cc/Makefile
@@ -45,6 +45,6 @@ y.tab.c: $(YFILES)
yacc $(YFLAGS) $(YFILES)
clean:
- rm -f $(OFILES) $(TARG) *.6 enam.c 6.out a.out y.tab.h y.tab.c $(LIB)
+ rm -f $(OFILES) *.6 enam.c 6.out a.out y.tab.h y.tab.c $(LIB)
install: $(LIB)
コアとなるコードの解説
$(TARG)
依存関係の追加
src/cmd/6c/Makefile
とsrc/cmd/6g/Makefile
における変更は、$(TARG)
ターゲットのビルドルールに$(LIB)
を依存関係として追加しています。
- 変更前:
$(TARG): $(OFILES)
- これは、
$(TARG)
をビルドするために$(OFILES)
(オブジェクトファイル)が最新であればよい、とmake
に伝えています。しかし、リンク時に必要となる$(LIB)
がまだビルドされていない場合、リンクコマンドは失敗します。
- これは、
- 変更後:
$(TARG): $(OFILES) $(LIB)
- これにより、
make
は$(TARG)
をビルドする前に、$(OFILES)
と$(LIB)
の両方が最新であることを確認します。もし$(LIB)
が古いか存在しない場合、make
はまず$(LIB)
をビルドするためのルールを探して実行します。これにより、リンク時に必要なライブラリが確実に利用可能になり、ビルドの信頼性が向上します。
- これにより、
clean
ルールからの$(TARG)
削除
src/cmd/cc/Makefile
とsrc/cmd/gc/Makefile
における変更は、clean
ターゲットのコマンドから$(TARG)
を削除しています。
- 変更前:
rm -f $(OFILES) $(TARG) ...
clean
コマンドが実行されると、オブジェクトファイルや一時ファイルに加えて、最終的な実行可能ファイルである$(TARG)
も削除されます。
- 変更後:
rm -f $(OFILES) ...
clean
コマンドが実行されても、$(TARG)
は削除されなくなります。これにより、コンパイラやリンカといった主要なツールがmake clean
によって誤って削除されることを防ぎ、開発者がビルド後にこれらのツールをすぐに利用できるようになります。これは、ビルドシステムにおける「クリーンアップ」の範囲を、中間生成物や一時ファイルに限定するという一般的なプラクティスに沿ったものです。
関連リンク
- Go言語の歴史: https://go.dev/doc/history
- Plan 9 from Bell Labs: https://9p.io/plan9/
- GNU Make マニュアル: https://www.gnu.org/software/make/manual/
参考にした情報源リンク
- Go言語の公式ドキュメント
- GNU Makeのドキュメント
- Plan 9のシステム設計に関する一般的な知識
- ソフトウェアビルドシステムに関する一般的な知識