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

[インデックス 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つのファイルに影響を与えています。

  1. src/pkg/go/build/build.go:

    • このファイルは、go/buildパッケージの主要な機能を含むように大幅に拡張されました。
    • Context構造体、DefaultContext変数、defaultContext関数、envOr関数、DirInfo構造体、ScanDir関数(Contextのメソッド版とパッケージレベルのラッパー版)、shouldBuild関数、saveCgo関数、safeName関数、splitQuoted関数、match関数、goodOSArchFile関数、knownOSknownArchマップ、init関数、ToolDir変数、isLocalPath関数が、dir.goおよびpath.goからこのファイルに移動されました。
    • これにより、build.gogo/buildパッケージの「中心」としての役割を強化し、パッケージスキャン、ビルド制約の評価、Cgo関連の処理など、ビルドに関するほとんどのロジックを包含するようになりました。
  2. src/pkg/go/build/dir.go:

    • このファイルは完全に削除されました
    • 以前はContext構造体、DirInfo構造体、ScanDir関数、ビルド制約の評価ロジック(shouldBuild, matchなど)、Cgo関連の処理(saveCgo)など、パッケージスキャンとビルド制約に関する主要な機能が含まれていました。これらの内容はすべてbuild.goに移動されました。
  3. 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.」という説明と一致しています。

コアとなるコードの解説

移動されたコードの主要な機能は以下の通りです。

  1. Context構造体と関連メソッド:

    • Contextは、ビルドプロセスにおける環境設定(GOOS, GOARCH, CgoEnabled, BuildTagsなど)を保持します。
    • ReadDirReadFileは、ファイルシステム操作を抽象化し、カスタムのファイル読み取りロジックを注入できるようにします。
    • match関数は、ビルド制約の各項目(例: linux, amd64, cgo, !cgo, カスタムタグ)が現在のビルドコンテキストに合致するかどうかを評価します。
    • shouldBuild関数は、Goソースファイルの先頭にある// +buildコメントを解析し、そのファイルが現在のビルドコンテキストでコンパイルされるべきかを判断します。
    • saveCgo関数は、import "C"ブロック内の#cgoディレクティブ(CFLAGS, LDFLAGS, pkg-configなど)を解析し、DirInfoに保存します。これはCgoがCコードをビルドする際に使用する情報です。
    • goodOSArchFile関数は、name_GOOS.goname_GOARCH.goのようなファイル名に基づく暗黙のビルド制約を評価します。
  2. DirInfo構造体:

    • ScanDir関数によって返される、ディレクトリ内のGoパッケージに関する詳細なメタデータ(パッケージ名、インポート、ファイルリストなど)を保持します。
  3. ScanDir関数:

    • 指定されたディレクトリをスキャンし、そのディレクトリ内のGoパッケージに関する情報をDirInfo構造体として返します。この関数は、ファイル名やファイル内容のビルド制約を考慮して、どのファイルをパッケージに含めるかを決定します。

これらの機能は、Goのビルドシステムの中核をなすものであり、ソースファイルの発見、パッケージの特定、ビルド条件の適用、Cgoの統合といった重要なステップを担っています。今回のコミットでは、これらの機能がdir.goからbuild.goへと物理的に移動されただけであり、そのロジック自体に変更はありません。これにより、build.gogo/buildパッケージの主要なインターフェースと実装の両方を集約する形になりました。

関連リンク

参考にした情報源リンク