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

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

このコミットは、Go言語のディストリビューションビルドツールである misc/dist/bindist.go に2つの主要な変更を加えています。一つは、ビルドされるGoディストリビューションのバージョン名を上書きするための -version フラグの追加です。もう一つは、ソースディストリビューションを作成する際にGo Tourをビルドしないようにする変更です。これにより、ソースディストリビューションのサイズが削減され、ビルドプロセスが効率化されます。

コミット

commit 5d1c7bd1a66544376cf267706b005462b275f6a6
Author: Andrew Gerrand <adg@golang.org>
Date:   Thu Apr 4 14:21:19 2013 +1100

    misc/dist: add -version flag to override version name
    
    Also, don't build the tour when making the source distribution.
    
    R=golang-dev, dsymonds
    CC=golang-dev
    https://golang.org/cl/8354043

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

https://github.com/golang/go/commit/5d1c7bd1a66544376cf267706b005462b275f6a6

元コミット内容

misc/dist: add -version flag to override version name

Also, don't build the tour when making the source distribution.

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/8354043

変更の背景

このコミットは、Go言語の公式ディストリビューションビルドプロセスにおける2つの課題に対処するために行われました。

  1. バージョン名の柔軟性向上: 従来のビルドプロセスでは、Goディストリビューションのバージョン名は、リポジトリのタグ情報などから自動的に決定されていました。しかし、特定のリリースプロセスやテストシナリオにおいては、この自動生成されたバージョン名を明示的に上書きしたいというニーズがありました。例えば、カスタムビルドやプレリリース版に特定の識別子を付与したい場合などです。-version フラグの追加により、この柔軟性が提供されます。

  2. ソースディストリビューションの最適化: Go Tourは、Go言語の学習を支援するためのインタラクティブなチュートリアルであり、Goディストリビューションの一部として配布されています。しかし、ソースディストリビューション(バイナリを含まない、ソースコードのみの配布)の場合、Go Tourのソースコードや関連ファイルを含めることは、ディストリビューションのサイズを不必要に増加させ、ダウンロード時間やストレージ要件に影響を与える可能性があります。ソースディストリビューションの目的は、開発者がGoのソースコードからビルドできるようにすることであり、Go Tourの実行環境は通常、別途用意されるか、バイナリディストリビューションに含まれることが期待されます。したがって、ソースディストリビューションからGo Tourのビルドを除外することで、より軽量で目的に特化したパッケージを提供できるようになります。

これらの変更は、Goのリリースエンジニアリングとディストリビューション管理の効率化と柔軟性向上を目的としています。

前提知識の解説

このコミットを理解するためには、以下の概念について知っておく必要があります。

  • Go言語のビルドシステム: Go言語は、go buildgo install といったコマンドを通じて、ソースコードからバイナリを生成します。Goの標準ライブラリやツール群も、Go自身で書かれており、Goのビルドシステムによってコンパイルされます。
  • misc/dist ディレクトリ: Goプロジェクトのルートディレクトリにある misc/dist は、Goの公式ディストリビューション(バイナリ配布やソース配布)を作成するためのスクリプトやツールが含まれるディレクトリです。bindist.go はその中核をなすGoプログラムの一つで、様々なプラットフォーム向けのGoバイナリパッケージやソースパッケージを生成するロジックをカプセル化しています。
  • flag パッケージ: Goの標準ライブラリである flag パッケージは、コマンドライン引数を解析し、プログラム内で利用するための機能を提供します。flag.String, flag.Bool などを用いて、特定のフラグとそのデフォルト値、説明を定義します。
  • go install -race std:
    • go install: 指定されたパッケージをコンパイルし、インストールします。通常は $GOPATH/bin または $GOBIN に実行可能ファイルを、$GOPATH/pkg にコンパイル済みパッケージを配置します。
    • -race: Goの組み込みのデータ競合検出器を有効にしてビルドします。これにより、実行時にデータ競合を検出できるようになりますが、ビルドされたバイナリは通常よりも大きく、実行速度も遅くなります。
    • std: Goの標準ライブラリパッケージ全体を指します。
    • このコマンドは、標準ライブラリをデータ競合検出器を有効にした状態でビルドし、インストールすることを意味します。これは、Goのビルドプロセスにおいて、標準ライブラリの健全性を確認するための一環として行われることがあります。
  • Go Tour: Go言語の公式チュートリアルであり、Webブラウザ上でインタラクティブにGoのコードを記述・実行しながら学習できるツールです。通常、Goのバイナリディストリビューションに含まれています。
  • Mercurial (Hg): GoプロジェクトはかつてMercurialという分散型バージョン管理システムを使用していました。コミットメッセージやコード内の mercurial tag という記述はその名残です。現在はGitに移行しています。
  • Google Code: かつてGoogleが提供していたオープンソースプロジェクトホスティングサービスです。Goプロジェクトも以前はGoogle Codeでホストされており、コミットメッセージの https://golang.org/cl/8354043upload resulting files to Google Code といった記述はその歴史的な背景を示しています。golang.org/cl/ は、Goプロジェクトがコードレビューに利用しているGerritシステムへのリンクです。

技術的詳細

このコミットは、misc/dist/bindist.go ファイルに対して以下の主要な技術的変更を加えています。

  1. -version フラグの追加:

    • var ブロックに versionOverride = flag.String("version", "", "override version name") という新しいフラグ定義が追加されました。
    • これにより、コマンドラインから -version <your_version_string> の形式でバージョン名を指定できるようになります。
    • Do() メソッド内で、Goのバージョン情報を取得した後、*versionOverride != "" (つまり、-version フラグが指定されている場合) には、取得したバージョン情報ではなく、*versionOverride の値が version 変数に代入されるようになりました。これにより、最終的に生成される VERSION ファイルの内容や、アップロード時のファイル名、ラベルに反映されるバージョン名を制御できます。
  2. Go Tour ビルドの条件付き実行:

    • 変更前は、b.tour() の呼び出しが if err := b.tour(); err != nil { return err } のように、常に実行されるロジックの一部として存在していました。
    • 変更後は、b.tour() の呼び出しが if !b.Source && *includeRace { ... } ブロックの外に移動し、かつ、その前に err = b.tour() が追加されました。
    • 重要なのは、b.Source というフィールド(おそらくソースディストリビューションをビルドしているかどうかを示すブール値)が false の場合にのみ b.tour() が実行されるように、ロジックが変更された点です。
    • 具体的には、if !b.Source の条件が明示的に追加されたわけではありませんが、既存の if !b.Source && *includeRace ブロックの構造が変更され、b.tour() の呼び出しがそのブロックの外に移動し、if err != nil { return err } の直前に配置されました。これにより、ソースディストリビューション (b.Sourcetrue の場合) では b.tour() が呼び出されなくなります。
  3. go install -race std の実行順序とエラーハンドリングの改善:

    • 変更前は、make.bash の実行後にエラーチェックがあり、その後に go install -race stdgo install -a std が実行されていました。
    • 変更後は、make.bash の実行結果のエラーチェックが if *includeRace ブロックの内部に移動しました。これにより、make.bash の実行が成功した場合にのみ、-race ビルドとそれに続く標準ライブラリの再インストールが行われるようになりました。
    • また、go install -race stdgo install -a std の各ステップでエラーが発生した場合に、即座にエラーを返すようにエラーハンドリングが改善されています。
  4. ラベル生成ロジックの堅牢化:

    • Upload 関数内で、Google Codeにアップロードする際のラベル(例: OpSys-linux, Type-Source)を生成する部分が変更されました。
    • 変更前は labels = append(labels, "OpSys-"+opsys, "Type-"+ftype) のように、opsysftype が空文字列であっても無条件にラベルを追加していました。
    • 変更後は if opsys != "" { labels = append(labels, "OpSys-"+opsys) }if ftype != "" { labels = append(labels, "Type-"+ftype) } のように、opsysftype が空でない場合にのみラベルを追加するようになりました。これにより、不必要な空のラベルが生成されるのを防ぎ、よりクリーンなラベル付けが可能になります。

これらの変更は、bindist.go の堅牢性、柔軟性、および効率性を向上させるものです。

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

misc/dist/bindist.go ファイルにおける主要な変更箇所は以下の通りです。

--- a/misc/dist/bindist.go
+++ b/misc/dist/bindist.go
@@ -29,14 +29,15 @@ import (
 )
 
 var (
-	tag         = flag.String("tag", "release", "mercurial tag to check out")
-	repo        = flag.String("repo", "https://code.google.com/p/go", "repo URL")
-	tourPath    = flag.String("tour", "code.google.com/p/go-tour", "Go tour repo import path")
-	verbose     = flag.Bool("v", false, "verbose output")
-	upload      = flag.Bool("upload", true, "upload resulting files to Google Code")
-	wxsFile     = flag.String("wxs", "", "path to custom installer.wxs")
-	addLabel    = flag.String("label", "", "additional label to apply to file when uploading")
-	includeRace = flag.Bool("race", true, "build race detector packages")
+	tag             = flag.String("tag", "release", "mercurial tag to check out")
+	repo            = flag.String("repo", "https://code.google.com/p/go", "repo URL")
+	tourPath        = flag.String("tour", "code.google.com/p/go-tour", "Go tour repo import path")
+	verbose         = flag.Bool("v", false, "verbose output")
+	upload          = flag.Bool("upload", true, "upload resulting files to Google Code")
+	wxsFile         = flag.String("wxs", "", "path to custom installer.wxs")
+	addLabel        = flag.String("label", "", "additional label to apply to file when uploading")
+	includeRace     = flag.Bool("race", true, "build race detector packages")
+	versionOverride = flag.String("version", "", "override version name")
 
 	username, password string // for Google Code upload
 )
@@ -184,28 +185,28 @@ func (b *Build) Do() error {
 		} else {
 			_, err = b.run(src, "bash", "make.bash")
 		}
-	}
-	if err != nil {
-		return err
-	}
-	if !b.Source && *includeRace {
-		goCmd := filepath.Join(b.root, "bin", "go")
-		if b.OS == "windows" {
-			goCmd += ".exe"
-		}
-		_, err = b.run(src, goCmd, "install", "-race", "std")
-		if err != nil {
-			return err
+	// 変更前: } の後に err != nil のチェックと race ビルドのロジックが続く
+	// 変更後: make.bash のエラーチェックと race ビルドのロジックが統合され、tour() の呼び出し位置も変更
+	if *includeRace { // race ビルドが有効な場合
+		if err != nil { // make.bash の実行でエラーが発生した場合
+			return err
 		}
-		// Re-install std without -race, so that we're not left with
-		// a slower, race-enabled cmd/go, cmd/godoc, etc.
-		_, err = b.run(src, goCmd, "install", "-a", "std")
+		goCmd := filepath.Join(b.root, "bin", "go")
+		if b.OS == "windows" {
+			goCmd += ".exe"
+		}
+		_, err = b.run(src, goCmd, "install", "-race", "std") // -race 付きで標準ライブラリをインストール
 		if err != nil {
 			return err
 		}
+		// Re-install std without -race, so that we're not left with
+		// a slower, race-enabled cmd/go, cmd/godoc, etc.
+		_, err = b.run(src, goCmd, "install", "-a", "std") // -race なしで標準ライブラリを再インストール
+		if err != nil {
+			return err
+		}
 	}
-\n-\tif err := b.tour(); err != nil {
+\terr = b.tour() // tour() の呼び出し位置が変更され、エラーハンドリングも変更
+	if err != nil {
 		return err
 	}
 
@@ -229,6 +230,9 @@ func (b *Build) Do() error {
 	fullVersion = bytes.TrimSpace(fullVersion)
 	v := bytes.SplitN(fullVersion, []byte(" "), 2)
 	version = string(v[0])
+	if *versionOverride != "" { // -version フラグが指定されている場合、バージョンを上書き
+		version = *versionOverride
+	}
 
 	// Write VERSION file.
 	err = ioutil.WriteFile(filepath.Join(b.root, "VERSION"), fullVersion, 0644)
@@ -522,7 +526,12 @@ func (b *Build) Upload(version string, filename string) error {
 		ftype = "Source"
 		summary = fmt.Sprintf("%s (source only)", version)
 	}\n-	labels = append(labels, "OpSys-"+opsys, "Type-"+ftype)
+	// 変更前: labels = append(labels, "OpSys-"+opsys, "Type-"+ftype)
+	// 変更後: opsys または ftype が空でない場合にのみラベルを追加
+	if opsys != "" {
+		labels = append(labels, "OpSys-"+opsys)
+	}
+	if ftype != "" {
+		labels = append(labels, "Type-"+ftype)
+	}
 	if *addLabel != "" {
 		labels = append(labels, *addLabel)
 	}

コアとなるコードの解説

  1. -version フラグの追加 (var ブロック):

    +	versionOverride = flag.String("version", "", "override version name")
    

    flag.String を使用して、versionOverride という新しいグローバル変数を定義しています。これはコマンドライン引数 -version に対応し、デフォルト値は空文字列 ""、説明は "override version name" です。この変数は、プログラムの実行時にユーザーが指定したバージョン文字列を保持します。

  2. Go Tour ビルドの条件付き実行と go install -race のロジック変更 (func (b *Build) Do() error): 変更前は、make.bash の実行後にエラーチェックがあり、その後に !b.Source && *includeRace の条件で go install -race std が実行され、さらにその後に b.tour() が実行されていました。

    変更後は、make.bash の実行後のエラーチェックが if *includeRace ブロックの内部に移動しました。

    	if *includeRace {
    		if err != nil {
    			return err
    		}
    		// ... go install -race std and go install -a std ...
    	}
    	err = b.tour() // Go Tour のビルド呼び出しがここに移動
    	if err != nil {
    		return err
    	}
    

    この変更により、b.tour() の呼び出しは、*includeRace の条件とは独立して実行されるようになりました。しかし、元のコードの if !b.Source の条件が b.tour() の呼び出しに影響を与えていたため、この変更によって b.Sourcetrue (ソースディストリビューション) の場合には b.tour() が実行されないという意図が維持されています。これは、b.tour() メソッド内部で b.Source の値に基づいて処理をスキップするロジックがあるか、または、この Do() メソッドの呼び出し元で b.Source の値に応じて b.tour() の実行パスが制御されていることを示唆しています。コミットメッセージの「don't build the tour when making the source distribution」という記述から、後者の可能性が高いです。

  3. バージョン名の上書きロジック (func (b *Build) Do() error):

    	version = string(v[0])
    +	if *versionOverride != "" {
    +		version = *versionOverride
    +	}
    

    Goのバージョン情報(例: go1.1)が fullVersion から抽出され、version 変数に代入された後、この新しいロジックが適用されます。もし versionOverride フラグが空文字列でなければ(つまり、ユーザーが -version フラグを指定した場合)、version 変数の値は *versionOverride の値で上書きされます。これにより、ビルドされるGoディストリビューションのバージョン名をプログラム的に制御できるようになります。

  4. ラベル生成ロジックの改善 (func (b *Build) Upload(version string, filename string) error):

    -	labels = append(labels, "OpSys-"+opsys, "Type-"+ftype)
    +	if opsys != "" {
    +		labels = append(labels, "OpSys-"+opsys)
    +	}
    +	if ftype != "" {
    +		labels = append(labels, "Type-"+ftype)
    +	}
    

    Google Codeへのアップロード時に使用されるラベルを生成する部分です。変更前は opsys (オペレーティングシステム) や ftype (ファイルタイプ、例: "Source", "Binary") が空文字列であっても、"OpSys-""Type-" といったプレフィックス付きの空のラベルが生成されていました。変更後は、opsysftype が実際に値を持っている場合にのみ、対応するラベルが labels スライスに追加されるようになりました。これにより、生成されるラベルがより正確で意味のあるものになります。

関連リンク

  • Gerrit Change-ID: https://golang.org/cl/8354043 このリンクは、Goプロジェクトがコードレビューに利用しているGerritシステム上の変更セット(Change-ID)を示しています。コミットがGitHubにマージされる前に、ここでレビューと承認が行われます。

参考にした情報源リンク