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

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

このコミットは、Go言語のコマンドラインツール go において、build および install サブコマンドに -v (verbose) フラグを追加するものです。このフラグが指定されると、ビルドまたはインストール中に処理されているパッケージの名前が標準エラー出力に表示されるようになります。これにより、特に大規模なプロジェクトのビルド時に、現在どのパッケージが処理されているのかが視覚的に分かりやすくなり、ビルドが「サイレント」に停止しているかのような印象を与えることを防ぎます。また、Goのビルドスクリプトである make.bash および run.bash でもこの -v フラグが利用されるようになり、Goコードのコンパイル中の進行状況がより明確に表示されるようになりました。

コミット

commit 146a703cd1ecf096d270873090c8eeef6438b5f7
Author: Russ Cox <rsc@golang.org>
Date:   Mon Jan 9 16:44:01 2012 -0800

    cmd/go: add -v flag to build and install
    
    The -v flag prints the names of packages as they are built/installed.
    
    Use -v in make.bash/run.bash to avoid a silent pause during
    the build while Go code is being compiled.
    
    R=golang-dev, r
    CC=golang-dev
    https://golang.org/cl/5532055
---
 src/cmd/go/build.go | 20 +++++++++++++++-----\
 src/cmd/go/run.go   |  2 +-\
 src/cmd/go/test.go  |  2 +-\
 src/make.bash       |  2 +-\
 src/run.bash        |  2 +-\
 5 files changed, 19 insertions(+), 9 deletions(-)

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

https://github.com/golang/go/commit/146a703cd1ecf096d270873090c8eeef6438b5f7

元コミット内容

cmd/go: add -v flag to build and install

The -v flag prints the names of packages as they are built/installed.

Use -v in make.bash/run.bash to avoid a silent pause during
the build while Go code is being compiled.

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

変更の背景

この変更の主な背景は、Goのビルドプロセスにおけるユーザーエクスペリエンスの向上です。以前の go buildgo install コマンドは、特に多数のパッケージをビルドする際に、コンパイルの進行状況をほとんど表示しませんでした。これにより、ユーザーはコマンドがフリーズしているのか、それとも単に時間がかかっているだけなのかを判断するのが困難でした。コミットメッセージにある「silent pause (サイレントな一時停止)」という表現は、この問題点を明確に示しています。

開発者は、ビルド中にどのパッケージが処理されているかを視覚的にフィードバックすることで、ユーザーがプロセスの進行状況を把握しやすくし、不安を軽減することを目的としました。また、GoのソースコードからGoツールチェイン自体をビルドする際に使用される make.bashrun.bash スクリプトでもこの冗長な出力が利用されることで、ツールチェインのビルドプロセスもより透過的になりました。

前提知識の解説

このコミットを理解するためには、以下のGo言語および関連ツールの基本的な知識が必要です。

  • go build: Goのソースコードをコンパイルして実行可能ファイルやパッケージを生成するコマンドです。通常、現在のディレクトリのパッケージをビルドします。
  • go install: go build と似ていますが、コンパイルされたパッケージや実行可能ファイルを $GOPATH/pkg$GOPATH/bin (または $GOBIN) にインストールする点が異なります。これにより、他のプロジェクトからそのパッケージをインポートしたり、コマンドとして実行したりできるようになります。
  • go test: Goのテストを実行するコマンドです。
  • go run: Goのソースファイルをコンパイルし、すぐに実行するコマンドです。一時的な実行可能ファイルを生成し、実行後に削除します。
  • -v (verbose) フラグ: 多くのコマンドラインツールで一般的に使用されるフラグで、「詳細な出力」を意味します。通常、このフラグが指定されると、コマンドは通常の出力に加えて、より多くの情報(進行状況、デバッグ情報など)を表示します。
  • make.bash / run.bash: Go言語の公式リポジトリに含まれるシェルスクリプトで、Goツールチェイン自体をソースコードからビルドするために使用されます。make.bash はGoの初期ビルドや再ビルドを行い、run.bash はビルドされたツールチェインを使ってテストを実行したり、特定のコマンドを実行したりします。
  • パッケージ (Package): Go言語におけるコードの組織単位です。関連するGoソースファイルがまとめられ、インポートパスによって識別されます。
  • builder 構造体: cmd/go パッケージ内でビルドプロセスを管理するための内部的な構造体です。ビルドのオプション(-a, -n, -x など)や状態を保持します。

技術的詳細

このコミットは、go build および go install コマンドに -v フラグのサポートを追加するために、主に以下の変更を行っています。

  1. フラグの定義と解析:

    • src/cmd/go/build.go 内の cmdBuild および cmdInstall コマンドの UsageLine-v フラグが追加され、ヘルプメッセージにもその説明が追加されました。
    • buildV および installV という新しい bool 型の変数が定義され、それぞれ cmdBuild.Flag.Bool("v", false, "") および cmdInstall.Flag.Bool("v", false, "") を使って -v フラグの値を格納するように設定されました。
  2. builder 構造体の変更:

    • src/cmd/go/build.go 内の builder 構造体に vflag bool という新しいフィールドが追加されました。これは、ビルドが冗長モードで実行されているかどうかを示すブール値です。
    • builder 構造体の init メソッドのシグネチャが変更され、vflag パラメータを受け取るようになりました (func (b *builder) init(aflag, nflag, vflag, xflag bool)).
    • runBuild および runInstall 関数内で builder.init を呼び出す際に、新しく定義された *buildV および *installV の値が init メソッドに渡されるようになりました。
  3. 冗長出力の実装:

    • src/cmd/go/build.go 内の builder.build メソッドに、b.vflagtrue の場合にパッケージのインポートパスを標準エラー出力 (os.Stderr) に出力するロジックが追加されました。
      if b.vflag {
          fmt.Fprintf(os.Stderr, "%s\n", a.p.ImportPath)
      }
      
      ここで a.p.ImportPath は現在ビルドされているパッケージのインポートパスを指します。
  4. go run および go test の調整:

    • src/cmd/go/run.go および src/cmd/go/test.go では、builder.init を呼び出す際に、-v フラグに相当する引数として false が明示的に渡されるようになりました。これは、go rungo test 自体はパッケージのビルド進行状況を詳細に表示する必要がないためです。これらのコマンドは内部的に go build のロジックを利用しますが、ユーザーへの出力はそれぞれのコマンドの目的に特化しています。
  5. ビルドスクリプトの更新:

    • src/make.bash および src/run.bash スクリプト内で、go install -a std コマンドが go install -a -v std に変更されました。これにより、Goツールチェイン自体のビルド時に、標準ライブラリの各パッケージがビルドされる際にその名前が表示されるようになり、ビルドの進行状況がより分かりやすくなりました。

この変更は、Goのビルドシステムがどのようにコマンドラインフラグを解析し、内部的なビルドロジックにその情報を伝達し、最終的にユーザーへの出力を制御しているかを示す良い例です。特に、builder 構造体を通じてビルドオプションが管理され、build メソッド内で実際の出力ロジックが実行されるというパターンは、Goツールの設計における一般的なアプローチです。

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

このコミットで変更された主要なファイルと、その変更の概要は以下の通りです。

  • src/cmd/go/build.go:
    • cmdBuildcmdInstallUsageLine-v フラグを追加。
    • buildVinstallV という新しいブール型フラグ変数を定義。
    • runBuildrunInstall 関数内で builder.init の呼び出しに *buildV / *installV を追加。
    • builder 構造体に vflag bool フィールドを追加。
    • builder.init メソッドのシグネチャに vflag パラメータを追加し、その値を b.vflag に設定。
    • builder.build メソッド内で b.vflagtrue の場合に a.p.ImportPathos.Stderr に出力するロジックを追加。
  • src/cmd/go/run.go:
    • runRun 関数内で builder.init の呼び出しに false を追加(-v フラグの引数として)。
  • src/cmd/go/test.go:
    • runTest 関数内で builder.init の呼び出しに false を追加(-v フラグの引数として)。
  • src/make.bash:
    • go install -a stdgo install -a -v std に変更。
  • src/run.bash:
    • go install -a stdgo install -a -a -v std に変更。

コアとなるコードの解説

最も重要な変更は src/cmd/go/build.go に集中しています。

  1. cmdBuildcmdInstall の定義:

    var cmdBuild = &Command{
    	UsageLine: "build [-a] [-n] [-v] [-x] [-o output] [importpath... | gofiles...]",
    	// ...
    }
    // ...
    var cmdInstall = &Command{
    	UsageLine: "install [-a] [-n] [-v] [-x] [importpath...]",
    	// ...
    }
    

    これにより、ユーザーが go help buildgo help install を実行した際に、-v フラグが利用可能であることが表示されます。

  2. フラグ変数の追加:

    var buildV = cmdBuild.Flag.Bool("v", false, "")
    // ...
    var installV = cmdInstall.Flag.Bool("v", false, "")
    

    Flag.Bool は、コマンドライン引数からブール値のフラグを解析するためのGoの標準ライブラリの機能です。これにより、ユーザーが -v を指定したかどうかが buildV または installV に格納されます。

  3. builder 構造体と init メソッドの更新:

    type builder struct {
    	// ...
    	vflag       bool                 // the -v flag
    	// ...
    }
    
    func (b *builder) init(aflag, nflag, vflag, xflag bool) {
    	var err error
    	b.aflag = aflag
    	b.nflag = nflag
    	b.vflag = vflag // ここでフラグの値が構造体に保存される
    	b.xflag = xflag
    	// ...
    }
    

    builder 構造体は、ビルドプロセス全体の状態と設定をカプセル化します。init メソッドは、コマンドラインから渡されたフラグの値をこの構造体のフィールドに設定し、後続のビルド処理で利用できるようにします。

  4. builder.build メソッドでの冗長出力:

    func (b *builder) build(a *action) error {
    	// ...
    	if b.vflag {
    		fmt.Fprintf(os.Stderr, "%s\n", a.p.ImportPath)
    	}
    	// ...
    }
    

    これが冗長出力の核心部分です。builder.build メソッドは個々のパッケージのビルドを担当します。b.vflagtrue の場合(つまり、ユーザーが -v フラグを指定した場合)、fmt.Fprintf(os.Stderr, "%s\n", a.p.ImportPath) が実行され、現在ビルド中のパッケージのインポートパスが標準エラー出力に書き込まれます。標準エラー出力を使用するのは、通常のプログラム出力とは異なる、診断情報や進行状況のメッセージに適しているためです。

これらの変更により、Goのビルドコマンドはよりユーザーフレンドリーになり、特に長時間のビルドにおいて、ユーザーがプロセスの進行状況を把握しやすくなりました。

関連リンク

参考にした情報源リンク

  • Go言語公式ドキュメント (go build, go install, go test, go run コマンドに関する情報)
  • Go言語のソースコード (特に src/cmd/go ディレクトリ内のファイル)
  • 一般的なコマンドラインツールの -v (verbose) フラグの慣習
  • Go言語の flag パッケージのドキュメント
  • Go言語の fmt パッケージのドキュメント
  • Go言語の os パッケージのドキュメント (特に os.Stderr について)
  • Go言語のビルドプロセスに関する一般的な知識
  • シェルスクリプト (.bash ファイル) の基本的な構文と実行方法