[インデックス 18496] ファイルの概要
このコミットは、Goコンパイラのフロントエンドであるcmd/gc
におけるWindowsビルドの問題を修正するものです。具体的には、lex.c
ファイル内で定義されているcatcher
関数が、Windows環境で未定義の参照エラー(undefined reference to noted
)を引き起こしていた問題を解決します。
コミット
commit e0dee49688c1c767e2f81a4dab824ba0be36dcbb
Author: Dmitriy Vyukov <dvyukov@google.com>
Date: Thu Feb 13 20:15:19 2014 +0400
cmd/gc: fix windows build
c:\src\go\pkg\obj\windows_amd64\libgc.a(lex.o): In function `catcher':
c:/src/go/src/cmd/gc/lex.c:181: undefined reference to `noted'
LGTM=0intro
R=0intro
CC=golang-codereviews
https://golang.org/cl/63270043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/e0dee49688c1c767e2f81a4dab824ba0be36dcbb
元コミット内容
cmd/gc: fix windows build
c:\src\go\pkg\obj\windows_amd64\libgc.a(lex.o): In function `catcher':
c:/src/go/src/cmd/gc/lex.c:181: undefined reference to `noted'
LGTM=0intro
R=0intro
CC=golang-codereviews
https://golang.org/cl/63270043
変更の背景
このコミットは、Goコンパイラのcmd/gc
(Goコンパイラのフロントエンド部分)をWindows環境でビルドする際に発生していたエラーを修正するために行われました。エラーメッセージ「undefined reference to noted
」が示すように、lex.c
ファイル内のcatcher
関数が、noted
というシンボル(関数または変数)を参照しているにもかかわらず、そのシンボルがリンク時に見つからないという問題が発生していました。
この問題は、noted
シンボルが特定のオペレーティングシステム(この場合はPlan 9)に特有のものであり、Windows環境では提供されていないために発生していました。Goコンパイラは、その歴史的経緯からPlan 9のツールチェインの影響を強く受けており、一部のコードがPlan 9固有のAPIを使用していることがあります。しかし、Windowsのような異なるOSでビルドする際には、これらのOS固有の依存関係が問題となることがあります。
開発者Dmitriy Vyukov氏によって報告されたこのビルドエラーは、Goコンパイラのクロスプラットフォーム対応における重要な課題の一つでした。
前提知識の解説
cmd/gc
: Go言語のコンパイラのフロントエンド部分を指します。Goのソースコードを解析し、中間表現に変換する役割を担います。gc
は「Go compiler」の略です。lex.c
: 字句解析(lexical analysis)を行うC言語のソースファイルです。字句解析は、ソースコードをトークン(単語のようなもの)の並びに分解するプロセスであり、コンパイラの最初の段階です。- Plan 9: ベル研究所で開発された分散オペレーティングシステムです。Go言語の開発者の一部はPlan 9の開発にも携わっており、Goの設計思想やツールチェインにはPlan 9の影響が色濃く残っています。特に、Goの初期のコンパイラやツールはPlan 9のツールチェインをベースにしていました。
noted
関数: Plan 9オペレーティングシステムにおけるシステムコールの一つです。Plan 9では、プロセスがシグナルを受信した際に、そのシグナルを「通知(note)」として処理するメカニズムがあります。noted
関数は、この通知メカニズムに関連する関数であり、通常はシグナルハンドラ内で使用され、通知を処理したことをシステムに伝える役割を果たします。Windowsにはこれに直接対応するAPIは存在しません。- 条件付きコンパイル (
#ifdef
,#endif
): C/C++言語におけるプリプロセッサディレクティブです。#ifdef マクロ名
から#endif
までのコードブロックは、指定されたマクロ名
が定義されている場合にのみコンパイルされます。これにより、異なるプラットフォームや環境に応じて、特定のコードをコンパイルに含めたり除外したりすることができます。このコミットでは、PLAN9
というマクロが定義されている場合にのみcatcher
関数をコンパイルするように制御しています。
技術的詳細
この問題の根本原因は、src/cmd/gc/lex.c
内のcatcher
関数が、Plan 9固有のnoted
関数を呼び出していたことにあります。Goコンパイラは、様々なオペレーティングシステムでビルドおよび実行できるように設計されていますが、一部の低レベルなコードやレガシーな部分では、特定のOSに依存するAPIが使用されていることがあります。
Windows環境でcmd/gc
をビルドする際、リンカはnoted
関数の定義を見つけることができませんでした。これは、Windowsの標準ライブラリやGoのランタイムライブラリにはnoted
関数が含まれていないためです。結果として、リンカは未解決のシンボルエラーを報告し、ビルドが失敗していました。
このコミットによる修正は、非常にシンプルかつ効果的なものです。catcher
関数全体を#ifdef PLAN9
と#endif
で囲むことにより、PLAN9
マクロが定義されている環境(つまりPlan 9環境)でのみcatcher
関数がコンパイルされるように変更しました。
#ifdef PLAN9
: この行は、プリプロセッサに対して、PLAN9
というマクロが定義されているかどうかをチェックするように指示します。void catcher(void *v, char *s)
からnoted(NDFLT); }
まで: このコードブロックは、catcher
関数の定義です。#endif
: この行は、#ifdef
ディレクティブで開始された条件付きコンパイルブロックの終わりを示します。
Windows環境ではPLAN9
マクロは定義されていないため、catcher
関数はコンパイル対象から除外されます。これにより、noted
関数への未定義参照エラーが解消され、Windowsでのビルドが成功するようになります。
この修正は、catcher
関数がWindows環境では不要であるか、あるいはその機能がWindowsでは異なる方法で処理されることを示唆しています。コンパイラの字句解析器において、catcher
関数がどのような役割を担っていたのかは、このコミットメッセージだけでは明確ではありませんが、おそらく特定のシグナルや例外処理に関連するもので、Plan 9の環境でのみ必要とされる特殊なケースハンドリングだったと考えられます。
コアとなるコードの変更箇所
変更はsrc/cmd/gc/lex.c
ファイルにのみ行われました。
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -164,6 +164,7 @@ fault(int s)
fatal("fault");
}
+#ifdef PLAN9
void
catcher(void *v, char *s)
{
@@ -180,6 +181,7 @@ catcher(void *v, char *s)
}
noted(NDFLT);
}
+#endif
void
doversion(void)
コアとなるコードの解説
この変更は、catcher
関数の定義全体を#ifdef PLAN9
と#endif
プリプロセッサディレクティブで囲むことで構成されています。
+ #ifdef PLAN9
:catcher
関数の定義の直前に挿入された行です。これにより、この後のコードブロックがPLAN9
マクロが定義されている場合にのみコンパイルされるようになります。+ #endif
:catcher
関数の定義の直後に挿入された行です。これにより、#ifdef PLAN9
で開始された条件付きコンパイルブロックが閉じられます。
この修正により、WindowsのようなPlan 9以外の環境でGoコンパイラをビルドする際には、catcher
関数とその中で呼び出されているnoted
関数がコンパイル対象から除外されます。結果として、Windows環境での「undefined reference to noted
」というリンクエラーが解消され、ビルドが正常に完了するようになります。
これは、クロスプラットフォーム開発において一般的な手法であり、特定のOSに依存するコードを分離し、必要な環境でのみコンパイルすることで、移植性を高めることができます。
関連リンク
- Go CL 63270043: https://golang.org/cl/63270043
参考にした情報源リンク
- Go言語のソースコード(
src/cmd/gc/lex.c
の関連部分) - Plan 9のシステムコールに関する一般的な情報
- C言語のプリプロセッサディレクティブ(
#ifdef
,#endif
)に関する一般的な情報 - Go言語のコンパイラ構造に関する一般的な情報
- Go言語のIssueトラッカーやメーリングリストでの関連議論(もしあれば)