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

[インデックス 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") という行が、条件なしに常に実行されていました。これは、goinstallmake コマンドを呼び出す際に、その引数として「install」というターゲットを無条件に追加していたことを意味します。結果として、ユーザーが -install=false フラグを指定していても、make install が実行されてしまい、意図しないインストールが発生していました。

このコミットによる修正は、以下の2つの主要な変更を導入しています。

  1. -install フラグの尊重: cmd = append(cmd, "install") の行が、if *doInstall { ... } という条件ブロックの中に移動されました。ここで *doInstall は、コマンドラインで指定された -install フラグの値(ブール値)を指します。これにより、ユーザーが -install=false を指定した場合(つまり *doInstallfalse の場合)は、「install」ターゲットが make コマンドの引数に追加されなくなります。

  2. 「何もすることがない」場合の早期リターン: if len(cmd) <= 3 { return nil } という新しい条件が追加されました。 cmd スライスは、make コマンドとその引数を構築するために使用されます。

    • makefile (例: make)
    • dir (例: -C /path/to/package)
    • pkg (例: my/package) これら3つの要素は常に cmd に含まれるため、len(cmd) が3以下であるということは、cleaninstall といった追加のターゲットが何も指定されていない状態を意味します。 この条件が追加されたことで、もし make コマンドに渡すべき実質的なターゲット(cleaninstall など)が一つもなければ、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 コマンドを呼び出すためのロジックを含んでいます。

  1. 変更前:

    	} else if *clean {
    		cmd = append(cmd, "clean")
    	}
    	cmd = append(cmd, "install") // ここで無条件に "install" が追加されていた
    	return run(dir, makefile, cmd...)
    }
    

    このコードでは、clean フラグが設定されている場合は clean ターゲットが cmd スライスに追加され、その後、無条件に install ターゲットが cmd スライスに追加されていました。これにより、make コマンドは常に install ターゲットを実行しようとしていました。

  2. 変更後:

    	} 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以下ということは、cleaninstall といった追加のターゲットが何も指定されていない状態を意味します。このチェックにより、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言語のコマンドラインフラグの一般的な実装パターン