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

[インデックス 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 ファイルなど)が配置されるべきパスを示します。しかし、ローカルインポートされたパッケージは、通常、GOPATHGOROOT のような標準的なインストールパスにはインストールされません。これらは、現在のプロジェクトのコンテキスト内で一時的にビルドされ、実行可能ファイルにリンクされることがほとんどです。

したがって、ローカルインポートに対して Target パスが設定されていると、ビルドツールやIDEが誤った情報を解釈したり、予期せぬ動作を引き起こしたりする可能性がありました。このコミットは、この不整合を解消し、go/build パッケージがより正確なビルド情報を提供するようにするための修正です。

前提知識の解説

Go言語のパッケージとインポート

Go言語では、コードは「パッケージ」という単位で整理されます。パッケージは、関連する機能を持つGoソースファイルの集まりです。他のパッケージの機能を利用するには、import ステートメントを使用します。

インポートパスには大きく分けて2種類あります。

  1. 標準ライブラリ/外部モジュール: fmtnet/http のような標準ライブラリ、または github.com/gin-gonic/gin のような外部モジュールは、通常、絶対パスまたはモジュールパスで指定されます。これらのパッケージは、GOPATH や Go Modules のキャッシュディレクトリにインストールされ、対応する Target パスを持つことができます。
  2. ローカルインポート: 同じプロジェクト内の別のパッケージを参照する場合、相対パスでインポートすることがあります。例えば、import "./subpackage" のように記述します。これらのパッケージは、通常、独立してインストールされることを意図しておらず、現在のビルドコンテキスト内でのみ意味を持ちます。

go/build パッケージ

go/build パッケージは、Goのソースコードを解析し、ビルドに必要な情報を抽出するためのGo標準ライブラリです。go build コマンドや、GoのIDE、その他の開発ツールは、内部的にこのパッケージを利用して、ソースファイルの発見、パッケージの依存関係の解決、ビルドタグの処理などを行います。

go/build.Context 構造体は、ビルド環境に関する情報(GOROOTGOPATH、ビルドタグなど)を保持し、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のビルドシステム全体の堅牢性を高めることに貢献しています。

関連リンク

参考にした情報源リンク