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

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

このコミットは、Go言語のツールチェインがPlan 9オペレーティングシステム上で正しくビルドされるようにするための修正を含んでいます。具体的には、lib9ライブラリ内の関数(runcmd, removeall, tempdir)の修正、ビルドツールであるcmd/distがPlan 9固有のファイルを適切に含めるようにする変更、そしてリンカであるcmd/ldlib9の新しい関数シグネチャに対応するための変更が行われています。

コミット

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オペレーティングシステム上で適切に機能するようにするための修正です。主な変更点は以下の通りです。

  1. lib9の修正: runcmdremovealltempdirといった関数がPlan 9環境で正しく動作するように修正されました。これには、プロセス実行や一時ディレクトリの管理に関するPlan 9固有のシステムコールへの適応が含まれます。
  2. cmd/distの修正: ビルドプロセスにおいて、run_plan9.ctempdir_plan9.cのようなPlan 9固有のソースファイルが適切にビルド対象に含まれるように、cmd/distのビルドロジックが更新されました。これにより、ファイル名に"plan9"を含むファイルがビルド時に考慮されるようになりました。
  3. 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環境でのビルドの健全性を確保するために行われました。

前提知識の解説

このコミットを理解するためには、以下の前提知識が役立ちます。

  1. Go言語のツールチェイン:

    • cmd/dist: Go言語のソースコードからGoツールチェイン自体をビルドするためのツールです。Goのコンパイラ、リンカ、アセンブラなどを生成する役割を担います。OS固有のビルド設定やファイルの選択ロジックを含んでいます。
    • cmd/ld: Go言語のリンカです。コンパイルされたオブジェクトファイルを結合し、実行可能なバイナリを生成します。外部ライブラリの関数呼び出しを解決する役割も持ちます。
    • lib9: Go言語のソースツリー内にあるライブラリの一つで、Plan 9オペレーティングシステムに特化した低レベルな関数やシステムコールラッパーを提供します。Goのランタイムや標準ライブラリがPlan 9上で動作するために必要な抽象化レイヤーです。
  2. Plan 9 from Bell Labs:

    • ベル研究所で開発された分散オペレーティングシステムです。Unixの設計思想をさらに推し進め、すべてのリソースをファイルとして扱うという徹底した哲学を持っています。
    • Unix系OSとの違い: Plan 9はUnixから派生したものの、多くの点で異なる設計を採用しています。特に、プロセス管理、ファイルシステム、ネットワークプロトコル、システムコールインターフェースにおいて顕著な違いがあります。
    • execexecvp:
      • Unix系OSでは、execファミリーの関数が新しいプログラムを実行するために使われます。
      • execvp(file, argv): fileで指定されたプログラムをPATH環境変数で指定されたディレクトリから検索して実行します。
      • exec(file, argv0, argv1, ...): fileで指定された絶対パスまたは相対パスのプログラムを直接実行します。PATH検索は行いません。
      • Plan 9では、execがUnixのexecvpに相当する機能を持つことがあり、パス検索の挙動が異なる場合があります。このコミットでは、Plan 9のexecのセマンティクスに合わせるために変更されています。
    • _exitexits:
      • Unix系OSでは、_exit(status)はプロセスを即座に終了させるシステムコールです。バッファのフラッシュなどを行いません。
      • Plan 9では、exits(message)がプロセスを終了させるための標準的なシステムコールです。終了ステータスではなく、終了メッセージ(文字列)を渡すのが特徴です。この違いが、Goのクロスプラットフォーム対応において重要になります。
  3. C言語の基礎:

    • このコミットで変更されているファイルはC言語で書かれています。C言語の関数定義、変数宣言、プリプロセッサディレクティブ、標準ライブラリ関数(streq, containsなど)の知識が必要です。
    • 関数プロトタイプ宣言: int runcmd(char**); のような記述は、関数の前方宣言(プロトタイプ宣言)であり、リンカが関数呼び出しを解決するために必要です。

これらの知識を持つことで、コミットの意図と具体的な変更内容がより深く理解できます。

技術的詳細

このコミットは、Go言語のビルドシステムとランタイムがPlan 9環境で正しく動作するための複数の技術的修正を含んでいます。

  1. src/cmd/dist/build.c の変更:

    • shouldbuild関数は、特定のソースファイルが現在のビルドターゲット(OSやアーキテクチャ)に対してビルドされるべきかどうかを判断します。
    • 変更前は、goos.cflag.c以外のファイルはデフォルトでビルド対象から除外されていました(return 0;)。
    • 変更後は、if(!contains(name, "plan9")) return 0;という行が追加されました。これは、「ファイル名に"plan9"という文字列が含まれていない場合はビルド対象から除外する」という意味になります。
    • このロジックの変更により、run_plan9.ctempdir_plan9.cのようにファイル名にplan9を含むファイルが、Plan 9向けのビルド時に適切にcmd/distによって認識され、コンパイル対象に含まれるようになります。これは、特定のOS向けのコードを条件付きでビルドに含めるための一般的なパターンです。
  2. src/cmd/ld/lib.c の変更:

    • このファイルはGoリンカ(cmd/ld)の一部であり、リンカが外部関数を解決するために必要な宣言を含んでいます。
    • 追加された行は以下の通りです。
      // provided by lib9
      int runcmd(char**);
      char* mktempdir(void);
      void removeall(char*);
      
    • これらは、lib9ライブラリによって提供されるruncmdmktempdirremoveall関数の前方宣言(プロトタイプ宣言)です。
    • リンカは、これらの宣言を見て、GoのコードがこれらのC言語関数を呼び出す際に、そのシグネチャ(引数の型と戻り値の型)を正しく認識し、リンク時にシンボルを解決できるようになります。これは、lib9でこれらの関数のシグネチャが変更されたか、あるいはGoのツールチェインがこれらの関数を新しく利用するようになったために必要になったと考えられます。
  3. src/lib9/run_plan9.c の変更:

    • このファイルは、Plan 9環境でのプロセス実行に関するruncmd関数の実装を含んでいます。
    • execvpからexecへの変更:
      • 変更前: execvp(argv[0], argv);
      • 変更後: exec(argv[0], argv);
      • Unix系OSではexecvpPATH環境変数を使って実行ファイルを検索しますが、Plan 9のexecシステムコールはUnixのexecvpとは異なるセマンティクスを持つ場合があります。この変更は、Plan 9のネイティブなexecシステムコールの挙動に合わせるためのものです。Plan 9では、execPATH検索を行うか、あるいはargv[0]が絶対パスである必要があるかなど、OSのバージョンや設定によって挙動が異なる可能性がありますが、この修正はPlan 9の標準的なAPIに準拠するためのものです。
    • _exitからexitsへの変更:
      • 変更前: _exit(1);
      • 変更後: exits("exec");
      • _exitはPOSIX標準のシステムコールで、プロセスを即座に終了させます。一方、exitsはPlan 9固有のシステムコールで、プロセス終了時に文字列メッセージを渡すことができます。この変更は、Plan 9の慣習とAPIに準拠するために行われました。エラー発生時に"exec"というメッセージを付けて終了することで、デバッグやログ記録が容易になります。
  4. 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の要件に合わせるか、あるいは既存のコードのバグ修正(例えば、未宣言変数の使用)である可能性が高いです。

これらの技術的詳細は、Go言語が異なるOS環境でどのように低レベルなシステムコールやビルドプロセスを適応させているかを示しています。

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

このコミットにおけるコアとなるコードの変更箇所は以下の通りです。

  1. src/cmd/dist/build.cshouldbuild 関数:

    --- 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;
    
  2. 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)
     {
    
  3. src/lib9/run_plan9.cruncmd 関数:

    --- 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();
    
  4. 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.cshouldbuild 関数

この変更は、GoのビルドシステムがPlan 9固有のソースファイルを適切に認識し、ビルドプロセスに含めるようにするためのものです。 以前のロジックでは、goos.cflag.cといった特定のファイル名以外は、デフォルトでビルド対象から除外されていました。 新しい行 if(!contains(name, "plan9")) return 0; は、この除外ロジックに例外を追加します。つまり、ファイル名に "plan9" という文字列が含まれている場合は、たとえそれがgoos.cflag.cでなくても、ビルド対象として考慮されるようになります。これにより、run_plan9.ctempdir_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.cruncmd 関数

この変更は、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環境での一時ディレクトリの作成と削除が安定して行われるようになります。

関連リンク

参考にした情報源リンク