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

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

このコミットは、Go言語のビルドシステムにおける CGO_ENABLED 環境変数の管理方法に関する重要な変更を導入しています。具体的には、CGO_ENABLED の設定ロジックを、Goの配布版ビルドツール (cmd/dist) から、一般的なGoコマンド (cmd/go) の環境変数表示機能 (go env) へと移行しています。これにより、特定のOS/アーキテクチャの組み合わせがcgoをサポートしているかどうかの知識の重複を排除し、Goの環境設定の一元化を図っています。また、Goのテストスクリプト (src/run.bash および src/sudo.bash) も、この変更に合わせて go tool dist env の代わりに go env を使用するように更新されています。

コミット

commit 6d4da06d3647607081819e444be60259225d0efe
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Sat Mar 10 03:42:23 2012 +0800

    cmd/dist, cmd/go: move CGO_ENABLED from 'go tool dist env' to 'go env'
            So that we don't duplicate knowledge about which OS/ARCH combination
            supports cgo.
            Also updated src/run.bash and src/sudo.bash to use 'go env'.
    
    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/5792055
---
 src/cmd/dist/build.c | 18 ------------------
 src/cmd/go/env.go    |  6 ++++++
 src/run.bash         |  2 +--
 src/sudo.bash        |  2 +--
 4 files changed, 8 insertions(+), 20 deletions(-)

diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c
index d5fcfbedb3..acd7347aa8 100644
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -52,19 +52,6 @@ static char *okgoos[] = {
  	"windows",
 };
 
-// The known cgo-enabled combinations.
-// This list is also known to ../../pkg/go/build/build.go.
-static char *okcgo[] = {
-	"darwin/386",
-	"darwin/amd64",
-	"linux/386",
-	"linux/amd64",
-	"freebsd/386",
-	"freebsd/amd64",
-	"windows/386",
-	"windows/amd64",
-};
-
 static void rmworkdir(void);
 
 // find reports the first index of p in l[0:n], or else -1.
@@ -1321,11 +1308,6 @@ cmdenv(int argc, char **argv)
  		xprintf(format, "GOTOOLDIR", tooldir);
  		xprintf(format, "GOCHAR", gochar);
 
-\tif(find(bprintf(&b, "%s/%s", goos, goarch), okcgo, nelem(okcgo)) >= 0)
-\t\txprintf(format, "CGO_ENABLED", "1");
-\telse
-\t\txprintf(format, "CGO_ENABLED", "0");
-\
  	if(pflag) {
  		sep = ":";
  		if(streq(gohostos, "windows"))
diff --git a/src/cmd/go/env.go b/src/cmd/go/env.go
index 804dc8e63f..d5b0348096 100644
--- a/src/cmd/go/env.go
+++ b/src/cmd/go/env.go
@@ -45,6 +45,12 @@ func mkEnv() []envVar {\n \t\t{"GOGCCFLAGS", strings.Join(b.gccCmd(".")[3:], " ")},\n \t}\n \n+\tif buildContext.CgoEnabled {\n+\t\tenv = append(env, envVar{"CGO_ENABLED", "1"})\n+\t} else {\n+\t\tenv = append(env, envVar{"CGO_ENABLED", "0"})\n+\t}\n+\n \treturn env\n }\n \ndiff --git a/src/run.bash b/src/run.bash
index 0e4600b0ad..430ee76dba 100755
--- a/src/run.bash
+++ b/src/run.bash
@@ -5,7 +5,7 @@
 
 set -e
 
-eval $(go tool dist env)
+eval $(go env)
 
 unset CDPATH	# in case user has it set
 
diff --git a/src/sudo.bash b/src/sudo.bash
index 78cdb0b8a7..cccebd3427 100755
--- a/src/sudo.bash
+++ b/src/sudo.bash
@@ -17,7 +17,7 @@ if [[ ! -d /usr/local/bin ]]; then
  		exit 2
 fi
 
-eval $(go tool dist env)
+eval $(go env)
 cd $(dirname $0)
 for i in prof cov
 do

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

https://github.com/golang/go/commit/6d4da06d3647607081819e444be60259225d0efe

元コミット内容

このコミットの目的は、CGO_ENABLED 環境変数の設定ロジックを go tool dist env から go env へと移動することです。これにより、どのOS/アーキテクチャの組み合わせがcgoをサポートしているかという知識の重複を排除します。また、src/run.bashsrc/sudo.bashgo env を使用するように更新されます。

変更の背景

Go言語のビルドシステムでは、C言語のコードをGoプログラムから呼び出すためのツールであるcgoの有効/無効を制御する CGO_ENABLED という環境変数があります。この変数の値は、Goのビルドプロセスにおいて非常に重要です。

このコミット以前は、CGO_ENABLED のデフォルト値(特定のOS/アーキテクチャの組み合わせでcgoが有効になるかどうか)に関する知識が、Goの配布版をビルドするためのツールである cmd/dist と、Goのビルドシステムの中核をなす go/build パッケージの両方に存在していました。これは「知識の重複」を意味し、将来的にcgoのサポート状況が変更された場合、複数の場所を更新する必要があるという保守性の問題を引き起こします。

この変更の主な目的は、この知識の重複を解消し、CGO_ENABLED の決定ロジックを一元化することにあります。go env コマンドは、ユーザーがGoの環境設定を確認するための主要なインターフェースであり、Goのビルドシステムが内部的に使用する環境変数を正確に反映するべきです。したがって、CGO_ENABLED の決定ロジックを go env の内部に移動することで、この変数の真のソースを一つに集約し、システム全体の整合性と保守性を向上させることができます。

また、Goのテストスクリプト (src/run.bashsrc/sudo.bash) が go tool dist env を使用して環境変数を設定していたことも、この変更の動機の一つです。go tool dist env はGoの配布版ビルドに特化したツールであり、一般的なGo開発やテストのシナリオでは go env を使用する方が適切です。この変更により、テストスクリプトもより一般的な go env を利用するようになり、Goの環境設定に関するベストプラクティスに沿う形になります。

前提知識の解説

Goのビルドシステム

Go言語は、ソースコードをコンパイルして実行可能なバイナリを生成するための強力なビルドシステムを内蔵しています。このシステムは、依存関係の解決、クロスコンパイル、テストの実行など、様々なタスクを自動化します。Goのビルドシステムは、GOOS (オペレーティングシステム)、GOARCH (アーキテクチャ)、GOROOT (Goのインストールディレクトリ)、GOPATH (Goのワークスペースディレクトリ) など、様々な環境変数に依存して動作します。

go tool dist

go tool dist は、Go言語の配布版(ディストリビューション)をビルド、テスト、インストールするための低レベルなツールです。これは主にGoの開発者や、GoのソースコードからGo自体をビルドする際に使用されます。go tool dist env サブコマンドは、Goツールチェーンのビルドシステムが使用する環境変数を表示するために設計されています。これは、Goの内部ビルドプロセスに関する詳細な情報を提供しますが、一般的なGoアプリケーションの開発者が日常的に使用するものではありません。

go env

go env は、Go言語の環境変数を表示するためのコマンドです。これは、Goプログラムのビルドや実行に影響を与える様々な設定(GOOS, GOARCH, GOROOT, GOPATH など)をユーザーが簡単に確認できるようにするために提供されています。go env は、Goのビルドコマンド (go build, go run など) がどのように動作するかを理解する上で非常に役立ちます。このコマンドは、Go開発者にとって日常的に使用される重要なツールです。

CGO_ENABLED

CGO_ENABLED は、GoプログラムがC言語のコードを呼び出すためのツールである cgo を有効にするかどうかを制御する環境変数です。

  • CGO_ENABLED=1: cgoが有効になります。これにより、GoコードはCライブラリと連携できるようになります。cgoが有効な場合、Goプログラムは通常、Cライブラリに対して動的リンクを使用するため、生成されるバイナリは小さくなりますが、ターゲットシステムに共有ライブラリファイルが存在する必要があります。
  • CGO_ENABLED=0: cgoが無効になります。GoコードはC関数を呼び出すことができません。cgoを無効にすると、Goプログラムは完全に自己完結型の静的リンクされたバイナリを生成しやすくなります。これは、配布が容易で、ターゲットシステムに特定のライブラリがインストールされている必要がないという利点があります。

デフォルトでは、CGO_ENABLED は一般的なプラットフォーム(Windows、macOS、Linux)の標準アーキテクチャ(amd64、386、armなど)では 1 に設定されています。しかし、クロスコンパイルを行う場合、Cのクロスコンパイル環境のセットアップが複雑になるため、デフォルトで無効になることがあります。

eval $(...)

eval $(...) は、シェルスクリプトでコマンドの出力を評価し、その結果を現在のシェルのコマンドとして実行するための一般的なパターンです。このコミットの文脈では、go tool dist envgo env の出力が VAR=VALUE の形式で環境変数の定義を含んでいるため、eval $(go env) とすることで、これらの環境変数を現在のシェルセッションに設定することができます。

技術的詳細

このコミットの技術的詳細は、主に以下の3つの側面から構成されています。

  1. src/cmd/dist/build.c からの CGO_ENABLED 決定ロジックの削除:

    • 以前は、Goの配布版をビルドする際に使用される cmd/dist ツールの一部である build.c ファイル内に、特定のOS/アーキテクチャの組み合わせ (darwin/386, linux/amd64 など) に対して CGO_ENABLED1 に設定するかどうかを決定するロジックが存在していました。
    • このロジックは、okcgo という静的配列にcgoが有効な組み合わせのリストを持ち、現在の goos/goarch がそのリストに含まれるかどうかを find 関数でチェックしていました。
    • このコミットでは、この okcgo 配列と、それに基づいて CGO_ENABLEDxprintf で出力するコードブロックが完全に削除されました。これにより、cmd/distCGO_ENABLED のデフォルト値を決定する責任を持たなくなりました。
  2. src/cmd/go/env.go への CGO_ENABLED 決定ロジックの移動:

    • CGO_ENABLED の決定ロジックは、Goの主要コマンドである go コマンドの環境変数表示機能 (go env) を実装する src/cmd/go/env.go ファイルに移動されました。
    • 具体的には、mkEnv() 関数内で、buildContext.CgoEnabled の値に基づいて CGO_ENABLED 環境変数を 1 または 0 に設定し、env スライスに追加するようになりました。
    • buildContext.CgoEnabled は、Goのビルドシステムが内部的にcgoの有効/無効を判断する際に使用する真のソースです。この変更により、go env が常にGoのビルドシステムが認識している正確な CGO_ENABLED の状態を報告するようになります。
  3. src/run.bash および src/sudo.bash の更新:

    • Goのテストスイートを実行するためのシェルスクリプトである src/run.bash と、特権昇格を伴うテストを実行するための src/sudo.bash は、以前は eval $(go tool dist env) を使用してGoの環境変数を設定していました。
    • このコミットでは、これらのスクリプトが eval $(go env) を使用するように変更されました。
    • この変更は、CGO_ENABLED の決定ロジックが go env に移動されたことと整合性を保つだけでなく、一般的なGo開発の文脈でより適切な go env コマンドを使用するというベストプラクティスにも従っています。

この変更が「知識の重複を避ける」という目的を達成しているのは、CGO_ENABLED のデフォルト値に関する情報が、cmd/dist のビルドロジックと go/build パッケージの両方に散在していた状態から、go/build パッケージ(buildContext.CgoEnabled を通じて)がその真のソースとなり、go env がその情報を公開する唯一のインターフェースとなるためです。これにより、cgoのサポート状況に関する変更があった場合でも、更新すべき場所が明確になり、システム全体の整合性が保たれます。

go tool dist envgo env の違いは、前者がGoの配布版ビルドという特定の目的のための低レベルな環境情報を提供するのに対し、後者は一般的なGo開発環境の環境情報を提供するという点にあります。このコミットは、CGO_ENABLED のような一般的なビルド設定に関する情報を、より広範なGo開発者コミュニティにとって関連性の高い go env に集約することで、Goのツールエコシステムをより直感的で一貫性のあるものにしています。

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

src/cmd/dist/build.c

// 削除されたコードブロック
// The known cgo-enabled combinations.
// This list is also known to ../../pkg/go/build/build.go.
static char *okcgo[] = {
	"darwin/386",
	"darwin/amd64",
	"linux/386",
	"linux/amd64",
	"freebsd/386",
	"freebsd/amd64",
	"windows/386",
	"windows/amd64",
};

// ...

// 削除されたCGO_ENABLEDの設定ロジック
-\tif(find(bprintf(&b, "%s/%s", goos, goarch), okcgo, nelem(okcgo)) >= 0)
-\t\txprintf(format, "CGO_ENABLED", "1");
-\telse
-\t\txprintf(format, "CGO_ENABLED", "0");

src/cmd/go/env.go

// 追加されたCGO_ENABLEDの設定ロジック
+\tif buildContext.CgoEnabled {\n+\t\tenv = append(env, envVar{"CGO_ENABLED", "1"})\n+\t} else {\n+\t\tenv = append(env, envVar{"CGO_ENABLED", "0"})\n+\t}\n+\

src/run.bash

-eval $(go tool dist env)
+eval $(go env)

src/sudo.bash

-eval $(go tool dist env)
+eval $(go env)

コアとなるコードの解説

src/cmd/dist/build.c の変更

このファイルから okcgo という静的配列と、それを用いて CGO_ENABLED の値を決定し出力するロジックが削除されました。これは、cmd/dist がcgoのサポート状況に関する知識を持つ必要がなくなり、その責任がGoのビルドシステムの中核部分に委譲されたことを意味します。これにより、cgoのサポートに関する情報が複数の場所に分散している状態が解消され、保守性が向上します。

src/cmd/go/env.go の変更

mkEnv() 関数内に、buildContext.CgoEnabled の値に基づいて CGO_ENABLED 環境変数を設定するロジックが追加されました。buildContext.CgoEnabled は、Goのビルドシステムが現在の環境でcgoが有効であると判断しているかどうかを示すブール値です。この変更により、go env コマンドは、Goのビルドシステムが実際に使用する CGO_ENABLED の値を正確に反映するようになります。これは、Goの環境設定に関する情報の一貫性を保つ上で非常に重要です。

src/run.bash および src/sudo.bash の変更

これらのシェルスクリプトでは、環境変数を設定するために go tool dist env の代わりに go env を使用するように変更されました。これは、CGO_ENABLED の決定ロジックが go env に移動されたことと直接関連しています。テストスクリプトが go env を使用することで、Goのビルドシステムが認識している最新かつ正確な環境設定を確実に取得できるようになります。また、これはGoの一般的な開発ワークフローにおいて go env が推奨されるツールであるという点にも合致しています。

関連リンク

参考にした情報源リンク