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

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

このコミットは、Go言語のビルドシステムにおいて、gccgoコンパイラが使用するパッケージディレクトリの命名規則を修正するものです。具体的には、パッケージディレクトリ名にGOOS(オペレーティングシステム)とGOARCH(アーキテクチャ)の情報を追加することで、cmd/go/build.gobuilder.includeArgsの挙動と一致させるように変更されています。これにより、異なるOSやアーキテクチャ向けのビルドが、それぞれ独立したパッケージディレクトリを持つようになり、ビルドの整合性が向上します。

コミット

commit 5b2f62615970532374c9bd1b48dfe7f7ffef217a
Author: Ian Lance Taylor <iant@golang.org>
Date:   Fri Oct 11 16:17:45 2013 -0700

    go/build: add GOOS and GOARCH to name of gccgo pkg directory
    
    This matches the behaviour of builder.includeArgs in
    cmd/go/build.go.
    
    R=golang-dev, minux.ma
    CC=golang-dev
    https://golang.org/cl/14535048

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

https://github.com/golang/go/commit/5b2f62615970532374c9bd1b48dfe7f7ffef217a

元コミット内容

go/build: add GOOS and GOARCH to name of gccgo pkg directory

This matches the behaviour of builder.includeArgs in
cmd/go/build.go.

変更の背景

Go言語のビルドシステムでは、コンパイルされたパッケージ(ライブラリ)は特定のディレクトリに保存されます。gccgoはGo言語のフロントエンドを持つGCCコンパイラであり、Goの標準コンパイラ(gc)とは異なるビルドパスやパッケージ管理の仕組みを持つことがあります。

このコミット以前は、go/buildパッケージがgccgo用のパッケージディレクトリ名を生成する際に、GOOS(ターゲットOS)とGOARCH(ターゲットアーキテクチャ)の情報を考慮していませんでした。しかし、cmd/go/build.go内のbuilder.includeArgsは、これらの環境変数を考慮してビルドパスを構築していました。この不一致により、異なるOSやアーキテクチャ向けのgccgoビルドが同じパッケージディレクトリを共有してしまう可能性がありました。これは、クロスコンパイルを行う際や、異なる環境でビルドされたパッケージが混在する際に問題を引き起こす可能性があります。

この変更の目的は、go/buildパッケージにおけるgccgoのパッケージディレクトリ命名規則を、cmd/go/build.goの既存の挙動と一致させることで、ビルドシステム全体の整合性を高め、異なる環境向けのビルドが適切に分離されるようにすることです。これにより、ビルドの信頼性と予測可能性が向上します。

前提知識の解説

  • GOOSGOARCH:

    • GOOSはGoプログラムが実行されるターゲットオペレーティングシステム(例: linux, windows, darwinなど)を指定する環境変数です。
    • GOARCHはGoプログラムが実行されるターゲットアーキテクチャ(例: amd64, arm, 386など)を指定する環境変数です。
    • これらの環境変数は、クロスコンパイルを行う際や、特定のプラットフォーム向けに最適化されたバイナリを生成する際に非常に重要です。
  • gccgo:

    • gccgoは、GCC(GNU Compiler Collection)のフロントエンドとして実装されたGo言語のコンパイラです。Go言語の標準コンパイラであるgcとは異なり、GCCの最適化パスやバックエンドを利用できるという特徴があります。
    • gccgoは、Goの標準ライブラリとは別に、独自のパッケージパスやビルド成果物の管理方法を持つことがあります。
  • go/buildパッケージ:

    • Go言語の標準ライブラリの一部であり、Goのソースコードパッケージの構造を解析し、ビルドに必要な情報を取得するための機能を提供します。
    • go buildコマンドなどのGoツールチェインの内部で利用され、ソースファイルの依存関係の解決、パッケージのインポートパスの解決などを行います。
  • cmd/go/build.go:

    • Goツールチェインのgo buildコマンドの実装の一部です。
    • ビルドプロセス全体を管理し、コンパイラの呼び出し、リンク、パッケージのインストールなどを行います。
    • builder.includeArgsは、ビルド時にコンパイラに渡されるインクルードパスなどの引数を生成するロジックの一部であり、GOOSGOARCHを考慮してパスを構築します。
  • パッケージディレクトリ:

    • Go言語では、コンパイルされたパッケージ(.aファイルなど)は、通常、$GOPATH/pkg以下の特定のディレクトリに保存されます。
    • これらのディレクトリは、Goのツールチェインがパッケージを検索し、リンクするために使用されます。

技術的詳細

このコミットの核心は、go/buildパッケージ内のContext.Importメソッドにおけるgccgoコンパイラ向けのパッケージアーカイブ(.aファイル)のパス生成ロジックの変更です。

変更前は、gccgoのパッケージアーカイブのパスは以下のように生成されていました。

pkga = "pkg/gccgo/" + dir + "lib" + elem + ".a"

このパスは、pkg/gccgo/という固定のプレフィックスを使用しており、GOOSGOARCHの情報を一切含んでいませんでした。このため、例えばLinux/amd64でビルドされたgccgoパッケージと、Windows/amd64でビルドされたgccgoパッケージが、同じpkg/gccgo/ディレクトリ以下に保存される可能性がありました。これは、異なるプラットフォーム向けのバイナリが混在し、予期せぬビルドエラーやランタイムエラーを引き起こす原因となります。

このコミットでは、この行が以下のように変更されました。

pkga = "pkg/gccgo_" + ctxt.GOOS + "_" + ctxt.GOARCH + "/" + dir + "lib" + elem + ".a"

この変更により、pkg/gccgo/の後に_区切りで現在のContextオブジェクトが持つGOOSGOARCHの値が追加されるようになりました。例えば、Linux/amd64環境であればpkg/gccgo_linux_amd64/、Windows/386環境であればpkg/gccgo_windows_386/といった形で、プラットフォーム固有のディレクトリが生成されるようになります。

この修正は、cmd/go/build.go内のbuilder.includeArgsが既にGOOSGOARCHを考慮してビルドパスを構築している挙動と一致させるためのものです。これにより、go/buildパッケージが生成するパッケージディレクトリのパスと、cmd/goが期待するパスとの間に整合性が生まれ、gccgoを用いたクロスコンパイルやマルチプラットフォームビルドがより堅牢になります。

結果として、各GOOS/GOARCHの組み合わせに対して独立したgccgoパッケージディレクトリが作成されるため、異なる環境向けのビルド成果物が適切に分離され、ビルドシステムの信頼性が向上します。

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

--- a/src/pkg/go/build/build.go
+++ b/src/pkg/go/build/build.go
@@ -445,7 +445,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
 	switch ctxt.Compiler {
 	case "gccgo":
 		dir, elem := pathpkg.Split(p.ImportPath)
-		pkga = "pkg/gccgo/" + dir + "lib" + elem + ".a"
+		pkga = "pkg/gccgo_" + ctxt.GOOS + "_" + ctxt.GOARCH + "/" + dir + "lib" + elem + ".a"
 	case "gc":
 		suffix := ""
 		if ctxt.InstallSuffix != "" {

コアとなるコードの解説

変更された行は、src/pkg/go/build/build.goファイルのContext.Importメソッド内にあります。このメソッドは、指定されたインポートパスに基づいてパッケージをインポートする際に呼び出されます。

switch ctxt.Compiler文は、現在使用されているコンパイラの種類(gccgoまたはgc)に基づいて異なるロジックを実行します。

変更があったのはcase "gccgo":のブロック内です。

  • 変更前:

    pkga = "pkg/gccgo/" + dir + "lib" + elem + ".a"
    

    この行では、gccgoコンパイラが生成するパッケージアーカイブ(.aファイル)のパスを構築しています。dirはパッケージのディレクトリ部分、elemはパッケージ名です。このパスは常にpkg/gccgo/という固定のプレフィックスで始まっていました。

  • 変更後:

    pkga = "pkg/gccgo_" + ctxt.GOOS + "_" + ctxt.GOARCH + "/" + dir + "lib" + elem + ".a"
    

    変更後では、pkg/gccgo/の代わりにpkg/gccgo_に続けて、現在のビルドコンテキスト(ctxt)から取得したGOOSGOARCHの値がアンダースコアで連結されて追加されています。これにより、生成されるパッケージディレクトリのパスは、pkg/gccgo_linux_amd64/pkg/gccgo_windows_386/のように、ターゲットのOSとアーキテクチャに固有のものとなります。

この修正により、gccgoでビルドされたパッケージは、そのターゲットプラットフォームに応じた専用のディレクトリに保存されるようになり、異なるプラットフォーム向けのパッケージが混在することによる問題を回避します。これは、Goのビルドシステム全体の堅牢性と正確性を向上させるための重要な変更です。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Go言語のソースコード
  • GCCGoに関する情報
  • Goのビルドプロセスに関する一般的な知識