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

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

このコミットは、Go言語のビルドシステムの一部である cmd/dist ディレクトリ内の build.c ファイルに対する変更です。build.c は、GoのソースコードからGoツールチェインや標準ライブラリをビルドする際の、クリーンアップ処理を含む様々なビルドタスクを管理する役割を担っています。具体的には、この変更はクリーンアッププロセスにおいて、src/pkg/runtime ディレクトリ下に生成される z で始まる一時ファイルや生成ファイルを確実に削除するためのものです。

コミット

commit 52ec4aa24aa6af413d950bfb50de56315a61fd73
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Fri May 4 00:58:48 2012 +0800

    cmd/dist: remove stray src/pkg/runtime/z* when cleaning

    R=golang-dev, bradfitz, dave, rsc, lstoakes, rsc
    CC=golang-dev
    https://golang.org/cl/6180044

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

https://github.com/golang/go/commit/52ec4aa24aa6af413d950bfb50de56315a61fd73

元コミット内容

cmd/dist: remove stray src/pkg/runtime/z* when cleaning

R=golang-dev, bradfitz, dave, rsc, lstoakes, rsc
CC=golang-dev
https://golang.org/cl/6180044

変更の背景

Go言語のビルドシステム cmd/dist は、Goのソースコードからコンパイラ、リンカ、標準ライブラリなどを構築するための重要なツールです。このシステムには、ビルドプロセス中に生成される一時ファイルや成果物を削除する「クリーンアップ」機能が含まれています。

このコミットの背景には、src/pkg/runtime ディレクトリ(Goランタイムのソースコードが置かれている場所)に、ビルドプロセス中に生成されるはずの z で始まるファイル(例: zversion.go, zgoos_*.go, zgoarch_*.go など)が、クリーンアップ時に適切に削除されずに「stray(迷子)」として残ってしまう問題がありました。

これらの z* ファイルは、Goのビルド時に現在のGoのバージョン情報、ターゲットOS、ターゲットアーキテクチャなどの環境固有の情報を埋め込むために自動生成されます。もし古い、あるいは不適切な z* ファイルが残っていると、以下のような問題を引き起こす可能性があります。

  1. ビルドの不整合: 古い情報を持つ z* ファイルが残っていると、新しいビルドが古い情報に基づいて行われ、予期せぬ動作やバグの原因となる可能性があります。
  2. ビルドエラー: 環境が変更された際に、古い z* ファイルが新しいビルドプロセスと競合し、ビルドが失敗する可能性があります。
  3. ディスクスペースの無駄: 不要なファイルが蓄積され、ディスクスペースを消費します。

このコミットは、これらの問題を解決するために、cmd/dist のクリーンアップ処理に、src/pkg/runtime ディレクトリ内の z で始まるファイルを無条件に削除するロジックを追加することで、ビルド環境の健全性を保つことを目的としています。

前提知識の解説

Go言語のビルドシステム (cmd/dist)

cmd/dist は、Go言語のセルフホスティング(Go自身がGoで書かれているため、GoのソースコードからGoのツールチェインをビルドするプロセス)において中心的な役割を果たすツールです。これは、Goのソースコードをダウンロードした後、all.bash (Unix系) や all.bat (Windows) スクリプトを実行する際に内部的に呼び出されます。cmd/dist は、コンパイラ、アセンブラ、リンカ、標準ライブラリなど、Goの開発に必要なすべてのツールとライブラリをビルドし、インストールします。また、ビルド環境をクリーンアップする機能も提供します。

Goランタイム (src/pkg/runtime)

src/pkg/runtime は、Goプログラムの実行を支える低レベルなコードが含まれるディレクトリです。これには、ガベージコレクション、スケジューラ、ゴルーチン管理、システムコールインターフェース、メモリ管理など、Goの並行処理モデルや効率的な実行を可能にするための基盤となる機能が実装されています。Goランタイムは、GoプログラムがOS上で動作するために不可欠な部分であり、C言語やアセンブリ言語で書かれた部分も多く含まれています。

z* ファイル

Goのビルドプロセスでは、特定の情報(Goのバージョン、ターゲットOS、ターゲットアーキテクチャなど)をソースコードに埋め込むために、一時的なGoソースファイルが生成されることがあります。これらのファイルは慣習的にファイル名が z で始まることが多く、例えば以下のようなものがあります。

  • zversion.go: 現在のGoのバージョン情報が含まれます。
  • zgoos_*.go: ターゲットOSに特化した情報が含まれます(例: zgoos_linux.go, zgoos_windows.go)。
  • zgoarch_*.go: ターゲットアーキテクチャに特化した情報が含まれます(例: zgoarch_amd64.go, zgoarch_arm.go)。

これらのファイルはビルド時に動的に生成され、コンパイルされます。通常、ビルドが完了するか、クリーンアッププロセスが実行されると削除されるべき一時ファイルです。

技術的詳細

このコミットは、src/cmd/dist/build.c ファイル内の clean 関数に新しいロジックを追加しています。clean 関数は、Goのビルドシステムが一時ファイルや生成された成果物を削除する際に呼び出される主要な関数です。

変更前の clean 関数は、cleantab というテーブルに定義されたパターンに基づいてファイルを削除していました。しかし、src/pkg/runtime ディレクトリ内の z* ファイルの一部がこの既存のクリーンアップメカニズムで捕捉されず、残ってしまうケースがあったようです。

追加されたコードブロックは、この問題を解決するために、src/pkg/runtime ディレクトリを明示的にスキャンし、z で始まるすべてのファイルを無条件に削除するようになっています。

具体的な処理の流れは以下の通りです。

  1. ディレクトリ構造のリセット: vreset(&dir); は、ディレクトリを読み込むための内部構造体 dir をリセットします。これは、新しいディレクトリの内容を読み込む前に、以前の状態をクリアするために行われます。
  2. パスの構築: bpathf(&path, "%s/src/pkg/runtime", goroot); は、src/pkg/runtime ディレクトリへの絶対パスを構築します。ここで goroot はGoのインストールルートディレクトリを指します。bpathf はパスをフォーマットするためのユーティリティ関数です。
  3. ディレクトリ内容の読み込み: xreaddir(&dir, bstr(&path)); は、構築されたパスにある src/pkg/runtime ディレクトリの内容(ファイルおよびサブディレクトリ)を読み込み、その情報を dir 構造体に格納します。xreaddir はディレクトリを読み込むためのユーティリティ関数です。
  4. ファイル名のチェックと削除:
    • for(j=0; j<dir.len; j++) { ... } ループは、src/pkg/runtime ディレクトリ内で見つかった各エントリ(ファイルまたはディレクトリ)を順番に処理します。
    • if(hasprefix(dir.p[j], "z")) は、現在処理しているエントリの名前が文字列 z で始まるかどうかをチェックします。hasprefix は文字列が特定のプレフィックスで始まるかをチェックするユーティリティ関数です。
    • 条件が真(つまり、ファイル名が z で始まる)の場合、xremove(bpathf(&b, "%s/%s", bstr(&path), dir.p[j])); が実行されます。これは、src/pkg/runtime ディレクトリ内の該当する z* ファイルへの完全なパスを再度構築し、xremove ユーティリティ関数を使ってそのファイルを削除します。

この変更により、Goのビルドシステムは、src/pkg/runtime ディレクトリに迷子の z* ファイルが残ることを防ぎ、より堅牢で予測可能なクリーンアッププロセスを実現します。

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

src/cmd/dist/build.c ファイルの clean 関数に以下のコードブロックが追加されました。

--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -1285,6 +1285,15 @@ clean(void)
 		txremove(bpathf(&b, "%s/%s", bstr(&path), cleantab[i]+4));
 	}
 
+	// remove src/pkg/runtime/z* unconditionally
+	vreset(&dir);
+	bpathf(&path, "%s/src/pkg/runtime", goroot);
+	xreaddir(&dir, bstr(&path));
+	for(j=0; j<dir.len; j++) {
+		if(hasprefix(dir.p[j], "z"))
+			xremove(bpathf(&b, "%s/%s", bstr(&path), dir.p[j]));
+	}
+
 	if(rebuildall) {
 		// Remove object tree.
 		xremoveall(bpathf(&b, "%s/pkg/obj/%s_%s", goroot, gohostos, gohostarch));

コアとなるコードの解説

追加されたコードブロックは、clean 関数内で既存のクリーンアップロジックの後に実行されます。

	// remove src/pkg/runtime/z* unconditionally
	vreset(&dir); // ディレクトリ読み込み用の構造体をリセット
	bpathf(&path, "%s/src/pkg/runtime", goroot); // Goのルートディレクトリからruntimeディレクトリへのパスを構築
	xreaddir(&dir, bstr(&path)); // runtimeディレクトリの内容を読み込む
	for(j=0; j<dir.len; j++) { // 読み込んだ各エントリ(ファイル/ディレクトリ)についてループ
		if(hasprefix(dir.p[j], "z")) // エントリ名が 'z' で始まるかチェック
			xremove(bpathf(&b, "%s/%s", bstr(&path), dir.p[j])); // 'z' で始まるファイルを削除
	}

このコードは、src/pkg/runtime ディレクトリに特化して、ファイル名が z で始まるものを無条件に削除する処理を実装しています。

  • vreset(&dir);: dir はディレクトリの内容を保持するためのデータ構造です。この行は、新しいディレクトリを読み込む前に、この構造体を初期状態にリセットします。
  • bpathf(&path, "%s/src/pkg/runtime", goroot);: goroot はGoのインストールディレクトリのパスを保持する変数です。この行は、goroot の下に src/pkg/runtime を結合して、Goランタイムのソースディレクトリへの完全なパスを path 変数に格納します。
  • xreaddir(&dir, bstr(&path));: xreaddir は指定されたディレクトリの内容を読み込むヘルパー関数です。bstr(&path)path 変数の内容を文字列として渡します。読み込まれたディレクトリ内のファイルやサブディレクトリの名前は dir 構造体に格納されます。
  • for(j=0; j<dir.len; j++) { ... }: このループは、dir に格納されたすべてのエントリを反復処理します。dir.len はエントリの総数、dir.p[j]j 番目のエントリの名前(文字列)を指します。
  • if(hasprefix(dir.p[j], "z")): 各エントリの名前に対して、それが文字 z で始まるかどうかを hasprefix 関数でチェックします。
  • xremove(bpathf(&b, "%s/%s", bstr(&path), dir.p[j]));: もしファイル名が z で始まる場合、この行が実行されます。bpathf を再度使用して、src/pkg/runtime ディレクトリ内のそのファイルへの完全なパスを構築し、xremove 関数を呼び出してそのファイルを削除します。

この追加により、Goのビルドシステムは、ビルドプロセス中に生成され、クリーンアップ時に見落とされがちだった src/pkg/runtime ディレクトリ内の z* ファイルを確実に削除できるようになり、ビルドの信頼性と環境の清潔さが向上しました。

関連リンク

参考にした情報源リンク

  • Goのソースコード (cmd/dist/build.c): https://github.com/golang/go/blob/master/src/cmd/dist/build.c
  • Goのコードレビューシステム (Gerrit): https://go-review.googlesource.com/ (コミットメッセージに記載されている https://golang.org/cl/6180044 は、このGerritの変更リストへのリンクです。)
  • Goのビルドプロセスに関する一般的な情報 (Goのドキュメントやブログ記事など、具体的なURLは検索結果による)
    • "Go build process explained": https://go.dev/doc/ (Go公式ドキュメント)
    • "Understanding Go's build system": (一般的なGoのビルドに関する解説記事)
    • "What are z*.go files in Go runtime?": (Goのz*ファイルに関するStack Overflowやフォーラムの議論)
    • "Go runtime source code": https://github.com/golang/go/tree/master/src/runtime (Goランタイムのソースコード)