[インデックス 19410] ファイルの概要
このコミットは、Go言語のビルドシステムがGoogle Native Client (NaCl) 環境で適切に動作するようにするための変更を導入しています。具体的には、NaCl環境でのテスト実行に必要な入力ファイルを埋め込んだsyscall
パッケージのバリアントをビルドするための新しいスクリプトnacl.bash
を追加し、NaCl環境と互換性のない一部のテスト(主にos/exec
を使用するもの)を無効にしています。
コミット
- コミットハッシュ:
0c2a727477908dc0adbfcb05baac34b4ba4fa309
- Author: Russ Cox rsc@golang.org
- Date: Tue May 20 12:10:19 2014 -0400
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/0c2a727477908dc0adbfcb05baac34b4ba4fa309
元コミット内容
build: make nacl pass
Add nacl.bash, the NaCl version of all.bash.
It's a separate script because it builds a variant of package syscall
with a large zip file embedded in it, containing all the input files
needed for tests.
Disable various tests new since the last round, mostly the ones using os/exec.
Fixes #7945.
LGTM=dave
R=golang-codereviews, remyoudompheng, dave, bradfitz
CC=golang-codereviews
https://golang.org/cl/100590044
変更の背景
この変更の主な背景は、Go言語がGoogle Native Client (NaCl) 環境で動作し、そのテストスイートがNaCl上でパスするようにすることです。
Google Native Client (NaCl) とは? Google Native Client (NaCl) は、ウェブブラウザ内でネイティブコード(C/C++など)を安全かつポータブルに実行するためのサンドボックス技術です。これにより、ウェブアプリケーションはネイティブのパフォーマンスを活用しつつ、セキュリティ上のリスクを最小限に抑えることができます。NaClは、特定のCPUアーキテクチャ(x86-32, x86-64, ARM)とオペレーティングシステム(Windows, macOS, Linux, Chrome OS)に依存しないバイナリ形式(Portable Native Client, PNaCl)を提供し、一度コンパイルすればどこでも実行できることを目指していました。
Go言語は、その設計思想としてクロスプラットフォーム対応を重視しており、様々な環境での動作をサポートしています。NaClもその一つであり、Goプログラムをウェブブラウザ内で実行可能にすることは、Goの適用範囲を広げる上で重要な目標でした。
しかし、NaCl環境は通常のオペレーティングシステム環境とは異なる制約を持っています。例えば、ファイルシステムへのアクセスやプロセス間通信、外部プログラムの実行など、一部のシステムコールが制限されるか、異なる方法で提供されます。Goの標準ライブラリ、特にテストスイートは、これらのシステム機能に依存している部分が多く、そのままではNaCl上で動作しませんでした。
このコミットは、GoのテストスイートをNaCl環境で実行可能にするための具体的なステップとして、以下の課題に対処しています。
- テストデータの管理: 多くのテストは、外部ファイルからデータを読み込んだり、一時ファイルを作成したりします。NaClのサンドボックス環境では、通常のファイルシステムアクセスが制限されるため、これらのテストデータをどのように提供するかが課題でした。
- システムコールと互換性:
os/exec
パッケージのように、外部プロセスを起動する機能はNaCl環境では直接サポートされません。このような機能に依存するテストは、NaClでは実行できないため、適切に処理する必要がありました。 - ビルドプロセスの適応: NaCl向けのGoバイナリをビルドするためには、通常のビルドプロセスとは異なる手順や設定が必要になります。
このコミットは、これらの課題に対する解決策を提供し、GoのNaClサポートを強化することを目的としています。
前提知識の解説
このコミットを理解するためには、以下の概念について基本的な知識があると役立ちます。
-
Go言語のビルドシステム:
all.bash
: Goプロジェクトのルートディレクトリにあるシェルスクリプトで、Goの標準ライブラリ、ツール、およびテストをビルド・実行するための主要なスクリプトです。これはGoのCI/CDパイプラインや開発者がローカルでGo環境をセットアップする際に広く使用されます。- クロスコンパイル: Goは、あるプラットフォーム(例: Linux x86-64)で別のプラットフォーム(例: Windows ARM)向けのバイナリを生成するクロスコンパイルを強力にサポートしています。これは、
GOOS
(ターゲットOS)やGOARCH
(ターゲットアーキテクチャ)といった環境変数を設定することで実現されます。 - パッケージ: Goのコードはパッケージに分割されており、各パッケージは特定の機能を提供します。
syscall
パッケージは、オペレーティングシステムのシステムコールへの低レベルなインターフェースを提供します。os/exec
パッケージは、外部コマンドの実行を可能にします。
-
Google Native Client (NaCl):
- サンドボックス: NaClは、実行されるコードを厳しく制限された環境(サンドボックス)内で動作させます。これにより、悪意のあるコードがシステムに損害を与えたり、機密情報にアクセスしたりするのを防ぎます。
- PNaCl (Portable Native Client): NaClの進化版で、特定のCPUアーキテクチャに依存しない中間表現(LLVM IRベース)を使用します。これにより、開発者は一度PNaClバイナリをコンパイルすれば、Chromeブラウザが実行時にターゲットアーキテクチャに最適化されたネイティブコードに変換して実行します。
- 制限されたI/O: NaClサンドボックス内では、通常のファイルシステムアクセスやネットワークアクセスが制限されます。ファイルアクセスは、通常、事前にパッケージ化されたリソース(例えば、アプリケーションの
.nmf
マニフェストファイルに記述されたリソース)や、ブラウザのAPIを介して行われます。
-
テストとテストデータ:
- Goのテストは、通常、
_test.go
ファイルに記述され、go test
コマンドで実行されます。 - テストの中には、外部ファイル(設定ファイル、入力データ、期待される出力など)を必要とするものがあります。これらのファイルは「テストデータ」と呼ばれます。
- Goのテストは、通常、
-
埋め込みリソース:
- Goのバイナリに任意のファイルを埋め込む一般的な方法は、Goのコードとしてバイト配列に変換し、それをプログラム内で読み込むことです。これにより、外部ファイルへの依存をなくし、単一のバイナリとして配布できるようになります。このコミットでは、特にテストデータをzipファイルとして埋め込むアプローチが取られています。
これらの知識を前提として、コミットの技術的詳細を掘り下げていきます。
技術的詳細
このコミットは、GoのNaClビルドとテスト実行を可能にするために、いくつかの重要な技術的変更を導入しています。
-
nacl.bash
の導入:src/all.bash
のNaCl版としてsrc/nacltest.bash
が追加されました。これは、NaCl環境に特化したビルドとテストのロジックを含んでいます。- 通常の
all.bash
がGoの標準的なビルドとテストを行うのに対し、nacltest.bash
はNaClの制約と要件に合わせて調整されています。
-
テストデータの埋め込みと
mkzip.go
:- NaCl環境では、テストが外部ファイルにアクセスすることが困難です。この問題を解決するため、テストに必要なすべての入力ファイルを一つの大きなzipファイルにまとめ、それをGoのバイナリに埋め込むというアプローチが取られました。
misc/nacl/mkzip.go
という新しいGoプログラムが追加されました。このツールは、特定のプロトコルファイル(testzip.proto
)で記述されたファイルツリー構造に基づいて、zipファイルを作成します。mkzip.go
は、src.proto
という入力ファイルとout.zip
という出力ファイルを引数にとります。src.proto
は、どのファイルをzipに含めるか、そしてそれらのファイルがzip内でどのようなパスを持つかを定義します。- さらに、
mkzip.go
は-p
フラグを使用することで、生成されたzipファイルの内容をGoのソースコード(バイト配列として)として出力する機能を持っています。これにより、zipファイルがGoのバイナリに直接埋め込まれることが可能になります。
-
testzip.proto
の役割:misc/nacl/testzip.proto
は、mkzip.go
がzipファイルを作成する際に参照する「プロトタイプ」ファイルです。これは、Plan 9のmkfs
プロトタイプファイル形式にインスパイアされています。- このファイルは、タブによるインデントでディレクトリ構造を表現し、各行にはファイル名とオプションの属性(例:
src=foo
で元のファイルのパスを指定)が記述されます。 - このプロトファイルには、
etc/mime.types
やusr/bin
、Goの標準ライブラリのテストデータなど、Goのテストスイートが依存する様々なファイルが含まれています。特にmime.types
は非常に大きなファイルであり、これが埋め込まれることで、syscall
パッケージのサイズが大きくなることが示唆されています。
-
syscall
パッケージのバリアント:nacltest.bash
は、mkzip.go
を使用して生成されたzipファイルをsyscall
パッケージに埋め込みます。これにより、NaCl環境で実行されるGoプログラムは、外部ファイルシステムにアクセスすることなく、必要なテストデータにアクセスできるようになります。- この埋め込みは、
syscall
パッケージの特定のビルドタグ(おそらくNaCl固有のタグ)が有効な場合にのみ行われるように設計されていると考えられます。
-
os/exec
を使用するテストの無効化:- NaClのサンドボックスモデルでは、外部プロセスの実行(
os/exec
パッケージが提供する機能)はセキュリティ上の理由から厳しく制限されるか、完全に禁止されます。 - このコミットでは、
os/exec
に依存するテストがNaCl環境で実行されないように、それらのテストを無効化する変更が含まれています。これは、テストファイルの変更(例:src/pkg/os/exec/exec_test.go
)や、nacltest.bash
スクリプト内での条件付き実行によって実現されています。
- NaClのサンドボックスモデルでは、外部プロセスの実行(
これらの変更により、GoのビルドシステムはNaClの特殊な環境に対応し、テストがサンドボックス内で必要なリソースにアクセスできるようになり、同時にNaClの制約に違反するテストはスキップされるようになります。
コアとなるコードの変更箇所
このコミットにおける主要なコード変更は以下のファイルに集中しています。
-
misc/nacl/mkzip.go
:- 新規追加されたファイル。
testzip.proto
で定義されたファイル構造に基づいてzipファイルを作成するGoプログラム。-p
フラグを使用すると、zipの内容をGoのバイト配列として出力し、Goのソースコードに埋め込める形式にする機能を持つ。
-
misc/nacl/testzip.proto
:- 新規追加されたファイル。
mkzip.go
がzipファイルを作成する際に参照するプロトタイプファイル。- Goのテストに必要な様々なファイル(例:
mime.types
,group
,hosts
など)のパスと、それらをzip内でどのように配置するかを定義。
-
src/nacltest.bash
:- 新規追加されたファイル。
all.bash
のNaCl版であり、NaCl環境でのGoのビルドとテスト実行をオーケストレーションするシェルスクリプト。mkzip.go
を呼び出してテストデータを埋め込んだsyscall
パッケージをビルドするロジックが含まれる。
-
src/all.bash
:- 既存のファイルへの変更。
nacltest.bash
の呼び出しや、NaCl関連のビルド設定が追加された可能性がある。
-
各種テストファイル (
src/cmd/..._test.go
,src/pkg/..._test.go
,test/...go
):- 多数の既存テストファイルに修正が加えられています。
- 主に、
os/exec
パッケージを使用するテストや、NaCl環境で問題を引き起こす可能性のあるテストが、NaClビルドタグが有効な場合にスキップされるように変更されています。これは、if runtime.GOOS == "nacl"
のような条件分岐や、ビルドタグ(例:// +build !nacl
)の追加によって実現されます。 - 例:
src/pkg/os/exec/exec_test.go
、src/pkg/net/http/cgi/matryoshka_test.go
など。
-
misc/nacl/testdata/
以下のファイル:mime.types
,group
,hosts
,empty
,bin/placeholder
などが新規追加されています。- これらは
testzip.proto
で参照され、最終的に埋め込まれるテストデータの一部となります。特にmime.types
は非常に大きなファイルです。
コアとなるコードの解説
このコミットの核心は、NaCl環境の制約を克服し、GoのテストスイートをNaCl上で実行可能にするための巧妙なデータ埋め込みとビルドプロセスの調整にあります。
mkzip.go
とtestzip.proto
によるテストデータの埋め込み
mkzip.go
は、Goのテストが実行時に必要とする外部ファイルを、単一のGoバイナリに埋め込むための重要なツールです。
-
testzip.proto
の解析:mkzip.go
は、testzip.proto
ファイルを読み込み、その内容を解析します。testzip.proto
は、以下のような形式でファイルツリーを記述します。etc src=/etc mime.types src=../misc/nacl/testdata/mime.types resolv.conf src=../misc/nacl/testdata/empty usr src=../misc/nacl/testdata bin
- 行頭のタブの数でディレクトリの階層構造を示します。
- 最初のフィールドは、zipファイル内のパス名です。
src=...
属性は、実際のファイルデータがどこから取得されるかを指定します。これが指定されない場合、同名のファイルが現在のソースディレクトリからコピーされます。*
や+
は、ディレクトリ内のすべてのファイルや、サブディレクトリを含めたすべてのファイルを再帰的に追加することを示します。
-
Zipファイルの生成:
mkzip.go
は、解析した情報に基づいてarchive/zip
パッケージを使用してzipファイルを作成します。各エントリは、testzip.proto
で指定されたパスとソースからデータを取得して追加されます。 -
Goソースコードへの変換(
-p
フラグ): 最も重要な機能の一つは、-p
フラグが指定された場合です。この場合、mkzip.go
はzipファイルの内容を直接ファイルに書き込むのではなく、Goのソースコードとして標準出力に出力します。具体的には、zipファイルのバイナリデータを16進数エスケープシーケンス(\xNN
)の文字列リテラルに変換し、それをinit()
関数内でunzip
関数に渡す形式で出力します。package somepackage func init() { unzip("\x50\x4b\x03\x04\x14\x00\x00\x00...") // zipファイルのバイナリデータ }
この生成されたGoコードは、Goのビルドプロセス中に
syscall
パッケージ(または関連するパッケージ)にコンパイルされ、結果としてzipファイルの内容がGoのバイナリに埋め込まれます。
nacltest.bash
によるビルドオーケストレーション
nacltest.bash
は、NaCl環境向けのGoのビルドとテストを調整するスクリプトです。
-
mkzip.go
の実行: このスクリプトは、mkzip.go
を呼び出し、testzip.proto
を読み込ませて、テストデータを埋め込んだGoソースファイルを生成させます。この生成されたソースファイルは、Goのビルドシステムによってsyscall
パッケージの一部としてコンパイルされます。 -
syscall
パッケージの特殊なビルド: NaCl環境では、syscall
パッケージが通常のシステムコールではなく、NaClのnewlib
やglibc
インターフェースを介して動作する必要があります。また、このコミットでは、前述の埋め込まれたテストデータにアクセスするためのロジックもsyscall
パッケージ内に含まれるようになります。これにより、テストは実行時に外部ファイルシステムに依存することなく、必要なデータにアクセスできます。 -
テストの選択的無効化:
nacltest.bash
は、NaCl環境で実行できないテスト(特にos/exec
を使用するもの)を特定し、それらをスキップするようにGoのテストコマンドを調整します。これは、テストファイル内のビルドタグ(例:// +build !nacl
)や、テスト実行時の環境変数設定によって制御されます。
テストファイルの変更
多くのテストファイルでは、以下のような変更が加えられています。
// Some test code
if runtime.GOOS == "nacl" {
t.Skip("skipping test on nacl")
}
// Original test logic
または、ファイルの先頭にビルドタグが追加されます。
// +build !nacl
package somepackage_test
// ...
これにより、nacl
ビルドタグが有効な場合(つまりNaCl向けにビルドされる場合)、特定のテストファイル全体またはテスト関数がコンパイルから除外されるか、実行時にスキップされるようになります。これは、NaClのサンドボックスモデルではサポートされない機能(例: 外部プロセスの起動、特定のネットワーク操作、ファイルシステム操作)に依存するテストを適切に処理するために不可欠です。
これらの変更の組み合わせにより、GoはNaCl環境で動作し、そのテストスイートもNaClの制約内で実行可能になります。特に、テストデータの埋め込みは、NaClの制限されたファイルシステムアクセスに対する実用的な解決策を提供しています。
関連リンク
-
Go Issue #7945: https://github.com/golang/go/issues/7945
- このコミットが修正したGoのIssueです。通常、Issueには問題の詳細な説明や議論が含まれています。
-
Go Code Review (CL) 100590044: https://golang.org/cl/100590044
- このコミットに対応するGoのコードレビューページです。ここには、コミットがマージされるまでの議論、レビューコメント、変更の差分などが詳細に記録されています。
参考にした情報源リンク
- Google Native Client (NaCl) 公式ドキュメント:
- https://developer.chrome.com/native-client/ (現在はアーカイブされており、PNaClは非推奨となっていますが、当時の技術背景を理解する上で参考になります。)
- Go言語の公式ドキュメント:
- Goのビルドシステム、パッケージ、テストに関する一般的な情報。
- Go言語のソースコード:
src/all.bash
やsrc/make.bash
など、Goのビルドプロセスに関連するスクリプト。os/exec
パッケージのドキュメント。
- Plan 9
mkfs
:testzip.proto
の形式のインスピレーション元。- https://9p.io/sys/man/4/mkfs.html (Plan 9のドキュメント)
(注: 上記の参考情報源リンクは、当時の技術背景を理解するための一般的な情報源であり、このコミットが直接参照したものではない可能性があります。特にNaClは現在では非推奨の技術ですが、コミット当時の状況を説明するために言及しています。)# [インデックス 19410] ファイルの概要
このコミットは、Go言語のビルドシステムがGoogle Native Client (NaCl) 環境で適切に動作するようにするための変更を導入しています。具体的には、NaCl環境でのテスト実行に必要な入力ファイルを埋め込んだsyscall
パッケージのバリアントをビルドするための新しいスクリプトnacl.bash
を追加し、NaCl環境と互換性のない一部のテスト(主にos/exec
を使用するもの)を無効にしています。
コミット
- コミットハッシュ:
0c2a727477908dc0adbfcb05baac34b4ba4fa309
- Author: Russ Cox rsc@golang.org
- Date: Tue May 20 12:10:19 2014 -0400
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/0c2a727477908dc0adbfcb05baac34b4ba4fa309
元コミット内容
build: make nacl pass
Add nacl.bash, the NaCl version of all.bash.
It's a separate script because it builds a variant of package syscall
with a large zip file embedded in it, containing all the input files
needed for tests.
Disable various tests new since the last round, mostly the ones using os/exec.
Fixes #7945.
LGTM=dave
R=golang-codereviews, remyoudompheng, dave, bradfitz
CC=golang-codereviews
https://golang.org/cl/100590044
変更の背景
この変更の主な背景は、Go言語がGoogle Native Client (NaCl) 環境で動作し、そのテストスイートがNaCl上でパスするようにすることです。
Google Native Client (NaCl) とは? Google Native Client (NaCl) は、ウェブブラウザ内でネイティブコード(C/C++など)を安全かつポータブルに実行するためのサンドボックス技術です。これにより、ウェブアプリケーションはネイティブのパフォーマンスを活用しつつ、セキュリティ上のリスクを最小限に抑えることができます。NaClは、特定のCPUアーキテクチャ(x86-32, x86-64, ARM)とオペレーティングシステム(Windows, macOS, Linux, Chrome OS)に依存しないバイナリ形式(Portable Native Client, PNaCl)を提供し、一度コンパイルすればどこでも実行できることを目指していました。
Go言語は、その設計思想としてクロスプラットフォーム対応を重視しており、様々な環境での動作をサポートしています。NaClもその一つであり、Goプログラムをウェブブラウザ内で実行可能にすることは、Goの適用範囲を広げる上で重要な目標でした。
しかし、NaCl環境は通常のオペレーティングシステム環境とは異なる制約を持っています。例えば、ファイルシステムへのアクセスやプロセス間通信、外部プログラムの実行など、一部のシステムコールが制限されるか、異なる方法で提供されます。Goの標準ライブラリ、特にテストスイートは、これらのシステム機能に依存している部分が多く、そのままではNaCl上で動作しませんでした。
このコミットは、GoのテストスイートをNaCl環境で実行可能にするための具体的なステップとして、以下の課題に対処しています。
- テストデータの管理: 多くのテストは、外部ファイルからデータを読み込んだり、一時ファイルを作成したりします。NaClのサンドボックス環境では、通常のファイルシステムアクセスが制限されるため、これらのテストデータをどのように提供するかが課題でした。
- システムコールと互換性:
os/exec
パッケージのように、外部プロセスを起動する機能はNaCl環境では直接サポートされません。このような機能に依存するテストは、NaClでは実行できないため、適切に処理する必要がありました。 - ビルドプロセスの適応: NaCl向けのGoバイナリをビルドするためには、通常のビルドプロセスとは異なる手順や設定が必要になります。
このコミットは、これらの課題に対する解決策を提供し、GoのNaClサポートを強化することを目的としています。
前提知識の解説
このコミットを理解するためには、以下の概念について基本的な知識があると役立ちます。
-
Go言語のビルドシステム:
all.bash
: Goプロジェクトのルートディレクトリにあるシェルスクリプトで、Goの標準ライブラリ、ツール、およびテストをビルド・実行するための主要なスクリプトです。これはGoのCI/CDパイプラインや開発者がローカルでGo環境をセットアップする際に広く使用されます。- クロスコンパイル: Goは、あるプラットフォーム(例: Linux x86-64)で別のプラットフォーム(例: Windows ARM)向けのバイナリを生成するクロスコンパイルを強力にサポートしています。これは、
GOOS
(ターゲットOS)やGOARCH
(ターゲットアーキテクチャ)といった環境変数を設定することで実現されます。 - パッケージ: Goのコードはパッケージに分割されており、各パッケージは特定の機能を提供します。
syscall
パッケージは、オペレーティングシステムのシステムコールへの低レベルなインターフェースを提供します。os/exec
パッケージは、外部コマンドの実行を可能にします。
-
Google Native Client (NaCl):
- サンドボックス: NaClは、実行されるコードを厳しく制限された環境(サンドボックス)内で動作させます。これにより、悪意のあるコードがシステムに損害を与えたり、機密情報にアクセスしたりするのを防ぎます。
- PNaCl (Portable Native Client): NaClの進化版で、特定のCPUアーキテクチャに依存しない中間表現(LLVM IRベース)を使用します。これにより、開発者は一度PNaClバイナリをコンパイルすれば、Chromeブラウザが実行時にターゲットアーキテクチャに最適化されたネイティブコードに変換して実行します。
- 制限されたI/O: NaClサンドボックス内では、通常のファイルシステムアクセスやネットワークアクセスが制限されます。ファイルアクセスは、通常、事前にパッケージ化されたリソース(例えば、アプリケーションの
.nmf
マニフェストファイルに記述されたリソース)や、ブラウザのAPIを介して行われます。
-
テストとテストデータ:
- Goのテストは、通常、
_test.go
ファイルに記述され、go test
コマンドで実行されます。 - テストの中には、外部ファイル(設定ファイル、入力データ、期待される出力など)を必要とするものがあります。これらのファイルは「テストデータ」と呼ばれます。
- Goのテストは、通常、
-
埋め込みリソース:
- Goのバイナリに任意のファイルを埋め込む一般的な方法は、Goのコードとしてバイト配列に変換し、それをプログラム内で読み込むことです。これにより、外部ファイルへの依存をなくし、単一のバイナリとして配布できるようになります。このコミットでは、特にテストデータをzipファイルとして埋め込むアプローチが取られています。
これらの知識を前提として、コミットの技術的詳細を掘り下げていきます。
技術的詳細
このコミットは、GoのNaClビルドとテスト実行を可能にするために、いくつかの重要な技術的変更を導入しています。
-
nacl.bash
の導入:src/all.bash
のNaCl版としてsrc/nacltest.bash
が追加されました。これは、NaCl環境に特化したビルドとテストのロジックを含んでいます。- 通常の
all.bash
がGoの標準的なビルドとテストを行うのに対し、nacltest.bash
はNaClの制約と要件に合わせて調整されています。
-
テストデータの埋め込みと
mkzip.go
:- NaCl環境では、テストが外部ファイルにアクセスすることが困難です。この問題を解決するため、テストに必要なすべての入力ファイルを一つの大きなzipファイルにまとめ、それをGoのバイナリに埋め込むというアプローチが取られました。
misc/nacl/mkzip.go
という新しいGoプログラムが追加されました。このツールは、特定のプロトコルファイル(testzip.proto
)で記述されたファイルツリー構造に基づいて、zipファイルを作成します。mkzip.go
は、src.proto
という入力ファイルとout.zip
という出力ファイルを引数にとります。src.proto
は、どのファイルをzipに含めるか、そしてそれらのファイルがzip内でどのようなパスを持つかを定義します。- さらに、
mkzip.go
は-p
フラグを使用することで、生成されたzipファイルの内容をGoのソースコード(バイト配列として)として出力する機能を持っています。これにより、zipファイルがGoのバイナリに直接埋め込まれることが可能になります。
-
testzip.proto
の役割:misc/nacl/testzip.proto
は、mkzip.go
がzipファイルを作成する際に参照する「プロトタイプ」ファイルです。これは、Plan 9のmkfs
プロトタイプファイル形式にインスパイアされています。- このファイルは、タブによるインデントでディレクトリ構造を表現し、各行にはファイル名とオプションの属性(例:
src=foo
で元のファイルのパスを指定)が記述されます。 - このプロトファイルには、
etc/mime.types
やusr/bin
、Goの標準ライブラリのテストデータなど、Goのテストスイートが依存する様々なファイルが含まれています。特にmime.types
は非常に大きなファイルであり、これが埋め込まれることで、syscall
パッケージのサイズが大きくなることが示唆されています。
-
syscall
パッケージのバリアント:nacltest.bash
は、mkzip.go
を使用して生成されたzipファイルをsyscall
パッケージに埋め込みます。これにより、NaCl環境で実行されるGoプログラムは、外部ファイルシステムにアクセスすることなく、必要なテストデータにアクセスできるようになります。- この埋め込みは、
syscall
パッケージの特定のビルドタグ(おそらくNaCl固有のタグ)が有効な場合にのみ行われるように設計されていると考えられます。
-
os/exec
を使用するテストの無効化:- NaClのサンドボックスモデルでは、外部プロセスの実行(
os/exec
パッケージが提供する機能)はセキュリティ上の理由から厳しく制限されるか、完全に禁止されます。 - このコミットでは、
os/exec
に依存するテストがNaCl環境で実行されないように、それらのテストを無効化する変更が含まれています。これは、テストファイルの変更(例:src/pkg/os/exec/exec_test.go
)や、nacltest.bash
スクリプト内での条件付き実行によって実現されています。
- NaClのサンドボックスモデルでは、外部プロセスの実行(
これらの変更により、GoのビルドシステムはNaClの特殊な環境に対応し、テストがサンドボックス内で必要なリソースにアクセスできるようになり、同時にNaClの制約に違反するテストはスキップされるようになります。
コアとなるコードの変更箇所
このコミットにおける主要なコード変更は以下のファイルに集中しています。
-
misc/nacl/mkzip.go
:- 新規追加されたファイル。
testzip.proto
で定義されたファイル構造に基づいてzipファイルを作成するGoプログラム。-p
フラグを使用すると、zipの内容をGoのバイト配列として出力し、Goのソースコードに埋め込める形式にする機能を持つ。
-
misc/nacl/testzip.proto
:- 新規追加されたファイル。
mkzip.go
がzipファイルを作成する際に参照するプロトタイプファイル。- Goのテストに必要な様々なファイル(例:
mime.types
,group
,hosts
など)のパスと、それらをzip内でどのように配置するかを定義。
-
src/nacltest.bash
:- 新規追加されたファイル。
all.bash
のNaCl版であり、NaCl環境でのGoのビルドとテスト実行をオーケストレーションするシェルスクリプト。mkzip.go
を呼び出してテストデータを埋め込んだsyscall
パッケージをビルドするロジックが含まれる。
-
src/all.bash
:- 既存のファイルへの変更。
nacltest.bash
の呼び出しや、NaCl関連のビルド設定が追加された可能性がある。
-
各種テストファイル (
src/cmd/..._test.go
,src/pkg/..._test.go
,test/...go
):- 多数の既存テストファイルに修正が加えられています。
- 主に、
os/exec
パッケージを使用するテストや、NaCl環境で問題を引き起こす可能性のあるテストが、NaClビルドタグが有効な場合にスキップされるように変更されています。これは、if runtime.GOOS == "nacl"
のような条件分岐や、ビルドタグ(例:// +build !nacl
)の追加によって実現されます。 - 例:
src/pkg/os/exec/exec_test.go
、src/pkg/net/http/cgi/matryoshka_test.go
など。
-
misc/nacl/testdata/
以下のファイル:mime.types
,group
,hosts
,empty
,bin/placeholder
などが新規追加されています。- これらは
testzip.proto
で参照され、最終的に埋め込まれるテストデータの一部となります。特にmime.types
は非常に大きなファイルです。
コアとなるコードの解説
このコミットの核心は、NaCl環境の制約を克服し、GoのテストスイートをNaCl上で実行可能にするための巧妙なデータ埋め込みとビルドプロセスの調整にあります。
mkzip.go
とtestzip.proto
によるテストデータの埋め込み
mkzip.go
は、Goのテストが実行時に必要とする外部ファイルを、単一のGoバイナリに埋め込むための重要なツールです。
-
testzip.proto
の解析:mkzip.go
は、testzip.proto
ファイルを読み込み、その内容を解析します。testzip.proto
は、以下のような形式でファイルツリーを記述します。etc src=/etc mime.types src=../misc/nacl/testdata/mime.types resolv.conf src=../misc/nacl/testdata/empty usr src=../misc/nacl/testdata bin
- 行頭のタブの数でディレクトリの階層構造を示します。
- 最初のフィールドは、zipファイル内のパス名です。
src=...
属性は、実際のファイルデータがどこから取得されるかを指定します。これが指定されない場合、同名のファイルが現在のソースディレクトリからコピーされます。*
や+
は、ディレクトリ内のすべてのファイルや、サブディレクトリを含めたすべてのファイルを再帰的に追加することを示します。
-
Zipファイルの生成:
mkzip.go
は、解析した情報に基づいてarchive/zip
パッケージを使用してzipファイルを作成します。各エントリは、testzip.proto
で指定されたパスとソースからデータを取得して追加されます。 -
Goソースコードへの変換(
-p
フラグ): 最も重要な機能の一つは、-p
フラグが指定された場合です。この場合、mkzip.go
はzipファイルの内容を直接ファイルに書き込むのではなく、Goのソースコードとして標準出力に出力します。具体的には、zipファイルのバイナリデータを16進数エスケープシーケンス(\xNN
)の文字列リテラルに変換し、それをinit()
関数内でunzip
関数に渡す形式で出力します。package somepackage func init() { unzip("\x50\x4b\x03\x04\x14\x00\x00\x00...") // zipファイルのバイナリデータ }
この生成されたGoコードは、Goのビルドプロセス中に
syscall
パッケージ(または関連するパッケージ)にコンパイルされ、結果としてzipファイルの内容がGoのバイナリに埋め込まれます。
nacltest.bash
によるビルドオーケストレーション
nacltest.bash
は、NaCl環境向けのGoのビルドとテストを調整するスクリプトです。
-
mkzip.go
の実行: このスクリプトは、mkzip.go
を呼び出し、testzip.proto
を読み込ませて、テストデータを埋め込んだGoソースファイルを生成させます。この生成されたソースファイルは、Goのビルドシステムによってsyscall
パッケージの一部としてコンパイルされます。 -
syscall
パッケージの特殊なビルド: NaCl環境では、syscall
パッケージが通常のシステムコールではなく、NaClのnewlib
やglibc
インターフェースを介して動作する必要があります。また、このコミットでは、前述の埋め込まれたテストデータにアクセスするためのロジックもsyscall
パッケージ内に含まれるようになります。これにより、テストは実行時に外部ファイルシステムに依存することなく、必要なデータにアクセスできます。 -
テストの選択的無効化:
nacltest.bash
は、NaCl環境で実行できないテスト(特にos/exec
を使用するもの)を特定し、それらをスキップするようにGoのテストコマンドを調整します。これは、テストファイル内のビルドタグ(例:// +build !nacl
)や、テスト実行時の環境変数設定によって制御されます。
テストファイルの変更
多くのテストファイルでは、以下のような変更が加えられています。
// Some test code
if runtime.GOOS == "nacl" {
t.Skip("skipping test on nacl")
}
// Original test logic
または、ファイルの先頭にビルドタグが追加されます。
// +build !nacl
package somepackage_test
// ...
これにより、nacl
ビルドタグが有効な場合(つまりNaCl向けにビルドされる場合)、特定のテストファイル全体またはテスト関数がコンパイルから除外されるか、実行時にスキップされるようになります。これは、NaClのサンドボックスモデルではサポートされない機能(例: 外部プロセスの起動、特定のネットワーク操作、ファイルシステム操作)に依存するテストを適切に処理するために不可欠です。
これらの変更の組み合わせにより、GoはNaCl環境で動作し、そのテストスイートもNaClの制約内で実行可能になります。特に、テストデータの埋め込みは、NaClの制限されたファイルシステムアクセスに対する実用的な解決策を提供しています。
関連リンク
-
Go Issue #7945: https://github.com/golang/go/issues/7945
- このコミットが修正したGoのIssueです。通常、Issueには問題の詳細な説明や議論が含まれています。
-
Go Code Review (CL) 100590044: https://golang.org/cl/100590044
- このコミットに対応するGoのコードレビューページです。ここには、コミットがマージされるまでの議論、レビューコメント、変更の差分などが詳細に記録されています。
参考にした情報源リンク
- Google Native Client (NaCl) 公式ドキュメント:
- https://developer.chrome.com/native-client/ (現在はアーカイブされており、PNaClは非推奨となっていますが、当時の技術背景を理解する上で参考になります。)
- Go言語の公式ドキュメント:
- Goのビルドシステム、パッケージ、テストに関する一般的な情報。
- Go言語のソースコード:
src/all.bash
やsrc/make.bash
など、Goのビルドプロセスに関連するスクリプト。os/exec
パッケージのドキュメント。
- Plan 9
mkfs
:testzip.proto
の形式のインスピレーション元。- https://9p.io/sys/man/4/mkfs.html (Plan 9のドキュメント)
(注: 上記の参考情報源リンクは、当時の技術背景を理解するための一般的な情報源であり、このコミットが直接参照したものではない可能性があります。特にNaClは現在では非推奨の技術ですが、コミット当時の状況を説明するために言及しています。)