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

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

このコミットは、Go言語のビルドコマンド cmd/go において、インクルードディレクトリの決定方法を改善するものです。具体的には、go build コマンドに渡される -installsuffix フラグの値が、生成されるインクルードディレクトリのパスに適切に反映されるように変更されています。

コミット

commit 57f69710d5d0f8fb24bb07aa3ce83f98077d9112
Author: Dave Day <djd@golang.org>
Date:   Tue Oct 1 20:44:57 2013 -0400

    cmd/go: use -installsuffix to determine the includes directory list
    
    Currently, the directories generaed by includeArgs can have the "_race"
    suffix added if invoked with -race flag, but ignores -installsuffix if
    set.
    
    R=adg, rsc
    CC=golang-dev
    https://golang.org/cl/14174043

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

https://github.com/golang/go/commit/57f69710d5d0f8fb24bb07aa3ce83f98077d9112

元コミット内容

cmd/go: use -installsuffix to determine the includes directory list

現在、includeArgs によって生成されるディレクトリは、-race フラグが指定された場合に _race サフィックスが追加されることがありますが、-installsuffix が設定されていても無視されます。

変更の背景

Go言語のビルドシステムでは、コンパイルされたパッケージやライブラリが特定のディレクトリにインストールされます。これらのディレクトリは、Goのツールチェーンが依存関係を解決し、適切なバイナリをリンクするために使用されます。

従来、go build コマンドに -race フラグ(データ競合検出を有効にするためのフラグ)が渡された場合、生成されるインクルードディレクトリのパスには _race というサフィックスが自動的に追加されていました。これは、race検出が有効なビルドとそうでないビルドの成果物を区別し、衝突を避けるための仕組みです。

しかし、Goには -installsuffix という別のフラグも存在します。このフラグは、インストールされるパッケージのディレクトリ名に任意のサフィックスを追加するために使用されます。例えば、異なるバージョンのGoや異なるビルド設定でコンパイルされたパッケージを共存させたい場合などに利用されます。

このコミット以前は、-installsuffix が指定されても、インクルードディレクトリのパスにはそのサフィックスが反映されませんでした。これは、ユーザーが -installsuffix を使って意図的に異なるビルド環境を分離しようとしても、インクルードパスの不整合により問題が発生する可能性を意味していました。特に、Cgo(GoからC言語のコードを呼び出す機能)を使用する場合、Cコンパイラが正しいヘッダーファイルを見つけるために、正確なインクルードパスが必要となります。

この不整合を解消し、-installsuffix の意図された挙動を完全にサポートするために、この変更が導入されました。これにより、-installsuffix を使用してビルドされたパッケージのインクルードパスも、指定されたサフィックスを含むようになり、より堅牢で予測可能なビルド環境が提供されるようになりました。

前提知識の解説

  • Go言語のビルドシステム (cmd/go): go build, go install, go get などのコマンドを提供するGo言語の公式ツールチェーンの中核をなす部分です。ソースコードをコンパイルし、実行可能ファイルやライブラリを生成する役割を担います。
  • インクルードディレクトリ (Include Directories): C/C++などの言語において、ヘッダーファイル(.h ファイルなど)が置かれているディレクトリを指します。コンパイラはこれらのディレクトリを検索して、ソースコード中で include ディレクティブによって指定されたヘッダーファイルを見つけます。Go言語の文脈では、特にCgoを使用する際に、C言語のヘッダーファイルを探すためにこの概念が重要になります。
  • -race フラグ: go buildgo test コマンドに渡されるビルドフラグの一つです。これを指定すると、Goランタイムにデータ競合検出機能が組み込まれます。これにより、並行処理における潜在的なデータ競合バグをランタイムで検出できるようになります。このフラグが有効な場合、ビルド成果物や関連するディレクトリには _race サフィックスが付与されることがあります。
  • -installsuffix フラグ: go buildgo install コマンドに渡されるビルドフラグの一つです。このフラグを使用すると、インストールされるパッケージのディレクトリ名に任意のサフィックスを追加できます。例えば、go install -installsuffix=mybuild とすると、通常 pkg/linux_amd64 にインストールされるパッケージが pkg/linux_amd64_mybuild のようなディレクトリにインストールされます。これは、異なるビルド設定やGoのバージョンでコンパイルされたパッケージを同じGOPATH内で共存させるために非常に有用です。
  • filepath.Join: Go言語の path/filepath パッケージにある関数で、オペレーティングシステムに応じた適切なパス区切り文字を使用して、複数のパス要素を結合します。これにより、クロスプラットフォームでのパス操作が容易になります。
  • buildContext.InstallSuffix: Goのビルドコンテキスト内で、-installsuffix フラグによって指定された値が格納されるフィールドです。この値は、ビルドプロセス全体で利用され、インストールパスの決定などに影響を与えます。
  • buildRace: ビルドコンテキスト内で、-race フラグが有効になっているかどうかを示すブール値の変数です。

技術的詳細

このコミットは、src/cmd/go/build.go ファイル内の includeArgs 関数を変更しています。この関数は、Cgoを使用する際にCコンパイラに渡すインクルードパスを生成する役割を担っています。

変更前は、includeArgs 関数内でインクルードディレクトリのパスを構築する際、buildRace フラグが true の場合にのみ _race サフィックスを追加していました。しかし、buildContext.InstallSuffix の値は考慮されていませんでした。

変更後は、buildRace のチェックの代わりに buildContext.InstallSuffix != "" のチェックが行われるようになりました。これにより、-installsuffix フラグが指定され、その値が空文字列でない場合に、その値がインクルードディレクトリのパスにサフィックスとして追加されるようになります。具体的には、dir += "_" + buildContext.InstallSuffix という形でサフィックスが追加されます。

この変更により、-installsuffix を使用してビルドされたパッケージのインクルードパスも、そのサフィックスを含むようになります。これにより、Cgoを使用するプロジェクトにおいて、異なる -installsuffix でビルドされたライブラリが正しくリンクされるようになり、ビルドの整合性が向上します。

例えば、-installsuffix=debug を指定してビルドした場合、以前はインクルードパスが pkg/linux_amd64 のような形になっていましたが、この変更後は pkg/linux_amd64_debug のような形になり、Cコンパイラが正しいヘッダーファイルを見つけられるようになります。

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

変更は src/cmd/go/build.go ファイルの includeArgs 関数内で行われています。

--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -1052,8 +1052,8 @@ func (b *builder) includeArgs(flag string, all []*action) []string {
 			        dir = filepath.Join(dir, "gccgo_"+goos+"_"+goarch)
 			} else {
 			        dir = filepath.Join(dir, goos+"_"+goarch)
-			        if buildRace {
-			                dir += "_race"
+			        if buildContext.InstallSuffix != "" {
+			                dir += "_" + buildContext.InstallSuffix
 			        }
 			}
 			inc = append(inc, flag, dir)

コアとなるコードの解説

上記の差分は、src/cmd/go/build.go ファイル内の includeArgs 関数の一部を示しています。

  • dir = filepath.Join(dir, goos+"_"+goarch): この行は、GoのOS (goos) とアーキテクチャ (goarch) に基づいて、プラットフォーム固有のディレクトリパスを構築しています。例えば、Linux AMD64環境であれば linux_amd64 のようなサフィックスが追加されます。
  • - if buildRace {- dir += "_race": 変更前のコードでは、buildRace というブール変数が true(つまり、-race フラグが指定されている)の場合にのみ、ディレクトリパスに _race というサフィックスを追加していました。
  • + if buildContext.InstallSuffix != "" {+ dir += "_" + buildContext.InstallSuffix: 変更後のコードでは、buildRace のチェックが削除され、代わりに buildContext.InstallSuffix が空文字列でないかどうかがチェックされます。buildContext.InstallSuffix は、-installsuffix フラグによって指定された値が格納されているフィールドです。もしこの値が設定されていれば、その値の前にアンダースコア (_) を付けてディレクトリパスに追加します。

この変更により、インクルードディレクトリの命名規則が -race フラグだけでなく、より汎用的な -installsuffix フラグによって制御されるようになりました。これにより、ユーザーはビルド成果物のインストールパスをより柔軟にカスタマイズできるようになり、異なるビルド設定間での衝突を避けることが可能になります。

関連リンク

参考にした情報源リンク

  • https://golang.org/cl/14174043 (元のGerritチェンジリスト)
  • Go言語のソースコード (src/cmd/go/build.go)
  • Go言語の公式ドキュメント
  • Go言語のビルドシステムに関する一般的な知識