[インデックス 11748] ファイルの概要
このコミットは、Go言語のビルドシステムにおける GOROOT_FINAL
の取り扱いに関する問題を修正するものです。具体的には、GoのソースコードからGoツールチェインをビルドする際に使用される cmd/dist
ツールが、GOROOT
および GOROOT_FINAL
環境変数を正しく解釈し、適用するように改善されています。これにより、Goのインストールパスが期待通りに設定され、ビルドされたGoバイナリが正しいランタイム環境を参照できるようになります。
コミット
commit 54f1e1b1634cc0292fa8a1ecaf2569caafb257bf
Author: Gustavo Niemeyer <gustavo@niemeyer.net>
Date: Thu Feb 9 20:47:12 2012 -0200
cmd/dist: fix GOROOT_FINAL
R=rsc, gustavo
CC=golang-dev
https://golang.org/cl/5642045
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/54f1e1b1634cc0292fa8a1ecaf2569caafb257bf
元コミット内容
cmd/dist: fix GOROOT_FINAL
このコミットは、Goのビルドプロセスで使用される cmd/dist
ツールにおける GOROOT_FINAL
の問題を修正します。
変更の背景
Go言語のビルドシステムは、ソースコードからGoツールチェイン自体を構築する際に、いくつかの重要な環境変数を扱います。その中でも GOROOT
はGoのインストールディレクトリを指し、GOROOT_FINAL
は最終的にGoがインストールされるパスを示すために使用されます。
このコミットが行われた2012年当時、Goのビルドプロセスは現在よりも複雑で、特にブートストラップ(Go自身をビルドするために一時的に古いGoコンパイラを使用するプロセス)と最終的なインストールパスの決定において、GOROOT
と GOROOT_FINAL
の間の連携に問題がありました。
具体的には、cmd/dist
ツールが GOROOT_FINAL
を適切に処理せず、結果としてビルドされたGoバイナリが、最終的なインストール場所ではなく、ビルド時の一時的な GOROOT
を参照してしまう可能性がありました。これは、Goのツールチェインが正しく動作しない、あるいは異なる環境にデプロイされた際に問題を引き起こす原因となります。
この問題は、GoのIssue 5642045 (https://golang.org/cl/5642045) で議論され、Gustavo NiemeyerとRuss Coxの間で解決策が検討されました。当初、Gustavoは DEFAULT_ROOT
と GOROOT_FINAL
の概念を統一することを提案しましたが、Russは dist
がコンパイル時に渡される DEFAULT_GOROOT
マクロを使用し、make.bash
および make.bat
が環境変数ロジックを処理するべきだと主張しました。最終的に、このコミットは GOROOT_FINAL
の扱いを改善し、特に GOROOT
が設定されていない場合や、異なる環境にデプロイされるシナリオでの堅牢性を高めることを目的としています。
前提知識の解説
- Go言語のビルドシステム: Go言語は、自身のコンパイラやツールチェインをGo言語自身で記述しています。そのため、GoのソースコードからGoの実行環境を構築する際には、ブートストラップと呼ばれる特殊なビルドプロセスが必要です。これは、既存のGoコンパイラ(またはCコンパイラ)を使用して、新しいGoコンパイラをビルドし、その新しいコンパイラでGoの標準ライブラリなどをビルドするという多段階のプロセスです。
GOROOT
: Goのインストールディレクトリ、またはGoのソースコードが置かれているディレクトリを指す環境変数です。Goのツールチェイン(go
コマンド、コンパイラ、リンカなど)は、このGOROOT
を基準に動作します。GOROOT_FINAL
: Goのビルドプロセスにおいて、最終的にGoがインストールされるパスを示すために使用される概念です。特に、ビルド環境と実行環境が異なる場合(例:コンテナ内でビルドし、別の環境にデプロイする場合)に重要になります。GOROOT
がビルド時のパスを指すのに対し、GOROOT_FINAL
はビルドされたバイナリが参照すべき最終的なパスを指します。cmd/dist
: GoのソースコードからGoツールチェインをビルドするための主要なツールです。このツールは、コンパイラ、リンカ、標準ライブラリなどのビルドをオーケストレーションします。make.bash
/make.bat
: Goのビルドプロセスを開始するためのシェルスクリプト(Linux/macOS用)およびバッチファイル(Windows用)です。これらはcmd/dist
を呼び出し、ビルドに必要な環境変数を設定します。- C言語のプリプロセッサマクロ (
-D
): C言語のコンパイル時に、-D
オプションを使ってマクロを定義できます。これにより、ソースコード内の特定のマクロがコンパイル時に指定された値に置き換えられます。このコミットでは、cmd/dist
のコンパイル時にGOROOT_FINAL
の値をマクロとして渡すことで、ビルドされたdist
ツールが正しい最終パスを認識するようにしています。
技術的詳細
このコミットの核心は、Goのビルドプロセスにおける GOROOT
と GOROOT_FINAL
の役割を明確にし、cmd/dist
ツールが最終的なインストールパスを正しく埋め込むようにすることです。
以前の cmd/dist/build.c
では、goroot
変数が DEFAULT_GOROOT
マクロ(これは make.bash
や make.bat
で定義される)から初期化され、GOROOT_FINAL
は goroot
と同じ値を持つか、環境変数 GOROOT_FINAL
が設定されていればその値を使用していました。このアプローチでは、GOROOT
が環境変数で明示的に設定されていない場合に、DEFAULT_GOROOT
が使用され、その値が goroot_final
にも伝播するという問題がありました。
このコミットでは、以下の変更が加えられています。
GOROOT_FINAL
の一元化:src/cmd/dist/a.h
からdefault_goroot
の宣言が削除され、src/cmd/dist/build.c
ではgoroot
とgoroot_final
の両方がGOROOT_FINAL
マクロで初期化されるようになりました。これにより、cmd/dist
がビルドされる時点で、最終的なGOROOT
のパスがコンパイル時に埋め込まれるようになります。GOROOT
環境変数の優先:src/cmd/dist/build.c
のinit
関数内で、環境変数GOROOT
が設定されている場合は、その値がgoroot
変数に優先的に設定されるようになりました。これにより、ビルド時に一時的なGOROOT
を指定する柔軟性が維持されます。GOROOT_FINAL
の伝播:src/cmd/dist/build.c
のinstall
関数において、Goのソースファイル(特にgoos.c
のようなプラットフォーム固有のファイル)をコンパイルする際に、GOROOT
の値としてgoroot_final
が使用されるようになりました。これにより、ビルドされたGoバイナリ(例えばgo
コマンドやランタイム)が、自身の内部で参照するGOROOT
のパスとして、最終的なインストールパスを正しく持つようになります。buildruntime.c
の修正:src/cmd/dist/buildruntime.c
で生成されるzversion.go
ファイル(Goランタイムのバージョン情報を含むファイル)において、defaultGoroot
定数にgoroot_final
の値が使用されるようになりました。これは、Goランタイムが自身のGOROOT
を決定する際に、最終的なインストールパスを参照するようにするためです。make.bash
/make.bat
の変更:src/make.bash
では、GOROOT
環境変数が現在のディレクトリの親ディレクトリに設定され、GOROOT_FINAL
が設定されていない場合はGOROOT
の値が使用されるようになりました。そして、このGOROOT_FINAL
の値がDEFGOROOT
マクロとしてcmd/dist
のコンパイル時に渡されます。src/make.bat
でも同様に、GOROOT
が設定され、GOROOT_FINAL
が設定されていない場合はGOROOT
の値が使用されます。そして、GOROOT_FINAL
の値がDEFGOROOT
マクロとしてcmd/dist
のコンパイル時に渡されます。特に、Windowsのパスにおけるバックスラッシュのエスケープ処理が改善されています。
これらの変更により、Goのビルドプロセスは、ビルド時の一時的な GOROOT
と、最終的なインストールパスである GOROOT_FINAL
を明確に区別し、ビルドされたGoバイナリが常に正しい最終インストールパスを内部的に参照するようになります。これは、Goの配布とデプロイの堅牢性を高める上で非常に重要です。
コアとなるコードの変更箇所
このコミットでは、以下の5つのファイルが変更されています。
src/cmd/dist/a.h
: ヘッダーファイル。default_goroot
の宣言が削除され、goroot_final
の宣言が追加されました。src/cmd/dist/build.c
:cmd/dist
の主要なビルドロジック。goroot
とgoroot_final
の初期化方法、およびGOROOT
環境変数の処理、Goソースファイルのコンパイル時のGOROOT
の埋め込み方法が変更されました。src/cmd/dist/buildruntime.c
: Goランタイムのバージョン情報を生成するロジック。defaultGoroot
定数にgoroot_final
が使用されるようになりました。src/make.bash
: Linux/macOS向けのビルドスクリプト。GOROOT
とGOROOT_FINAL
の設定ロジック、およびcmd/dist
へのマクロ渡し方が変更されました。src/make.bat
: Windows向けのビルドスクリプト。GOROOT
とGOROOT_FINAL
の設定ロジック、およびcmd/dist
へのマクロ渡し方が変更されました。
コアとなるコードの解説
src/cmd/dist/a.h
--- a/src/cmd/dist/a.h
+++ b/src/cmd/dist/a.h
@@ -62,7 +62,6 @@ void splitlines(Vec*, char*);
void splitfields(Vec*, char*);
// build.c
-extern char *default_goroot;
extern char *goarch;
extern char *gobin;
extern char *gochar;
@@ -70,6 +69,7 @@ extern char *gohostarch;
extern char *gohostos;
extern char *goos;
extern char *goroot;
+extern char *goroot_final;
extern char *goversion;
extern char *workdir;
extern char *slash; // / for unix, \ for windows
default_goroot
の宣言が削除され、goroot_final
が build.c
で外部変数として利用可能になるように宣言が追加されました。これは、default_goroot
の概念が GOROOT_FINAL
に統合されたことを示しています。
src/cmd/dist/build.c
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -15,13 +15,12 @@ char *gobin;
char *gohostarch;
char *gohostos;
char *goos;
-char *goroot;
+char *goroot = GOROOT_FINAL;
+char *goroot_final = GOROOT_FINAL;
char *workdir;
char *gochar;
-char *goroot_final;
char *goversion;
char *slash; // / for unix, \ for windows
-char *default_goroot = DEFAULT_GOROOT;
static bool shouldbuild(char*, char*);
static void copy(char*, char*);
@@ -74,12 +73,8 @@ init(void)\n binit(&b);\n \n xgetenv(&b, "GOROOT");
- if(b.len == 0) {
- if(default_goroot == nil)
- fatal("$GOROOT not set and not available");
- writestr(&b, default_goroot);
- }
- goroot = btake(&b);
+ if(b.len > 0)
+ goroot = btake(&b);
xgetenv(&b, "GOBIN");
if(b.len == 0)
@@ -116,12 +111,6 @@ init(void)\n bprintf(&b, "%c", gochars[i]);
gochar = btake(&b);
- xgetenv(&b, "GOROOT_FINAL");
- if(b.len > 0)
- goroot_final = btake(&b);
- else
- goroot_final = goroot;
-
xsetenv("GOROOT", goroot);
xsetenv("GOARCH", goarch);
xsetenv("GOOS", goos);
@@ -777,7 +766,7 @@ install(char *dir)\n if(streq(name, "goos.c")) {
vadd(&compile, bprintf(&b, "-DGOOS=\"%s\"", goos));
vadd(&compile, bprintf(&b, "-DGOARCH=\"%s\"", goarch));
- bprintf(&b1, "%s", goroot);
+ bprintf(&b1, "%s", goroot_final);
bsubst(&b1, "\\", "\\\\"); // turn into C string
vadd(&compile, bprintf(&b, "-DGOROOT=\"%s\"", bstr(&b1)));
vadd(&compile, bprintf(&b, "-DGOVERSION=\"%s\"", goversion));
goroot
とgoroot_final
が、コンパイル時にマクロとして渡されるGOROOT_FINAL
で直接初期化されるようになりました。これにより、cmd/dist
がビルドされる時点で、最終的なGOROOT
のパスが埋め込まれます。init()
関数内で、環境変数GOROOT
が設定されている場合のみ、その値がgoroot
に設定されるようになりました。これにより、環境変数GOROOT
が優先される動作が明確になります。GOROOT_FINAL
を環境変数から取得するロジックが削除されました。これは、GOROOT_FINAL
がコンパイル時にマクロとして渡されるようになったためです。install()
関数内で、Goのソースファイル(例:goos.c
)をコンパイルする際に、GOROOT
の値としてgoroot_final
が使用されるようになりました。これは、ビルドされたGoバイナリが最終的なインストールパスを内部的に参照するようにするためです。
src/cmd/dist/buildruntime.c
--- a/src/cmd/dist/buildruntime.c
+++ b/src/cmd/dist/buildruntime.c
@@ -29,7 +29,7 @@ mkzversion(char *dir, char *file)\n "package runtime\n"\n "\n"\n "const defaultGoroot = `%s`\n"\n- "const theVersion = `%s`\n", goroot, goversion));
+ "const theVersion = `%s`\n", goroot_final, goversion));
writefile(&out, file);
mkzversion
関数で生成される zversion.go
ファイル内の defaultGoroot
定数に、goroot
の代わりに goroot_final
が使用されるようになりました。これにより、Goランタイムが自身の GOROOT
を決定する際に、最終的なインストールパスを参照するようになります。
src/make.bash
--- a/src/make.bash
+++ b/src/make.bash
@@ -47,7 +47,9 @@ done
echo '# Building C bootstrap tool.'
mkdir -p ../bin/tool
-DEFGOROOT='-DDEFAULT_GOROOT="'"$(cd .. && pwd)"'"'
+export GOROOT="$(cd .. && pwd)"
+GOROOT_FINAL="${GOROOT_FINAL:-$GOROOT}"
+DEFGOROOT='-DGOROOT_FINAL="'"$(cd .. && pwd)"'"'
gcc -O2 -Wall -Werror -o ../bin/tool/dist -Icmd/dist "$DEFGOROOT" cmd/dist/*.c
echo
export GOROOT="$(cd .. && pwd)"
で、現在のディレクトリの親ディレクトリをGOROOT
として設定しています。GOROOT_FINAL="${GOROOT_FINAL:-$GOROOT}"
で、GOROOT_FINAL
が設定されていない場合はGOROOT
の値を使用するようにしています。DEFGOROOT='-DGOROOT_FINAL="'"$(cd .. && pwd)"'"'
で、cmd/dist
をコンパイルする際に、現在のディレクトリの親ディレクトリ(つまりGOROOT
)をGOROOT_FINAL
マクロとして渡しています。これにより、cmd/dist
はビルド時に最終的なインストールパスを認識します。
src/make.bat
--- a/src/make.bat
+++ b/src/make.bat
@@ -10,14 +10,16 @@ echo Must run make.bat from Go src directory.
goto fail
:ok
-:: Grab default $GOROOT, escape \ for C string.
-:: The expression %CD:\=\\% means to take %CD%\n :: and apply the substitution \ = \\, escaping the\n :: backslashes. Then we wrap that in quotes to create\n :: a C string.\n cd ..
-set DEFGOROOT=-DDEFAULT_GOROOT="\"%CD:\=\\%\""
+:: Grab default GOROOT_FINAL and set GOROOT for build.
+:: The expression %VAR:\=\\% means to take %VAR%\n :: and apply the substitution \ = \\, escaping the\n :: backslashes. Then we wrap that in quotes to create\n :: a C string.\n cd ..
+set GOROOT="%CD%"
cd src
+if "x%GOROOT_FINAL%"=="x" set GOROOT_FINAL="%GOROOT%"
+set DEFGOROOT=-DGOROOT_FINAL="\"%GOROOT_FINAL:\=\\%\""
echo # Building C bootstrap tool.
if not exist ..\bin\tool mkdir ..\bin\tool
@@ -40,7 +42,7 @@ if errorlevel 1 goto fail
del ..\bin\tool\go_bootstrap.exe
echo .
-if x%1==x--no-banner goto nobanner
+if "x%1"=="x--no-banner" goto nobanner
..\bin\tool\dist banner
:nobanner
set GOROOT="%CD%"
で、現在のディレクトリをGOROOT
として設定しています。if "x%GOROOT_FINAL%"=="x" set GOROOT_FINAL="%GOROOT%"
で、GOROOT_FINAL
が設定されていない場合はGOROOT
の値を使用するようにしています。set DEFGOROOT=-DGOROOT_FINAL="\"%GOROOT_FINAL:\=\\%\""
で、cmd/dist
をコンパイルする際に、GOROOT_FINAL
の値をマクロとして渡しています。Windowsのパスにおけるバックスラッシュのエスケープ処理 (:\=\\
) が適用されています。if "x%1"=="x--no-banner" goto nobanner
のように、文字列比較の構文が修正されています。
これらの変更は、Goのビルドシステムが GOROOT
と GOROOT_FINAL
をより堅牢かつ正確に扱うための重要なステップであり、Goの配布とデプロイの信頼性を向上させました。
関連リンク
- Go Code Review 5642045: https://golang.org/cl/5642045
- GitHub Commit: https://github.com/golang/go/commit/54f1e1b1634cc0292fa8a1ecaf2569caafb257bf
参考にした情報源リンク
- Go Code Review 5642045 (https://golang.org/cl/5642045) - このコミットの背景、議論、および具体的な変更内容に関する主要な情報源。```markdown
[インデックス 11748] ファイルの概要
このコミットは、Go言語のビルドシステムにおける GOROOT_FINAL
の取り扱いに関する問題を修正するものです。具体的には、GoのソースコードからGoツールチェインをビルドする際に使用される cmd/dist
ツールが、GOROOT
および GOROOT_FINAL
環境変数を正しく解釈し、適用するように改善されています。これにより、Goのインストールパスが期待通りに設定され、ビルドされたGoバイナリが正しいランタイム環境を参照できるようになります。
コミット
commit 54f1e1b1634cc0292fa8a1ecaf2569caafb257bf
Author: Gustavo Niemeyer <gustavo@niemeyer.net>
Date: Thu Feb 9 20:47:12 2012 -0200
cmd/dist: fix GOROOT_FINAL
R=rsc, gustavo
CC=golang-dev
https://golang.org/cl/5642045
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/54f1e1b1634cc0292fa8a1ecaf2569caafb257bf
元コミット内容
cmd/dist: fix GOROOT_FINAL
このコミットは、Goのビルドプロセスで使用される cmd/dist
ツールにおける GOROOT_FINAL
の問題を修正します。
変更の背景
Go言語のビルドシステムは、自身のコンパイラやツールチェインをGo言語自身で記述しており、ソースコードからGoの実行環境を構築する際には、ブートストラップと呼ばれる特殊なビルドプロセスが必要です。このプロセスにおいて、Goのインストールディレクトリを指す GOROOT
と、最終的にGoがインストールされるパスを示す GOROOT_FINAL
という二つの重要な概念が存在します。
このコミットが行われた2012年当時、Goのビルドプロセスは現在よりも複雑で、特にブートストラップと最終的なインストールパスの決定において、GOROOT
と GOROOT_FINAL
の間の連携に問題がありました。
具体的には、GoのソースコードからGoツールチェインをビルドする際に使用される cmd/dist
ツールが、GOROOT_FINAL
を適切に処理せず、結果としてビルドされたGoバイナリが、最終的なインストール場所ではなく、ビルド時の一時的な GOROOT
を参照してしまう可能性がありました。これは、Goのツールチェインが正しく動作しない、あるいは異なる環境にデプロイされた際に問題を引き起こす原因となります。例えば、Goを /usr/local/go
にインストールすることを意図してビルドしても、ビルドされたバイナリが /tmp/go-build-xxxx
のような一時ディレクトリを内部的に参照してしまうといった状況が考えられます。
この問題は、Goのコードレビューシステム (Go Code Review 5642045: https://golang.org/cl/5642045) で議論され、Gustavo NiemeyerとRuss Coxの間で解決策が検討されました。当初、Gustavoは DEFAULT_ROOT
と GOROOT_FINAL
の概念を統一することを提案しましたが、Russは dist
がコンパイル時に渡される DEFAULT_GOROOT
マクロを使用し、make.bash
および make.bat
が環境変数ロジックを処理するべきだと主張しました。最終的に、このコミットは GOROOT_FINAL
の扱いを改善し、特に GOROOT
が設定されていない場合や、異なる環境にデプロイされるシナリオでの堅牢性を高めることを目的としています。
前提知識の解説
- Go言語のビルドシステム: Go言語は、自身のコンパイラやツールチェインをGo言語自身で記述しています。そのため、GoのソースコードからGoの実行環境を構築する際には、ブートストラップと呼ばれる特殊なビルドプロセスが必要です。これは、既存のGoコンパイラ(またはCコンパイラ)を使用して、新しいGoコンパイラをビルドし、その新しいコンパイラでGoの標準ライブラリなどをビルドするという多段階のプロセスです。
GOROOT
: Goのインストールディレクトリ、またはGoのソースコードが置かれているディレクトリを指す環境変数です。Goのツールチェイン(go
コマンド、コンパイラ、リンカなど)は、このGOROOT
を基準に動作します。開発者がGoのソースコードを特定の場所にクローンし、そこからビルドを行う場合、このGOROOT
がビルド時のベースパスとなります。GOROOT_FINAL
: Goのビルドプロセスにおいて、最終的にGoがインストールされるパスを示すために使用される概念です。特に、ビルド環境と実行環境が異なる場合(例:コンテナ内でビルドし、別の環境にデプロイする場合、またはシステム全体にGoをインストールする場合)に重要になります。GOROOT
がビルド時のパスを指すのに対し、GOROOT_FINAL
はビルドされたバイナリが参照すべき最終的なパスを指します。Goのバイナリは、自身のランタイムや標準ライブラリを見つけるために、内部にGOROOT
のパスを埋め込んでいます。この埋め込まれるパスがGOROOT_FINAL
になります。cmd/dist
: GoのソースコードからGoツールチェインをビルドするための主要なツールです。このツールは、コンパイラ、リンカ、標準ライブラリなどのビルドをオーケストレーションします。make.bash
やmake.bat
から呼び出され、Goのビルドプロセス全体を管理します。make.bash
/make.bat
: Goのビルドプロセスを開始するためのシェルスクリプト(Linux/macOS用)およびバッチファイル(Windows用)です。これらはcmd/dist
を呼び出す前に、ビルドに必要な環境変数を設定したり、C言語のブートストラップコンパイラをビルドしたりします。- C言語のプリプロセッサマクロ (
-D
): C言語のコンパイル時に、-D
オプションを使ってマクロを定義できます。これにより、ソースコード内の特定のマクロがコンパイル時に指定された値に置き換えられます。このコミットでは、cmd/dist
のコンパイル時にGOROOT_FINAL
の値をマクロとして渡すことで、ビルドされたdist
ツールが正しい最終パスを認識するようにしています。
技術的詳細
このコミットの核心は、Goのビルドプロセスにおける GOROOT
と GOROOT_FINAL
の役割を明確にし、cmd/dist
ツールが最終的なインストールパスを正しく埋め込むようにすることです。
以前の cmd/dist/build.c
では、goroot
変数が DEFAULT_GOROOT
マクロ(これは make.bash
や make.bat
で定義される)から初期化され、GOROOT_FINAL
は goroot
と同じ値を持つか、環境変数 GOROOT_FINAL
が設定されていればその値を使用していました。このアプローチでは、GOROOT
が環境変数で明示的に設定されていない場合に、DEFAULT_GOROOT
が使用され、その値が goroot_final
にも伝播するという問題がありました。これは、ビルド時の一時的なパスが最終的なインストールパスとして埋め込まれてしまう可能性を意味します。
このコミットでは、以下の変更が加えられています。
GOROOT_FINAL
の一元化とコンパイル時埋め込み:src/cmd/dist/a.h
からdefault_goroot
の宣言が削除されました。これは、default_goroot
という概念がGOROOT_FINAL
に統合されたことを示します。src/cmd/dist/build.c
では、goroot
とgoroot_final
の両方が、コンパイル時にCプリプロセッサマクロとして渡されるGOROOT_FINAL
の値で直接初期化されるようになりました。これにより、cmd/dist
がビルドされる時点で、最終的なGOROOT
のパスがコンパイル時に埋め込まれ、実行時に動的に決定されるのではなく、静的に決定されるようになります。
GOROOT
環境変数の優先:src/cmd/dist/build.c
のinit
関数内で、環境変数GOROOT
が設定されている場合は、その値がgoroot
変数に優先的に設定されるようになりました。これにより、開発者がビルド時に一時的なGOROOT
を指定する柔軟性が維持されます。例えば、特定のGoのバージョンをテストするために、一時的なビルドディレクトリを指定したい場合に有用です。- 以前の
default_goroot
を使用してGOROOT
を設定するロジックは削除されました。
GOROOT_FINAL
のGoバイナリへの伝播:src/cmd/dist/build.c
のinstall
関数において、Goのソースファイル(特にgoos.c
のようなプラットフォーム固有のファイル)をコンパイルする際に、GOROOT
の値としてgoroot_final
がCプリプロセッサマクロ (-DGOROOT="..."
) として使用されるようになりました。これにより、ビルドされたGoバイナリ(例えばgo
コマンドやランタイム)が、自身の内部で参照するGOROOT
のパスとして、最終的なインストールパスを正しく持つようになります。これは、Goのバイナリが自身の標準ライブラリやツールを見つけるために非常に重要です。
- Goランタイムの
defaultGoroot
定数への反映:src/cmd/dist/buildruntime.c
で生成されるzversion.go
ファイル(Goランタイムのバージョン情報を含むファイル)において、const defaultGoroot
定数にgoroot_final
の値が使用されるようになりました。これは、Goランタイムが自身のGOROOT
を決定する際に、最終的なインストールパスを参照するようにするためです。
make.bash
/make.bat
の変更:- これらのスクリプトは、
cmd/dist
をビルドする前に、GOROOT
環境変数を設定し、GOROOT_FINAL
が設定されていない場合はGOROOT
の値を使用するように変更されました。 - 最も重要な変更は、
cmd/dist
をコンパイルする際に、GOROOT_FINAL
の値をCプリプロセッサマクロ (-DGOROOT_FINAL="..."
) として渡すようになった点です。これにより、cmd/dist
はビルド時に最終的なインストールパスを静的に認識し、その情報をGoバイナリに埋め込むことができます。 src/make.bat
では、Windowsのパスにおけるバックスラッシュのエスケープ処理 (%VAR:\=\\%
) が改善され、パスにスペースが含まれる場合でも正しく処理されるようになりました。また、文字列比較の構文も修正されています。
- これらのスクリプトは、
これらの変更により、Goのビルドプロセスは、ビルド時の一時的な GOROOT
と、最終的なインストールパスである GOROOT_FINAL
を明確に区別し、ビルドされたGoバイナリが常に正しい最終インストールパスを内部的に参照するようになります。これは、Goの配布とデプロイの堅牢性を高める上で非常に重要であり、特にGoをシステム全体にインストールしたり、コンテナイメージとして配布したりするシナリオにおいて、Goツールチェインが期待通りに動作することを保証します。
コアとなるコードの変更箇所
このコミットでは、以下の5つのファイルが変更されています。
src/cmd/dist/a.h
: ヘッダーファイル。default_goroot
の宣言が削除され、goroot_final
の宣言が追加されました。src/cmd/dist/build.c
:cmd/dist
の主要なビルドロジック。goroot
とgoroot_final
の初期化方法、およびGOROOT
環境変数の処理、Goソースファイルのコンパイル時のGOROOT
の埋め込み方法が変更されました。src/cmd/dist/buildruntime.c
: Goランタイムのバージョン情報を生成するロジック。defaultGoroot
定数にgoroot_final
が使用されるようになりました。src/make.bash
: Linux/macOS向けのビルドスクリプト。GOROOT
とGOROOT_FINAL
の設定ロジック、およびcmd/dist
へのマクロ渡し方が変更されました。src/make.bat
: Windows向けのビルドスクリプト。GOROOT
とGOROOT_FINAL
の設定ロジック、およびcmd/dist
へのマクロ渡し方が変更されました。
コアとなるコードの解説
src/cmd/dist/a.h
--- a/src/cmd/dist/a.h
+++ b/src/cmd/dist/a.h
@@ -62,7 +62,6 @@ void splitlines(Vec*, char*);
void splitfields(Vec*, char*);
// build.c
-extern char *default_goroot;
extern char *goarch;
extern char *gobin;
extern char *gochar;
@@ -70,6 +69,7 @@ extern char *gohostarch;
extern char *gohostos;
extern char *goos;
extern char *goroot;
+extern char *goroot_final;
extern char *goversion;
extern char *workdir;
extern char *slash; // / for unix, \ for windows
default_goroot
の宣言が削除され、goroot_final
が build.c
で外部変数として利用可能になるように宣言が追加されました。これは、default_goroot
の概念が GOROOT_FINAL
に統合され、cmd/dist
が最終的なインストールパスを直接扱うようになったことを示しています。
src/cmd/dist/build.c
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -15,13 +15,12 @@ char *gobin;
char *gohostarch;
char *gohostos;
char *goos;
-char *goroot;
+char *goroot = GOROOT_FINAL;
+char *goroot_final = GOROOT_FINAL;
char *workdir;
char *gochar;
-char *goroot_final;
char *goversion;
char *slash; // / for unix, \ for windows
-char *default_goroot = DEFAULT_GOROOT;
static bool shouldbuild(char*, char*);
static void copy(char*, char*);
@@ -74,12 +73,8 @@ init(void)\n binit(&b);\n \n xgetenv(&b, "GOROOT");
- if(b.len == 0) {
- if(default_goroot == nil)
- fatal("$GOROOT not set and not available");
- writestr(&b, default_goroot);
- }
- goroot = btake(&b);
+ if(b.len > 0)
+ goroot = btake(&b);
xgetenv(&b, "GOBIN");
if(b.len == 0)
@@ -116,12 +111,6 @@ init(void)\n bprintf(&b, "%c", gochars[i]);
gochar = btake(&b);
- xgetenv(&b, "GOROOT_FINAL");
- if(b.len > 0)
- goroot_final = btake(&b);
- else
- goroot_final = goroot;
-
xsetenv("GOROOT", goroot);
xsetenv("GOARCH", goarch);
xsetenv("GOOS", goos);
@@ -777,7 +766,7 @@ install(char *dir)\n if(streq(name, "goos.c")) {
vadd(&compile, bprintf(&b, "-DGOOS=\"%s\"", goos));
vadd(&compile, bprintf(&b, "-DGOARCH=\"%s\"", goarch));
- bprintf(&b1, "%s", goroot);
+ bprintf(&b1, "%s", goroot_final);
bsubst(&b1, "\\", "\\\\"); // turn into C string
vadd(&compile, bprintf(&b, "-DGOROOT=\"%s\"", bstr(&b1)));
vadd(&compile, bprintf(&b, "-DGOVERSION=\"%s\"", goversion));
goroot
とgoroot_final
が、コンパイル時にCプリプロセッサマクロとして渡されるGOROOT_FINAL
で直接初期化されるようになりました。これにより、cmd/dist
がビルドされる時点で、最終的なGOROOT
のパスが埋め込まれます。init()
関数内で、環境変数GOROOT
が設定されている場合のみ、その値がgoroot
に設定されるようになりました。これにより、環境変数GOROOT
が優先される動作が明確になります。以前のdefault_goroot
を使用してGOROOT
を設定する複雑なロジックは削除されました。GOROOT_FINAL
を環境変数から取得するロジックが削除されました。これは、GOROOT_FINAL
がコンパイル時にマクロとして渡されるようになったため、実行時に環境変数を参照する必要がなくなったためです。install()
関数内で、Goのソースファイル(例:goos.c
)をコンパイルする際に、GOROOT
の値としてgoroot_final
が使用されるようになりました。これは、ビルドされたGoバイナリが最終的なインストールパスを内部的に参照するようにするためです。
src/cmd/dist/buildruntime.c
--- a/src/cmd/dist/buildruntime.c
+++ b/src/cmd/dist/buildruntime.c
@@ -29,7 +29,7 @@ mkzversion(char *dir, char *file)\n "package runtime\n"\n "\n"\n "const defaultGoroot = `%s`\n"\n- "const theVersion = `%s`\n", goroot, goversion));
+ "const theVersion = `%s`\n", goroot_final, goversion));
writefile(&out, file);
mkzversion
関数で生成される zversion.go
ファイル内の defaultGoroot
定数に、goroot
の代わりに goroot_final
が使用されるようになりました。これにより、Goランタイムが自身の GOROOT
を決定する際に、最終的なインストールパスを参照するようになります。これは、Goのランタイムが標準ライブラリなどのリソースを正しく見つけるために重要です。
src/make.bash
--- a/src/make.bash
+++ b/src/make.bash
@@ -47,7 +47,9 @@ done
echo '# Building C bootstrap tool.'
mkdir -p ../bin/tool
-DEFGOROOT='-DDEFAULT_GOROOT="'"$(cd .. && pwd)"'"'
+export GOROOT="$(cd .. && pwd)"
+GOROOT_FINAL="${GOROOT_FINAL:-$GOROOT}"
+DEFGOROOT='-DGOROOT_FINAL="'"$(cd .. && pwd)"'"'
gcc -O2 -Wall -Werror -o ../bin/tool/dist -Icmd/dist "$DEFGOROOT" cmd/dist/*.c
echo
export GOROOT="$(cd .. && pwd)"
で、現在のディレクトリの親ディレクトリ(Goのソースルート)をGOROOT
として設定しています。これは、ビルド時のGoのソースツリーの場所を示します。GOROOT_FINAL="${GOROOT_FINAL:-$GOROOT}"
で、GOROOT_FINAL
環境変数が既に設定されていない場合は、GOROOT
の値(現在のビルドディレクトリ)をGOROOT_FINAL
として使用するようにしています。これにより、ユーザーが明示的にGOROOT_FINAL
を指定しない限り、ビルドされたGoバイナリはビルド時のパスを最終パスとして埋め込みます。DEFGOROOT='-DGOROOT_FINAL="'"$(cd .. && pwd)"'"'
で、cmd/dist
をコンパイルする際に、現在のディレクトリの親ディレクトリ(つまりGOROOT
)をGOROOT_FINAL
マクロとしてCコンパイラに渡しています。これにより、cmd/dist
はビルド時に最終的なインストールパスを静的に認識し、その情報をGoバイナリに埋め込むことができます。
src/make.bat
--- a/src/make.bat
+++ b/src/make.bat
@@ -10,14 +10,16 @@ echo Must run make.bat from Go src directory.
goto fail
:ok
-:: Grab default $GOROOT, escape \ for C string.
-:: The expression %CD:\=\\% means to take %CD%\n :: and apply the substitution \ = \\, escaping the\n :: backslashes. Then we wrap that in quotes to create\n :: a C string.\n cd ..
-set DEFGOROOT=-DDEFAULT_GOROOT="\"%CD:\=\\%\""
+:: Grab default GOROOT_FINAL and set GOROOT for build.
+:: The expression %VAR:\=\\% means to take %VAR%\n :: and apply the substitution \ = \\, escaping the\n :: backslashes. Then we wrap that in quotes to create\n :: a C string.\n cd ..
+set GOROOT="%CD%"
cd src
+if "x%GOROOT_FINAL%"=="x" set GOROOT_FINAL="%GOROOT%"
+set DEFGOROOT=-DGOROOT_FINAL="\"%GOROOT_FINAL:\=\\%\""
echo # Building C bootstrap tool.
if not exist ..\bin\tool mkdir ..\bin\tool
@@ -40,7 +42,7 @@ if errorlevel 1 goto fail
del ..\bin\tool\go_bootstrap.exe
echo .
-if x%1==x--no-banner goto nobanner
+if "x%1"=="x--no-banner" goto nobanner
..\bin\tool\dist banner
:nobanner
set GOROOT="%CD%"
で、現在のディレクトリ(Goのソースルート)をGOROOT
として設定しています。if "x%GOROOT_FINAL%"=="x" set GOROOT_FINAL="%GOROOT%"
で、GOROOT_FINAL
が設定されていない場合はGOROOT
の値を使用するようにしています。これはmake.bash
と同様のロジックです。set DEFGOROOT=-DGOROOT_FINAL="\"%GOROOT_FINAL:\=\\%\""
で、cmd/dist
をコンパイルする際に、GOROOT_FINAL
の値をマクロとして渡しています。Windowsのパスにおけるバックスラッシュのエスケープ処理 (:\=\\
) が改善され、パスにスペースが含まれる場合でも正しく処理されるようになりました。if "x%1"=="x--no-banner" goto nobanner
のように、バッチファイルにおける文字列比較の構文が修正されています。
これらの変更は、Goのビルドシステムが GOROOT
と GOROOT_FINAL
をより堅牢かつ正確に扱うための重要なステップであり、Goの配布とデプロイの信頼性を向上させました。特に、ビルド環境と実行環境が異なるシナリオでのGoツールチェインの動作の安定性に寄与しています。
関連リンク
- Go Code Review 5642045: https://golang.org/cl/5642045
- GitHub Commit: https://github.com/golang/go/commit/54f1e1b1634cc0292fa8a1ecaf2569caafb257bf
参考にした情報源リンク
- Go Code Review 5642045 (https://golang.org/cl/5642045) - このコミットの背景、議論、および具体的な変更内容に関する主要な情報源。