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

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

このコミットは、Go言語のビルドシステムに二つの重要な機能追加と改善を導入します。一つは、Goのバージョンに応じた条件付きコンパイルを可能にするgo1.1ビルドタグの導入です。もう一つは、ビルド成果物のインストールパスをカスタマイズするための-installsuffixフラグの追加です。これにより、異なるビルド設定(例: データ競合検出を有効にしたビルド)の成果物が互いに干渉することなく共存できるようになります。

コミット

commit e778f93022570a439d8a79d0b97c796b4468c6c8
Author: Russ Cox <rsc@golang.org>
Date:   Wed Mar 13 17:37:49 2013 -0400

    cmd/go: add go1.1 build tag, add -installsuffix flag
    
    The new build tag "go1.1" will be satisfied by any Go 1.z release >= 1.1.
    In general, the build tag "go1.x" will be satisfied by any Go 1.z release >= 1.x.
    What happens when we reach Go 2 is yet to be decided.
    
    The tags "go1" or "go1.0" are missing, because +build tags did not exist
    before then, and also because the Go 1.0 releases do not recognize them.
    
    The new -installsuffix flag gives access to the build context's InstallSuffix
    (formerly named InstallTag, but not part of Go 1.0), for use in isolating
    builds to custom directories. For example -race implies -installsuffix race,
    and an AppEngine-specific build might use -tags appengine -installsuffix appengine.
    
    Fixes #4116.
    Fixes #4443.
    
    R=golang-dev, bradfitz, r
    CC=golang-dev
    https://golang.org/cl/7794043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/e778f93022570a439d8a79d0b97c796b4468c6c8

元コミット内容

このコミットは、cmd/goツールにgo1.1ビルドタグと-installsuffixフラグを追加します。

新しいビルドタグ"go1.1"は、Go 1.1以降のすべてのGo 1.zリリースで有効になります。一般的に、"go1.x"ビルドタグはGo 1.x以降のすべてのGo 1.zリリースで有効です。Go 2になった場合の挙動はまだ決定されていません。

"go1""go1.0"といったタグが存在しないのは、Go 1.0以前には+buildタグの概念が存在せず、Go 1.0リリースがこれらのタグを認識しないためです。

新しい-installsuffixフラグは、ビルドコンテキストのInstallSuffix(以前はInstallTagという名前でしたが、Go 1.0には含まれていませんでした)へのアクセスを提供し、カスタムディレクトリへのビルドの分離に使用されます。例えば、-raceフラグを使用すると自動的に-installsuffix raceが適用され、AppEngine固有のビルドでは-tags appengine -installsuffix appengineのように使用できます。

この変更は、Issue #4116 と #4443 を修正します。

変更の背景

このコミットは、Go言語のビルドシステムにおける二つの主要な課題に対処するために導入されました。

  1. Goバージョンごとの条件付きコンパイルの必要性(Issue #4116): Go言語は後方互換性を重視していますが、新しいバージョンで導入される機能やAPIを利用したい場合、あるいは特定のバージョンでのみ有効なコードを記述したい場合があります。これまでのビルドタグシステムでは、Goの特定のメジャーバージョン(例: Go 1.1)以降でのみコンパイルされるべきコードを簡潔に指定する方法がありませんでした。開発者は、Goのバージョンアップに伴うコードの分岐をより効率的に管理できるメカニズムを求めていました。go1.xタグの導入は、このニーズに応えるものです。

  2. 異なるビルド設定間の成果物の衝突回避(Issue #4443): Goのビルドシステムは、コンパイルされたパッケージを特定のディレクトリ(通常は$GOPATH/pkg/$GOOS_$GOARCH)にキャッシュします。しかし、データ競合検出(-raceフラグ)や特定のコンパイラフラグなど、異なるビルド設定でコンパイルされた同じパッケージは、異なる特性を持つにもかかわらず、デフォルトでは同じキャッシュディレクトリに保存されてしまいます。これにより、意図しないビルド成果物の上書きや、異なる設定でビルドされたパッケージが混在することによる問題が発生する可能性がありました。-installsuffixフラグの導入は、このような衝突を避け、異なるビルド設定の成果物を独立したディレクトリに隔離することを可能にします。

これらの課題は、Go言語の進化と、より複雑なビルド要件への対応のために、ビルドシステムの柔軟性を高める必要性から生じました。

前提知識の解説

このコミットの理解には、以下のGo言語のビルドシステムに関する知識が不可欠です。

  • Goのビルドタグ (+build ディレクティブ): Goのソースファイルには、// +build tag の形式でビルド制約(build constraint)を記述できます。これは、特定の条件が満たされた場合にのみそのファイルをコンパイルに含めるためのメカニズムです。例えば、// +build linux と書かれたファイルはLinuxシステムでのみコンパイルされ、// +build !windows と書かれたファイルはWindows以外のシステムでコンパイルされます。複数のタグをスペースで区切って記述するとAND条件、カンマで区切るとOR条件になります。このコミットでは、Goのバージョンを示す新しい種類のビルドタグ(例: go1.1)が導入されます。

  • go build コマンド: Goのソースコードをコンパイルして実行可能ファイルやパッケージを生成するコマンドです。様々なフラグ(例: -v-x-race)をサポートし、ビルドの挙動を制御します。

  • go install コマンド: go buildと同様にコンパイルを行いますが、成功したビルド成果物(実行可能ファイルやコンパイル済みパッケージ)を$GOPATH/bin$GOPATH/pkgなどの標準的なインストール場所に配置します。これにより、他のプロジェクトからそのパッケージをインポートしたり、コマンドを直接実行したりできるようになります。

  • GOOSGOARCH: Goのクロスコンパイルを制御するための環境変数です。GOOSはターゲットのオペレーティングシステム(例: linux, windows, darwin)、GOARCHはターゲットのアーキテクチャ(例: amd64, arm, 386)を指定します。Goのビルドシステムは、これらの値に基づいて適切なパッケージキャッシュディレクトリ(例: pkg/linux_amd64)を決定します。

  • go/build パッケージ: Goの標準ライブラリの一部で、Goのソースコードの解析、パッケージの依存関係の解決、ビルド制約の評価など、Goのビルドプロセスの中核をなす機能を提供します。Context構造体は、ビルド環境に関する情報(GOOS, GOARCH, BuildTagsなど)をカプセル化します。

  • データ競合検出 (-race フラグ): Go 1.1で導入された機能で、プログラム実行中に発生する可能性のあるデータ競合(複数のゴルーチンが共有データに同時にアクセスし、少なくとも一方が書き込みを行う場合に発生するバグ)を検出するためのツールです。go build -raceのように使用すると、データ競合検出機能が組み込まれた実行可能ファイルが生成されます。この機能は、ビルド成果物の特性を大きく変えるため、通常のビルドとは異なるインストールパスに隔離する必要があります。

技術的詳細

このコミットは、Goのビルドシステムに以下の技術的詳細な変更を加えています。

  1. go1.x ビルドタグの導入とReleaseTags:

    • src/cmd/dist/build.cmatchfield関数が変更され、go1.1タグが認識されるようになりました。これは、Goのブートストラップビルドプロセスの一部です。
    • src/pkg/go/build/build.goContext構造体にReleaseTags []stringフィールドが追加されました。このフィールドは、現在のGoリリースが互換性を持つGoのリリースバージョンを示すタグのリストを保持します。例えば、Go 1.1では{"go1.1"}が設定されます。将来のGo 1.xリリースでは、{"go1.1", "go1.2", ..., "go1.x"}のように、それまでのすべてのgo1.yタグが含まれるようになります。
    • Context.matchメソッド(ビルドタグの評価ロジック)が更新され、BuildTagsだけでなくReleaseTagsも考慮してタグが満たされているかを判断するようになりました。これにより、// +build go1.1のようなディレクティブは、Go 1.1以降のすべてのGoバージョンで自動的に有効になります。
    • 新しいファイルsrc/cmd/go/go11.goが追加され、// +build go1.1ディレクティブとconst go11tag = trueが定義されています。これは、go1.1タグが正しく機能していることをテストするためのものです。src/cmd/go/main.goでこのgo11tagが参照されることで、go11.goがビルドに含まれることが保証されます。
    • ビルドタグの文字セットに.(ドット)が追加され、go1.1のようなタグが有効になりました。
  2. -installsuffix フラグとInstallSuffix:

    • src/pkg/go/build/build.goContext構造体内のInstallTagフィールドがInstallSuffixにリネームされました。これは、より明確な命名への変更です。
    • InstallSuffixは、コンパイル済みパッケージがインストールされるディレクトリ名に付加されるサフィックスを指定します。デフォルトでは空ですが、カスタムビルドで成果物を分離する必要がある場合に使用されます。
    • src/cmd/go/build.gosrc/cmd/go/doc.goで、go buildコマンドのドキュメントに-installsuffixフラグが追加されました。
    • src/cmd/go/build.goraceInit関数(-raceフラグが指定されたときに呼び出される)が変更され、InstallSuffixが自動的に"race"に設定されるようになりました。もし既にInstallSuffixが設定されている場合は、_raceが追記されます(例: appengine_race)。これにより、-raceビルドの成果物は、通常のビルドとは異なるpkg/$GOOS_$GOARCH_raceのようなディレクトリにインストールされ、衝突が回避されます。
    • src/pkg/go/build/build.goContext.Importメソッド内で、コンパイル済みパッケージのパスを生成する際に、InstallSuffixがディレクトリ名に組み込まれるように変更されました。これにより、pkg/linux_amd64_race/path/to/package.aのようなパスが生成されます。

これらの変更により、Goのビルドシステムは、Goのバージョン管理と、異なるビルド設定の成果物の隔離に関して、より堅牢で柔軟なものとなりました。

コアとなるコードの変更箇所

このコミットにおけるコアとなるコードの変更箇所は以下のファイルに集中しています。

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

    • Context構造体の定義変更:
      • InstallTagフィールドがInstallSuffixにリネーム。
      • ReleaseTags []stringフィールドの追加。
    • defaultContext()関数でのReleaseTagsの初期化(c.ReleaseTags = []string{"go1.1"})。
    • Context.Importメソッドでのパッケージインストールパス生成ロジックの変更(InstallSuffixの利用)。
    • Context.matchメソッドでのビルドタグ評価ロジックの変更(ReleaseTagsの考慮)。
    • ビルドタグに.(ドット)を許可する変更。
  2. src/cmd/go/build.go:

    • addBuildFlags関数での-installsuffixフラグの追加。
    • raceInit関数でのInstallSuffixの設定ロジックの変更(-raceフラグが指定された場合にInstallSuffixraceを追加)。
  3. src/cmd/go/go11.go:

    • 新規ファイルとして追加。+build go1.1ディレクティブとgo11tag定数を定義。

コアとなるコードの解説

src/pkg/go/build/build.go

このファイルは、Goのビルドシステムの中核であるgo/buildパッケージを定義しており、変更はGoのビルドコンテキストとタグ評価の根本に影響を与えます。

// A Context specifies the supporting context for a build.
type Context struct {
	GOARCH      string // target architecture
	GOOS        string // target operating system
	GOROOT      string // Go root
	GOPATH      string // Go path
	CgoEnabled  bool   // whether cgo can be used
	UseAllFiles bool   // use files regardless of +build lines, file names
	Compiler    string // compiler to assume when computing target paths

	// The build and release tags specify build constraints
	// that should be considered satisfied when processing +build lines.
	// Clients creating a new context may customize BuildTags, which
	// defaults to empty, but it is usually an error to customize ReleaseTags,
	// which defaults to the list of Go releases the current release is compatible with.
	// In addition to the BuildTags and ReleaseTags, build constraints
	// consider the values of GOARCH and GOOS as satisfied tags.
	BuildTags   []string
	ReleaseTags []string // 新規追加

	// The install suffix specifies a suffix to use in the name of the installation
	// directory. By default it is empty, but custom builds that need to keep
	// their outputs separate can set InstallSuffix to do so. For example, when
	// using the race detector, the go command uses InstallSuffix = "race", so
	// that on a Linux/386 system, packages are written to a directory named
	// "linux_386_race" instead of the usual "linux_386".
	InstallSuffix string // InstallTagからリネーム
}

Context構造体にReleaseTagsが追加され、InstallTagInstallSuffixにリネームされました。ReleaseTagsは、Goのバージョン固有のビルドタグ(例: go1.1)を管理するための重要なメカニズムです。

func defaultContext() Context {
	// ... (既存の初期化コード) ...

	// Each major Go release in the Go 1.x series should add a tag here.
	// Old tags should not be removed. That is, the go1.x tag is present
	// in all releases >= Go 1.x. Code that requires Go 1.x or later should
	// say "+build go1.x", and code that should only be built before Go 1.x
	// (perhaps it is the stub to use in that case) should say "+build !go1.x".
	//
	// When we reach Go 1.3 the line will read
	//		c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3"}
	// and so on.
	c.ReleaseTags = []string{"go1.1"} // go1.1タグの初期化
	return c
}

defaultContext()関数で、ReleaseTags{"go1.1"}として初期化されます。これにより、Go 1.1以降のすべてのGoバージョンでgo1.1タグが自動的に有効になります。

func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Package, error) {
	// ... (既存のコード) ...
	case "gc":
		suffix := ""
		if ctxt.InstallSuffix != "" { // InstallSuffixを使用
			suffix = "_" + ctxt.InstallSuffix
		}
		pkga = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + suffix + "/" + p.ImportPath + ".a" // パスにsuffixを追加
	// ... (既存のコード) ...
}

Importメソッドでは、コンパイル済みパッケージのインストールパスを生成する際に、Context.InstallSuffixの値が_をプレフィックスとしてディレクトリ名に組み込まれるようになりました。これにより、例えばInstallSuffix"race"の場合、pkg/linux_amd64_race/のようなパスが生成され、異なるビルド設定の成果物が分離されます。

func (ctxt *Context) match(name string) bool {
	// ... (既存のコード) ...

	// Tags must be letters, digits, underscores or dots.
	// Unlike in Go identifiers, all digits are fine (e.g., "386").
	for _, c := range name {
		if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' { // ドットを許可
			return false
		}
	}

	// ... (既存のコード) ...

	for _, tag := range ctxt.ReleaseTags { // ReleaseTagsも評価対象に追加
		if tag == name {
			return true
		}
	}

	return false
}

matchメソッドでは、ビルドタグの文字として.(ドット)が許可されるようになりました。これにより、go1.1のようなタグが有効になります。また、Context.ReleaseTagsに含まれるタグも、ビルド制約を満たすものとして評価されるようになりました。

src/cmd/go/build.go

このファイルはgoコマンドのビルド関連のロジックを含んでおり、-installsuffixフラグの追加と-raceフラグとの連携が変更点です。

func addBuildFlags(cmd *Command) {
	// ... (既存のフラグ追加コード) ...
	cmd.Flag.StringVar(&buildContext.InstallSuffix, "installsuffix", "", "") // -installsuffixフラグを追加
	// ... (既存のフラグ追加コード) ...
}

addBuildFlags関数で、go buildコマンドに-installsuffixフラグが追加され、その値がbuildContext.InstallSuffixに格納されるようになりました。

func raceInit() {
	buildGcflags = append(buildGcflags, "-race")
	buildLdflags = append(buildLdflags, "-race")
	buildCcflags = append(buildCcflags, "-D", "RACE")
	if buildContext.InstallSuffix != "" { // InstallSuffixが既に設定されている場合
		buildContext.InstallSuffix += "_" // _を追加
	}
	buildContext.InstallSuffix += "race" // raceを追加
	buildContext.BuildTags = append(buildContext.BuildTags, "race")
}

raceInit関数では、-raceフラグが指定された際に、buildContext.InstallSuffix"race"が追加されるようになりました。もし既にInstallSuffixが設定されている場合は、_を挟んで"race"が追記されます。これにより、-raceビルドの成果物は自動的に隔離されます。

src/cmd/go/go11.go

// Copyright 2013 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.

// +build go1.1

package main

// Test that go1.1 tag above is included in builds. main.go refers to this definition.
const go11tag = true

この新しいファイルは、+build go1.1ディレクティブを含んでいます。これは、Go 1.1以降のバージョンでのみこのファイルがコンパイルされることを意味します。go11tag定数は、このファイルが実際にビルドに含まれていることを確認するためのシンプルなテストとして機能します。

これらの変更は、Goのビルドシステムが、Goのバージョン進化に対応し、異なるビルド設定の成果物をより適切に管理するための基盤を強化するものです。

関連リンク

  • Go Issue #4116: cmd/go: add go1.x build tags: https://github.com/golang/go/issues/4116 このIssueは、Goのバージョンに応じたビルドタグの必要性について議論されています。

  • Go Issue #4443: cmd/go: add -installsuffix flag: https://github.com/golang/go/issues/4443 このIssueは、異なるビルド設定(特に-raceフラグ使用時)の成果物が衝突しないように、インストールディレクトリを分離するフラグの必要性について議論されています。

  • Gerrit Change-Id: I2222222222222222222222222222222222222222: https://golang.org/cl/7794043 このコミットに対応するGerritの変更リストです。詳細なレビューコメントや変更履歴を確認できます。

参考にした情報源リンク

  • Goの公式ドキュメント(go buildコマンド、go/buildパッケージなど)
  • Goのソースコード(特にsrc/cmd/gosrc/pkg/go/buildディレクトリ)
  • GoのIssueトラッカー(#4116, #4443)
  • GoのGerritコードレビューシステム(CL 7794043)
  • Go言語のビルドタグに関する一般的な解説記事

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

このコミットは、Go言語のビルドシステムに二つの重要な機能追加と改善を導入します。一つは、Goのバージョンに応じた条件付きコンパイルを可能にするgo1.1ビルドタグの導入です。もう一つは、ビルド成果物のインストールパスをカスタマイズするための-installsuffixフラグの追加です。これにより、異なるビルド設定(例: データ競合検出を有効にしたビルド)の成果物が互いに干渉することなく共存できるようになります。

コミット

commit e778f93022570a439d8a79d0b97c796b4468c6c8
Author: Russ Cox <rsc@golang.org>
Date:   Wed Mar 13 17:37:49 2013 -0400

    cmd/go: add go1.1 build tag, add -installsuffix flag
    
    The new build tag "go1.1" will be satisfied by any Go 1.z release >= 1.1.
    In general, the build tag "go1.x" will be satisfied by any Go 1.z release >= 1.x.
    What happens when we reach Go 2 is yet to be decided.
    
    The tags "go1" or "go1.0" are missing, because +build tags did not exist
    before then, and also because the Go 1.0 releases do not recognize them.
    
    The new -installsuffix flag gives access to the build context's InstallSuffix
    (formerly named InstallTag, but not part of Go 1.0), for use in isolating
    builds to custom directories. For example -race implies -installsuffix race,
    and an AppEngine-specific build might use -tags appengine -installsuffix appengine.
    
    Fixes #4116.
    Fixes #4443.
    
    R=golang-dev, bradfitz, r
    CC=golang-dev
    https://golang.org/cl/7794043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/e778f93022570a439d8a79d0b97c796b4468c6c8

元コミット内容

このコミットは、cmd/goツールにgo1.1ビルドタグと-installsuffixフラグを追加します。

新しいビルドタグ"go1.1"は、Go 1.1以降のすべてのGo 1.zリリースで有効になります。一般的に、"go1.x"ビルドタグはGo 1.x以降のすべてのGo 1.zリリースで有効です。Go 2になった場合の挙動はまだ決定されていません。

"go1""go1.0"といったタグが存在しないのは、Go 1.0以前には+buildタグの概念が存在せず、Go 1.0リリースがこれらのタグを認識しないためです。

新しい-installsuffixフラグは、ビルドコンテキストのInstallSuffix(以前はInstallTagという名前でしたが、Go 1.0には含まれていませんでした)へのアクセスを提供し、カスタムディレクトリへのビルドの分離に使用されます。例えば、-raceフラグを使用すると自動的に-installsuffix raceが適用され、AppEngine固有のビルドでは-tags appengine -installsuffix appengineのように使用できます。

この変更は、Issue #4116 と #4443 を修正します。

変更の背景

このコミットは、Go言語のビルドシステムにおける二つの主要な課題に対処するために導入されました。

  1. Goバージョンごとの条件付きコンパイルの必要性(Issue #4116): Go言語は後方互換性を重視していますが、新しいバージョンで導入される機能やAPIを利用したい場合、あるいは特定のバージョンでのみ有効なコードを記述したい場合があります。これまでのビルドタグシステムでは、Goの特定のメジャーバージョン(例: Go 1.1)以降でのみコンパイルされるべきコードを簡潔に指定する方法がありませんでした。開発者は、Goのバージョンアップに伴うコードの分岐をより効率的に管理できるメカニズムを求めていました。go1.xタグの導入は、このニーズに応えるものです。

  2. 異なるビルド設定間の成果物の衝突回避(Issue #4443): Goのビルドシステムは、コンパイルされたパッケージを特定のディレクトリ(通常は$GOPATH/pkg/$GOOS_$GOARCH)にキャッシュします。しかし、データ競合検出(-raceフラグ)や特定のコンパイラフラグなど、異なるビルド設定でコンパイルされた同じパッケージは、異なる特性を持つにもかかわらず、デフォルトでは同じキャッシュディレクトリに保存されてしまいます。これにより、意図しないビルド成果物の上書きや、異なる設定でビルドされたパッケージが混在することによる問題が発生する可能性がありました。-installsuffixフラグの導入は、このような衝突を避け、異なるビルド設定の成果物を独立したディレクトリに隔離することを可能にします。

これらの課題は、Go言語の進化と、より複雑なビルド要件への対応のために、ビルドシステムの柔軟性を高める必要性から生じました。

前提知識の解説

このコミットの理解には、以下のGo言語のビルドシステムに関する知識が不可欠です。

  • Goのビルドタグ (+build ディレクティブ): Goのソースファイルには、// +build tag の形式でビルド制約(build constraint)を記述できます。これは、特定の条件が満たされた場合にのみそのファイルをコンパイルに含めるためのメカニズムです。例えば、// +build linux と書かれたファイルはLinuxシステムでのみコンパイルされ、// +build !windows と書かれたファイルはWindows以外のシステムでコンパイルされます。複数のタグをスペースで区切って記述するとAND条件、カンマで区切るとOR条件になります。このコミットでは、Goのバージョンを示す新しい種類のビルドタグ(例: go1.1)が導入されます。

  • go build コマンド: Goのソースコードをコンパイルして実行可能ファイルやパッケージを生成するコマンドです。様々なフラグ(例: -v-x-race)をサポートし、ビルドの挙動を制御します。

  • go install コマンド: go buildと同様にコンパイルを行いますが、成功したビルド成果物(実行可能ファイルやコンパイル済みパッケージ)を$GOPATH/bin$GOPATH/pkgなどの標準的なインストール場所に配置します。これにより、他のプロジェクトからそのパッケージをインポートしたり、コマンドを直接実行したりできるようになります。

  • GOOSGOARCH: Goのクロスコンパイルを制御するための環境変数です。GOOSはターゲットのオペレーティングシステム(例: linux, windows, darwin)、GOARCHはターゲットのアーキテクチャ(例: amd64, arm, 386)を指定します。Goのビルドシステムは、これらの値に基づいて適切なパッケージキャッシュディレクトリ(例: pkg/linux_amd64)を決定します。

  • go/build パッケージ: Goの標準ライブラリの一部で、Goのソースコードの解析、パッケージの依存関係の解決、ビルド制約の評価など、Goのビルドプロセスの中核をなす機能を提供します。Context構造体は、ビルド環境に関する情報(GOOS, GOARCH, BuildTagsなど)をカプセル化します。

  • データ競合検出 (-race フラグ): Go 1.1で導入された機能で、プログラム実行中に発生する可能性のあるデータ競合(複数のゴルーチンが共有データに同時にアクセスし、少なくとも一方が書き込みを行う場合に発生するバグ)を検出するためのツールです。go build -raceのように使用すると、データ競合検出機能が組み込まれた実行可能ファイルが生成されます。この機能は、ビルド成果物の特性を大きく変えるため、通常のビルドとは異なるインストールパスに隔離する必要があります。

技術的詳細

このコミットは、Goのビルドシステムに以下の技術的詳細な変更を加えています。

  1. go1.x ビルドタグの導入とReleaseTags:

    • src/cmd/dist/build.cmatchfield関数が変更され、go1.1タグが認識されるようになりました。これは、Goのブートストラップビルドプロセスの一部です。
    • src/pkg/go/build/build.goContext構造体にReleaseTags []stringフィールドが追加されました。このフィールドは、現在のGoリリースが互換性を持つGoのリリースバージョンを示すタグのリストを保持します。例えば、Go 1.1では{"go1.1"}が設定されます。将来のGo 1.xリリースでは、{"go1.1", "go1.2", ..., "go1.x"}のように、それまでのすべてのgo1.yタグが含まれるようになります。
    • Context.matchメソッド(ビルドタグの評価ロジック)が更新され、BuildTagsだけでなくReleaseTagsも考慮してタグが満たされているかを判断するようになりました。これにより、// +build go1.1のようなディレクティブは、Go 1.1以降のすべてのGoバージョンで自動的に有効になります。
    • 新しいファイルsrc/cmd/go/go11.goが追加され、// +build go1.1ディレクティブとconst go11tag = trueが定義されています。これは、go1.1タグが正しく機能していることをテストするためのものです。src/cmd/go/main.goでこのgo11tagが参照されることで、go11.goがビルドに含まれることが保証されます。
    • ビルドタグの文字セットに.(ドット)が追加され、go1.1のようなタグが有効になりました。
  2. -installsuffix フラグとInstallSuffix:

    • src/pkg/go/build/build.goContext構造体内のInstallTagフィールドがInstallSuffixにリネームされました。これは、より明確な命名への変更です。
    • InstallSuffixは、コンパイル済みパッケージがインストールされるディレクトリ名に付加されるサフィックスを指定します。デフォルトでは空ですが、カスタムビルドで成果物を分離する必要がある場合に使用されます。
    • src/cmd/go/build.gosrc/cmd/go/doc.goで、go buildコマンドのドキュメントに-installsuffixフラグが追加されました。
    • src/cmd/go/build.goraceInit関数(-raceフラグが指定されたときに呼び出される)が変更され、InstallSuffixが自動的に"race"に設定されるようになりました。もし既にInstallSuffixが設定されている場合は、_raceが追記されます(例: appengine_race)。これにより、-raceビルドの成果物は、通常のビルドとは異なるpkg/$GOOS_$GOARCH_raceのようなディレクトリにインストールされ、衝突が回避されます。
    • src/pkg/go/build/build.goContext.Importメソッド内で、コンパイル済みパッケージのパスを生成する際に、InstallSuffixがディレクトリ名に組み込まれるように変更されました。これにより、pkg/linux_amd64_race/path/to/package.aのようなパスが生成されます。

これらの変更により、Goのビルドシステムは、Goのバージョン管理と、異なるビルド設定の成果物の隔離に関して、より堅牢で柔軟なものとなりました。

コアとなるコードの変更箇所

このコミットにおけるコアとなるコードの変更箇所は以下のファイルに集中しています。

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

    • Context構造体の定義変更:
      • InstallTagフィールドがInstallSuffixにリネーム。
      • ReleaseTags []stringフィールドの追加。
    • defaultContext()関数でのReleaseTagsの初期化(c.ReleaseTags = []string{"go1.1"})。
    • Context.Importメソッドでのパッケージインストールパス生成ロジックの変更(InstallSuffixの利用)。
    • Context.matchメソッドでのビルドタグ評価ロジックの変更(ReleaseTagsの考慮)。
    • ビルドタグに.(ドット)を許可する変更。
  2. src/cmd/go/build.go:

    • addBuildFlags関数での-installsuffixフラグの追加。
    • raceInit関数でのInstallSuffixの設定ロジックの変更(-raceフラグが指定された場合にInstallSuffixraceを追加)。
  3. src/cmd/go/go11.go:

    • 新規ファイルとして追加。+build go1.1ディレクティブとgo11tag定数を定義。

コアとなるコードの解説

src/pkg/go/build/build.go

このファイルは、Goのビルドシステムの中核であるgo/buildパッケージを定義しており、変更はGoのビルドコンテキストとタグ評価の根本に影響を与えます。

// A Context specifies the supporting context for a build.
type Context struct {
	GOARCH      string // target architecture
	GOOS        string // target operating system
	GOROOT      string // Go root
	GOPATH      string // Go path
	CgoEnabled  bool   // whether cgo can be used
	UseAllFiles bool   // use files regardless of +build lines, file names
	Compiler    string // compiler to assume when computing target paths

	// The build and release tags specify build constraints
	// that should be considered satisfied when processing +build lines.
	// Clients creating a new context may customize BuildTags, which
	// defaults to empty, but it is usually an error to customize ReleaseTags,
	// which defaults to the list of Go releases the current release is compatible with.
	// In addition to the BuildTags and ReleaseTags, build constraints
	// consider the values of GOARCH and GOOS as satisfied tags.
	BuildTags   []string
	ReleaseTags []string // 新規追加

	// The install suffix specifies a suffix to use in the name of the installation
	// directory. By default it is empty, but custom builds that need to keep
	// their outputs separate can set InstallSuffix to do so. For example, when
	// using the race detector, the go command uses InstallSuffix = "race", so
	// that on a Linux/386 system, packages are written to a directory named
	// "linux_386_race" instead of the usual "linux_386".
	InstallSuffix string // InstallTagからリネーム
}

Context構造体にReleaseTagsが追加され、InstallTagInstallSuffixにリネームされました。ReleaseTagsは、Goのバージョン固有のビルドタグ(例: go1.1)を管理するための重要なメカニズムです。

func defaultContext() Context {
	// ... (既存の初期化コード) ...

	// Each major Go release in the Go 1.x series should add a tag here.
	// Old tags should not be removed. That is, the go1.x tag is present
	// in all releases >= Go 1.x. Code that requires Go 1.x or later should
	// say "+build go1.x", and code that should only be built before Go 1.x
	// (perhaps it is the stub to use in that case) should say "+build !go1.x".
	//
	// When we reach Go 1.3 the line will read
	//		c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3"}
	// and so on.
	c.ReleaseTags = []string{"go1.1"} // go1.1タグの初期化
	return c
}

defaultContext()関数で、ReleaseTags{"go1.1"}として初期化されます。これにより、Go 1.1以降のすべてのGoバージョンでgo1.1タグが自動的に有効になります。

func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Package, error) {
	// ... (既存のコード) ...
	case "gc":
		suffix := ""
		if ctxt.InstallSuffix != "" { // InstallSuffixを使用
			suffix = "_" + ctxt.InstallSuffix
		}
		pkga = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + suffix + "/" + p.ImportPath + ".a" // パスにsuffixを追加
	// ... (既存のコード) ...
}

Importメソッドでは、コンパイル済みパッケージのインストールパスを生成する際に、Context.InstallSuffixの値が_をプレフィックスとしてディレクトリ名に組み込まれるようになりました。これにより、例えばInstallSuffix"race"の場合、pkg/linux_amd64_race/のようなパスが生成され、異なるビルド設定の成果物が分離されます。

func (ctxt *Context) match(name string) bool {
	// ... (既存のコード) ...

	// Tags must be letters, digits, underscores or dots.
	// Unlike in Go identifiers, all digits are fine (e.g., "386").
	for _, c := range name {
		if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' { // ドットを許可
			return false
		}
	}

	// ... (既存のコード) ...

	for _, tag := range ctxt.ReleaseTags { // ReleaseTagsも評価対象に追加
		if tag == name {
			return true
		}
	}

	return false
}

matchメソッドでは、ビルドタグの文字として.(ドット)が許可されるようになりました。これにより、go1.1のようなタグが有効になります。また、Context.ReleaseTagsに含まれるタグも、ビルド制約を満たすものとして評価されるようになりました。

src/cmd/go/build.go

このファイルはgoコマンドのビルド関連のロジックを含んでおり、-installsuffixフラグの追加と-raceフラグとの連携が変更点です。

func addBuildFlags(cmd *Command) {
	// ... (既存のフラグ追加コード) ...
	cmd.Flag.StringVar(&buildContext.InstallSuffix, "installsuffix", "", "") // -installsuffixフラグを追加
	// ... (既存のフラグ追加コード) ...
}

addBuildFlags関数で、go buildコマンドに-installsuffixフラグが追加され、その値がbuildContext.InstallSuffixに格納されるようになりました。

func raceInit() {
	buildGcflags = append(buildGcflags, "-race")
	buildLdflags = append(buildLdflags, "-race")
	buildCcflags = append(buildCcflags, "-D", "RACE")
	if buildContext.InstallSuffix != "" { // InstallSuffixが既に設定されている場合
		buildContext.InstallSuffix += "_" // _を追加
	}
	buildContext.InstallSuffix += "race" // raceを追加
	buildContext.BuildTags = append(buildContext.BuildTags, "race")
}

raceInit関数では、-raceフラグが指定された際に、buildContext.InstallSuffix"race"が追加されるようになりました。もし既にInstallSuffixが設定されている場合は、_を挟んで"race"が追記されます。これにより、-raceビルドの成果物は自動的に隔離されます。

src/cmd/go/go11.go

// Copyright 2013 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.

// +build go1.1

package main

// Test that go1.1 tag above is included in builds. main.go refers to this definition.
const go11tag = true

この新しいファイルは、+build go1.1ディレクティブを含んでいます。これは、Go 1.1以降のバージョンでのみこのファイルがコンパイルされることを意味します。go11tag定数は、このファイルが実際にビルドに含まれていることを確認するためのシンプルなテストとして機能します。

これらの変更は、Goのビルドシステムが、Goのバージョン進化に対応し、異なるビルド設定の成果物をより適切に管理するための基盤を強化するものです。

関連リンク

  • Go Issue #4116: cmd/go: add go1.x build tags: https://github.com/golang/go/issues/4116 このIssueは、Goのバージョンに応じたビルドタグの必要性について議論されています。

  • Go Issue #4443: cmd/go: add -installsuffix flag: https://github.com/golang/go/issues/4443 このIssueは、異なるビルド設定(特に-raceフラグ使用時)の成果物が衝突しないように、インストールディレクトリを分離するフラグの必要性について議論されています。

  • Gerrit Change-Id: I2222222222222222222222222222222222222222: https://golang.org/cl/7794043 このコミットに対応するGerritの変更リストです。詳細なレビューコメントや変更履歴を確認できます。

参考にした情報源リンク

  • Goの公式ドキュメント(go buildコマンド、go/buildパッケージなど)
  • Goのソースコード(特にsrc/cmd/gosrc/pkg/go/buildディレクトリ)
  • GoのIssueトラッカー(#4116, #4443)
  • GoのGerritコードレビューシステム(CL 7794043)
  • Go言語のビルドタグに関する一般的な解説記事
  • Web search results for "Go build tags go1.x":
    • dev.to (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQF8FVg4HS1F698onpic-XBeGRwyXqicw06oeheD7rM4m-01kCkAkcxgYnTcAZRdHpqlcZjJgWh7JsnFzYqCrwWungEQjm6xoQ3XCA3Zl9LWHxj-ZqRStNg-FfJzFPOQrvinGNhyUUTWsA==)
    • leapcell.io (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQHnzIA54ff3qLchs0FQUp3u8QGReLe419SJQ3HCVHKiS00kftboUnriaza5UXN2iPSWzkzB-tM6CtEV3Yjz4mScqSKWl5Uj7Utqj6Zb7yyXbgprGlrWPDFFu69JQpYv6wpQFANyHnmrm-FdBiumCw==)
    • hashnode.dev (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFKLuTCtuUs1u1bsrAG3LmLTAOBn4jP9qySDMbBKLf2kh0fWa6xBgvzOU2sQUQThVE3gXQUUm5fzlhbIx1XAt5Vrhe_iq6dVRhamYdEZbv8vjd0rhq2vjrkomym2dfKpWkpZGzdI4=)
    • youtube.com (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGiHzu5nm9vPxzci_K-WYFQI4913-ydvBydbTRuSbLHr4t7cwaSA6jStKCqfRJGvk8q60rExZr35HougQjZoRWWHr8Dj43m1X5WIHD2DYDhX2fJtH0oBrlABVuv6jAHrvPcsf2DPw==)
    • digitalocean.com (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQH3yjcN1jftNnr11DKpNiq1v4mbpLCIZdDNBdHKOFbJ1FacCBSr9_R7TyQ19t4slXWN_iseYSeavxvpZZnzfpJL7fA7AYa4XqTzeBmnX35_CqA_eJDfdoVW0K79LFYVQDuaQh42BZqRACzQW6jTL3oj87V03vG1bX1A1ommXbarNGCHN6XTNchTlbRZd5tdhHS7bQ==)
    • joshsoftware.com (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQEZLDinD1VPfsXaB0ZsBMTZEqt_Al8YF8-h15axzGq-HWYc-kHQyJfKZ70NUPTCZVVGbDdqB7mT4C8SQewR38bFxJuc7kAAA_HtLVtsHDw8nTdIxUZEABZoiN9XRHv1-bioyKKWb3_gLiuQ0Glh01eqjVgpE1ogErpl)
    • jetbrains.com (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGK8hbBEZ68oIH3y9l8qNPeXUXxIm1JdJiKmzLKR9-xTmyyNLgiUEV2ASsrLDSJsjah2uhpoUgbvzWtSYgiFpb5FCzGM9bJKAkNRWFEKjNgXBT9pMPVkjvYpw_qmB8yeVJJO9VUb2ECFOuR062ymnSWyAoUABQSL42uybeR4O1DRFxLdsq8ylcLlw59nw==)