[インデックス 10631] ファイルの概要
このコミットは、goinstall
コマンドの動作を修正するものです。具体的には、-make=true
フラグが指定されている場合に、-install=false
フラグが正しく尊重されるように変更されています。これにより、ユーザーが明示的にインストールを無効にしたい場合に、意図しないインストールが実行されるのを防ぎます。
コミット
- コミットハッシュ:
2c7a84a95bc10fe57b7b0699aee23f06f23076b5
- 作者: Andrew Gerrand adg@golang.org
- 日付: Wed Dec 7 09:41:20 2011 +1100
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/2c7a84a95bc10fe57b7b0699aee23f06f23076b5
元コミット内容
goinstall: honour -install=false flag when -make=true
R=rsc
CC=golang-dev
https://golang.org/cl/5448124
変更の背景
goinstall
は、Go言語のパッケージをダウンロード、ビルド、インストールするための初期のツールでした。このツールには、パッケージをビルドするだけでなく、その結果を $GOPATH/bin
や $GOPATH/pkg
にインストールする機能が含まれていました。
コミットメッセージによると、この変更の背景には、ユーザーが -make=true
フラグを使用してパッケージをビルドしたいが、その結果を自動的にインストールしたくないというユースケースがあったと考えられます。従来の goinstall
の実装では、-make=true
が指定されると、-install=false
が指定されていても、内部的に install
コマンドが常に実行されてしまうという問題がありました。
この挙動は、例えば、単にビルドのテストを行いたい場合や、ビルドされたバイナリやパッケージを特定の場所に手動で配置したい場合に不都合でした。このコミットは、ユーザーの意図を尊重し、-install=false
フラグが正しく機能するように修正することで、goinstall
の柔軟性を向上させることを目的としています。
前提知識の解説
goinstall
コマンド
goinstall
は、Go言語の初期のバージョン(Go 1.0以前)で使われていた、リモートリポジトリからGoパッケージを取得し、ビルドし、インストールするためのコマンドラインツールです。現在の go get
コマンドの前身にあたります。
goinstall
は、指定されたパッケージのソースコードをダウンロードし、依存関係を解決し、コンパイルして実行可能ファイル(コマンドの場合)やアーカイブファイル(ライブラリの場合)を生成し、適切な場所に配置する一連の処理を自動化していました。
make
コマンドと Makefile
Unix系のシステムでは、make
コマンドはプログラムのビルドプロセスを自動化するためのツールとして広く使われています。Makefile
というファイルに、ソースファイルのコンパイル順序や依存関係、実行するコマンドなどを記述します。
Go言語のプロジェクトでは、Go自身のビルドシステム(go build
, go install
など)が強力であるため、一般的なアプリケーション開発で Makefile
を直接使うことは少ないですが、プロジェクトのルートディレクトリに Makefile
を置いて、テストの実行、デプロイ、特定のビルドオプションの適用など、Goコマンドだけでは完結しない複雑なタスクを自動化するために利用されることがあります。
このコミットの文脈では、goinstall
内部で make
コマンドを呼び出してビルド処理を行っていたことが示唆されています。src/cmd/goinstall/make.go
というファイル名からも、make
コマンドとの連携が推測できます。
コマンドラインフラグ (-install
, -make
)
コマンドラインフラグは、プログラムの実行時にその動作を制御するために使用されるオプションです。Go言語の標準ライブラリには flag
パッケージがあり、これを使って簡単にコマンドラインフラグを定義・解析できます。
-make=true
: このフラグは、goinstall
に対して、指定されたパッケージをビルド(make)するように指示します。-install=false
: このフラグは、goinstall
に対して、ビルドされた成果物をインストールしないように指示します。通常、ビルドとインストールはセットで行われることが多いですが、このフラグを使うことでインストールのみをスキップできます。
このコミットの核心は、これら二つのフラグが同時に指定された場合の goinstall
の内部的な挙動の不整合を解消することにあります。
技術的詳細
このコミットは、goinstall
ツールの一部である src/cmd/goinstall/make.go
ファイル内の domake
関数に焦点を当てています。domake
関数は、Goパッケージのビルドプロセスを管理し、必要に応じて make
コマンドを呼び出す役割を担っていました。
変更前のコードでは、domake
関数内で cmd = append(cmd, "install")
という行が、条件なしに常に実行されていました。これは、goinstall
が make
コマンドを呼び出す際に、その引数として「install」というターゲットを無条件に追加していたことを意味します。結果として、ユーザーが -install=false
フラグを指定していても、make install
が実行されてしまい、意図しないインストールが発生していました。
このコミットによる修正は、以下の2つの主要な変更を導入しています。
-
-install
フラグの尊重:cmd = append(cmd, "install")
の行が、if *doInstall { ... }
という条件ブロックの中に移動されました。ここで*doInstall
は、コマンドラインで指定された-install
フラグの値(ブール値)を指します。これにより、ユーザーが-install=false
を指定した場合(つまり*doInstall
がfalse
の場合)は、「install」ターゲットがmake
コマンドの引数に追加されなくなります。 -
「何もすることがない」場合の早期リターン:
if len(cmd) <= 3 { return nil }
という新しい条件が追加されました。cmd
スライスは、make
コマンドとその引数を構築するために使用されます。makefile
(例:make
)dir
(例:-C /path/to/package
)pkg
(例:my/package
) これら3つの要素は常にcmd
に含まれるため、len(cmd)
が3以下であるということは、clean
やinstall
といった追加のターゲットが何も指定されていない状態を意味します。 この条件が追加されたことで、もしmake
コマンドに渡すべき実質的なターゲット(clean
やinstall
など)が一つもなければ、domake
関数は何もせずに早期にnil
(エラーなし) を返します。これは、不必要なmake
コマンドの実行を防ぎ、効率性を向上させます。
これらの変更により、goinstall
はユーザーの意図をより正確に反映し、-install=false
フラグが期待通りに機能するようになりました。
コアとなるコードの変更箇所
--- a/src/cmd/goinstall/make.go
+++ b/src/cmd/goinstall/make.go
@@ -29,7 +29,12 @@ func domake(dir, pkg string, tree *build.Tree, isCmd bool) (err error) {
} else if *clean {
cmd = append(cmd, "clean")
}
-\tcmd = append(cmd, "install")
+\tif *doInstall {
+\t\tcmd = append(cmd, "install")
+\t}\n+\tif len(cmd) <= 3 { // nothing to do
+\t\treturn nil
+\t}\n \treturn run(dir, makefile, cmd...)\n }
コアとなるコードの解説
変更された domake
関数は、Goパッケージのビルド処理において make
コマンドを呼び出すためのロジックを含んでいます。
-
変更前:
} else if *clean { cmd = append(cmd, "clean") } cmd = append(cmd, "install") // ここで無条件に "install" が追加されていた return run(dir, makefile, cmd...) }
このコードでは、
clean
フラグが設定されている場合はclean
ターゲットがcmd
スライスに追加され、その後、無条件にinstall
ターゲットがcmd
スライスに追加されていました。これにより、make
コマンドは常にinstall
ターゲットを実行しようとしていました。 -
変更後:
} else if *clean { cmd = append(cmd, "clean") } if *doInstall { // -install フラグが true の場合のみ "install" を追加 cmd = append(cmd, "install") } if len(cmd) <= 3 { // nothing to do return nil // 実行すべきターゲットがない場合は早期リターン } return run(dir, makefile, cmd...) }
-
if *doInstall { cmd = append(cmd, "install") }
: この行が追加されたことで、install
ターゲットがcmd
スライスに追加されるのは、*doInstall
(つまり-install
フラグ)がtrue
の場合のみとなりました。これにより、ユーザーが-install=false
を指定した場合、install
ターゲットはmake
コマンドに渡されなくなり、意図しないインストールが防止されます。 -
if len(cmd) <= 3 { // nothing to do return nil }
: この新しい条件は、cmd
スライスの要素数が3以下の場合にnil
を返して関数を終了させます。cmd
スライスには、最低限makefile
(例:make
)、dir
(例:-C /path/to/package
)、pkg
(例:my/package
) の3つの要素が含まれます。したがって、len(cmd)
が3以下ということは、clean
やinstall
といった追加のターゲットが何も指定されていない状態を意味します。このチェックにより、make
コマンドに実質的な作業がない場合に、不必要な外部コマンドの実行を避けることができます。
-
これらの変更により、goinstall
はより柔軟になり、ユーザーのコマンドラインフラグの指定を正確に反映するようになりました。
関連リンク
- Go言語の初期のツールに関する議論やドキュメントは、現在のGoの公式ドキュメントからは見つけにくい場合があります。当時のメーリングリストやGoのIssueトラッカーを検索すると、より詳細な情報が見つかる可能性があります。
- Goの
flag
パッケージのドキュメント: https://pkg.go.dev/flag go get
コマンドのドキュメント(goinstall
の後継): https://pkg.go.dev/cmd/go#hdr-Download_and_install_packages_and_dependencies
参考にした情報源リンク
- Go言語の公式ドキュメント (現在の
go get
コマンドの理解のため) - 一般的な
make
コマンドとMakefile
の概念 - コミットメッセージとコードの差分そのもの
- Go言語のコマンドラインフラグの一般的な実装パターン