[インデックス 152] ファイルの概要
このコミットでは、Go言語のツールチェインにおけるビルドシステムが、Plan 9由来のmkからより一般的なmakeへと移行されました。具体的には、以下のファイルが変更されています。
src/cmd/6a/Makefile: 新規作成src/cmd/6c/Makefile: 新規作成src/cmd/6c/cgen.c: 修正src/cmd/6g/Makefile: 新規作成src/cmd/6l/Makefile: 新規作成src/cmd/cc/Makefile: 新規作成src/cmd/clean.bash: 修正src/cmd/gc/Makefile: 新規作成src/cmd/make.bash: 修正
コミット
convert from mk to make phew.
SVN=122266
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/461d1b798770e5de49b9364abc5b12d557027e09
元コミット内容
convert from mk to make
phew.
SVN=122266
変更の背景
このコミットの主な背景は、Go言語の初期開発において、ビルドシステムをPlan 9オペレーティングシステムで広く使われていたmkから、Unix系システムでデファクトスタンダードとなっているmakeへ移行することです。コミットメッセージの「phew.」という一言は、この移行作業がかなりの労力を要したことを示唆しています。
Go言語は、その設計思想や初期の実装においてPlan 9の影響を強く受けていました。mkはPlan 9のビルドツールであり、makeとは異なる哲学と構文を持っています。しかし、Go言語がより広い開発者コミュニティに普及するためには、多くの開発者が慣れ親しんでいるmakeへの移行が不可欠でした。これにより、Goのビルドプロセスがよりアクセスしやすくなり、Plan 9環境に依存しない開発が可能になります。
前提知識の解説
mk (Plan 9 Make)
mkは、Bell LabsのPlan 9オペレーティングシステムで開発されたビルドツールです。従来のUnix makeとはいくつかの点で異なります。
- 構文:
mkはよりシンプルで一貫性のある構文を持ち、シェルスクリプトと密接に統合されています。変数の展開やルールの記述方法がmakeとは異なります。 - 並列実行:
mkはデフォルトで並列実行をサポートしており、依存関係グラフに基づいて効率的にタスクを並行処理します。 - 依存関係の解決:
mkは、ファイル名だけでなく、コマンドの出力や環境変数なども依存関係として考慮できます。 - 哲学:
mkは、ビルドプロセスをより宣言的に記述することを目指しており、makeよりも柔軟性が高いと評価されることもあります。
make (GNU Make)
makeは、Unix系システムで広く使われているビルド自動化ツールです。Makefileというファイルに記述されたルールに基づいて、ソースコードのコンパイルやリンクなどのタスクを実行します。
- 構文:
makeは、ターゲット、依存関係、コマンドの3つの要素からなるルールを記述します。変数の定義や関数の使用も可能です。 - 並列実行:
makeも-jオプションを使用することで並列実行が可能ですが、mkとは実装が異なります。 - 普及度:
makeは非常に広く普及しており、多くのオープンソースプロジェクトや商用ソフトウェアのビルドに利用されています。
Go言語の初期ツールチェインの名称
Go言語の初期のコンパイラやアセンブラは、Plan 9のツールチェインに倣って、ターゲットアーキテクチャとツールの種類を示すプレフィックスを持っていました。
- 6a:
6はx86-64アーキテクチャ(amd64)を指し、aはアセンブラ(assembler)を指します。つまり、x86-64用のアセンブラです。 - 6c:
6はx86-64アーキテクチャを指し、cはCコンパイラを指します。Go言語の初期のコンパイラはC言語で書かれており、この6cがそのコンパイラでした。 - 6g:
6はx86-64アーキテクチャを指し、gはGoコンパイラを指します。Go言語のソースコードをコンパイルするGoコンパイラです。 - 6l:
6はx86-64アーキテクチャを指し、lはリンカ(linker)を指します。コンパイルされたオブジェクトファイルをリンクして実行可能ファイルを生成します。 - gc: Goコンパイラ全般を指す場合もありますが、ここではGo言語のガベージコレクタ(garbage collector)に関連する部分を指す可能性があります。
- cc: Cコンパイラ全般を指します。Go言語のツールチェイン内でC言語のコードをコンパイルするために使用されます。
これらのツールは、Go言語のビルドプロセスにおいて相互に連携し、ソースコードから実行可能ファイルを生成する役割を担っていました。
技術的詳細
このコミットの技術的詳細は、主にmk形式のビルドスクリプトをmake形式に変換することに集約されます。
-
Makefileの新規作成:
src/cmd/6a/Makefile、src/cmd/6c/Makefile、src/cmd/6g/Makefile、src/cmd/6l/Makefile、src/cmd/cc/Makefile、src/cmd/gc/Makefileが新規作成されています。これらのファイルは、それぞれのツール(アセンブラ、Cコンパイラ、Goコンパイラ、リンカなど)のビルド手順をmakeの構文で記述しています。- 各Makefileには、
# Copyright 2009 The Go Authors. All rights reserved.という著作権表示と、BSDスタイルのライセンスに関する記述が追加されています。これは、Goプロジェクトの標準的なヘッダです。 YFLAGS、CFLAGS、BIN、Oといった変数が定義されています。YFLAGS=-d:yaccコマンドに-dオプションを渡すことを意味します。これは、y.tab.hというヘッダファイルを生成するために使用されます。CFLAGS=-I/home/r/plan9/include -I$(GOROOT)/include: Cコンパイラに渡すインクルードパスを指定しています。/home/r/plan9/includeはPlan 9のヘッダファイルへのパス、$(GOROOT)/includeはGoのルートディレクトリ内のヘッダファイルへのパスです。BIN=$(HOME)/bin: 生成されたバイナリをインストールするディレクトリを指定しています。O=o: オブジェクトファイルの拡張子を.oと定義しています。
TARG変数でターゲットとなる実行可能ファイル名(例:6a,6c)が定義されています。HFILES変数でヘッダファイルが、OFILES変数でオブジェクトファイルが、LIB変数でライブラリファイルが定義されています。- ビルドルールが定義されています。例えば、
$(TARG): $(OFILES)は、ターゲットがオブジェクトファイルに依存し、それらをcc(Cコンパイラ)でリンクして実行可能ファイルを生成することを示しています。 cleanターゲットが定義されており、ビルドによって生成された中間ファイルや実行可能ファイルを削除するコマンドが含まれています。installターゲットが定義されており、生成されたバイナリを指定されたBINディレクトリにコピーするコマンドが含まれています。y.tab.c: $(YFILES)のようなルールは、yacc(Yet Another Compiler Compiler)を使用して、.yファイル(Yaccの入力ファイル)からパーサのCソースコード(y.tab.c)とヘッダファイル(y.tab.h)を生成することを示しています。
- 各Makefileには、
-
シェルスクリプトの修正:
src/cmd/clean.bashとsrc/cmd/make.bashが修正されています。- これらのスクリプトは、Goツールチェインの各コンポーネント(
6l,6a,6c,6g,gc,cc)のディレクトリに移動し、それぞれのビルドコマンドを実行する役割を担っています。 - 変更前は
mk cleanやmk installのようにmkコマンドを直接呼び出していましたが、変更後はmake cleanやmake installのようにmakeコマンドを呼び出すように修正されています。これにより、ビルドシステムがmakeに完全に移行したことがわかります。
- これらのスクリプトは、Goツールチェインの各コンポーネント(
-
src/cmd/6c/cgen.cの修正: このファイルでは、log2(c)という関数呼び出しがxlog2(c)に変更されています。これは、ビルドシステムとは直接関係ありませんが、このコミットで同時に行われたコードの修正です。おそらく、log2関数の定義が変更されたか、より適切な名前の関数に置き換えられたことを示唆しています。
全体として、この変更はGo言語のビルドプロセスをPlan 9のmkからUnixのmakeへと標準化し、より多くの開発者がGoをビルドしやすい環境を整えるための重要なステップでした。
コアとなるコードの変更箇所
src/cmd/6a/Makefile (新規作成)
# Copyright 2009 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
YFLAGS=-d
CFLAGS=-I/home/r/plan9/include -I$(GOROOT)/include
BIN=$(HOME)/bin
O=o
TARG=\
6a\
HFILES=\
a.h\
y.tab.h\
../6l/6.out.h\
compat.h\
OFILES=\
y.tab.$O\
lex.$O\
compat.$O\
../6l/enam.$O\
YFILES=\
a.y\
$(TARG): $(OFILES)
cc -o $(TARG) -L/home/r/plan9/lib $(OFILES) -lbio -l9
$(OFILES): $(HFILES)
lex.$O: ../cc/macbody ../cc/lexbody
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
install: $(TARG)
cp $(TARG) $(BIN)/$(TARG)
src/cmd/clean.bash (修正)
--- a/src/cmd/clean.bash
+++ b/src/cmd/clean.bash
@@ -6,6 +6,6 @@
for i in 6l 6a 6c 6g gc cc
do
cd $i
- mk clean
+ make clean
cd ..
done
src/cmd/6c/cgen.c (修正)
--- a/src/cmd/6c/cgen.c
+++ b/src/cmd/6c/cgen.c
@@ -333,7 +333,7 @@ cgen(Node *n, Node *nn)
tc = r->vconst;
if(c < 0)
tc = -c;
- tv = log2(c);
+ tv = xlog2(c);
if(v < 0)
break;
/* fall thru */
@@ -640,7 +640,7 @@ cgen(Node *n, Node *nn)
tc = r->vconst;
if(c < 0)
tc = -c;
- tv = log2(c);
+ tv = xlog2(c);
if(v < 0)
break;
/* fall thru */
コアとなるコードの解説
Makefileの構造と役割
新規作成された各Makefileは、Goツールチェインの個々のコンポーネント(6a, 6c, 6g, 6l, cc, gc)をビルドするための標準的なmakeルールを定義しています。
- 変数定義:
YFLAGS,CFLAGS,BIN,Oは、ビルドプロセス全体で再利用される定数やオプションを定義します。 - ターゲット定義:
TARGは、最終的に生成される実行可能ファイルの名前を指定します。 - ファイルリスト:
HFILES(ヘッダファイル)、OFILES(オブジェクトファイル)、YFILES(Yaccの入力ファイル)、LIB(ライブラリファイル)は、ビルドに必要なソースファイルや中間ファイルをリストアップします。 - ビルドルール:
$(TARG): $(OFILES): 最終的な実行可能ファイルを生成するためのルールです。オブジェクトファイルをCコンパイラ(cc)でリンクし、plan9/libにあるライブラリ(libbio,lib9)とリンクします。$(OFILES): $(HFILES): オブジェクトファイルがヘッダファイルに依存することを示します。ヘッダファイルが変更された場合、関連するオブジェクトファイルが再コンパイルされます。y.tab.c: $(YFILES): Yaccの入力ファイル(.y)からCソースコード(y.tab.c)とヘッダファイル(y.tab.h)を生成するルールです。lex.$O: ../cc/macbody ../cc/lexbody:lexのオブジェクトファイルが特定のファイルに依存することを示します。enam.c: 6.out.h(6l/Makefile):mkenamシェルスクリプトを実行してenam.cを生成するルールです。
- クリーンアップとインストール:
clean: ビルドによって生成された一時ファイルや実行可能ファイルを削除します。install: ビルドされた実行可能ファイルを指定されたインストールディレクトリにコピーします。
これらのMakefileは、Goツールチェインの各部分がどのようにビルドされるかを明確に定義し、makeコマンドを通じて一貫したビルドプロセスを可能にします。
clean.bashとmake.bashの変更
これらのシェルスクリプトは、Goツールチェイン全体のビルドとクリーンアップをオーケストレーションする役割を担っています。
clean.bash: 各コンポーネントディレクトリに移動し、それぞれのMakefileで定義されたcleanターゲットを実行します。mk cleanからmake cleanへの変更は、ビルドシステムがmakeに完全に切り替わったことを示しています。make.bash: 同様に、各コンポーネントディレクトリに移動し、それぞれのMakefileで定義されたinstallターゲットを実行します。mk installからmake installへの変更も、ビルドシステムの移行を反映しています。
これらのスクリプトの変更により、Goツールチェイン全体のビルドとクリーンアップがmakeベースのコマンドで統一的に実行できるようになりました。
src/cmd/6c/cgen.cのlog2からxlog2への変更
この変更は、cgen.cファイル内のlog2(c)という関数呼び出しがxlog2(c)に変更されたものです。cgen.cはGoのCコンパイラ(6c)のコード生成部分に関連するファイルです。
log2: 一般的には2を底とする対数を計算する関数です。xlog2: このコンテキストでは、おそらくlog2関数の名前が変更されたか、あるいは特定の最適化やエラーハンドリングが追加された新しいバージョンの関数を指すと考えられます。Goの初期のコードベースでは、Plan 9の慣習に従って、標準ライブラリ関数に独自のプレフィックス(例:x)を付けていることがありました。この変更は、ビルドシステムの移行とは直接関係ありませんが、このコミットで同時に行われたコードの改善またはリファクタリングの一部である可能性が高いです。
関連リンク
- GNU Make: https://www.gnu.org/software/make/manual/
- Plan 9 mk: https://9p.io/sys/doc/mk/mk.html
- Go言語の初期ツールチェインに関する議論 (Stack Overflow): https://stackoverflow.com/questions/tagged/go-toolchain (一般的な情報源として)
参考にした情報源リンク
- 上記の関連リンク
- Git commit diffの内容
- Go言語の公式ドキュメントおよび初期のソースコード(一般的な知識として)
- Plan 9のドキュメント(
mkに関する一般的な知識として)