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

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

このコミットは、Go言語のビルドシステムがDebian GNU/kFreeBSD環境をサポートするための変更を導入しています。具体的には、cmd/distツールがkFreeBSDをFreeBSDとして認識するように修正し、make.bashスクリプトがkFreeBSD環境でCgoを自動的に無効化するよう調整されています。これにより、Debian GNU/kFreeBSD上でのGoのビルドが可能になります。

コミット

commit 3167c12eb2bea4c96ccb0308159925d5f4e8cd21
Author: Dave Cheney <dave@cheney.net>
Date:   Tue Dec 4 08:27:30 2012 +1100

    cmd/dist: support building on debian/kFreeBSD
    
    The debian/kFreeBSD project uses the FreeBSD kernel and the debian userspace. From our point of view, this is freebsd not linux as GOOS talks about the kernel syscall interface, not the userspace (although cgo alters that). As debian/kFreeBSD is experimental at this time, I do not think it is worth the effort of duplicating all the freebsd specific code so this is proposal represents a reasonable workaround.
    
    Currently cgo is not supported, make.bash will detect this and disable cgo automatically during the build.
    
    dfc@debian:~/go/src$ uname -a
    GNU/kFreeBSD debian 8.1-1-686 #0 Sat Jul 21 17:02:04 UTC 2012 i686 i386 Intel(R) Core(TM) i5-2415M CPU @ 2.30GHz GNU/kFreeBSD
    dfc@debian:~/go/src$ ../bin/go version
    go version devel +d05272f402ec Sat Dec 01 15:15:14 2012 -0800
    
    Tested with GOOS=freebsd GOARCH=386
    
    R=golang-dev
    CC=golang-dev
    https://golang.org/cl/6868046

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

https://github.com/golang/go/commit/3167c12eb2bea4c96ccb0308159925d5f4e8cd21

元コミット内容

このコミットは、Goのビルドツールであるcmd/distとビルドスクリプトであるmake.bashを修正し、Debian GNU/kFreeBSD環境でのGoのビルドをサポートします。

主な変更点は以下の通りです。

  1. src/cmd/dist/unix.cにおいて、__FreeBSD_kernel__マクロが定義されている場合に、ホストOSをfreebsdとして認識するように変更。これはDebian GNU/kFreeBSDをFreeBSDカーネルとして扱うためです。
  2. src/make.bashにおいて、uname -sコマンドの出力がGNU/kFreeBSDである場合に、環境変数CGO_ENABLED0に設定し、Cgoを無効化するように変更。これは、現在のところkFreeBSD環境でCgoがサポートされていないためです。

変更の背景

Go言語は、様々なオペレーティングシステムとアーキテクチャの組み合わせ(GOOS/GOARCH)をサポートするように設計されています。しかし、Debian GNU/kFreeBSDのような特定のニッチな環境では、Goのビルドシステムがその特性を正しく認識できない場合がありました。

Debian GNU/kFreeBSDは、DebianのユーザーランドとFreeBSDのカーネルを組み合わせたオペレーティングシステムです。Goのビルドシステムにおいて、GOOS(Go Operating System)は主にカーネルのシステムコールインターフェースを指します。そのため、kFreeBSDはユーザーランドがDebian(Linuxライク)であっても、カーネルがFreeBSDであるため、Goの観点からはfreebsdとして扱われるべきです。

このコミットが作成された2012年当時、Debian GNU/kFreeBSDはまだ実験的な段階であり、Goのビルドシステムがこの環境をネイティブにサポートするための包括的な変更を加えることは、労力に見合わないと判断されました。そこで、既存のFreeBSD関連のコードを重複させることなく、最小限の変更でビルドを可能にする「合理的な回避策」が提案されました。

また、Cgo(GoとC言語の相互運用機能)は、kFreeBSD環境では当時サポートされていませんでした。そのため、ビルドプロセス中にCgoが自動的に無効化されるようにする必要がありました。

これらの背景から、cmd/distでのOS認識の修正と、make.bashでのCgo無効化のロジックが導入されました。

前提知識の解説

Go言語のビルドシステムとクロスコンパイル

Go言語は、GOOSGOARCHという環境変数を用いて、ターゲットとなるオペレーティングシステムとアーキテクチャを指定し、クロスコンパイルを容易に行うことができます。

  • GOOS: Goが実行されるオペレーティングシステム(例: linux, windows, darwin, freebsdなど)。Goのビルドシステムは、この値に基づいて適切なシステムコールインターフェースやライブラリを選択します。
  • GOARCH: Goが実行されるCPUアーキテクチャ(例: amd64, 386, armなど)。

Debian GNU/kFreeBSD

Debian GNU/kFreeBSDは、Debianプロジェクトによって開発されたオペレーティングシステムの一つです。通常のDebianがLinuxカーネルを使用するのに対し、Debian GNU/kFreeBSDはFreeBSDカーネルを使用し、その上にDebianのGNUユーザーランド(GNUツールチェイン、aptパッケージ管理システムなど)を構築しています。これにより、FreeBSDカーネルの安定性や機能と、Debianの豊富なソフトウェアパッケージを組み合わせたシステムが実現されています。

Cgo

Cgoは、GoプログラムからC言語のコードを呼び出したり、C言語のコードからGoの関数を呼び出したりするためのGoの機能です。Cgoを使用すると、既存のCライブラリをGoプロジェクトに統合したり、パフォーマンスが重要な部分をCで記述したりすることができます。Cgoを有効にするには、環境変数CGO_ENABLED1に設定します(デフォルトは1)。Cgoを使用するプログラムをビルドするには、Cコンパイラ(通常はGCCやClang)が必要です。

cmd/dist

cmd/distは、GoのソースコードからGoツールチェイン自体をビルドするために使用される内部ツールです。Goのブートストラッププロセスにおいて重要な役割を果たし、Goのコンパイラ、リンカ、その他のツールを生成します。このツールは、ビルド環境のOSやアーキテクチャを検出し、それに基づいてビルドプロセスを調整します。

make.bash

make.bashは、Goのソースツリーのルートにあるシェルスクリプトで、Goのツールチェイン全体をビルドするための主要なスクリプトです。このスクリプトは、環境変数の設定、依存関係のチェック、cmd/distの呼び出し、テストの実行など、ビルドプロセスの様々な段階をオーケストレーションします。

技術的詳細

このコミットの技術的詳細は、Goのビルドシステムがどのように異なるOS環境を識別し、それに応じて動作を調整するかという点に集約されます。

  1. OS識別のロジック (src/cmd/dist/unix.c):

    • cmd/distは、C言語で書かれており、コンパイル時に利用可能なプリプロセッサマクロ(#define)を利用して、実行されているホストOSを識別します。
    • 従来のGoのビルドシステムでは、__FreeBSD__が定義されていればfreebsd__linux__が定義されていればlinuxと認識していました。
    • Debian GNU/kFreeBSDの場合、カーネルはFreeBSDですが、ユーザーランドはDebianです。Cコンパイラによっては、__FreeBSD_kernel__というマクロが定義されることがあります。このコミットでは、このマクロを検出することで、Debian GNU/kFreeBSDをGoのGOOSとしてはfreebsdとして扱うように明示的に指定しています。これは、GoのGOOSがカーネルのシステムコールインターフェースを指すという設計思想に合致しています。
  2. Cgoの無効化 (src/make.bash):

    • make.bashスクリプトは、ビルドプロセスの初期段階で環境をセットアップします。
    • uname -sコマンドは、システムのカーネル名を返します。Debian GNU/kFreeBSDシステムでは、このコマンドはGNU/kFreeBSDという文字列を返します。
    • スクリプトは、この文字列をチェックし、もしGNU/kFreeBSDであれば、export CGO_ENABLED=0を実行します。これにより、Goのビルドシステム全体でCgoが無効化され、Cgoに依存するパッケージのビルドがスキップされるか、Cgoなしでビルドされるようになります。これは、kFreeBSD環境でのCgoの未サポートという制約に対応するためのものです。

これらの変更により、GoのビルドシステムはDebian GNU/kFreeBSD環境を正しく識別し、Cgoの制約を考慮した上で、Goのツールチェインを正常にビルドできるようになります。

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

src/cmd/dist/unix.c

--- a/src/cmd/dist/unix.c
+++ b/src/cmd/dist/unix.c
@@ -670,6 +670,10 @@ main(int argc, char **argv)
 	gohostos = "linux";
 #elif defined(__FreeBSD__)
 	gohostos = "freebsd";
+#elif defined(__FreeBSD_kernel__)
+	// detect debian/kFreeBSD. 
+	// http://wiki.debian.org/Debian_GNU/kFreeBSD_FAQ#Q._How_do_I_detect_kfreebsd_with_preprocessor_directives_in_a_C_program.3F
+	gohostos = "freebsd";	
 #elif defined(__OpenBSD__)
 	gohostos = "openbsd";
 #elif defined(__NetBSD__)

src/make.bash

--- a/src/make.bash
+++ b/src/make.bash
@@ -77,6 +77,13 @@ do
 	fi
 done
 
+# Test for debian/kFreeBSD.
+# cmd/dist will detect kFreeBSD as freebsd/$GOARCH, but we need to
+# disable cgo manually.
+if [ "$(uname -s)" == "GNU/kFreeBSD" ]; then
+        export CGO_ENABLED=0
+fi
+
 # Clean old generated file that will cause problems in the build.
 rm -f ./pkg/runtime/runtime_defs.go
 

コアとなるコードの解説

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

このC言語のコードスニペットは、cmd/distがホストOSを識別する部分です。

  • #elif defined(__FreeBSD_kernel__)という行が追加されています。これはCプリプロセッサのディレクティブで、コンパイル時に__FreeBSD_kernel__というマクロが定義されているかどうかをチェックします。
  • Debian GNU/kFreeBSD環境でコンパイルされる場合、このマクロが定義されることが期待されます。
  • この条件が真であれば、gohostos = "freebsd";が実行され、GoのビルドシステムはホストOSをfreebsdとして扱います。
  • コメントには、Debian GNU/kFreeBSDの検出方法に関するFAQへのリンクが記載されており、この変更の意図が明確に示されています。

src/make.bashの変更

このシェルスクリプトの変更は、Goのビルドプロセス全体に影響を与えます。

  • if [ "$(uname -s)" == "GNU/kFreeBSD" ]; thenという条件文が追加されています。
    • uname -sコマンドは、システムのカーネル名を出力します。Debian GNU/kFreeBSDシステムでは、この出力は正確にGNU/kFreeBSDとなります。
    • この条件が真(つまり、現在のシステムがDebian GNU/kFreeBSDである)の場合、export CGO_ENABLED=0が実行されます。
  • export CGO_ENABLED=0は、環境変数CGO_ENABLED0に設定します。これにより、GoのビルドシステムはCgoを使用しないモードで動作し、Cgoに依存するすべてのGoパッケージがCgoなしでビルドされるか、Cgoが必須のパッケージはビルドがスキップされます。
  • コメントには、「cmd/distはkFreeBSDをfreebsd/$GOARCHとして検出するが、Cgoは手動で無効にする必要がある」と明記されており、cmd/distの変更とmake.bashの変更が連携して機能することが示唆されています。

これらの変更は、GoのビルドシステムがDebian GNU/kFreeBSDという特定のハイブリッド環境を適切に処理し、その環境の制約(Cgoの未サポート)に対応するための、実用的かつ効果的なアプローチを示しています。

関連リンク

参考にした情報源リンク