[インデックス 18822] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにおけるWindowsシステムコール生成メカニズムの重要な変更を導入します。具体的には、既存のPerlスクリプトであるmksyscall_windows.pl
をGo言語で書かれた新しいツールmksyscall_windows.go
に置き換え、さらにWindows固有のエラー生成スクリプトmkerrors_windows.sh
を削除しています。これにより、Windows環境でのGo開発における外部依存性を減らし、ビルドプロセスの簡素化を図っています。
コミット
commit c07ca77432d0c6b7e75eb0eec83ecccea03d38b5
Author: Alex Brainman <alex.brainman@gmail.com>
Date: Tue Mar 11 16:36:14 2014 +1100
syscall: replace mksyscall_windows.pl with mksyscall_windows.go
Not many windows users have perl installed. They can just use
standard go tools instead. Also mkerrors_windows.sh script
removed - we don't add any new "unix" errors to windows
syscall package anymore.
LGTM=rsc
R=golang-codereviews, rsc
CC=golang-codereviews
https://golang.org/cl/41060044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/c07ca77432d0c6b7e75eb0eec83ecccea03d38b5
元コミット内容
syscall: replace mksyscall_windows.pl with mksyscall_windows.go
Not many windows users have perl installed. They can just use
standard go tools instead. Also mkerrors_windows.sh script
removed - we don't add any new "unix" errors to windows
syscall package anymore.
LGTM=rsc
R=golang-codereviews, rsc
CC=golang-codereviews
https://golang.org/cl/41060044
変更の背景
この変更の主な背景には、以下の2点があります。
- Perlへの依存性排除: 従来のWindowsシステムコール生成にはPerlスクリプト(
mksyscall_windows.pl
)が使用されていました。しかし、コミットメッセージにあるように「多くのWindowsユーザーはPerlをインストールしていない」という問題がありました。Goのツールチェーン自体でシステムコール生成を完結させることで、Go開発者がWindows環境でGoをビルド・開発する際の外部依存性を減らし、セットアップの複雑さを軽減することが目的です。 - ビルドプロセスの簡素化:
mkerrors_windows.sh
スクリプトの削除は、Windows固有のエラー生成プロセスを簡素化するためです。Goのsyscall
パッケージは、Unix系システムのエラーコードをWindowsのエラーコードにマッピングする機能を持っていましたが、このコミットの時点では、新しい「Unix」エラーをWindowsのsyscall
パッケージに追加する必要がなくなったため、専用のスクリプトが不要になりました。これにより、全体的なビルドスクリプトの複雑性が低減されます。
前提知識の解説
このコミットを理解するためには、以下の前提知識が役立ちます。
- Go言語の
syscall
パッケージ: Go言語のsyscall
パッケージは、オペレーティングシステム(OS)の低レベルな機能(システムコール)にアクセスするためのインターフェースを提供します。これにより、ファイル操作、ネットワーク通信、プロセス管理など、OSが提供する基本的なサービスをGoプログラムから直接呼び出すことができます。 - システムコールラッパーの生成: 異なるOS(Windows, Linux, macOSなど)は、それぞれ独自のシステムコールインターフェースを持っています。Goのようなクロスプラットフォーム言語では、各OSのシステムコールをGoの関数として呼び出せるように、OS固有のラッパーコードを生成する必要があります。この生成プロセスは、通常、特定のツール(この場合は
mksyscall_windows.pl
やmksyscall_windows.go
)によって自動化されます。 - コード生成: ソフトウェア開発において、特定のパターンに従うコードや、異なるプラットフォーム向けのコードを自動的に生成する手法です。これにより、手動での記述ミスを減らし、開発効率を向上させることができます。Go言語では、
go generate
コマンドや、ビルド時に実行されるスクリプトによってコード生成が行われることがあります。 - Perlスクリプト: Perlは、テキスト処理やシステム管理タスクに広く使用されるスクリプト言語です。過去には、Goプロジェクトを含む多くのオープンソースプロジェクトで、ビルドスクリプトやコード生成スクリプトとして利用されていました。
- Windows API: Windowsオペレーティングシステムが提供するアプリケーションプログラミングインターフェース(API)の集合体です。GoプログラムがWindows固有の機能(レジストリ操作、GUI、特定のデバイスアクセスなど)を利用する際には、このAPIを呼び出す必要があります。
技術的詳細
このコミットの技術的な核心は、Windowsシステムコールラッパーの生成方法をPerlからGoへ移行した点にあります。
-
mksyscall_windows.pl
の役割:- このPerlスクリプトは、
syscall_windows.go
などのファイルに記述された特殊なコメント(//sys
で始まる行)を解析していました。 - これらのコメントは、Windows API関数のGo言語でのプロトタイプ(関数名、引数、戻り値の型など)を定義していました。
- スクリプトは、これらのプロトタイプを読み取り、Goの
syscall
パッケージがWindows APIを呼び出すために必要な低レベルのGoコード(zsyscall_windows_386.go
やzsyscall_windows_amd64.go
など)を生成していました。これには、DLLのロード、プロシージャアドレスの取得、Syscall
関数(Syscall
,Syscall6
,Syscall9
など)の呼び出しなどが含まれます。 - 特に、文字列引数の変換(Goの文字列からWindows APIが期待するUTF-16またはANSI文字列への変換)や、エラーハンドリング(Windowsの
GetLastError
に基づくエラーの取得)のロジックも生成していました。
- このPerlスクリプトは、
-
mksyscall_windows.go
の導入:- 新しい
mksyscall_windows.go
は、Perlスクリプトと同じ機能をGo言語で再実装したものです。 - このGoプログラムは、
text/template
パッケージを使用して、Goのソースコードを生成します。これにより、コード生成ロジックがGo言語の標準ライブラリ内で完結し、外部ツールへの依存がなくなります。 mksyscall_windows.go
は、//sys
コメントの解析、パラメータの型変換(string
から*uint16
や*byte
への変換、bool
からuint32
への変換、スライスからポインタと長さへの変換など)、システムコール引数の準備、およびエラー処理ロジックの生成を行います。- 特に、
FailCond
という概念が導入され、Windows APIの戻り値がどのような条件で失敗とみなされるかを指定できるようになっています(例:[failretval==-1]
)。
- 新しい
-
mkerrors_windows.sh
の削除:- このシェルスクリプトは、Windows固有のエラー定数(
EINVAL
など)をGoのコードとして生成していました。 - コミットメッセージによると、「新しい"unix"エラーをWindowsの
syscall
パッケージに追加しなくなった」ため、このスクリプトは不要になりました。これは、Goのエラーハンドリング戦略が進化し、Windows固有のエラーマッピングの必要性が減少したことを示唆しています。
- このシェルスクリプトは、Windows固有のエラー定数(
-
ビルドプロセスの変更:
src/pkg/syscall/mkall.sh
は、Goのビルドプロセスで使用される主要なスクリプトであり、各OS/アーキテクチャ向けのシステムコールラッパーやエラーコードを生成する役割を担っています。このコミットでは、Windows向けのセクションが更新され、mksyscall_windows.pl
の代わりにmksyscall_windows.go
がビルド・実行されるように変更されています。src/pkg/syscall/mkall_windows.bat
は、Windows環境でmkall.sh
の役割を果たすバッチスクリプトとして新しく追加されました。これにより、WindowsユーザーはUnixシェル環境を必要とせずに、Goのツールチェーンのみでシステムコールラッパーを生成できるようになります。
コアとなるコードの変更箇所
このコミットにおける主要なコード変更は以下のファイルに集中しています。
src/pkg/syscall/mkall.sh
:windows_386
およびwindows_amd64
のケースで、mksyscall
変数の設定が削除され、mkerrors
変数の設定も削除されました。windows)
ケースにおいて、mksyscall_windows.go
をビルドし、それを使ってzsyscall_windows_*.go
ファイルを生成するコマンドが追加されました。mkerrors_windows.sh
の呼び出しが削除されました。
src/pkg/syscall/mkall_windows.bat
(新規追加):- Windows環境で
mksyscall_windows.go
をビルドし、生成された実行ファイルを使用してzsyscall_windows_*.go
ファイルを生成するためのバッチスクリプトです。
- Windows環境で
src/pkg/syscall/mkerrors_windows.sh
(削除):- Windows向けのエラー定数を生成していたシェルスクリプトが完全に削除されました。
src/pkg/syscall/mksyscall_windows.go
(新規追加):- Perlスクリプトの機能をGo言語で再実装したものです。
//sys
コメントを解析し、Goの関数定義、DLLのロード、プロシージャの取得、Syscall
関数の呼び出し、エラーハンドリングなどを含むGoコードを生成します。Param
、Rets
、Fn
などの構造体が定義され、システムコール関数のパラメータ、戻り値、および関数自体のメタデータを表現しています。srcTemplate
というGoのテンプレート文字列が含まれており、これが最終的なzsyscall_windows_*.go
ファイルの構造を定義しています。
src/pkg/syscall/mksyscall_windows.pl
(削除):- 従来のPerlによるシステムコール生成スクリプトが完全に削除されました。
src/pkg/syscall/zsyscall_windows_386.go
およびsrc/pkg/syscall/zsyscall_windows_amd64.go
:- ファイルのヘッダーコメントが更新され、生成元が
mksyscall_windows.pl
からmksyscall_windows.go
に変更されたことが示されています。
- ファイルのヘッダーコメントが更新され、生成元が
コアとなるコードの解説
mksyscall_windows.go
の主要なロジックは、ParseFiles
関数とGenerate
関数、そしてそれらをサポートするヘルパー関数群にあります。
-
ParseFiles
関数:- 引数として与えられたGoのソースファイル(例:
syscall_windows.go
,security_windows.go
)を読み込みます。 - 各行をスキャンし、
//sys
で始まるコメント行を探します。 //sys
コメント行が見つかると、その行をnewFn
関数に渡し、システムコール関数のメタデータ(関数名、パラメータ、戻り値、DLL名、DLL関数名、失敗条件など)を抽出してFn
構造体のインスタンスを作成します。- 抽出された
Fn
インスタンスは、Source
構造体のFuncs
スライスに追加されます。
- 引数として与えられたGoのソースファイル(例:
-
Fn
構造体:Name
: Goの関数名。Params
:Param
構造体のスライスで、入力パラメータを表現します。Rets
:Rets
構造体で、戻り値を表現します。dllname
,dllfuncname
: 呼び出すWindows DLLの名前とDLL内の関数名。PrintTrace
: システムコール呼び出し時にトレース情報を出力するかどうか。curTmpVarIdx
: 一時変数のインデックス管理用。
-
Param
構造体:Name
: パラメータ名。Type
: パラメータのGoの型。TmpVarCode()
:string
、bool
、[]byte
などのGoの型をWindows APIが期待する型(ポインタ、uint32
など)に変換するための一時変数を宣言するコードを生成します。例えば、Goのstring
はUTF16PtrFromString
やBytePtrFromString
を使って*uint16
や*byte
に変換されます。SyscallArgList()
:Syscall
関数に渡す引数リストを生成します。スライスはポインタと長さの2つの引数に展開されます。
-
Rets
構造体:Name
,Type
: 戻り値のGoの型と名前。ReturnsError
: 戻り値にerror
が含まれるか。FailCond
: Windows APIの戻り値が失敗とみなされる条件(例:failretval==-1
)。SetReturnValuesCode()
:Syscall
関数からの戻り値(r0
,r1
,e1
など)を受け取るコードを生成します。SetErrorCode()
:Syscall
関数が失敗した場合に、Windowsの「最後のエラー」(GetLastError
)をGoのerror
型に変換して設定するコードを生成します。
-
Generate
関数:text/template
パッケージを使用して、Source
構造体に含まれるFn
インスタンスのデータに基づいて最終的なGoのソースコードを生成します。srcTemplate
というテンプレート文字列には、dlls
、funcnames
、funcbody
、tmpvars
、syscall
、seterror
、printtrace
などのGoテンプレート定義が含まれており、これらが組み合わされて最終的なzsyscall_windows_*.go
ファイルが作成されます。- 特に
funcbody
テンプレートは、各システムコール関数のGoラッパーの本体を生成し、一時変数の準備、Syscall
関数の呼び出し、戻り値の設定、エラー処理、およびオプションのトレース出力を行います。
このGoプログラムは、Goのビルドシステムに深く統合されており、GoのソースコードからWindowsシステムコールラッパーを自動生成することで、GoのクロスコンパイルとWindows環境での開発をよりスムーズにしています。
関連リンク
- Go言語の
syscall
パッケージのドキュメント: https://pkg.go.dev/syscall - Go言語の
text/template
パッケージのドキュメント: https://pkg.go.dev/text/template - Go言語のコード生成に関する一般的な情報: https://go.dev/blog/generate
参考にした情報源リンク
- Go project commit: c07ca77432d0c6b7e75eb0eec83ecccea03d38b5 (GitHub)
- Web検索結果: "Go mksyscall_windows.pl mksyscall_windows.go purpose"
- Web検索結果: "Go mkerrors_windows.sh removal"
- Goのソースコード(
src/pkg/syscall/
ディレクトリ) - Goのコードレビューシステム (Gerrit) のCL 41060044: https://golang.org/cl/41060044