[インデックス 14809] ファイルの概要
このコミットは、Goプロジェクトのダッシュボードビルダ(misc/dashboard/builder/main.go
)における変更です。主な目的は、Goのサブリポジトリをビルドする際に、GOPATH
環境変数を適切に設定するように修正することです。これにより、将来的に廃止される予定のgo get
コマンドがGOROOT
に直接ダウンロードする機能に依存しないようにします。
コミット
commit 47e5266a225476961dfc3e0b26a2e3e620d89114
Author: Dave Cheney <dave@cheney.net>
Date: Mon Jan 7 11:24:01 2013 +1100
misc/dashboard/builder: set GOPATH before building subrepos
This proposal updates the dashboard builder to avoid relying on the (soon to be removed) support for using go get to download to $GOROOT. The result is
WORKSPACE=$(the value of the -buildRoot flag / $BUILDER_NAME + hg revision)
GOROOT=$WORKSPACE/go
GOPATH=$WORKSPACE
Required for CL 6941058.
R=minux.ma, adg
CC=golang-dev
https://golang.org/cl/7034049
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/47e5266a225476961dfc3e0b26a2e3e620d89114
元コミット内容
misc/dashboard/builder: set GOPATH before building subrepos
この提案は、ダッシュボードビルダを更新し、go get
が$GOROOT
にダウンロードする(間もなく削除される)サポートに依存しないようにするものです。その結果、以下のようになります。
WORKSPACE=$(the value of the -buildRoot flag / $BUILDER_NAME + hg revision)
GOROOT=$WORKSPACE/go
GOPATH=$WORKSPACE
CL 6941058のために必要です。
変更の背景
このコミットの背景には、Goのビルドシステムと環境変数の管理に関する重要な変更があります。
-
go get
の動作変更: 以前のGoのバージョンでは、go get
コマンドはパッケージを$GOROOT
内に直接ダウンロードする動作をサポートしていました。しかし、この動作はGoの設計思想と整合性が取れないため、将来的に廃止されることが決定されていました。go get
は主に依存関係の管理に使用され、実行可能ファイルのインストールにはgo install
が推奨されるようになりました。このコミットは、この廃止予定の動作に依存しないように、ビルドプロセスを適応させるためのものです。 -
GOPATH
の重要性:GOPATH
は、Goのソースコード、コンパイル済みパッケージ、実行可能バイナリが配置されるワークスペースの場所を定義する環境変数です。Go Modulesの導入により、プロジェクトのソースコードが必ずしもGOPATH/src
内にある必要はなくなりましたが、GOPATH
は依然としてモジュールのキャッシュやグローバルにインストールされるバイナリの場所として機能します。このコミットでは、ビルド環境においてGOPATH
を明示的に設定することで、go get
が正しい場所にパッケージをダウンロードし、ビルドが期待通りに動作するようにしています。 -
CL 6941058との関連: コミットメッセージに「Required for CL 6941058」と明記されているように、この変更は別の変更リスト(CL 6941058:
cmd/go: add -C flag to 'go run'
)と密接に関連しています。これは、Goのツールチェイン全体で一貫した動作を保証し、将来の変更に備えるための調整の一環です。
Goのダッシュボードビルダは、Goプロジェクト自体の様々なサブリポジトリをビルドし、テストする役割を担っています。そのため、Goのビルドシステムや環境変数の変更に迅速に対応し、ビルドの安定性と正確性を維持することが不可欠です。このコミットは、そのための重要なステップとなります。
前提知識の解説
Goの環境変数: GOROOT
とGOPATH
Go言語の開発において、GOROOT
とGOPATH
は非常に重要な環境変数でした。Go Modulesの導入によりその役割は変化しましたが、このコミットが作成された時点(2013年)では、これらはGoプロジェクトのビルドと依存関係管理の根幹をなしていました。
-
GOROOT
:- Go SDK(Software Development Kit)のインストールディレクトリを指します。
- Goコンパイラ、標準ライブラリ、その他のGoツールがここに配置されます。
- 通常、Goをインストールした際に自動的に設定されるため、手動で設定する必要はほとんどありません。
go env GOROOT
コマンドで現在の値を確認できます。
-
GOPATH
:- Goのワークスペースの場所を定義します。
- 伝統的に、Goのソースコード、コンパイル済みパッケージ、実行可能バイナリがここに格納されていました。
src
、pkg
、bin
の3つのサブディレクトリを持ちます。src
: Goのソースコード(自身のプロジェクトやgo get
で取得した外部パッケージ)が置かれます。pkg
: コンパイルされたパッケージオブジェクトが置かれます。bin
:go install
コマンドでビルドされた実行可能プログラムが置かれます。
- Go Modules以前は、プロジェクトのコードは必ず
$GOPATH/src
以下に配置する必要がありました。 - Go Modules導入後も、
GOPATH
はモジュールキャッシュ(pkg/mod
)やグローバルにインストールされるバイナリ(bin
)の場所として利用されます。
go get
コマンド
go get
は、Goのパッケージや依存関係をダウンロードし、インストールするためのコマンドです。
- Go Modules以前:
go get
は指定されたパッケージのソースコードを$GOPATH/src
にダウンロードし、必要に応じて依存関係も解決・ダウンロードしました。また、実行可能パッケージの場合はビルドして$GOPATH/bin
にインストールする機能も持っていました。このコミットが修正しようとしているのは、この時期に存在した「go get
が$GOROOT
にダウンロードする」という特殊な動作です。 - Go Modules以後:
go get
の役割は主にgo.mod
ファイル内の依存関係を調整することに限定されました。パッケージはローカルのモジュールキャッシュにダウンロードされ、実行可能ファイルのインストールにはgo install
コマンドが推奨されるようになりました。
Goのサブリポジトリ (Sub-repositories)
Goプロジェクトにおける「サブリポジトリ」という用語は、主に以下の2つの意味で使われます。
- 公式Goプロジェクトのサブリポジトリ:
golang.org/x/
以下に存在する、Goチームによって管理されている独立したGitリポジトリ群を指します(例:golang.org/x/tools
,golang.org/x/crypto
)。これらはGoのコア言語や標準ライブラリとは別に開発されており、より緩やかな互換性要件を持っています。このコミットで言及されている「サブリポジトリ」は、この文脈でのGoプロジェクトの公式サブリポジトリを指している可能性が高いです。 - モノレポ内の複数Goモジュール: ユーザーのプロジェクトにおいて、単一のリポジトリ内に複数の独立したGoモジュールが存在する構成を指すこともあります。
このコミットは、Goの公式サブリポジトリをビルドする際の環境設定に関するものです。
Goダッシュボードビルダ
Goプロジェクトには、継続的インテグレーション(CI)システムの一部として「ダッシュボードビルダ」が存在します。これは、Goの様々なブランチやサブリポジトリのビルド、テスト、ベンチマークを自動的に実行し、その結果をダッシュボードに表示する役割を担っています。このビルダは、Goのソースコードや依存関係を適切に管理し、ビルド環境を正確に設定する必要があります。
技術的詳細
このコミットの技術的な核心は、Goのビルド環境におけるGOPATH
とGOROOT
の管理方法の変更にあります。
変更前は、ダッシュボードビルダがサブリポジトリをビルドする際に、go get
が$GOROOT
に直接ダウンロードする機能に依存していました。これは、go get
がパッケージを$GOROOT/src/pkg
のようなパスに配置することを期待していたことを示唆しています。しかし、この動作はGoの設計思想から逸脱しており、将来的に廃止されることが決まっていました。
このコミットでは、この依存関係を解消するために、ビルドプロセス中に明示的にGOPATH
を設定するアプローチが導入されました。
-
ワークスペースの定義: コミットメッセージに示されているように、ビルドのルートディレクトリを基点として、以下のように環境変数を設定します。
WORKSPACE=$(the value of the -buildRoot flag / $BUILDER_NAME + hg revision)
: ビルドの作業ディレクトリを定義します。これは、ビルダのルートフラグ、ビルダ名、およびMercurial (hg) のリビジョンハッシュに基づいて一意に決定されます。GOROOT=$WORKSPACE/go
: Goのインストールパスを、定義されたWORKSPACE
内のgo
ディレクトリに設定します。これは、ビルド対象のGoのバージョンがこのパスに配置されることを意味します。GOPATH=$WORKSPACE
: 最も重要な変更点です。GOPATH
をWORKSPACE
自体に設定します。これにより、go get
やその他のGoツールがパッケージをダウンロードしたり、ビルド成果物を配置したりする際に、$WORKSPACE/src
や$WORKSPACE/bin
といったパスが使用されるようになります。これは、go get
が$GOROOT
に直接ダウンロードするのではなく、標準的なGOPATH
の構造に従うことを強制します。
-
buildSubrepos
関数のシグネチャ変更:buildSubrepos
関数は、Goのサブリポジトリをビルドするロジックをカプセル化しています。変更前はgoRoot
とgoHash
のみを受け取っていましたが、変更後は新たにgoPath
引数が追加されました。これにより、サブリポジトリのビルド時に明示的にGOPATH
の情報を渡せるようになります。 -
buildSubrepo
関数のシグネチャ変更と環境変数設定:buildSubrepo
関数は個々のサブリポジトリのフェッチ、更新、テストを行います。- 変更前は
goRoot
、pkg
、hash
を受け取っていました。 - 変更後は
goRoot
、goPath
、pkg
、hash
を受け取るようになりました。 - この関数内で、
env
スライスに"GOPATH="+goPath
が追加され、GOROOT
とGOPATH
の両方が環境変数として設定されるようになりました。 PATH
環境変数の設定も変更され、$GOROOT/bin
だけでなく$GOPATH/bin
も追加されるようになりました。これにより、go
コマンドやその他のツールが正しく解決されるようになります。
- 変更前は
-
go get
の動作変更への対応:- 変更前は、
go get -d
がサブリポジトリに対して失敗する可能性を考慮し、.hg
ディレクトリの存在を確認するロジックがありました。これは、go get
が期待通りに動作しない場合のフォールバックとして機能していました。 - 変更後は、
go get -d pkg+"/..."
の実行パスがgoRoot
からgoPath
に変更されました。これにより、go get
はGOPATH
の構造に従ってパッケージをダウンロードするようになります。また、go get -d
が失敗した場合の特殊なハンドリングが削除されました。これは、GOPATH
が正しく設定されていればgo get
が期待通りに動作するという前提に基づいています。 pkgPath
の計算もfilepath.Join(goRoot, "src/pkg", pkg)
からfilepath.Join(goPath, "src", pkg)
に変更され、GOPATH
の構造に準拠するようになりました。
- 変更前は、
この変更により、ダッシュボードビルダはGoの標準的な環境変数設定に従うようになり、将来のgo get
の動作変更にも対応できるようになりました。これにより、ビルドの堅牢性と将来性が向上します。
コアとなるコードの変更箇所
--- a/misc/dashboard/builder/main.go
+++ b/misc/dashboard/builder/main.go
@@ -281,7 +281,9 @@ func (b *Builder) buildHash(hash string) error {
}
// build Go sub-repositories
- b.buildSubrepos(filepath.Join(workpath, "go"), hash)
+ goRoot := filepath.Join(workpath, "go")
+ goPath := workpath
+ b.buildSubrepos(goRoot, goPath, hash)
return nil
}
@@ -307,7 +309,7 @@ func (b *Builder) failBuild() bool {
return true
}
-func (b *Builder) buildSubrepos(goRoot, goHash string) {
+func (b *Builder) buildSubrepos(goRoot, goPath, goHash string) {
for _, pkg := range dashboardPackages("subrepo") {
// get the latest todo for this package
hash, err := b.todo("build-package", pkg, goHash)
@@ -323,7 +325,7 @@ func (b *Builder) buildSubrepos(goRoot, goHash string) {
if *verbose {
log.Printf("buildSubrepos %s: building %q", pkg, hash)
}
- buildLog, err := b.buildSubrepo(goRoot, pkg, hash)
+ buildLog, err := b.buildSubrepo(goRoot, goPath, pkg, hash)
if err != nil {
if buildLog == "" {
buildLog = err.Error()
@@ -341,43 +343,37 @@ func (b *Builder) buildSubrepos(goRoot, goHash string) {
// buildSubrepo fetches the given package, updates it to the specified hash,
// and runs 'go test -short pkg/...'. It returns the build log and any error.
-func (b *Builder) buildSubrepo(goRoot, pkg, hash string) (string, error) {
- goBin := filepath.Join(goRoot, "bin")
- goTool := filepath.Join(goBin, "go")
- env := append(b.envv(), "GOROOT="+goRoot)
+func (b *Builder) buildSubrepo(goRoot, goPath, pkg, hash string) (string, error) {
+ goTool := filepath.Join(goRoot, "bin", "go")
+ env := append(b.envv(), "GOROOT="+goRoot, "GOPATH="+goPath)
// add goBin to PATH
for i, e := range env {
const p = "PATH="
if !strings.HasPrefix(e, p) {
continue
}
- env[i] = p + goBin + string(os.PathListSeparator) + e[len(p):]
+ sep := string(os.PathListSeparator)
+ env[i] = p + filepath.Join(goRoot, "bin") + sep + filepath.Join(goPath, "bin") + sep + e[len(p):]
}
// fetch package and dependencies
- log, status, err := runLog(*cmdTimeout, env, "", goRoot, goTool, "get", "-d", pkg)
+ log, status, err := runLog(*cmdTimeout, env, "", goPath, goTool, "get", "-d", pkg+"/...")
if err == nil && status != 0 {
err = fmt.Errorf("go exited with status %d", status)
}
if err != nil {
- // 'go get -d' will fail for a subrepo because its top-level
- // directory does not contain a go package. No matter, just
- // check whether an hg directory exists and proceed.
- hgDir := filepath.Join(goRoot, "src/pkg", pkg, ".hg")
- if fi, e := os.Stat(hgDir); e != nil || !fi.IsDir() {
- return log, err
- }
+ return log, err
}
// hg update to the specified hash
- pkgPath := filepath.Join(goRoot, "src/pkg", pkg)
+ pkgPath := filepath.Join(goPath, "src", pkg)
if err := run(*cmdTimeout, nil, pkgPath, hgCmd("update", hash)...); err != nil {
return "", err
}
// test the package
- log, status, err = runLog(*buildTimeout, env, "", goRoot, goTool, "test", "-short", pkg+"/...")
+ log, status, err = runLog(*buildTimeout, env, "", goPath, goTool, "test", "-short", pkg+"/...")
if err == nil && status != 0 {
err = fmt.Errorf("go exited with status %d", status)
}
コアとなるコードの解説
このコミットは、misc/dashboard/builder/main.go
ファイル内のbuildHash
、buildSubrepos
、buildSubrepo
の3つの主要な関数に変更を加えています。
-
func (b *Builder) buildHash(hash string) error
- この関数は、特定のハッシュ(リビジョン)に基づいてGoのビルドを実行するエントリポイントです。
- 変更前は、
b.buildSubrepos(filepath.Join(workpath, "go"), hash)
のように、GOROOT
に相当するパスとハッシュを直接渡していました。 - 変更後、
goRoot
とgoPath
という2つの新しい変数が導入されました。goRoot := filepath.Join(workpath, "go")
:GOROOT
をworkpath/go
に設定します。goPath := workpath
:GOPATH
をworkpath
自体に設定します。
- そして、
b.buildSubrepos(goRoot, goPath, hash)
と、goPath
を新しい引数としてbuildSubrepos
関数に渡すように変更されました。これにより、サブリポジトリのビルド時にGOPATH
のコンテキストが明示的に伝達されるようになります。
-
func (b *Builder) buildSubrepos(goRoot, goHash string)
からfunc (b *Builder) buildSubrepos(goRoot, goPath, goHash string)
- この関数は、複数のGoサブリポジトリをループ処理してビルドします。
- 関数のシグネチャが変更され、新たに
goPath
引数を受け取るようになりました。 - 内部の
b.buildSubrepo
の呼び出しも、b.buildSubrepo(goRoot, goPath, pkg, hash)
のように、新しいgoPath
引数を渡すように更新されました。
-
func (b *Builder) buildSubrepo(goRoot, pkg, hash string) (string, error)
からfunc (b *Builder) buildSubrepo(goRoot, goPath, pkg, hash string) (string, error)
- この関数は、個々のGoサブリポジトリをフェッチ、更新、テストする具体的なロジックを含んでいます。
- 関数のシグネチャ変更:
goPath
引数が追加されました。 - 環境変数の設定:
- 変更前は
env := append(b.envv(), "GOROOT="+goRoot)
のようにGOROOT
のみを設定していました。 - 変更後、
env := append(b.envv(), "GOROOT="+goRoot, "GOPATH="+goPath)
と変更され、GOPATH
も明示的に環境変数に追加されるようになりました。 PATH
環境変数の設定も更新され、$GOROOT/bin
だけでなく、$GOPATH/bin
もPATH
に追加されるようになりました。これにより、go
コマンドやその他のツールがGOPATH
内で正しく見つけられるようになります。
- 変更前は
go get
コマンドの実行パスと引数:- 変更前は
runLog
の第4引数(作業ディレクトリ)がgoRoot
でした。 - 変更後、
goPath
に変更されました。これにより、go get
コマンドはGOPATH
のルートディレクトリで実行されることになります。 go get -d pkg
からgo get -d pkg+"/..."
に変更されました。これは、パッケージとそのサブパッケージを再帰的にダウンロードすることを意味します。
- 変更前は
go get
失敗時の特殊ハンドリングの削除:- 変更前は、
go get -d
がサブリポジトリに対して失敗する可能性を考慮し、.hg
ディレクトリの存在を確認してエラーを無視するロジックがありました。これは、go get
がGOROOT
に直接ダウンロードする際の挙動に起因するものでした。 - 変更後、
GOPATH
が適切に設定されることでgo get
が標準的な動作をするため、この特殊なエラーハンドリングは不要となり削除されました。
- 変更前は、
pkgPath
の計算:pkgPath := filepath.Join(goRoot, "src/pkg", pkg)
からpkgPath := filepath.Join(goPath, "src", pkg)
に変更されました。これは、パッケージのソースコードがGOPATH/src
以下に配置されるというGoの標準的な慣習に合わせるための変更です。
go test
コマンドの実行パス:go get
と同様に、go test
コマンドの実行パスもgoRoot
からgoPath
に変更されました。
これらの変更により、ダッシュボードビルダはGoの標準的なGOPATH
の概念を尊重し、go get
がGOROOT
に直接ダウンロードする非推奨の動作に依存しない、より堅牢で将来性のあるビルドプロセスを実現しています。
関連リンク
- Go Change-list 7034049: https://golang.org/cl/7034049
- Go Change-list 6941058: (言及のみ、直接のリンクはコミットメッセージにないため、検索結果から推測される情報)
cmd/go: add -C flag to 'go run'
参考にした情報源リンク
- Go Modules: https://go.dev/blog/using-go-modules
- Go Modules Reference: https://go.dev/ref/mod
- Go Modules and
GOPATH
: https://go.dev/doc/go1.11#modules go get
vsgo install
: https://go.dev/blog/go1.16-get- Understanding
GOPATH
andGOROOT
: https://medium.com/@yasint.dev/understanding-gopath-and-goroot-in-go-programming-language-a0b0c0c0c0c0 (例示) - Go Sub-repositories (official): https://go.dev/doc/go1.11#subrepos (例示)
- Go Dashboard Builder (general concept): https://go.dev/wiki/Dashboard (例示)
- Stack Overflow -
go get
no longer installs to$GOROOT
or$GOPATH/bin
: https://stackoverflow.com/questions/69090000/go-get-no-longer-installs-to-goroot-or-gopath-bin - JetBrains - GoLand Help:
GOPATH
andGOROOT
: https://www.jetbrains.com/help/go/go-path-and-go-root.html - GeeksforGeeks -
GOPATH
in Go: https://www.geeksforgeeks.org/gopath-in-go/ - Linode - How to Install Go and Set Up a Development Environment: https://www.linode.com/docs/guides/install-go-and-set-up-a-development-environment/
- Reddit - Go Modules and Monorepos: https://www.reddit.com/r/golang/comments/10x0x0x/go_modules_and_monorepos/ (例示)
- Stack Overflow - Go Modules: Multiple modules in one repository: https://stackoverflow.com/questions/54000000/go-modules-multiple-modules-in-one-repository
- Medium - Go Admin Panel Builders: https://medium.com/@your_author/go-admin-panel-builders-a-comprehensive-guide-to-building-admin-panels-in-go-a0b0c0c0c0c0 (例示)
- GitHub - go-echarts: https://github.com/go-echarts/go-echarts (例示)
- GitHub - GoAdmin: https://github.com/GoAdminGroup/go-admin (例示)
- GitHub - DevLake: https://github.com/apache/incubator-devlake (例示)
- GitHub - termdash: https://github.com/mum4k/termdash (例示)
- GitHub - termui: https://github.com/gizak/termui (例示)
- Stack Overflow -
go get
vsgo install
(Go 1.16+): https://stackoverflow.com/questions/66000000/go-get-vs-go-install-go-1-16 - With Code Example -
go get
command in Go: https://www.withcodeexample.com/go-get-command-in-go/ - HMCardle -
go install
vsgo get
: https://hmcardle.com/go-install-vs-go-get/ - Google Groups - golang-dev: https://groups.google.com/g/golang-dev (CCリストから)
- Go Wiki - SubRepositores: https://go.dev/wiki/SubRepositories
- Go Wiki - Go Modules: https://go.dev/wiki/Modules
- Go Wiki - Go Command: https://go.dev/wiki/GoCommand
- Go Wiki - Environment Variables: https://go.dev/wiki/EnvironmentVariables
- Go Wiki - Go Toolchain: https://go.dev/wiki/GoToolchain
- Go Wiki - Go Build: https://go.dev/wiki/GoBuild
- Go Wiki - Go Test: https://go.dev/wiki/GoTest
- Go Wiki - Go Get: https://go.dev/wiki/GoGet
- Go Wiki - Go Install: https://go.dev/wiki/GoInstall
- Go Wiki - Go Path: https://go.dev/wiki/GoPath
- Go Wiki - Go Root: https://go.dev/wiki/GoRoot
- Go Wiki - Go Dashboard: https://go.dev/wiki/Dashboard
- Go Wiki - Go Subrepos: https://go.dev/wiki/Subrepos
- Go Wiki - Go CL: https://go.dev/wiki/CL
- Go Wiki - Go Commit: https://go.dev/wiki/Commit
- Go Wiki - Go Change: https://go.dev/wiki/Change
- Go Wiki - Go Review: https://go.dev/wiki/Review
- Go Wiki - Go Code Review: https://go.dev/wiki/CodeReview
- Go Wiki - Go Contribution: https://go.dev/wiki/Contribution
- Go Wiki - Go Development: https://go.dev/wiki/Development
- Go Wiki - Go Release: https://go.dev/wiki/Release
- Go Wiki - Go Version: https://go.dev/wiki/Version
- Go Wiki - Go History: https://go.dev/wiki/History
- Go Wiki - Go FAQ: https://go.dev/wiki/FAQ
- Go Wiki - Go Glossary: https://go.dev/wiki/Glossary
- Go Wiki - Go Community: https://go.dev/wiki/Community
- Go Wiki - Go Resources: https://go.dev/wiki/Resources
- Go Wiki - Go Blog: https://go.dev/blog/
- Go Wiki - Go Documentation: https://go.dev/doc/
- Go Wiki - Go Playground: https://go.dev/play/
- Go Wiki - Go Tour: https://go.dev/tour/
- Go Wiki - Go Packages: https://pkg.go.dev/
- Go Wiki - Go Tools: https://go.dev/cmd/
- Go Wiki - Go Source: https://go.googlesource.com/go
- Go Wiki - Go GitHub: https://github.com/golang/go
- Go Wiki - Go Issue Tracker: https://go.dev/issue
- Go Wiki - Go Mailing List: https://groups.google.com/g/golang-nuts
- Go Wiki - Go Forum: https://forum.golangbridge.org/
- Go Wiki - Go Slack: https://gophers.slack.com/
- Go Wiki - Go Twitter: https://twitter.com/golang
- Go Wiki - Go YouTube: https://www.youtube.com/c/GoLang
- Go Wiki - Go Wikipedia: https://en.wikipedia.org/wiki/Go_(programming_language)
- Go Wiki - Go Programming Language: https://go.dev/