[インデックス 10815] ファイルの概要
このコミットは、Go言語の標準ライブラリであるosパッケージにおけるシグナル定義のビルドプロセスを改善し、go/buildパッケージとの互換性を確保することを目的としています。具体的には、オペレーティングシステム(OS)とアーキテクチャ(ARCH)の組み合わせごとにシグナル定義ファイルを自動生成する仕組みを導入し、ビルド時の問題を解決しています。
コミット
commit 1b82e03a8fd1a2558979d8870d973244505b5494
Author: Russ Cox <rsc@golang.org>
Date: Thu Dec 15 12:33:36 2011 -0500
os: make compatible with go/build
It is probably a mistake to have these here at all -
os is supposed to be portable - but this only fixes
the build issue.
R=golang-dev, r, r, iant
CC=golang-dev
https://golang.org/cl/5487073
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/1b82e03a8fd1a2558979d8870d973244505b5494
元コミット内容
このコミットは、src/pkg/osディレクトリ内のビルドシステムとシグナル定義ファイルに大幅な変更を加えています。
主な変更点は以下の通りです。
-
Makefileの変更:- 各OS(freebsd, darwin, linux, netbsd, openbsd, windows)の
GOFILES変数から、汎用的なsignal_unix.goやsignal_windows.goの代わりに、zsignal_$(GOOS)_$(GOARCH).goという形式のファイルがインクルードされるように変更されました。これにより、ビルド時に現在のOSとアーキテクチャに特化したシグナル定義が使用されるようになります。 CLEANFILESからsignal_unix.goとsignal_windows.goが削除されました。signal_unix.goとsignal_windows.goを生成するためのMakefileルールが削除されました。これは、新しい生成スクリプトmksignals.shにその役割が移管されたためです。
- 各OS(freebsd, darwin, linux, netbsd, openbsd, windows)の
-
src/pkg/os/mksignals.shの新規追加:- この新しいシェルスクリプトは、様々なOSとアーキテクチャの組み合わせ(darwin_386, darwin_amd64, freebsd_386, freebsd_amd64, linux_386, linux_amd64, linux_arm, openbsd_386, openbsd_amd64, windows_386, windows_amd64)に対応する
zsignal_*.goファイルを生成します。 - 各
zsignal_*.goファイルは、mkunixsignals.shスクリプトとgofmtコマンドを組み合わせて生成されます。
- この新しいシェルスクリプトは、様々なOSとアーキテクチャの組み合わせ(darwin_386, darwin_amd64, freebsd_386, freebsd_amd64, linux_386, linux_amd64, linux_arm, openbsd_386, openbsd_amd64, windows_386, windows_amd64)に対応する
-
src/pkg/os/mkunixsignals.shの変更:- 生成されるGoファイルのヘッダーコメントが更新され、
// MACHINE GENERATED; DO NOT EDITという警告と、再生成方法(./mksignals.shを実行すること)が明記されました。
- 生成されるGoファイルのヘッダーコメントが更新され、
-
zsignal_*.goファイルの新規追加:zsignal_darwin_386.go,zsignal_darwin_amd64.go,zsignal_freebsd_386.go,zsignal_freebsd_amd64.go,zsignal_linux_386.go,zsignal_linux_amd64.go,zsignal_linux_arm.go,zsignal_openbsd_386.go,zsignal_openbsd_amd64.go,zsignal_windows_386.go,zsignal_windows_amd64.goといった、OSとアーキテクチャに特化した多数のシグナル定義ファイルが追加されました。- これらのファイルは、
syscallパッケージから対応するシグナル定数をosパッケージのUnixSignal型にキャストしてエクスポートしています。
変更の背景
このコミットの主な背景は、Go言語のビルドシステム、特にgo/buildパッケージとの互換性の問題に対処することです。コミットメッセージには「os is supposed to be portable - but this only fixes the build issue.」(osパッケージはポータブルであるべきだが、これはビルドの問題を修正するだけだ)とあります。
初期のGo言語のビルドシステムでは、特定のOSやアーキテクチャに依存するコードの取り扱いが課題となることがありました。特に、シグナル定義のようなOS固有の定数は、異なる環境でビルドする際に問題を引き起こす可能性があります。
以前のGoのビルドプロセスでは、signal_unix.goやsignal_windows.goといった汎用的なシグナル定義ファイルが生成されていました。しかし、Goのクロスコンパイル機能が進化し、GOOS(ターゲットOS)とGOARCH(ターゲットアーキテクチャ)の組み合わせがより重要になるにつれて、これらの汎用ファイルでは不十分になったと考えられます。
このコミットは、各OSとアーキテクチャの組み合わせに対して明示的にシグナル定義ファイルを生成することで、ビルドシステムがより正確に依存関係を解決し、特定の環境でのビルドエラーを回避できるようにしています。これにより、go/buildパッケージがGoプロジェクトのビルドをより堅牢に管理できるようになります。
前提知識の解説
このコミットを理解するためには、以下の概念が前提となります。
-
Go言語の
osパッケージ:osパッケージは、オペレーティングシステム機能へのプラットフォームに依存しないインターフェースを提供します。ファイル操作、プロセス管理、環境変数、そしてシグナル処理などが含まれます。- シグナルは、プロセスに対して非同期に通知されるイベントであり、プログラムの終了、中断、再開などを制御するために使用されます。例えば、
SIGINTはCtrl+Cによるプログラム終了、SIGTERMは正常終了要求、SIGKILLは強制終了などを意味します。
-
Go言語の
syscallパッケージ:syscallパッケージは、低レベルのオペレーティングシステムプリミティブへのインターフェースを提供します。これは、OS固有のシステムコールを直接呼び出すための機能を含んでおり、osパッケージのような高レベルな抽象化の基盤となっています。- シグナル定数(例:
syscall.SIGINT,syscall.SIGTERM)は、このパッケージで定義されており、OSによってその値が異なります。
-
Go言語のビルドシステムと
go/build:- Go言語のビルドシステムは、ソースコードをコンパイルして実行可能ファイルを生成するプロセスを管理します。Goはクロスコンパイルを強力にサポートしており、
GOOSとGOARCHという環境変数を使って、異なるOSやアーキテクチャ向けのバイナリを生成できます。 go/buildパッケージは、Goのビルドプロセスの中核をなすもので、ソースファイルの解析、依存関係の解決、ビルドタグの処理などを行います。このパッケージは、どのファイルが特定のビルドターゲットに含まれるべきかを決定する上で重要な役割を果たします。
- Go言語のビルドシステムは、ソースコードをコンパイルして実行可能ファイルを生成するプロセスを管理します。Goはクロスコンパイルを強力にサポートしており、
-
ビルドタグ(Build Tags):
- Goのソースファイルには、
// +build linux,amd64のようなビルドタグを記述することで、特定のOS、アーキテクチャ、またはその他の条件が満たされた場合にのみそのファイルをビルドに含めるように指定できます。 - このコミットでは、
zsignal_$(GOOS)_$(GOARCH).goという命名規則とMakefileの変更により、ビルドタグに似た効果を実現し、適切なシグナル定義ファイルが選択されるようにしています。
- Goのソースファイルには、
-
コード生成 (Code Generation):
- Goプロジェクトでは、定数、インターフェース、特定のプラットフォーム固有のコードなどを自動生成するためにスクリプトを使用することがよくあります。これにより、手動での記述ミスを防ぎ、異なる環境への対応を容易にします。
- このコミットで追加された
mksignals.shや既存のmkunixsignals.shは、このコード生成の典型的な例です。
技術的詳細
このコミットの技術的な核心は、Goのosパッケージが扱うシグナル定数を、より細粒度でプラットフォーム固有の形で提供するように変更した点にあります。
以前は、Unix系OS向けにsignal_unix.go、Windows向けにsignal_windows.goという2つの主要なファイルが、それぞれmkunixsignals.shによって生成されていました。これらのファイルは、syscallパッケージからシグナル定数をインポートし、osパッケージ内で利用可能なUnixSignal型として再エクスポートしていました。
しかし、このアプローチでは、例えばLinuxの32ビット版と64ビット版、あるいはARM版でシグナル定数の値が異なる場合や、特定のOSバージョンで追加されたシグナルに対応する場合に、柔軟性に欠ける問題がありました。また、go/buildパッケージがGoのソースファイルを解析し、適切なビルドターゲットを決定する際に、より具体的なファイル名やビルドタグを期待するようになった可能性があります。
このコミットでは、以下の技術的アプローチが取られています。
-
zsignal_$(GOOS)_$(GOARCH).go命名規則の導入:zsignal_darwin_386.go、zsignal_linux_amd64.goのように、ファイル名に直接ターゲットOS (GOOS) とアーキテクチャ (GOARCH) を埋め込むことで、Goのビルドシステムが自動的に適切なファイルを選択できるようになります。これは、Goのビルドシステムがファイル名に基づいてプラットフォーム固有のファイルを自動的に含めるメカニズム(例:file_linux.goはLinuxでのみビルドされる)を応用したものです。- ファイル名の先頭に
zが付いているのは、Goのソースファイルがアルファベット順に処理される際に、これらの生成ファイルが他のファイルよりも後に処理されるようにするための慣習的なものです。
-
mksignals.shによる一元的な生成管理:- 新しく追加された
mksignals.shスクリプトは、すべてのサポート対象OSとアーキテクチャの組み合わせに対して、対応するzsignal_*.goファイルを生成する役割を担います。 - このスクリプトは、ループ内で
mkunixsignals.shを呼び出し、その出力をgofmtで整形してから、適切なファイル名で保存します。これにより、シグナル定義の生成プロセスが自動化され、一貫性が保たれます。
- 新しく追加された
-
Makefileの動的なファイル選択:src/pkg/os/Makefileは、GOFILES_$(GOOS)変数にzsignal_$(GOOS)_$(GOARCH).goを追加するように変更されました。- Goのビルドシステムは、
GOOSとGOARCH環境変数の値に基づいて、この変数に展開されるファイル名を決定します。例えば、GOOS=linuxかつGOARCH=amd64の場合、zsignal_linux_amd64.goがビルドに含められます。 - これにより、手動で各プラットフォームのシグナル定義を管理する手間が省け、ビルドの柔軟性と正確性が向上します。
-
mkunixsignals.shのコメント更新:- 生成されるGoファイルのヘッダーコメントがより詳細になり、
// MACHINE GENERATED; DO NOT EDITという警告と、再生成のためのコマンド(./mksignals.sh)が明記されました。これは、開発者がこれらのファイルを手動で編集しないように促し、コード生成の意図を明確にするためのベストプラクティスです。
- 生成されるGoファイルのヘッダーコメントがより詳細になり、
この変更により、osパッケージは、異なるOSやアーキテクチャの環境下でも、より正確かつ堅牢なシグナル処理を提供できるようになりました。特に、クロスコンパイルを行う際に、ターゲット環境に合致したシグナル定数が確実に利用されるようになります。
コアとなるコードの変更箇所
このコミットのコアとなる変更は、主に以下の3つのファイルに集約されます。
-
src/pkg/os/Makefile:GOFILES_freebsd,GOFILES_darwin,GOFILES_linux,GOFILES_netbsd,GOFILES_openbsd,GOFILES_windowsの各定義において、signal_unix.goまたはsignal_windows.goの代わりに、zsignal_$(GOOS)_$(GOARCH).goが追加されました。CLEANFILESからsignal_unix.goとsignal_windows.goの項目が削除されました。signal_unix.goとsignal_windows.goを生成するための具体的なルール(signal_unix.go: ...とsignal_windows.go: ...)が削除されました。
--- a/src/pkg/os/Makefile +++ b/src/pkg/os/Makefile @@ -26,7 +26,7 @@ GOFILES_freebsd=\ sys_bsd.go\ exec_posix.go\ exec_unix.go\ - signal_unix.go\ + zsignal_$(GOOS)_$(GOARCH).go\ GOFILES_darwin=\ dir_unix.go\ @@ -37,7 +37,7 @@ GOFILES_darwin=\ sys_bsd.go\ exec_posix.go\ exec_unix.go\ - signal_unix.go\ + zsignal_$(GOOS)_$(GOARCH).go\ GOFILES_linux=\ dir_unix.go\ @@ -48,7 +48,7 @@ GOFILES_linux=\ sys_linux.go\ exec_posix.go\ exec_unix.go\ - signal_unix.go\ + zsignal_$(GOOS)_$(GOARCH).go\ GOFILES_netbsd=\ dir_unix.go\ @@ -59,7 +59,7 @@ GOFILES_netbsd=\ sys_bsd.go\ exec_posix.go\ exec_unix.go\ - signal_unix.go\ + zsignal_$(GOOS)_$(GOARCH).go\ GOFILES_openbsd=\ dir_unix.go\ @@ -70,7 +70,7 @@ GOFILES_openbsd=\ sys_bsd.go\ exec_posix.go\ exec_unix.go\ - signal_unix.go\ + zsignal_$(GOOS)_$(GOARCH).go\ GOFILES_windows=\ dir_windows.go\ @@ -81,7 +81,7 @@ GOFILES_windows=\ sys_windows.go\ exec_posix.go\ exec_windows.go\ - signal_windows.go\\\ + zsignal_$(GOOS)_$(GOARCH).go\ GOFILES_plan9=\ dir_plan9.go\ @@ -94,12 +94,4 @@ GOFILES_plan9=\ GOFILES+=$(GOFILES_$(GOOS))\ -CLEANFILES+=signal_unix.go signal_windows.go -\ include ../../Make.pkg -\ -signal_unix.go: ../syscall/zerrors_$(GOOS)_$(GOARCH).go -\t./mkunixsignals.sh $< > $@ || rm -f $@ -\ -signal_windows.go: ../syscall/ztypes_$(GOOS).go -\t./mkunixsignals.sh $< > $@ || rm -f $@ -
src/pkg/os/mksignals.sh(新規ファイル):- このスクリプトは、Unix系OSとWindows系のOS/アーキテクチャの組み合わせごとにループを回し、
mkunixsignals.shを実行してzsignal_*.goファイルを生成します。
--- /dev/null +++ b/src/pkg/os/mksignals.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +for targ in \ + darwin_386 \ + darwin_amd64 \ + freebsd_386 \ + freebsd_amd64 \ + linux_386 \ + linux_amd64 \ + linux_arm \ + openbsd_386 \ + openbsd_amd64 \ +; do + ./mkunixsignals.sh ../syscall/zerrors_$targ.go |gofmt >zsignal_$targ.go +done + +for targ in \ + windows_386 \ + windows_amd64 \ +; do + ./mkunixsignals.sh ../syscall/ztypes_windows.go |gofmt >zsignal_$targ.go +done - このスクリプトは、Unix系OSとWindows系のOS/アーキテクチャの組み合わせごとにループを回し、
-
src/pkg/os/mkunixsignals.sh:- 生成されるGoファイルのヘッダーコメントが変更され、再生成方法がより明確に指示されるようになりました。
--- a/src/pkg/os/mkunixsignals.sh +++ b/src/pkg/os/mkunixsignals.sh @@ -3,8 +3,11 @@ # license that can be found in the LICENSE file.\ \ -echo '// ./mkunixsignals.sh' "$1"\ -echo '// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT'\ +echo '// MACHINE GENERATED; DO NOT EDIT'\ +echo '// To regenerate, run'\ +echo '//\t./mksignals.sh'\ +echo '// which, for this file, will run'\ +echo '//\t./mkunixsignals.sh' "$1"\ echo\ \ cat <<EOH
また、以下の多数のzsignal_*.goファイルが新規追加されています。これらはmksignals.shによって生成されるファイルであり、各OS/アーキテクチャの組み合わせに対応するシグナル定数を定義しています。
src/pkg/os/zsignal_darwin_386.gosrc/pkg/os/zsignal_darwin_amd64.gosrc/pkg/os/zsignal_freebsd_386.gosrc/pkg/os/zsignal_freebsd_amd64.gosrc/pkg/os/zsignal_linux_386.gosrc/pkg/os/zsignal_linux_amd64.gosrc/pkg/os/zsignal_linux_arm.gosrc/pkg/os/zsignal_openbsd_386.gosrc/pkg/os/zsignal_openbsd_amd64.gosrc/pkg/os/zsignal_windows_386.gosrc/pkg/os/zsignal_windows_amd64.go
これらのzsignal_*.goファイルは、基本的に以下のような構造を持っています。
// MACHINE GENERATED; DO NOT EDIT
// To regenerate, run
// ./mksignals.sh
// which, for this file, will run
// ./mkunixsignals.sh ../syscall/zerrors_darwin_386.go
package os
import (
"syscall"
)
var _ = syscall.Open // in case there are zero signals
const (
SIGABRT = UnixSignal(syscall.SIGABRT)
SIGALRM = UnixSignal(syscall.SIGALRM)
// ... その他のシグナル定数 ...
)
コアとなるコードの解説
このコミットの核となる変更は、Goのosパッケージがシグナル定数を扱う方法を、より動的かつプラットフォーム固有の形に移行した点です。
-
Makefileの変更:- 以前の
Makefileでは、signal_unix.goやsignal_windows.goといった、比較的汎用的なシグナル定義ファイルを直接ビルドに含めていました。これらのファイルは、mkunixsignals.shスクリプトによって生成されていました。 - 今回の変更では、
GOFILES_$(GOOS)変数にzsignal_$(GOOS)_$(GOARCH).goというパターンが導入されました。これは、Goのビルドシステムが、現在のビルドターゲット(GOOSとGOARCHの組み合わせ)に基づいて、適切なシグナル定義ファイルを自動的に選択して含めることを可能にします。例えば、Linux AMD64向けにビルドする場合、zsignal_linux_amd64.goが自動的に選択されます。 - これにより、ビルドシステムは、特定のOSとアーキテクチャに厳密に合致するシグナル定数を使用できるようになり、クロスコンパイル時の正確性が向上します。また、以前の汎用ファイル生成ルールが削除されたことで、ビルドプロセスの責任が新しい
mksignals.shスクリプトに一元化されました。
- 以前の
-
mksignals.shの導入:- この新しいシェルスクリプトは、Goのビルドプロセスにおけるシグナル定義ファイルの生成を自動化する中心的な役割を担います。
- スクリプトは、Goがサポートする主要なOSとアーキテクチャの組み合わせを列挙し、それぞれの組み合わせに対して
mkunixsignals.shを実行します。 mkunixsignals.shの出力はパイプでgofmtに渡され、Goの標準的なフォーマットに整形された後、zsignal_$(GOOS)_$(GOARCH).goという命名規則に従ってファイルに保存されます。- この自動化により、新しいOS/アーキテクチャのサポートが追加された場合や、シグナル定義が変更された場合に、手動で多数のファイルを更新する手間が省け、エラーのリスクが低減されます。
-
zsignal_*.goファイルの役割:- これらのファイルは、各OSとアーキテクチャの組み合わせに対応するシグナル定数を定義しています。例えば、
zsignal_linux_amd64.goにはLinux AMD64環境におけるSIGABRT,SIGALRMなどのシグナル定数が、syscallパッケージからインポートされた値に基づいて定義されています。 UnixSignal型へのキャストは、osパッケージ内でシグナルを扱うための型安全な方法を提供します。- これらのファイルは「MACHINE GENERATED; DO NOT EDIT」と明記されており、手動での変更は推奨されません。これは、コード生成によって管理されるファイルの典型的なパターンです。
- これらのファイルは、各OSとアーキテクチャの組み合わせに対応するシグナル定数を定義しています。例えば、
この一連の変更により、Goのosパッケージは、より堅牢で保守性の高い方法でプラットフォーム固有のシグナル定義を扱うことができるようになりました。これは、Goが多様な環境で動作するポータブルな言語としての地位を確立する上で重要なステップです。
関連リンク
- Go言語の
osパッケージ公式ドキュメント: https://pkg.go.dev/os - Go言語の
syscallパッケージ公式ドキュメント: https://pkg.go.dev/syscall - Go言語のビルドコマンド(
go build)に関するドキュメント: https://go.dev/cmd/go/#hdr-Compile_packages_and_dependencies - Go言語のビルドタグに関するドキュメント: https://go.dev/cmd/go/#hdr-Build_constraints
参考にした情報源リンク
- Go言語の公式リポジトリ: https://github.com/golang/go
- Go Code Review Comments (特にコード生成に関する慣習): https://go.dev/doc/effective_go#generality
- Goのクロスコンパイルに関する情報 (例:
GOOSとGOARCH): https://go.dev/doc/install/source#environment - Goの初期のビルドシステムに関する議論や歴史的背景(GoのメーリングリストやIssueトラッカーなど)
- このコミットのChange-ID:
https://golang.org/cl/5487073(GoのGerrit Code Reviewシステムへのリンク) - GoのIssueトラッカーで
go/buildやosパッケージに関連する過去のIssueを検索すると、より詳細な背景情報が見つかる可能性があります。```markdown
- このコミットのChange-ID:
[インデックス 10815] ファイルの概要
このコミットは、Go言語の標準ライブラリであるosパッケージにおけるシグナル定義のビルドプロセスを改善し、go/buildパッケージとの互換性を確保することを目的としています。具体的には、オペレーティングシステム(OS)とアーキテクチャ(ARCH)の組み合わせごとにシグナル定義ファイルを自動生成する仕組みを導入し、ビルド時の問題を解決しています。
コミット
commit 1b82e03a8fd1a2558979d8870d973244505b5494
Author: Russ Cox <rsc@golang.org>
Date: Thu Dec 15 12:33:36 2011 -0500
os: make compatible with go/build
It is probably a mistake to have these here at all -
os is supposed to be portable - but this only fixes
the build issue.
R=golang-dev, r, r, iant
CC=golang-dev
https://golang.org/cl/5487073
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/1b82e03a8fd1a2558979d8870d973244505b5494
元コミット内容
このコミットは、src/pkg/osディレクトリ内のビルドシステムとシグナル定義ファイルに大幅な変更を加えています。
主な変更点は以下の通りです。
-
Makefileの変更:- 各OS(freebsd, darwin, linux, netbsd, openbsd, windows)の
GOFILES変数から、汎用的なsignal_unix.goやsignal_windows.goの代わりに、zsignal_$(GOOS)_$(GOARCH).goという形式のファイルがインクルードされるように変更されました。これにより、ビルド時に現在のOSとアーキテクチャに特化したシグナル定義が使用されるようになります。 CLEANFILESからsignal_unix.goとsignal_windows.goが削除されました。signal_unix.goとsignal_windows.goを生成するためのMakefileルールが削除されました。これは、新しい生成スクリプトmksignals.shにその役割が移管されたためです。
- 各OS(freebsd, darwin, linux, netbsd, openbsd, windows)の
-
src/pkg/os/mksignals.shの新規追加:- この新しいシェルスクリプトは、様々なOSとアーキテクチャの組み合わせ(darwin_386, darwin_amd64, freebsd_386, freebsd_amd64, linux_386, linux_amd64, linux_arm, openbsd_386, openbsd_amd64, windows_386, windows_amd64)に対応する
zsignal_*.goファイルを生成します。 - 各
zsignal_*.goファイルは、mkunixsignals.shスクリプトとgofmtコマンドを組み合わせて生成されます。
- この新しいシェルスクリプトは、様々なOSとアーキテクチャの組み合わせ(darwin_386, darwin_amd64, freebsd_386, freebsd_amd64, linux_386, linux_amd64, linux_arm, openbsd_386, openbsd_amd64, windows_386, windows_amd64)に対応する
-
src/pkg/os/mkunixsignals.shの変更:- 生成されるGoファイルのヘッダーコメントが更新され、
// MACHINE GENERATED; DO NOT EDITという警告と、再生成方法(./mksignals.shを実行すること)が明記されました。
- 生成されるGoファイルのヘッダーコメントが更新され、
-
zsignal_*.goファイルの新規追加:zsignal_darwin_386.go,zsignal_darwin_amd64.go,zsignal_freebsd_386.go,zsignal_freebsd_amd64.go,zsignal_linux_386.go,zsignal_linux_amd64.go,zsignal_linux_arm.go,zsignal_openbsd_386.go,zsignal_openbsd_amd64.go,zsignal_windows_386.go,zsignal_windows_amd64.goといった、OSとアーキテクチャに特化した多数のシグナル定義ファイルが追加されました。- これらのファイルは、
syscallパッケージから対応するシグナル定数をosパッケージのUnixSignal型にキャストしてエクスポートしています。
変更の背景
このコミットの主な背景は、Go言語のビルドシステム、特にgo/buildパッケージとの互換性の問題に対処することです。コミットメッセージには「os is supposed to be portable - but this only fixes the build issue.」(osパッケージはポータブルであるべきだが、これはビルドの問題を修正するだけだ)とあります。
初期のGo言語のビルドシステムでは、特定のOSやアーキテクチャに依存するコードの取り扱いが課題となることがありました。特に、シグナル定義のようなOS固有の定数は、異なる環境でビルドする際に問題を引き起こす可能性があります。
以前のGoのビルドプロセスでは、signal_unix.goやsignal_windows.goといった汎用的なシグナル定義ファイルが生成されていました。しかし、Goのクロスコンパイル機能が進化し、GOOS(ターゲットOS)とGOARCH(ターゲットアーキテクチャ)の組み合わせがより重要になるにつれて、これらの汎用ファイルでは不十分になったと考えられます。
このコミットは、各OSとアーキテクチャの組み合わせに対して明示的にシグナル定義ファイルを生成することで、ビルドシステムがより正確に依存関係を解決し、特定の環境でのビルドエラーを回避できるようにしています。これにより、go/buildパッケージがGoプロジェクトのビルドをより堅牢に管理できるようになります。
前提知識の解説
このコミットを理解するためには、以下の概念が前提となります。
-
Go言語の
osパッケージ:osパッケージは、オペレーティングシステム機能へのプラットフォームに依存しないインターフェースを提供します。ファイル操作、プロセス管理、環境変数、そしてシグナル処理などが含まれます。- シグナルは、プロセスに対して非同期に通知されるイベントであり、プログラムの終了、中断、再開などを制御するために使用されます。例えば、
SIGINTはCtrl+Cによるプログラム終了、SIGTERMは正常終了要求、SIGKILLは強制終了などを意味します。
-
Go言語の
syscallパッケージ:syscallパッケージは、低レベルのオペレーティングシステムプリミティブへのインターフェースを提供します。これは、OS固有のシステムコールを直接呼び出すための機能を含んでおり、osパッケージのような高レベルな抽象化の基盤となっています。- シグナル定数(例:
syscall.SIGINT,syscall.SIGTERM)は、このパッケージで定義されており、OSによってその値が異なります。
-
Go言語のビルドシステムと
go/build:- Go言語のビルドシステムは、ソースコードをコンパイルして実行可能ファイルを生成するプロセスを管理します。Goはクロスコンパイルを強力にサポートしており、
GOOSとGOARCHという環境変数を使って、異なるOSやアーキテクチャ向けのバイナリを生成できます。 go/buildパッケージは、Goのビルドプロセスの中核をなすもので、ソースファイルの解析、依存関係の解決、ビルドタグの処理などを行います。このパッケージは、どのファイルが特定のビルドターゲットに含まれるべきかを決定する上で重要な役割を果たします。
- Go言語のビルドシステムは、ソースコードをコンパイルして実行可能ファイルを生成するプロセスを管理します。Goはクロスコンパイルを強力にサポートしており、
-
ビルドタグ(Build Tags):
- Goのソースファイルには、
// +build linux,amd64のようなビルドタグを記述することで、特定のOS、アーキテクチャ、またはその他の条件が満たされた場合にのみそのファイルをビルドに含めるように指定できます。 - このコミットでは、
zsignal_$(GOOS)_$(GOARCH).goという命名規則とMakefileの変更により、ビルドタグに似た効果を実現し、適切なシグナル定義ファイルが選択されるようにしています。
- Goのソースファイルには、
-
コード生成 (Code Generation):
- Goプロジェクトでは、定数、インターフェース、特定のプラットフォーム固有のコードなどを自動生成するためにスクリプトを使用することがよくあります。これにより、手動での記述ミスを防ぎ、異なる環境への対応を容易にします。
- このコミットで追加された
mksignals.shや既存のmkunixsignals.shは、このコード生成の典型的な例です。
技術的詳細
このコミットの技術的な核心は、Goのosパッケージが扱うシグナル定数を、より細粒度でプラットフォーム固有の形で提供するように変更した点にあります。
以前は、Unix系OS向けにsignal_unix.go、Windows向けにsignal_windows.goという2つの主要なファイルが、それぞれmkunixsignals.shによって生成されていました。これらのファイルは、syscallパッケージからシグナル定数をインポートし、osパッケージ内で利用可能なUnixSignal型として再エクスポートしていました。
しかし、このアプローチでは、例えばLinuxの32ビット版と64ビット版、あるいはARM版でシグナル定数の値が異なる場合や、特定のOSバージョンで追加されたシグナルに対応する場合に、柔軟性に欠ける問題がありました。また、go/buildパッケージがGoのソースファイルを解析し、適切なビルドターゲットを決定する際に、より具体的なファイル名やビルドタグを期待するようになった可能性があります。
このコミットでは、以下の技術的アプローチが取られています。
-
zsignal_$(GOOS)_$(GOARCH).go命名規則の導入:zsignal_darwin_386.go、zsignal_linux_amd64.goのように、ファイル名に直接ターゲットOS (GOOS) とアーキテクチャ (GOARCH) を埋め込むことで、Goのビルドシステムが自動的に適切なファイルを選択できるようになります。これは、Goのビルドシステムがファイル名に基づいてプラットフォーム固有のファイルを自動的に含めるメカニズム(例:file_linux.goはLinuxでのみビルドされる)を応用したものです。- ファイル名の先頭に
zが付いているのは、Goのソースファイルがアルファベット順に処理される際に、これらの生成ファイルが他のファイルよりも後に処理されるようにするための慣習的なものです。
-
mksignals.shによる一元的な生成管理:- 新しく追加された
mksignals.shスクリプトは、すべてのサポート対象OSとアーキテクチャの組み合わせに対して、対応するzsignal_*.goファイルを生成する役割を担います。 - このスクリプトは、ループ内で
mkunixsignals.shを呼び出し、その出力をgofmtで整形してから、適切なファイル名で保存します。これにより、シグナル定義の生成プロセスが自動化され、一貫性が保たれます。
- 新しく追加された
-
Makefileの動的なファイル選択:src/pkg/os/Makefileは、GOFILES_$(GOOS)変数にzsignal_$(GOOS)_$(GOARCH).goを追加するように変更されました。- Goのビルドシステムは、
GOOSとGOARCH環境変数の値に基づいて、この変数に展開されるファイル名を決定します。例えば、GOOS=linuxかつGOARCH=amd64の場合、zsignal_linux_amd64.goがビルドに含められます。 - これにより、手動で各プラットフォームのシグナル定義を管理する手間が省け、ビルドの柔軟性と正確性が向上します。
-
mkunixsignals.shのコメント更新:- 生成されるGoファイルのヘッダーコメントがより詳細になり、
// MACHINE GENERATED; DO NOT EDITという警告と、再生成のためのコマンド(./mksignals.sh)が明記されました。これは、開発者がこれらのファイルを手動で編集しないように促し、コード生成の意図を明確にするためのベストプラクティスです。
- 生成されるGoファイルのヘッダーコメントがより詳細になり、
この変更により、osパッケージは、異なるOSやアーキテクチャの環境下でも、より正確かつ堅牢なシグナル処理を提供できるようになりました。特に、クロスコンパイルを行う際に、ターゲット環境に合致したシグナル定数が確実に利用されるようになります。
コアとなるコードの変更箇所
このコミットのコアとなる変更は、主に以下の3つのファイルに集約されます。
-
src/pkg/os/Makefile:GOFILES_freebsd,GOFILES_darwin,GOFILES_linux,GOFILES_netbsd,GOFILES_openbsd,GOFILES_windowsの各定義において、signal_unix.goまたはsignal_windows.goの代わりに、zsignal_$(GOOS)_$(GOARCH).goが追加されました。CLEANFILESからsignal_unix.goとsignal_windows.goの項目が削除されました。signal_unix.goとsignal_windows.goを生成するための具体的なルール(signal_unix.go: ...とsignal_windows.go: ...)が削除されました。
--- a/src/pkg/os/Makefile +++ b/src/pkg/os/Makefile @@ -26,7 +26,7 @@ GOFILES_freebsd=\ sys_bsd.go\ exec_posix.go\ exec_unix.go\ - signal_unix.go\ + zsignal_$(GOOS)_$(GOARCH).go\ GOFILES_darwin=\ dir_unix.go\ @@ -37,7 +37,7 @@ GOFILES_darwin=\ sys_bsd.go\ exec_posix.go\ exec_unix.go\ - signal_unix.go\ + zsignal_$(GOOS)_$(GOARCH).go\ GOFILES_linux=\ dir_unix.go\ @@ -48,7 +48,7 @@ GOFILES_linux=\ sys_linux.go\ exec_posix.go\ exec_unix.go\ - signal_unix.go\ + zsignal_$(GOOS)_$(GOARCH).go\ GOFILES_netbsd=\ dir_unix.go\ @@ -59,7 +59,7 @@ GOFILES_netbsd=\ sys_bsd.go\ exec_posix.go\ exec_unix.go\ - signal_unix.go\ + zsignal_$(GOOS)_$(GOARCH).go\ GOFILES_openbsd=\ dir_unix.go\ @@ -70,7 +70,7 @@ GOFILES_openbsd=\ sys_bsd.go\ exec_posix.go\ exec_unix.go\ - signal_unix.go\ + zsignal_$(GOOS)_$(GOARCH).go\ GOFILES_windows=\ dir_windows.go\ @@ -81,7 +81,7 @@ GOFILES_windows=\ sys_windows.go\ exec_posix.go\ exec_windows.go\ - signal_windows.go\\\ + zsignal_$(GOOS)_$(GOARCH).go\ GOFILES_plan9=\ dir_plan9.go\ @@ -94,12 +94,4 @@ GOFILES_plan9=\ GOFILES+=$(GOFILES_$(GOOS))\ -CLEANFILES+=signal_unix.go signal_windows.go -\ include ../../Make.pkg -\ -signal_unix.go: ../syscall/zerrors_$(GOOS)_$(GOARCH).go -\t./mkunixsignals.sh $< > $@ || rm -f $@ -\ -signal_windows.go: ../syscall/ztypes_$(GOOS).go -\t./mkunixsignals.sh $< > $@ || rm -f $@ -
src/pkg/os/mksignals.sh(新規ファイル):- このスクリプトは、Unix系OSとWindows系のOS/アーキテクチャの組み合わせごとにループを回し、
mkunixsignals.shを実行してzsignal_*.goファイルを生成します。
--- /dev/null +++ b/src/pkg/os/mksignals.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +for targ in \ + darwin_386 \ + darwin_amd64 \ + freebsd_386 \ + freebsd_amd64 \ + linux_386 \ + linux_amd64 \ + linux_arm \ + openbsd_386 \ + openbsd_amd64 \ +; do + ./mkunixsignals.sh ../syscall/zerrors_$targ.go |gofmt >zsignal_$targ.go +done + +for targ in \ + windows_386 \ + windows_amd64 \ +; do + ./mkunixsignals.sh ../syscall/ztypes_windows.go |gofmt >zsignal_$targ.go +done - このスクリプトは、Unix系OSとWindows系のOS/アーキテクチャの組み合わせごとにループを回し、
-
src/pkg/os/mkunixsignals.sh:- 生成されるGoファイルのヘッダーコメントが変更され、再生成方法がより明確に指示されるようになりました。
--- a/src/pkg/os/mkunixsignals.sh +++ b/src/pkg/os/mkunixsignals.sh @@ -3,8 +3,11 @@ # license that can be found in the LICENSE file.\ \ -echo '// ./mkunixsignals.sh' "$1"\ -echo '// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT'\ +echo '// MACHINE GENERATED; DO NOT EDIT'\ +echo '// To regenerate, run'\ +echo '//\t./mksignals.sh'\ +echo '// which, for this file, will run'\ +echo '//\t./mkunixsignals.sh' "$1"\ echo\ \ cat <<EOH
また、以下の多数のzsignal_*.goファイルが新規追加されています。これらはmksignals.shによって生成されるファイルであり、各OS/アーキテクチャの組み合わせに対応するシグナル定数を定義しています。
src/pkg/os/zsignal_darwin_386.gosrc/pkg/os/zsignal_darwin_amd64.gosrc/pkg/os/zsignal_freebsd_386.gosrc/pkg/os/zsignal_freebsd_amd64.gosrc/pkg/os/zsignal_linux_386.gosrc/pkg/os/zsignal_linux_amd64.gosrc/pkg/os/zsignal_linux_arm.gosrc/pkg/os/zsignal_openbsd_386.gosrc/pkg/os/zsignal_openbsd_amd64.gosrc/pkg/os/zsignal_windows_386.gosrc/pkg/os/zsignal_windows_amd64.go
これらのzsignal_*.goファイルは、基本的に以下のような構造を持っています。
// MACHINE GENERATED; DO NOT EDIT
// To regenerate, run
// ./mksignals.sh
// which, for this file, will run
// ./mkunixsignals.sh ../syscall/zerrors_darwin_386.go
package os
import (
"syscall"
)
var _ = syscall.Open // in case there are zero signals
const (
SIGABRT = UnixSignal(syscall.SIGABRT)
SIGALRM = UnixSignal(syscall.SIGALRM)
// ... その他のシグナル定数 ...
)
コアとなるコードの解説
このコミットの核となる変更は、Goのosパッケージがシグナル定数を扱う方法を、より動的かつプラットフォーム固有の形に移行した点です。
-
Makefileの変更:- 以前の
Makefileでは、signal_unix.goやsignal_windows.goといった、比較的汎用的なシグナル定義ファイルを直接ビルドに含めていました。これらのファイルは、mkunixsignals.shスクリプトによって生成されていました。 - 今回の変更では、
GOFILES_$(GOOS)変数にzsignal_$(GOOS)_$(GOARCH).goというパターンが導入されました。これは、Goのビルドシステムが、現在のビルドターゲット(GOOSとGOARCHの組み合わせ)に基づいて、適切なシグナル定義ファイルを自動的に選択して含めることを可能にします。例えば、Linux AMD64向けにビルドする場合、zsignal_linux_amd64.goが自動的に選択されます。 - これにより、ビルドシステムは、特定のOSとアーキテクチャに厳密に合致するシグナル定数を使用できるようになり、クロスコンパイル時の正確性が向上します。また、以前の汎用ファイル生成ルールが削除されたことで、ビルドプロセスの責任が新しい
mksignals.shスクリプトに一元化されました。
- 以前の
-
mksignals.shの導入:- この新しいシェルスクリプトは、Goのビルドプロセスにおけるシグナル定義ファイルの生成を自動化する中心的な役割を担います。
- スクリプトは、Goがサポートする主要なOSとアーキテクチャの組み合わせを列挙し、それぞれの組み合わせに対して
mkunixsignals.shを実行します。 mkunixsignals.shの出力はパイプでgofmtに渡され、Goの標準的なフォーマットに整形された後、zsignal_$(GOOS)_$(GOARCH).goという命名規則に従ってファイルに保存されます。- この自動化により、新しいOS/アーキテクチャのサポートが追加された場合や、シグナル定義が変更された場合に、手動で多数のファイルを更新する手間が省け、エラーのリスクが低減されます。
-
zsignal_*.goファイルの役割:- これらのファイルは、各OSとアーキテクチャの組み合わせに対応するシグナル定数を定義しています。例えば、
zsignal_linux_amd64.goにはLinux AMD64環境におけるSIGABRT,SIGALRMなどのシグナル定数が、syscallパッケージからインポートされた値に基づいて定義されています。 UnixSignal型へのキャストは、osパッケージ内でシグナルを扱うための型安全な方法を提供します。- これらのファイルは「MACHINE GENERATED; DO NOT EDIT」と明記されており、手動での変更は推奨されません。これは、コード生成によって管理されるファイルの典型的なパターンです。
- これらのファイルは、各OSとアーキテクチャの組み合わせに対応するシグナル定数を定義しています。例えば、
この一連の変更により、Goのosパッケージは、より堅牢で保守性の高い方法でプラットフォーム固有のシグナル定義を扱うことができるようになりました。これは、Goが多様な環境で動作するポータブルな言語としての地位を確立する上で重要なステップです。
関連リンク
- Go言語の
osパッケージ公式ドキュメント: https://pkg.go.dev/os - Go言語の
syscallパッケージ公式ドキュメント: https://pkg.go.dev/syscall - Go言語のビルドコマンド(
go build)に関するドキュメント: https://go.dev/cmd/go/#hdr-Compile_packages_and_dependencies - Go言語のビルドタグに関するドキュメント: https://go.dev/cmd/go/#hdr-Build_constraints
参考にした情報源リンク
- Go言語の公式リポジトリ: https://github.com/golang/go
- Go Code Review Comments (特にコード生成に関する慣習): https://go.dev/doc/effective_go#generality
- Goのクロスコンパイルに関する情報 (例:
GOOSとGOARCH): https://go.dev/doc/install/source#environment - Goの初期のビルドシステムに関する議論や歴史的背景(GoのメーリングリストやIssueトラッカーなど)
- このコミットのChange-ID:
https://golang.org/cl/5487073(GoのGerrit Code Reviewシステムへのリンク) - GoのIssueトラッカーで
go/buildやosパッケージに関連する過去のIssueを検索すると、より詳細な背景情報が見つかる可能性があります。
- このコミットのChange-ID: