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

[インデックス 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 netgogo 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のビルドシステムにおける特定のコーナーケースを巧妙に回避するものです。

関連リンク

参考にした情報源リンク

  • 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のビルドシステムに関する一般的な知識