[インデックス 11130] ファイルの概要
このコミットは、Go言語のビルドシステムにおけるgo/build
パッケージの変更に関するものです。具体的には、#cgo
ディレクティブ内で使用されるフラグにおいて、コロン(:
)文字が許可されるように修正されました。これにより、Windows環境でcgo
を使用する際に、C:/foo
のようなドライブレターを含むパスを-I
(インクルードパス)フラグとして正しく指定できるようになりました。
コミット
commit fb036824df95f5d127064b3897e3e74fb9691b29
Author: Russ Cox <rsc@golang.org>
Date: Thu Jan 12 11:05:54 2012 -0800
go/build: allow colon in #cgo flags
This makes it possible to say -I c:/foo on Windows.
Fixes #2683 comment #3.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5540043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/fb036824df95f5d127064b3897e3e74fb9691b29
元コミット内容
go/build
パッケージにおいて、#cgo
ディレクティブのフラグにコロンを許可する変更。これにより、Windows環境で-I c:/foo
のようなパス指定が可能になる。Issue 2683のコメント3を修正。
変更の背景
Go言語のcgo
機能は、GoプログラムからC言語のコードを呼び出すための重要なメカニズムです。#cgo
ディレクティブは、Cコンパイラやリンカに渡す追加のフラグ(例: インクルードパス、ライブラリパス)を指定するために使用されます。
このコミットが行われる前は、go/build
パッケージ内のsafeBytes
という変数が、#cgo
フラグとして許可される文字のセットを定義していました。このセットにはコロン(:
)が含まれていませんでした。
Windowsオペレーティングシステムでは、ファイルパスにドライブレター(例: C:
、D:
)が含まれることが一般的です。例えば、特定のヘッダーファイルがC:\Program Files\MyLib\include
にある場合、Cコンパイラには-I C:\Program Files\MyLib\include
のようなフラグを渡す必要があります。しかし、safeBytes
にコロンが含まれていなかったため、#cgo CFLAGS: -I C:/path/to/include
のように指定しようとすると、go/build
パッケージがこれを不正な文字として認識し、ビルドエラーが発生していました。
この制限は、特にWindows環境でcgo
を利用して外部Cライブラリと連携する開発者にとって大きな障壁となっていました。このコミットは、この問題を解決し、Windows環境でのcgo
の使い勝手を向上させることを目的としています。
前提知識の解説
go/build
パッケージ: Go言語の標準ライブラリの一部で、Goのソースコードを解析し、パッケージの依存関係を解決し、ビルドに必要な情報を収集する役割を担います。go build
コマンドの基盤となるパッケージの一つです。cgo
: Go言語の機能の一つで、GoプログラムからC言語の関数を呼び出したり、C言語のコードをGoプログラムに組み込んだりするためのメカニズムです。C言語のライブラリを利用する際に不可欠です。#cgo
ディレクティブ:cgo
を使用するGoソースファイル内に記述される特殊なコメント行です。Cコンパイラやリンカに渡すフラグ(例:CFLAGS
、LDFLAGS
)や、GoとCの間で共有される型定義などを指定します。- 例:
#cgo CFLAGS: -I/usr/local/include
は、Cコンパイラに/usr/local/include
をインクルードパスとして追加するよう指示します。
- 例:
-I
フラグ (Cコンパイラ): C/C++コンパイラ(GCC, Clangなど)において、インクルードファイルの検索パスを追加するために使用されるオプションです。例えば、-I/path/to/headers
と指定すると、コンパイラは/path/to/headers
ディレクトリ内もヘッダーファイルを検索するようになります。- Windowsのファイルパス形式: Windowsでは、ファイルパスは通常、ドライブレター(例:
C:
)から始まり、ディレクトリの区切り文字としてバックスラッシュ(\
)またはスラッシュ(/
)が使用されます。例えば、C:\Users\User\Documents
やC:/Users/User/Documents
のように記述されます。
技術的詳細
go/build
パッケージは、Goのソースファイルを解析する際に、#cgo
ディレクティブを特別に処理します。この処理の一環として、#cgo
フラグとして指定された文字列が、特定の安全な文字セットのみで構成されているかを検証するロジックが存在しました。これは、不正な文字がコマンドライン引数としてシェルに渡されることによるセキュリティリスクや、予期せぬ動作を防ぐための措置と考えられます。
具体的には、src/pkg/go/build/dir.go
ファイル内にsafeBytes
というバイトスライスが定義されており、これが許可される文字のホワイトリストとして機能していました。そして、safeName
という関数が、与えられた文字列がこのsafeBytes
に含まれる文字のみで構成されているかをチェックしていました。
変更前は、safeBytes
には以下の文字が含まれていました。
+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz
このリストにはコロン(:
)が含まれていなかったため、Windowsのドライブレターを含むパス(例: C:/path/to/include
)が#cgo CFLAGS: -I C:/path/to/include
のように指定されると、safeName
関数がコロンを不正な文字と判断し、ビルドプロセスがエラーとなっていました。
このコミットでは、safeBytes
にコロン文字を追加することで、この問題を解決しています。これにより、safeName
関数がコロンを含む文字列も「安全」と判断するようになり、Windowsパスの指定が可能になりました。
コアとなるコードの変更箇所
変更はsrc/pkg/go/build/dir.go
ファイルの一箇所のみです。
--- a/src/pkg/go/build/dir.go
+++ b/src/pkg/go/build/dir.go
@@ -476,7 +476,7 @@ func (ctxt *Context) saveCgo(filename string, di *DirInfo, cg *ast.CommentGroup)\
return nil
}
-var safeBytes = []byte("+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz")
+var safeBytes = []byte("+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:")
func safeName(s string) bool {
if s == "" {
コアとなるコードの解説
変更された行は、safeBytes
というグローバル変数(バイトスライス)の定義です。
-
変更前:
var safeBytes = []byte("+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz")
このバイトスライスは、#cgo
ディレクティブのフラグとして許可される文字の集合を定義しています。この文字列には、英数字、一部の記号(+
,-
,.
,,
,/
,=
)、アンダースコアが含まれていますが、コロン(:
)は含まれていませんでした。 -
変更後:
var safeBytes = []byte("+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:")
変更点として、文字列の末尾にコロン(:
)が追加されました。これにより、safeBytes
がコロンを許可する文字として認識するようになります。
このsafeBytes
変数は、safeName
という関数によって利用されます。safeName
関数は、#cgo
フラグとして渡された文字列の各バイトがsafeBytes
に含まれているかをチェックします。もし含まれていない文字があれば、その文字列は「安全でない」と判断され、エラーとなります。
コロンがsafeBytes
に追加されたことで、safeName
関数はC:/path/to/include
のような文字列に含まれるコロンを正当な文字として扱い、#cgo
フラグの検証が成功するようになります。これにより、Windows環境でのcgo
の利用がスムーズになりました。
関連リンク
- Go Issue 2683: https://github.com/golang/go/issues/2683 このコミットが修正した具体的な問題に関する議論が記載されています。特にコメント3がこの変更の直接的なトリガーとなっています。
- Go Code Review 5540043: https://golang.org/cl/5540043 この変更がGoのコードレビューシステム(Gerrit)でどのようにレビューされたかを確認できます。
参考にした情報源リンク
- Go言語公式ドキュメント - cgo: https://pkg.go.dev/cmd/cgo
cgo
の基本的な使い方や#cgo
ディレクティブに関する詳細な情報が記載されています。 - Go言語公式ドキュメント - go/buildパッケージ: https://pkg.go.dev/go/build
go/build
パッケージのAPIドキュメントです。 - Windowsのファイルパス: 一般的なWindowsのファイルパスの構造に関する情報源(例: Microsoft Learnのドキュメントなど)。
- Cコンパイラの
-I
オプション: GCCやClangなどのCコンパイラのドキュメントで、-I
オプションの使われ方に関する情報。