[インデックス 18531] ファイルの概要
このコミットは、Go言語のツールチェインにおけるcmd/go
パッケージ内のbuild.go
ファイルに対する変更です。具体的には、cgoを用いたクロスコンパイルに関する制限を削除することを目的としています。
コミット
commit 9b0736fc5850271ed89880202eed797692976a49
Author: Elias Naur <elias.naur@gmail.com>
Date: Fri Feb 14 11:36:52 2014 -0800
cmd/go: remove cross compiling restriction on cgo
A previous CL added support for cross compiling with cgo, but
missed the GOOS check in cmd/go. Remove it.
Update #4714
LGTM=iant
R=iant
CC=golang-codereviews
https://golang.org/cl/57210046
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/9b0736fc5850271ed89880202eed797692976a49
元コミット内容
このコミットは、cmd/go
ツールがcgoを使用する際のクロスコンパイルに関する制約を削除します。以前の変更でcgoのクロスコンパイルサポートが追加されたにもかかわらず、cmd/go
内のGOOS
チェックが見落とされていたため、そのチェックを削除するものです。
変更の背景
Go言語は、GOOS
(ターゲットOS)とGOARCH
(ターゲットアーキテクチャ)環境変数を設定することで、異なるプラットフォーム向けに簡単にクロスコンパイルできる強力な機能を持っています。しかし、C言語のコードをGoプログラムに組み込むための機能であるcgoを使用する場合、このクロスコンパイルは複雑になります。cgoは、Goのコンパイラだけでなく、ターゲットシステム用のCコンパイラ(クロスコンパイラ)とCライブラリに依存するためです。
このコミット以前のGoツールチェインでは、cgoを使用する際に、ビルドを実行しているホストOSとターゲットOSが異なる場合(すなわちクロスコンパイルの場合)にエラーを発生させる明示的なチェックが存在していました。これは、cgoのクロスコンパイルがまだ完全にサポートされていなかったり、安定していなかったりした時期の名残と考えられます。
しかし、このコミットのメッセージにあるように、「A previous CL added support for cross compiling with cgo」とあることから、このコミットの前にcgoのクロスコンパイルを可能にする変更が既に行われていたことが示唆されます。にもかかわらず、cmd/go
ツール内の特定のGOOS
チェックが削除されずに残っていたため、cgoを使用したクロスコンパイルが不必要にブロックされる状況が発生していました。このコミットは、その残存するチェックを削除し、cgoのクロスコンパイル機能を完全に解放することを目的としています。
前提知識の解説
- cgo: Go言語のプログラムからC言語のコードを呼び出したり、C言語のコードからGo言語の関数を呼び出したりするためのメカニズムです。cgoを使用すると、既存のCライブラリをGoプロジェクトで再利用したり、パフォーマンスが重要な部分をCで記述したりすることができます。cgoが有効な場合、
go build
はGoコンパイラだけでなく、システムにインストールされているCコンパイラ(通常はGCCやClang)も利用します。 - クロスコンパイル (Cross-compilation): あるコンピュータシステム(ホスト)上で、それとは異なるアーキテクチャやオペレーティングシステムを持つ別のコンピュータシステム(ターゲット)で実行可能なバイナリを生成するプロセスです。Go言語は、
GOOS
とGOARCH
環境変数を設定するだけで、純粋なGoプログラムのクロスコンパイルを非常に容易に行えます。 GOOS
: Goのビルドターゲットとなるオペレーティングシステムを指定する環境変数です(例:linux
,windows
,darwin
)。toolGOOS
: これはGoの公式な環境変数ではありませんが、文脈上、Goツールチェインが動作しているホストのオペレーティングシステムを指すか、あるいはCクロスコンパイラがターゲットとするOSを指す概念として使われます。このコミットのコードでは、Goツールチェインが認識しているホストOSを指す内部変数としてtoolGOOS
が使われていたと考えられます。cmd/go
: Go言語のビルド、テスト、パッケージ管理などを行うコマンドラインツールです。go build
やgo run
などのコマンドを実行する際に内部的に使用されます。build.go
:cmd/go
パッケージ内のファイルの一つで、Goプログラムのビルドプロセスに関するロジックが含まれています。cgoの処理もこのファイル内で管理されています。
技術的詳細
このコミットの核心は、src/cmd/go/build.go
ファイル内の特定の条件分岐の削除です。以前のコードでは、cgo
関数内で以下のようなチェックが行われていました。
if goos != toolGOOS {
return nil, nil, errors.New("cannot use cgo when compiling for a different operating system")
}
このコードは、ビルドターゲットのOS (goos
) が、Goツールチェインが動作しているホストのOS (toolGOOS
) と異なる場合にエラーを返していました。これは、cgoを使用したクロスコンパイルを明示的に禁止するものでした。
しかし、cgoのクロスコンパイルサポートがGoツールチェインに導入された後も、このチェックが残っていたため、ユーザーはcgoを含むGoプログラムをクロスコンパイルしようとすると、このエラーに遭遇していました。このコミットは、この不要になった制約を取り除くことで、cgoのクロスコンパイルを可能にします。
cgoのクロスコンパイルは、純粋なGoのクロスコンパイルよりも複雑です。なぜなら、ターゲットOSとアーキテクチャに対応するCコンパイラ(クロスコンパイラ)と、必要なCライブラリがホストシステムにインストールされている必要があるからです。Goツールチェインは、CC
やCXX
といった環境変数を通じて、使用すべきクロスコンパイラを指定できるようになっています。このコミットは、Goツールチェインがこれらの外部ツールを適切に利用できるようになったことを前提として、内部的な制約を解除するものです。
コアとなるコードの変更箇所
変更はsrc/cmd/go/build.go
ファイルに集中しており、具体的には以下の4行が削除されています。
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -2068,10 +2068,6 @@ var (
)
func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) {
- if goos != toolGOOS {
- return nil, nil, errors.New("cannot use cgo when compiling for a different operating system")
- }
-
cgoCPPFLAGS := stringList(envList("CGO_CPPFLAGS"), p.CgoCPPFLAGS)
cgoCFLAGS := stringList(envList("CGO_CFLAGS"), p.CgoCFLAGS)
cgoCXXFLAGS := stringList(envList("CGO_CXXFLAGS"), p.CgoCXXFLAGS)
コアとなるコードの解説
削除されたコードブロックは、cgo
関数(builder
構造体のメソッド)の冒頭に位置していました。この関数は、cgoを使用するパッケージのビルド処理を担当しています。
if goos != toolGOOS
という条件は、ビルドターゲットのOS (goos
) が、ビルドを実行しているホストのOS (toolGOOS
) と異なる場合に真となります。この条件が真の場合、errors.New("cannot use cgo when compiling for a different operating system")
というエラーが返され、cgoを含むパッケージのクロスコンパイルが中断されていました。
この4行が削除されたことにより、cgo
関数は、ターゲットOSがホストOSと異なっていても、エラーを発生させることなく処理を続行するようになります。これにより、Goツールチェインは、外部のクロスコンパイラが適切に設定されていれば、cgoを使用したクロスコンパイルを正常に実行できるようになります。
この変更は、Go言語のクロスコンパイル能力をさらに向上させ、cgoを使用するアプリケーションの開発者が、より多様なターゲットプラットフォーム向けにビルドを行えるようにするための重要なステップでした。
関連リンク
- Go issue #4714: https://github.com/golang/go/issues/4714 (このコミットが解決したIssue)
- Go CL 57210046: https://golang.org/cl/57210046 (このコミットのGerrit Code Reviewページ)
参考にした情報源リンク
- Go言語の公式ドキュメント (cgo, クロスコンパイルに関する情報)
- Stack OverflowやGoコミュニティの議論 (cgoクロスコンパイルの課題と解決策に関する情報)
- Goのソースコード (特に
cmd/go
パッケージのbuild.go
ファイル) - Web search results for "Go cgo cross compilation GOOS toolGOOS" (上記Web検索結果)