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

[インデックス 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点があります。

  1. Perlへの依存性排除: 従来のWindowsシステムコール生成にはPerlスクリプト(mksyscall_windows.pl)が使用されていました。しかし、コミットメッセージにあるように「多くのWindowsユーザーはPerlをインストールしていない」という問題がありました。Goのツールチェーン自体でシステムコール生成を完結させることで、Go開発者がWindows環境でGoをビルド・開発する際の外部依存性を減らし、セットアップの複雑さを軽減することが目的です。
  2. ビルドプロセスの簡素化: 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.plmksyscall_windows.go)によって自動化されます。
  • コード生成: ソフトウェア開発において、特定のパターンに従うコードや、異なるプラットフォーム向けのコードを自動的に生成する手法です。これにより、手動での記述ミスを減らし、開発効率を向上させることができます。Go言語では、go generateコマンドや、ビルド時に実行されるスクリプトによってコード生成が行われることがあります。
  • Perlスクリプト: Perlは、テキスト処理やシステム管理タスクに広く使用されるスクリプト言語です。過去には、Goプロジェクトを含む多くのオープンソースプロジェクトで、ビルドスクリプトやコード生成スクリプトとして利用されていました。
  • Windows API: Windowsオペレーティングシステムが提供するアプリケーションプログラミングインターフェース(API)の集合体です。GoプログラムがWindows固有の機能(レジストリ操作、GUI、特定のデバイスアクセスなど)を利用する際には、このAPIを呼び出す必要があります。

技術的詳細

このコミットの技術的な核心は、Windowsシステムコールラッパーの生成方法をPerlからGoへ移行した点にあります。

  1. mksyscall_windows.plの役割:

    • このPerlスクリプトは、syscall_windows.goなどのファイルに記述された特殊なコメント(//sysで始まる行)を解析していました。
    • これらのコメントは、Windows API関数のGo言語でのプロトタイプ(関数名、引数、戻り値の型など)を定義していました。
    • スクリプトは、これらのプロトタイプを読み取り、GoのsyscallパッケージがWindows APIを呼び出すために必要な低レベルのGoコード(zsyscall_windows_386.gozsyscall_windows_amd64.goなど)を生成していました。これには、DLLのロード、プロシージャアドレスの取得、Syscall関数(Syscall, Syscall6, Syscall9など)の呼び出しなどが含まれます。
    • 特に、文字列引数の変換(Goの文字列からWindows APIが期待するUTF-16またはANSI文字列への変換)や、エラーハンドリング(WindowsのGetLastErrorに基づくエラーの取得)のロジックも生成していました。
  2. 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])。
  3. mkerrors_windows.shの削除:

    • このシェルスクリプトは、Windows固有のエラー定数(EINVALなど)をGoのコードとして生成していました。
    • コミットメッセージによると、「新しい"unix"エラーをWindowsのsyscallパッケージに追加しなくなった」ため、このスクリプトは不要になりました。これは、Goのエラーハンドリング戦略が進化し、Windows固有のエラーマッピングの必要性が減少したことを示唆しています。
  4. ビルドプロセスの変更:

    • 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ファイルを生成するためのバッチスクリプトです。
  • src/pkg/syscall/mkerrors_windows.sh (削除):
    • Windows向けのエラー定数を生成していたシェルスクリプトが完全に削除されました。
  • src/pkg/syscall/mksyscall_windows.go (新規追加):
    • Perlスクリプトの機能をGo言語で再実装したものです。
    • //sysコメントを解析し、Goの関数定義、DLLのロード、プロシージャの取得、Syscall関数の呼び出し、エラーハンドリングなどを含むGoコードを生成します。
    • ParamRetsFnなどの構造体が定義され、システムコール関数のパラメータ、戻り値、および関数自体のメタデータを表現しています。
    • 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スライスに追加されます。
  • Fn構造体:

    • Name: Goの関数名。
    • Params: Param構造体のスライスで、入力パラメータを表現します。
    • Rets: Rets構造体で、戻り値を表現します。
    • dllname, dllfuncname: 呼び出すWindows DLLの名前とDLL内の関数名。
    • PrintTrace: システムコール呼び出し時にトレース情報を出力するかどうか。
    • curTmpVarIdx: 一時変数のインデックス管理用。
  • Param構造体:

    • Name: パラメータ名。
    • Type: パラメータのGoの型。
    • TmpVarCode(): stringbool[]byteなどのGoの型をWindows APIが期待する型(ポインタ、uint32など)に変換するための一時変数を宣言するコードを生成します。例えば、GoのstringUTF16PtrFromStringBytePtrFromStringを使って*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というテンプレート文字列には、dllsfuncnamesfuncbodytmpvarssyscallseterrorprinttraceなどのGoテンプレート定義が含まれており、これらが組み合わされて最終的なzsyscall_windows_*.goファイルが作成されます。
    • 特にfuncbodyテンプレートは、各システムコール関数のGoラッパーの本体を生成し、一時変数の準備、Syscall関数の呼び出し、戻り値の設定、エラー処理、およびオプションのトレース出力を行います。

このGoプログラムは、Goのビルドシステムに深く統合されており、GoのソースコードからWindowsシステムコールラッパーを自動生成することで、GoのクロスコンパイルとWindows環境での開発をよりスムーズにしています。

関連リンク

参考にした情報源リンク

  • 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