[インデックス 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
に関する一般的な知識として)