[インデックス 12260] ファイルの概要
このコミットは、Go言語の標準ライブラリgo/build
パッケージ内のコードの再配置を目的としています。具体的には、src/pkg/go/build/dir.go
ファイルに存在していたパッケージスキャンおよびビルド制約関連のロジックが、src/pkg/go/build/build.go
ファイルに移動されました。また、src/pkg/go/build/path.go
からも一部のコードが移動されています。この変更は、機能的な変更を伴わず、純粋なコードの移動(コピー&ペースト)であり、今後のコードレビューにおける差分を小さくすることを意図しています。
コミット
commit 38a03de6a16f3c7489fdc425eba607f8e7f08676
Author: Russ Cox <rsc@golang.org>
Date: Tue Feb 28 16:34:41 2012 -0500
go/build: move code around
Only copy+paste here.
Will make next code review's diffs a bit smaller.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5704050
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/38a03de6a16f3c7489fdc425eba607f8e7f08676
元コミット内容
go/build: move code around
Only copy+paste here.
Will make next code review's diffs a bit smaller.
変更の背景
このコミットの主な背景は、コードベースの整理と、将来の機能追加や変更を容易にすることにあります。コミットメッセージに「Only copy+paste here. Will make next code review's diffs a bit smaller.」と明記されている通り、この変更自体は機能的な影響を一切持ちません。
Go言語の開発では、大規模な変更を行う際に、まずコードの再編成(リファクタリング)を行い、その後に実際の機能変更を適用するというプラクティスがしばしば見られます。これにより、機能変更のコミットが純粋にその機能に焦点を当てたものとなり、コードの移動による大量の差分に埋もれることなく、レビューがしやすくなります。
この特定のケースでは、go/build
パッケージ内のパッケージスキャンとビルド制約に関するロジックが、dir.go
という独立したファイルから、パッケージの主要な機能を含むbuild.go
に統合されました。これは、関連するコードをより一箇所に集約し、パッケージ全体の構造をより論理的にするための一歩と考えられます。
前提知識の解説
Go言語のgo/build
パッケージ
go/build
パッケージは、Goのソースコードパッケージに関する情報を収集するためのツールを提供します。これには、指定されたディレクトリ内のGoパッケージの特定、そのパッケージに含まれるファイルのリストアップ、インポートパスの解決、ビルド制約の評価などが含まれます。Goツールチェーン(go build
, go install
など)は、内部的にこのパッケージを利用して、どのファイルをコンパイルに含めるべきか、どの依存関係を解決すべきかを決定します。
ビルド制約(Build Constraints / +build
タグ)
Go言語では、ソースファイルに特別なコメント行を追加することで、そのファイルを特定のビルド条件でのみコンパイル対象に含めるように指定できます。これを「ビルド制約」または「+build
タグ」と呼びます。
- 形式: ソースファイルの先頭付近に
// +build <条件>
という形式で記述します。 - 条件の評価: 条件はスペース区切りのオプションのOR結合、各オプションはカンマ区切りの項目のAND結合として評価されます。各項目は英数字の単語、または
!
を前置した否定形です。- 例:
// +build linux,amd64 darwin,!cgo
は(linux AND amd64) OR (darwin AND (NOT cgo))
を意味します。
- 例:
- 認識されるキーワード:
GOOS
: ターゲットOS(例:linux
,windows
,darwin
)GOARCH
: ターゲットアーキテクチャ(例:amd64
,386
,arm
)cgo
: Cgoが有効な場合!cgo
: Cgoが無効な場合ignore
: ファイルをビルドから除外する慣習的なタグBuildTags
:Context
構造体のBuildTags
フィールドで指定された追加のカスタムタグ
- ファイル名による暗黙の制約:
*_GOOS.go
、*_GOARCH.go
、*_GOOS_GOARCH.go
のようなファイル名も、暗黙的にビルド制約として扱われます(例:main_windows.go
はWindowsでのみビルドされる)。
これらのビルド制約は、クロスプラットフォーム開発や、特定の環境に依存するコード(例: Cgoを使用するコード)を分離する際に非常に重要です。
Context
構造体
go/build
パッケージのContext
構造体は、ビルド環境に関する情報(ターゲットOS、アーキテクチャ、Cgoの有効/無効、追加のビルドタグなど)をカプセル化します。また、ファイルシステム操作(ディレクトリの読み取り、ファイルの読み取り)をカスタマイズするための関数ポインタ(ReadDir
, ReadFile
)も持ちます。これにより、実際のファイルシステムだけでなく、仮想的なファイルシステムやテスト環境でもパッケージスキャンを実行できるようになります。
DirInfo
構造体
DirInfo
構造体は、ScanDir
関数によって返される、特定のディレクトリ内のGoパッケージに関する詳細な情報を含みます。これには、パッケージ名、インポートパス、Goソースファイル、Cgo関連ファイル、テストファイル、インポートされたパッケージのリストなどが含まれます。
技術的詳細
このコミットは、go/build
パッケージ内の3つのファイルに影響を与えています。
-
src/pkg/go/build/build.go
:- このファイルは、
go/build
パッケージの主要な機能を含むように大幅に拡張されました。 Context
構造体、DefaultContext
変数、defaultContext
関数、envOr
関数、DirInfo
構造体、ScanDir
関数(Context
のメソッド版とパッケージレベルのラッパー版)、shouldBuild
関数、saveCgo
関数、safeName
関数、splitQuoted
関数、match
関数、goodOSArchFile
関数、knownOS
、knownArch
マップ、init
関数、ToolDir
変数、isLocalPath
関数が、dir.go
およびpath.go
からこのファイルに移動されました。- これにより、
build.go
がgo/build
パッケージの「中心」としての役割を強化し、パッケージスキャン、ビルド制約の評価、Cgo関連の処理など、ビルドに関するほとんどのロジックを包含するようになりました。
- このファイルは、
-
src/pkg/go/build/dir.go
:- このファイルは完全に削除されました。
- 以前は
Context
構造体、DirInfo
構造体、ScanDir
関数、ビルド制約の評価ロジック(shouldBuild
,match
など)、Cgo関連の処理(saveCgo
)など、パッケージスキャンとビルド制約に関する主要な機能が含まれていました。これらの内容はすべてbuild.go
に移動されました。
-
src/pkg/go/build/path.go
:- このファイルからは、
ToolDir
変数とisLocalPath
関数が削除されました。 - これらの機能は
build.go
に移動されました。path.go
は、主にGoのパス解決(GOROOT
,GOPATH
)に関連するロジックに特化するようになりました。
- このファイルからは、
この変更は、機能的な振る舞いを一切変更せず、純粋にコードの物理的な配置を変更するものです。これにより、go/build
パッケージの内部構造がより整理され、関連するコードが論理的にグループ化されることになります。
コアとなるコードの変更箇所
このコミットのコアとなる変更は、src/pkg/go/build/dir.go
の削除と、その内容のほとんどがsrc/pkg/go/build/build.go
への移動です。
src/pkg/go/build/build.go
への追加(挿入):
build.go
には、dir.go
にあった以下の主要な型、変数、関数が追加されました。
Context
構造体とその関連メソッド(readDir
,readFile
,match
,shouldBuild
,saveCgo
,goodOSArchFile
)DefaultContext
変数とdefaultContext
関数cgoEnabled
マップenvOr
関数DirInfo
構造体とそのメソッド(IsCommand
)- パッケージレベルの
ScanDir
関数 slashslash
バイトスライスsafeBytes
バイトスライスとsafeName
関数splitQuoted
関数knownOS
,knownArch
マップとinit
関数ToolDir
変数(path.go
から移動)isLocalPath
関数(path.go
から移動)
これらの追加により、build.go
の行数は718行増加しています。
src/pkg/go/build/dir.go
の削除:
ファイル全体が削除され、705行が削除されています。
src/pkg/go/build/path.go
からの削除:
ToolDir
変数の定義isLocalPath
関数の定義
これらの削除により、path.go
の行数は13行減少しています。
全体として、716行の挿入と720行の削除があり、これはコミットメッセージの「Only copy+paste here.」という説明と一致しています。
コアとなるコードの解説
移動されたコードの主要な機能は以下の通りです。
-
Context
構造体と関連メソッド:Context
は、ビルドプロセスにおける環境設定(GOOS
,GOARCH
,CgoEnabled
,BuildTags
など)を保持します。ReadDir
とReadFile
は、ファイルシステム操作を抽象化し、カスタムのファイル読み取りロジックを注入できるようにします。match
関数は、ビルド制約の各項目(例:linux
,amd64
,cgo
,!cgo
, カスタムタグ)が現在のビルドコンテキストに合致するかどうかを評価します。shouldBuild
関数は、Goソースファイルの先頭にある// +build
コメントを解析し、そのファイルが現在のビルドコンテキストでコンパイルされるべきかを判断します。saveCgo
関数は、import "C"
ブロック内の#cgo
ディレクティブ(CFLAGS
,LDFLAGS
,pkg-config
など)を解析し、DirInfo
に保存します。これはCgoがCコードをビルドする際に使用する情報です。goodOSArchFile
関数は、name_GOOS.go
やname_GOARCH.go
のようなファイル名に基づく暗黙のビルド制約を評価します。
-
DirInfo
構造体:ScanDir
関数によって返される、ディレクトリ内のGoパッケージに関する詳細なメタデータ(パッケージ名、インポート、ファイルリストなど)を保持します。
-
ScanDir
関数:- 指定されたディレクトリをスキャンし、そのディレクトリ内のGoパッケージに関する情報を
DirInfo
構造体として返します。この関数は、ファイル名やファイル内容のビルド制約を考慮して、どのファイルをパッケージに含めるかを決定します。
- 指定されたディレクトリをスキャンし、そのディレクトリ内のGoパッケージに関する情報を
これらの機能は、Goのビルドシステムの中核をなすものであり、ソースファイルの発見、パッケージの特定、ビルド条件の適用、Cgoの統合といった重要なステップを担っています。今回のコミットでは、これらの機能がdir.go
からbuild.go
へと物理的に移動されただけであり、そのロジック自体に変更はありません。これにより、build.go
がgo/build
パッケージの主要なインターフェースと実装の両方を集約する形になりました。
関連リンク
- Go CL 5704050: https://golang.org/cl/5704050
参考にした情報源リンク
- Go Command Documentation: Build constraints: https://pkg.go.dev/cmd/go#hdr-Build_constraints
- Go
go/build
package documentation: https://pkg.go.dev/go/build - Go
go/ast
package documentation: https://pkg.go.dev/go/ast - Go
go/parser
package documentation: https://pkg.go.dev/go/parser - Go
go/token
package documentation: https://pkg.go.dev/go/token - Go
os
package documentation: https://pkg.go.dev/os - Go
path/filepath
package documentation: https://pkg.go.dev/path/filepath - Go
runtime
package documentation: https://pkg.go.dev/runtime - Go
strings
package documentation: https://pkg.go.dev/strings - Go
unicode
package documentation: https://pkg.go.dev/unicode - Go
bytes
package documentation: https://pkg.go.dev/bytes - Go
errors
package documentation: https://pkg.go.dev/errors - Go
fmt
package documentation: https://pkg.go.dev/fmt - Go
io/ioutil
package documentation: https://pkg.go.dev/io/ioutil - Go
log
package documentation: https://pkg.go.dev/log - Go
sort
package documentation: https://pkg.go.dev/sort - Go
strconv
package documentation: https://pkg.go.dev/strconv