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

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

このコミットは、Go言語のドキュメントに含まれるプログラム実行スクリプト doc/progs/run において、FreeBSD環境で特定の cgo プログラム (cgo1 および cgo2) の実行をスキップするように変更を加えるものです。これは、FreeBSDの srandom 関数のシグネチャがDarwin (macOS) やLinuxと異なるために発生するビルドまたは実行時の問題を回避するための対応です。

コミット

commit d2d7de974ceffbcfbcc2d7b9e15b3c2472d65ac4
Author: Andrew Gerrand <adg@golang.org>
Date:   Tue Mar 13 11:55:16 2012 +1100

    doc/progs: skip cgo1 and cgo2 on freebsd
    
    FreeBSD's srandom has a different signature to darwin/linux.
    
    R=golang-dev, dsymonds
    CC=golang-dev
    https://golang.org/cl/5795067

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

https://github.com/golang/go/commit/d2d7de974ceffbcfbcc2d7b9e15b3c2472d65ac4

元コミット内容

doc/progs: skip cgo1 and cgo2 on freebsd

FreeBSD's srandom has a different signature to darwin/linux.

変更の背景

この変更の背景には、Go言語の cgo 機能と、異なるオペレーティングシステム間でのC標準ライブラリ関数の互換性の問題があります。具体的には、FreeBSDの srandom (擬似乱数ジェネレータのシードを設定する関数) の関数シグネチャ(引数の型や数)が、Darwin (macOS) やLinuxのそれと異なっていました。

Goのドキュメントに含まれるサンプルプログラムは、様々な環境での動作を検証するために実行されます。cgo1cgo2 というサンプルプログラムが srandom 関数を使用しており、FreeBSD上でこれらのプログラムをビルドまたは実行しようとすると、シグネチャの不一致によりエラーが発生していました。この問題を解決するため、FreeBSD環境ではこれらの特定の cgo サンプルをスキップするよう、実行スクリプトが修正されました。

前提知識の解説

cgo

cgo はGo言語の機能の一つで、GoプログラムからC言語のコードを呼び出したり、C言語のコードからGoの関数を呼び出したりすることを可能にします。これにより、既存のCライブラリをGoプロジェクトで再利用したり、パフォーマンスが重要な部分をCで記述したりすることができます。

cgo を使用する際には、Goの型とCの型の間で適切な変換を行う必要があります。例えば、Goの int をCの unsigned int に渡す場合、明示的な型キャスト (C.uint(goIntVariable)) が必要になることがあります。この変換が正しく行われないと、コンパイル時または実行時にシグネチャの不一致エラーが発生する可能性があります。

srandom関数

srandom は、擬似乱数ジェネレータのシード(種)を設定するために使用されるC標準ライブラリ関数です。この関数は通常、stdlib.h ヘッダファイルで宣言されています。シードを設定することで、random などの関数が生成する乱数のシーケンスを初期化し、再現可能な乱数シーケンスを得ることができます。

一般的な srandom のシグネチャは以下のようになります。 void srandom(unsigned int seed);

しかし、オペレーティングシステムやCライブラリの実装によっては、引数の型や数が異なる場合があります。

関数シグネチャ

関数シグネチャとは、関数の名前、引数の型と順序、および戻り値の型を組み合わせたものです。プログラミング言語において、関数を呼び出す際には、呼び出し側と定義側の関数シグネチャが一致している必要があります。一致しない場合、コンパイラは型エラーを報告したり、実行時に未定義の動作を引き起こしたりする可能性があります。

特に、異なるOSやコンパイラ環境では、同じ名前の関数であっても、そのシグネチャが微妙に異なることがあります。これは、低レベルのシステムコールやライブラリの実装詳細に起因することが多いです。

技術的詳細

このコミットが対処している技術的な問題は、Goの cgo がCライブラリ関数を呼び出す際の型システムと、FreeBSDの srandom 関数のシグネチャの不一致です。

Web検索の結果によると、FreeBSDの srandom 関数は void srandom(unsigned int seed); というシグネチャを持っています。これは一般的なシグネチャですが、Goの cgo が内部的にGoの型をCの型にマッピングする際に、FreeBSD環境での特定の cgo サンプル (cgo1, cgo2) が期待するシグネチャと合致しなかった可能性があります。

考えられる原因としては、以下の点が挙げられます。

  1. 暗黙的な型変換の失敗: cgo はGoの型をCの型に自動的に変換しようとしますが、特定のプラットフォームでその変換ルールが期待通りに機能しない場合がある。特に、ポインタ型や構造体型、あるいは整数型のサイズや符号の解釈が異なる場合に問題が発生しやすいです。
  2. ヘッダファイルの差異: FreeBSDのシステムヘッダファイル (stdlib.h など) が、DarwinやLinuxとは異なる srandom のプロトタイプを定義していた可能性。これにより、cgo がCコードをコンパイルする際に、Go側から渡される引数の型とC側が期待する引数の型との間に不一致が生じた。
  3. リンカの問題: シグネチャの不一致が、コンパイル時ではなくリンカがシンボルを解決する段階で問題として顕在化するケースもあります。

このコミットでは、根本的な cgo の型変換ロジックやFreeBSDの srandom 実装を変更するのではなく、問題が発生する特定のサンプルプログラムの実行をFreeBSD環境でのみスキップするという、実用的な回避策が取られています。これは、Goのテストやドキュメントのビルドプロセスにおいて、特定の環境でのみ発生する互換性問題を効率的に解決するための一般的なアプローチです。

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

--- a/doc/progs/run
+++ b/doc/progs/run
@@ -5,6 +5,8 @@
 
 set -e
 
+goos=$(go env GOOS)
+
 defer_panic_recover="
 	defer
 	defer2
@@ -29,11 +31,15 @@ law_of_reflection=\"
 \"
 
 c_go_cgo=\"
-    cgo1
-    cgo2
-    cgo3
-    cgo4
+\tcgo1
+\tcgo2
+\tcgo3
+\tcgo4
 \"
+# cgo1 and cgo2 don't run on freebsd, srandom has a different signature
+if [ "$goos" == "freebsd" ]; then
+\tc_go_cgo="cgo3 cgo4"
+fi
 
 all=$(echo $defer_panic_recover $effective_go $error_handling $law_of_reflection $c_go_cgo slices go1)
 

コアとなるコードの解説

変更は doc/progs/run というシェルスクリプトに対して行われています。このスクリプトは、Goのドキュメントに含まれる様々なサンプルプログラムを実行し、その動作を検証するために使用されます。

  1. goos=$(go env GOOS) の追加: go env GOOS コマンドを実行して、現在のGoのビルド環境におけるオペレーティングシステム (GOOS) の値を取得し、goos というシェル変数に格納しています。例えば、Linuxであれば linux、FreeBSDであれば freebsd が設定されます。

  2. c_go_cgo 変数の初期化: c_go_cgo というシェル変数は、cgo に関連するサンプルプログラムのリストを保持しています。変更前は、cgo1 cgo2 cgo3 cgo4 の全てが含まれていました。

  3. FreeBSD環境での条件分岐:

    if [ "$goos" == "freebsd" ]; then
    	c_go_cgo="cgo3 cgo4"
    fi
    

    この部分が今回の変更の核心です。goos 変数の値が "freebsd" であるかどうかをチェックしています。 もし現在のOSがFreeBSDであれば、c_go_cgo 変数の内容を "cgo3 cgo4" に上書きしています。これにより、cgo1cgo2 がリストから除外され、後続のスクリプトでこれらのプログラムが実行されなくなります。

この変更により、FreeBSD環境で doc/progs/run スクリプトが実行された際に、srandom のシグネチャ問題を引き起こす cgo1cgo2 の実行が回避され、スクリプトが正常に完了するようになります。

関連リンク

参考にした情報源リンク