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

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

このコミットは、Go言語のダッシュボードビルダにおけるWindows環境でのデフォルトのビルドルートパスの変更に関するものです。具体的には、Windows上でのビルド時に発生するパスの長さ制限の問題(issue 3358)を解決するため、デフォルトのビルドルートを c:\gobuilder に設定するように修正しています。

コミット

commit db3c800d19a394d76531f001dbb09e13a6630712
Author: Alex Brainman <alex.brainman@gmail.com>
Date:   Fri Sep 14 12:53:30 2012 +1000

    misc/dashboard/builder: use c:\ as default buildroot on windows
    
    We have some tests (misc/cgo/test) that are disabled only because
    they will fail to run on go builder - see issue 3358 for details.
    This change will allow us to enable these tests.
    
    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/6493118

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

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

元コミット内容

misc/dashboard/builder: use c:\ as default buildroot on windows

このコミットは、Windows環境におけるGoビルダのデフォルトビルドルートを c:\ に変更します。これにより、Goビルダ上で実行される一部のテスト(misc/cgo/test など)が、パスの長さ制限のために失敗する問題を解決し、これらのテストを有効にできるようになります。詳細は issue 3358 を参照してください。

変更の背景

この変更の背景には、Windowsオペレーティングシステムにおけるファイルパスの長さ制限という固有の問題があります。Goプロジェクトのビルドプロセス、特に自動化されたビルドシステム(Goビルダ)では、ソースコードのチェックアウト、依存関係のダウンロード、中間ファイルの生成などにより、非常に深いディレクトリ構造が生成されることがあります。

コミットメッセージに記載されている「issue 3358」は、まさにこの問題に起因しています。Windowsでは、歴史的にファイルパスの最大長が約260文字(MAX_PATH)に制限されており、これを超えるパスは多くのファイルシステム操作でエラーを引き起こします。Goビルダが一時ディレクトリ(os.TempDir() が返すパス)の下にビルドアーティファクトを配置すると、そのパスが長くなりすぎ、特に misc/cgo/test のような深い階層を持つテストが実行時に失敗していました。

この問題は、テストの実行を妨げ、Goプロジェクト全体の品質保証プロセスに影響を与えていました。テストが実行できないということは、そのテストがカバーする機能の回帰を検出できないことを意味します。したがって、このコミットは、Windows環境でのビルドの堅牢性を高め、より多くのテストをGoビルダ上で実行可能にすることを目的としています。

前提知識の解説

  • Goビルダ (Go Builder): Goプロジェクトの継続的インテグレーション(CI)システムの一部です。世界中の様々なアーキテクチャやオペレーティングシステム上でGoのコードを自動的にビルドし、テストを実行します。これにより、Go言語のクロスプラットフォーム互換性と安定性が保証されます。
  • ビルドルート (Buildroot): ソフトウェアのビルドプロセスにおいて、すべてのビルド関連ファイル(ソースコード、中間ファイル、最終的なバイナリなど)が配置される最上位のディレクトリを指します。
  • os.TempDir(): Go言語の os パッケージに含まれる関数で、オペレーティングシステムが一時ファイルやディレクトリを保存するために推奨するデフォルトのディレクトリのパスを返します。Windowsでは通常 C:\Users\<username>\AppData\Local\Temp のようなパスになります。
  • filepath.Join(): Go言語の path/filepath パッケージに含まれる関数で、複数のパス要素を結合して単一のパスを生成します。オペレーティングシステム固有のパス区切り文字(Windowsでは \、Unix系では /)を適切に処理します。
  • runtime.GOOS: Go言語の runtime パッケージに含まれる定数で、プログラムが実行されているオペレーティングシステムの名前(例: "windows", "linux", "darwin")を文字列で返します。
  • Cgo: Go言語の機能の一つで、C言語のコードをGoプログラムから呼び出すことを可能にします。Cgoを使用するプロジェクトは、Cコンパイラやリンカへの依存関係を持つため、ビルド環境のパス設定に敏感な場合があります。misc/cgo/test は、Cgoに関連するテストであることを示唆しています。
  • Windowsのパス長制限 (MAX_PATH): Windows APIには、ファイルパスの長さに260文字という制限(MAX_PATH)があります。これは、特に深いディレクトリ構造を持つプロジェクトや、自動生成される長いパスを持つファイルで問題となることがあります。Windows 10以降では、レジストリ設定を変更することでこの制限を緩和できますが、古いシステムやデフォルト設定では依然としてこの制限が存在します。

技術的詳細

このコミットは、misc/dashboard/builder/main.go ファイルに defaultBuildRoot() という新しい関数を導入し、既存の buildroot フラグのデフォルト値をこの関数からの戻り値に置き換えることで、Windows環境でのビルドルートの挙動を変更しています。

変更前は、buildroot フラグのデフォルト値は filepath.Join(os.TempDir(), "gobuilder") と直接ハードコードされていました。これは、一時ディレクトリのパスがOSによって異なるものの、そのパスが長くなる可能性があるという問題がありました。

変更後、defaultBuildRoot() 関数が導入されました。この関数は、runtime.GOOS をチェックし、現在のOSが "windows" であるかどうかを判断します。

  • もしOSが "windows" であれば、d 変数に c:\ という短いパスを設定します。これは、Windowsのパス長制限を回避するための意図的な選択です。
  • それ以外のOS(Unix系など)であれば、d 変数には os.TempDir() の結果が設定されます。これは、これらのOSではパス長制限が問題にならないため、従来の一時ディレクトリを使用する挙動を維持するためです。

最終的に、defaultBuildRoot() 関数は、選択されたベースディレクトリ d と "gobuilder" を filepath.Join() で結合したパスを返します。これにより、Windows環境では c:\gobuilder がデフォルトのビルドルートとなり、パス長の問題が緩和されます。

このアプローチは、OS固有の挙動を抽象化し、コードの可読性と保守性を向上させるとともに、Windows環境でのビルドの信頼性を高める効果があります。

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

--- a/misc/dashboard/builder/main.go
+++ b/misc/dashboard/builder/main.go
@@ -46,7 +46,7 @@ type Builder struct {
 }
 
 var (
-	buildroot     = flag.String("buildroot", filepath.Join(os.TempDir(), "gobuilder"), "Directory under which to build")
+	buildroot     = flag.String("buildroot", defaultBuildRoot(), "Directory under which to build")
 	commitFlag    = flag.Bool("commit", false, "upload information about new commits")
 	dashboard     = flag.String("dashboard", "build.golang.org", "Go Dashboard Host")
 	buildRelease  = flag.Bool("release", false, "Build and upload binary release archives")
@@ -668,6 +668,19 @@ func defaultSuffix() string {
 	return ".bash"
 }
 
+// defaultBuildRoot returns default buildroot directory.
+func defaultBuildRoot() string {
+	var d string
+	if runtime.GOOS == "windows" {
+		// will use c:\, otherwise absolute paths become too long
+		// during builder run, see http://golang.org/issue/3358.
+		d = `c:\`
+	} else {
+		d = os.TempDir()
+	}
+	return filepath.Join(d, "gobuilder")
+}
+
 func getenvOk(k string) (v string, ok bool) {
 	v = os.Getenv(k)
 	if v != "" {

コアとなるコードの解説

変更は主に misc/dashboard/builder/main.go ファイルの2箇所です。

  1. buildroot フラグの初期化の変更:

    -	buildroot     = flag.String("buildroot", filepath.Join(os.TempDir(), "gobuilder"), "Directory under which to build")
    +	buildroot     = flag.String("buildroot", defaultBuildRoot(), "Directory under which to build")
    

    buildroot というコマンドラインフラグのデフォルト値が変更されています。以前は os.TempDir() と "gobuilder" を結合したパスが直接使われていましたが、この変更により、新しく定義された defaultBuildRoot() 関数の戻り値がデフォルト値として使用されるようになりました。これにより、ビルドルートの決定ロジックが関数にカプセル化され、OSごとの挙動の切り替えが可能になります。

  2. defaultBuildRoot() 関数の追加:

    // defaultBuildRoot returns default buildroot directory.
    func defaultBuildRoot() string {
    	var d string
    	if runtime.GOOS == "windows" {
    		// will use c:\, otherwise absolute paths become too long
    		// during builder run, see http://golang.org/issue/3358.
    		d = `c:\`
    	} else {
    		d = os.TempDir()
    	}
    	return filepath.Join(d, "gobuilder")
    }
    

    この新しい関数は、デフォルトのビルドルートディレクトリを決定するロジックを含んでいます。

    • runtime.GOOS == "windows" の条件分岐により、実行環境がWindowsであるかどうかがチェックされます。
    • Windowsの場合、d にはハードコードされた c:\ が代入されます。これは、Windowsのパス長制限(issue 3358で言及されている問題)を回避するための戦略です。c:\ は非常に短いベースパスであり、その下に gobuilder ディレクトリが作成されても、パス全体の長さが制限を超える可能性が低くなります。
    • Windows以外の場合(else ブロック)、d には os.TempDir() の結果が代入されます。これは、他のOSではパス長が問題にならないため、通常の一時ディレクトリを使用する従来の挙動を維持するためです。
    • 最後に、選択されたベースディレクトリ d と文字列 "gobuilder" を filepath.Join() で結合し、完全なビルドルートパスとして返します。filepath.Join() を使用することで、OSに応じた適切なパス区切り文字が自動的に挿入されます。

この変更により、GoビルダはWindows環境でより短いベースパスを使用するようになり、パス長制限に起因するビルドやテストの失敗が減少することが期待されます。

関連リンク

参考にした情報源リンク