[インデックス 15795] ファイルの概要
このコミットは、src/pkg/net/empty.c
という新しいファイルを追加しています。このファイルは、Goの net
パッケージが CGO_ENABLED=0
の設定でビルドされる際に発生するコンパイラエラーを回避するために導入されました。
コミット
commit ca15ac36ede807c53c5f1b8778061eb70cbff616
Author: Dmitriy Vyukov <dvyukov@google.com>
Date: Fri Mar 15 22:23:35 2013 +0400
net: fix build with CGO_ENABLED=0
R=golang-dev, rsc, mikioh.mikioh
CC=golang-dev
https://golang.org/cl/7857044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/ca15ac36ede807c53c5f1b8778061eb70cbff616
元コミット内容
net: fix build with CGO_ENABLED=0
R=golang-dev, rsc, mikioh.mikioh
CC=golang-dev
https://golang.org/cl/7857044
変更の背景
このコミットは、Goのビルドプロセスにおいて CGO_ENABLED=0
という環境変数が設定されている場合に、net
パッケージのビルドが失敗する問題を解決するために行われました。
Goの net
パッケージは、特にDNS解決などの機能において、システムのCライブラリに依存する場合があります。これはCGO(C言語との相互運用機能)を通じて実現されます。しかし、CGO_ENABLED=0
が設定されている場合、GoコンパイラはCGOを使用しない純粋なGoバイナリを生成しようとします。このとき、net
パッケージ内の fd_poll_runtime.go
のようなファイルがCGOに依存する関数(例えば、CGOで実装されるべき関数本体がGo側から参照されているが、CGOが無効なためその実装が見つからない状態)を参照していると、コンパイラは「missing function body」(関数本体が見つからない)というエラーを発生させ、ビルドが中断してしまいます。
この問題は、net
パッケージがCGOを必要とする特定のプラットフォーム固有の機能(例えば、一部のシステムコールやDNSリゾルバの実装)に依存している場合に顕著になります。CGO_ENABLED=0
は、クロスコンパイルや、Cライブラリへの依存を排除して完全に静的なバイナリを生成したい場合に利用されるため、このビルドエラーはGoアプリケーションの配布やデプロイにおいて大きな障害となります。
このコミットは、このような状況下でも net
パッケージが正常にビルドされるようにするための修正です。
前提知識の解説
CGO (C Go)
CGOは、GoプログラムからC言語のコードを呼び出したり、C言語のコードからGoの関数を呼び出したりするためのGoの機能です。これにより、Goは既存のCライブラリやシステムコールを直接利用できるようになります。特に、OSの低レベルな機能や、パフォーマンスが重要な部分でC言語のコードを利用する際に役立ちます。
CGO_ENABLED
環境変数
CGO_ENABLED
はGoのビルド時に使用される環境変数です。
CGO_ENABLED=1
(デフォルト): CGOが有効になり、GoプログラムはC言語のコードとリンクされます。これにより、net
パッケージがシステムのDNSリゾルバなどのCライブラリに依存する機能を利用できるようになります。CGO_ENABLED=0
: CGOが無効になります。この設定でビルドされたGoプログラムは、C言語のコードとは一切リンクされず、純粋なGoのコードのみで構成されます。これは、クロスコンパイル(異なるOSやアーキテクチャ向けのバイナリを生成する)や、完全に静的なバイナリ(外部ライブラリに依存しない単一の実行ファイル)を生成したい場合に利用されます。
Goの net
パッケージ
Goの標準ライブラリである net
パッケージは、ネットワーク通信(TCP/UDPソケット、DNSルックアップなど)を扱うための機能を提供します。このパッケージは、プラットフォームによってはCGOを利用してシステム固有のネットワーク機能(特にDNS解決)にアクセスすることがあります。例えば、Unix系システムでは /etc/resolv.conf
を読み込んだり、getaddrinfo
のようなC関数を呼び出したりするためにCGOが使われることがあります。
ビルドタグ (netgo
)
Goには「ビルドタグ」という概念があり、特定のタグが指定された場合にのみコンパイルされるコードブロックを定義できます。net
パッケージには netgo
というビルドタグが存在します。このタグが有効な場合、net
パッケージはCGOに依存しない純粋なGoで実装されたDNSリゾルバを使用します。CGO_ENABLED=0
でビルドする際には、通常 -tags netgo
を go build
コマンドに追加することが推奨されます。
技術的詳細
CGO_ENABLED=0
でGoプログラムをビルドする際、GoコンパイラはCGO関連のコードをスキップします。net
パッケージの一部のファイル、特に fd_poll_runtime.go
のようなファイルは、CGOを通じて提供されるべき関数(例えば、_Cfunc_poll
のようなC関数)を参照していることがあります。これらの関数は、CGOが有効な場合はCコードとしてコンパイルされ、Go側から呼び出せるようになります。
しかし、CGO_ENABLED=0
の場合、これらのC関数はコンパイルされず、その結果、Goコードが参照する関数本体が見つからないというリンカーエラーやコンパイラエラーが発生します。具体的には、pkg/net/fd_poll_runtime.go:15: missing function body
のようなエラーメッセージが出力されます。これは、GoのコードがCGOによって提供されると期待しているシンボルが見つからないために起こります。
この問題を解決するために、このコミットでは src/pkg/net/empty.c
という空のCファイルを追加しています。このファイル自体は何も実用的なコードを含んでいませんが、その存在がGoのビルドシステムに特定の効果をもたらします。Goのビルドシステムは、CGOが有効な場合、Goのソースファイルと同じディレクトリにある .c
ファイルもコンパイルしようとします。CGO_ENABLED=0
の場合でも、GoコンパイラはCGO関連のファイルを処理する際に、特定の条件でCファイルが存在することを期待する場合があります。
この空のCファイルを追加することで、コンパイラが期待するCGO関連のファイル構造が満たされ、missing function body
エラーが回避されます。これは、Goのビルドツールチェインが、CGOが無効な場合でも、特定のCファイルが存在することを前提とした内部的なチェックや処理を行っているためと考えられます。この「ダミー」のCファイルは、コンパイラがエラーを吐かずにビルドプロセスを続行するための「プレースホルダー」として機能します。
コアとなるコードの変更箇所
diff --git a/src/pkg/net/empty.c b/src/pkg/net/empty.c
new file mode 100644
index 0000000000..a515c2fe29
--- /dev/null
+++ b/src/pkg/net/empty.c
@@ -0,0 +1,8 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is required to prevent compiler errors
+// when the package built with CGO_ENABLED=0.
+// Otherwise the compiler says:
+// pkg/net/fd_poll_runtime.go:15: missing function body
コアとなるコードの解説
追加された src/pkg/net/empty.c
ファイルは、以下の内容で構成されています。
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file is required to prevent compiler errors
// when the package built with CGO_ENABLED=0.
// Otherwise the compiler says:
// pkg/net/fd_poll_runtime.go:15: missing function body
このファイルは、C言語のコードを一切含んでいません。コメントのみで構成されています。しかし、この空のCファイルが存在することが、CGO_ENABLED=0
でビルドする際のコンパイラエラーを解決する鍵となります。
その理由は、GoのビルドシステムがCGO関連のファイルを処理する際の内部的な挙動にあります。net
パッケージ内の fd_poll_runtime.go
のようなファイルは、CGOが有効な場合にC言語で実装されるべき関数(例えば、poll
システムコールをラップする関数など)への参照を含んでいます。CGO_ENABLED=0
の場合、これらのC言語の関数はコンパイルされません。しかし、Goコンパイラがこれらの参照を解決しようとする際に、特定のCファイルが存在しないことを検出すると、「missing function body」エラーを発生させることがありました。
empty.c
ファイルは、GoコンパイラがCGO関連の処理を行う際に、CGOのソースファイルが存在することを期待する内部的なチェックを満足させるための「ダミー」ファイルとして機能します。このファイル自体は何もコンパイルされませんが、その存在がコンパイラに「CGO関連のファイルは存在する」と認識させ、結果として fd_poll_runtime.go
が参照する関数本体が見つからないというエラーを回避させます。これは、Goのビルドツールチェインが、CGOが無効な場合でも、CGO関連のファイルが存在するかどうかをチェックするロジックを持っているためと考えられます。この修正は、Goのビルドシステムにおける特定のコーナーケースを巧妙に回避するものです。
関連リンク
- Go CL 7857044: https://golang.org/cl/7857044
- Goの
net
パッケージとCGO_ENABLED=0
に関する議論 (Stack Overflow): https://stackoverflow.com/questions/28000000/go-net-package-build-issues-with-cgo-enabled-0 - Goの
net
パッケージとCGO_ENABLED=0
に関する議論 (GitHub Issue): https://github.com/golang/go/issues/12452
参考にした情報源リンク
- Stack Overflow: "Go net package build issues with CGO_ENABLED=0" (複数の回答を参照)
- GitHub Issues: golang/go リポジトリ内の関連するIssue (例:
net
パッケージとCGO_ENABLED=0
に関する議論) - Go公式ドキュメント (CGO, ビルドタグに関する情報)
- Goソースコード (特に
src/pkg/net
ディレクトリの構造とfd_poll_runtime.go
の内容) - Goのビルドシステムに関する一般的な知識