[インデックス 15692] ファイルの概要
このコミットは、Go言語のツールチェインがPlan 9オペレーティングシステム上で正しくビルドされるようにするための修正を含んでいます。具体的には、lib9
ライブラリ内の関数(runcmd
, removeall
, tempdir
)の修正、ビルドツールであるcmd/dist
がPlan 9固有のファイルを適切に含めるようにする変更、そしてリンカであるcmd/ld
がlib9
の新しい関数シグネチャに対応するための変更が行われています。
コミット
commit 76374412c36ccbac91c86a033b37732661787246
Author: Akshat Kumar <seed@mail.nanosouffle.net>
Date: Mon Mar 11 13:34:57 2013 -0700
lib9, cmd/dist, cmd/ld: Plan 9: fix build
lib9: fix runcmd, removeall, and tempdir functions
cmd/dist: Include run_plan9.c and tempdir_plan9.c
from lib9 for build, and in general consider
file names containing "plan9" for building.
cmd/ld: provide function args for the new functions
from lib9.
R=rsc, rminnich, ality, bradfitz
CC=golang-dev
https://golang.org/cl/7666043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/76374412c36ccbac91c86a033b37732661787246
元コミット内容
このコミットの元の内容は、Go言語のビルドシステムがPlan 9オペレーティングシステム上で適切に機能するようにするための修正です。主な変更点は以下の通りです。
lib9
の修正:runcmd
、removeall
、tempdir
といった関数がPlan 9環境で正しく動作するように修正されました。これには、プロセス実行や一時ディレクトリの管理に関するPlan 9固有のシステムコールへの適応が含まれます。cmd/dist
の修正: ビルドプロセスにおいて、run_plan9.c
やtempdir_plan9.c
のようなPlan 9固有のソースファイルが適切にビルド対象に含まれるように、cmd/dist
のビルドロジックが更新されました。これにより、ファイル名に"plan9"を含むファイルがビルド時に考慮されるようになりました。cmd/ld
の修正:lib9
で修正された新しい関数(runcmd
,mktempdir
,removeall
)の引数定義が、リンカであるcmd/ld
に提供されました。これにより、リンカがこれらの関数を正しく解決できるようになります。
変更の背景
Go言語は、様々なオペレーティングシステム(Linux, macOS, Windowsなど)をサポートしていますが、その中にはPlan 9 from Bell Labsも含まれています。Goの初期開発はPlan 9環境で行われていた経緯もあり、Plan 9はGoにとって重要なターゲットプラットフォームの一つです。
このコミットが行われた2013年当時、Goのツールチェインは活発に開発されており、新しい機能の追加や既存コードのリファクタリングが頻繁に行われていました。その過程で、特定のオペレーティングシステム(この場合はPlan 9)に特化したビルドや実行に関する問題が発生することがありました。
このコミットの背景には、Plan 9環境でのGoツールチェインのビルドが失敗するか、あるいは正しく動作しないという問題があったと考えられます。特に、lib9
のようなOS固有の抽象化レイヤーを提供するライブラリは、OSのシステムコールやAPIの細かな違いに依存するため、他のOS向けの変更がPlan 9のビルドに影響を与えることがよくあります。
具体的には、execvp
からexec
への変更や_exit
からexits
への変更は、Plan 9のプロセス管理や終了コードの扱いがUnix系OSとは異なることに起因する互換性の問題に対処するためのものです。また、cmd/dist
がPlan 9固有のファイルを認識しない問題は、ビルドシステムが特定のOS向けのソースファイルを適切に選択・コンパイルできないという、ビルドの根本的な問題を示しています。
このコミットは、Go言語が多様なプラットフォームで安定して動作するという目標を達成するための一環として、Plan 9環境でのビルドの健全性を確保するために行われました。
前提知識の解説
このコミットを理解するためには、以下の前提知識が役立ちます。
-
Go言語のツールチェイン:
cmd/dist
: Go言語のソースコードからGoツールチェイン自体をビルドするためのツールです。Goのコンパイラ、リンカ、アセンブラなどを生成する役割を担います。OS固有のビルド設定やファイルの選択ロジックを含んでいます。cmd/ld
: Go言語のリンカです。コンパイルされたオブジェクトファイルを結合し、実行可能なバイナリを生成します。外部ライブラリの関数呼び出しを解決する役割も持ちます。lib9
: Go言語のソースツリー内にあるライブラリの一つで、Plan 9オペレーティングシステムに特化した低レベルな関数やシステムコールラッパーを提供します。Goのランタイムや標準ライブラリがPlan 9上で動作するために必要な抽象化レイヤーです。
-
Plan 9 from Bell Labs:
- ベル研究所で開発された分散オペレーティングシステムです。Unixの設計思想をさらに推し進め、すべてのリソースをファイルとして扱うという徹底した哲学を持っています。
- Unix系OSとの違い: Plan 9はUnixから派生したものの、多くの点で異なる設計を採用しています。特に、プロセス管理、ファイルシステム、ネットワークプロトコル、システムコールインターフェースにおいて顕著な違いがあります。
exec
とexecvp
:- Unix系OSでは、
exec
ファミリーの関数が新しいプログラムを実行するために使われます。 execvp(file, argv)
:file
で指定されたプログラムをPATH
環境変数で指定されたディレクトリから検索して実行します。exec(file, argv0, argv1, ...)
:file
で指定された絶対パスまたは相対パスのプログラムを直接実行します。PATH
検索は行いません。- Plan 9では、
exec
がUnixのexecvp
に相当する機能を持つことがあり、パス検索の挙動が異なる場合があります。このコミットでは、Plan 9のexec
のセマンティクスに合わせるために変更されています。
- Unix系OSでは、
_exit
とexits
:- Unix系OSでは、
_exit(status)
はプロセスを即座に終了させるシステムコールです。バッファのフラッシュなどを行いません。 - Plan 9では、
exits(message)
がプロセスを終了させるための標準的なシステムコールです。終了ステータスではなく、終了メッセージ(文字列)を渡すのが特徴です。この違いが、Goのクロスプラットフォーム対応において重要になります。
- Unix系OSでは、
-
C言語の基礎:
- このコミットで変更されているファイルはC言語で書かれています。C言語の関数定義、変数宣言、プリプロセッサディレクティブ、標準ライブラリ関数(
streq
,contains
など)の知識が必要です。 - 関数プロトタイプ宣言:
int runcmd(char**);
のような記述は、関数の前方宣言(プロトタイプ宣言)であり、リンカが関数呼び出しを解決するために必要です。
- このコミットで変更されているファイルはC言語で書かれています。C言語の関数定義、変数宣言、プリプロセッサディレクティブ、標準ライブラリ関数(
これらの知識を持つことで、コミットの意図と具体的な変更内容がより深く理解できます。
技術的詳細
このコミットは、Go言語のビルドシステムとランタイムがPlan 9環境で正しく動作するための複数の技術的修正を含んでいます。
-
src/cmd/dist/build.c
の変更:shouldbuild
関数は、特定のソースファイルが現在のビルドターゲット(OSやアーキテクチャ)に対してビルドされるべきかどうかを判断します。- 変更前は、
goos.c
やflag.c
以外のファイルはデフォルトでビルド対象から除外されていました(return 0;
)。 - 変更後は、
if(!contains(name, "plan9")) return 0;
という行が追加されました。これは、「ファイル名に"plan9"という文字列が含まれていない場合はビルド対象から除外する」という意味になります。 - このロジックの変更により、
run_plan9.c
やtempdir_plan9.c
のようにファイル名にplan9
を含むファイルが、Plan 9向けのビルド時に適切にcmd/dist
によって認識され、コンパイル対象に含まれるようになります。これは、特定のOS向けのコードを条件付きでビルドに含めるための一般的なパターンです。
-
src/cmd/ld/lib.c
の変更:- このファイルはGoリンカ(
cmd/ld
)の一部であり、リンカが外部関数を解決するために必要な宣言を含んでいます。 - 追加された行は以下の通りです。
// provided by lib9 int runcmd(char**); char* mktempdir(void); void removeall(char*);
- これらは、
lib9
ライブラリによって提供されるruncmd
、mktempdir
、removeall
関数の前方宣言(プロトタイプ宣言)です。 - リンカは、これらの宣言を見て、GoのコードがこれらのC言語関数を呼び出す際に、そのシグネチャ(引数の型と戻り値の型)を正しく認識し、リンク時にシンボルを解決できるようになります。これは、
lib9
でこれらの関数のシグネチャが変更されたか、あるいはGoのツールチェインがこれらの関数を新しく利用するようになったために必要になったと考えられます。
- このファイルはGoリンカ(
-
src/lib9/run_plan9.c
の変更:- このファイルは、Plan 9環境でのプロセス実行に関する
runcmd
関数の実装を含んでいます。 execvp
からexec
への変更:- 変更前:
execvp(argv[0], argv);
- 変更後:
exec(argv[0], argv);
- Unix系OSでは
execvp
がPATH
環境変数を使って実行ファイルを検索しますが、Plan 9のexec
システムコールはUnixのexecvp
とは異なるセマンティクスを持つ場合があります。この変更は、Plan 9のネイティブなexec
システムコールの挙動に合わせるためのものです。Plan 9では、exec
がPATH
検索を行うか、あるいはargv[0]
が絶対パスである必要があるかなど、OSのバージョンや設定によって挙動が異なる可能性がありますが、この修正はPlan 9の標準的なAPIに準拠するためのものです。
- 変更前:
_exit
からexits
への変更:- 変更前:
_exit(1);
- 変更後:
exits("exec");
_exit
はPOSIX標準のシステムコールで、プロセスを即座に終了させます。一方、exits
はPlan 9固有のシステムコールで、プロセス終了時に文字列メッセージを渡すことができます。この変更は、Plan 9の慣習とAPIに準拠するために行われました。エラー発生時に"exec"
というメッセージを付けて終了することで、デバッグやログ記録が容易になります。
- 変更前:
- このファイルは、Plan 9環境でのプロセス実行に関する
-
src/lib9/tempdir_plan9.c
の変更:- このファイルは、Plan 9環境での一時ディレクトリ作成(
mktempdir
)と削除(removeall
)に関する関数を含んでいます。 - 変数宣言の追加:
mktempdir
関数でint fd, i;
がint i;
からint fd, i;
に変更されました。これは、一時ファイルの作成時にファイルディスクリプタfd
を使用する必要があるため、その変数を宣言したものです。removeall
関数でint fd, n, i;
がint fd, n;
からint fd, n, i;
に変更されました。これは、ディレクトリ内のファイルを再帰的に削除する際にループカウンタi
が必要になったため、その変数を宣言したものです。
- これらの変更は、Plan 9のファイルシステム操作APIの要件に合わせるか、あるいは既存のコードのバグ修正(例えば、未宣言変数の使用)である可能性が高いです。
- このファイルは、Plan 9環境での一時ディレクトリ作成(
これらの技術的詳細は、Go言語が異なるOS環境でどのように低レベルなシステムコールやビルドプロセスを適応させているかを示しています。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更箇所は以下の通りです。
-
src/cmd/dist/build.c
のshouldbuild
関数:--- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -1070,7 +1070,8 @@ shouldbuild(char *file, char *dir) name = lastelem(file); if(streq(name, "goos.c") || streq(name, "flag.c")) return 1; - return 0; + if(!contains(name, "plan9")) + return 0; } if(streq(dir, "libbio")) return 0;
-
src/cmd/ld/lib.c
への関数プロトタイプ宣言の追加:--- a/src/cmd/ld/lib.c +++ b/src/cmd/ld/lib.c @@ -556,6 +556,11 @@ hostobjs(void) } } +// provided by lib9 +int runcmd(char**); +char* mktempdir(void); +void removeall(char*); + static void rmtemp(void) {
-
src/lib9/run_plan9.c
のruncmd
関数:--- a/src/lib9/run_plan9.c +++ b/src/lib9/run_plan9.c @@ -15,9 +15,9 @@ runcmd(char **argv) case -1: return -1; case 0: - execvp(argv[0], argv); + exec(argv[0], argv); fprintf(2, "exec %s: %r", argv[0]); - _exit(1); + exits("exec"); } w = wait();
-
src/lib9/tempdir_plan9.c
の変数宣言の修正:--- a/src/lib9/tempdir_plan9.c +++ b/src/lib9/tempdir_plan9.c @@ -9,7 +9,7 @@ char* mktempdir(void) { char *p; - int i; + int fd, i; p = smprint("/tmp/go-link-XXXXXX"); for(i=0; i<1000; i++) { @@ -27,7 +27,7 @@ mktempdir(void) void removeall(char *p) { - int fd, n; + int fd, n, i; Dir *d; char *q;
コアとなるコードの解説
src/cmd/dist/build.c
の shouldbuild
関数
この変更は、GoのビルドシステムがPlan 9固有のソースファイルを適切に認識し、ビルドプロセスに含めるようにするためのものです。
以前のロジックでは、goos.c
やflag.c
といった特定のファイル名以外は、デフォルトでビルド対象から除外されていました。
新しい行 if(!contains(name, "plan9")) return 0;
は、この除外ロジックに例外を追加します。つまり、ファイル名に "plan9"
という文字列が含まれている場合は、たとえそれがgoos.c
やflag.c
でなくても、ビルド対象として考慮されるようになります。これにより、run_plan9.c
やtempdir_plan9.c
のようなPlan 9専用のソースファイルが、Plan 9向けのビルド時に正しくコンパイルされるようになります。
src/cmd/ld/lib.c
への関数プロトタイプ宣言の追加
この変更は、Goのリンカ(cmd/ld
)がlib9
ライブラリによって提供される特定の関数(runcmd
, mktempdir
, removeall
)を正しくリンクできるようにするためのものです。
C言語では、関数を呼び出す前にその関数のプロトタイプ(引数の型と戻り値の型)を宣言しておく必要があります。これにより、コンパイラは関数呼び出しが正しい引数で行われているかを確認でき、リンカは後で実際の関数定義を見つけて結合することができます。
これらの宣言が追加されたということは、lib9
内のこれらの関数のシグネチャが変更されたか、あるいはGoのツールチェインがこれらの関数を新しく利用するようになったため、リンカがそれらを認識できるようにする必要があったことを示しています。
src/lib9/run_plan9.c
の runcmd
関数
この変更は、Plan 9環境での外部プログラム実行とプロセス終了のメカニズムを、Plan 9のネイティブなシステムコールに合わせるためのものです。
-
execvp
からexec
への変更:execvp
はUnix系OSで一般的に使用される関数で、PATH
環境変数を利用して実行ファイルを検索します。- Plan 9の
exec
システムコールは、Unixのexecvp
とは異なる挙動を持つことがあります。この変更は、Plan 9のexec
のセマンティクスに直接合わせることで、互換性の問題を解決し、Plan 9環境でプログラムが正しく実行されるようにします。
-
_exit
からexits
への変更:_exit(1)
はPOSIX標準のシステムコールで、プロセスを終了させ、終了ステータスを返します。exits("exec")
はPlan 9固有のシステムコールで、プロセス終了時に文字列メッセージを渡します。この変更は、Plan 9の慣習に従い、エラー発生時に具体的なメッセージを付けてプロセスを終了させることで、デバッグやシステムログの解析を容易にします。
src/lib9/tempdir_plan9.c
の変数宣言の修正
この変更は、mktempdir
(一時ディレクトリ作成)とremoveall
(ディレクトリ再帰削除)関数における変数宣言の修正です。
mktempdir
関数では、一時ファイルの作成に関連してファイルディスクリプタ(fd
)が必要になったため、int fd
が追加されました。removeall
関数では、ディレクトリ内のエントリを処理するループで、ループカウンタとしてi
が必要になったため、int i
が追加されました。
これらの変更は、Plan 9のファイルシステムAPIの正確な使用法に合わせるか、あるいは既存のコードにおける未宣言変数の使用といったコンパイルエラーを修正するためのものです。これにより、Plan 9環境での一時ディレクトリの作成と削除が安定して行われるようになります。
関連リンク
- Go言語の公式ウェブサイト: https://golang.org/
- Plan 9 from Bell Labs: https://9p.io/plan9/
- GoのGerritコードレビューシステム (CL 7666043): https://golang.org/cl/7666043 (コミットメッセージに記載されているリンク)
参考にした情報源リンク
- Go言語のソースコード (GitHub): https://github.com/golang/go
- Plan 9のシステムコールに関するドキュメント (例:
exec
,exits
): Plan 9の公式ドキュメントや関連する書籍、オンラインリソース(例: https://man.cat-v.org/plan_9/2/exec, https://man.cat-v.org/plan_9/2/exits など) - Unix系OSの
exec
ファミリー関数に関するドキュメント (例:man 3 execvp
) - C言語の標準ライブラリ関数に関するドキュメント