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

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

このコミットは、Go言語の標準ライブラリおよびビルドスクリプトにおいて、オペレーティングシステム (OS) およびアーキテクチャ (ARCH) の識別方法を syscall パッケージの定数から runtime パッケージの変数へと変更するものです。これにより、Goプログラムが実行される環境の情報をより標準的かつ柔軟に取得できるようになります。

影響を受けるファイルは以下の通りです。

  • src/buildscript_darwin_386.sh
  • src/buildscript_darwin_amd64.sh
  • src/buildscript_freebsd_386.sh
  • src/buildscript_freebsd_amd64.sh
  • src/buildscript_linux_386.sh
  • src/buildscript_linux_amd64.sh
  • src/buildscript_linux_arm.sh
  • src/buildscript_netbsd_386.sh
  • src/buildscript_netbsd_amd64.sh
  • src/buildscript_openbsd_386.sh
  • src/buildscript_openbsd_amd64.sh
  • src/buildscript_plan9_386.sh
  • src/buildscript_windows_386.sh
  • src/buildscript_windows_amd64.sh
  • src/pkg/debug/gosym/pclntab_test.go
  • src/pkg/net/file_test.go
  • src/pkg/net/server_test.go
  • src/pkg/os/os_test.go
  • src/pkg/os/os_unix_test.go
  • src/pkg/os/path_test.go
  • src/pkg/syscall/Makefile
  • src/pkg/syscall/exec_bsd.go
  • src/pkg/syscall/exec_unix.go
  • src/pkg/syscall/syscall_386.go (削除)
  • src/pkg/syscall/syscall_amd64.go (削除)
  • src/pkg/syscall/syscall_arm.go (削除)
  • src/pkg/syscall/syscall_bsd.go
  • src/pkg/syscall/syscall_darwin.go
  • src/pkg/syscall/syscall_freebsd.go
  • src/pkg/syscall/syscall_linux.go
  • src/pkg/syscall/syscall_netbsd.go
  • src/pkg/syscall/syscall_openbsd.go
  • src/pkg/syscall/syscall_plan9.go
  • src/pkg/syscall/syscall_unix.go
  • src/pkg/syscall/syscall_windows.go

コミット

  • コミットハッシュ: 92c8df46c6f398930ba598b1a2eb1248e739cc0b
  • 作者: Mikio Hara mikioh.mikioh@gmail.com
  • コミット日時: 2012年1月14日 土曜日 06:40:55 +0900

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

https://github.com/golang/go/commit/92c8df46c6f398930ba598b1a2eb1248e739cc0b

元コミット内容

src: make use of runtime.GOOS, GOARCH instead of syscall.OS, ARCH

R=rsc, r
CC=golang-dev
https://golang.org/cl/5545048

変更の背景

Go言語の初期のバージョンでは、特定のOSやアーキテクチャに依存するシステムコール関連のコード内で、現在のOSやアーキテクチャを識別するために syscall パッケージ内に OSARCH といった定数が定義されていました。しかし、これはGoのクロスコンパイル能力や、より汎用的な環境情報へのアクセスという観点から、いくつかの問題を引き起こしていました。

具体的には、syscall.OSsyscall.ARCH は、そのファイルがコンパイルされる特定のOS/ARCHにハードコードされる傾向があり、Goプログラムが実行される実際の環境とは異なる情報を持つ可能性がありました。例えば、Linux上でWindows向けにクロスコンパイルされたGoプログラムが syscall.OS を参照した場合、それは linux を返すのではなく、コンパイルターゲットである windows を返すことが期待されますが、syscall パッケージの定数として定義されている場合、その挙動は一貫性がなく、混乱を招く可能性がありました。

このコミットの背景には、Goのビルドシステムと実行環境の情報をより一元化し、runtime パッケージが提供する GOOS および GOARCH 変数にその役割を移譲することで、以下の利点を得る目的がありました。

  1. 一貫性の向上: OSとアーキテクチャの情報源を runtime パッケージに集約することで、Goプログラム全体で一貫した環境情報へのアクセスが可能になります。
  2. クロスコンパイルの簡素化: クロスコンパイル時にターゲットOS/ARCHの情報を正確に反映できるようになり、ビルドスクリプトや条件付きコンパイルのロジックが簡素化されます。
  3. コードの可読性と保守性の向上: runtime.GOOSruntime.GOARCH は、Goの実行環境に関する標準的な情報源として広く認識されており、これを使用することでコードの意図がより明確になります。
  4. syscall パッケージの責務の明確化: syscall パッケージはシステムコールへの低レベルなインターフェースを提供することに専念し、OS/ARCHの識別という高レベルな情報は runtime パッケージに任せることで、各パッケージの責務がより明確になります。

前提知識の解説

Go言語の環境変数 GOOSGOARCH

Go言語のビルドシステムは、GOOS (Go Operating System) と GOARCH (Go Architecture) という2つの重要な環境変数に依存しています。これらは、GoプログラムがどのオペレーティングシステムとCPUアーキテクチャ向けにビルドされるかを指定します。

  • GOOS: ビルドターゲットのOSを指定します。例: linux, windows, darwin (macOS), freebsd, plan9 など。
  • GOARCH: ビルドターゲットのCPUアーキテクチャを指定します。例: amd64, 386, arm, arm64 など。

これらの変数は、Goのコンパイラやリンカが適切なシステムライブラリやアセンブリコードを選択するために使用されます。

runtime パッケージ

runtime パッケージは、Goプログラムのランタイムシステムとのインターフェースを提供します。これには、ガベージコレクション、ゴルーチン管理、そして現在の実行環境に関する情報などが含まれます。runtime.GOOSruntime.GOARCH は、このパッケージで提供されるグローバル変数であり、Goプログラムが実行されている(またはコンパイルされている)OSとアーキテクチャの文字列を返します。これらは、Goのビルド時に設定された GOOS および GOARCH の値と一致します。

syscall パッケージ

syscall パッケージは、Goプログラムから基盤となるオペレーティングシステムのシステムコールに直接アクセスするための低レベルなインターフェースを提供します。ファイル操作、ネットワーク通信、プロセス管理など、OS固有の機能を利用する際に使用されます。このパッケージはOSに強く依存するため、OSやアーキテクチャごとに異なる実装を持つことがあります。

クロスコンパイル

Go言語は、あるOS/アーキテクチャの環境で、別のOS/アーキテクチャ向けの実行ファイルを生成する「クロスコンパイル」を強力にサポートしています。例えば、LinuxのAMD64マシンでWindowsの386向け実行ファイルをビルドすることができます。この際、GOOSGOARCH 環境変数を適切に設定することで、ターゲット環境に合わせたバイナリが生成されます。

技術的詳細

このコミットの核心は、Goのコードベース全体でOSとアーキテクチャの識別に使用される情報源を統一することにあります。以前は、syscall パッケージ内で const OS = "..."const ARCH = "..." のようにOSやアーキテクチャがハードコードされている箇所がありました。これは、syscall パッケージがOS固有の機能に密接に関連しているため、一見すると理にかなっているように見えます。

しかし、このアプローチにはいくつかの問題がありました。

  1. 冗長性と不整合: runtime パッケージにも同様の GOOSGOARCH が存在するため、情報源が二重になり、将来的に不整合が生じる可能性がありました。
  2. クロスコンパイルの複雑化: syscall パッケージ内の定数がビルドターゲットではなく、ビルドホストのOS/ARCHを誤って反映してしまう可能性がありました。これは、特にビルドスクリプトやテストコードで問題となります。
  3. syscall パッケージの責務の曖昧化: syscall パッケージの主な責務はシステムコールへのインターフェース提供であり、一般的な環境情報の提供は runtime パッケージの責務と考えるのがより適切です。

この変更により、以下の技術的な影響があります。

  • syscall パッケージの簡素化: syscall パッケージからOS/ARCHを定義する定数が削除され、その役割は runtime パッケージに完全に移譲されます。これにより、syscall パッケージのコードベースがクリーンになり、その責務がより明確になります。
  • ビルドスクリプトの変更: 各OS/ARCHごとのビルドスクリプト (buildscript_*.sh) から、syscall パッケージの特定のOS/ARCHファイル (syscall_386.go, syscall_amd64.go, syscall_arm.go など) をコンパイル対象から除外する変更が行われています。これは、これらのファイルがもはや ARCH 定数を含まないため、不要になったことを意味します。
  • テストコードの修正: debug/gosym, net, os パッケージのテストコード内で syscall.OSsyscall.ARCH を使用してOS/ARCHを判定していた箇所が、runtime.GOOSruntime.GOARCH に置き換えられています。これにより、テストがより正確に、かつクロスコンパイル環境でも期待通りに動作するようになります。
  • syscall/Makefile の変更: syscall パッケージの Makefile から syscall_$(GOARCH).go の行が削除されています。これは、アーキテクチャ固有の syscall_ARCH.go ファイルが削除されたことに伴う変更です。

この変更は、Go言語の設計思想である「シンプルさ」と「一貫性」を追求したものであり、Goのビルドシステムとランタイムの成熟を示す一歩と言えます。

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

このコミットにおけるコアとなるコードの変更は、主に以下の3つのパターンに集約されます。

  1. syscall パッケージ内の OS および ARCH 定数の削除:

    • src/pkg/syscall/syscall_386.go, src/pkg/syscall/syscall_amd64.go, src/pkg/syscall/syscall_arm.go といったアーキテクチャ固有のファイルが完全に削除されました。これらのファイルは、それぞれ const ARCH = "386" のようなアーキテクチャ定数のみを含んでいました。
    • src/pkg/syscall/syscall_darwin.go, src/pkg/syscall/syscall_freebsd.go, src/pkg/syscall/syscall_linux.go など、OS固有のファイルから const OS = "..." の行が削除されました。

    例: src/pkg/syscall/syscall_darwin.go の変更

    --- a/src/pkg/syscall/syscall_darwin.go
    +++ b/src/pkg/syscall/syscall_darwin.go
    @@ -14,8 +14,6 @@ package syscall
    
     import "unsafe"
    
    -const OS = "darwin"
    -
     type SockaddrDatalink struct {
     	Len    uint8
     	Family uint8
    
  2. syscall.OS および syscall.ARCHruntime.GOOS および runtime.GOARCH への置き換え:

    • src/pkg/debug/gosym/pclntab_test.go, src/pkg/net/file_test.go, src/pkg/net/server_test.go, src/pkg/os/os_test.go, src/pkg/os/os_unix_test.go, src/pkg/os/path_test.go, src/pkg/syscall/exec_bsd.go, src/pkg/syscall/exec_unix.go, src/pkg/syscall/syscall_bsd.go, src/pkg/syscall/syscall_unix.go など、多くのGoソースファイルでこの置き換えが行われました。

    例: src/pkg/debug/gosym/pclntab_test.go の変更

    --- a/src/pkg/debug/gosym/pclntab_test.go
    +++ b/src/pkg/debug/gosym/pclntab_test.go
    @@ -7,14 +7,14 @@ package gosym
     import (
      	"debug/elf"
      	"os"
    -	"syscall"
    +	"runtime"
      	"testing"
     )
    
     func dotest() bool {
      	// For now, only works on ELF platforms.
      	// TODO: convert to work with new go tool
    -	return false && syscall.OS == "linux" && os.Getenv("GOARCH") == "amd64"
    +	return false && runtime.GOOS == "linux" && runtime.GOARCH == "amd64"
     }
    
     func getTable(t *testing.T) *Table {
    
  3. ビルドスクリプト (buildscript_*.sh) および syscall/Makefile の変更:

    • 各OS/ARCHごとのビルドスクリプトから、削除された syscall_ARCH.go ファイルのコンパイル指示が削除されました。
    • src/pkg/syscall/Makefile から syscall_$(GOARCH).go の行が削除されました。

    例: src/buildscript_darwin_386.sh の変更

    --- a/src/buildscript_darwin_386.sh
    +++ b/src/buildscript_darwin_386.sh
    @@ -232,7 +232,7 @@ cp "$WORK"/encoding/base64.a "$GOROOT"/pkg/darwin_386/encoding/base64.a
    
     mkdir -p "$WORK"/syscall/_obj/
     cd "$GOROOT"/src/pkg/syscall
    -8g -o "$WORK"/syscall/_obj/_go_.8 -p syscall -I "$WORK" ./bpf_bsd.go ./env_unix.go ./exec_bsd.go ./exec_unix.go ./route_bsd.go ./route_darwin.go ./sockcmsg_unix.go ./str.go ./syscall.go ./syscall_386.go ./syscall_bsd.go ./syscall_darwin.go ./syscall_darwin_386.go ./syscall_unix.go ./zerrors_darwin_386.go ./zsyscall_darwin_386.go ./zsysnum_darwin_386.go ./ztypes_darwin_386.go
    +8g -o "$WORK"/syscall/_obj/_go_.8 -p syscall -I "$WORK" ./bpf_bsd.go ./env_unix.go ./exec_bsd.go ./exec_unix.go ./route_bsd.go ./route_darwin.go ./sockcmsg_unix.go ./str.go ./syscall.go ./syscall_bsd.go ./syscall_darwin.go ./syscall_darwin_386.go ./syscall_unix.go ./zerrors_darwin_386.go ./zsyscall_darwin_386.go ./zsysnum_darwin_386.go ./ztypes_darwin_386.go
     8a -I "$WORK"/syscall/_obj/ -o "$WORK"/syscall/_obj/asm_darwin_386.8 -DGOOS_darwin -DGOARCH_386 ./asm_darwin_386.s
     gopack grc "$WORK"/syscall.a "$WORK"/syscall/_obj/_go_.8 "$WORK"/syscall/_obj/asm_darwin_386.8
     cp "$WORK"/syscall.a "$GOROOT"/pkg/darwin_386/syscall.a
    

    この変更では、syscall_386.go がコンパイル対象から削除されていることがわかります。

コアとなるコードの解説

このコミットの変更は、Go言語の設計哲学における重要な進化を示しています。

  1. syscall パッケージからの定数削除の意義: syscall パッケージは、OSの低レベルな機能にアクセスするためのものです。OSやアーキテクチャの識別といった高レベルな情報は、本来 runtime パッケージの責務です。syscall パッケージからこれらの定数を削除することで、各パッケージの役割が明確になり、Goの標準ライブラリ全体のモジュール性が向上します。これにより、syscall パッケージは純粋にシステムコールインターフェースに集中できるようになります。

  2. runtime.GOOSruntime.GOARCH の採用の利点: runtime.GOOSruntime.GOARCH は、Goのビルドプロセスによって設定される公式な環境情報です。これらを使用することで、GoプログラムはコンパイルターゲットのOSとアーキテクチャを常に正確に知ることができます。これは特にクロスコンパイルのシナリオで重要です。例えば、Linux上でWindows向けにビルドされたプログラムが runtime.GOOS を参照すると、それは windows を返し、期待通りの挙動を示します。これにより、条件付きコンパイルやプラットフォーム固有のロジックの実装がより堅牢になります。

  3. ビルドスクリプトとテストコードへの影響: ビルドスクリプトやテストコードは、Goのビルドプロセスやテスト実行の健全性を保証するために非常に重要です。これらのファイルで syscall.OSsyscall.ARCH が使用されていたのは、過去のGoの設計に起因するものでした。今回の変更により、これらのスクリプトやテストも runtime パッケージの標準的な情報源に依存するようになり、Goのビルドシステム全体の一貫性と信頼性が向上します。特に、syscall_ARCH.go ファイルの削除は、特定のアーキテクチャに依存する定数を個別のファイルで管理する必要がなくなったことを意味し、コードベースの重複を減らし、メンテナンスを容易にします。

この変更は、Go言語がその初期段階から、より洗練された、堅牢な、そしてクロスプラットフォーム開発に優れた言語へと進化していく過程の一部を示しています。

関連リンク

参考にした情報源リンク