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

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

コミット

  • コミットハッシュ: 0724e5cefe92f9f4fd52101e3a7a25299a2b7f63
  • 作者: Mikio Hara mikioh.mikioh@gmail.com
  • コミット日時: 2012年2月15日 23:52:07 +0900

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

https://github.com/golang/go/commit/0724e5cefe92f9f4fd52101e3a7a25299a2b7f63

元コミット内容

build: fix clean.bash

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5672052

変更の背景

このコミットは、Go言語のビルドシステムにおける clean.bash スクリプトの修正を目的としています。clean.bash は、Goのソースツリーからビルドによって生成されたファイルやディレクトリを削除し、クリーンな状態に戻すためのスクリプトです。

以前の clean.bash スクリプトでは、go tool dist コマンドが生成する環境変数(特に $GOTOOLDIR)を適切に利用できていませんでした。具体的には、../bin/tool/dist という相対パスで dist ツールを参照していましたが、これはビルド環境や実行コンテキストによっては正しく解決できない可能性がありました。

この問題は、Goのビルドプロセスが進化する中で、ツールの配置や環境変数の設定方法が変更されたことに起因していると考えられます。go tool dist env コマンドは、Goのビルドツールが使用する環境変数を標準出力に出力する機能を提供しており、これを eval コマンドと組み合わせることで、スクリプト内でこれらの環境変数を確実に設定できます。

このコミットの目的は、clean.bashdist ツールやその他のビルド関連パスを確実に特定できるようにし、クリーンアップ処理の堅牢性を向上させることにあります。これにより、異なる環境やGoのバージョンアップ後でも、clean.bash が期待通りに動作することが保証されます。

前提知識の解説

Go言語のビルドシステム

Go言語は、そのソースコードからコンパイラ、リンカ、標準ライブラリ、各種ツール(go コマンド自体や dist ツールなど)をビルドする独自のシステムを持っています。このビルドプロセスは、通常、Goのソースツリーのルートにある all.bashmake.bash (Windowsでは make.bat) といったスクリプトによって開始されます。

clean.bash

clean.bash は、Goのソースツリーをクリーンアップするためのシェルスクリプトです。具体的には、go installgo buildgo test などによって生成されたバイナリファイル、オブジェクトファイル、キャッシュなどを削除し、ソースツリーを初期状態に近い形に戻します。これは、新しいビルドを開始する前や、開発環境をリフレッシュする際によく使用されます。

go tool dist

go tool dist は、Goのビルドシステムの一部である内部ツールです。このツールは、Goのソースツリーのビルドプロセスを管理するために使用されます。 特に重要なのが go tool dist env サブコマンドです。これは、Goのビルドに必要な環境変数(例: GOROOT, GOBIN, GOTOOLDIR など)をシェルスクリプトが eval できる形式で出力します。これにより、スクリプトはGoのビルド環境を正確に設定できます。

GOBINGOTOOLDIR

  • GOBIN: Goのコマンド(go コマンド自体や gofmt など)がインストールされるディレクトリを指します。
  • GOTOOLDIR: Goの内部ツール(distlinkcompile など)が配置されるディレクトリを指します。これらのツールは通常、直接ユーザーが実行するものではなく、go コマンドによって内部的に呼び出されます。

eval $(command)

シェルスクリプトにおける eval $(command) は、command の実行結果を現在のシェルのコマンドとして評価・実行する構文です。 このコミットの文脈では、eval $(go tool dist env)go tool dist env が出力する環境変数の設定コマンド(例: export GOROOT=/path/to/go; export GOBIN=/path/to/go/bin; ...)を現在のシェルで実行し、それらの環境変数をスクリプト内で利用可能にする役割を果たします。

技術的詳細

このコミットの技術的な変更点は、clean.bash スクリプトがGoのビルドツールへのパスを特定する方法を改善したことに集約されます。

変更前

変更前のスクリプトでは、dist ツールへのパスを ../bin/tool/dist という相対パスで直接指定していました。

-if [ ! -x ../bin/tool/dist ]; then
-	echo 'cannot find ../bin/tool/dist; nothing to clean' >&2
-	exit 1
-fi
...
-eval $(../bin/tool/dist env)
...
-../bin/tool/dist clean

このアプローチにはいくつかの問題がありました。

  1. パスの堅牢性: ../bin/tool/dist という相対パスは、clean.bash が実行されるカレントディレクトリに依存します。もしスクリプトがGoのソースツリーの異なる場所から実行された場合、このパスは無効になる可能性があります。
  2. 環境変数との不整合: Goのビルドシステムは、go tool dist env を通じて GOTOOLDIR のような環境変数を設定し、ツールの場所を抽象化します。相対パスの直接指定は、この抽象化の恩恵を受けられず、将来的なパス変更に対して脆弱でした。

変更後

変更後のスクリプトでは、go tool dist env コマンドを利用して、Goのビルド環境変数をスクリプトにロードするように変更されました。

+eval $(go tool dist env)
+
+if [ ! -x $GOTOOLDIR/dist ]; then
+	echo 'cannot find $GOTOOLDIR/dist; nothing to clean' >&2
+	exit 1
+fi
...
 "$GOBIN/go" clean -i std
+$GOTOOLDIR/dist clean

具体的な変更点は以下の通りです。

  1. eval $(go tool dist env) の追加: スクリプトの冒頭で eval $(go tool dist env) が実行されるようになりました。これにより、go tool dist env が出力する GOTOOLDIRGOBIN などの環境変数が現在のシェルセッションに設定されます。
  2. $GOTOOLDIR の利用: dist ツールへの参照が、ハードコードされた相対パス ../bin/tool/dist から、環境変数 $GOTOOLDIR を利用した $GOTOOLDIR/dist に変更されました。これにより、dist ツールの実際のパスがどこにあっても、go tool dist env が提供する正しいパスが使用されるようになります。
  3. GOBIN の利用: "$GOBIN/go" clean -i std の行は変更されていませんが、eval $(go tool dist env) によって GOBIN が確実に設定されるため、go コマンドの呼び出しもより堅牢になります。

この変更により、clean.bash はGoのビルドシステムが提供する標準的な方法でツールのパスを解決するようになり、スクリプトの堅牢性と移植性が大幅に向上しました。

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

--- a/src/clean.bash
+++ b/src/clean.bash
@@ -5,11 +5,12 @@
 
 set -e
 
-if [ ! -x ../bin/tool/dist ]; then
-	echo 'cannot find ../bin/tool/dist; nothing to clean' >&2
+eval $(go tool dist env)
+
+if [ ! -x $GOTOOLDIR/dist ]; then
+	echo 'cannot find $GOTOOLDIR/dist; nothing to clean' >&2
 	exit 1
 fi
 
-"$GOBIN/go" clean -i std
-../bin/tool/dist clean
+$GOTOOLDIR/dist clean

コアとなるコードの解説

  • -if [ ! -x ../bin/tool/dist ]; then
    • 変更前のコードで、../bin/tool/dist という相対パスで dist ツールが存在し、実行可能であるかを確認していました。この相対パスは、clean.bash が実行されるカレントディレクトリに依存するため、問題がありました。
  • +eval $(go tool dist env)
    • この行が新しく追加されました。go tool dist env コマンドを実行し、その出力(Goのビルドに必要な環境変数の設定コマンド群)を eval コマンドによって現在のシェルで評価・実行します。これにより、GOTOOLDIRGOBIN などの環境変数がスクリプト内で利用可能になります。
  • +if [ ! -x $GOTOOLDIR/dist ]; then
    • eval $(go tool dist env) によって設定された $GOTOOLDIR 環境変数を使用して、dist ツールの存在と実行可能性をチェックするように変更されました。これにより、dist ツールの実際のパスがどこにあっても、Goのビルドシステムが提供する正しいパスが使用されるようになります。
  • -../bin/tool/dist clean
    • 変更前のコードで、相対パス ../bin/tool/dist を使って dist clean コマンドを実行していました。
  • +$GOTOOLDIR/dist clean
    • eval $(go tool dist env) によって設定された $GOTOOLDIR 環境変数を使用して、dist clean コマンドを実行するように変更されました。これにより、clean.bash がより堅牢になり、Goのビルドシステムが管理するツールのパス変更にも対応できるようになりました。

この変更は、Goのビルドスクリプトが、ハードコードされた相対パスではなく、Goのツールチェーンが提供する標準的な環境変数を利用して、ツールの場所を動的に解決するようになったことを示しています。これは、ビルドシステムの保守性と移植性を向上させる上で重要な改善です。

関連リンク

  • Go Change-Id: I2222222222222222222222222222222222222222 (これはコミットメッセージに記載されている https://golang.org/cl/5672052 のChange-Idに対応するものです。GoのコードレビューシステムGerritのリンクです。)

参考にした情報源リンク

  • Go言語の公式ドキュメント (Goのビルドシステムやツールの詳細について)
  • シェルスクリプトの eval コマンドに関する一般的な情報
  • Goのソースコードリポジトリ (特に src/clean.bash の履歴)
  • GoのGerritコードレビューシステム (コミットメッセージに記載されているCLリンク)
    • https://golang.org/cl/5672052 (このコミットのGerritレビューページ)
    • (注: 2012年の古いCLのため、現在のGerritシステムでは直接アクセスできない可能性がありますが、当時のレビュープロセスを示すものです。)