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

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

このコミットは、Go言語のツールチェーンの一部である cmd/dist における変更です。具体的には、go tool dist env -w コマンドの出力形式を修正し、Windowsバッチファイルが正しく動作するように改行コードにキャリッジリターン (\r) を追加しています。

コミット

commit 792518c65618599853e1f9da3c23d4ba7d2cce9f
Author: Russ Cox <rsc@golang.org>
Date:   Wed Sep 12 12:05:34 2012 -0400

    cmd/dist: emit \r in env -w output
    
    go tool dist env -w is supposed to print a Windows batch file.
    Normally Windows will execute batch files without \r before \n,
    but issue 3060 reports that if the file ends up containing paths
    written in Chinese, Windows 7 cannot execute it without the \r.
    So add the \r.
    
    Fixes #3060.
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/6498120

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

https://github.com/golang/go/commit/792518c65618599853e1f9da3c23d4ba7d2cce9f

元コミット内容

cmd/dist: emit \r in env -w output

このコミットは、go tool dist env -w コマンドの出力にキャリッジリターン (\r) を含めるように変更します。これは、Windowsバッチファイルが特定の条件下(特に中国語のパスを含む場合)で正しく実行されるようにするために必要でした。

変更の背景

go tool dist env -w コマンドは、Goのビルド環境を設定するためのWindowsバッチファイルを出力することを目的としています。通常、Windowsのバッチファイルは改行コードとして \n (LF) のみが存在する場合でも実行できます。しかし、issue 3060で報告された問題によると、出力されるバッチファイルに中国語のパスが含まれている場合、Windows 7では \r (キャリッジリターン) が \n (ラインフィード) の前にないと、そのバッチファイルを正しく実行できないという問題が発生しました。

この問題は、Windowsのコマンドプロンプトやバッチファイルのパーサーが、改行コードの解釈において CRLF (\r\n) を期待していることに起因します。特に非ASCII文字を含むパスの場合、この期待が満たされないと問題が発生する可能性がありました。このコミットは、この互換性の問題を解決し、go tool dist env -w が生成するバッチファイルが、どのような環境やパスの内容であってもWindows上で確実に動作するようにするために行われました。

前提知識の解説

  • cmd/dist: Go言語のソースコードリポジトリ内のディレクトリで、Goのビルドシステムとツールチェーンの構築に関連するコマンドやスクリプトが含まれています。Goのコンパイラや標準ライブラリなどをビルドするために使用されます。
  • go tool dist env -w: go tool dist はGoのビルドシステムを操作するための内部コマンドです。env サブコマンドは環境変数を表示し、-w フラグはWindowsバッチファイル形式で環境変数を設定するコマンドを出力します。例えば、set VAR=VALUE のような形式で出力されます。
  • Windowsバッチファイル: .bat または .cmd 拡張子を持つスクリプトファイルで、Windowsのコマンドプロンプトで実行されます。これらのファイルは、一連のコマンドを自動的に実行するために使用されます。
  • 改行コード (\r, \n, \r\n):
    • \n (LF: Line Feed): Unix系システムで一般的に使用される改行コード。カーソルを次の行の同じ桁に移動させます。
    • \r (CR: Carriage Return): タイプライターのキャリッジリターンに由来し、カーソルを行の先頭に移動させます。
    • \r\n (CRLF): Windows系システムで一般的に使用される改行コード。カーソルを次の行の先頭に移動させます。 Windowsのテキスト処理やコマンドプロンプトは、歴史的に CRLF を標準の改行コードとして扱ってきました。LF のみの場合でも多くの場合で問題なく動作しますが、特定の状況や古いシステム、あるいは非ASCII文字の扱いにおいて、CRLF が必須となることがあります。
  • Issue 3060: GoプロジェクトのIssueトラッカーで報告されたバグです。このコミットメッセージに記載されている通り、中国語のパスを含むバッチファイルがWindows 7で実行できない問題が報告されました。

技術的詳細

この変更の核心は、go tool dist env -w コマンドが環境変数を設定する際に使用するフォーマット文字列に \r を追加することです。

元のコードでは、Windowsバッチファイル形式の出力を生成するために set %s=%s\n というフォーマット文字列を使用していました。これは、環境変数名と値の後に \n (LF) のみを付加することを意味します。

変更後、このフォーマット文字列は set %s=%s\r\n となりました。これにより、出力される各行の末尾に \r (CR) と \n (LF) の両方が含まれるようになります。これは、Windowsの標準的な改行コードである CRLF に準拠します。

この修正により、Windows 7のコマンドプロンプトがバッチファイルを解析する際に、特に中国語のようなマルチバイト文字を含むパスが正しく認識され、コマンドが期待通りに実行されるようになります。これは、Windowsのバッチファイルパーサーが、行の終端を正確に識別するために \r の存在を必要とする場合があるためです。特に、非ASCII文字が絡むと、文字エンコーディングと改行コードの組み合わせが複雑な問題を引き起こすことがあります。この変更は、より堅牢なWindows互換性を提供します。

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

変更は src/cmd/dist/build.c ファイルの1箇所のみです。

--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -1352,7 +1352,7 @@ cmdenv(int argc, char **argv)
 		vflag++;
 		break;
 	case 'w':
-		format = "set %s=%s\n";
+		format = "set %s=%s\r\n";
 		break;
 	default:
 		usage();

コアとなるコードの解説

src/cmd/dist/build.c は、Goのビルドプロセスにおける様々なユーティリティ関数を含むC言語のソースファイルです。このファイル内の cmdenv 関数は、go tool dist env コマンドの処理を担当しています。

cmdenv 関数内で、コマンドライン引数に応じて異なる処理が分岐しています。case 'w': の部分は、-w フラグが指定された場合の処理です。このフラグは、Windowsバッチファイル形式で環境変数を設定する文字列を出力することを意味します。

変更前は、format 変数に set %s=%s\n という文字列が代入されていました。これは、printf のような関数で使用されるフォーマット文字列で、%s の部分に環境変数名と値が挿入され、その後に \n (LF) が続くことを示します。

変更後、format 変数には set %s=%s\r\n が代入されます。これにより、出力される各行の末尾に \r (CR) と \n (LF) の両方が含まれるようになり、Windowsの標準的な改行コードである CRLF に準拠するようになります。この小さな変更が、Windows環境でのバッチファイルの互換性を大幅に向上させました。

関連リンク

  • Go言語のIssueトラッカー: https://github.com/golang/go/issues (Issue 3060は古いIssueであり、直接リンクを見つけるのは難しい場合がありますが、GoのIssueトラッカーで過去のIssueを検索できます。)
  • Go言語のコードレビューシステム (Gerrit): https://go-review.googlesource.com/ (コミットメッセージに記載されている https://golang.org/cl/6498120 は、このGerritシステムへのリンクです。)

参考にした情報源リンク

  • コミットメッセージ自体
  • Go言語のソースコード (src/cmd/dist/build.c)
  • Windowsの改行コードに関する一般的な知識
  • バッチファイルの動作に関する一般的な知識
  • Go言語のIssueトラッカーの仕組みに関する一般的な知識
  • Go言語のビルドシステムに関する一般的な知識