[インデックス 17773] ファイルの概要
このコミットは、Go言語のビルドツール (cmd/go
) におけるSWIG (Simplified Wrapper and Interface Generator) の統合に関する改善です。具体的には、SWIGによって生成される共有ライブラリにC/C++ファイルが適切に含まれるようにし、またSWIG共有ライブラリの検索パスにアクションのオブジェクトディレクトリを追加することで、SWIGを利用したGoプログラムのビルドプロセスをより堅牢にすることを目的としています。
コミット
commit c774e902083c677cffb9873e7d46346bcbf8cc21
Author: Ian Lance Taylor <iant@golang.org>
Date: Wed Oct 9 10:35:46 2013 -0700
cmd/go: add any .c/.cc files to the SWIG shared library
Also add the action's object directory to the list of
directories we use to find SWIG shared libraries.
Fixes #6521.
R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/14369043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/c774e902083c677cffb9873e7d46346bcbf8cc21
元コミット内容
cmd/go: add any .c/.cc files to the SWIG shared library
Also add the action's object directory to the list of directories we use to find SWIG shared libraries.
Fixes #6521.
変更の背景
このコミットは、GoのビルドツールがSWIGを使用する際に、C言語 (.c
) およびC++言語 (.cc
) のソースファイルをSWIGによって生成される共有ライブラリに適切に含めるようにするためのものです。また、SWIGが共有ライブラリを検索する際に、ビルドアクションのオブジェクトディレクトリも検索パスに追加することで、ビルドの信頼性を向上させています。
Fixes #6521
と記載されていますが、現在のGoリポジトリのIssue番号ははるかに大きいため、このIssueは非常に古いか、既にクローズされている可能性があります。しかし、この記述から、以前のGoビルドプロセスでは、SWIGを使用する際にC/C++ファイルが共有ライブラリに正しくリンクされない、あるいはSWIGが生成した共有ライブラリを見つけられないという問題が存在していたことが推測されます。この問題は、GoとC/C++コードをSWIGを介して連携させるアプリケーションの開発において、ビルドエラーや実行時エラーを引き起こす可能性がありました。
前提知識の解説
- Go言語のビルドシステム (
cmd/go
): Go言語の公式ビルドツールであり、ソースコードのコンパイル、リンク、パッケージ管理などを行います。go build
コマンドなどがこれに該当します。 - SWIG (Simplified Wrapper and Interface Generator): C/C++/Objective-C/Java/Python/Ruby/Goなど、様々な言語間でC/C++コードを呼び出すためのインターフェースコードを自動生成するツールです。Go言語から既存のC/C++ライブラリを利用する際に、SWIGがその橋渡し役となります。SWIGは、C/C++のヘッダファイルやインターフェース定義ファイル (
.i
ファイル) を読み込み、ターゲット言語(この場合はGo)からC/C++関数を呼び出すためのラッパーコードと、C/C++側からGoの関数を呼び出すためのコールバックコードを生成します。 - 共有ライブラリ (Shared Library): 複数のプログラムから共有して利用できるライブラリです。WindowsではDLL (Dynamic Link Library)、LinuxではSO (Shared Object) ファイルとして知られています。SWIGは、GoからC/C++コードを呼び出す際に、C/C++コードを共有ライブラリとしてコンパイルし、Goプログラムがそれをロードして利用する形式を取ることがあります。
- オブジェクトファイル (Object File): コンパイラによってソースコードが機械語に変換された中間ファイルです。通常、
.o
や.obj
の拡張子を持ちます。これらのオブジェクトファイルがリンカによって結合され、実行可能ファイルや共有ライブラリが生成されます。 gcc
/g++
: GNU Compiler Collectionの一部であり、C言語およびC++言語のコンパイラです。Goのビルドシステムは、CgoやSWIGを使用する際に、内部的にこれらのコンパイラを呼び出してC/C++コードをコンパイルします。ld
(Linker): リンカは、コンパイルされたオブジェクトファイルやライブラリを結合して、最終的な実行可能ファイルや共有ライブラリを生成するツールです。
技術的詳細
このコミットの主要な変更点は以下の2つです。
-
SWIG共有ライブラリへのC/C++ファイルの追加:
- 以前の
cmd/go
のSWIG処理では、SWIGによって生成されたC/C++ラッパーコードはコンパイルされていましたが、ユーザーが提供する追加のC/C++ソースファイル (.c
や.cc
) が共有ライブラリに適切に含まれていない可能性がありました。 - このコミットでは、
b.swig
関数がgccfiles
(Cファイル) とgxxfiles
(C++ファイル) の両方を受け取るように変更されました。 b.swig
関数内で、これらのC/C++ファイルがgcc
またはg++
を使用して個別にオブジェクトファイル (.o
ファイル) にコンパイルされ、extraObj
というスライスに追加されます。- 最終的に、SWIGによって生成される共有ライブラリをリンクする際に、これらの
extraObj
がリンカに渡されることで、ユーザーが提供するC/C++コードも共有ライブラリの一部として含まれるようになります。これにより、GoプログラムからSWIGを介してC/C++の機能全体を呼び出すことが可能になります。
- 以前の
-
SWIG共有ライブラリ検索パスへのオブジェクトディレクトリの追加:
- Goのビルドシステムは、SWIGによって生成された共有ライブラリをロードする際に、特定のディレクトリを検索します。
- このコミットでは、
gcToolchain.ld
およびtools gccgoToolchain.ld
関数内で、ビルドアクションのオブジェクトディレクトリ (a.objdir
) がSWIG共有ライブラリの検索パス (swigDirs
) に追加されるようになりました。 - これにより、SWIGが生成した共有ライブラリが一時的なオブジェクトディレクトリに配置された場合でも、Goのビルドシステムがそのライブラリを確実に見つけてロードできるようになり、ビルドの失敗を防ぎます。
これらの変更により、GoとSWIGを組み合わせた開発において、C/C++コードの統合がよりスムーズになり、ビルドプロセスの信頼性が向上しました。
コアとなるコードの変更箇所
misc/swig/callback/callback.cc
: 新規追加されたC++ファイル。SWIGのコールバック機能のテスト/サンプルコードの一部として追加されたようです。Caller::call()
メソッドの実装が含まれています。misc/swig/callback/callback.h
:callback.cc
に対応するヘッダファイル。Caller::call()
の宣言が変更され、インライン実装から外部実装(callback.cc
)に移行しています。これは、callback.cc
がSWIG共有ライブラリに適切に含まれることをテストするための一環である可能性があります。src/cmd/go/build.go
: Goのビルドロジックの核心部分。func (b *builder) build(a *action) (err error)
:b.swig
の呼び出しが変更され、a.p.CXXFiles
(C++ファイル) が新しい引数として渡されるようになりました。func (gcToolchain) ld(...)
およびfunc (tools gccgoToolchain) ld(...)
: SWIG共有ライブラリの検索パスにa.objdir
(アクションのオブジェクトディレクトリ) を追加するロジックが追加されました。func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles []string) ...
: この関数のシグネチャが変更され、gxxfiles
(C++ファイル) を受け取るようになりました。関数内でgccfiles
とgxxfiles
のそれぞれに対してb.gcc
またはb.gxx
を呼び出してオブジェクトファイルを生成し、extraObj
スライスに格納するロジックが追加されています。func (b *builder) swigOne(...)
:extraObj
スライスを新しい引数として受け取るように変更され、最終的なリンカコマンド (b.run(...)
) にextraObj
が渡されるようになりました。
コアとなるコードの解説
src/cmd/go/build.go
の変更点
-
build
メソッド内のswig
呼び出しの変更:// 変更前 // outGo, outObj, err := b.swig(a.p, obj, gccfiles) // 変更後 outGo, outObj, err := b.swig(a.p, obj, gccfiles, a.p.CXXFiles)
b.swig
関数に、パッケージ (a.p
) に含まれるC++ソースファイル (a.p.CXXFiles
) が明示的に渡されるようになりました。これにより、SWIG処理においてC++ファイルも考慮されるようになります。 -
ld
メソッドにおけるSWIG共有ライブラリ検索パスの追加:// gcToolchain.ld および tools gccgoToolchain.ld 内 if a.objdir != "" && !swigDirs[a.objdir] { swigArg[1] += ":" swigArg[1] += a.objdir swigDirs[a.objdir] = true }
リンカがSWIG共有ライブラリを検索するパス (
swigArg[1]
) に、現在のビルドアクションのオブジェクトディレクトリ (a.objdir
) が追加されます。これにより、SWIGが生成した共有ライブラリが一時的なビルドディレクトリに存在する場合でも、リンカがそれを見つけられるようになります。 -
swig
メソッドの変更:// 変更前 // func (b *builder) swig(p *Package, obj string, gccfiles []string) (outGo, outObj []string, err error) { // 変更後 func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles []string) (outGo, outObj []string, err error) { var extraObj []string for _, file := range gccfiles { // ... CファイルのコンパイルとextraObjへの追加 ... } for _, file := range gxxfiles { // ... C++ファイルのコンパイルとextraObjへの追加 ... } // ... // b.swigOne の呼び出しに extraObj を渡す // goFile, objFile, err := b.swigOne(p, f, obj, false, intgosize, extraObj) }
swig
関数は、Cファイル (gccfiles
) とC++ファイル (gxxfiles
) の両方を受け取るようになりました。これらのファイルはそれぞれb.gcc
またはb.gxx
を使って個別にコンパイルされ、生成されたオブジェクトファイルはextraObj
スライスに集められます。このextraObj
は、後続のswigOne
関数に渡され、最終的な共有ライブラリのリンク時に使用されます。 -
swigOne
メソッドの変更:// 変更前 // func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize string) (outGo, outObj string, err error) { // 変更後 func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize string, extraObj []string) (outGo, outObj string, err error) { // ... // b.run の呼び出しに extraObj を渡す // b.run(p.Dir, p.ImportPath, nil, b.gccCmd(p.Dir), "-o", target, gccObj, extraObj, ldflags) }
swigOne
関数は、extraObj
スライスを受け取るようになりました。このextraObj
は、SWIGによって生成されたラッパーコードのオブジェクトファイル (gccObj
) と共に、最終的な共有ライブラリを生成するためのリンカコマンド (b.run
) に渡されます。これにより、ユーザーが提供するC/C++ソースファイルが共有ライブラリに正しくリンクされることが保証されます。
misc/swig/callback/callback.cc
と misc/swig/callback/callback.h
の変更点
これらのファイルは、SWIGのコールバック機能のテストまたはサンプルとして追加されたものです。callback.cc
が新規追加され、callback.h
の Caller::call()
メソッドがインライン実装から外部実装に変わっています。これは、cmd/go
の変更が、このような外部のC++ソースファイルがSWIGによって生成される共有ライブラリに適切にコンパイル・リンクされることを保証するためのテストケースの一部である可能性が高いです。
関連リンク
- SWIG 公式サイト: http://www.swig.org/
- Go言語のCgoドキュメント: GoとC/C++を連携させるための別のメカニズムですが、SWIGと関連する概念が多く含まれます。
参考にした情報源リンク
- Go言語のソースコード (特に
src/cmd/go/build.go
) - SWIGのドキュメンテーション
- C/C++コンパイル・リンクの一般的な知識
- 共有ライブラリの概念に関する一般的な情報