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

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

このコミットは、Go言語のツール群である gofixgovet を、より簡潔な fixvet へと名称変更し、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言語の標準ツールである gofixgovet を、それぞれ fixvet という短い名前に変更し、go tool コマンドのサブコマンドとして統合することです。これにより、Goのツールエコシステムがより一貫性のあるものになります。コミットメッセージにもあるように、変更の大部分はファイルのリネームであり、実質的なコードロジックの変更は限定的です。yacc ツールもこの再編に含まれています。

変更の背景

Go言語の開発初期段階では、様々な補助ツールが個別に提供されていました。gofix はGoのAPI変更に対応して古いコードを自動的に修正するツールとして、govet はGoコードの静的解析を行い潜在的なバグを検出するツールとして、それぞれ独立したコマンドとして存在していました。

しかし、Goエコシステムの成長に伴い、これらのツールを go コマンドの統一されたインターフェースの下に置くことが望ましいという認識が高まりました。これは、ユーザーがGoのツールをより発見しやすく、使いやすくするためです。go tool サブコマンドの導入は、Goのビルドシステムとツール管理を整理し、将来的なツールの追加や管理を容易にするための重要なステップでした。このコミットは、その再編の一環として、特に利用頻度の高い fixvetgo 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 buildgo 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のビルドシステムとツールパスの管理方法の変更にあります。

  1. ファイルのリネーム:

    • src/cmd/gofix ディレクトリとその配下のすべてのファイルが src/cmd/fix にリネームされました。
    • src/cmd/govet ディレクトリとその配下のすべてのファイルが src/cmd/vet にリネームされました。
    • これに伴い、各ツールの doc.go ファイルの内容も更新され、新しいコマンド名 (fix, vet) と go tool を使用した呼び出し方法が明記されました。
    • main.go ファイル内のデバッグメッセージや一時ファイル名も、新しいツール名に合わせて変更されています。
  2. Makefileの更新:

    • src/cmd/Makefile および src/pkg/Makefile において、gofixgovet への参照が fixvet に更新されました。
    • 特に src/cmd/gofix/Makefilesrc/cmd/govet/Makefile は、それぞれ src/cmd/fix/Makefilesrc/cmd/vet/Makefile にリネームされ、ビルドターゲット名 (TARG) やインクルードするMakefile (Make.cmd から Make.tool) が変更されました。Make.tool は、go tool コマンドで実行されるツール向けの共通Makefileインクルードファイルであり、これらのツールが GOROOT/bin/go-tool にインストールされることを示唆しています。
  3. 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> にインストールされます。
    • この変更により、fixvet といった補助ツールが、主要な go コマンドとは別の専用ディレクトリに配置されるようになり、go tool コマンドを通じてのみ実行されるという意図が明確化されました。
  4. cmd/go/fix.go および cmd/go/vet.go の変更:

    • これらのファイルは、go fix および go vet コマンドのラッパーとして機能します。
    • UsageLineLong フィールドが更新され、ユーザーに対して go tool fixgo tool vet を直接実行するよう促すメッセージが追加されました。これは、go fixgo vet が内部的に go tool fixgo 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/binGOPATH/bin に配置し、Goの公式ツールは go tool を介して利用するという、より整理されたワークフローが確立されました。

src/cmd/fix/doc.go は、fix コマンドの新しい公式ドキュメントとして機能します。このドキュメントは、fix の目的、使用方法、オプション、および go tool fix として実行することの重要性を明確に説明しています。特に、go tool fix -? を実行することで利用可能な修正の一覧が表示されることや、バージョン管理システムと組み合わせて変更を検査することの推奨事項は、ユーザーが fix を安全かつ効果的に利用するための重要な情報です。

関連リンク

参考にした情報源リンク

  • 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 tool design", "Go gofix govet rename" など。
    • 特に、Go 1のリリースに向けたツールの整理に関する議論は、Goのメーリングリストアーカイブやデザインドキュメントに多く見られます。