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

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

このコミットは、Go言語の標準ライブラリの一部である src/pkg/syscall/mksyscall_windows.pl スクリプトに対する変更を記録しています。このPerlスクリプトは、WindowsシステムコールをGo言語のコードとして自動生成するために使用されます。具体的には、Windows APIの関数定義を読み込み、それに対応するGoのsyscallパッケージ内の関数スタブや関連する定数、構造体などを生成する役割を担っています。これにより、GoプログラムからWindowsの低レベルなシステム機能にアクセスできるようになります。

コミット

commit 27cab90363159d5dbf9c6412778210f63dace7b5
Author: Alex Brainman <alex.brainman@gmail.com>
Date:   Fri Dec 9 11:12:03 2011 +1100

    syscall: allow for mksyscall_windows.pl to be used outside of syscall
    
    this change should have been part of fafcd328da73
    
    R=golang-dev, bsiegert
    CC=golang-dev
    https://golang.org/cl/5462045

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

https://github.com/golang/go/commit/27cab90363159d5dbf9c6412778210f63dace7b5

元コミット内容

このコミットは、以前のコミット fafcd328da73 の一部として含まれるべきだった変更を適用しています。元のコミットメッセージは直接提供されていませんが、このコミットのメッセージから「mksyscall_windows.plsyscall パッケージの外部で使用できるようにする」という目的が読み取れます。これは、コード生成スクリプトの汎用性を高め、syscallパッケージに限定されずに利用できるようにするための修正であると推測されます。

変更の背景

Go言語のsyscallパッケージは、オペレーティングシステム固有の低レベルな機能へのアクセスを提供します。Windowsの場合、これはWin32 APIの関数呼び出しをGoから行うことを意味します。これらの関数は非常に数が多く、手動でGoのバインディングを作成するのは非効率的です。そのため、mksyscall_windows.plのようなスクリプトが、Windows APIの定義からGoのコードを自動生成するために開発されました。

このコミットの背景には、mksyscall_windows.plスクリプトが、その設計上、syscallパッケージの内部でのみ使用されることを前提としていたという問題があります。しかし、Goのツールチェインや他のコンポーネントが、syscallパッケージの外部でこのスクリプトを利用する必要が生じた可能性があります。例えば、特定のWindows API関数に対するカスタムなバインディングを生成したい場合や、テスト目的でsyscallパッケージの外部でコード生成ロジックを再利用したい場合などが考えられます。

元のコミット fafcd328da73 がこの汎用性の問題を完全に解決できなかったため、このコミット 27cab90363159d5dbf9c6412778210f63dace7b5 がその修正として導入されました。これは、コード生成スクリプトがより柔軟に、かつ再利用可能な形で機能するようにするための重要な改善です。

前提知識の解説

Go言語の syscall パッケージ

Go言語のsyscallパッケージは、オペレーティングシステム(OS)の低レベルなプリミティブへのアクセスを提供します。これには、ファイル操作、プロセス管理、ネットワーク通信、メモリ管理など、OSが提供する基本的な機能が含まれます。GoプログラムがOSと直接対話する必要がある場合(例えば、特定のシステムコールを呼び出す場合や、OS固有の構造体や定数を使用する場合)にこのパッケージが利用されます。

Windows API (Win32 API)

Windows APIは、Microsoft Windowsオペレーティングシステムが提供するアプリケーションプログラミングインターフェースの集合体です。これには、グラフィカルユーザーインターフェース(GUI)、ファイルシステム、ネットワーク、デバイス管理など、Windows上で動作するアプリケーションを開発するために必要な数千もの関数、構造体、定数が含まれます。Go言語からWindowsの機能を利用する場合、このWin32 APIを呼び出す必要があります。

mksyscall_windows.pl スクリプト

mksyscall_windows.plは、Go言語のソースコードツリー内にあるPerlスクリプトです。このスクリプトの主な目的は、Windows APIの関数定義を解析し、それに対応するGo言語のsyscallパッケージ内の関数スタブ(GoからWindows APIを呼び出すためのラッパー関数)を自動生成することです。これにより、開発者が手動で膨大な数のWindows API関数のGoバインディングを作成する手間を省き、開発効率を向上させます。このスクリプトは、Goのビルドプロセスの一部として実行されることがあります。

コード生成 (Code Generation)

コード生成とは、プログラムによって別のプログラムのソースコードを自動的に生成するプロセスです。Go言語のプロジェクトでは、特に異なる言語(C/C++など)で書かれたライブラリやOSのAPIと連携する場合に、このコード生成が頻繁に利用されます。mksyscall_windows.plスクリプトは、まさにこのコード生成の典型的な例であり、Windows APIの定義からGoのコードを生成することで、GoとWindowsの間のインターフェースを自動的に構築します。

技術的詳細

このコミットの技術的な核心は、mksyscall_windows.plスクリプトが生成するGoコード内で、Errno関数を呼び出す際の修飾子を動的に制御できるようにした点にあります。

以前のコードでは、エラー処理のために生成されるGoコードは常にErrno($reg)という形式でErrno関数を呼び出していました。これは、mksyscall_windows.plスクリプトがsyscallパッケージの内部でのみ実行され、生成されるコードもsyscallパッケージ内に配置されることを前提としていました。この場合、Errno関数は同じパッケージ内にあるため、パッケージ名を修飾する必要はありません。

しかし、mksyscall_windows.plスクリプトがsyscallパッケージの外部で実行され、生成されたコードが別のパッケージに配置される場合、Errno関数を呼び出す際には、その関数が属するパッケージ名を明示的に指定する必要があります。例えば、syscallパッケージのErrno関数を呼び出すには、syscall.Errnoと記述する必要があります。

このコミットでは、Perlスクリプトの内部で${syscalldot}という変数を導入し、この変数がsyscall.という文字列を持つか、あるいは空文字列を持つかを制御できるようにしました。これにより、生成されるGoコードがsyscall.Errno($reg)となるか、あるいは単にErrno($reg)となるかを、スクリプトの実行コンテキストに応じて切り替えることが可能になります。

具体的には、mksyscall_windows.plスクリプトがsyscallパッケージの外部で実行される場合、${syscalldot}syscall.に設定され、生成されるコードはsyscall.Errno($reg)となります。これにより、生成されたコードがsyscallパッケージの外部に配置されても、Errno関数を正しく参照できるようになります。

この変更は、Goのビルドシステムやツールチェインが、syscallパッケージのコード生成ロジックをより柔軟に利用できるようにするための、小さなしかし重要な修正です。

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

--- a/src/pkg/syscall/mksyscall_windows.pl
+++ b/src/pkg/syscall/mksyscall_windows.pl
@@ -263,7 +263,7 @@ while(<>) {
 		} elsif($rettype eq "error") {
 			# Set $reg to "error" only if returned value indicate failure
 			$body .= "\tif $reg != 0 {\\n";
-			$body .= "\t\t$name = Errno($reg)\\n";
+			$body .= "\t\t$name = ${syscalldot}Errno($reg)\\n";
 			$body .= "\t}\\n";
 		} else {
 			$body .= "\t$name = $rettype($reg)\\n";

コアとなるコードの解説

上記のdiffは、mksyscall_windows.plスクリプト内のPerlコードの変更を示しています。

変更前の行: $body .= "\t\t$name = Errno($reg)\\n";

変更後の行: $body .= "\t\t$name = ${syscalldot}Errno($reg)\\n";

この変更は、生成されるGoコードの文字列を構築している部分にあります。

  • $body: これは、最終的にGoのソースコードとして出力される文字列を構築するための変数です。
  • $name: 生成されるGoの変数名(例えば、戻り値を受け取る変数)。
  • Errno($reg): Windows API呼び出しがエラーを返した場合に、そのエラーコード($reg)をGoのerror型に変換するための関数呼び出しです。

変更の核心は、Errno($reg)の前に${syscalldot}というPerlの変数が追加されたことです。

  • ${syscalldot}の役割: この変数は、mksyscall_windows.plスクリプトの実行コンテキストに応じて、"syscall."という文字列、または空文字列("")のいずれかの値を持つように設計されています。
    • スクリプトがsyscallパッケージの内部で実行され、生成されるGoコードもsyscallパッケージ内に配置される場合、${syscalldot}は空文字列になります。この場合、生成されるGoコードはErrno($reg)となり、Errno関数は同じパッケージ内にあるため、パッケージ名を修飾する必要はありません。
    • スクリプトがsyscallパッケージの外部で実行され、生成されるGoコードが別のパッケージに配置される場合、${syscalldot}"syscall."という文字列になります。この場合、生成されるGoコードはsyscall.Errno($reg)となり、Errno関数がsyscallパッケージに属していることを明示的に示します。

この修正により、mksyscall_windows.plスクリプトは、生成されるGoコードがどのパッケージに属するかに関わらず、Errno関数への参照を正しく生成できるようになりました。これにより、スクリプトの再利用性が向上し、Goのビルドシステムがより柔軟にWindowsシステムコール関連のコードを生成できるようになります。

関連リンク

参考にした情報源リンク