[インデックス 11462] ファイルの概要
このコミットは、Go言語のビルドシステムにおいて、内部ツール(go-tool
)の配置ディレクトリの参照方法を修正するものです。具体的には、go-tool
がGOBIN
環境変数で指定されるディレクトリではなく、Goのインストールルートディレクトリ(GOROOT
)内のbin/go-tool
に配置されるべきであるという認識に基づき、関連するMakefileとGoのソースコードが更新されています。これにより、Goの内部ツールが常に正しい場所から参照され、ビルドや実行時の問題が解消されます。
コミット
commit 2d13e1f16e4b6709dc98f2cc45d717af8807005a
Author: Alex Brainman <alex.brainman@gmail.com>
Date: Mon Jan 30 16:43:28 2012 +1100
build: use correct go-tool directory location
R=golang-dev, rsc, cw, rsc
CC=golang-dev
https://golang.org/cl/5576070
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/2d13e1f16e4b6709dc98f2cc45d717af8807005a
元コミット内容
このコミットの元の内容は、「build: use correct go-tool directory location」であり、Goのビルドプロセスにおいて、go-tool
という内部ツールのディレクトリ位置を正しく使用するように修正することを目的としています。
変更の背景
Go言語のビルドシステムでは、コンパイラやリンカ、プロファイラなどの様々な内部ツールが使用されます。これらのツールは通常、Goのインストールディレクトリ(GOROOT
)内の特定の場所に配置され、Goコマンド(go build
, go run
など)から内部的に呼び出されます。
以前の実装では、これらの内部ツールがGOBIN
環境変数によって指定されるディレクトリ、またはbuild.Path[0].BinDir()
というGoのビルドパスから導出されるディレクトリに配置されると誤って想定されていました。しかし、GOBIN
はユーザーがGoの実行可能ファイルをインストールする場所を指定するためのものであり、Goの内部ツールが配置されるべき場所ではありません。また、build.Path[0].BinDir()
の挙動が、内部ツールの実際の配置場所と一致しないケースがあった可能性があります。
この不整合により、Goのビルドプロセスが内部ツールを見つけられず、ビルドエラーや予期せぬ動作が発生する可能性がありました。このコミットは、go-tool
が常にGOROOT/bin/go-tool
という固定された、かつ正しい場所に配置されるように参照パスを修正することで、この問題を解決することを目的としています。
前提知識の解説
- GOROOT: Go言語のインストールディレクトリを指す環境変数です。Goの標準ライブラリ、ツール、ソースコードなどがこのディレクトリ以下に配置されます。Goのビルドシステムは、
GOROOT
を基準として内部ツールやライブラリを探します。 - GOBIN: Goの実行可能ファイル(
go install
などでビルドされたバイナリ)がインストールされるディレクトリを指す環境変数です。ユーザーがGoのプログラムをビルドしてパスに追加したい場合などに設定します。GOBIN
はユーザーがビルドしたプログラムのためのものであり、Go言語自体が提供する内部ツールのためではありません。 - go-tool: Go言語のビルドシステムが内部的に使用する補助ツールの総称です。これには、
go tool compile
(コンパイラ)、go tool link
(リンカ)、go tool vet
(静的解析ツール)、go tool pprof
(プロファイラ)などが含まれます。これらのツールはGoのインストール時にGOROOT/pkg/tool/<GOOS_GOARCH>
(古いバージョンではGOROOT/bin/go-tool
)のようなディレクトリに配置されます。 - Makefile: ソフトウェアのビルドプロセスを自動化するためのツールである
make
が使用する設定ファイルです。このファイルには、ソースコードのコンパイル、リンク、インストールなどの手順が記述されます。Goのソースコード内でも、一部のツールのビルドやインストールにMakefileが使用されています。 go/build
パッケージ: Go言語の標準ライブラリの一部で、Goのビルド環境に関する情報(GOROOT
、GOPATH
、GOOS
、GOARCH
など)を提供するパッケージです。build.DefaultContext
は現在のビルドコンテキストを表し、build.Path
はGoのソースコードパスに関する情報を提供します。path/filepath
パッケージ: Go言語の標準ライブラリの一部で、ファイルパスの操作(結合、分割、正規化など)を行うための機能を提供するパッケージです。filepath.Join
は、複数のパス要素を結合して、オペレーティングシステムに適した形式のパスを生成します。
技術的詳細
このコミットの技術的な核心は、Goの内部ツール(go-tool
)の配置場所を特定し、そのパスを正しく参照するようにビルドスクリプトとGoのソースコードを修正することにあります。
-
Makefileの修正:
src/cmd/cov/Makefile
とsrc/cmd/prof/Makefile
において、install-default
ターゲットのcp
コマンドのパスが変更されています。- 変更前:
cp $(TARG) "$(GOBIN)"/go-tool/$(TARG)
- 変更後:
cp $(TARG) "$(GOROOT)"/bin/go-tool/$(TARG)
- この変更は、
cov
(カバレッジツール)とprof
(プロファイリングツール)のバイナリをインストールする際に、GOBIN
ではなくGOROOT/bin/go-tool
ディレクトリにコピーするように指示しています。これは、これらのツールがユーザーがインストールする一般的なGoプログラムではなく、Goシステムの一部として扱われるべきであることを明確にしています。
-
src/cmd/go/tool.go
の修正:- このファイルは、
go tool
コマンドの内部的なロジックを定義しています。 - 変更前:
toolBinToolDir = build.Path[0].BinDir() + "/go-tool"
- 変更後:
toolBinToolDir = filepath.Join(build.Path[0].Path, "bin", "go-tool")
- この変更は、
go tool
コマンドが内部ツールを探すためのベースディレクトリtoolBinToolDir
の計算方法を修正しています。build.Path[0].BinDir()
は、Goのビルドパスの最初の要素(通常はGOROOT
)のbin
ディレクトリを返しますが、その挙動が常にgo-tool
の実際の配置場所と一致するとは限りませんでした。filepath.Join(build.Path[0].Path, "bin", "go-tool")
は、build.Path[0].Path
(通常はGOROOT
)とbin
、go-tool
という文字列を結合して、オペレーティングシステムに依存しない形で正しいパスを構築します。これにより、go tool
コマンドが内部ツールを確実に発見できるようになります。filepath.Join
を使用することで、パス区切り文字(Windowsの\
やUnix系の/
)の違いを吸収し、クロスプラットフォームでの互換性を高めています。
- このファイルは、
これらの変更により、Goのビルドシステム全体でgo-tool
の場所に関する一貫性が保たれ、ビルドの信頼性が向上します。
コアとなるコードの変更箇所
src/cmd/cov/Makefile
--- a/src/cmd/cov/Makefile
+++ b/src/cmd/cov/Makefile
@@ -38,4 +38,4 @@ install-darwin: $(TARG)
@true
install-default: $(TARG)
- cp $(TARG) "$(GOBIN)"/go-tool/$(TARG)
+ cp $(TARG) "$(GOROOT)"/bin/go-tool/$(TARG)
src/cmd/go/tool.go
--- a/src/cmd/go/tool.go
+++ b/src/cmd/go/tool.go
@@ -9,6 +9,7 @@ import (
"go/build"
"os"
"os/exec"
+ "path/filepath"
"sort"
"strings"
)
@@ -28,7 +29,7 @@ For more about each tool command, see 'go tool command -h'.
var (
toolGoos = build.DefaultContext.GOOS
toolIsWindows = toolGoos == "windows"
- toolBinToolDir = build.Path[0].BinDir() + "/go-tool"
+ toolBinToolDir = filepath.Join(build.Path[0].Path, "bin", "go-tool")
)
const toolWindowsExtension = ".exe"
src/cmd/prof/Makefile
--- a/src/cmd/prof/Makefile
+++ b/src/cmd/prof/Makefile
@@ -32,7 +32,7 @@ install-darwin: $(TARG)
@true
install-default: $(TARG)
- cp $(TARG) "$(GOBIN)"/go-tool/$(TARG)
+ cp $(TARG) "$(GOROOT)"/bin/go-tool/$(TARG)
install-pprof: pprof
- cp pprof "$(GOBIN)"/go-tool/pprof
+ cp pprof "$(GOROOT)"/bin/go-tool/pprof
コアとなるコードの解説
Makefileの変更 (src/cmd/cov/Makefile
, src/cmd/prof/Makefile
)
これらのMakefileは、cov
(カバレッジツール)とprof
(プロファイリングツール)のビルドとインストールを担当しています。install-default
ターゲットは、ビルドされたバイナリをGoのシステムにインストールする際のパスを定義しています。
- 変更前:
cp $(TARG) "$(GOBIN)"/go-tool/$(TARG)
- これは、ビルドされたターゲット(
$(TARG)
)を、GOBIN
環境変数で指定されたディレクトリの下のgo-tool
サブディレクトリにコピーしようとしていました。しかし、前述の通り、GOBIN
はユーザーがインストールするGoプログラムのためのものであり、Goの内部ツールが配置されるべき場所ではありません。この誤ったパス指定が、ツールの発見失敗やビルドエラーの原因となる可能性がありました。
- これは、ビルドされたターゲット(
- 変更後:
cp $(TARG) "$(GOROOT)"/bin/go-tool/$(TARG)
- この修正により、ターゲットは
GOROOT
環境変数で指定されたGoのインストールルートディレクトリの下のbin/go-tool
サブディレクトリにコピーされるようになります。これは、Goの内部ツールが標準的に配置されるべき正しい場所であり、Goのビルドシステムがこれらのツールを期待する場所です。これにより、ツールのインストールパスがGoの内部的な期待と一致し、ビルドの信頼性が向上します。
- この修正により、ターゲットは
src/cmd/go/tool.go
の変更
このファイルは、go tool
コマンドがGoの内部ツールを実行する際のロジックを管理しています。特に、toolBinToolDir
変数は、go tool
コマンドが内部ツールバイナリを探すためのベースディレクトリを定義しています。
- 変更前:
toolBinToolDir = build.Path[0].BinDir() + "/go-tool"
build.Path[0]
は、Goのビルドパスの最初の要素(通常はGOROOT
)を表します。BinDir()
メソッドは、そのパスのbin
サブディレクトリを返します。したがって、この行はGOROOT/bin
に"/go-tool"
を文字列として連結していました。- このアプローチの問題点は、
BinDir()
の挙動がプラットフォームやGoのバージョンによって微妙に異なる可能性があったこと、また、単なる文字列連結ではパス区切り文字の自動調整が行われないため、クロスプラットフォームでの互換性に問題が生じる可能性があったことです。
- 変更後:
toolBinToolDir = filepath.Join(build.Path[0].Path, "bin", "go-tool")
- この修正では、
path/filepath
パッケージのJoin
関数が導入されています。 build.Path[0].Path
は、GOROOT
の絶対パスを文字列として返します。filepath.Join
は、引数として与えられた複数のパス要素を、現在のオペレーティングシステムに適したパス区切り文字を使用して結合し、正規化されたパスを生成します。例えば、Unix系システムでは/
、Windowsでは\
が使用されます。- この変更により、
toolBinToolDir
は常にGOROOT/bin/go-tool
という形式の正しい絶対パスを指すようになり、go tool
コマンドが内部ツールを確実に発見できるようになります。これは、パスの構築における堅牢性とクロスプラットフォーム互換性を大幅に向上させます。
- この修正では、
関連リンク
- Go言語の公式ドキュメント: https://golang.org/doc/
- Goの環境変数に関するドキュメント: https://golang.org/cmd/go/#hdr-Environment_variables (このコミットが作成された当時のドキュメントは異なる可能性がありますが、概念は共通です)
- Goの
build
パッケージに関するドキュメント: https://pkg.go.dev/go/build - Goの
path/filepath
パッケージに関するドキュメント: https://pkg.go.dev/path/filepath - このコミットが参照しているGoのChange List: https://golang.org/cl/5576070
参考にした情報源リンク
- 上記の関連リンクに加えて、Go言語のソースコード自体と、Goのビルドシステムに関する一般的な知識を参考にしました。
GOBIN
とGOROOT
の役割に関する一般的なGoのチュートリアルやドキュメント。Makefile
の基本的な構文とcp
コマンドの動作。- Goの
path/filepath.Join
関数の動作に関するGoのドキュメント。