[インデックス 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
パッケージ内に OS
や ARCH
といった定数が定義されていました。しかし、これはGoのクロスコンパイル能力や、より汎用的な環境情報へのアクセスという観点から、いくつかの問題を引き起こしていました。
具体的には、syscall.OS
や syscall.ARCH
は、そのファイルがコンパイルされる特定のOS/ARCHにハードコードされる傾向があり、Goプログラムが実行される実際の環境とは異なる情報を持つ可能性がありました。例えば、Linux上でWindows向けにクロスコンパイルされたGoプログラムが syscall.OS
を参照した場合、それは linux
を返すのではなく、コンパイルターゲットである windows
を返すことが期待されますが、syscall
パッケージの定数として定義されている場合、その挙動は一貫性がなく、混乱を招く可能性がありました。
このコミットの背景には、Goのビルドシステムと実行環境の情報をより一元化し、runtime
パッケージが提供する GOOS
および GOARCH
変数にその役割を移譲することで、以下の利点を得る目的がありました。
- 一貫性の向上: OSとアーキテクチャの情報源を
runtime
パッケージに集約することで、Goプログラム全体で一貫した環境情報へのアクセスが可能になります。 - クロスコンパイルの簡素化: クロスコンパイル時にターゲットOS/ARCHの情報を正確に反映できるようになり、ビルドスクリプトや条件付きコンパイルのロジックが簡素化されます。
- コードの可読性と保守性の向上:
runtime.GOOS
とruntime.GOARCH
は、Goの実行環境に関する標準的な情報源として広く認識されており、これを使用することでコードの意図がより明確になります。 syscall
パッケージの責務の明確化:syscall
パッケージはシステムコールへの低レベルなインターフェースを提供することに専念し、OS/ARCHの識別という高レベルな情報はruntime
パッケージに任せることで、各パッケージの責務がより明確になります。
前提知識の解説
Go言語の環境変数 GOOS
と GOARCH
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.GOOS
と runtime.GOARCH
は、このパッケージで提供されるグローバル変数であり、Goプログラムが実行されている(またはコンパイルされている)OSとアーキテクチャの文字列を返します。これらは、Goのビルド時に設定された GOOS
および GOARCH
の値と一致します。
syscall
パッケージ
syscall
パッケージは、Goプログラムから基盤となるオペレーティングシステムのシステムコールに直接アクセスするための低レベルなインターフェースを提供します。ファイル操作、ネットワーク通信、プロセス管理など、OS固有の機能を利用する際に使用されます。このパッケージはOSに強く依存するため、OSやアーキテクチャごとに異なる実装を持つことがあります。
クロスコンパイル
Go言語は、あるOS/アーキテクチャの環境で、別のOS/アーキテクチャ向けの実行ファイルを生成する「クロスコンパイル」を強力にサポートしています。例えば、LinuxのAMD64マシンでWindowsの386向け実行ファイルをビルドすることができます。この際、GOOS
と GOARCH
環境変数を適切に設定することで、ターゲット環境に合わせたバイナリが生成されます。
技術的詳細
このコミットの核心は、Goのコードベース全体でOSとアーキテクチャの識別に使用される情報源を統一することにあります。以前は、syscall
パッケージ内で const OS = "..."
や const ARCH = "..."
のようにOSやアーキテクチャがハードコードされている箇所がありました。これは、syscall
パッケージがOS固有の機能に密接に関連しているため、一見すると理にかなっているように見えます。
しかし、このアプローチにはいくつかの問題がありました。
- 冗長性と不整合:
runtime
パッケージにも同様のGOOS
とGOARCH
が存在するため、情報源が二重になり、将来的に不整合が生じる可能性がありました。 - クロスコンパイルの複雑化:
syscall
パッケージ内の定数がビルドターゲットではなく、ビルドホストのOS/ARCHを誤って反映してしまう可能性がありました。これは、特にビルドスクリプトやテストコードで問題となります。 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.OS
やsyscall.ARCH
を使用してOS/ARCHを判定していた箇所が、runtime.GOOS
やruntime.GOARCH
に置き換えられています。これにより、テストがより正確に、かつクロスコンパイル環境でも期待通りに動作するようになります。 syscall/Makefile
の変更:syscall
パッケージのMakefile
からsyscall_$(GOARCH).go
の行が削除されています。これは、アーキテクチャ固有のsyscall_ARCH.go
ファイルが削除されたことに伴う変更です。
この変更は、Go言語の設計思想である「シンプルさ」と「一貫性」を追求したものであり、Goのビルドシステムとランタイムの成熟を示す一歩と言えます。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更は、主に以下の3つのパターンに集約されます。
-
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
-
syscall.OS
およびsyscall.ARCH
のruntime.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 {
-
ビルドスクリプト (
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
がコンパイル対象から削除されていることがわかります。 - 各OS/ARCHごとのビルドスクリプトから、削除された
コアとなるコードの解説
このコミットの変更は、Go言語の設計哲学における重要な進化を示しています。
-
syscall
パッケージからの定数削除の意義:syscall
パッケージは、OSの低レベルな機能にアクセスするためのものです。OSやアーキテクチャの識別といった高レベルな情報は、本来runtime
パッケージの責務です。syscall
パッケージからこれらの定数を削除することで、各パッケージの役割が明確になり、Goの標準ライブラリ全体のモジュール性が向上します。これにより、syscall
パッケージは純粋にシステムコールインターフェースに集中できるようになります。 -
runtime.GOOS
とruntime.GOARCH
の採用の利点:runtime.GOOS
とruntime.GOARCH
は、Goのビルドプロセスによって設定される公式な環境情報です。これらを使用することで、GoプログラムはコンパイルターゲットのOSとアーキテクチャを常に正確に知ることができます。これは特にクロスコンパイルのシナリオで重要です。例えば、Linux上でWindows向けにビルドされたプログラムがruntime.GOOS
を参照すると、それはwindows
を返し、期待通りの挙動を示します。これにより、条件付きコンパイルやプラットフォーム固有のロジックの実装がより堅牢になります。 -
ビルドスクリプトとテストコードへの影響: ビルドスクリプトやテストコードは、Goのビルドプロセスやテスト実行の健全性を保証するために非常に重要です。これらのファイルで
syscall.OS
やsyscall.ARCH
が使用されていたのは、過去のGoの設計に起因するものでした。今回の変更により、これらのスクリプトやテストもruntime
パッケージの標準的な情報源に依存するようになり、Goのビルドシステム全体の一貫性と信頼性が向上します。特に、syscall_ARCH.go
ファイルの削除は、特定のアーキテクチャに依存する定数を個別のファイルで管理する必要がなくなったことを意味し、コードベースの重複を減らし、メンテナンスを容易にします。
この変更は、Go言語がその初期段階から、より洗練された、堅牢な、そしてクロスプラットフォーム開発に優れた言語へと進化していく過程の一部を示しています。
関連リンク
- Go Change List: https://golang.org/cl/5545048
参考にした情報源リンク
- Go Documentation: The
runtime
package: https://pkg.go.dev/runtime - Go Documentation: The
syscall
package: https://pkg.go.dev/syscall - Go Wiki: Go Environment Variables: https://go.dev/doc/install/source#environment
- Go Wiki: Cross-compilation: https://go.dev/doc/install/source#go_build