[インデックス 19282] ファイルの概要
このコミットは、Go言語のコマンドラインツールgo
に、go build -i
という新しいフラグを追加するものです。このフラグは、指定されたパッケージをビルドする際に、そのパッケージが依存するすべてのパッケージも自動的にインストールする機能を提供します。これにより、開発者は依存関係の手動インストールなしに、よりスムーズにビルドプロセスを進めることができるようになります。
コミット
commit bb5a827a4b76ff22fdf34a66b1e8c8d4786438cc
Author: David Crawshaw <david.crawshaw@zentus.com>
Date: Tue May 6 09:12:15 2014 -0400
cmd/go: add go build -i
Fixes #7071.
LGTM=iant
R=golang-codereviews, iant
CC=golang-codereviews
https://golang.org/cl/93770044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/bb5a827a4b76ff22fdf34a66b1e8c8d4786438cc
元コミット内容
cmd/go: add go build -i
Fixes #7071.
LGTM=iant
R=golang-codereviews, iant
CC=golang-codereviews
https://golang.org/cl/93770044
変更の背景
この変更は、GoのIssue #7071を解決するために導入されました。当時のgo build
コマンドは、指定されたパッケージをビルドする機能は持っていたものの、そのパッケージが依存する他のパッケージ(依存関係)を自動的にインストールする機能は持っていませんでした。これは、特に大規模なプロジェクトや、多くの依存関係を持つパッケージを扱う際に、開発者が手動で各依存パッケージをgo install
する必要があるという不便さを生んでいました。
go install
コマンドは、パッケージをビルドしてインストールディレクトリ(通常は$GOPATH/bin
または$GOBIN
)に実行可能ファイルを配置し、依存関係もインストールします。しかし、go build
は単にビルドするだけで、インストールは行いません。このため、ビルド対象のパッケージが依存するライブラリがまだインストールされていない場合、ビルドは失敗していました。
go build -i
フラグの導入により、go build
コマンドがgo install
と同様に依存関係を自動的にインストールするようになり、開発ワークフローが大幅に改善されました。これにより、ユーザーはgo build
を実行するだけで、必要な依存関係がすべて揃った状態でビルドを完了できるようになりました。
前提知識の解説
Goのビルドシステムとパッケージ管理
Go言語は、シンプルで効率的なビルドシステムとパッケージ管理を提供します。
- パッケージ (Package): Goのコードはパッケージとして組織されます。関連する機能は一つのパッケージにまとめられ、他のパッケージからインポートして利用できます。
go build
: このコマンドは、Goのソースコードをコンパイルして実行可能ファイルやパッケージアーカイブを生成します。デフォルトでは、現在のディレクトリのパッケージをビルドし、実行可能ファイルを生成します。ライブラリパッケージの場合は、コンパイルされたアーカイブファイル(.a
ファイル)を$GOPATH/pkg
または$GOROOT/pkg
に配置します。go install
: このコマンドは、go build
と同様にパッケージをビルドしますが、それに加えてビルドされた実行可能ファイルを$GOPATH/bin
または$GOBIN
に、パッケージアーカイブを$GOPATH/pkg
または$GOROOT/pkg
にインストールします。go install
は、依存関係も自動的にビルド・インストールする特性があります。- 依存関係 (Dependencies): あるパッケージが別のパッケージの機能を利用する場合、そのパッケージは「依存関係」となります。Goのビルドシステムは、これらの依存関係を解決し、必要に応じてビルド・インストールします。
$GOPATH
: Goのワークスペースのルートディレクトリを指定する環境変数です。Goのソースコード、パッケージ、実行可能ファイルがこのディレクトリ構造内に配置されます。$GOROOT
: GoのSDKがインストールされているディレクトリを指定する環境変数です。標準ライブラリのパッケージなどが含まれます。
ビルドモードとインストールモード
Goのビルドシステム内部では、パッケージのビルドやインストールには異なる「モード」が存在します。
modeBuild
: パッケージをビルドするだけのモード。結果は一時的な場所に置かれるか、指定された出力ファイルに書き出されます。modeInstall
: パッケージをビルドし、その結果を永続的なインストールディレクトリ($GOPATH/pkg
や$GOPATH/bin
など)に配置するモード。
このコミットでは、go build
コマンドに-i
フラグが追加されることで、ビルド対象のパッケージの依存関係に対してはmodeInstall
が適用されるようになります。
技術的詳細
このコミットの主要な変更点は、go build
コマンドに-i
フラグを追加し、そのフラグが指定された場合に依存パッケージのビルドモードをmodeInstall
に変更することです。
具体的には、以下のファイルが変更されています。
-
src/cmd/go/build.go
:cmdBuild
コマンドのUsageLine
に[-i]
オプションが追加され、ヘルプメッセージに-i
フラグの説明が追加されました。buildI
という新しいブール型変数が導入され、-i
フラグの状態を保持します。runBuild
関数内で、depMode
という変数が導入されました。この変数は、デフォルトではmodeBuild
に設定されますが、buildI
がtrue
(つまり-i
フラグが指定された)の場合にはmodeInstall
に設定されます。- パッケージの依存関係を処理する
b.action
関数の呼び出しにおいて、これまでは常にmodeBuild
が渡されていた第二引数(依存関係のビルドモード)が、新しく導入されたdepMode
変数に置き換えられました。これにより、-i
フラグが指定された場合に依存関係がインストールされるようになります。
-
src/cmd/go/test.bash
:go build -i
の機能が正しく動作するかを確認するための新しいテストケースが追加されました。このテストは、依存関係を持つ2つのパッケージ(x/y/foo
とx/y/bar
)を作成し、go build -i x/y/bar
を実行してx/y/foo
がビルド・インストールされることを確認します。また、2回目の実行ではx/y/foo
が再ビルドされないことを確認し、キャッシュが正しく機能していることも検証しています。
-
src/cmd/go/test.go
:testI
という変数(go test -i
に関連するもの)が削除されました。これは、go test
コマンドの-i
フラグがgo build
の-i
フラグと統合され、buildI
変数で一元的に管理されるようになったためです。
-
src/cmd/go/testflag.go
:testFlagDefn
から{name: "i", boolVar: &testI}
のエントリが削除され、代わりに{name: "i", boolVar: &buildI}
が追加されました。これにより、go test
コマンドの-i
フラグもbuildI
変数にマッピングされ、go build -i
と同じロジックが適用されるようになりました。
これらの変更により、go build -i
は、ビルド対象のパッケージだけでなく、その依存関係もgo install
と同様にビルド・インストールする動作を実現しています。
コアとなるコードの変更箇所
src/cmd/go/build.go
におけるrunBuild
関数の変更がこのコミットの核心です。
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -28,7 +28,7 @@ import (
)
var cmdBuild = &Command{
- UsageLine: "build [-o output] [build flags] [packages]",
+ UsageLine: "build [-o output] [-i] [build flags] [packages]",
Short: "compile packages and dependencies",
Long: `
Build compiles the packages named by the import paths,
@@ -50,6 +50,8 @@ derives from the first file name mentioned, such as f1 for 'go build
f1.go f2.go'; with no files provided ('go build'), the output file
name is the base name of the containing directory.
+The -i flag installs the packages that are dependencies of the target.
+
The build flags are shared by the build, install, run, and test commands:
-a
@@ -107,6 +109,8 @@ func init() {
cmdBuild.Run = runBuild
cmdInstall.Run = runInstall
+ cmdBuild.Flag.BoolVar(&buildI, "i", false, "")
+
addBuildFlags(cmdBuild)
addBuildFlags(cmdInstall)
}
@@ -117,6 +121,7 @@ var buildN bool // -n flag
var buildP = runtime.NumCPU() // -p flag
var buildV bool // -v flag
var buildX bool // -x flag
+var buildI bool // -i flag
var buildO = cmdBuild.Flag.String("o", "", "output file")
var buildWork bool // -work flag
var buildGcflags []string // -gcflags flag
@@ -290,8 +295,12 @@ func runBuild(cmd *Command, args []string) {
}\n
a := &action{}
+\tdepMode := modeBuild
+\tif buildI {
+\t\tdepMode = modeInstall
+\t}
for _, p := range packages(args) {
-\t\ta.deps = append(a.deps, b.action(modeBuild, modeBuild, p))\n
+\t\ta.deps = append(a.deps, b.action(modeBuild, depMode, p))\n
}
b.do(a)
}
コアとなるコードの解説
上記の差分は、go build -i
の動作を制御する主要なロジックを示しています。
-
UsageLine
とヘルプメッセージの更新:- UsageLine: "build [-o output] [build flags] [packages]", + UsageLine: "build [-o output] [-i] [build flags] [packages]", ... +The -i flag installs the packages that are dependencies of the target.
これは、
go build
コマンドの利用方法を示す文字列と、-i
フラグの簡単な説明を追加しています。ユーザーがgo help build
を実行した際に、この新しいオプションが表示されるようになります。 -
buildI
変数の導入とフラグの登録:+var buildI bool // -i flag ... + cmdBuild.Flag.BoolVar(&buildI, "i", false, "")
buildI
というグローバルなブール変数が宣言され、-i
フラグがコマンドラインで指定されたかどうかを追跡します。cmdBuild.Flag.BoolVar
は、コマンドライン引数を解析し、-i
フラグが存在すればbuildI
をtrue
に設定する役割を担います。 -
depMode
の導入と条件分岐:+ depMode := modeBuild + if buildI { + depMode = modeInstall + }
これがこのコミットの最も重要な部分です。
depMode
という新しい変数が導入され、デフォルト値としてmodeBuild
(ビルドのみ)が設定されます。if buildI
の条件文により、もし-i
フラグが指定されてbuildI
がtrue
であれば、depMode
はmodeInstall
(ビルドとインストール)に上書きされます。
-
b.action
へのdepMode
の適用:- a.deps = append(a.deps, b.action(modeBuild, modeBuild, p)) + a.deps = append(a.deps, b.action(modeBuild, depMode, p))
b.action
関数は、Goのビルドシステム内でパッケージのビルドアクションを定義するものです。この関数は複数の引数を取り、そのうちの2番目の引数は「依存関係のビルドモード」を指定します。- 変更前は、依存関係も常に
modeBuild
で処理されていました。 - 変更後は、新しく計算された
depMode
がこの引数に渡されます。これにより、-i
フラグが指定された場合には、ビルド対象のパッケージの依存関係がmodeInstall
で処理され、自動的にインストールされるようになります。
- 変更前は、依存関係も常に
この一連の変更により、go build -i
は、ビルド対象のパッケージの依存関係を自動的にインストールするという、ユーザーが求めていた機能を実現しています。
関連リンク
- Go CL: https://golang.org/cl/93770044
- Go Issue #7071 (直接のリンクは見つかりませんでしたが、コミットメッセージで参照されています)
参考にした情報源リンク
- Go CL 93770044 の内容 (Web Fetchによる取得)
- Go言語の公式ドキュメント (go build, go install コマンドに関する一般的な知識)
- Go言語のパッケージ管理に関する一般的な知識
- Go言語のビルドシステムに関する一般的な知識
- GitHubのコミット履歴
- Go言語のIssueトラッカーの一般的な構造に関する知識 (Issue #7071の背景を推測するため)