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

[インデックス 11617] ファイルの概要

このコミットは、Go言語のビルドツールである cmd/dist におけるビルドの問題を修正するものです。具体的には、DEFAULT_GOROOT の初期化方法の変更、macOS (darwin) 環境でのオブジェクトファイルのクリーンアップロジックの調整、およびWindows環境でのエラーハンドリングと終了処理の改善が含まれています。これにより、Goのビルドプロセスがより堅牢になり、特にクロスプラットフォームでのビルドの信頼性が向上します。

コミット

commit b8b2253ac78ac76aa5ef171171005b8214e44fec
Author: Russ Cox <rsc@golang.org>
Date:   Sat Feb 4 01:23:54 2012 -0500

    cmd/dist: fix build
    
    TBR=golang-dev
    CC=golang-dev
    https://golang.org/cl/5630049
---
 src/cmd/dist/build.c   | 15 +++++++++------
 src/cmd/dist/unix.c    |  8 ++------
 src/cmd/dist/windows.c |  6 +++---\n src/make.bash          |  3 ++-\n 4 files changed, 16 insertions(+), 16 deletions(-)\n

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/b8b2253ac78ac76aa5ef171171005b8214e44fec

元コミット内容

cmd/dist: fix build

このコミットは、Go言語のビルドツールである cmd/dist のビルドプロセスにおける問題を修正することを目的としています。

変更の背景

このコミットの主な背景は、Go言語のビルドシステム、特に cmd/dist ツールが直面していたビルドの不具合を解消することにあります。cmd/dist はGoのソースコードからGoツールチェイン全体をビルドするために使用される重要なツールです。ビルドプロセスは複雑であり、異なるオペレーティングシステム(Unix系、Windows、macOSなど)やアーキテクチャに対応する必要があります。

コミットメッセージの「fix build」という簡潔な説明は、以前のバージョンでビルドが失敗したり、期待通りに動作しなかったりする問題があったことを示唆しています。特に、DEFAULT_GOROOT の初期化に関する問題や、macOSでのデバッグビルド時のオブジェクトファイルの扱い、Windowsでのエラー終了処理などが、ビルドの安定性や信頼性に影響を与えていた可能性があります。

この修正は、Goツールチェインの自己ホスト型ビルド(Go自身がGoをビルドする)の健全性を保つ上で不可欠であり、開発者がGoの新しいバージョンをビルドしたり、異なる環境でGoをセットアップしたりする際の障壁を取り除くことを目的としています。

前提知識の解説

このコミットを理解するためには、以下のGo言語のビルドシステムとC言語プログラミングに関する基本的な知識が必要です。

  • cmd/dist: Go言語のソースコードからGoツールチェイン全体(コンパイラ、リンカ、標準ライブラリなど)をビルドするためのブートストラップツールです。Goの初期バージョンではC言語で書かれており、Goのビルドプロセスを管理する「make」のような役割を果たします。go tool dist コマンドとして利用されます。

  • GOROOT: Goのインストールディレクトリのルートパスを示す環境変数です。GoのツールやライブラリがどこにあるかをGoツールチェインに教えます。DEFAULT_GOROOT は、GOROOT が明示的に設定されていない場合のデフォルトのパスを指します。

  • gcc: GNU Compiler Collectionの略で、C、C++、Goなど様々なプログラミング言語をコンパイルできるコンパイラです。このコミットでは、cmd/dist ツール自体をコンパイルするために使用されています。

  • make.bash: Goのソースツリーのルートにあるシェルスクリプトで、Goツールチェインをビルドするための主要なスクリプトです。cmd/dist ツールをビルドし、それを使って残りのGoツールチェインをビルドするプロセスをオーケストレーションします。

  • fatal() 関数: エラーが発生した際にプログラムを終了させるためのカスタム関数です。通常、エラーメッセージを出力し、非ゼロの終了コードで終了します。

  • ExitProcess() 関数: Windows APIの一部で、現在のプロセスを終了させるために使用されます。C標準ライブラリの exit() 関数に相当しますが、Windows固有の環境でより直接的なプロセス終了を制御します。

  • bgwait() 関数: cmd/dist ツール内でバックグラウンドで実行されている子プロセスがすべて終了するのを待つための関数です。ビルドプロセス中に並行して実行される可能性のあるコンパイルやリンクのタスクが完了するのを保証するために重要です。

  • _IOLBFsetvbuf(): C標準ライブラリの関数で、ストリーム(stdoutstderr など)のバッファリングモードを設定します。_IOLBF は行バッファリングモードを意味し、出力が行ごとにフラッシュされることを保証します。これは、特にログ出力やインタラクティブなCLIツールにおいて、出力がすぐに表示されるようにするために重要です。

  • darwin (macOS): AppleのmacOSオペレーティングシステムの内部名です。Goのビルドシステムは、macOS固有のビルド要件(例:デバッグ情報の扱い)に対応する必要があります。

  • オブジェクトファイル (.o ファイル): コンパイラによって生成される中間ファイルで、ソースコードが機械語に変換されたものです。リンカによって最終的な実行可能ファイルやライブラリに結合されます。

技術的詳細

このコミットは、Goのビルドツール cmd/dist の複数の側面を修正しています。

  1. DEFAULT_GOROOT の初期化の修正 (src/cmd/dist/build.c, src/cmd/dist/unix.c, src/cmd/dist/windows.c, src/make.bash):

    • 以前は default_goroot 変数が初期化されていませんでしたが、DEFAULT_GOROOT マクロで直接初期化されるようになりました。
    • src/make.bash スクリプトで、gcc コマンドに -DDEFAULT_GOROOT="..." オプションが追加され、コンパイル時に DEFAULT_GOROOT の値が定義されるようになりました。これにより、cmd/dist ツールがビルドされる際に、Goのルートディレクトリのパスが正しく埋め込まれるようになります。
    • src/cmd/dist/unix.csrc/cmd/dist/windows.c から、実行時に default_goroot を設定しようとするロジックが削除されました。これは、コンパイル時に値が埋め込まれるようになったため、不要になったためです。
  2. macOS (darwin) でのオブジェクトファイルのクリーンアップロジックの調整 (src/cmd/dist/build.c):

    • install 関数内で、macOS環境でのCプログラムのデバッグに関する特別な処理が追加されました。macOSでは、デバッグのためにオブジェクトファイルを残しておく必要があるため、doclean フラグが導入されました。
    • isgo が偽(C言語のファイル)で、かつ gohostosdarwin の場合、オブジェクトファイルは goroot/pkg/obj ディレクトリに保存され、doclean0 に設定されます。これにより、これらのオブジェクトファイルがビルド後にクリーンアップされないようになります。
    • それ以外の場合(GoのファイルやmacOS以外のOSの場合)、オブジェクトファイルは workdir に保存され、doclean1 に設定され、ビルド後にクリーンアップされます。
    • これにより、macOSでのC言語のデバッグビルドが正しく機能するようになります。
  3. エラーハンドリングと終了処理の改善 (src/cmd/dist/unix.c, src/cmd/dist/windows.c):

    • fatal() 関数(Unix系)と ExitProcess() を呼び出す前の fatal() 関数(Windows)に bgwait() の呼び出しが追加されました。これにより、エラー終了する前にバックグラウンドで実行中のすべての子プロセスが確実に終了するようになります。これは、リソースリークを防ぎ、クリーンな終了を保証するために重要です。
    • src/cmd/dist/windows.cxexit() 関数が exit(n) から ExitProcess(n) に変更されました。これは、Windows環境でより適切なプロセス終了メカニズムを使用するためです。
  4. 出力フォーマットの修正 (src/cmd/dist/build.c):

    • cmdenv 関数内の format 文字列が "%s=\\"%s\\"" から "%s=\\"%s\\"\\n" に変更されました。これにより、環境変数の出力後に改行が追加され、出力の可読性が向上します。

これらの変更は、Goのビルドプロセスの堅牢性、クロスプラットフォーム互換性、およびデバッグの容易さを向上させることを目的としています。

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

diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c
index f2b25d991e..6cd6f6d4ac 100644
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -21,7 +21,7 @@ char *gochar;\n char *goroot_final;\n char *goversion;\n char *slash;\t// / for unix, \\ for windows\n-char *default_goroot;\n+char *default_goroot = DEFAULT_GOROOT;\n \n static bool shouldbuild(char*, char*);\n static void copy(char*, char*);\n@@ -487,7 +487,7 @@ install(char *dir)\n \tBuf b, b1, path;\n \tVec compile, files, link, go, missing, clean, lib, extra;\n \tTime ttarg, t;\n-\tint i, j, k, n;\n+\tint i, j, k, n, doclean;\n \n \tbinit(&b);\n \tbinit(&b1);\n@@ -747,6 +747,8 @@ install(char *dir)\n \t\t\tvadd(&compile, bprintf(&b, \"-DGOARCH_%s\", goos));\n \t\t}\t\n \n+\t\tbpathf(&b, \"%s/%s\", workdir, lastelem(files.p[i]));\n+\t\tdoclean = 1;\n \t\tif(!isgo && streq(gohostos, \"darwin\")) {\n \t\t\t// To debug C programs on OS X, it is not enough to say -ggdb\n \t\t\t// on the command line.  You have to leave the object files\n@@ -755,8 +757,8 @@ install(char *dir)\n \t\t\tbpathf(&b1, \"%s/pkg/obj/%s\", goroot, dir);\n \t\t\txmkdirall(bstr(&b1));\n \t\t\tbpathf(&b, \"%s/%s\", bstr(&b1), lastelem(files.p[i]));\n-\t\t} else\n-\t\t\tbpathf(&b, \"%s/%s\", workdir, lastelem(files.p[i]));\n+\t\t\tdoclean = 0;\n+\t\t}\n \n \t\tb.p[b.len-1] = \'o\';  // was c or s\n \t\tvadd(&compile, \"-o\");\n@@ -765,7 +767,8 @@ install(char *dir)\n \t\tbgrunv(bstr(&path), CheckExit, &compile);\n \n \t\tvadd(&link, bstr(&b));\n-\t\tvadd(&clean, bstr(&b));\n+\t\tif(doclean)\n+\t\t\tvadd(&clean, bstr(&b));\n \t}\n \tbgwait();\n \t\n@@ -1144,7 +1147,7 @@ cmdenv(int argc, char **argv)\n \tbinit(&b);\n \tbinit(&b1);\n \n-\tformat = \"%s=\\\"%s\\\"\";\n+\tformat = \"%s=\\\"%s\\\"\\n\";\n \tpflag = 0;\n \tARGBEGIN{\n \tcase \'p\':\ndiff --git a/src/cmd/dist/unix.c b/src/cmd/dist/unix.c
index 465a86c0df..d62ebcaa83 100644
--- a/src/cmd/dist/unix.c
+++ b/src/cmd/dist/unix.c
@@ -475,6 +475,8 @@ fatal(char *msg, ...)\n \tvfprintf(stderr, msg, arg);\n \tva_end(arg);\n \tfprintf(stderr, \"\\n\");\n+\t\n+\tbgwait();\n \texit(1);\n }\n \n@@ -624,16 +626,10 @@ xsetenv(char *name, char *value)\n int\n main(int argc, char **argv)\n {\n-\tchar *p;\n \tBuf b;\n \tstruct utsname u;\n \n \tbinit(&b);\n-\tp = argv[0];\n-\tif(hassuffix(p, \"bin/tool/dist\")) {\n-\t\tdefault_goroot = xstrdup(p);\n-\t\tdefault_goroot[strlen(p)-strlen(\"bin/tool/dist\")] = \'\\0\';\n-\t}\n \t\n \tslash = \"/\";\n \ndiff --git a/src/cmd/dist/windows.c b/src/cmd/dist/windows.c
index 89bd3d733a..fade7bc026 100644
--- a/src/cmd/dist/windows.c
+++ b/src/cmd/dist/windows.c
@@ -688,6 +688,8 @@ fatal(char *msg, ...)\n \tva_end(arg);\n \n \txprintf(\"go tool dist: %s\\n\", buf1);\n+\t\n+\tbgwait();\n \tExitProcess(1);\n }\n \n@@ -800,7 +802,7 @@ xstrlen(char *p)\n void\n xexit(int n)\n {\n-\texit(n);\n+\tExitProcess(n);\n }\n \n void\n@@ -831,8 +833,6 @@ main(int argc, char **argv)\n \tsetvbuf(stdout, nil, _IOLBF, 0);\n \tsetvbuf(stderr, nil, _IOLBF, 0);\n \n-\tdefault_goroot = DEFAULT_GOROOT;\n-\n \tslash = \"\\\\\";\n \tgohostos = \"windows\";\n \ndiff --git a/src/make.bash b/src/make.bash
index 1c29568fdc..fcc320e573 100755
--- a/src/make.bash
+++ b/src/make.bash
@@ -47,7 +47,8 @@ done\n \n echo \'# Building C bootstrap tool.\'\n mkdir -p ../bin/tool\n-gcc -O2 -Wall -Werror -o ../bin/tool/dist -Icmd/dist cmd/dist/*.c\n+DEFGOROOT=\'-DDEFAULT_GOROOT=\"\'\"$(cd .. && pwd)\"\'\"\'\n+gcc -O2 -Wall -Werror -o ../bin/tool/dist -Icmd/dist \"$DEFGOROOT\" cmd/dist/*.c\n echo\n \n echo \'# Building compilers and Go bootstrap tool.\'\n```

## コアとなるコードの解説

### `src/cmd/dist/build.c`

*   **`char *default_goroot;` から `char *default_goroot = DEFAULT_GOROOT;` へ**:
    `default_goroot` 変数が宣言時に `DEFAULT_GOROOT` マクロで初期化されるようになりました。これにより、変数が未初期化の状態で使用される可能性がなくなります。`DEFAULT_GOROOT` は `make.bash` で `gcc` の `-D` オプションを通じて定義されます。

*   **`install` 関数内の `doclean` 変数の導入とロジック変更**:
    *   `int i, j, k, n;` の行に `doclean` 変数 (`int doclean;`) が追加されました。この変数は、ビルドされたオブジェクトファイルをクリーンアップするかどうかを制御します。
    *   新しい行 `bpathf(&b, "%s/%s", workdir, lastelem(files.p[i]));` と `doclean = 1;` が追加されました。これは、デフォルトでオブジェクトファイルが `workdir` に配置され、クリーンアップされることを示します。
    *   macOS (darwin) 環境でC言語のプログラムをデバッグする際の特殊なケースが追加されました。
        *   `if(!isgo && streq(gohostos, "darwin"))` のブロック内で、オブジェクトファイルが `goroot/pkg/obj` ディレクトリに保存されるようにパスが変更され、`doclean = 0;` が設定されます。これは、macOSではデバッグのためにオブジェクトファイルを残しておく必要があるためです。
        *   以前の `else` ブロックが削除され、`doclean = 0;` がこの `if` ブロックの内部に移動しました。これにより、macOSのC言語オブジェクトファイルのみがクリーンアップされないようになります。
    *   `vadd(&clean, bstr(&b));` の行が `if(doclean) vadd(&clean, bstr(&b));` に変更されました。これにより、`doclean` が `1` の場合にのみ、オブジェクトファイルがクリーンアップリストに追加されるようになります。

*   **`cmdenv` 関数内の `format` 文字列の変更**:
    *   `format = "%s=\\"%s\\""` から `format = "%s=\\"%s\\"\\n";` に変更されました。これにより、環境変数の出力後に改行が追加され、`go env` コマンドなどの出力がより整形されて表示されるようになります。

### `src/cmd/dist/unix.c`

*   **`fatal` 関数への `bgwait()` の追加**:
    *   `fatal` 関数内で `exit(1);` の直前に `bgwait();` が追加されました。これにより、エラーでプログラムが終了する前に、バックグラウンドで実行中のすべての子プロセスが完了するのを待つようになります。これは、リソースリークを防ぎ、クリーンな終了を保証するために重要です。

*   **`main` 関数からの `default_goroot` 設定ロジックの削除**:
    *   `main` 関数から、実行時に `argv[0]` を解析して `default_goroot` を設定しようとするロジックが削除されました。これは、`default_goroot` がコンパイル時に `DEFAULT_GOROOT` マクロで初期化されるようになったため、不要になりました。

### `src/cmd/dist/windows.c`

*   **`fatal` 関数への `bgwait()` の追加**:
    *   `fatal` 関数内で `ExitProcess(1);` の直前に `bgwait();` が追加されました。Unix版と同様に、Windowsでもエラー終了前にバックグラウンドプロセスが完了するのを保証します。

*   **`xexit` 関数の変更**:
    *   `xexit(int n)` 関数が `exit(n);` から `ExitProcess(n);` に変更されました。これは、Windows環境でプロセスを終了させるためのより適切なAPIを使用するためです。

*   **`main` 関数からの `default_goroot` 設定ロジックの削除**:
    *   `main` 関数から `default_goroot = DEFAULT_GOROOT;` の行が削除されました。これは、`default_goroot` がコンパイル時に `DEFAULT_GOROOT` マクロで初期化されるようになったため、不要になりました。

### `src/make.bash`

*   **`gcc` コマンドへの `DEFGOROOT` の追加**:
    *   `gcc` コマンドの行が変更され、`DEFGOROOT=\'-DDEFAULT_GOROOT=\"\'\"$(cd .. && pwd)\"\'\"\'` という変数が導入されました。
    *   この `DEFGOROOT` 変数は、現在のスクリプトの実行ディレクトリから親ディレクトリに移動し、その絶対パスを取得して、それを `DEFAULT_GOROOT` マクロの値として `gcc` に渡します。
    *   これにより、`cmd/dist` ツールがコンパイルされる際に、Goのルートディレクトリのパスがコンパイル時定数として埋め込まれるようになり、実行時の `default_goroot` の設定が不要になります。

これらの変更は、Goのビルドシステムの堅牢性と移植性を向上させ、特に異なるプラットフォームでのビルドの信頼性を高めることを目的としています。

## 関連リンク

*   Go Change-Id: `golang.org/cl/5630049`

## 参考にした情報源リンク

*   [appspot.com (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFYn8AbaKIlqdfeCXppBHBf_smQla29kfDbdFKAv7_2f_L_3dljWGZ4iNk6xeTsnZXyAIM8hnlprVtCpaM3XbSiXU9zsdKAXeUhvN9073Ny_eiFyUZHErWDgu6GQ8U-Uq0a)](https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFYn8AbaKIlqdfeCXppBHBf_smQla29kfDbdFKAv7_2f_L_3dljWGZ4iNk6xeTsnZXyAIM8hnlprVtCpaM3XbSiXU9zsdKAXeUhvN9073Ny_eiFyUZHErWDgu6GQ8U-Uq0a)
*   [golang.org (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFrxvAmMPknYow5KHF5WD3bHVWOXdPpPURdFfxG93kHC66V7iLYlxkkAXQQQjjYvkSmcYvvnvdAtbDq4-kd9XRRNq9ygjIDma1xsn_UoeH-AelkBTNyz0Ma)](https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFrxvAmMPknYow5KHF5WD3bHVWOXdPpPURdFfxG93kHC66V7iLYlxkkAXQQQjjYvkSmcYvvnvdAtbDq4-kd3XRRNq9ygjIDma1xsn_UoeH-AelkBTNyz0Ma)