[インデックス 10944] ファイルの概要
このコミットは、Go言語のコマンドラインツールである cmd/go
が、Goコンパイラ (gc
) に渡す追加のフラグを定義する環境変数 $GCFLAGS
を尊重するように変更するものです。これにより、ユーザーはビルド時にコンパイラの挙動をより細かく制御できるようになります。
コミット
commit 25c8014ed905a41a7f060efeea9a4c289c0aa0de
Author: Russ Cox <rsc@golang.org>
Date: Wed Dec 21 09:04:34 2011 -0500
cmd/go: respect $GCFLAGS
R=lvd
CC=golang-dev
https://golang.org/cl/5500060
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/25c8014ed905a41a7f060efeea9a4c289c0aa0de
元コミット内容
cmd/go: respect $GCFLAGS
このコミットは、go
コマンドが $GCFLAGS
環境変数を尊重するように変更します。
変更の背景
Go言語のビルドシステムにおいて、コンパイラ (gc
) に特定のオプションを渡したい場合があります。例えば、デバッグ情報の詳細度を変更したり、最適化の挙動を調整したり、特定の警告を抑制したりする際に、これらのオプションが必要となります。
以前の go
コマンドは、このようなコンパイラオプションを直接指定するメカニズムが不足していました。開発者が go build
や go install
のようなコマンドを使用する際に、コンパイラにカスタムフラグを渡すことができないため、ビルドプロセスの柔軟性が制限されていました。
このコミットは、標準的な環境変数である $GCFLAGS
を利用することで、この問題を解決します。$GCFLAGS
に設定された値が go
コマンドによって読み取られ、Goコンパイラ (gc
) の呼び出し時にそのフラグが自動的に追加されるようになります。これにより、ユーザーは go
コマンドのラッパーを記述することなく、コンパイラの挙動を簡単にカスタマイズできるようになりました。
前提知識の解説
- Go言語のビルドシステム: Go言語は、
go build
やgo install
といったコマンドを通じて、ソースコードのコンパイル、リンク、実行可能ファイルの生成を行います。これらのコマンドは内部的にGoコンパイラ (gc
) やアセンブラ (go tool asm
)、リンカ (go tool link
) などのツールを呼び出します。 gc
(Go Compiler): Go言語の公式コンパイラです。Goのソースコードを機械語に変換します。gc
には、デバッグ、最適化、コード生成などに関する様々なコマンドラインフラグが存在します。- 環境変数
$GCFLAGS
: Goのビルドシステムで認識される環境変数の一つです。この変数には、Goコンパイラ (gc
) に渡したい追加のフラグをスペース区切りで指定します。例えば、GCFLAGS="-N -l"
と設定すると、コンパイラの最適化を無効にし(-N
)、インライン化を無効にします(-l
)。これはデバッグ時に非常に役立ちます。 src/cmd/go/build.go
:go
コマンドのビルドロジックを定義しているGo言語のソースファイルです。このファイルは、パッケージの依存関係の解決、コンパイル順序の決定、コンパイラやリンカの呼び出しなど、ビルドプロセスの中心的な役割を担っています。
技術的詳細
このコミットの技術的な核心は、src/cmd/go/build.go
内で $GCFLAGS
環境変数を読み込み、その値をGoコンパイラ (gc
) の呼び出し引数に動的に追加することにあります。
-
builder
構造体へのフィールド追加:builder
構造体は、Goのビルドプロセス全体を管理する主要なオブジェクトです。この構造体にgcflags []string
という新しいフィールドが追加されました。これは、$GCFLAGS
環境変数から読み込まれたコンパイラフラグを文字列スライスの形で保持するためのものです。 -
init
メソッドでの環境変数読み込み:builder
のinit
メソッドは、ビルドプロセスの初期化時に呼び出されます。このメソッド内でos.Getenv("GCFLAGS")
を使用して$GCFLAGS
環境変数の値を取得し、strings.Fields
を使ってスペースで区切られた文字列を個々のフラグに分割し、b.gcflags
フィールドに格納します。 -
gc
メソッドでのフラグ追加:gc
メソッドは、Goコンパイラ (gc
) を呼び出してGoソースファイルをコンパイルする役割を担っています。このメソッド内で、gc
コマンドに渡す引数リスト (args
) に、b.gcflags
に格納されているすべてのフラグがappend
されます。これにより、$GCFLAGS
で指定されたフラグが実際のコンパイルコマンドに反映されるようになります。 -
gccCmd
メソッドの変更:gccCmd
メソッドは、CGO(C言語との連携)に関連するgcc
コマンドの引数を構築します。このコミットでは、Windows環境でのgcc
の挙動を考慮し、-fPIC
フラグの追加ロジックが変更されました。Windowsでは-fPIC
が不要または警告を出す場合があるため、OSがWindowsでない場合にのみ-fPIC
を追加するように修正されています。これは$GCFLAGS
とは直接関係ありませんが、同じコミット内で関連するビルドロジックの改善として行われています。
これらの変更により、go
コマンドは $GCFLAGS
を透過的に処理し、ユーザーが指定したコンパイラフラグをビルドプロセスに組み込むことが可能になりました。
コアとなるコードの変更箇所
src/cmd/go/build.go
ファイルにおける変更点は以下の通りです。
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -139,6 +139,7 @@ type builder struct {\n goos string // the $GOOS\n gobin string // the $GOBIN\n exe string // the executable suffix - "" or ".exe"\n+ gcflags []string // additional flags for Go compiler\n actionCache map[cacheKey]*action // a cache of already-constructed actions\n mkdirCache map[string]bool // a cache of created directories\n \n@@ -202,6 +203,7 @@ func (b *builder) init(aflag, nflag, xflag bool) {\n if b.goos == "windows" {\n b.exe = ".exe"\n }\n+ b.gcflags = strings.Fields(os.Getenv("GCFLAGS"))\n \n b.arch, err = build.ArchChar(b.goarch)\n if err != nil {\n@@ -836,6 +838,7 @@ func mkAbs(dir, f string) string {\n // to generate the named output file. \n func (b *builder) gc(p *Package, ofile string, gcargs, importArgs []string, gofiles []string) error {\n args := []string{b.arch + "g", "-o", ofile}\n+\targs = append(args, b.gcflags...)\n args = append(args, gcargs...)\n args = append(args, importArgs...)\n for _, f := range gofiles {\n@@ -890,7 +893,13 @@ func (b *builder) gccld(p *Package, out string, flags []string, obj []string) er\n // gccCmd returns a gcc command line ending with args\n func (b *builder) gccCmd(objdir string, flags []string, args ...string) []string {\n // TODO: HOST_CC?\n-\ta := []string{"gcc", "-I", objdir, "-g", "-fPIC", "-O2"}\n+\ta := []string{"gcc", "-I", objdir, "-g", "-O2"}\n+\n+\t// Definitely want -fPIC but on Windows gcc complains\n+\t// "-fPIC ignored for target (all code is position independent)"\n+\tif b.goos != "windows" {\n+\t\ta = append(a, "-fPIC")\n+\t}\n \tswitch b.arch {\n \tcase "8":\n \t\ta = append(a, "-m32")\n```
## コアとなるコードの解説
1. **`type builder struct { ... }` への `gcflags` フィールド追加**:
```go
+ gcflags []string // additional flags for Go compiler
```
`builder` 構造体に `gcflags` という新しいフィールドが追加されました。これは、`$GCFLAGS` 環境変数から取得したコンパイラフラグを文字列スライスとして保持するためのものです。これにより、ビルドプロセス全体でこれらのフラグにアクセスできるようになります。
2. **`func (b *builder) init(...)` 内での `$GCFLAGS` 読み込み**:
```go
+ b.gcflags = strings.Fields(os.Getenv("GCFLAGS"))
```
`builder` の初期化時に、`os.Getenv("GCFLAGS")` を呼び出して環境変数 `$GCFLAGS` の値を取得します。`strings.Fields` は、取得した文字列をスペースで分割し、個々のフラグを文字列スライスとして `b.gcflags` に代入します。これにより、`$GCFLAGS` に設定されたすべてのフラグがビルドシステムに認識されます。
3. **`func (b *builder) gc(...)` 内でのフラグ適用**:
```go
+ args = append(args, b.gcflags...)
```
Goコンパイラ (`gc`) を呼び出す `gc` メソッド内で、コンパイラに渡す引数リスト `args` に、`b.gcflags` の内容が追加されます。`...` はスライスを展開して個々の要素を引数として渡すGoの構文です。これにより、`$GCFLAGS` で指定されたすべてのフラグが `gc` コマンドの実行時に適用されます。
4. **`func (b *builder) gccCmd(...)` 内の `-fPIC` 修正**:
```go
- a := []string{"gcc", "-I", objdir, "-g", "-fPIC", "-O2"}
+ a := []string{"gcc", "-I", objdir, "-g", "-O2"}
+
+ // Definitely want -fPIC but on Windows gcc complains
+ // "-fPIC ignored for target (all code is position independent)"
+ if b.goos != "windows" {
+ a = append(a, "-fPIC")
+ }
```
この変更は、CGOビルド時に `gcc` に渡される `-fPIC` フラグの扱いを改善するものです。Windows環境では `-fPIC` が不要であり、警告を発生させる可能性があるため、`b.goos != "windows"` の条件を追加し、Windows以外のOSでのみ `-fPIC` を追加するように修正されました。これは `$GCFLAGS` の機能とは直接関係ありませんが、ビルドシステムの堅牢性を高めるための改善です。
これらの変更により、Goのビルドプロセスは `$GCFLAGS` を介したコンパイラオプションのカスタマイズをサポートし、より柔軟な開発ワークフローを提供できるようになりました。
## 関連リンク
* Go Change-ID: [https://golang.org/cl/5500060](https://golang.org/cl/5500060)
## 参考にした情報源リンク
* Go言語の公式ドキュメント (Go Compiler Flags, Environment Variables)
* Go言語のソースコード (`src/cmd/go/build.go`)
* Go言語の環境変数に関する一般的な知識
* `strings.Fields` および `os.Getenv` のGo標準ライブラリドキュメント
* `append` 関数のGo言語のドキュメント
* `-fPIC` フラグに関するGCCのドキュメント (Position-Independent Code)