[インデックス 17919] ファイルの概要
コミット
commit 8642cbd660cd8f62f77a37227c640b234fcf9c30
Author: Russ Cox <rsc@golang.org>
Date: Sun Dec 8 22:48:11 2013 -0500
cmd/dist: add liblink build information
In addition to adding the library, change the way the anames array is created.
Previously, it was written to src/cmd/6l/enam.c (and similarly for 5l and 8l)
and each of the other tools (6g, 6c, 6a) compiled the 6l/enam.c file in addition
to their own sources.
Now that there is a library shared by all these programs, move the anames
array into that library. To eliminate name conflicts, name the array after
the architecture letter: anames5, anames6, anames8.
First step to linker cleanup (golang.org/s/go13linker).
This CL does not build by itself. It depends on the CLs introducing
liblink and changing commands to use it.
R=iant
CC=golang-dev
https://golang.org/cl/35740044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/8642cbd660cd8f62f77a37227c640b234fcf9c30
元コミット内容
cmd/dist: add liblink build information
このコミットは、liblink
ライブラリのビルド情報を追加し、anames
配列の生成方法を変更します。以前は anames
配列は src/cmd/6l/enam.c
(および 5l
, 8l
も同様) に書き込まれ、他のツール (6g
, 6c
, 6a
) は自身のソースに加えて 6l/enam.c
をコンパイルしていました。
この変更により、anames
配列はこれらのプログラムすべてで共有されるライブラリ (liblink
) に移動されます。名前の衝突を避けるため、配列名はアーキテクチャ文字 (anames5
, anames6
, anames8
) にちなんで命名されます。
これはリンカのクリーンアップ (golang.org/s/go13linker) の第一歩です。
この変更は単独ではビルドできません。liblink
を導入し、コマンドがそれを使用するように変更する他の変更セット (CLs) に依存しています。
変更の背景
このコミットの主な背景は、Goコンパイラおよびリンカツールチェーンの構造を改善し、特にリンカのクリーンアップとモジュール化を進めることにあります。コミットメッセージに明記されているように、「リンカのクリーンアップ (golang.org/s/go13linker) の第一歩」として位置づけられています。
以前のGoツールチェーンでは、anames
と呼ばれるシンボル名の配列が、各アーキテクチャ (5l
, 6l
, 8l
など) のリンカ (5l
, 6l
, 8l
) ごとに enam.c
というファイルに生成され、それぞれのリンカツールだけでなく、コンパイラ (5g
, 6g
, 8g
) やアセンブラ (5a
, 6a
, 8a
) もこのファイルをコンパイルして利用していました。これは、コードの重複、ビルドプロセスの複雑化、そして将来的なリンカの改善を妨げる要因となっていました。
liblink
という共通ライブラリを導入し、anames
配列をこのライブラリに集約することで、以下のメリットが期待されます。
- コードの重複排除とモジュール化:
anames
配列の定義と生成ロジックが一箇所に集約され、各ツールが共通ライブラリをリンクするだけで済むようになります。これにより、コードベースがより整理され、保守性が向上します。 - ビルドプロセスの簡素化: 各ツールが個別に
enam.c
をコンパイルする必要がなくなり、ビルドシステム (cmd/dist
) の設定が簡素化されます。 - リンカの将来的な改善の促進:
liblink
の導入は、Go 1.3 リンカの再設計 (golang.org/s/go13linker) の一環であり、リンカの内部構造をよりクリーンで拡張性の高いものにするための基盤を築きます。これにより、新しいアーキテクチャのサポートや、リンカの機能改善が容易になります。 - 名前衝突の回避: 複数のアーキテクチャで共通の
anames
配列を使用する際に発生しうる名前衝突を避けるため、アーキテクチャごとにanames5
,anames6
,anames8
のように命名規則を変更しています。
このコミットは、liblink
の導入とそれを使用するためのコマンド変更に依存しているため、単独ではビルドできない「中間的な」コミットであることが明記されており、大規模なリファクタリングの一部であることが示唆されています。
前提知識の解説
このコミットを理解するためには、以下のGo言語のビルドシステムとツールチェーンに関する前提知識が必要です。
-
Goツールチェーンの構成要素:
- コンパイラ (e.g.,
6g
,5g
,8g
): Goソースコードをアセンブリコードに変換します。6g
はamd64、5g
はarm、8g
は386アーキテクチャに対応します。 - アセンブラ (e.g.,
6a
,5a
,8a
): アセンブリコードをオブジェクトファイルに変換します。 - リンカ (e.g.,
6l
,5l
,8l
): オブジェクトファイルを結合し、実行可能バイナリを生成します。 cmd/dist
: Goのビルドシステム全体を管理するツールです。Goのソースコードからコンパイラ、リンカ、標準ライブラリなどをビルドする役割を担います。make.bash
(Unix系) やmake.bat
(Windows) スクリプトによって呼び出されます。anames
配列: Goのコンパイラやリンカが内部的に使用する、シンボル名(オペコード、レジスタ名など)の文字列配列です。これらのシンボルは、アセンブリコードの生成やオブジェクトファイルの解析に必要となります。
- コンパイラ (e.g.,
-
Goのクロスコンパイルとアーキテクチャ: Goはクロスコンパイルを強力にサポートしており、異なるCPUアーキテクチャやOS向けにバイナリを生成できます。このコミットで言及されている
5
,6
,8
は、それぞれ以下のCPUアーキテクチャを指します。5
: ARM (e.g.,GOARCH=arm
)6
: AMD64 (e.g.,GOARCH=amd64
)8
: 386 (e.g.,GOARCH=386
) これらのアーキテクチャごとに、対応するコンパイラ、アセンブラ、リンカが存在します(例:6g
,6a
,6l
はamd64用)。
-
enam.c
とanames?.c
:- 変更前は、各リンカ (
5l
,6l
,8l
) のディレクトリ内にenam.c
というファイルが存在し、その中にそのアーキテクチャ用のanames
配列が定義されていました。 - この
enam.c
は、リンカだけでなく、対応するコンパイラやアセンブラもコンパイル時に含んでいました。これは、各ツールが同じシンボル定義を必要とするためです。 - 変更後は、
anames?.c
(例:anames5.c
,anames6.c
,anames8.c
) というファイルに分割され、これらが新しい共通ライブラリliblink
の一部としてビルドされるようになります。
- 変更前は、各リンカ (
-
liblink
ライブラリ: このコミットで導入される新しい概念です。Goのリンカ関連の共通コードやデータ構造をまとめたライブラリとして機能します。これにより、各リンカツールが個別に同じコードを持つのではなく、共通のライブラリをリンクするだけで済むようになります。これは、Go 1.3 リンカの再設計における重要なステップです。 -
dist
ツールとビルドプロセス:cmd/dist
はGoのソースツリーをビルドする際に使用される内部ツールです。build.c
やbuildgc.c
といったファイルは、dist
がどのようにGoのツールチェーンや標準ライブラリをビルドするかを定義しています。static struct { ... } gentab[]
:dist
がビルド時に特定のファイルを生成するためのテーブルです。例えば、opnames.h
やenam.c
(変更前) のようなファイルは、Goのソースコードから自動生成されていました。static struct { ... } buildorder[]
: ビルドの依存関係と順序を定義します。static struct { ... } cleantab[]
: クリーンアップ時に削除されるファイルを定義します。
これらの知識を持つことで、このコミットがGoのビルドシステムとリンカの内部構造にどのような影響を与え、なぜこのような変更が必要とされたのかを深く理解できます。
技術的詳細
このコミットは、Goのビルドシステム (cmd/dist
) とリンカ関連のコードベースにおける重要なリファクタリングの一部です。主な技術的変更点は以下の通りです。
-
liblink
ライブラリの導入:src/cmd/dist/build.c
に、新しいビルドターゲットliblink
が追加されました。- この
liblink
は、u.h
,utf.h
,fmt.h
,libc.h
,bio.h
,ar.h
,link.h
といった共通のヘッダファイルに加え、anames5.c
,anames6.c
,anames8.c
といったアーキテクチャ固有のanames
配列定義ファイルを含みます。 - これにより、リンカ関連の共通コードとデータが
liblink
という単一のライブラリに集約され、各リンカツールがこれをリンクする形になります。
-
anames
配列の生成と利用方法の変更:- 変更前:
anames
配列は、各アーキテクチャのリンカディレクトリ (src/cmd/5l
,src/cmd/6l
,src/cmd/8l
) 内のenam.c
ファイルに生成されていました。そして、コンパイラ (5g
,6g
,8g
)、アセンブラ (5a
,6a
,8a
)、リンカ自身がこのenam.c
をコンパイルして利用していました。 - 変更後:
src/cmd/dist/buildgc.c
内のmkenam
関数がmkanames
にリネームされ、その機能が変更されました。mkanames
は、以前のように単一のenam.c
を生成するのではなく、アーキテクチャごとにanames5.c
,anames6.c
,anames8.c
というファイルを生成するようになりました。- これらの新しい
anames?.c
ファイルは、liblink
ライブラリの一部としてビルドされます。 src/cmd/dist/build.c
から、各コンパイラ (cmd/5c
,cmd/6c
,cmd/8c
,cmd/5g
,cmd/6g
,cmd/8g
) およびリンカ (cmd/5l
,cmd/6l
,cmd/8l
) のビルド定義から、以前のenam.c
への参照が削除されました。代わりに、これらのツールはliblink.a
をリンクするようになります。anames
配列の名前が、anames[]
からanames5[]
,anames6[]
,anames8[]
のようにアーキテクチャ固有の名前に変更されました。これは、liblink
内で複数のアーキテクチャのanames
配列が共存する際に名前衝突を避けるためです。
- 変更前:
-
ビルドシステム (
cmd/dist
) の変更:.hgignore
(Mercurialの無視ファイル、Gitの.gitignore
に相当) にsrc/liblink/anames?.c
が追加され、src/cmd/?l/enam.c
が削除されました。これは、生成されるファイルの位置と命名規則の変更を反映しています。src/cmd/dist/a.h
で、mkenam
関数のプロトタイプがmkanames
に変更されました。src/cmd/dist/build.c
のgentab
配列が更新され、enam.c
の生成エントリが削除され、代わりにanames5.c
,anames6.c
,anames8.c
の生成エントリがmkanames
関数を指すように追加されました。また、enam.c
がもはや生成されないことを示す{"enam.c", nil}
エントリが追加され、クリーンアップ時にこのファイルが削除されるようにしています。buildorder
とcleantab
にliblink
が追加され、ビルドおよびクリーンアッププロセスに新しいライブラリが組み込まれるようになりました。install
関数内のファイル生成ロジックが修正され、gentab[j].gen == nil
の場合にスキップするようになりました。これは、enam.c
のように生成されなくなったが、クリーンアップのためにエントリを残すケースに対応するためです。
これらの変更は、Goのツールチェーンのモジュール性を高め、リンカのコードベースをより管理しやすくするための重要なステップです。特に、共通の liblink
ライブラリに依存することで、将来的なリンカの機能拡張や最適化が容易になります。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更箇所は、主にGoのビルドシステムを定義する src/cmd/dist/build.c
と、anames
配列の生成ロジックを定義する src/cmd/dist/buildgc.c
に集中しています。
-
src/cmd/dist/build.c
:-
liblink
のビルド情報追加:--- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -493,6 +493,18 @@ static struct { "$GOROOT/include/ureg_arm.h", "$GOROOT/include/ureg_x86.h", }}, + {"liblink", { + "$GOROOT/include/u.h", + "$GOROOT/include/utf.h", + "$GOROOT/include/fmt.h", + "$GOROOT/include/libc.h", + "$GOROOT/include/bio.h", + "$GOROOT/include/ar.h", + "$GOROOT/include/link.h", + "anames5.c", + "anames6.c", + "anames8.c", + }}, {"cmd/cc", { "-pgen.c", "-pswt.c",
liblink
という新しいビルドターゲットが追加され、それに含まれるソースファイルとヘッダファイルが定義されています。特にanames5.c
,anames6.c
,anames8.c
が含まれる点が重要です。 -
各ツールからの
enam.c
参照の削除:--- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -508,19 +520,16 @@ static struct { {"cmd/5c", { "../cc/pgen.c", "../cc/pswt.c", - "../5l/enam.c", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libcc.a", }}, {"cmd/6c", { "../cc/pgen.c", "../cc/pswt.c", - "../6l/enam.c", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libcc.a", }}, {"cmd/8c", { "../cc/pgen.c", "../cc/pswt.c", - "../8l/enam.c", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libcc.a", }}, {"cmd/5g", { @@ -529,7 +538,6 @@ static struct { "../gc/plive.c", "../gc/popt.c", "../gc/popt.h", - "../5l/enam.c", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libgc.a", }}, {"cmd/6g", { @@ -538,7 +546,6 @@ static struct { "../gc/plive.c", "../gc/popt.c", "../gc/popt.h", - "../6l/enam.c", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libgc.a", }}, {"cmd/8g", { @@ -547,25 +554,22 @@ static struct { "../gc/plive.c", "../gc/popt.c", "../gc/popt.h", - "../8l/enam.c", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libgc.a", }}, {"cmd/5l", { "../ld/*", - "enam.c", }}, {"cmd/6l", { "../ld/*", - "enam.c", }}, {"cmd/8l", { "../ld/*", - "enam.c", }}, {"cmd/go", { "zdefaultcc.go", }}, {"cmd/", { + "$GOROOT/pkg/obj/$GOOS_$GOARCH/liblink.a", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libmach.a", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libbio.a", "$GOROOT/pkg/obj/$GOOS_$GOARCH/lib9.a",
各コンパイラ (
5c
,6c
,8c
,5g
,6g
,8g
) およびリンカ (5l
,6l
,8l
) のビルド定義から、直接enam.c
を参照する行が削除されています。代わりに、cmd/
の共通ビルド定義に$GOROOT/pkg/obj/$GOOS_$GOARCH/liblink.a
が追加され、liblink
ライブラリをリンクするようになっています。 -
gentab
の更新:--- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -596,7 +600,9 @@ static struct { void (*gen)(char*, char*);\n } gentab[] = {\n \t{"opnames.h", gcopnames},\n-\t{"enam.c", mkenam},\n+\t{"anames5.c", mkanames},\n+\t{"anames6.c", mkanames},\n+\t{"anames8.c", mkanames},\n \t{"zasm_", mkzasm},\n \t{"zdefaultcc.go", mkzdefaultcc},\n \t{"zsys_", mkzsys},\ @@ -605,6 +611,9 @@ static struct { \t{"zruntime_defs_", mkzruntimedefs},\n \t{"zversion.go", mkzversion},\n \t{"zaexperiment.h", mkzexperiment},\ +\n+\t// not generated anymore, but delete the file if we see it\n+\t{"enam.c", nil},\ };\ \ // install installs the library, package, or binary associated with dir,\
gentab
からenam.c
の生成エントリが削除され、代わりにanames5.c
,anames6.c
,anames8.c
をmkanames
関数で生成するエントリが追加されています。また、enam.c
がもはや生成されないが、クリーンアップのためにエントリを残すための{"enam.c", nil}
が追加されています。 -
buildorder
とcleantab
へのliblink
追加:--- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -1247,6 +1258,7 @@ static char *buildorder[] = { "lib9", "libbio", "libmach", + "liblink", "misc/pprof", @@ -1338,6 +1350,7 @@ static char *cleantab[] = { "lib9", "libbio", "libmach", + "liblink", "pkg/bufio", "pkg/bytes", "pkg/container/heap",
ビルド順序とクリーンアップ対象に
liblink
が追加されています。
-
-
src/cmd/dist/buildgc.c
:mkenam
からmkanames
へのリネームと機能変更:
関数名が--- a/src/cmd/dist/buildgc.c +++ b/src/cmd/dist/buildgc.c @@ -63,10 +63,10 @@ gcopnames(char *dir, char *file)\ vfree(&fields);\ }\ \n-// mkenam reads [568].out.h and writes enam.c\ +// mkanames reads [568].out.h and writes anames[568].c\ // The format is much the same as the Go opcodes above.\ void\ -mkenam(char *dir, char *file)\ +mkanames(char *dir, char *file)\ {\ int i, ch;\ Buf in, b, out;\ @@ -78,11 +78,11 @@ mkenam(char *dir, char *file)\ binit(&out);\ vinit(&lines);\ \n-\tch = dir[xstrlen(dir)-2];\ -\tbprintf(&b, "%s/../%cl/%c.out.h", dir, ch, ch);\ +\tch = file[xstrlen(file)-3];\ +\tbprintf(&b, "%s/../cmd/%cl/%c.out.h", dir, ch, ch);\ \treadfile(&in, bstr(&b));\ \tsplitlines(&lines, bstr(&in));\ -\tbwritestr(&out, "char*\tanames[] = {\\n");\ +\tbprintf(&out, "char*\tanames%c[] = {\\n", ch);\ \tfor(i=0; i<lines.len; i++) {\ \t\tif(hasprefix(lines.p[i], "\tA")) {\ \t\t\tp = xstrstr(lines.p[i], ",");\
mkenam
からmkanames
に変更され、生成されるファイル名がenam.c
からanames?.c
に、そして配列名がanames[]
からanames?[]
に変更されています。また、入力ファイルのパスの決定ロジックも変更されています。
これらの変更は、Goのビルドシステムが liblink
という新しい共通ライブラリを認識し、anames
配列の生成と利用方法を、各ツールが個別に enam.c
をコンパイルするのではなく、共通ライブラリをリンクする形に移行させるためのものです。
コアとなるコードの解説
このコミットのコアとなる変更は、Goのビルドプロセスにおける anames
配列の管理方法を根本的に変えるものです。
変更前:
Goのコンパイラ、アセンブラ、リンカは、それぞれが動作するために、オペコードやレジスタ名などのシンボル名を定義した anames
配列を必要としていました。この配列は、各アーキテクチャ(例: amd64
の場合は 6l
)のリンカディレクトリ内に enam.c
というファイルとして生成されていました。そして、関連するすべてのツール(例: 6g
, 6a
, 6l
)が、ビルド時にこの enam.c
を個別にコンパイルして自身のバイナリに含めていました。
この方式の問題点は以下の通りです。
- コードの重複: 同じ
anames
配列の定義が、複数のツールバイナリ内に重複して存在することになります。 - ビルドの複雑性: 各ツールが個別に
enam.c
をコンパイルする必要があり、ビルドシステム (cmd/dist
) の設定が複雑になります。 - 保守性の低下:
anames
配列の定義に変更があった場合、複数の場所で再コンパイルが必要となり、エラーの温床となる可能性がありました。
変更後:
このコミットでは、これらの問題を解決するために liblink
という新しい共通ライブラリを導入し、anames
配列の管理をこのライブラリに集約します。
-
liblink
の導入:src/cmd/dist/build.c
にliblink
という新しいビルドターゲットが定義されました。このライブラリは、リンカ関連の共通ヘッダファイル (u.h
,utf.h
,fmt.h
など) と、新しい形式のanames
配列定義ファイル (anames5.c
,anames6.c
,anames8.c
) を含みます。 -
anames
配列の生成方法の変更:src/cmd/dist/buildgc.c
内のmkenam
関数がmkanames
にリネームされ、その機能が拡張されました。- 以前は
enam.c
という単一のファイルを生成していましたが、変更後はアーキテクチャごとにanames5.c
,anames6.c
,anames8.c
というファイルを生成するようになりました。 - これらのファイル内の
anames
配列の名前も、anames[]
からanames5[]
,anames6[]
,anames8[]
のようにアーキテクチャ固有の名前に変更されました。これは、liblink
内で複数のアーキテクチャのanames
配列が共存する際に名前衝突を避けるためです。
- 以前は
-
各ツールの
liblink
への依存:src/cmd/dist/build.c
から、各コンパイラやリンカのビルド定義におけるenam.c
への直接参照が削除されました。代わりに、これらのツールはビルド時にliblink.a
(コンパイルされたliblink
ライブラリ) をリンクするようになります。これにより、各ツールは共通のanames
配列定義をliblink
経由で利用できるようになります。
効果:
この変更により、anames
配列の定義と生成ロジックが一箇所に集約され、各ツールは共通ライブラリをリンクするだけで済むようになります。これは、コードの重複を排除し、ビルドプロセスを簡素化し、Goのリンカ関連コードのモジュール化と保守性を大幅に向上させるための重要なステップです。コミットメッセージにあるように、「リンカのクリーンアップ」の第一歩であり、Go 1.3 リンカの再設計に向けた基盤を築くものです。
関連リンク
- Go 1.3 リンカの再設計に関する提案: https://golang.org/s/go13linker (このコミットメッセージで言及されているリンク)
- このコミットが依存する可能性のある変更セット (CL): https://golang.org/cl/35740044 (コミットメッセージで言及されているリンク)
参考にした情報源リンク
- Goの公式ドキュメント (特にGo 1.3リリースノートやリンカに関する設計ドキュメント)
- Goのソースコード (特に
src/cmd/dist
およびsrc/cmd
以下の各ツールディレクトリ) - GoのIssueトラッカーやメーリングリストでの関連議論 (特にリンカの再設計に関するもの)
- Mercurial (Hg) の
.hgignore
ファイルに関するドキュメント (変更差分に登場するため) - C言語のビルドシステムとライブラリの概念 (
.c
ファイル、.h
ファイル、.a
ファイルなど)
これらの情報源は、Goのビルドシステム、リンカの内部構造、そしてこのコミットが解決しようとしている問題の背景を深く理解するために役立ちます。# [インデックス 17919] ファイルの概要
コミット
commit 8642cbd660cd8f62f77a37227c640b234fcf9c30
Author: Russ Cox <rsc@golang.org>
Date: Sun Dec 8 22:48:11 2013 -0500
cmd/dist: add liblink build information
In addition to adding the library, change the way the anames array is created.
Previously, it was written to src/cmd/6l/enam.c (and similarly for 5l and 8l)
and each of the other tools (6g, 6c, 6a) compiled the 6l/enam.c file in addition
to their own sources.
Now that there is a library shared by all these programs, move the anames
array into that library. To eliminate name conflicts, name the array after
the architecture letter: anames5, anames6, anames8.
First step to linker cleanup (golang.org/s/go13linker).
This CL does not build by itself. It depends on the CLs introducing
liblink and changing commands to use it.
R=iant
CC=golang-dev
https://golang.org/cl/35740044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/8642cbd660cd8f62f77a37227c640b234fcf9c30
元コミット内容
cmd/dist: add liblink build information
このコミットは、liblink
ライブラリのビルド情報を追加し、anames
配列の生成方法を変更します。以前は anames
配列は src/cmd/6l/enam.c
(および 5l
, 8l
も同様) に書き込まれ、他のツール (6g
, 6c
, 6a
) は自身のソースに加えて 6l/enam.c
をコンパイルしていました。
この変更により、anames
配列はこれらのプログラムすべてで共有されるライブラリ (liblink
) に移動されます。名前の衝突を避けるため、配列名はアーキテクチャ文字 (anames5
, anames6
, anames8
) にちなんで命名されます。
これはリンカのクリーンアップ (golang.org/s/go13linker) の第一歩です。
この変更は単独ではビルドできません。liblink
を導入し、コマンドがそれを使用するように変更する他の変更セット (CLs) に依存しています。
変更の背景
このコミットの主な背景は、Goコンパイラおよびリンカツールチェーンの構造を改善し、特にリンカのクリーンアップとモジュール化を進めることにあります。コミットメッセージに明記されているように、「リンカのクリーンアップ (golang.org/s/go13linker) の第一歩」として位置づけられています。
以前のGoツールチェーンでは、anames
と呼ばれるシンボル名の配列が、各アーキテクチャ (5l
, 6l
, 8l
など) のリンカ (5l
, 6l
, 8l
) ごとに enam.c
というファイルに生成され、それぞれのリンカツールだけでなく、コンパイラ (5g
, 6g
, 8g
) やアセンブラ (5a
, 6a
, 8a
) もこのファイルをコンパイルして利用していました。これは、コードの重複、ビルドプロセスの複雑化、そして将来的なリンカの改善を妨げる要因となっていました。
liblink
という共通ライブラリを導入し、anames
配列をこのライブラリに集約することで、以下のメリットが期待されます。
- コードの重複排除とモジュール化:
anames
配列の定義と生成ロジックが一箇所に集約され、各ツールが共通ライブラリをリンクするだけで済むようになります。これにより、コードベースがより整理され、保守性が向上します。 - ビルドプロセスの簡素化: 各ツールが個別に
enam.c
をコンパイルする必要がなくなり、ビルドシステム (cmd/dist
) の設定が簡素化されます。 - リンカの将来的な改善の促進:
liblink
の導入は、Go 1.3 リンカの再設計 (golang.org/s/go13linker) の一環であり、リンカの内部構造をよりクリーンで拡張性の高いものにするための基盤を築きます。これにより、新しいアーキテクチャのサポートや、リンカの機能改善が容易になります。 - 名前衝突の回避: 複数のアーキテクチャで共通の
anames
配列を使用する際に発生しうる名前衝突を避けるため、アーキテクチャごとにanames5
,anames6
,anames8
のように命名規則を変更しています。
このコミットは、liblink
の導入とそれを使用するためのコマンド変更に依存しているため、単独ではビルドできない「中間的な」コミットであることが明記されており、大規模なリファクタリングの一部であることが示唆されています。
前提知識の解説
このコミットを理解するためには、以下のGo言語のビルドシステムとツールチェーンに関する前提知識が必要です。
-
Goツールチェーンの構成要素:
- コンパイラ (e.g.,
6g
,5g
,8g
): Goソースコードをアセンブリコードに変換します。6g
はamd64、5g
はarm、8g
は386アーキテクチャに対応します。 - アセンブラ (e.g.,
6a
,5a
,8a
): アセンブリコードをオブジェクトファイルに変換します。 - リンカ (e.g.,
6l
,5l
,8l
): オブジェクトファイルを結合し、実行可能バイナリを生成します。 cmd/dist
: Goのビルドシステム全体を管理するツールです。Goのソースコードからコンパイラ、リンカ、標準ライブラリなどをビルドする役割を担います。make.bash
(Unix系) やmake.bat
(Windows) スクリプトによって呼び出されます。anames
配列: Goのコンパイラやリンカが内部的に使用する、シンボル名(オペコード、レジスタ名など)の文字列配列です。これらのシンボルは、アセンブリコードの生成やオブジェクトファイルの解析に必要となります。
- コンパイラ (e.g.,
-
Goのクロスコンパイルとアーキテクチャ: Goはクロスコンパイルを強力にサポートしており、異なるCPUアーキテクチャやOS向けにバイナリを生成できます。このコミットで言及されている
5
,6
,8
は、それぞれ以下のCPUアーキテクチャを指します。5
: ARM (e.g.,GOARCH=arm
)6
: AMD64 (e.g.,GOARCH=amd64
)8
: 386 (e.g.,GOARCH=386
) これらのアーキテクチャごとに、対応するコンパイラ、アセンブラ、リンカが存在します(例:6g
,6a
,6l
はamd64用)。
-
enam.c
とanames?.c
:- 変更前は、各リンカ (
5l
,6l
,8l
) のディレクトリ内にenam.c
というファイルが存在し、その中にそのアーキテクチャ用のanames
配列が定義されていました。 - この
enam.c
は、リンカだけでなく、対応するコンパイラやアセンブラもコンパイル時に含んでいました。これは、各ツールが同じシンボル定義を必要とするためです。 - 変更後は、
anames?.c
(例:anames5.c
,anames6.c
,anames8.c
) というファイルに分割され、これらが新しい共通ライブラリliblink
の一部としてビルドされるようになります。
- 変更前は、各リンカ (
-
liblink
ライブラリ: このコミットで導入される新しい概念です。Goのリンカ関連の共通コードやデータ構造をまとめたライブラリとして機能します。これにより、各リンカツールが個別に同じコードを持つのではなく、共通のライブラリをリンクするだけで済むようになります。これは、Go 1.3 リンカの再設計における重要なステップです。 -
dist
ツールとビルドプロセス:cmd/dist
はGoのソースツリーをビルドする際に使用される内部ツールです。build.c
やbuildgc.c
といったファイルは、dist
がどのようにGoのツールチェーンや標準ライブラリをビルドするかを定義しています。static struct { ... } gentab[]
:dist
がビルド時に特定のファイルを生成するためのテーブルです。例えば、opnames.h
やenam.c
(変更前) のようなファイルは、Goのソースコードから自動生成されていました。static struct { ... } buildorder[]
: ビルドの依存関係と順序を定義します。static struct { ... } cleantab[]
: クリーンアップ時に削除されるファイルを定義します。
これらの知識を持つことで、このコミットがGoのビルドシステムとリンカの内部構造にどのような影響を与え、なぜこのような変更が必要とされたのかを深く理解できます。
技術的詳細
このコミットは、Goのビルドシステム (cmd/dist
) とリンカ関連のコードベースにおける重要なリファクタリングの一部です。主な技術的変更点は以下の通りです。
-
liblink
ライブラリの導入:src/cmd/dist/build.c
に、新しいビルドターゲットliblink
が追加されました。- この
liblink
は、u.h
,utf.h
,fmt.h
,libc.h
,bio.h
,ar.h
,link.h
といった共通のヘッダファイルに加え、anames5.c
,anames6.c
,anames8.c
といったアーキテクチャ固有のanames
配列定義ファイルを含みます。 - これにより、リンカ関連の共通コードとデータが
liblink
という単一のライブラリに集約され、各リンカツールがこれをリンクする形になります。
-
anames
配列の生成と利用方法の変更:- 変更前:
anames
配列は、各アーキテクチャのリンカディレクトリ (src/cmd/5l
,src/cmd/6l
,src/cmd/8l
) 内のenam.c
ファイルに生成されていました。そして、コンパイラ (5g
,6g
,8g
)、アセンブラ (5a
,6a
,8a
)、リンカ自身がこのenam.c
をコンパイルして利用していました。 - 変更後:
src/cmd/dist/buildgc.c
内のmkenam
関数がmkanames
にリネームされ、その機能が変更されました。mkanames
は、以前のように単一のenam.c
を生成するのではなく、アーキテクチャごとにanames5.c
,anames6.c
,anames8.c
というファイルを生成するようになりました。- これらの新しい
anames?.c
ファイルは、liblink
ライブラリの一部としてビルドされます。 src/cmd/dist/build.c
から、各コンパイラ (cmd/5c
,cmd/6c
,cmd/8c
,cmd/5g
,cmd/6g
,cmd/8g
) およびリンカ (cmd/5l
,cmd/6l
,cmd/8l
) のビルド定義から、以前のenam.c
への参照が削除されました。代わりに、これらのツールはliblink.a
をリンクするようになります。anames
配列の名前が、anames[]
からanames5[]
,anames6[]
,anames8[]
のようにアーキテクチャ固有の名前に変更されました。これは、liblink
内で複数のアーキテクチャのanames
配列が共存する際に名前衝突を避けるためです。
- 変更前:
-
ビルドシステム (
cmd/dist
) の変更:.hgignore
(Mercurialの無視ファイル、Gitの.gitignore
に相当) にsrc/liblink/anames?.c
が追加され、src/cmd/?l/enam.c
が削除されました。これは、生成されるファイルの位置と命名規則の変更を反映しています。src/cmd/dist/a.h
で、mkenam
関数のプロトタイプがmkanames
に変更されました。src/cmd/dist/build.c
のgentab
配列が更新され、enam.c
の生成エントリが削除され、代わりにanames5.c
,anames6.c
,anames8.c
の生成エントリがmkanames
関数を指すように追加されました。また、enam.c
がもはや生成されないことを示す{"enam.c", nil}
エントリが追加され、クリーンアップ時にこのファイルが削除されるようにしています。buildorder
とcleantab
にliblink
が追加され、ビルドおよびクリーンアッププロセスに新しいライブラリが組み込まれるようになりました。install
関数内のファイル生成ロジックが修正され、gentab[j].gen == nil
の場合にスキップするようになりました。これは、enam.c
のように生成されなくなったが、クリーンアップのためにエントリを残すケースに対応するためです。
これらの変更は、Goのツールチェーンのモジュール性を高め、リンカのコードベースをより管理しやすくするための重要なステップです。特に、共通の liblink
ライブラリに依存することで、将来的なリンカの機能拡張や最適化が容易になります。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更箇所は、主にGoのビルドシステムを定義する src/cmd/dist/build.c
と、anames
配列の生成ロジックを定義する src/cmd/dist/buildgc.c
に集中しています。
-
src/cmd/dist/build.c
:-
liblink
のビルド情報追加:--- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -493,6 +493,18 @@ static struct { "$GOROOT/include/ureg_arm.h", "$GOROOT/include/ureg_x86.h", }}, + {"liblink", { + "$GOROOT/include/u.h", + "$GOROOT/include/utf.h", + "$GOROOT/include/fmt.h", + "$GOROOT/include/libc.h", + "$GOROOT/include/bio.h", + "$GOROOT/include/ar.h", + "$GOROOT/include/link.h", + "anames5.c", + "anames6.c", + "anames8.c", + }}, {"cmd/cc", { "-pgen.c", "-pswt.c",
liblink
という新しいビルドターゲットが追加され、それに含まれるソースファイルとヘッダファイルが定義されています。特にanames5.c
,anames6.c
,anames8.c
が含まれる点が重要です。 -
各ツールからの
enam.c
参照の削除:--- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -508,19 +520,16 @@ static struct { {"cmd/5c", { "../cc/pgen.c", "../cc/pswt.c", - "../5l/enam.c", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libcc.a", }}, {"cmd/6c", { "../cc/pgen.c", "../cc/pswt.c", - "../6l/enam.c", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libcc.a", }}, {"cmd/8c", { "../cc/pgen.c", "../cc/pswt.c", - "../8l/enam.c", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libcc.a", }}, {"cmd/5g", { @@ -529,7 +538,6 @@ static struct { "../gc/plive.c", "../gc/popt.c", "../gc/popt.h", - "../5l/enam.c", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libgc.a", }}, {"cmd/6g", { @@ -538,7 +546,6 @@ static struct { "../gc/plive.c", "../gc/popt.c", "../gc/popt.h", - "../6l/enam.c", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libgc.a", }}, {"cmd/8g", { @@ -547,25 +554,22 @@ static struct { "../gc/plive.c", "../gc/popt.c", "../gc/popt.h", - "../8l/enam.c", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libgc.a", }}, {"cmd/5l", { "../ld/*", - "enam.c", }}, {"cmd/6l", { "../ld/*", - "enam.c", }}, {"cmd/8l", { "../ld/*", - "enam.c", }}, {"cmd/go", { "zdefaultcc.go", }}, {"cmd/", { + "$GOROOT/pkg/obj/$GOOS_$GOARCH/liblink.a", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libmach.a", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libbio.a", "$GOROOT/pkg/obj/$GOOS_$GOARCH/lib9.a",
各コンパイラ (
5c
,6c
,8c
,5g
,6g
,8g
) およびリンカ (5l
,6l
,8l
) のビルド定義から、直接enam.c
を参照する行が削除されています。代わりに、cmd/
の共通ビルド定義に$GOROOT/pkg/obj/$GOOS_$GOARCH/liblink.a
が追加され、liblink
ライブラリをリンクするようになっています。 -
gentab
の更新:--- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -596,7 +600,9 @@ static struct { void (*gen)(char*, char*);\n } gentab[] = {\n \t{"opnames.h", gcopnames},\n-\t{"enam.c", mkenam},\n+\t{"anames5.c", mkanames},\n+\t{"anames6.c", mkanames},\n+\t{"anames8.c", mkanames},\n \t{"zasm_", mkzasm},\n \t{"zdefaultcc.go", mkzdefaultcc},\n \t{"zsys_", mkzsys},\ @@ -605,6 +611,9 @@ static struct { \t{"zruntime_defs_", mkzruntimedefs},\n \t{"zversion.go", mkzversion},\n \t{"zaexperiment.h", mkzexperiment},\ +\n+\t// not generated anymore, but delete the file if we see it\n+\t{"enam.c", nil},\ };\ \ // install installs the library, package, or binary associated with dir,\
gentab
からenam.c
の生成エントリが削除され、代わりにanames5.c
,anames6.c
,anames8.c
をmkanames
関数で生成するエントリが追加されています。また、enam.c
がもはや生成されないが、クリーンアップのためにエントリを残すための{"enam.c", nil}
が追加されています。 -
buildorder
とcleantab
へのliblink
追加:--- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -1247,6 +1258,7 @@ static char *buildorder[] = { "lib9", "libbio", "libmach", + "liblink", "misc/pprof", @@ -1338,6 +1350,7 @@ static char *cleantab[] = { "lib9", "libbio", "libmach", + "liblink", "pkg/bufio", "pkg/bytes", "pkg/container/heap",
ビルド順序とクリーンアップ対象に
liblink
が追加されています。
-
-
src/cmd/dist/buildgc.c
:mkenam
からmkanames
へのリネームと機能変更:
関数名が--- a/src/cmd/dist/buildgc.c +++ b/src/cmd/dist/buildgc.c @@ -63,10 +63,10 @@ gcopnames(char *dir, char *file)\ vfree(&fields);\ }\ \n-// mkenam reads [568].out.h and writes enam.c\ +// mkanames reads [568].out.h and writes anames[568].c\ // The format is much the same as the Go opcodes above.\ void\ -mkenam(char *dir, char *file)\ +mkanames(char *dir, char *file)\ {\ int i, ch;\ Buf in, b, out;\ @@ -78,11 +78,11 @@ mkenam(char *dir, char *file)\ binit(&out);\ vinit(&lines);\ \n-\tch = dir[xstrlen(dir)-2];\ -\tbprintf(&b, "%s/../%cl/%c.out.h", dir, ch, ch);\ +\tch = file[xstrlen(file)-3];\ +\tbprintf(&b, "%s/../cmd/%cl/%c.out.h", dir, ch, ch);\ \treadfile(&in, bstr(&b));\ \tsplitlines(&lines, bstr(&in));\ -\tbwritestr(&out, "char*\tanames[] = {\\n");\ +\tbprintf(&out, "char*\tanames%c[] = {\\n", ch);\ \tfor(i=0; i<lines.len; i++) {\ \t\tif(hasprefix(lines.p[i], "\tA")) {\ \t\t\tp = xstrstr(lines.p[i], ",");\
mkenam
からmkanames
に変更され、生成されるファイル名がenam.c
からanames?.c
に、そして配列名がanames[]
からanames?[]
に変更されています。また、入力ファイルのパスの決定ロジックも変更されています。
これらの変更は、Goのビルドシステムが liblink
という新しい共通ライブラリを認識し、anames
配列の生成と利用方法を、各ツールが個別に enam.c
をコンパイルするのではなく、共通ライブラリをリンクする形に移行させるためのものです。
コアとなるコードの解説
このコミットのコアとなる変更は、Goのビルドプロセスにおける anames
配列の管理方法を根本的に変えるものです。
変更前:
Goのコンパイラ、アセンブラ、リンカは、それぞれが動作するために、オペコードやレジスタ名などのシンボル名を定義した anames
配列を必要としていました。この配列は、各アーキテクチャ(例: amd64
の場合は 6l
)のリンカディレクトリ内に enam.c
というファイルとして生成されていました。そして、関連するすべてのツール(例: 6g
, 6a
, 6l
)が、ビルド時にこの enam.c
を個別にコンパイルして自身のバイナリに含めていました。
この方式の問題点は以下の通りです。
- コードの重複: 同じ
anames
配列の定義が、複数のツールバイナリ内に重複して存在することになります。 - ビルドの複雑性: 各ツールが個別に
enam.c
をコンパイルする必要があり、ビルドシステム (cmd/dist
) の設定が複雑になります。 - 保守性の低下:
anames
配列の定義に変更があった場合、複数の場所で再コンパイルが必要となり、エラーの温床となる可能性がありました。
変更後:
このコミットでは、これらの問題を解決するために liblink
という新しい共通ライブラリを導入し、anames
配列の管理をこのライブラリに集約します。
-
liblink
の導入:src/cmd/dist/build.c
にliblink
という新しいビルドターゲットが定義されました。このライブラリは、リンカ関連の共通ヘッダファイル (u.h
,utf.h
,fmt.h
など) と、新しい形式のanames
配列定義ファイル (anames5.c
,anames6.c
,anames8.c
) を含みます。 -
anames
配列の生成方法の変更:src/cmd/dist/buildgc.c
内のmkenam
関数がmkanames
にリネームされ、その機能が拡張されました。- 以前は
enam.c
という単一のファイルを生成していましたが、変更後はアーキテクチャごとにanames5.c
,anames6.c
,anames8.c
というファイルを生成するようになりました。 - これらのファイル内の
anames
配列の名前も、anames[]
からanames5[]
,anames6[]
,anames8[]
のようにアーキテクチャ固有の名前に変更されました。これは、liblink
内で複数のアーキテクチャのanames
配列が共存する際に名前衝突を避けるためです。
- 以前は
-
各ツールの
liblink
への依存:src/cmd/dist/build.c
から、各コンパイラやリンカのビルド定義におけるenam.c
への直接参照が削除されました。代わりに、これらのツールはビルド時にliblink.a
(コンパイルされたliblink
ライブラリ) をリンクするようになります。これにより、各ツールは共通のanames
配列定義をliblink
経由で利用できるようになります。
効果:
この変更により、anames
配列の定義と生成ロジックが一箇所に集約され、各ツールは共通ライブラリをリンクするだけで済むようになります。これは、コードの重複を排除し、ビルドプロセスを簡素化し、Goのリンカ関連コードのモジュール化と保守性を大幅に向上させるための重要なステップです。コミットメッセージにあるように、「リンカのクリーンアップ」の第一歩であり、Go 1.3 リンカの再設計に向けた基盤を築くものです。
関連リンク
- Go 1.3 リンカの再設計に関する提案: https://golang.org/s/go13linker (このコミットメッセージで言及されているリンク)
- このコミットが依存する可能性のある変更セット (CL): https://golang.org/cl/35740044 (コミットメッセージで言及されているリンク)
参考にした情報源リンク
- Goの公式ドキュメント (特にGo 1.3リリースノートやリンカに関する設計ドキュメント)
- Goのソースコード (特に
src/cmd/dist
およびsrc/cmd
以下の各ツールディレクトリ) - GoのIssueトラッカーやメーリングリストでの関連議論 (特にリンカの再設計に関するもの)
- Mercurial (Hg) の
.hgignore
ファイルに関するドキュメント (変更差分に登場するため) - C言語のビルドシステムとライブラリの概念 (
.c
ファイル、.h
ファイル、.a
ファイルなど)
これらの情報源は、Goのビルドシステム、リンカの内部構造、そしてこのコミットが解決しようとしている問題の背景を深く理解するために役立ちます。