[インデックス 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言語のコマンドラインフラグの一般的な実装パターン