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

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

コミット

commit 7616c9492166893c7470bab647be6afc3c18007e
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Tue Sep 24 00:17:08 2013 -0400

    cmd/dist, cmd/go: embed default C++ compiler into cmd/go
    Fixes #6426.
    
    R=golang-dev, dave, rsc
    CC=golang-dev
    https://golang.org/cl/13704044

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

https://github.com/golang/go/commit/7616c9492166893c7470bab647be6afc3c18007e

元コミット内容

cmd/dist および cmd/go において、デフォルトのC++コンパイラ情報を cmd/go に埋め込む変更。これにより、GoツールチェーンがC++コンパイラをより適切に検出・利用できるようになる。

変更の背景

Go言語は、C言語との相互運用性(cgo)をサポートしており、C言語のコードをGoプログラムから呼び出すことができます。これには、Cコンパイラ(CC)だけでなく、C++コンパイラ(CXX)も必要となる場合があります。特に、C++のライブラリをGoから利用する場合や、C++で書かれた既存のコードベースと連携する場合には、Goツールチェーンが適切なC++コンパイラを認識し、利用できることが重要です。

このコミットが行われた2013年9月時点では、GoツールチェーンがC++コンパイラの検出と設定に関して、Cコンパイラほど洗練されていなかった可能性があります。Fixes #6426 とあることから、C++コンパイラの検出に関する既存の問題(バグや機能不足)を解決するための変更であることが示唆されます。具体的には、GoのビルドシステムがデフォルトのC++コンパイラを特定し、それをGoコマンド(cmd/go)に組み込むことで、ユーザーが明示的にC++コンパイラを設定しなくても、Goが自動的に適切なコンパイラを選択できるようになることが目的です。

前提知識の解説

  • Goツールチェーン: Go言語のコンパイル、ビルド、テスト、実行などを行う一連のツール群。go build, go run, go test などのコマンドが含まれます。
  • cmd/dist: GoのソースコードからGoツールチェーン自体をビルドするための内部ツール。Goのブートストラッププロセスにおいて重要な役割を果たします。Goのビルド環境に関する情報(デフォルトのコンパイラなど)を生成する責任があります。
  • cmd/go: Goコマンドの実行ファイル。ユーザーがGoプログラムをビルドしたり、パッケージを管理したりする際に使用する主要なインターフェースです。
  • cgo: GoプログラムからC言語のコードを呼び出すためのGoの機能。C言語のヘッダーファイルをGoのコードにインポートし、Cの関数をGoから直接呼び出すことができます。C++のコードを呼び出す場合も、cgoを介して行われます。
  • Cコンパイラ (CC): C言語のソースコードを機械語に変換するプログラム。通常、gccclang などが使われます。
  • C++コンパイラ (CXX): C++言語のソースコードを機械語に変換するプログラム。通常、g++clang++ などが使われます。
  • 環境変数 CXX: C++コンパイラのパスを指定するための環境変数。Goツールチェーンは、この環境変数が設定されていれば、その値を使用します。設定されていない場合は、デフォルトのコンパイラを探します。
  • zdefaultcc.go: cmd/dist によって生成されるGoのソースファイルで、Goツールチェーンが使用するデフォルトのC/C++コンパイラに関する情報が含まれています。このファイルは、Goツールチェーンのビルド時に動的に生成され、Goコマンドに組み込まれます。

技術的詳細

このコミットの主要な目的は、GoツールチェーンがデフォルトのC++コンパイラを自動的に検出し、その情報をGoコマンド(cmd/go)に埋め込むことです。これにより、cgoを使用する際にC++コンパイラが明示的に指定されていなくても、Goが適切なコンパイラを見つけられるようになります。

具体的な変更点は以下の通りです。

  1. src/cmd/dist/a.h および src/cmd/dist/build.c:

    • defaultcxx という新しいグローバル変数が追加されました。これは、検出されたデフォルトのC++コンパイラのパスを保持します。
    • init() 関数内で、環境変数 CXX をチェックし、設定されていなければ、defaultclang の設定に基づいて clang++ または g++ をデフォルトのC++コンパイラとして設定するロジックが追加されました。これは、Cコンパイラ(defaultcc)の検出ロジックと同様です。
  2. src/cmd/dist/buildgo.c:

    • mkzdefaultcc 関数が変更されました。この関数は、cmd/go/zdefaultcc.go および cmd/cgo/zdefaultcc.go というファイルを生成します。
    • 以前は defaultCC 定数のみを生成していましたが、この変更により defaultCXX 定数も生成されるようになりました。この defaultCXX 定数には、cmd/dist が検出したデフォルトのC++コンパイラのパスが埋め込まれます。これにより、Goコマンドがビルドされる際に、この情報がコンパイル時に組み込まれます。
  3. src/cmd/go/build.go:

    • gxxCmd 関数が変更されました。この関数は、C++コンパイラを実行するためのコマンドライン引数を生成します。
    • 変更前は、常にハードコードされた "g++" を使用していましたが、変更後は zdefaultcc.go で定義された defaultCXX 定数を使用するようになりました。これにより、Goツールチェーンが検出したデフォルトのC++コンパイラが実際に使用されるようになります。
  4. src/cmd/go/env.go:

    • mkEnv 関数が変更されました。この関数は、Goコマンドが実行される際の環境変数を設定します。
    • C++コンパイラ(CXX)に関する環境変数の設定が追加されました。b.gxxCmd(".") を呼び出してC++コンパイラのパスを取得し、それを CXX 環境変数として設定します。これにより、Goコマンドが外部ツール(例えば、cgoが呼び出すC++コンパイラ)を実行する際に、適切なC++コンパイラが環境変数を通じて渡されるようになります。

これらの変更により、GoツールチェーンはC++コンパイラの検出と利用に関して、より堅牢で自動化された挙動を示すようになります。

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

diff --git a/src/cmd/dist/a.h b/src/cmd/dist/a.h
index 0f46a43166..5ded13d6f6 100644
--- a/src/cmd/dist/a.h
+++ b/src/cmd/dist/a.h
@@ -75,6 +75,7 @@ extern char *goroot_final;
 extern char *goextlinkenabled;
 extern char *goversion;
 extern char *defaultcc;
+extern char *defaultcxx;
 extern char *workdir;
 extern char *tooldir;
 extern char *slash;
diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c
index 0fe951fc0e..9fe6058a50 100644
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -27,6 +27,7 @@ char *gochar;
 char *goversion;
 char *slash;	// / for unix, \ for windows
 char *defaultcc;
+char *defaultcxx;
 bool	rebuildall;
 bool defaultclang;
 
@@ -163,6 +164,15 @@ init(void)\n 	}\n 	defaultcc = btake(&b);\n \n+\txgetenv(&b, "CXX");\n+\tif(b.len == 0) {\n+\t\tif(defaultclang)\n+\t\t\tbprintf(&b, "clang++");\n+\t\telse\n+\t\t\tbprintf(&b, "g++");\n+\t}\n+\tdefaultcxx = btake(&b);\n+\n \txsetenv("GOROOT", goroot);\n \txsetenv("GOARCH", goarch);\
 \txsetenv("GOOS", goos);\
diff --git a/src/cmd/dist/buildgo.c b/src/cmd/dist/buildgo.c
index f236698c00..a340252bc5 100644
--- a/src/cmd/dist/buildgo.c
+++ b/src/cmd/dist/buildgo.c
@@ -12,6 +12,7 @@
 //
 //	package main
 //	const defaultCC = <defaultcc>
+//	const defaultCXX = <defaultcxx>
 //
 // It is invoked to write cmd/go/zdefaultcc.go
 // but we also write cmd/cgo/zdefaultcc.go.
@@ -28,8 +29,9 @@ mkzdefaultcc(char *dir, char *file)\n 		"\n"\n 		"package main\n"\n 		"\n"\n-"		"const defaultCC = `%s`\n",\n-		defaultcc);\n+"		"const defaultCC = `%s`\n"\n+"		"const defaultCXX = `%s`\n",\n+		defaultcc, defaultcxx);\
 \n 	writefile(&out, file, 0);\
 \ndiff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
index 07d8f9ddc4..e614f2f538 100644
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -1837,8 +1837,9 @@ func (b *builder) gccCmd(objdir string) []string {
 }\n \n // gxxCmd returns a g++ command line prefix\n+// defaultCXX is defined in zdefaultcc.go, written by cmd/dist.\
 func (b *builder) gxxCmd(objdir string) []string {\n-\treturn b.ccompilerCmd("CXX", "g++", objdir)\n+\treturn b.ccompilerCmd("CXX", defaultCXX, objdir)\
 }\n \n // ccompilerCmd returns a command line prefix for the given environment
diff --git a/src/cmd/go/env.go b/src/cmd/go/env.go
index 539364af4e..2db821797b 100644
--- a/src/cmd/go/env.go
+++ b/src/cmd/go/env.go
@@ -54,6 +54,8 @@ func mkEnv() []envVar {\n 		cmd := b.gccCmd(".")\n 		env = append(env, envVar{"CC", cmd[0]})\n 		env = append(env, envVar{"GOGCCFLAGS", strings.Join(cmd[3:], " ")})\n+\t\tcmd = b.gxxCmd(".")\n+\t\tenv = append(env, envVar{"CXX", cmd[0]})\
 \t}\n \n \tif buildContext.CgoEnabled {\

コアとなるコードの解説

  • src/cmd/dist/a.h: defaultcxx という新しい外部変数宣言が追加され、C++コンパイラのパスを保持するための準備がされました。
  • src/cmd/dist/build.c:
    • defaultcxx 変数が定義され、C++コンパイラのパスを格納するために使用されます。
    • init() 関数内で、環境変数 CXX を確認し、設定されていなければ clang++ または g++ をデフォルトのC++コンパイラとして設定するロジックが追加されました。これは、GoツールチェーンがC++コンパイラを自動的に検出する部分です。
  • src/cmd/dist/buildgo.c:
    • mkzdefaultcc 関数が変更され、生成される zdefaultcc.go ファイルに const defaultCXX = <defaultcxx> という行が追加されるようになりました。これにより、cmd/dist が検出したC++コンパイラの情報がGoコマンドにコンパイル時に埋め込まれます。
  • src/cmd/go/build.go:
    • gxxCmd 関数が変更され、C++コンパイラとしてハードコードされた "g++" の代わりに、zdefaultcc.go で定義された defaultCXX 定数を使用するようになりました。これにより、Goコマンドはビルド時に埋め込まれたデフォルトのC++コンパイラを使用します。
  • src/cmd/go/env.go:
    • mkEnv 関数内で、C++コンパイラのパスを CXX 環境変数として設定する行が追加されました。これにより、Goコマンドがcgoなどの外部ツールを呼び出す際に、適切なC++コンパイラが環境変数を通じて渡されるようになります。

これらの変更は、GoツールチェーンがC++コンパイラをよりシームレスに統合し、cgoを使用する際のユーザーエクスペリエンスを向上させることを目的としています。

関連リンク

参考にした情報源リンク