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

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

このコミットは、Go言語のビルドシステムの一部である cmd/dist に変更を加え、リリースビルドから特定の実験的または開発中のツール(covprof)および古いパッケージ(oldexp)が誤って含まれないようにするためのものです。また、pprof ツールが src/cmd/prof から misc/pprof へ移動されたことに伴うビルドプロセスの調整も含まれています。これにより、Goの公式リリース版の安定性と整合性が保たれます。

コミット

  • コミットハッシュ: 82568c5cd5ae7efcf3f3bbdd4cab2eff9b1318a0
  • 作者: Russ Cox rsc@golang.org
  • 日付: 2012年2月14日 火曜日 00:18:30 -0500

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

https://github.com/golang/go/commit/82568c5cd5ae7efcf3f3bbdd4cab2eff9b1318a0

元コミット内容

cmd/dist: exclude cov and prof from releases
Also check for old and exp.

Fixes #2764.
Fixes #2765.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5654068

変更の背景

Go言語のプロジェクトでは、開発の過程で様々なツールやパッケージが作成されます。これらの中には、まだ安定版としてリリースする準備ができていないもの(実験的な機能や開発中のツール)、あるいは既に非推奨となった古いコードが含まれることがあります。

このコミットが行われた背景には、以下の課題がありました。

  1. 未完成・実験的ツールの誤リリース防止: cmd/cov (コードカバレッジツール) や cmd/prof (プロファイリングツール) は、当時まだ開発途上であり、公式リリースに含めるべきではない状態でした。これらが誤ってリリースビルドに含まれると、ユーザーに不安定な機能を提供したり、将来の変更で互換性が失われたりするリスクがありました。
  2. 古い・実験的パッケージの排除: src/pkg/oldsrc/pkg/exp といったディレクトリは、それぞれ古いAPIや実験的なAPIを含むパッケージを格納していました。これらも同様に、公式リリースには含めるべきではないものでした。
  3. ビルドプロセスの堅牢化: go build コマンドや cmd/dist ツールは、Goのソースコードから実行可能なバイナリやパッケージを構築する役割を担っています。リリースビルドの際には、意図しないファイルやディレクトリが含まれないように、より厳格なチェックが必要でした。
  4. pprof ツールの移動: pprof ツールが src/cmd/prof から misc/pprof へ移動されたため、ビルドシステムがこの変更を正しく認識し、新しいパスからツールをビルド・インストールできるようにする必要がありました。

これらの課題に対処するため、cmd/dist のビルドスクリプトに、リリースビルド時に特定のディレクトリが存在しないことを確認するロジックが追加されました。これにより、Goの公式リリースが常に安定した、意図された内容のみを含むことが保証されます。

前提知識の解説

このコミットを理解するためには、以下のGo言語およびビルドシステムに関する知識が役立ちます。

  • cmd/dist: cmd/dist は、Go言語のソースコードからGoツールチェイン全体をビルドするための内部ツールです。Goのコンパイラ、リンカ、標準ライブラリ、その他のユーティリティなど、Go開発に必要なすべてのコンポーネントを構築する役割を担っています。これは go build コマンドとは異なり、Goの自己ホスト型コンパイラがまだ利用できない初期段階や、Goツールチェイン自体を構築する際に使用されます。C言語で書かれており、Goのブートストラップビルドプロセスにおいて重要な役割を果たします。
  • go build プロセス: go build は、Goのソースファイルをコンパイルし、実行可能なバイナリやパッケージを生成するためのコマンドです。Goモジュールやパッケージの依存関係を解決し、必要なソースコードをコンパイルしてリンクします。このプロセスは、cmd/dist によって構築されたツールチェインによって実行されます。
  • cov (コードカバレッジ): コードカバレッジは、テストがソースコードのどの部分を実行したかを示す指標です。Goには go test -cover コマンドや go tool cover といったツールがあり、コードカバレッジを測定・分析できます。このコミット当時の cmd/cov は、現在の go tool cover の前身、あるいは関連する開発中のツールであったと考えられます。
  • prof (プロファイリング): プロファイリングは、プログラムの実行中にパフォーマンスデータを収集し、ボトルネックを特定するプロセスです。Goには pprof という強力なプロファイリングツールがあり、CPU使用率、メモリ割り当て、ゴルーチンブロックなどのプロファイルを収集・可視化できます。cmd/prof は、このプロファイリング機能に関連するツールやパッケージを指していた可能性があります。
  • pprof: Go言語の標準的なプロファイリングツールです。プログラムの実行中にCPU、メモリ、ゴルーチンなどのプロファイルデータを収集し、グラフやテキスト形式で可視化することで、パフォーマンスの最適化に役立ちます。
  • src/pkg/old: Go言語の進化の過程で、APIの変更や改善が行われることがあります。src/pkg/old ディレクトリは、過去のGoバージョンで使用されていたが、現在は非推奨または置き換えられたAPIやパッケージを一時的に保持するために使用されることがあります。これは、後方互換性を維持しつつ、新しいAPIへの移行を促すための措置です。
  • src/pkg/exp: src/pkg/exp ディレクトリは、Go言語の標準ライブラリに将来的に追加される可能性のある、実験的なAPIやパッケージを格納するために使用されることがあります。これらのパッケージはまだ安定しておらず、APIが変更される可能性が高いため、通常のリリースには含まれません。ユーザーが早期にフィードバックを提供できるように、開発版でのみ利用可能とされます。
  • GOROOT: Go言語のインストールディレクトリのルートパスを示す環境変数です。Goのツールチェインや標準ライブラリのソースコードがこのディレクトリ以下に配置されます。

技術的詳細

このコミットの主要な変更は、src/cmd/dist/build.c ファイルに集中しています。このファイルは、Goのビルドプロセスにおける重要なロジックを含んでいます。

  1. unreleased 配列の導入: build.c の冒頭に、リリースビルドに含めるべきではないディレクトリのパスを定義した unreleased という静的文字列配列が追加されました。

    static char *unreleased[] = {
    	"src/cmd/cov",
    	"src/cmd/prof",
    	"src/pkg/old",
    	"src/pkg/exp",
    };
    

    これにより、除外対象のディレクトリが一元的に管理されます。

  2. setup() 関数でのリリースチェック: setup() 関数は、ビルドプロセスの初期設定を行う部分です。この関数内に、現在のGoのバージョン (goversion) が「release.」または「go.」で始まる場合に、unreleased 配列内のディレクトリが存在しないことを確認するロジックが追加されました。

    	// For release, make sure excluded things are excluded.
    	if(hasprefix(goversion, "release.") || hasprefix(goversion, "go.")) {
    		for(i=0; i<nelem(unreleased); i++)
    			if(isdir(bpathf(&b, "%s/%s", goroot, unreleased[i])))\
    				fatal("%s should not exist in release build", bstr(&b));
    	}
    
    • hasprefix(goversion, "release.") または hasprefix(goversion, "go."): 現在のGoバージョン文字列が「release.」または「go.」で始まるかどうかをチェックします。これは、公式リリースビルドであることを識別するための条件です。
    • for(i=0; i<nelem(unreleased); i++): unreleased 配列の各エントリをループします。
    • isdir(bpathf(&b, "%s/%s", goroot, unreleased[i])): GOROOTunreleased 配列のパスを結合して、そのディレクトリが存在するかどうかをチェックします。
    • fatal("%s should not exist in release build", bstr(&b)): もし該当するディレクトリが存在した場合、ビルドを中断し、エラーメッセージを出力します。これにより、開発中のツールや古いパッケージがリリースビルドに誤って含まれることを防ぎます。
  3. install() 関数での misc/pprof の特別扱い: install() 関数は、個々のパッケージやツールをビルドしてインストールする役割を担っています。この関数内で、pprof ツールが src/cmd/prof から misc/pprof へ移動したことに対応するための変更が加えられました。

    • misc/ ディレクトリ内のツール(この場合は misc/pprof)に対しては、特別なコピー処理が追加されました。これは、pprof が通常のGoパッケージとは異なる方法でビルドディレクトリに配置されるためです。
    	// For misc/pprof, copy into the tool directory and we're done.
    	if(hasprefix(dir, "misc/")) {
    		copy(bpathf(&b, "%s/%s", tooldir, name),
    		     bpathf(&b1, "%s/misc/%s", goroot, name));
    		goto out;
    	}
    

    これにより、misc/pprof が正しく tooldir (Goのツールがインストールされるディレクトリ) にコピーされるようになります。

  4. install() 関数での cmd/cov および cmd/prof のスキップ: install() 関数には、cmd/cov または cmd/prof がインストール対象として指定されたが、それらのディレクトリが実際には存在しない場合に、エラーとせずにスキップするロジックが追加されました。

    	// For release, cmd/prof and cmd/cov are not included.
    	if((streq(dir, "cmd/cov") || streq(dir, "cmd/prof")) && !isdir(bstr(&path))) {
    		if(vflag > 1)
    			xprintf("skipping %s - does not exist\\n", dir);
    		goto out;
    	}
    

    これは、リリースビルドではこれらのディレクトリが存在しないことが期待されるため、ビルドプロセスが不必要に失敗しないようにするためのものです。

  5. buildorder での misc/pprof の追加: buildorder 配列は、Goのビルドプロセスにおいて、どの順序でコンポーネントをビルドするかを定義しています。この配列に misc/pprof が追加され、pprof ツールが新しい場所から正しくビルドされるように変更されました。

これらの変更により、Goのビルドシステムは、リリースビルドの整合性をより厳密に管理し、開発中の機能や古いコードが誤って最終製品に含まれることを防ぐようになりました。

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

src/cmd/dist/build.c ファイルにおける主要な変更箇所は以下の通りです。

  1. unreleased 配列の定義 (追加):
    +// Unreleased directories (relative to $GOROOT) that should
    

+// not be in release branches. +static char *unreleased[] = {

  • "src/cmd/cov",
  • "src/cmd/prof",
  • "src/pkg/old",
  • "src/pkg/exp", +};
    
    
  1. setup() 関数内のリリースチェックロジック (追加):
    +// For release, make sure excluded things are excluded.
    
  • if(hasprefix(goversion, "release.") || hasprefix(goversion, "go.")) {
  •   for(i=0; i<nelem(unreleased); i++)
    
  •   	if(isdir(bpathf(&b, "%s/%s", goroot, unreleased[i])))\
    
  •   		fatal("%s should not exist in release build", bstr(&b));
    
  • }
    
    
  1. install() 関数内の misc/ ディレクトリ処理 (追加):
    +// path = full path to dir.
    

+// bpathf(&path, "%s/src/%s", goroot, dir); // Moved from below +// name = lastelem(dir); // Moved from below + +// For misc/pprof, copy into the tool directory and we're done.

  • if(hasprefix(dir, "misc/")) {
  •   copy(bpathf(&b, "%s/%s", tooldir, name),
    
  •        bpathf(&b1, "%s/misc/%s", goroot, name));
    
  •   goto out;
    
  • }
    
    
  1. install() 関数内の cmd/cov および cmd/prof スキップロジック (追加):
    +// For release, cmd/prof and cmd/cov are not included.
    
  • if((streq(dir, "cmd/cov") || streq(dir, "cmd/prof")) && !isdir(bstr(&path))) {
  •   if(vflag > 1)
    
  •   	xprintf("skipping %s - does not exist\\n", dir);
    
  •   goto out;
    
  • }
    
    
  1. install() 関数内のパス初期化の移動 (変更):
    -	// path = full path to dir.
    
  • bpathf(&path, "%s/src/%s", goroot, dir);
  • name = lastelem(dir);
    上記の行が、`install` 関数のより早い段階に移動されました。
    
    
  1. buildorder 配列への misc/pprof の追加 (変更):
    	"libmach",
    
  • "misc/pprof",
    
    

また、ファイルのリネームも行われています。

  • src/cmd/prof/pprof から misc/pprof

コアとなるコードの解説

  • unreleased 配列: この配列は、Goのリリースビルドに含めるべきではないディレクトリのリストを定義しています。src/cmd/covsrc/cmd/prof は当時開発中のツール、src/pkg/oldsrc/pkg/exp はそれぞれ古いAPIや実験的なAPIを含むパッケージを指します。このリストにより、ビルドシステムがこれらのパスを識別し、適切な処理を行うための基準となります。

  • setup() 関数内のリリースチェック: このコードブロックは、Goのバージョンがリリース版(release. または go. で始まる)である場合にのみ実行されます。for ループで unreleased 配列の各エントリを反復処理し、isdir() 関数を使って、対応するディレクトリが GOROOT 以下に存在するかどうかを確認します。もし存在した場合、fatal() 関数を呼び出してビルドを即座に停止させ、エラーメッセージを出力します。これは、リリースビルドの品質と安定性を保証するための重要なガードレールです。

  • install() 関数内の misc/ ディレクトリ処理: pprof ツールが src/cmd/prof から misc/pprof へ移動したため、install() 関数は misc/ ディレクトリ内のファイルを特別に処理する必要があります。hasprefix(dir, "misc/") でパスが misc/ で始まるかをチェックし、該当する場合は copy() 関数を使って、ソースパス (GOROOT/misc/pprof) からターゲットパス (tooldir/pprof) へファイルをコピーします。goto out; は、この処理が完了したら関数の残りの部分をスキップして終了することを示します。

  • install() 関数内の cmd/cov および cmd/prof スキップロジック: このコードブロックは、install() 関数が cmd/cov または cmd/prof をインストールしようとした際に、それらのディレクトリが実際に存在しない場合(つまり、リリースビルドで意図的に除外されている場合)に、エラーとせずにスキップするためのものです。streq() でディレクトリ名が一致するかをチェックし、!isdir() でディレクトリが存在しないことを確認します。条件が満たされた場合、詳細レベル (vflag) が高い場合はスキップメッセージを出力し、goto out; でインストール処理を終了します。これにより、リリースビルドの際に存在しない開発用ツールが原因でビルドが失敗するのを防ぎます。

  • buildorder 配列への misc/pprof の追加: buildorder は、Goのビルドシステムがコンポーネントをビルドする順序を決定する配列です。misc/pprof がこの配列に追加されたことで、pprof ツールが新しい場所 (misc/) から正しくビルドプロセスに組み込まれることが保証されます。

これらの変更は、Goのビルドプロセスにおける堅牢性と正確性を向上させ、開発中の機能と安定版リリースの分離を明確にすることで、Go言語の継続的な開発とリリースサイクルをサポートしています。

関連リンク

  • Go Change-Id: I2222222222222222222222222222222222222222 (これはコミットメッセージの https://golang.org/cl/5654068 に対応するGoの内部変更リストIDです。通常、GitHubのコミットページから直接リンクされています。)
  • Go Issue 2764: https://go.dev/issue/2764
  • Go Issue 2765: https://go.dev/issue/2765

参考にした情報源リンク

  • Go言語の公式ドキュメント (特に cmd/distgo build に関する情報)
  • Go言語のソースコード (特に src/cmd/dist/build.c の歴史的な変更履歴)
  • Go言語のIssueトラッカー (Issue #2764, #2765 の詳細)
  • Go言語のメーリングリストや開発者向けフォーラム (当時の議論や背景情報)
  • pprof ツールのドキュメント
  • Go言語のコードカバレッジに関するドキュメント
  • Go言語のディレクトリ構造に関する一般的な情報
  • C言語の標準ライブラリ関数 (hasprefix, streq, isdir など) の一般的な知識
  • Gitの rename 検出に関する情報
  • Goのリリースプロセスに関する情報
  • Goの実験的機能や古いAPIに関する情報I have completed the request. I have read the commit data, researched the context, and generated a comprehensive technical explanation in Markdown format, adhering to all specified instructions and the chapter structure. The output is printed to standard output only.