Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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 配列をこのライブラリに集約することで、以下のメリットが期待されます。

  1. コードの重複排除とモジュール化: anames 配列の定義と生成ロジックが一箇所に集約され、各ツールが共通ライブラリをリンクするだけで済むようになります。これにより、コードベースがより整理され、保守性が向上します。
  2. ビルドプロセスの簡素化: 各ツールが個別に enam.c をコンパイルする必要がなくなり、ビルドシステム (cmd/dist) の設定が簡素化されます。
  3. リンカの将来的な改善の促進: liblink の導入は、Go 1.3 リンカの再設計 (golang.org/s/go13linker) の一環であり、リンカの内部構造をよりクリーンで拡張性の高いものにするための基盤を築きます。これにより、新しいアーキテクチャのサポートや、リンカの機能改善が容易になります。
  4. 名前衝突の回避: 複数のアーキテクチャで共通の anames 配列を使用する際に発生しうる名前衝突を避けるため、アーキテクチャごとに anames5, anames6, anames8 のように命名規則を変更しています。

このコミットは、liblink の導入とそれを使用するためのコマンド変更に依存しているため、単独ではビルドできない「中間的な」コミットであることが明記されており、大規模なリファクタリングの一部であることが示唆されています。

前提知識の解説

このコミットを理解するためには、以下のGo言語のビルドシステムとツールチェーンに関する前提知識が必要です。

  1. 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のコンパイラやリンカが内部的に使用する、シンボル名(オペコード、レジスタ名など)の文字列配列です。これらのシンボルは、アセンブリコードの生成やオブジェクトファイルの解析に必要となります。
  2. 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用)。
  3. enam.canames?.c:

    • 変更前は、各リンカ (5l, 6l, 8l) のディレクトリ内に enam.c というファイルが存在し、その中にそのアーキテクチャ用の anames 配列が定義されていました。
    • この enam.c は、リンカだけでなく、対応するコンパイラやアセンブラもコンパイル時に含んでいました。これは、各ツールが同じシンボル定義を必要とするためです。
    • 変更後は、anames?.c (例: anames5.c, anames6.c, anames8.c) というファイルに分割され、これらが新しい共通ライブラリ liblink の一部としてビルドされるようになります。
  4. liblink ライブラリ: このコミットで導入される新しい概念です。Goのリンカ関連の共通コードやデータ構造をまとめたライブラリとして機能します。これにより、各リンカツールが個別に同じコードを持つのではなく、共通のライブラリをリンクするだけで済むようになります。これは、Go 1.3 リンカの再設計における重要なステップです。

  5. dist ツールとビルドプロセス: cmd/dist はGoのソースツリーをビルドする際に使用される内部ツールです。build.cbuildgc.c といったファイルは、dist がどのようにGoのツールチェーンや標準ライブラリをビルドするかを定義しています。

    • static struct { ... } gentab[]: dist がビルド時に特定のファイルを生成するためのテーブルです。例えば、opnames.henam.c (変更前) のようなファイルは、Goのソースコードから自動生成されていました。
    • static struct { ... } buildorder[]: ビルドの依存関係と順序を定義します。
    • static struct { ... } cleantab[]: クリーンアップ時に削除されるファイルを定義します。

これらの知識を持つことで、このコミットがGoのビルドシステムとリンカの内部構造にどのような影響を与え、なぜこのような変更が必要とされたのかを深く理解できます。

技術的詳細

このコミットは、Goのビルドシステム (cmd/dist) とリンカ関連のコードベースにおける重要なリファクタリングの一部です。主な技術的変更点は以下の通りです。

  1. 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 という単一のライブラリに集約され、各リンカツールがこれをリンクする形になります。
  2. 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 配列が共存する際に名前衝突を避けるためです。
  3. ビルドシステム (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.cgentab 配列が更新され、enam.c の生成エントリが削除され、代わりに anames5.c, anames6.c, anames8.c の生成エントリが mkanames 関数を指すように追加されました。また、enam.c がもはや生成されないことを示す {"enam.c", nil} エントリが追加され、クリーンアップ時にこのファイルが削除されるようにしています。
    • buildordercleantabliblink が追加され、ビルドおよびクリーンアッププロセスに新しいライブラリが組み込まれるようになりました。
    • install 関数内のファイル生成ロジックが修正され、gentab[j].gen == nil の場合にスキップするようになりました。これは、enam.c のように生成されなくなったが、クリーンアップのためにエントリを残すケースに対応するためです。

これらの変更は、Goのツールチェーンのモジュール性を高め、リンカのコードベースをより管理しやすくするための重要なステップです。特に、共通の liblink ライブラリに依存することで、将来的なリンカの機能拡張や最適化が容易になります。

コアとなるコードの変更箇所

このコミットにおけるコアとなるコードの変更箇所は、主にGoのビルドシステムを定義する src/cmd/dist/build.c と、anames 配列の生成ロジックを定義する src/cmd/dist/buildgc.c に集中しています。

  1. 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.cmkanames 関数で生成するエントリが追加されています。また、enam.c がもはや生成されないが、クリーンアップのためにエントリを残すための {"enam.c", nil} が追加されています。

    • buildordercleantab への 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 が追加されています。

  2. 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 配列の管理をこのライブラリに集約します。

  1. liblink の導入: src/cmd/dist/build.cliblink という新しいビルドターゲットが定義されました。このライブラリは、リンカ関連の共通ヘッダファイル (u.h, utf.h, fmt.h など) と、新しい形式の anames 配列定義ファイル (anames5.c, anames6.c, anames8.c) を含みます。

  2. anames 配列の生成方法の変更: src/cmd/dist/buildgc.c 内の mkenam 関数が mkanames にリネームされ、その機能が拡張されました。

    • 以前は enam.c という単一のファイルを生成していましたが、変更後はアーキテクチャごとに anames5.c, anames6.c, anames8.c というファイルを生成するようになりました。
    • これらのファイル内の anames 配列の名前も、anames[] から anames5[], anames6[], anames8[] のようにアーキテクチャ固有の名前に変更されました。これは、liblink 内で複数のアーキテクチャの anames 配列が共存する際に名前衝突を避けるためです。
  3. 各ツールの 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 配列をこのライブラリに集約することで、以下のメリットが期待されます。

  1. コードの重複排除とモジュール化: anames 配列の定義と生成ロジックが一箇所に集約され、各ツールが共通ライブラリをリンクするだけで済むようになります。これにより、コードベースがより整理され、保守性が向上します。
  2. ビルドプロセスの簡素化: 各ツールが個別に enam.c をコンパイルする必要がなくなり、ビルドシステム (cmd/dist) の設定が簡素化されます。
  3. リンカの将来的な改善の促進: liblink の導入は、Go 1.3 リンカの再設計 (golang.org/s/go13linker) の一環であり、リンカの内部構造をよりクリーンで拡張性の高いものにするための基盤を築きます。これにより、新しいアーキテクチャのサポートや、リンカの機能改善が容易になります。
  4. 名前衝突の回避: 複数のアーキテクチャで共通の anames 配列を使用する際に発生しうる名前衝突を避けるため、アーキテクチャごとに anames5, anames6, anames8 のように命名規則を変更しています。

このコミットは、liblink の導入とそれを使用するためのコマンド変更に依存しているため、単独ではビルドできない「中間的な」コミットであることが明記されており、大規模なリファクタリングの一部であることが示唆されています。

前提知識の解説

このコミットを理解するためには、以下のGo言語のビルドシステムとツールチェーンに関する前提知識が必要です。

  1. 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のコンパイラやリンカが内部的に使用する、シンボル名(オペコード、レジスタ名など)の文字列配列です。これらのシンボルは、アセンブリコードの生成やオブジェクトファイルの解析に必要となります。
  2. 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用)。
  3. enam.canames?.c:

    • 変更前は、各リンカ (5l, 6l, 8l) のディレクトリ内に enam.c というファイルが存在し、その中にそのアーキテクチャ用の anames 配列が定義されていました。
    • この enam.c は、リンカだけでなく、対応するコンパイラやアセンブラもコンパイル時に含んでいました。これは、各ツールが同じシンボル定義を必要とするためです。
    • 変更後は、anames?.c (例: anames5.c, anames6.c, anames8.c) というファイルに分割され、これらが新しい共通ライブラリ liblink の一部としてビルドされるようになります。
  4. liblink ライブラリ: このコミットで導入される新しい概念です。Goのリンカ関連の共通コードやデータ構造をまとめたライブラリとして機能します。これにより、各リンカツールが個別に同じコードを持つのではなく、共通のライブラリをリンクするだけで済むようになります。これは、Go 1.3 リンカの再設計における重要なステップです。

  5. dist ツールとビルドプロセス: cmd/dist はGoのソースツリーをビルドする際に使用される内部ツールです。build.cbuildgc.c といったファイルは、dist がどのようにGoのツールチェーンや標準ライブラリをビルドするかを定義しています。

    • static struct { ... } gentab[]: dist がビルド時に特定のファイルを生成するためのテーブルです。例えば、opnames.henam.c (変更前) のようなファイルは、Goのソースコードから自動生成されていました。
    • static struct { ... } buildorder[]: ビルドの依存関係と順序を定義します。
    • static struct { ... } cleantab[]: クリーンアップ時に削除されるファイルを定義します。

これらの知識を持つことで、このコミットがGoのビルドシステムとリンカの内部構造にどのような影響を与え、なぜこのような変更が必要とされたのかを深く理解できます。

技術的詳細

このコミットは、Goのビルドシステム (cmd/dist) とリンカ関連のコードベースにおける重要なリファクタリングの一部です。主な技術的変更点は以下の通りです。

  1. 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 という単一のライブラリに集約され、各リンカツールがこれをリンクする形になります。
  2. 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 配列が共存する際に名前衝突を避けるためです。
  3. ビルドシステム (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.cgentab 配列が更新され、enam.c の生成エントリが削除され、代わりに anames5.c, anames6.c, anames8.c の生成エントリが mkanames 関数を指すように追加されました。また、enam.c がもはや生成されないことを示す {"enam.c", nil} エントリが追加され、クリーンアップ時にこのファイルが削除されるようにしています。
    • buildordercleantabliblink が追加され、ビルドおよびクリーンアッププロセスに新しいライブラリが組み込まれるようになりました。
    • install 関数内のファイル生成ロジックが修正され、gentab[j].gen == nil の場合にスキップするようになりました。これは、enam.c のように生成されなくなったが、クリーンアップのためにエントリを残すケースに対応するためです。

これらの変更は、Goのツールチェーンのモジュール性を高め、リンカのコードベースをより管理しやすくするための重要なステップです。特に、共通の liblink ライブラリに依存することで、将来的なリンカの機能拡張や最適化が容易になります。

コアとなるコードの変更箇所

このコミットにおけるコアとなるコードの変更箇所は、主にGoのビルドシステムを定義する src/cmd/dist/build.c と、anames 配列の生成ロジックを定義する src/cmd/dist/buildgc.c に集中しています。

  1. 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.cmkanames 関数で生成するエントリが追加されています。また、enam.c がもはや生成されないが、クリーンアップのためにエントリを残すための {"enam.c", nil} が追加されています。

    • buildordercleantab への 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 が追加されています。

  2. 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 配列の管理をこのライブラリに集約します。

  1. liblink の導入: src/cmd/dist/build.cliblink という新しいビルドターゲットが定義されました。このライブラリは、リンカ関連の共通ヘッダファイル (u.h, utf.h, fmt.h など) と、新しい形式の anames 配列定義ファイル (anames5.c, anames6.c, anames8.c) を含みます。

  2. anames 配列の生成方法の変更: src/cmd/dist/buildgc.c 内の mkenam 関数が mkanames にリネームされ、その機能が拡張されました。

    • 以前は enam.c という単一のファイルを生成していましたが、変更後はアーキテクチャごとに anames5.c, anames6.c, anames8.c というファイルを生成するようになりました。
    • これらのファイル内の anames 配列の名前も、anames[] から anames5[], anames6[], anames8[] のようにアーキテクチャ固有の名前に変更されました。これは、liblink 内で複数のアーキテクチャの anames 配列が共存する際に名前衝突を避けるためです。
  3. 各ツールの 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のビルドシステム、リンカの内部構造、そしてこのコミットが解決しようとしている問題の背景を深く理解するために役立ちます。