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

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

このコミットは、Goコンパイラ(cmd/gc)におけるWindowsビルドの問題を修正することを目的としています。具体的には、Windows環境を判定するためのグローバル変数windowsの使用を廃止し、コンテキスト(ctxt)から取得するctxt->windowsに切り替えることで、より堅牢なビルドプロセスを実現しています。

コミット

commit 9a53fb571d3ce9846252b38ad8991e48a48ebc15
Author: Russ Cox <rsc@golang.org>
Date:   Mon Dec 9 13:02:56 2013 -0500

    cmd/gc: fix windows build, probably
    
    TBR=iant
    CC=golang-dev
    https://golang.org/cl/39540043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/9a53fb571d3ce9846252b38ad8991e48a48ebc15

元コミット内容

cmd/gc: fix windows build, probably

このコミットは、Goコンパイラ(cmd/gc)のWindowsビルドに関する問題を修正するものです。

変更の背景

Goコンパイラは、様々なオペレーティングシステム(OS)やアーキテクチャに対応するために、クロスコンパイル機能を備えています。以前のGoコンパイラでは、コンパイル対象がWindowsであるかどうかを判定するために、windowsというグローバル変数が使用されていました。しかし、このようなグローバル変数の使用は、特にクロスコンパイルのような複雑なビルド環境において、予期せぬ副作用や競合状態を引き起こす可能性がありました。

具体的には、コンパイラの異なる部分や、異なるビルドコンテキストが、この単一のグローバル変数に依存することで、Windows固有のパス処理やファイルシステム操作が正しく行われないケースが発生していたと考えられます。このコミットは、この問題を解決し、Windows上でのGoコンパイラのビルドの安定性を向上させることを目的としています。"probably"という言葉は、当時の開発者がこの修正が問題の根本的な解決策であると確信しつつも、複雑なビルド環境における潜在的なエッジケースを完全に排除できるかどうかに慎重な姿勢を示している可能性があります。

前提知識の解説

  • cmd/gc: これはGo言語の公式コンパイラの一部であり、Goソースコードを機械語に変換する役割を担っています。gcは「Go Compiler」の略です。Goのツールチェインの中核をなすコンポーネントの一つです。
  • yylex: 字句解析器(lexer/scanner)の関数名としてよく使われる慣習的な名前です。コンパイラにおいて、ソースコードをトークン(単語や記号の最小単位)に分解する処理を担当します。このコミットでは、lex.cというファイルで変更が行われていることから、字句解析に関連する部分でWindows固有のパス処理が行われていたことが示唆されます。
  • islocalname: この関数は、与えられた名前がローカルなファイルパスまたは識別子であるかどうかを判定するために使用されると考えられます。Windowsでは、ドライブレター(例: C:)やバックスラッシュ(\)がパス区切り文字として使用されるため、OS固有のパス解析ロジックが必要になります。
  • mkpackage: この関数は、Goのパッケージを構築する際に関連する処理を行うと考えられます。パッケージのビルドプロセスでは、出力ファイルのパス生成など、ファイルシステム操作が頻繁に行われるため、ここでもOS固有のパス処理が重要になります。
  • GoのビルドコンテキストとGOOS: Goのビルドシステムは、GOOS(ターゲットOS)やGOARCH(ターゲットアーキテクチャ)といった環境変数を通じて、コンパイル対象の環境を認識します。これらの情報は、コンパイラ内部でbuild.Contextのような構造体を通じて管理されます。GOOSwindowsに設定されている場合、コンパイラはWindows固有の動作(例: パス区切り文字の扱い、ファイルシステムの特性)を適用します。このコミットの変更は、グローバル変数ではなく、このコンテキスト情報からWindows判定を行うように切り替えることで、より堅牢で一貫性のあるビルド動作を目指しています。

技術的詳細

このコミットの核心は、Goコンパイラ内部でWindows環境を判定する方法の変更にあります。以前は、windowsという名前のグローバルなint型変数が存在し、これがWindows環境であるかどうかのフラグとして機能していました。しかし、このようなグローバル変数は、特に並行処理や複雑なビルドパイプラインにおいて、状態管理の複雑さを増し、予期せぬバグ(例えば、異なるビルドターゲットが同じコンパイラインスタンスを共有する場合の誤判定)を引き起こす可能性があります。

この修正では、windowsグローバル変数を廃止し、代わりにctxt->windowsという形式で、コンテキスト構造体(ctxt)のメンバーとしてWindows判定フラグを参照するように変更しています。

  • src/cmd/gc/go.h の変更:

    • extern int windows; の行が削除されました。これは、windows変数がもはやグローバルな外部変数として宣言されていないことを意味します。これにより、他のファイルがこのグローバル変数に直接アクセスすることを防ぎ、依存関係を明確にします。
  • src/cmd/gc/lex.c の変更:

    • int windows; の行が削除されました。これは、windowsグローバル変数の定義自体がなくなったことを意味します。
    • islocalname 関数内で、if(windows && name->len >= 3 && ...) という条件が if(ctxt->windows && name->len >= 3 && ...) に変更されました。islocalnameは、ファイルパスがローカルなものかどうかを判定する際に、Windows特有のドライブレター形式(例: C:/path)を考慮する必要がありました。この変更により、Windows環境であるかどうかの判定が、現在のコンパイルコンテキスト(ctxt)から取得されるようになりました。
    • mkpackage 関数内で、if(windows) { ... } という条件が if(ctxt->windows) { ... } に変更されました。mkpackageは、パッケージの出力ファイルパスを生成する際に、Windowsのパス区切り文字(\)を考慮する必要がありました。ここでも、Windows環境の判定がコンテキストベースになりました。

この変更により、コンパイラの各部分が、自身のビルドコンテキストに紐付けられたwindowsフラグを参照するようになります。これにより、異なるビルドターゲットや並行して実行されるコンパイルプロセスが、それぞれ独立した正しい環境情報を参照できるようになり、ビルドの堅牢性と信頼性が向上します。これは、Goコンパイラがクロスコンパイルを強力にサポートするための重要な改善点と言えます。

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

--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -1182,7 +1182,6 @@ char*	expstring(void);
 void	mkpackage(char* pkgname);
 void	unimportfile(void);
 int32	yylex(void);
-extern	int	windows;
 extern	int	yylast;
 extern	int	yyprev;
 
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index f1df9cc3b6..0ca330fac6 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -14,7 +14,6 @@
 #define	ungetc	ccungetc
 
 extern int yychar;
-int windows;
 int yyprev;
 int yylast;
 
@@ -548,7 +547,7 @@ islocalname(Strlit *name)
 {
 	if(name->len >= 1 && name->s[0] == '/')
 		return 1;
-	if(windows && name->len >= 3 &&
+	if(ctxt->windows && name->len >= 3 &&
 	   yy_isalpha(name->s[0]) && name->s[1] == ':' && name->s[2] == '/')
 	   	return 1;
 	if(name->len >= 2 && strncmp(name->s, "./", 2) == 0)
@@ -2342,7 +2341,7 @@ mkpackage(char* pkgname)
 
 	if(outfile == nil) {
 		tp = strrchr(infile, '/');
-		if(windows) {
+		if(ctxt->windows) {
 			q = strrchr(infile, '\\');
 			if(q > p)
 				p = q;

コアとなるコードの解説

このコミットは、GoコンパイラがWindows環境を検出する方法を、グローバル変数からコンテキストベースの変数へと変更しています。

  1. src/cmd/gc/go.h の変更:

    • -extern int windows; の行が削除されました。これは、windowsという名前のグローバル変数が、もはやGoコンパイラのヘッダーファイルで外部変数として宣言されていないことを意味します。これにより、この変数が他のファイルから直接アクセスされることがなくなり、そのスコープが限定されるか、完全に廃止されることを示唆しています。
  2. src/cmd/gc/lex.c の変更:

    • -int windows; の行が削除されました。これは、windowsという名前のグローバル変数の定義自体がこのファイルから削除されたことを意味します。これにより、このグローバル変数がメモリ上に存在しなくなり、その代わりにコンテキスト構造体内のフラグが使用されるようになります。
    • islocalname 関数内の変更:
      • -if(windows && name->len >= 3 &&+if(ctxt->windows && name->len >= 3 && に変更されました。
      • islocalname 関数は、ファイルパスがローカルなものかどうかを判定する際に、Windows特有のパス形式(例: C:/path)を認識する必要があります。以前はグローバルなwindows変数に依存していましたが、この変更により、現在のコンパイルコンテキストを表すctxt構造体のメンバーであるctxt->windowsを参照するようになりました。これにより、コンパイル対象のOSがWindowsであるかどうかの判定が、より正確かつ独立したコンテキストに基づいて行われるようになります。
    • mkpackage 関数内の変更:
      • -if(windows) {+if(ctxt->windows) { に変更されました。
      • mkpackage 関数は、Goのパッケージを構築する際に、出力ファイルのパスを決定します。Windowsではパス区切り文字が/ではなく\であるため、この関数内でOS固有のパス処理が必要でした。ここでも、グローバルなwindows変数からctxt->windowsへの切り替えが行われ、パッケージビルド時のパス処理がコンテキストに依存するようになりました。

これらの変更により、Goコンパイラは、コンパイル対象のOSに関する情報を、より構造化されたctxt(コンテキスト)オブジェクトを通じて取得するようになります。これは、コンパイラのモジュール性、テスト容易性、そして特にクロスコンパイル環境における堅牢性を向上させる上で重要な改善です。グローバル変数の使用を避け、明示的なコンテキストを渡すことで、予期せぬ状態の変更や競合のリスクが低減されます。

関連リンク

参考にした情報源リンク