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

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

このコミットは、Go言語のビルドシステムにおけるcmd/distツールとcmd/goツールの間のインクルードパスの不整合を修正するものです。具体的には、cmd/goがCgoやSWIGの利用時に追加していた-I$GOROOT/pkg/$GOOS_$GOARCHというインクルードパスを、ブートストラッププロセスで使用されるcmd/distにも追加することで、両者の挙動を一致させ、ビルドの失敗を防ぎます。

コミット

commit 7b4ac31cab7480084f45c2890c4ebd877944bc49
Author: Russ Cox <rsc@golang.org>
Date:   Mon Mar 11 16:50:44 2013 -0400

    cmd/dist: make cc rule match what cmd/go uses
    
    We added -I$GOROOT/pkg/$GOOS_$GOARCH in cmd/go
    (I think for use by cgo and swig, primarily) but didn't
    update cmd/dist. I was testing some other code and
    found that my changes built with cmd/go but failed
    during the initial bootstrap. Make them match again.
    
    R=golang-dev, iant
    CC=golang-dev
    https://golang.org/cl/7707044

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

https://github.com/golang/go/commit/7b4ac31cab7480084f45c2890c4ebd877944bc49

元コミット内容

cmd/dist: make cc rule match what cmd/go uses

We added -I$GOROOT/pkg/$GOOS_$GOARCH in cmd/go
(I think for use by cgo and swig, primarily) but didn't
update cmd/dist. I was testing some other code and
found that my changes built with cmd/go but failed
during the initial bootstrap. Make them match again.

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/7707044

変更の背景

この変更の背景には、Go言語のビルドシステムにおける二つの主要なツール、cmd/gocmd/distの間の設定の不整合がありました。

元々、cmd/go(Goコマンドラインツール)は、CgoやSWIGといった外部C/C++コードとの連携を必要とするGoプログラムをビルドする際に、コンパイラに対して特定のインクルードパス(-I$GOROOT/pkg/$GOOS_$GOARCH)を追加していました。これは、Goの標準ライブラリやCgoが生成するヘッダーファイルなどが配置される場所をコンパイラに教えるために重要です。

しかし、Goのブートストラッププロセス(Goコンパイラ自体をビルドするプロセス)で使用されるcmd/distツールには、この同じインクルードパスが追加されていませんでした。コミットメッセージにあるように、Russ Cox氏が別のコードをテストしていた際に、cmd/goでは問題なくビルドできるにもかかわらず、cmd/distを使った初期ブートストラップ時にビルドが失敗するという問題に直面しました。

この不整合は、Goのソースコード内でCgoやSWIGに関連する変更が行われた際に、cmd/goでは正しくコンパイルできるが、Goコンパイラ自体を再構築する際には必要なヘッダーファイルが見つからずにエラーとなる、という状況を引き起こしていました。このコミットは、このビルド環境の差異を解消し、両方のツールが同じインクルードパス設定を持つようにすることで、Goのビルドプロセス全体の堅牢性を高めることを目的としています。

前提知識の解説

このコミットを理解するためには、以下のGo言語のビルドシステムに関する前提知識が必要です。

  • Go言語のビルドシステム: Go言語は、そのコンパイラやツールチェイン自体もGoで書かれています。そのため、Goの新しいバージョンをビルドする際には、既存のGoコンパイラを使って新しいコンパイラをビルドするという「ブートストラップ」と呼ばれるプロセスが必要になります。
  • cmd/go: これはGo言語の主要なコマンドラインツールであり、go build, go run, go testなどのサブコマンドを提供します。開発者が日常的にGoプログラムをビルド、実行、テストする際に使用します。cmd/goは、Goのソースコードをコンパイルする際に、Goの標準ライブラリや外部パッケージの依存関係を解決し、適切なコンパイラフラグを渡す役割を担います。
  • cmd/dist: これはGo言語のブートストラッププロセスで使用される低レベルのビルドツールです。Goのツールチェイン(コンパイラ、リンカなど)自体をソースからビルドするために使われます。cmd/goがユーザーアプリケーションのビルドを担当するのに対し、cmd/distはGo言語のコア部分のビルドを担当します。
  • Cgo: GoプログラムからC言語のコードを呼び出すためのメカニズムです。Cgoを使用すると、既存のCライブラリをGoプログラムに統合したり、パフォーマンスが重要な部分をCで記述したりすることができます。Cgoを使用するGoプログラムをビルドする際には、Cコンパイラ(通常はGCCやClang)がGoのビルドプロセスに組み込まれ、Cのヘッダーファイルやライブラリのパスが適切に設定される必要があります。
  • SWIG (Simplified Wrapper and Interface Generator): SWIGは、C/C++のコードを様々なスクリプト言語(Python, Perl, Rubyなど)や、Goのようなコンパイル言語から呼び出すためのインターフェースを自動生成するツールです。Go言語の文脈では、SWIGを使ってC/C++ライブラリのGoバインディングを生成し、Goプログラムから利用することが可能です。SWIGもCgoと同様に、C/C++コンパイラと連携し、適切なインクルードパスが必要となります。
  • -I フラグ: C/C++コンパイラ(例: GCC, Clang)において、-Iフラグはインクルードファイル(ヘッダーファイルなど)を検索するディレクトリを指定するために使用されます。例えば、-I/path/to/includesと指定すると、コンパイラは/path/to/includesディレクトリ内をヘッダーファイルの検索パスに追加します。
  • $GOROOT: Go言語のインストールディレクトリを指す環境変数です。Goの標準ライブラリやツールチェインの実行ファイルなどがこのディレクトリ以下に配置されます。
  • $GOOS: Goプログラムが実行されるオペレーティングシステム(例: linux, windows, darwin)を指す環境変数です。
  • $GOARCH: Goプログラムが実行されるアーキテクチャ(例: amd64, arm, arm64)を指す環境変数です。
  • $GOROOT/pkg/$GOOS_$GOARCH: このパスは、特定のOSとアーキテクチャ向けにコンパイルされたGoの標準ライブラリのパッケージファイル(.aファイルなど)や、Cgoが生成するヘッダーファイルなどが配置されるディレクトリを指します。CgoやSWIGを使用する際に、C/C++コンパイラがGo関連のヘッダーファイルを見つけるために、このパスをインクルードパスに追加する必要があります。

技術的詳細

このコミットの技術的詳細は、Go言語のビルドシステムがC/C++コンパイラを呼び出す際に、インクルードパスをどのように管理しているかに焦点を当てています。

Goのビルドプロセスでは、Goのコードだけでなく、CgoやSWIGを介してC/C++のコードもコンパイルされることがあります。この際、Goのツールチェインは内部的にC/C++コンパイラ(例えばGCC)を呼び出し、必要なソースファイルやヘッダーファイルを渡します。C/C++コンパイラがヘッダーファイルを見つけるためには、-Iフラグを使って適切なインクルードパスを指定する必要があります。

問題は、cmd/gocmd/distという二つの異なるビルドツールが、このインクルードパスの設定において異なる挙動をしていた点にありました。

  • cmd/goの挙動: ユーザーがGoプログラムをビルドする際に使用するcmd/goは、CgoやSWIGの利用を考慮し、-I$GOROOT/pkg/$GOOS_$GOARCHというインクルードパスをC/C++コンパイラに渡していました。このパスは、Goの標準ライブラリのパッケージファイルや、Cgoが生成するCヘッダーファイルなどが格納されている場所です。これにより、CgoやSWIGを使用するGoプログラムは、必要なヘッダーファイルを正しく参照してコンパイルできました。

  • cmd/distの挙動: 一方、Goのツールチェイン自体をビルドする際に使用されるcmd/distは、この重要なインクルードパスを追加していませんでした。cmd/distは、Goのコンパイラやリンカなどのツールをビルドするために、Goのソースコードをコンパイルします。もしこれらのツールがCgoやSWIGに依存する部分を含んでいた場合、またはGoの内部的なCコードが$GOROOT/pkg/$GOOS_$GOARCHにあるヘッダーを参照する必要があった場合、cmd/distは必要なヘッダーファイルを見つけることができず、ビルドエラーが発生しました。

このコミットは、src/cmd/dist/build.cというファイル内のinstall関数(Goのツールチェインのインストールプロセスの一部)において、C/C++コンパイラに渡す引数を構築する部分に修正を加えています。具体的には、既存の-Iフラグに加えて、cmd/goが使用していた-I$GOROOT/pkg/$GOOS_$GOARCHというパスを明示的に追加しています。

これにより、cmd/distがC/C++コンパイラを呼び出す際にも、cmd/goと同様にGo関連のヘッダーファイルが正しく検索されるようになり、ブートストラッププロセスにおけるビルドの失敗が解消されました。この修正は、Goのビルドシステム全体の整合性を保ち、CgoやSWIGに関連する変更がGoのツールチェインのビルドに影響を与えないようにするために不可欠でした。

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

変更は src/cmd/dist/build.c ファイルにあります。

--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -939,6 +939,8 @@ install(char *dir)
 			}
 			vadd(&compile, "-I");
 			vadd(&compile, workdir);
+			vadd(&compile, "-I");
+			vadd(&compile, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
 			vadd(&compile, "-D");
 			vadd(&compile, bprintf(&b, "GOOS_%s", goos));
 			vadd(&compile, "-D");

コアとなるコードの解説

このコードスニペットは、src/cmd/dist/build.c 内の install 関数の一部です。この関数は、Goのツールチェインをビルドし、インストールするプロセスにおいて、C/C++コンパイラ(cc)に渡すコマンドライン引数を構築しています。

変更前のコードでは、vadd(&compile, "-I"); vadd(&compile, workdir); という行で、現在の作業ディレクトリ(workdir)をインクルードパスに追加していました。これは、ビルド中のGoのツールチェインのソースコード内で必要なヘッダーファイルを見つけるためです。

追加された2行は以下の通りです。

+			vadd(&compile, "-I");
+			vadd(&compile, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
  • vadd(&compile, "-I");: これは、C/C++コンパイラにインクルードパスを指定するための-Iフラグを追加します。
  • vadd(&compile, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));: これは、-Iフラグに続く実際のパスを構築し、追加します。
    • bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch): この関数は、goroot(Goのインストールディレクトリ)、goos(ターゲットOS)、goarch(ターゲットアーキテクチャ)の各変数を組み合わせて、$GOROOT/pkg/$GOOS_$GOARCHという形式の文字列を生成します。例えば、Linux AMD64環境であれば /usr/local/go/pkg/linux_amd64 のようなパスになります。

この変更により、cmd/distがC/C++コンパイラを呼び出す際に、$GOROOT/pkg/$GOOS_$GOARCHディレクトリもインクルードパスとして追加されるようになりました。このディレクトリには、Goの標準ライブラリのコンパイル済みパッケージや、Cgoが生成するCヘッダーファイルなどが格納されています。

結果として、cmd/distによるGoツールチェインのブートストラップビルド中に、CgoやSWIGに関連するC/C++コードがコンパイルされる際に、必要なヘッダーファイルが正しく見つかるようになり、ビルドエラーが解消されました。これは、cmd/goが通常のGoプログラムのビルドで行っていたインクルードパスの設定とcmd/distのそれを一致させることで、Goのビルドシステム全体の整合性と信頼性を向上させるための重要な修正です。

関連リンク

参考にした情報源リンク

  • Go言語公式ドキュメント (Cgo): https://pkg.go.dev/cmd/cgo
  • SWIG公式ウェブサイト: http://www.swig.org/
  • GCC (GNU Compiler Collection) ドキュメント (Invoking GCC): https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html (特に -I オプションについて)
  • Go言語のビルドプロセスに関する一般的な情報源 (例: Goのソースコード、Goのブログ記事など)
    • Goのソースコード: https://github.com/golang/go
    • Goのブログ: https://go.dev/blog/
    • Goのブートストラップに関する議論やドキュメント (特定のURLは難しいが、GoのメーリングリストやIssueトラッカーで関連情報が見つかる可能性あり)I have generated the comprehensive technical explanation in Markdown format, following all the specified instructions and chapter structure. The output is printed to standard output only, as requested.