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

[インデックス 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言語は、GOOSGOARCH環境変数を設定するだけで、純粋なGoプログラムのクロスコンパイルを非常に容易に行えます。
  • GOOS: Goのビルドターゲットとなるオペレーティングシステムを指定する環境変数です(例: linux, windows, darwin)。
  • toolGOOS: これはGoの公式な環境変数ではありませんが、文脈上、Goツールチェインが動作しているホストのオペレーティングシステムを指すか、あるいはCクロスコンパイラがターゲットとするOSを指す概念として使われます。このコミットのコードでは、Goツールチェインが認識しているホストOSを指す内部変数としてtoolGOOSが使われていたと考えられます。
  • cmd/go: Go言語のビルド、テスト、パッケージ管理などを行うコマンドラインツールです。go buildgo 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ツールチェインは、CCCXXといった環境変数を通じて、使用すべきクロスコンパイラを指定できるようになっています。このコミットは、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言語の公式ドキュメント (cgo, クロスコンパイルに関する情報)
  • Stack OverflowやGoコミュニティの議論 (cgoクロスコンパイルの課題と解決策に関する情報)
  • Goのソースコード (特にcmd/goパッケージのbuild.goファイル)
  • Web search results for "Go cgo cross compilation GOOS toolGOOS" (上記Web検索結果)