[インデックス 12650] ファイルの概要
このコミットは、Go言語の標準ライブラリである go/build
パッケージにおける挙動の修正に関するものです。具体的には、ローカルインポート(相対パスで指定されるパッケージ)の場合に、Package
構造体の Target
フィールドが誤って設定されるのを防ぐための変更が加えられました。これにより、ローカルインポートされたパッケージにはインストールパスが存在しないという事実が正確に反映されるようになります。
コミット
commit 20760e43356472f7c596ab2632fc069231af3ba0
Author: Russ Cox <rsc@golang.org>
Date: Thu Mar 15 15:08:57 2012 -0400
go/build: do not report Target for local imports
R=golang-dev, gri
CC=golang-dev
https://golang.org/cl/5820064
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/20760e43356472f7c596ab2632fc069231af3ba0
元コミット内容
go/build: do not report Target for local imports
R=golang-dev, gri
CC=golang-dev
https://golang.org/cl/5820064
変更の背景
Go言語のビルドシステムにおいて、パッケージのインポートは非常に重要な概念です。go/build
パッケージは、Goのソースコードを解析し、パッケージの依存関係を解決し、ビルドに必要な情報を収集するための低レベルな機能を提供します。
このコミットが行われた背景には、go/build
パッケージがローカルインポート(例えば、./mypackage
のように相対パスで指定されるインポート)を処理する際の Package
構造体の Target
フィールドの扱いに不整合があったことが挙げられます。
Target
フィールドは通常、コンパイルされたパッケージのアーカイブファイル(.a
ファイルなど)が配置されるべきパスを示します。しかし、ローカルインポートされたパッケージは、通常、GOPATH
や GOROOT
のような標準的なインストールパスにはインストールされません。これらは、現在のプロジェクトのコンテキスト内で一時的にビルドされ、実行可能ファイルにリンクされることがほとんどです。
したがって、ローカルインポートに対して Target
パスが設定されていると、ビルドツールやIDEが誤った情報を解釈したり、予期せぬ動作を引き起こしたりする可能性がありました。このコミットは、この不整合を解消し、go/build
パッケージがより正確なビルド情報を提供するようにするための修正です。
前提知識の解説
Go言語のパッケージとインポート
Go言語では、コードは「パッケージ」という単位で整理されます。パッケージは、関連する機能を持つGoソースファイルの集まりです。他のパッケージの機能を利用するには、import
ステートメントを使用します。
インポートパスには大きく分けて2種類あります。
- 標準ライブラリ/外部モジュール:
fmt
やnet/http
のような標準ライブラリ、またはgithub.com/gin-gonic/gin
のような外部モジュールは、通常、絶対パスまたはモジュールパスで指定されます。これらのパッケージは、GOPATH
や Go Modules のキャッシュディレクトリにインストールされ、対応するTarget
パスを持つことができます。 - ローカルインポート: 同じプロジェクト内の別のパッケージを参照する場合、相対パスでインポートすることがあります。例えば、
import "./subpackage"
のように記述します。これらのパッケージは、通常、独立してインストールされることを意図しておらず、現在のビルドコンテキスト内でのみ意味を持ちます。
go/build
パッケージ
go/build
パッケージは、Goのソースコードを解析し、ビルドに必要な情報を抽出するためのGo標準ライブラリです。go build
コマンドや、GoのIDE、その他の開発ツールは、内部的にこのパッケージを利用して、ソースファイルの発見、パッケージの依存関係の解決、ビルドタグの処理などを行います。
go/build.Context
構造体は、ビルド環境に関する情報(GOROOT
、GOPATH
、ビルドタグなど)を保持し、Import
メソッドは指定されたパスからパッケージ情報を読み込みます。
go/build.Package
構造体
go/build.Package
構造体は、Goのパッケージに関する詳細な情報(ソースファイルのリスト、依存関係、ビルドタグ、コンパイル済みアーカイブのパスなど)を保持します。この構造体には、以下のようなフィールドが含まれます。
Dir
: パッケージのルートディレクトリの絶対パス。ImportPath
: パッケージのインポートパス(例:fmt
,github.com/user/repo/pkg
)。Name
: パッケージ名。GoFiles
: パッケージ内のGoソースファイルのリスト。Imports
: このパッケージがインポートしている他のパッケージのリスト。Target
: コンパイルされたパッケージのアーカイブファイル(.a
または.o
)が配置されるべきパス。このフィールドが今回の変更の焦点です。
技術的詳細
このコミットは、go/build
パッケージの Context.Import
メソッドの内部ロジックに焦点を当てています。Import
メソッドは、与えられたインポートパスとソースディレクトリに基づいて、Package
構造体を構築します。
変更前の挙動では、IsLocalImport(path)
が true
(つまり、インポートパスがローカルインポートである)の場合でも、pkga
変数(最終的に Package.Target
に割り当てられる可能性のある値)が初期化されずに、以前の値やデフォルト値が残ってしまう可能性がありました。
ローカルインポートは、通常、go install
コマンドによって pkg
ディレクトリにインストールされることを意図していません。それらは、現在のビルドプロセスの一部としてコンパイルされ、最終的な実行可能ファイルに直接リンクされます。したがって、ローカルインポートされたパッケージには、永続的な「インストールされたパス」という概念は存在しません。
この修正は、この概念的な違いをコードに反映させるものです。IsLocalImport(path)
が true
の場合、pkga
を明示的に空文字列 ""
に設定することで、Package.Target
フィールドがローカルインポートに対しては空になることを保証します。これにより、go/build
パッケージの出力が、Goのビルドシステムの実際の動作とより一致するようになります。
コアとなるコードの変更箇所
diff --git a/src/pkg/go/build/build.go b/src/pkg/go/build/build.go
index ba3bfdf9a0..bf9801c802 100644
--- a/src/pkg/go/build/build.go
+++ b/src/pkg/go/build/build.go
@@ -363,6 +363,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
binaryOnly := false
if IsLocalImport(path) {
+ pkga = "" // local imports have no installed path
if srcDir == "" {
return p, fmt.Errorf("import %q: import relative to unknown directory", path)
}
コアとなるコードの解説
変更は src/pkg/go/build/build.go
ファイルの Context.Import
メソッド内で行われています。
元のコードでは、IsLocalImport(path)
が true
の場合、つまりインポートパスが ./
や ../
で始まるローカルインポートであると判断された場合、その後の処理に進みます。
追加された行は以下の通りです。
pkga = "" // local imports have no installed path
この行は、IsLocalImport(path)
が true
と評価された直後に実行されます。pkga
変数は、最終的に Package
構造体の Target
フィールドに割り当てられる文字列です。この修正により、ローカルインポートの場合には、pkga
が明示的に空文字列に設定されます。
コメント // local imports have no installed path
が示すように、この変更の意図は、ローカルインポートされたパッケージには、GOPATH/pkg
のような場所にインストールされるべき「インストールパス」という概念が存在しないことを明確にすることです。これにより、Package.Target
フィールドが、ローカルインポートに対しては常に空文字列となり、ビルドツールがこの情報を正しく解釈できるようになります。
この修正は、go/build
パッケージが提供するパッケージ情報の正確性を向上させ、Goのビルドシステム全体の堅牢性を高めることに貢献しています。
関連リンク
- Go CL 5820064: https://golang.org/cl/5820064
参考にした情報源リンク
- Go言語の公式ドキュメント (go/buildパッケージ): https://pkg.go.dev/go/build
- Go言語のパッケージとモジュールに関するドキュメント (Go Modules以前のGOPATHに関する情報も含む): https://go.dev/doc/ (一般的なGoのドキュメント)
- Go言語のソースコード (GitHub): https://github.com/golang/go
- Go言語のコミット履歴 (GitHub): https://github.com/golang/go/commits/master
- Go言語のコードレビューシステム (Gerrit): https://go-review.googlesource.com/ (CLリンクの元)