[インデックス 16361] ファイルの概要
このコミットは、Go言語のツールチェインにおけるLDFLAGS
の取り扱いを修正し、特にmacOS (Darwin) 環境でのmisc/cgo/testso
テストの実行を可能にするものです。具体的には、cgo
が共有ライブラリをリンクする際に、LDFLAGS
から不要なフラグ(例: -l
、-framework
、共有ライブラリのファイル名)を適切にフィルタリングするロジックを改善し、また、misc/cgo/testso
テストスクリプトをDarwin向けに調整しています。これにより、クロスプラットフォームでのcgo
の挙動の一貫性とテストカバレッジが向上します。
コミット
commit bea7b5187283cf73638332e5051c8e9333ccf4dd
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Wed May 22 00:32:03 2013 +0800
cmd/go: fix LDFLAGS handling, enable misc/cgo/testso on Darwin
Fixes #5479.
R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/9416047
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/bea7b5187283cf73638332e5051c8e9333ccf4dd
元コミット内容
このコミットは、Go言語のコマンドラインツール(cmd/go
)がLDFLAGS
(リンカフラグ)を処理する方法を修正し、さらにmisc/cgo/testso
というテストスイートをmacOS (Darwin) 上で実行できるようにするものです。この変更は、GoのIssue #5479を解決することを目的としています。
変更の背景
この変更の背景には、Goのcgo
機能が外部のCライブラリとリンクする際のLDFLAGS
の処理に問題があったことが挙げられます。特に、異なるオペレーティングシステム(Linux, FreeBSD, OpenBSD, NetBSD, Darwin, Windowsなど)で共有ライブラリをリンクする際に、LDFLAGS
の指定方法が微妙に異なるため、cgo
がこれらのフラグを適切に解釈・フィルタリングできないケースがありました。
Issue #5479は、cgo
がLDFLAGS
を処理する際に、リンカに渡すべきではない情報(例えば、共有ライブラリのファイル名自体や、-l
フラグの後に続くライブラリ名)を誤って渡してしまう問題が報告されていました。これにより、ビルドエラーが発生したり、意図しないリンカの挙動を引き起こしたりする可能性がありました。
また、misc/cgo/testso
は、cgo
が共有ライブラリを正しく扱えるかを検証するためのテストですが、Darwin環境では特定のリンカフラグ(-undefined suppress -flat_namespace
)が必要であるにもかかわらず、それが考慮されていなかったため、テストがスキップされていました。このコミットは、これらの問題を解決し、cgo
の堅牢性とクロスプラットフォーム互換性を向上させることを目的としています。
前提知識の解説
cgo
cgo
は、GoプログラムからC言語のコードを呼び出すためのGoの機能です。Goのソースファイル内にCのコードを直接記述したり、既存のCライブラリをリンクしたりすることができます。cgo
を使用すると、Goのビルドプロセス中にCコンパイラとリンカが呼び出され、GoとCのコードが結合されます。
LDFLAGS
(Linker Flags)
LDFLAGS
は、リンカに渡されるオプション(フラグ)のセットです。リンカは、コンパイルされたオブジェクトファイルとライブラリを結合して実行可能ファイルを生成するツールです。LDFLAGS
は、リンカがどのライブラリを検索するか(-L
)、どのライブラリをリンクするか(-l
)、共有ライブラリのパス(-rpath
など)、その他のリンカの挙動を制御するために使用されます。
共有ライブラリ
共有ライブラリは、複数のプログラムで共有されるコードの集合体です。これにより、ディスクスペースとメモリの使用量を節約できます。
- Linux:
.so
(Shared Object) 拡張子を使用します。例:libcgosotest.so
- macOS (Darwin):
.dylib
(Dynamic Library) 拡張子を使用します。例:libcgosotest.dylib
- Windows:
.dll
(Dynamic Link Library) 拡張子を使用します。例:libcgosotest.dll
LD_LIBRARY_PATH
/ DYLD_LIBRARY_PATH
これらは環境変数で、プログラムが実行時に共有ライブラリを検索するパスを指定するために使用されます。
LD_LIBRARY_PATH
: LinuxなどのUnix系システムで使用されます。DYLD_LIBRARY_PATH
: macOS (Darwin) で使用されます。
これらの環境変数を設定することで、システムが標準で検索するパス以外の場所に置かれた共有ライブラリを見つけることができます。
go env CC
/ go env GOGCCFLAGS
go env CC
: Goツールチェインが使用するCコンパイラのパスを出力します。通常はgcc
やclang
などです。go env GOGCCFLAGS
: GoツールチェインがCコンパイラに渡すデフォルトのフラグを出力します。これには、最適化フラグやインクルードパスなどが含まれることがあります。
Darwin特有のリンカフラグ
-undefined suppress
: リンカが未定義シンボル(参照されているが定義されていない関数や変数)を見つけてもエラーを抑制し、警告として扱うように指示します。共有ライブラリをビルドする際に、すべてのシンボルがそのライブラリ内で定義されている必要がない場合に便利です。-flat_namespace
: リンカがシンボル解決のために単一のグローバルな名前空間を使用するように指示します。これは、動的ライブラリが他のライブラリのシンボルを直接参照する場合に役立ちます。
技術的詳細
このコミットは、主に以下の3つのファイルに変更を加えています。
-
misc/cgo/testso/cgoso.go
:#cgo LDFLAGS
ディレクティブの記述方法が変更されました。以前は単一の-L. -lcgosotest
という記述でしたが、各OS(linux, freebsd, openbsd, netbsd, darwin, windows)ごとに異なるLDFLAGS
の記述例が追加されました。- これは、
cmd/go
がLDFLAGS
を解析する際の堅牢性をテストするためです。特に、-l
とライブラリ名がスペースで区切られている場合(-l cgosotest
)や、共有ライブラリのファイル名が直接指定されている場合(libcgosotest.so
、libcgosotest.dylib
、libcgosotest.dll
)など、様々な形式に対応できることを確認します。
-
misc/cgo/testso/test.bash
:- このシェルスクリプトは、
cgo
の共有ライブラリテストを実行するためのものです。 - Darwin (macOS) 向けの条件分岐が追加されました。
$(uname)
がDarwin
の場合、args
変数に-undefined suppress -flat_namespace
が設定されます。これらは、macOSで共有ライブラリをビルドする際に必要なリンカフラグです。dyld_envvar
がDYLD_LIBRARY_PATH
に設定されます。これはmacOSで共有ライブラリの検索パスを指定するための環境変数です。ext
変数がdylib
に設定されます。これはmacOSの共有ライブラリの拡張子です。
- 共有ライブラリのビルドコマンドが変更され、
$args
が追加されました。これにより、Darwin環境で適切なリンカフラグが渡されるようになります。 - 共有ライブラリのファイル名が
libcgosotest.$ext
(例:libcgosotest.dylib
)として動的に決定されるようになりました。 LD_LIBRARY_PATH=. ./main
の行がeval "$dyld_envvar"=. ./main
に変更されました。これにより、OSに応じて適切な環境変数(LD_LIBRARY_PATH
またはDYLD_LIBRARY_PATH
)が使用されるようになります。- テスト後のクリーンアップで、
*.dSYM
ファイル(macOSのデバッグシンボルファイル)も削除されるようになりました。
- このシェルスクリプトは、
-
src/cmd/go/build.go
:cgo
のビルドプロセスにおいて、LDFLAGS
からリンカに渡すべきではないフラグをフィルタリングするロジックが改善されました。- 以前は、
-l
で始まるフラグと、Darwin環境での-framework X
のみをフィルタリングしていました。 - 新しいロジックでは、
switch
文を使用して、より詳細なフィルタリングが行われます。-l
または-l somelib
のスキップ:-l
フラグ自体、またはスペースで区切られたライブラリ名(例:-l cgosotest
)をスキップします。- Darwinでの
-framework X
のスキップ: 以前と同様に、-framework
とその後のフレームワーク名をスキップします。 - 共有ライブラリファイル名(
.dylib
,.so
,.dll
)のスキップ:LDFLAGS
に直接共有ライブラリのファイル名が含まれている場合(例:libcgosotest.so
)もスキップするようになりました。これは、リンカがライブラリを検索する際に、ファイル名ではなく-l
フラグとライブラリ名を使用するため、ファイル名自体をLDFLAGS
として渡すのは不適切だからです。
- このフィルタリングにより、
bareLDFLAGS
(リンカに直接渡されるべきフラグ)には、リンカが適切に処理できる情報のみが含まれるようになります。
-
src/run.bash
:misc/cgo/testso
テストの実行条件から、[ "$GOHOSTOS" == darwin ] ||
という行が削除されました。これは、以前はDarwin環境ではこのテストがスキップされていたことを意味します。このコミットにより、Darwinでもテストが実行されるようになったため、このスキップ条件が不要になりました。
コアとなるコードの変更箇所
misc/cgo/testso/cgoso.go
--- a/misc/cgo/testso/cgoso.go
+++ b/misc/cgo/testso/cgoso.go
@@ -5,7 +5,15 @@
package cgosotest
/*
-#cgo LDFLAGS: -L. -lcgosotest
+// intentionally write the same LDFLAGS differently
+// to test correct handling of LDFLAGS.
+#cgo linux LDFLAGS: -L. -lcgosotest
+#cgo freebsd LDFLAGS: -L. -l cgosotest
+#cgo openbsd LDFLAGS: -L. -l cgosotest
+#cgo netbsd LDFLAGS: -L. libcgosotest.so
+#cgo darwin LDFLAGS: -L. libcgosotest.dylib
+#cgo windows LDFLAGS: -L. libcgosotest.dll
+
void init(void);\n void sofunc(void);\n */
misc/cgo/testso/test.bash
--- a/misc/cgo/testso/test.bash
+++ b/misc/cgo/testso/test.bash
@@ -4,7 +4,19 @@
# license that can be found in the LICENSE file.
set -e
-$(go env CC) $(go env GOGCCFLAGS) -shared -o libcgosotest.so cgoso_c.c
+\n+args=\n+dyld_envvar=LD_LIBRARY_PATH\n+ext=so\n+if [ "$(uname)" == "Darwin" ]; then\n+\targs="-undefined suppress -flat_namespace"\n+\tdyld_envvar=DYLD_LIBRARY_PATH\n+\text=dylib\n+fi\n+\n+dylib=libcgosotest.$ext\n+$(go env CC) $(go env GOGCCFLAGS) -shared $args -o $dylib cgoso_c.c
go build main.go
-LD_LIBRARY_PATH=. ./main
-rm -f libcgosotest.so main
+\n+eval "$dyld_envvar"=. ./main\n+rm -rf $dylib main *.dSYM
src/cmd/go/build.go
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -1855,14 +1855,24 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,\
var linkobj []string
var bareLDFLAGS []string
-\t// filter out -lsomelib, and -framework X if on Darwin
+\t// filter out -lsomelib, -l somelib, *.{so,dll,dylib}, and (on Darwin) -framework X
for i := 0; i < len(cgoLDFLAGS); i++ {\n \t\tf := cgoLDFLAGS[i]\n-\t\tif !strings.HasPrefix(f, "-l") {\n-\t\t\tif goos == "darwin" && f == "-framework" { // skip the -framework X\n-\t\t\t\ti += 1\n-\t\t\t\tcontinue\n+\t\tswitch {\n+\t\t// skip "-lc" or "-l somelib"\n+\t\tcase strings.HasPrefix(f, "-l"):\n+\t\t\tif f == "-l" {\n+\t\t\t\ti++\n \t\t\t}\n+\t\t// skip "-framework X" on Darwin\n+\t\tcase goos == "darwin" && f == "-framework":\n+\t\t\ti++\n+\t\t// skip "*.{dylib,so,dll}"\n+\t\tcase strings.HasSuffix(f, ".dylib"),\n+\t\t\tstrings.HasSuffix(f, ".so"),\n+\t\t\tstrings.HasSuffix(f, ".dll"):\n+\t\t\tcontinue\n+\t\tdefault:\n \t\t\tbareLDFLAGS = append(bareLDFLAGS, f)\n \t\t}\n \t}\n```
### `src/run.bash`
```diff
--- a/src/run.bash
+++ b/src/run.bash
@@ -104,7 +104,6 @@ esac
[ "$CGO_ENABLED" != 1 ] ||
[ "$GOHOSTOS" == windows ] ||
-[ "$GOHOSTOS" == darwin ] ||
(xcd ../misc/cgo/testso
./test.bash
) || exit $?\n```
## コアとなるコードの解説
### `misc/cgo/testso/cgoso.go`の変更
この変更は、`cgo`の`LDFLAGS`パーサーの堅牢性をテストするために、意図的に様々な形式の`LDFLAGS`指定を追加しています。これにより、Goのビルドシステムが異なるOSやリンカの挙動に対応できるかを確認します。特に、`-l`フラグの後にスペースがある場合や、共有ライブラリのファイル名が直接指定されている場合など、Goがこれらのバリエーションを正しく処理できることを保証します。
### `misc/cgo/testso/test.bash`の変更
このスクリプトの変更は、`misc/cgo/testso`テストをmacOS (Darwin) 環境で実行できるようにするためのものです。
* `if [ "$(uname)" == "Darwin" ]`ブロックにより、macOS特有のリンカフラグ(`-undefined suppress -flat_namespace`)が`args`変数に設定されます。これらのフラグは、macOSで共有ライブラリをビルドする際に、未定義シンボルのエラーを抑制し、シンボル解決に単一のグローバル名前空間を使用するために必要です。
* `dyld_envvar`が`DYLD_LIBRARY_PATH`に設定され、`eval "$dyld_envvar"=. ./main`によって、macOSで共有ライブラリの検索パスを正しく設定して実行可能ファイルを起動します。これにより、テスト対象の共有ライブラリが正しくロードされるようになります。
* `ext`変数が`dylib`に設定されることで、macOSの共有ライブラリの命名規則(`.dylib`)に準拠したファイルが生成・参照されるようになります。
これらの変更により、以前はスキップされていたDarwin環境での`cgo`共有ライブラリテストが実行可能になり、Goのクロスプラットフォーム互換性の検証が強化されます。
### `src/cmd/go/build.go`の変更
この変更は、`cmd/go`が`cgo`の`LDFLAGS`を処理する際のフィルタリングロジックを大幅に改善するものです。
* 以前のロジックは単純な`if`文でしたが、新しいロジックは`switch`文を使用し、より多様な`LDFLAGS`のパターンに対応しています。
* 特に重要なのは、`strings.HasSuffix(f, ".dylib")`, `strings.HasSuffix(f, ".so")`, `strings.HasSuffix(f, ".dll")`という条件が追加されたことです。これは、`LDFLAGS`に共有ライブラリのファイル名自体(例: `libcgosotest.so`)が含まれている場合に、それをリンカに渡さないようにするためのものです。リンカは通常、`-l`フラグとライブラリ名(例: `-lcgosotest`)を期待しており、ファイル名自体を渡すとエラーになるか、意図しない挙動を引き起こす可能性があります。
* この改善されたフィルタリングにより、`cgo`は様々なOSやリンカの挙動に対してより堅牢になり、ビルドの安定性が向上します。`bareLDFLAGS`には、リンカが正しく解釈できる必要最小限のフラグのみが含まれるようになります。
### `src/run.bash`の変更
この変更は、`src/run.bash`スクリプトから`[ "$GOHOSTOS" == darwin ] ||`という行を削除するものです。これは、以前はGoのテストスイートの一部として`misc/cgo/testso`がDarwin環境では実行されないように明示的にスキップされていたことを意味します。`misc/cgo/testso/test.bash`と`src/cmd/go/build.go`の変更により、Darwinでの`cgo`共有ライブラリのビルドとテストが正しく機能するようになったため、このスキップ条件が不要になりました。これにより、GoのテストカバレッジがDarwin環境でも完全になります。
## 関連リンク
* GitHubコミットページ: [https://github.com/golang/go/commit/bea7b5187283cf73638332e5051c8e9333ccf4dd](https://github.com/golang/go/commit/bea7b5187283cf73638332e5051c8e9333ccf4dd)
* Go Issue #5479: [https://golang.org/issue/5479](https://golang.org/issue/5479)
* Go CL 9416047: [https://golang.org/cl/9416047](https://golang.org/cl/9416047)
## 参考にした情報源リンク
* Go言語公式ドキュメント: `cgo` (GoのバージョンによってドキュメントのURLが異なる場合がありますが、`go doc cmd/cgo`などで参照できます)
* GCC リンカオプション: [https://gcc.gnu.org/onlinedocs/gcc/Link Options.html](https://gcc.gnu.org/onlinedocs/gcc/Link Options.html)
* macOS リンカオプション (man ld): `man ld` (macOSのターミナルで実行)
* 共有ライブラリの概念 (OSによって異なるため、各OSのドキュメントを参照)
* `LD_LIBRARY_PATH`と`DYLD_LIBRARY_PATH`に関する情報 (各OSのドキュメントやオンラインリソース)
# [インデックス 16361] ファイルの概要
このコミットは、Go言語のツールチェインにおける`LDFLAGS`の取り扱いを修正し、特にmacOS (Darwin) 環境での`misc/cgo/testso`テストの実行を可能にするものです。具体的には、`cgo`が共有ライブラリをリンクする際に、`LDFLAGS`から不要なフラグ(例: `-l`、`-framework`、共有ライブラリのファイル名)を適切にフィルタリングするロジックを改善し、また、`misc/cgo/testso`テストスクリプトをDarwin向けに調整しています。これにより、クロスプラットフォームでの`cgo`の挙動の一貫性とテストカバレッジが向上します。
## コミット
commit bea7b5187283cf73638332e5051c8e9333ccf4dd Author: Shenghou Ma minux.ma@gmail.com Date: Wed May 22 00:32:03 2013 +0800
cmd/go: fix LDFLAGS handling, enable misc/cgo/testso on Darwin
Fixes #5479.
R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/9416047
## GitHub上でのコミットページへのリンク
[https://github.com/golang/go/commit/bea7b5187283cf73638332e5051c8e9333ccf4dd](https://github.com/golang/go/commit/bea7b5187283cf73638332e5051c8e9333ccf4dd)
## 元コミット内容
このコミットは、Go言語のコマンドラインツール(`cmd/go`)が`LDFLAGS`(リンカフラグ)を処理する方法を修正し、さらに`misc/cgo/testso`というテストスイートをmacOS (Darwin) 上で実行できるようにするものです。この変更は、GoのIssue #5479を解決することを目的としています。
## 変更の背景
この変更の背景には、Goの`cgo`機能が外部のCライブラリとリンクする際の`LDFLAGS`の処理に問題があったことが挙げられます。特に、異なるオペレーティングシステム(Linux, FreeBSD, OpenBSD, NetBSD, Darwin, Windowsなど)で共有ライブラリをリンクする際に、`LDFLAGS`の指定方法が微妙に異なるため、`cgo`がこれらのフラグを適切に解釈・フィルタリングできないケースがありました。
Issue #5479は、`cgo`が`LDFLAGS`を処理する際に、リンカに渡すべきではない情報(例えば、共有ライブラリのファイル名自体や、`-l`フラグの後に続くライブラリ名)を誤って渡してしまう問題が報告されていました。これにより、ビルドエラーが発生したり、意図しないリンカの挙動を引き起こしたりする可能性がありました。
また、`misc/cgo/testso`は、`cgo`が共有ライブラリを正しく扱えるかを検証するためのテストですが、Darwin環境では特定のリンカフラグ(`-undefined suppress -flat_namespace`)が必要であるにもかかわらず、それが考慮されていなかったため、テストがスキップされていました。このコミットは、これらの問題を解決し、`cgo`の堅牢性とクロスプラットフォーム互換性を向上させることを目的としています。
## 前提知識の解説
### `cgo`
`cgo`は、GoプログラムからC言語のコードを呼び出すためのGoの機能です。Goのソースファイル内にCのコードを直接記述したり、既存のCライブラリをリンクしたりすることができます。`cgo`を使用すると、Goのビルドプロセス中にCコンパイラとリンカが呼び出され、GoとCのコードが結合されます。
### `LDFLAGS` (Linker Flags)
`LDFLAGS`は、リンカに渡されるオプション(フラグ)のセットです。リンカは、コンパイルされたオブジェクトファイルとライブラリを結合して実行可能ファイルを生成するツールです。`LDFLAGS`は、リンカがどのライブラリを検索するか(`-L`)、どのライブラリをリンクするか(`-l`)、共有ライブラリのパス(`-rpath`など)、その他のリンカの挙動を制御するために使用されます。
### 共有ライブラリ
共有ライブラリは、複数のプログラムで共有されるコードの集合体です。これにより、ディスクスペースとメモリの使用量を節約できます。
* **Linux**: `.so` (Shared Object) 拡張子を使用します。例: `libcgosotest.so`
* **macOS (Darwin)**: `.dylib` (Dynamic Library) 拡張子を使用します。例: `libcgosotest.dylib`
* **Windows**: `.dll` (Dynamic Link Library) 拡張子を使用します。例: `libcgosotest.dll`
### `LD_LIBRARY_PATH` / `DYLD_LIBRARY_PATH`
これらは環境変数で、プログラムが実行時に共有ライブラリを検索するパスを指定するために使用されます。
* **`LD_LIBRARY_PATH`**: LinuxなどのUnix系システムで使用されます。
* **`DYLD_LIBRARY_PATH`**: macOS (Darwin) で使用されます。
これらの環境変数を設定することで、システムが標準で検索するパス以外の場所に置かれた共有ライブラリを見つけることができます。
### `go env CC` / `go env GOGCCFLAGS`
* **`go env CC`**: Goツールチェインが使用するCコンパイラのパスを出力します。通常は`gcc`や`clang`などです。
* **`go env GOGCCFLAGS`**: GoツールチェインがCコンパイラに渡すデフォルトのフラグを出力します。これには、最適化フラグやインクルードパスなどが含まれることがあります。
### Darwin特有のリンカフラグ
* **`-undefined suppress`**: リンカが未定義シンボル(参照されているが定義されていない関数や変数)を見つけてもエラーを抑制し、警告として扱うように指示します。共有ライブラリをビルドする際に、すべてのシンボルがそのライブラリ内で定義されている必要がない場合に便利です。
* **`-flat_namespace`**: リンカがシンボル解決のために単一のグローバルな名前空間を使用するように指示します。これは、動的ライブラリが他のライブラリのシンボルを直接参照する場合に役立ちます。
## 技術的詳細
このコミットは、主に以下の3つのファイルに変更を加えています。
1. **`misc/cgo/testso/cgoso.go`**:
* `#cgo LDFLAGS`ディレクティブの記述方法が変更されました。以前は単一の`-L. -lcgosotest`という記述でしたが、各OS(linux, freebsd, openbsd, netbsd, darwin, windows)ごとに異なる`LDFLAGS`の記述例が追加されました。
* これは、`cmd/go`が`LDFLAGS`を解析する際の堅牢性をテストするためです。特に、`-l`とライブラリ名がスペースで区切られている場合(`-l cgosotest`)や、共有ライブラリのファイル名が直接指定されている場合(`libcgosotest.so`、`libcgosotest.dylib`、`libcgosotest.dll`)など、様々な形式に対応できることを確認します。
2. **`misc/cgo/testso/test.bash`**:
* このシェルスクリプトは、`cgo`の共有ライブラリテストを実行するためのものです。
* **Darwin (macOS) 向けの条件分岐が追加されました。**
* `$(uname)`が`Darwin`の場合、`args`変数に`-undefined suppress -flat_namespace`が設定されます。これらは、macOSで共有ライブラリをビルドする際に必要なリンカフラグです。
* `dyld_envvar`が`DYLD_LIBRARY_PATH`に設定されます。これはmacOSで共有ライブラリの検索パスを指定するための環境変数です。
* `ext`変数が`dylib`に設定されます。これはmacOSの共有ライブラリの拡張子です。
* 共有ライブラリのビルドコマンドが変更され、`$args`が追加されました。これにより、Darwin環境で適切なリンカフラグが渡されるようになります。
* 共有ライブラリのファイル名が`libcgosotest.$ext`(例: `libcgosotest.dylib`)として動的に決定されるようになりました。
* `LD_LIBRARY_PATH=. ./main`の行が`eval "$dyld_envvar"=. ./main`に変更されました。これにより、OSに応じて適切な環境変数(`LD_LIBRARY_PATH`または`DYLD_LIBRARY_PATH`)が使用されるようになります。
* テスト後のクリーンアップで、`*.dSYM`ファイル(macOSのデバッグシンボルファイル)も削除されるようになりました。
3. **`src/cmd/go/build.go`**:
* `cgo`のビルドプロセスにおいて、`LDFLAGS`からリンカに渡すべきではないフラグをフィルタリングするロジックが改善されました。
* 以前は、`-l`で始まるフラグと、Darwin環境での`-framework X`のみをフィルタリングしていました。
* 新しいロジックでは、`switch`文を使用して、より詳細なフィルタリングが行われます。
* **`-l`または`-l somelib`のスキップ**: `-l`フラグ自体、またはスペースで区切られたライブラリ名(例: `-l cgosotest`)をスキップします。
* **Darwinでの`-framework X`のスキップ**: 以前と同様に、`-framework`とその後のフレームワーク名をスキップします。
* **共有ライブラリファイル名(`.dylib`, `.so`, `.dll`)のスキップ**: `LDFLAGS`に直接共有ライブラリのファイル名が含まれている場合(例: `libcgosotest.so`)もスキップするようになりました。これは、リンカがライブラリを検索する際に、ファイル名ではなく`-l`フラグとライブラリ名を使用するため、ファイル名自体を`LDFLAGS`として渡すのは不適切だからです。
* このフィルタリングにより、`cgo`は様々なOSやリンカの挙動に対してより堅牢になり、ビルドの安定性が向上します。`bareLDFLAGS`には、リンカが正しく解釈できる必要最小限のフラグのみが含まれるようになります。
4. **`src/run.bash`**:
* `misc/cgo/testso`テストの実行条件から、`[ "$GOHOSTOS" == darwin ] ||`という行が削除されました。これは、以前はDarwin環境ではこのテストがスキップされていたことを意味します。このコミットにより、Darwinでもテストが実行されるようになったため、このスキップ条件が不要になりました。
## コアとなるコードの変更箇所
### `misc/cgo/testso/cgoso.go`
```diff
--- a/misc/cgo/testso/cgoso.go
+++ b/misc/cgo/testso/cgoso.go
@@ -5,7 +5,15 @@
package cgosotest
/*
-#cgo LDFLAGS: -L. -lcgosotest
+// intentionally write the same LDFLAGS differently
+// to test correct handling of LDFLAGS.
+#cgo linux LDFLAGS: -L. -lcgosotest
+#cgo freebsd LDFLAGS: -L. -l cgosotest
+#cgo openbsd LDFLAGS: -L. -l cgosotest
+#cgo netbsd LDFLAGS: -L. libcgosotest.so
+#cgo darwin LDFLAGS: -L. libcgosotest.dylib
+#cgo windows LDFLAGS: -L. libcgosotest.dll
+
void init(void);\n void sofunc(void);\n */
misc/cgo/testso/test.bash
--- a/misc/cgo/testso/test.bash
+++ b/misc/cgo/testso/test.bash
@@ -4,7 +4,19 @@
# license that can be found in the LICENSE file.
set -e
-$(go env CC) $(go env GOGCCFLAGS) -shared -o libcgosotest.so cgoso_c.c
+\n+args=\n+dyld_envvar=LD_LIBRARY_PATH\n+ext=so\n+if [ "$(uname)" == "Darwin" ]; then\n+\targs="-undefined suppress -flat_namespace"\n+\tdyld_envvar=DYLD_LIBRARY_PATH\n+\text=dylib\n+fi\n+\n+dylib=libcgosotest.$ext\n+$(go env CC) $(go env GOGCCFLAGS) -shared $args -o $dylib cgoso_c.c
go build main.go
-LD_LIBRARY_PATH=. ./main
-rm -f libcgosotest.so main
+\n+eval "$dyld_envvar"=. ./main\n+rm -rf $dylib main *.dSYM
src/cmd/go/build.go
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -1855,14 +1855,24 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,\
var linkobj []string
var bareLDFLAGS []string
-\t// filter out -lsomelib, and -framework X if on Darwin
+\t// filter out -lsomelib, -l somelib, *.{so,dll,dylib}, and (on Darwin) -framework X
for i := 0; i < len(cgoLDFLAGS); i++ {\n \t\tf := cgoLDFLAGS[i]\n-\t\tif !strings.HasPrefix(f, "-l") {\n-\t\t\tif goos == "darwin" && f == "-framework" { // skip the -framework X\n-\t\t\t\ti += 1\n-\t\t\t\tcontinue\n+\t\tswitch {\n+\t\t// skip "-lc" or "-l somelib"\n+\t\tcase strings.HasPrefix(f, "-l"):\n+\t\t\tif f == "-l" {\n+\t\t\t\ti++\n \t\t\t}\n+\t\t// skip "-framework X" on Darwin\n+\t\tcase goos == "darwin" && f == "-framework":\n+\t\t\ti++\n+\t\t// skip "*.{dylib,so,dll}"\n+\t\tcase strings.HasSuffix(f, ".dylib"),\n+\t\t\tstrings.HasSuffix(f, ".so"),\n+\t\t\tstrings.HasSuffix(f, ".dll"):\n+\t\t\tcontinue\n+\t\tdefault:\n \t\t\tbareLDFLAGS = append(bareLDFLAGS, f)\n \t\t}\n \t}\n```
### `src/run.bash`
```diff
--- a/src/run.bash
+++ b/src/run.bash
@@ -104,7 +104,6 @@ esac
[ "$CGO_ENABLED" != 1 ] ||
[ "$GOHOSTOS" == windows ] ||
-[ "$GOHOSTOS" == darwin ] ||
(xcd ../misc/cgo/testso
./test.bash
) || exit $?\n```
## コアとなるコードの解説
### `misc/cgo/testso/cgoso.go`の変更
この変更は、`cgo`の`LDFLAGS`パーサーの堅牢性をテストするために、意図的に様々な形式の`LDFLAGS`指定を追加しています。これにより、Goのビルドシステムが異なるOSやリンカの挙動に対応できるかを確認します。特に、`-l`フラグの後にスペースがある場合や、共有ライブラリのファイル名が直接指定されている場合など、Goがこれらのバリエーションを正しく処理できることを保証します。
### `misc/cgo/testso/test.bash`の変更
このスクリプトの変更は、`misc/cgo/testso`テストをmacOS (Darwin) 環境で実行できるようにするためのものです。
* `if [ "$(uname)" == "Darwin" ]`ブロックにより、macOS特有のリンカフラグ(`-undefined suppress -flat_namespace`)が`args`変数に設定されます。これらのフラグは、macOSで共有ライブラリをビルドする際に、未定義シンボルのエラーを抑制し、シンボル解決に単一のグローバル名前空間を使用するために必要です。
* `dyld_envvar`が`DYLD_LIBRARY_PATH`に設定され、`eval "$dyld_envvar"=. ./main`によって、macOSで共有ライブラリの検索パスを正しく設定して実行可能ファイルを起動します。これにより、テスト対象の共有ライブラリが正しくロードされるようになります。
* `ext`変数が`dylib`に設定されることで、macOSの共有ライブラリの命名規則(`.dylib`)に準拠したファイルが生成・参照されるようになります。
これらの変更により、以前はスキップされていたDarwin環境での`cgo`共有ライブラリテストが実行可能になり、Goのクロスプラットフォーム互換性の検証が強化されます。
### `src/cmd/go/build.go`の変更
この変更は、`cmd/go`が`cgo`の`LDFLAGS`を処理する際のフィルタリングロジックを大幅に改善するものです。
* 以前のロジックは単純な`if`文でしたが、新しいロジックは`switch`文を使用し、より多様な`LDFLAGS`のパターンに対応しています。
* 特に重要なのは、`strings.HasSuffix(f, ".dylib")`, `strings.HasSuffix(f, ".so")`, `strings.HasSuffix(f, ".dll")`という条件が追加されたことです。これは、`LDFLAGS`に共有ライブラリのファイル名自体(例: `libcgosotest.so`)が含まれている場合に、それをリンカに渡さないようにするためのものです。リンカは通常、`-l`フラグとライブラリ名(例: `-lcgosotest`)を期待しており、ファイル名自体を渡すとエラーになるか、意図しない挙動を引き起こす可能性があります。
* この改善されたフィルタリングにより、`cgo`は様々なOSやリンカの挙動に対してより堅牢になり、ビルドの安定性が向上します。`bareLDFLAGS`には、リンカが正しく解釈できる必要最小限のフラグのみが含まれるようになります。
### `src/run.bash`の変更
この変更は、`src/run.bash`スクリプトから`[ "$GOHOSTOS" == darwin ] ||`という行を削除するものです。これは、以前はGoのテストスイートの一部として`misc/cgo/testso`がDarwin環境では実行されないように明示的にスキップされていたことを意味します。`misc/cgo/testso/test.bash`と`src/cmd/go/build.go`の変更により、Darwinでの`cgo`共有ライブラリのビルドとテストが正しく機能するようになったため、このスキップ条件が不要になりました。これにより、GoのテストカバレッジがDarwin環境でも完全になります。
## 関連リンク
* GitHubコミットページ: [https://github.com/golang/go/commit/bea7b5187283cf73638332e5051c8e9333ccf4dd](https://github.com/golang/go/commit/bea7b5187283cf73638332e5051c8e9333ccf4dd)
* Go CL 9416047: [https://golang.org/cl/9416047](https://golang.org/cl/9416047)
## 参考にした情報源リンク
* Go言語公式ドキュメント: `cgo` (GoのバージョンによってドキュメントのURLが異なる場合がありますが、`go doc cmd/cgo`などで参照できます)
* GCC リンカオプション: [https://gcc.gnu.org/onlinedocs/gcc/Link Options.html](https://gcc.gnu.org/onlinedocs/gcc/Link Options.html)
* macOS リンカオプション (man ld): `man ld` (macOSのターミナルで実行)
* 共有ライブラリの概念 (OSによって異なるため、各OSのドキュメントを参照)
* `LD_LIBRARY_PATH`と`DYLD_LIBRARY_PATH`に関する情報 (各OSのドキュメントやオンラインリソース)