[インデックス 11482] ファイルの概要
このコミットは、Go言語のビルドスクリプト src/buildscript.sh
がWindows環境で正しく動作するように修正したものです。具体的には、sed
コマンドの処理順序を変更することで、パスの変換と文字列置換が適切に行われるように改善されています。
コミット
- コミットハッシュ:
be7a04944ea9eeb7ffd5458d26a83c1693df657c
- Author: Alex Brainman alex.brainman@gmail.com
- Date: Tue Jan 31 09:42:33 2012 +1100
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/be7a04944ea9eeb7ffd5458d26a83c1693df657c
元コミット内容
buildscript.sh: now works correctly on windows
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5569092
変更の背景
Go言語のビルドプロセスは、クロスプラットフォーム対応を重視しており、様々なオペレーティングシステム上で動作する必要があります。src/buildscript.sh
は、Goのツールチェインをビルドするためのシェルスクリプトであり、通常はUnix系システムで実行されます。しかし、Windows環境でGoをビルドする際には、CygwinやMinGW/MSYS2のようなUnixライクな環境が使われることが一般的です。
このコミット以前の buildscript.sh
では、Windowsパスの表現(バックスラッシュ \
を使用)と、go
バイナリの名前変更(go_bootstrap
へのリネーム)に関する sed
コマンドの適用順序に問題がありました。具体的には、$GOBIN/go
を $GOBIN/go_bootstrap
に置換する処理が、パス内のバックスラッシュをスラッシュに変換する処理よりも前に実行されていたため、Windowsパスが絡む場合に意図した置換が行われない、または不正なパスが生成される可能性がありました。
この問題は、Windows環境でのGoのビルドが失敗したり、生成されるバイナリのパスが正しく認識されないといった形で現れていました。このコミットは、この問題を解決し、Windows上でのGoのビルドプロセスを安定させることを目的としています。
前提知識の解説
1. Go言語のビルドシステム
Go言語は、自身のコンパイラやツールチェインをGo自身で記述するという「セルフホスティング」の原則を採用しています。このため、GoのソースコードからGoのバイナリを生成する際には、既存のGoコンパイラ(またはブートストラップコンパイラ)が必要になります。src/buildscript.sh
は、このブートストラッププロセスの一部として、Goのソースコードから最終的なGoツールチェインを構築するために使用されるスクリプトです。
2. buildscript.sh
buildscript.sh
は、Goのソースツリーの src
ディレクトリに存在するシェルスクリプトです。このスクリプトは、Goのビルドに必要な環境変数の設定、一時的なブートストラップコンパイラの構築、そして最終的なGoツールチェイン(go
コマンド、コンパイラ、リンカなど)のビルドとインストールを行います。
3. 環境変数 (GOBIN
, GOROOT
, WORK
)
GOBIN
: Goの実行可能バイナリがインストールされるディレクトリを指定します。通常は$GOROOT/bin
に設定されます。GOROOT
: Goのインストールルートディレクトリを指定します。Goのソースコード、標準ライブラリ、ツールなどがこのディレクトリ以下に配置されます。WORK
: ビルドプロセス中に一時ファイルや中間生成物が格納される作業ディレクトリを指定します。
これらの変数は、buildscript.sh
内でパスの構築やファイルの配置に使用されます。
4. sed
コマンド
sed
(stream editor) は、テキストファイルに対して変換処理を行うための強力なコマンドラインツールです。このコミットでは、sed
を使用して特定の文字列パターンを別の文字列に置換しています。
sed
の基本的な置換構文は s/pattern/replacement/flags
です。
s
: 置換コマンド (substitute) を意味します。pattern
: 検索する正規表現パターンです。replacement
:pattern
にマッチした部分を置換する文字列です。flags
: 置換の動作を制御するオプションです。g
は、行内でマッチしたすべてのパターンを置換することを意味します。
このコミットで使われている s;...;...;g
の形式は、区切り文字としてスラッシュ /
の代わりにセミコロン ;
を使用しています。これは、パターンや置換文字列にスラッシュが含まれる場合に、エスケープの手間を省くためによく使われるテクニックです。
5. WindowsパスとUnixパス
Windowsではディレクトリの区切り文字としてバックスラッシュ \
が使用されます(例: C:\Users\User\Documents
)。一方、Unix系システムではスラッシュ /
が使用されます(例: /home/user/documents
)。シェルスクリプトがWindows上でCygwinやMSYS2のような環境で実行される場合、内部的にはUnix形式のパスが扱われますが、Windowsネイティブのプログラムと連携する際にはパスの変換が必要になることがあります。
6. go_bootstrap
と go-tool
Goのビルドプロセスでは、まず最小限のGoコンパイラ(ブートストラップコンパイラ)が構築されます。これは通常、go_bootstrap
のような名前で一時的に存在します。その後、このブートストラップコンパイラを使用して、より完全なGoツールチェイン(go
コマンド、go-tool
など)がビルドされます。go-tool
は、Goの内部ツール(アセンブラ、リンカなど)を指すことが多いです。
技術的詳細
このコミットの核心は、src/buildscript.sh
内の sed
コマンドの順序変更です。
元のコードでは、以下の2つの sed
コマンドがこの順序で実行されていました。
# Original order
s;\"\\$GOBIN\"/go;&_bootstrap;g # (A) goをgo_bootstrapにリネーム
s;\\\\;/;g # (B) バックスラッシュをスラッシュに変換
-
s;\"\\$GOBIN\"/go;&_bootstrap;g
(A):- このコマンドは、
"$GOBIN"/go
という文字列を検索し、それを"$GOBIN"/go_bootstrap
に置換します。 \"
は引用符"
をエスケープしています。\\
はバックスラッシュ\
をエスケープしています。これは、$GOBIN
の値がWindowsパス(例:C:\Go\bin
)である場合に、その中のバックスラッシュが正規表現の特殊文字として解釈されないようにするためです。&
はマッチした文字列全体を指します。つまり、"$GOBIN"/go
に_bootstrap
を追加しています。
- このコマンドは、
-
s;\\\\;/;g
(B):- このコマンドは、すべてのバックスラッシュ
\
をスラッシュ/
に置換します。 \\\\
は、正規表現として\
をマッチさせるために、\
自体をエスケープし、さらにsed
の正規表現エンジンが\
を特殊文字として解釈しないようにするために、合計4つのバックスラッシュが必要です。
- このコマンドは、すべてのバックスラッシュ
問題点:
Windows環境では、$GOBIN
の値が C:\Go\bin
のようにバックスラッシュを含むパスになることがあります。
元の順序では、まず (A) の置換が実行されます。もし "$GOBIN"/go
が C:\Go\bin\go
のような形式だった場合、(A) は C:\Go\bin\go_bootstrap
に置換しようとします。しかし、この時点ではまだバックスラッシュがスラッシュに変換されていないため、sed
のパターンマッチングが期待通りに機能しない、または生成されるパスが不正になる可能性がありました。特に、正規表現のパターンにバックスラッシュが含まれる場合、その解釈が複雑になります。
修正内容:
コミットでは、この2つの sed
コマンドの順序を入れ替えています。
# New order
s;\\\\;/;g # (B) バックスラッシュをスラッシュに変換
s;\"\\$GOBIN\"/go;&_bootstrap;g # (A) goをgo_bootstrapにリネーム
-
s;\\\\;/;g
(B) が先に実行されます。- これにより、
$GOBIN
の値に含まれるすべてのバックスラッシュがスラッシュに変換されます。例えば、C:\Go\bin
はC:/Go/bin
になります。 - この変換は、後続の
sed
コマンドがUnix形式のパスを前提として動作するように、パスを正規化する役割を果たします。
- これにより、
-
次に
s;\"\\$GOBIN\"/go;&_bootstrap;g
(A) が実行されます。- この時点では、
$GOBIN
の値はすでにスラッシュ区切りのパスになっています(例:C:/Go/bin
)。 - したがって、
"$GOBIN"/go
というパターンはC:/Go/bin/go
のように解釈され、正確にマッチしてC:/Go/bin/go_bootstrap
に置換されることが保証されます。
- この時点では、
この順序変更により、Windowsパスの正規化が先に行われるため、その後の文字列置換が意図通りに機能し、Windows環境でのビルドスクリプトの信頼性が向上しました。
コアとなるコードの変更箇所
--- a/src/buildscript.sh
+++ b/src/buildscript.sh
@@ -33,8 +33,8 @@ set -e
s/\\$GOBIN/\"$GOBIN\"/g
s/\\$GOROOT/\"$GOROOT\"/g
s/\\$WORK/\"$WORK\"/g
- s;\"\\$GOBIN\"/go;&_bootstrap;g
s;\\\\;/;g
+ s;\"\\$GOBIN\"/go;&_bootstrap;g
s/go_bootstrap-tool/go-tool/g
s;\"\\$GOBIN\"/go-tool;\"$GOROOT\"/bin/go-tool;g
\'
コアとなるコードの解説
変更されたのは、src/buildscript.sh
内の sed
コマンドのブロックです。このブロックは、Goのビルドプロセス中に生成されるスクリプトや設定ファイル内のパスを調整するために使用されます。
元のコードでは、s;\"\\$GOBIN\"/go;&_bootstrap;g
という行が s;\\\\;/;g
の前にありました。
修正後のコードでは、この2行の順序が入れ替わっています。
s;\\\\;/;g
: この行は、入力ストリーム内のすべてのバックスラッシュ\
をスラッシュ/
に置換します。これは、WindowsパスをUnix形式のパスに変換する役割を果たします。s;\"\\$GOBIN\"/go;&_bootstrap;g
: この行は、$GOBIN
環境変数で指定されたパスに続くgo
という文字列を、go_bootstrap
に置換します。例えば、C:/Go/bin/go
をC:/Go/bin/go_bootstrap
に変更します。
この順序変更の重要性は、Windows環境におけるパスの扱いにあります。Windowsではパスの区切り文字としてバックスラッシュが使われますが、シェルスクリプト(特にUnix系ツールである sed
)はスラッシュを期待します。
-
変更前: まず
go
のリネームが行われ、その後にバックスラッシュのスラッシュへの変換が行われます。もし$GOBIN
がC:\Go\bin
のようなパスだった場合、sed
はC:\Go\bin\go
をパターンとして扱おうとします。このとき、バックスラッシュが正規表現の特殊文字として解釈される可能性があり、意図しないマッチングやエラーを引き起こす可能性がありました。 -
変更後: まずバックスラッシュがスラッシュに変換されます。これにより、
C:\Go\bin
はC:/Go/bin
となり、パスがUnix形式に正規化されます。その後のgo
のリネーム処理では、すでに正規化されたパス(例:C:/Go/bin/go
)に対してパターンマッチングが行われるため、正確かつ確実に置換が実行されます。
この修正により、Windows環境で buildscript.sh
が実行される際に、パスの解釈に関する潜在的な問題が解消され、Goのビルドプロセスがより堅牢になりました。
関連リンク
- Go CL 5569092: https://golang.org/cl/5569092 (Goのコードレビューシステムにおけるこの変更のページ)
- Go言語の公式リポジトリ: https://github.com/golang/go
参考にした情報源リンク
- Go言語のビルドプロセスに関するドキュメント:
- https://go.dev/doc/install/source (Goのソースからのインストールに関する公式ドキュメント)
- https://go.dev/doc/contribute (Goへの貢献に関するドキュメント)
- sed コマンドの基本と正規表現:
- https://www.gnu.org/software/sed/manual/sed.html (GNU sed の公式マニュアル)
- https://ja.wikipedia.org/wiki/Sed (Wikipedia: sed)
- Windowsにおけるシェルスクリプト環境 (Cygwin/MSYS2):
- https://www.cygwin.com/ (Cygwin 公式サイト)
- https://www.msys2.org/ (MSYS2 公式サイト)
- Goの環境変数:
- https://go.dev/doc/code (Goのコードの書き方に関する公式ドキュメント)
- https://go.dev/doc/gopath_code (GOPATHに関する公式ドキュメント)
- Goのブートストラッププロセス:
- Goのソースコード内の
src/make.bash
やsrc/make.bat
などのビルドスクリプト。 - Goのコンパイラ開発に関するブログ記事やプレゼンテーション。 (具体的なURLはコミット当時の情報ではないため、一般的な情報源として記載)
- Goのソースコード内の