[インデックス 1872] ファイルの概要
このコミットは、Goランタイムのソースコードのディレクトリ構造を整理し、特定のOSおよびアーキテクチャに依存するコードをより論理的なパスに移動させることを目的としています。具体的には、Darwin(macOS)およびLinux向けのamd64アーキテクチャ固有のコードが、それぞれ src/runtime/darwin/amd64/
および src/runtime/linux/amd64/
のような専用のサブディレクトリに移動されました。
さらに、このコミットの重要な変更点として、Goプログラムの初期起動処理を担う rt0
(runtime zero)コードが、これまで個別の .6
ファイルとして扱われていたものから、runtime.a
という単一のランタイムアーカイブライブラリに統合されました。これにより、ビルドプロセスが簡素化され、リンカ(6l
)がランタイムコードをより効率的に扱えるようになりました。
コミット
commit 878822f355a4c1c690be1189f726a129dbf25878
Author: Russ Cox <rsc@golang.org>
Date: Tue Mar 24 13:06:51 2009 -0700
move darwin specific code into runtime/darwin/
move darwin-amd64 specific code into runtime/darwin/amd64/
repeat for linux.
move rt0 into runtime.a instead of keeping a separate .6 file.
6l seems to have no problem with that.
TBR=r
OCL=26680
CL=26680
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/878822f355a4c1c690be1189f726a129dbf25878
元コミット内容
move darwin specific code into runtime/darwin/
move darwin-amd64 specific code into runtime/darwin/amd64/
repeat for linux.
move rt0 into runtime.a instead of keeping a separate .6 file.
6l seems to have no problem with that.
TBR=r
OCL=26680
CL=26680
変更の背景
このコミットの背景には、Goランタイムのコードベースの整理とビルドプロセスの効率化という二つの主要な目的があります。
-
コードのモジュール化と整理: Goはクロスプラットフォームを強く意識して設計されており、ランタイムには様々なOSやアーキテクチャに特化したコードが含まれています。初期のGoのコードベースでは、これらのプラットフォーム固有のファイルが
src/runtime
ディレクトリ直下に散在していました。これにより、コードの可読性や保守性が低下し、特定のプラットフォームのコードを探すのが困難になるという問題がありました。このコミットは、これらのファイルをsrc/runtime/<OS>/
およびsrc/runtime/<OS>/<ARCH>/
のような階層的なディレクトリ構造に移動することで、コードのモジュール化を進め、整理された状態を保つことを目指しました。 -
ビルドプロセスの簡素化:
rt0
(runtime zero)は、Goプログラムが実行される際に最初に実行されるアセンブリコードであり、OSとのインターフェースや初期スタックの設定など、非常に低レベルな初期化を担当します。Goの初期のビルドシステムでは、このrt0
がrt0_amd64_darwin.6
のように個別のオブジェクトファイルとして扱われ、リンカによって特別に処理される必要がありました。このコミットは、rt0
を通常のランタイムライブラリruntime.a
に含めることで、ビルドスクリプト(Makefile)の複雑さを軽減し、リンカが他のランタイムコードと同様にrt0
を扱えるようにしました。これは、ビルドシステムの設計が成熟していく過程で、より統一的で効率的なアプローチが模索された結果と言えます。
これらの変更は、Go言語がまだ初期開発段階にあった2009年に行われたものであり、言語の基盤となるランタイムとビルドシステムの設計が固まっていく過程における重要なステップでした。
前提知識の解説
このコミットを理解するためには、以下のGo言語およびシステムプログラミングに関する前提知識が必要です。
-
Goランタイム (Go Runtime): Goランタイムは、Goプログラムの実行を管理するC/アセンブリ言語で書かれたライブラリです。ガベージコレクション、スケジューラ(ゴルーチンの管理)、メモリ割り当て、システムコールインターフェースなど、Goの並行処理モデルとメモリ管理を支える中核的な機能を提供します。Goプログラムは、コンパイル時にこのランタイムとリンクされ、単一の実行可能ファイルを生成します。
-
rt0
(Runtime Zero):rt0
は "runtime zero" の略で、Goプログラムが起動する際にOSによって最初に実行されるコードです。これは通常、アセンブリ言語で書かれており、非常に低レベルな初期化タスクを担当します。具体的には、以下のような処理を行います。- OSスレッドの初期化
- 初期スタックのセットアップ
- コマンドライン引数と環境変数の処理
- Goランタイムの主要コンポーネント(ガベージコレクタ、スケジューラなど)の初期化
- 最初のゴルーチン(
g0
)とマシン(m0
)の作成 - 最終的にGoの
runtime.main
関数(そしてユーザーのmain.main
関数)を呼び出すための準備rt0
はOSとアーキテクチャに強く依存するため、プラットフォームごとに異なる実装が存在します。
-
Goのビルドプロセス: Goのビルドプロセスは、主に以下のステップを含みます。
- コンパイル: Goソースコード(
.go
)は、Goコンパイラ(例:6g
for amd64)によってオブジェクトファイル(.6
)にコンパイルされます。 - アセンブル: アセンブリ言語ソースコード(
.s
)は、Goアセンブラ(例:6a
for amd64)によってオブジェクトファイル(.6
)にアセンブルされます。 - アーカイブ: 複数のオブジェクトファイルは、Goアーカイバ(例:
6ar
)によってライブラリファイル(.a
)にまとめられます。Goランタイムは通常、runtime.a
というアーカイブライブラリとして提供されます。 - リンク: コンパイルされたオブジェクトファイルと必要なライブラリ(
runtime.a
など)は、Goリンカ(例:6l
for amd64)によって結合され、最終的な実行可能ファイルが生成されます。リンカは、プログラムのエントリポイント(この場合はrt0
)から実行を開始できるように、コードとデータを配置します。
- コンパイル: Goソースコード(
-
Makefile:
Makefile
は、ソフトウェアのビルドプロセスを自動化するためのスクリプトファイルです。make
コマンドによって解釈され、ソースファイルのコンパイル、リンク、ライブラリの作成などの手順を定義します。このコミットでは、ランタイムのビルド方法を変更するためにsrc/runtime/Makefile
が修正されています。 -
OSとアーキテクチャの識別: Goのビルドシステムでは、
GOOS
(オペレーティングシステム、例:darwin
,linux
)とGOARCH
(アーキテクチャ、例:amd64
)という環境変数を使用して、ターゲットプラットフォームを識別します。これにより、異なるプラットフォーム向けのコードを条件付きでコンパイルしたり、適切なパスからファイルをインクルードしたりすることが可能になります。
技術的詳細
このコミットにおける技術的な変更点は多岐にわたりますが、主に以下の3つのカテゴリに分類できます。
-
ディレクトリ構造の再編成: 最も顕著な変更は、Goランタイムのプラットフォーム固有のコードが新しい階層的なディレクトリ構造に移動されたことです。
- 旧パス:
src/runtime/amd64_darwin.h
,src/runtime/rt0_amd64_darwin.s
,src/runtime/signals_darwin.h
など - 新パス:
src/runtime/darwin/amd64/defs.h
,src/runtime/darwin/amd64/rt0.s
,src/runtime/darwin/signals.h
など 同様の変更がLinux関連のファイルにも適用され、src/runtime/linux/amd64/
およびsrc/runtime/linux/
ディレクトリが導入されました。 この変更により、特定のOSやアーキテクチャに関連するファイルがまとめて配置されるようになり、コードベースのモジュール性と保守性が向上しました。特に、defs.h
は以前のamd64_darwin.h
のようにOSとアーキテクチャをファイル名に含めるのではなく、ディレクトリ構造でその情報を表現するようになりました。
- 旧パス:
-
rt0
のruntime.a
への統合: 以前は、rt0
はrt0_$(GOARCH)_$(GOOS).$O
のように個別のオブジェクトファイルとしてビルドされ、リンカによって特別に扱われていました。このコミットでは、src/cmd/6l/obj.c
からrt0
を個別に読み込むロジックが削除されました。--- a/src/cmd/6l/obj.c +++ b/src/cmd/6l/obj.c @@ -353,12 +353,6 @@ main(int argc, char *argv[]) } lookup(INITENTRY, 0)->type = SXREF; - if(!debug['l']) { - a = mal(strlen(goroot)+strlen(goarch)+strlen(goos)+20); - sprint(a, "%s/lib/rt0_%s_%s.%c", goroot, goarch, goos, thechar); - objfile(a); - } - while(*argv) objfile(*argv++);
代わりに、
rt0.$O
がsrc/runtime/Makefile
のOFILES
変数に追加され、他のランタイムオブジェクトファイルと同様にruntime.a
ライブラリにアーカイブされるようになりました。--- a/src/runtime/Makefile +++ b/src/runtime/Makefile @@ -2,19 +2,14 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -CFLAGS= +CFLAGS=-I$(GOOS) -I$(GOOS)/$(GOARCH) -wF O=6 CC=$(O)c AS=$(O)a LIB=lib_$(GOARCH)_$(GOOS).a -RT0OFILES=\ -\trt0_$(GOARCH)_$(GOOS).$O\\\ - -LIBOFILES=\ -\trt1_$(GOARCH)_$(GOOS).$O\\\ -\tsys_$(GOARCH)_$(GOOS).$O\\\ +OFILES=\ array.$O\\\ asm.$O\\\ chan.$O\\\ @@ -36,25 +31,24 @@ LIBOFILES=\\\ proc.$O\\\ rune.$O\\\ runtime.$O\\\ +\trt0.$O\\\ +\trt1.$O\\\ sema.$O\\\ sema_go.$O\\\ string.$O\\\ symtab.$O\\\ +\tsys.$O\\\ traceback.$O\\\ -OFILES=$(RT0OFILES) $(LIBOFILES)\n OS_H=$(GOARCH)_$(GOOS).h\n HFILES=runtime.h hashmap.h malloc.h $(OS_H_)\n \n-install: rt0 $(LIB) runtime.acid\n-\tcp $(RT0OFILES) $(GOROOT)/lib\n+install: $(LIB) runtime.acid\n \tcp $(LIB) $(GOROOT)/lib\n \tcp runtime.acid $(GOROOT)/acid/runtime.acid\n \n-rt0:\t$(RT0OFILES)\n-\n-$(LIB): $(LIBOFILES)\n-\t$(O)ar rc $(LIB) $(LIBOFILES)\n+$(LIB): $(OFILES)\n+\t$(O)ar rc $(LIB) $(OFILES)\n ``` これにより、リンカは `runtime.a` を読み込むだけで `rt0` を含むすべてのランタイムコードを自動的に解決できるようになり、ビルドスクリプトが簡素化されました。
-
Makefileの変更とコンパイルフラグの調整:
src/runtime/Makefile
では、新しいディレクトリ構造に対応するために、コンパイル時のインクルードパスが調整されました。--- a/src/runtime/Makefile +++ b/src/runtime/Makefile @@ -2,19 +2,14 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file.\n \n-CFLAGS=\n+CFLAGS=-I$(GOOS) -I$(GOOS)/$(GOARCH) -wF
CFLAGS
に-I$(GOOS)
と-I$(GOOS)/$(GOARCH)
が追加され、コンパイラが新しいOS/アーキテクチャ固有のヘッダーファイル(例:defs.h
,signals.h
)を正しく見つけられるようになりました。 また、ソースファイルのコンパイルルールも更新され、新しいパスからのコンパイルをサポートしています。--- a/src/runtime/Makefile +++ b/src/runtime/Makefile @@ -65,17 +59,23 @@ clean:\n \trm -f *.$(O) *.a runtime.acid cgo2c\n \n %.$O:\t%.c\n-\t$(CC) $(CFLAGS) -wF $<\n+\t$(CC) $(CFLAGS) $<\n \n %.$O:\t$(GOARCH)/%.c\n-\t$(CC) $(CFLAGS) -wF $<\n+\t$(CC) $(CFLAGS) $<\n \n-%.$O:\t%.s\n-\t$(AS) $<\n+%.$O:\t$(GOOS)/%.c\n+\t$(CC) $(CFLAGS) $<\n+\n+%.$O:\t$(GOOS)/$(GOARCH)/%.c\n+\t$(CC) $(CFLAGS) $<\n \n %.$O:\t$(GOARCH)/%.s\n \t$(AS) $<\n \n+%.$O:\t$(GOOS)/$(GOARCH)/%.s\n+\t$(AS) $<\n ``` これにより、`$(GOOS)/%.c` や `$(GOOS)/$(GOARCH)/%.c` のようなパスにあるCソースファイルやアセンブリソースファイルが適切にコンパイル・アセンブルされるようになりました。
これらの変更は、Goランタイムのビルドシステムとコード構造をより堅牢でスケーラブルなものにするための初期段階の改善であり、後のGoの発展の基盤となりました。
コアとなるコードの変更箇所
このコミットで変更された主要なファイルと、その変更の概要は以下の通りです。
-
src/cmd/6l/obj.c
:rt0
を個別のオブジェクトファイルとして読み込むためのハードコードされたパスとロジックが削除されました。これにより、リンカはrt0
をruntime.a
の一部として扱うようになります。
-
src/runtime/Makefile
:CFLAGS
に-I$(GOOS)
と-I$(GOOS)/$(GOARCH)
が追加され、新しいディレクトリ構造のヘッダーファイルをインクルードできるようになりました。RT0OFILES
およびLIBOFILES
変数が削除され、OFILES
変数にrt0.$O
,rt1.$O
,sys.$O
が直接追加されました。これにより、rt0
がruntime.a
に含まれるようになりました。install
ターゲットからrt0
のコピーが削除され、$(LIB)
(runtime.a
)のみがコピーされるようになりました。rt0
を個別にビルドするルールが削除され、$(LIB)
のビルドルールが$(OFILES)
全体を対象とするように変更されました。- 新しいディレクトリ構造(
$(GOOS)/%.c
,$(GOOS)/$(GOARCH)/%.c
,$(GOOS)/$(GOARCH)/%.s
)からのCソースファイルおよびアセンブリソースファイルのコンパイル・アセンブルルールが追加されました。
-
ファイルのリネームと移動: 以下のファイルが、より整理されたディレクトリ構造に移動・リネームされました。
src/runtime/amd64_darwin.h
->src/runtime/darwin/amd64/defs.h
src/runtime/rt0_amd64_darwin.s
->src/runtime/darwin/amd64/rt0.s
src/runtime/rt1_amd64_darwin.c
->src/runtime/darwin/amd64/rt1.c
src/runtime/sys_amd64_darwin.s
->src/runtime/darwin/amd64/sys.s
src/runtime/signals_darwin.h
->src/runtime/darwin/signals.h
src/runtime/amd64_linux.h
->src/runtime/linux/amd64/defs.h
src/runtime/rt0_amd64_linux.s
->src/runtime/linux/amd64/rt0.s
src/runtime/rt1_amd64_linux.c
->src/runtime/linux/amd64/rt1.c
src/runtime/sys_amd64_linux.s
->src/runtime/linux/amd64/sys.s
src/runtime/signals_linux.h
->src/runtime/linux/signals.h
-
src/runtime/darwin/amd64/rt1.c
:- インクルードパスが変更され、
"amd64_darwin.h"
と"signals_darwin.h"
がそれぞれ"defs.h"
と"signals.h"
に変更されました。これは、新しいディレクトリ構造とファイル命名規則に対応するためです。
- インクルードパスが変更され、
コアとなるコードの解説
src/cmd/6l/obj.c
の変更
このファイルはGoリンカ 6l
の一部です。変更前は、リンカが rt0
を特定のパスから明示的に読み込むロジックを持っていました。これは、rt0
がGoプログラムのエントリポイントであり、他のランタイムコードとは異なる特別な扱いが必要だったためです。しかし、このアプローチはビルドシステムに rt0
のパスをハードコードすることになり、柔軟性に欠けていました。
変更後、この明示的な読み込みロジックが削除されました。これは、rt0
が通常のランタイムライブラリ runtime.a
の一部として提供されるようになったため、リンカが他のオブジェクトファイルと同様に rt0
を解決できるようになったことを意味します。これにより、リンカのコードが簡素化され、rt0
の管理がビルドシステム(Makefile)に一元化されました。
src/runtime/Makefile
の変更
Makefile
の変更は、このコミットのビルドシステム側の核心です。
-
CFLAGS
の変更:CFLAGS=-I$(GOOS) -I$(GOOS)/$(GOARCH) -wF
この変更は、新しいディレクトリ構造に対応するために不可欠です。-I
フラグはCコンパイラにインクルードパスを追加します。以前はsrc/runtime
ディレクトリ直下にあったヘッダーファイル(例:amd64_darwin.h
)が、src/runtime/darwin/amd64/defs.h
のようにサブディレクトリに移動したため、コンパイラがこれらの新しい場所にあるヘッダーファイルを見つけられるように、$(GOOS)
(例:darwin
)と$(GOOS)/$(GOARCH)
(例:darwin/amd64
)をインクルードパスに追加しています。これにより、Cソースファイル内で#include "defs.h"
のように記述しても、正しいヘッダーファイルが参照されるようになります。 -
OFILES
変数の再定義とrt0
の統合: 変更前はRT0OFILES
とLIBOFILES
という変数が存在し、rt0
が他のランタイムオブジェクトファイルとは別に扱われていました。 変更後、これらの変数は廃止され、OFILES
という単一の変数にすべてのランタイムオブジェクトファイル(array.$O
,asm.$O
,chan.$O
, ...,rt0.$O
,rt1.$O
,sys.$O
, ...)がリストされるようになりました。 そして、$(LIB): $(OFILES)
というルールにより、runtime.a
ライブラリがこれらのすべてのオブジェクトファイルから作成されるようになりました。これは、rt0
が他のランタイムコードと同様にruntime.a
にアーカイブされることを意味します。これにより、ビルドプロセスが統一され、rt0
の特別な扱いが不要になりました。 -
インストールルールの簡素化:
install
ターゲットからrt0
の個別のコピーが削除されました。これは、rt0
がruntime.a
に含まれるようになったため、runtime.a
をコピーするだけで十分になったためです。 -
新しいコンパイルルールの追加:
%.$O: $(GOOS)/%.c
や%.$O: $(GOOS)/$(GOARCH)/%.c
などの新しいルールが追加されました。これらは、新しいディレクトリ構造に配置されたCソースファイルやアセンブリソースファイル(例:src/runtime/darwin/amd64/rt0.s
)を適切にコンパイル・アセンブルするためのものです。make
はこれらのルールを使用して、対応するオブジェクトファイルを生成します。
ファイルのリネームと内容の変更
多くのファイルがリネームされ、src/runtime/<OS>/
および src/runtime/<OS>/<ARCH>/
の形式に移動されました。例えば、src/runtime/amd64_darwin.h
が src/runtime/darwin/amd64/defs.h
になりました。このリネームは、ファイル名からOSとアーキテクチャの情報を削除し、その情報をディレクトリ構造に委ねるという設計思想の変更を反映しています。これにより、ファイル名が短くなり、ディレクトリ構造を見るだけでどのプラットフォームのコードかが一目でわかるようになりました。
また、src/runtime/darwin/amd64/rt1.c
のように、移動されたCソースファイル内では、インクルードするヘッダーファイルのパスが新しい命名規則に合わせて変更されています。
#include "runtime.h"
#include "defs.h" // 以前は "amd64_darwin.h"
#include "signals.h" // 以前は "signals_darwin.h"
これは、新しいディレクトリ構造とファイル命名規則に合わせた内部的な整合性を保つための変更です。
これらの変更は、Goランタイムのコードベースをより整理し、将来の拡張やメンテナンスを容易にするための基盤を築きました。特に、rt0
の統合は、Goのビルドシステムがより洗練され、効率的になる方向性を示しています。
関連リンク
- Go言語公式ドキュメント: https://go.dev/doc/
- Goソースコードリポジトリ: https://github.com/golang/go
- Goのビルドプロセスに関する一般的な情報 (Goのバージョンによって詳細は異なる場合があります):
参考にした情報源リンク
- Go runtime rt0 の役割に関するWeb検索結果:
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQHuRRAty4cgxevZclYEZ28IE00aZ6XVX0FGL5BBPEI-6wrScvp--MBRZU_I_GK_qssjnwZctd7SpfJjXqFxjRxuiYDxp7vfGNflevrbmeSR72PYHm7kYzcIscr-iqKAhajWFxb0D_k=
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQEe7l4nwVfk-8IfP8dtKyiHZmr4kpK3zzXF4zyeDMsFgafyXLvf1MtHE6oNgoUVi8IMKqlpV7GXYwVPaNbthy3onk6xatEESGJxM1VpQfAEzMKkRzdlFn9o3uAFImUl48EX8LYiQRn14DQ=
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQHBjzo88Znv37EsSfUjczuR2L4v-AQ09vymdrOTmmUYrMHcFzo8e6VNidSSpI7v3vEr8SXm9s463ibYq9GDqdk7gNQWS7KnBcFpO8ldv4JHlzxr_yS9uwmD8iqZOuwJiLF2ve2nI4WKoPru3Qy7F1gqlMWn3p7wI8MOIUssJCqpTbnjkxvq_1kwPjmRMp0V
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGPIrU5NsccDWGsKIAsJXi4wy86ek5mmjf3_1qnomeRZiswZw11cmVLuAAkwqcMumuEmz3LqbvvnIncg4WF7TL-95iTXt_b5ti-wks5V9QnEC0izT_eWG-KK9O_ykdKKOOP9k82VVjv67sN0jO7erWj
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFfAy3lny6b5m3fRVu4i77TXQ84EhXfm-3so7sm820_lTXWy_P2RZTqzxWOVMCERezy64fpo8DXRip2v7bkIZWo8rzNGKrX4EXbDL9bGi2P338VEmzwjQ7mvhF4a6fyrZxaed6azg==
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFH9Ot-bGAcZPFvToggIW3--tHWfCSksYyGTTWwWCUze72ArypSFhRjPBjYhMY-VyEV3cFc-wf0a_HegQ5TVIXiIgglsnFDNogCsaxOSs2ZYMX_qKDZdhMRwO8O_nlecA==