[インデックス 11454] ファイルの概要
このコミットは、Go言語のツール群である gofix と govet を、より簡潔な fix と vet へと名称変更し、go tool コマンド体系の下に再配置する大規模な変更を伴います。これにより、Goのビルドシステムとツール管理がより整理され、ユーザーエクスペリエンスが向上します。
コミット
commit 71d83b72efe3e20ce6b0ab96226873074afe24be
Author: Rob Pike <r@golang.org>
Date: Sun Jan 29 11:07:25 2012 -0800
cmd/go: add go tools to rearrangement
fix, vet
yacc is also fixed (it was wrong before)
All that's left is the commands used during compilation
This looks like a huge CL, but it's almost all file renames.
The action is in cmd/go/pkg.go, the Makefiles, and .../doc.go.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5595044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/71d83b72efe3e20ce6b0ab96226873074afe24be
元コミット内容
このコミットの主な目的は、Go言語の標準ツールである gofix と govet を、それぞれ fix と vet という短い名前に変更し、go tool コマンドのサブコマンドとして統合することです。これにより、Goのツールエコシステムがより一貫性のあるものになります。コミットメッセージにもあるように、変更の大部分はファイルのリネームであり、実質的なコードロジックの変更は限定的です。yacc ツールもこの再編に含まれています。
変更の背景
Go言語の開発初期段階では、様々な補助ツールが個別に提供されていました。gofix はGoのAPI変更に対応して古いコードを自動的に修正するツールとして、govet はGoコードの静的解析を行い潜在的なバグを検出するツールとして、それぞれ独立したコマンドとして存在していました。
しかし、Goエコシステムの成長に伴い、これらのツールを go コマンドの統一されたインターフェースの下に置くことが望ましいという認識が高まりました。これは、ユーザーがGoのツールをより発見しやすく、使いやすくするためです。go tool サブコマンドの導入は、Goのビルドシステムとツール管理を整理し、将来的なツールの追加や管理を容易にするための重要なステップでした。このコミットは、その再編の一環として、特に利用頻度の高い fix と vet を go tool の傘下に収めることを目的としています。
前提知識の解説
gofix/fix: Go言語のバージョンアップに伴うAPIの変更や言語仕様の変更に対応するため、既存のGoソースコードを自動的に修正するツールです。例えば、Go 1からGo 1.1への移行時に、特定の関数のシグネチャが変更された場合などに、gofixを実行することでコードを新しいAPIに適合させることができました。このコミット以降はgo tool fixとして利用されます。govet/vet: Go言語の静的解析ツールです。コードを実行せずに、潜在的なバグや疑わしいコードパターン(例:Printfのフォーマット文字列と引数の不一致、到達不能なコードなど)を検出します。開発者がコードレビューやテストの前に問題を特定するのに役立ちます。このコミット以降はgo tool vetとして利用されます。go tool: Go 1.0以降に導入された、Go言語の補助ツールを実行するためのコマンドです。go buildやgo runといった主要なコマンドとは異なり、go toolはコンパイラ、リンカ、アセンブラ、プロファイラ、静的解析ツールなど、Goの内部的な開発ツールや、あまり頻繁には使われないが開発に役立つツール群へのアクセスを提供します。これにより、Goのツール群がgoコマンドの下に一元的に管理され、ユーザーはgo tool <toolname>の形式でこれらのツールを実行できるようになりました。GOROOT: Goのインストールディレクトリを指す環境変数です。Goの標準ライブラリ、ツール、ドキュメントなどがこのディレクトリ以下に配置されます。GOROOT/bin/go-tool: このコミットで導入された、go toolコマンドで実行される補助ツールがインストールされる新しいディレクトリパスです。これにより、主要なgoコマンド(go build,go runなど)がインストールされるGOROOT/binとは別に、補助ツールが管理されるようになります。
技術的詳細
このコミットの技術的な核心は、Goのビルドシステムとツールパスの管理方法の変更にあります。
-
ファイルのリネーム:
src/cmd/gofixディレクトリとその配下のすべてのファイルがsrc/cmd/fixにリネームされました。src/cmd/govetディレクトリとその配下のすべてのファイルがsrc/cmd/vetにリネームされました。- これに伴い、各ツールの
doc.goファイルの内容も更新され、新しいコマンド名 (fix,vet) とgo toolを使用した呼び出し方法が明記されました。 main.goファイル内のデバッグメッセージや一時ファイル名も、新しいツール名に合わせて変更されています。
-
Makefileの更新:
src/cmd/Makefileおよびsrc/pkg/Makefileにおいて、gofixとgovetへの参照がfixとvetに更新されました。- 特に
src/cmd/gofix/Makefileとsrc/cmd/govet/Makefileは、それぞれsrc/cmd/fix/Makefileとsrc/cmd/vet/Makefileにリネームされ、ビルドターゲット名 (TARG) やインクルードするMakefile (Make.cmdからMake.tool) が変更されました。Make.toolは、go toolコマンドで実行されるツール向けの共通Makefileインクルードファイルであり、これらのツールがGOROOT/bin/go-toolにインストールされることを示唆しています。
-
cmd/go/pkg.goの変更:- このファイルは
goコマンドがパッケージをスキャンし、ビルドターゲットを決定するロジックを含んでいます。 isGoToolという新しいマップが導入されました。このマップは、go toolコマンドで実行されるべきツール(cmd/fix,cmd/vet,cmd/yacc)のインポートパスを保持します。scanPackage関数内で、パッケージのターゲットパスを決定するロジックが変更されました。- もしパッケージが
mainパッケージであり、かつGOROOT内のツールであり、isGoToolマップに登録されている場合、そのツールのインストールパスはGOROOT/bin/go-tool/<toolname>となります。 - それ以外の場合(通常の実行可能ファイルなど)は、引き続き
GOROOT/bin/<toolname>またはGOPATH/bin/<toolname>にインストールされます。
- もしパッケージが
- この変更により、
fixやvetといった補助ツールが、主要なgoコマンドとは別の専用ディレクトリに配置されるようになり、go toolコマンドを通じてのみ実行されるという意図が明確化されました。
- このファイルは
-
cmd/go/fix.goおよびcmd/go/vet.goの変更:- これらのファイルは、
go fixおよびgo vetコマンドのラッパーとして機能します。 UsageLineやLongフィールドが更新され、ユーザーに対してgo tool fixやgo tool vetを直接実行するよう促すメッセージが追加されました。これは、go fixやgo vetが内部的にgo tool fixやgo tool vetを呼び出すことを示唆しており、ユーザーが直接go toolを使うことで、より詳細なオプションを渡せることを示しています。
- これらのファイルは、
これらの変更は、Goのビルドシステムとツールの配布方法における重要な構造的改善であり、Go 1.0のリリースに向けた最終的な整理の一環として行われました。
コアとなるコードの変更箇所
このコミットのコアとなる変更は、src/cmd/go/pkg.go における isGoTool マップの導入と、それに基づくツールのインストールパス決定ロジックの変更です。
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -224,6 +224,14 @@ Loop:
return string(b)
}
+// isGoTool is the list of directories for Go programs that are installed in
+// $GOROOT/bin/go-tool.
+var isGoTool = map[string]bool{
+ "cmd/fix": true,
+ "cmd/vet": true,
+ "cmd/yacc": true,
+}
+
func scanPackage(ctxt *build.Context, t *build.Tree, arg, importPath, dir string, stk *importStack) *Package {
// Read the files in the directory to learn the structure
// of the package.
@@ -262,7 +270,11 @@ func scanPackage(ctxt *build.Context, t *build.Tree, arg, importPath, dir string
if info.Package == "main" {
_, elem := filepath.Split(importPath)
- p.target = filepath.Join(t.BinDir(), elem)
+ if t.Goroot && isGoTool[p.ImportPath] {
+ p.target = filepath.Join(t.Path, "bin/go-tool", elem)
+ } else {
+ p.target = filepath.Join(t.BinDir(), elem)
+ }
if ctxt.GOOS == "windows" {
p.target += ".exe"
}
また、src/cmd/fix/doc.go の新規追加も重要です。これは fix コマンドの公式ドキュメントとなり、go tool fix としての利用方法を明確に示しています。
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Fix finds Go programs that use old APIs and rewrites them to use
newer ones. After you update to a new Go release, fix helps make
the necessary changes to your programs.
Usage:
go tool fix [-r name,...] [path ...]
Without an explicit path, fix reads standard input and writes the
result to standard output.
If the named path is a file, fix rewrites the named files in place.
If the named path is a directory, fix rewrites all .go files in that
directory tree. When fix rewrites a file, it prints a line to standard
error giving the name of the file and the rewrite applied.
If the -diff flag is set, no files are rewritten. Instead fix prints
the differences a rewrite would introduce.
The -r flag restricts the set of rewrites considered to those in the
named list. By default fix considers all known rewrites. Fix's
rewrites are idempotent, so that it is safe to apply fix to updated
or partially updated code even without using the -r flag.
Fix prints the full list of fixes it can apply in its help output;
to see them, run go tool fix -?.
Fix does not make backup copies of the files that it edits.
Instead, use a version control system's ``diff'' functionality to inspect
the changes that fix makes before committing them.
*/
package documentation
コアとなるコードの解説
src/cmd/go/pkg.go の変更は、Goのビルドシステムが実行可能ファイルをどこに配置するかを制御する中心的なロジックに影響を与えます。
isGoToolマップ: このマップは、Goのソースツリー内でcmd/fix,cmd/vet,cmd/yaccといった特定のインポートパスを持つパッケージが、通常の実行可能ファイルとは異なる特別なツールとして扱われるべきであることを示します。- ターゲットパスの決定ロジック:
scanPackage関数内で、ビルドされるパッケージがmainパッケージ(つまり実行可能ファイル)である場合に、そのインストール先パス (p.target) が決定されます。t.Gorootは、現在処理しているパッケージがGOROOT内にあるかどうかを示します。isGoTool[p.ImportPath]は、そのパッケージがgo toolコマンドで実行されるべき補助ツールであるかどうかをチェックします。- もし両方の条件が真であれば、ツールは
GOROOT/bin/go-tool/<toolname>にインストールされます。これは、これらのツールがGoの内部的な補助ツールであり、通常のユーザーが直接パスを通して実行するのではなく、go toolコマンドを介して実行することを意図しているためです。 - それ以外の場合、実行可能ファイルは
t.BinDir()(通常はGOROOT/binまたはGOPATH/bin) にインストールされます。
この変更により、Goのツール群の構造が明確化され、主要な go コマンドと補助ツールが論理的に分離されました。ユーザーは go build でビルドした自身のプログラムを GOROOT/bin や GOPATH/bin に配置し、Goの公式ツールは go tool を介して利用するという、より整理されたワークフローが確立されました。
src/cmd/fix/doc.go は、fix コマンドの新しい公式ドキュメントとして機能します。このドキュメントは、fix の目的、使用方法、オプション、および go tool fix として実行することの重要性を明確に説明しています。特に、go tool fix -? を実行することで利用可能な修正の一覧が表示されることや、バージョン管理システムと組み合わせて変更を検査することの推奨事項は、ユーザーが fix を安全かつ効果的に利用するための重要な情報です。
関連リンク
- Go言語の公式ドキュメント: https://go.dev/doc/
go toolコマンドに関する情報: https://go.dev/cmd/go/#hdr-Go_tool_commandsfixコマンドのドキュメント: https://go.dev/cmd/fix/vetコマンドのドキュメント: https://go.dev/cmd/vet/
参考にした情報源リンク
- Go言語のコミット履歴 (GitHub): https://github.com/golang/go/commits/master
- Go Code Review (Gerrit): https://go-review.googlesource.com/ (コミットメッセージに記載されている
https://golang.org/cl/5595044はGerritの変更リストへのリンクです) - Go言語のIssue Tracker: https://go.dev/issue
- Go言語のブログ (過去のリリース情報やツールの紹介): https://go.dev/blog/
- Go 1 Release Notes (
go toolの導入など): https://go.dev/doc/go1 - Goのツールに関する議論や設計ドキュメント (Goのメーリングリストやデザインドキュメント): 検索キーワード "Go
go tooldesign", "Gogofixgovetrename" など。- 特に、Go 1のリリースに向けたツールの整理に関する議論は、Goのメーリングリストアーカイブやデザインドキュメントに多く見られます。