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

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

コミット

cmd/go: do not fail if libgcc does not exist

(This is a patch from the pkgsrc Go package.)

LGTM=iant R=golang-codereviews, iant, joerg.sonnenberger, dave CC=golang-codereviews, joerg https://golang.org/cl/108340043

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

https://github.com/golang/go/commit/0e694298e9e5d6565b285f48860f73626d6705ff

元コミット内容

commit 0e694298e9e5d6565b285f48860f73626d6705ff
Author: Benny Siegert <bsiegert@gmail.com>
Date:   Thu Jul 10 14:35:04 2014 -0700

    cmd/go: do not fail if libgcc does not exist

    (This is a patch from the pkgsrc Go package.)

    LGTM=iant
    R=golang-codereviews, iant, joerg.sonnenberger, dave
    CC=golang-codereviews, joerg
    https://golang.org/cl/108340043

変更の背景

このコミットは、Goのビルドツールであるcmd/goが、libgccライブラリの存在を適切に扱えない場合に発生する問題を解決するために導入されました。特に、clangのようなコンパイラがlibgccを見つけられない状況で、cmd/goがビルドに失敗するのを防ぐことが目的です。

GoプログラムがCコードと連携する場合(Cgoを使用する場合など)、GoツールチェーンはCコンパイラ(GCCやClangなど)を呼び出してCコードをコンパイルし、リンクします。この際、Cコンパイラはランタイムサポートのためにlibgccを必要とすることがあります。

元のコードでは、cmd/golibgccを検索するロジックにおいて、clanglibgccを見つけられない場合に、libgcc.aという相対パスを返してしまう問題がありました。cmd/goはこの相対パスを有効なものとして扱ってしまい、結果としてビルドが失敗していました。

この問題は、特にpkgsrcのようなパッケージ管理システムを使用している環境で顕在化しました。pkgsrcは、様々なUNIX系システムでソフトウェアをビルド・インストールするためのフレームワークであり、Goパッケージも提供しています。pkgsrc環境下では、Goのビルドプロセスが特定のlibgccのパス解決に依存することがあり、clangの挙動が問題を引き起こしていました。

このコミットは、pkgsrcのGoパッケージからのパッチを元にしており、libgccが見つからない場合にcmd/goがビルドを中断しないように修正することで、より堅牢なビルドプロセスを実現しています。

前提知識の解説

cmd/go

cmd/goは、Go言語の公式ツールチェーンの中核をなすコマンドラインツールです。Goプログラムのコンパイル、テスト、依存関係の管理、パッケージのインストールなど、Go開発における様々なタスクを実行します。Goのビルドプロセスにおいて、Cgo(GoとC言語の相互運用機能)を使用する場合、cmd/goは内部的にCコンパイラ(GCCやClangなど)を呼び出してCコードを処理します。

libgcc

libgccは、GCC(GNU Compiler Collection)のランタイムサポートライブラリです。C/C++コンパイラが生成するコードが依存する、低レベルのヘルパー関数(例: 整数除算、浮動小数点演算、例外処理など)を提供します。GCCでコンパイルされたプログラムは、通常、静的または動的にlibgccにリンクされます。

clang

clangは、LLVMプロジェクトの一部として開発されているC、C++、Objective-C、Objective-C++コンパイラのフロントエンドです。GCCと互換性のあるコマンドラインオプションと診断メッセージを提供し、多くのプラットフォームでGCCの代替として使用されています。clangもまた、特定の状況下でlibgccに依存することがあります。特に、clangがGCCのツールチェーンと組み合わせて使用される場合や、特定のランタイムサポートが必要な場合にlibgccを検索します。

filepath.IsAbs

Go言語の標準ライブラリpath/filepathパッケージに含まれる関数で、与えられたパスが絶対パスであるかどうかを判定します。絶対パスは、ファイルシステムのルートから始まる完全なパスを指します(例: /usr/local/lib)。相対パスは、現在の作業ディレクトリからの相対的な位置を示します(例: libgcc.a)。この関数は、パスの有効性を検証し、ファイル操作の安全性を確保するために重要です。

pkgsrc

pkgsrcは、NetBSDプロジェクトによって開発された、クロスプラットフォームなパッケージ管理システムです。様々なUNIX系オペレーティングシステム(Linux, macOS, Solaris, FreeBSDなど)で動作し、数千ものソフトウェアパッケージをソースコードからビルド・インストールするためのフレームワークを提供します。pkgsrcは、依存関係の解決、ビルドオプションのカスタマイズ、パッチの適用などを自動的に行い、異なる環境間でのソフトウェアの移植性を高めます。このコミットのパッチがpkgsrc由来であることは、pkgsrcコミュニティがGoのビルドプロセスにおける特定の問題に直面し、その解決策を開発したことを示唆しています。

技術的詳細

このコミットは、src/cmd/go/build.goファイル内のlibgccを検索するロジックを修正しています。具体的には、builder.libgcc関数内の条件分岐が変更されました。

元のコードでは、libgccのパスが絶対パスでない場合に、それがclangによって返されたものであれば、空文字列を返す(つまり、libgccが見つからなかったと判断する)というロジックがありました。これは、clanglibgccを見つけられない場合に「libgcc.a」のような相対パスを返すことがあり、これをcmd/goが誤って有効なパスとして扱ってしまうのを防ぐためのものでした。

しかし、この条件はstrings.Contains(gccCmd[0], "clang")という形で、実行されているコンパイラがclangである場合に限定されていました。このため、clang以外のコンパイラ(例えば、特定のバージョンのGCCや、clangと互換性のある別のコンパイラ)が同様に相対パスを返した場合、このチェックが機能せず、問題が発生する可能性がありました。

新しいコードでは、このclangに特化したチェックが削除され、より汎用的な条件が適用されています。変更後のコードは、コンパイラの種類に関わらず、libgccのパスが絶対パスでない場合に常に空文字列を返すようになりました。

// Original:
// if strings.Contains(gccCmd[0], "clang") && !filepath.IsAbs(string(f)) {
// New:
// if !filepath.IsAbs(string(f)) {

この変更により、どのコンパイラが使用されているかに関わらず、libgccのパスが絶対パスでない場合は、cmd/goはそれを無効なパスと判断し、ビルドを続行できるようになります。これにより、libgccが見つからない状況でのビルドの堅牢性が向上し、特にpkgsrcのような多様なビルド環境での互換性が高まります。

この修正は、特定のコンパイラ(clang)に依存するのではなく、パスの絶対性というより一般的な特性に基づいて判断を行うことで、より汎用的で将来性のある解決策を提供しています。

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

--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -1951,9 +1951,9 @@ func (b *builder) libgcc(p *Package) (string, error) {
 		return "$LIBGCC", nil
 	}
 
-	// clang might not be able to find libgcc, and in that case,
+	// The compiler might not be able to find libgcc, and in that case,
 	// it will simply return "libgcc.a", which is of no use to us.
-	if strings.Contains(gccCmd[0], "clang") && !filepath.IsAbs(string(f)) {
+	if !filepath.IsAbs(string(f)) {
 		return "", nil
 	}
 

コアとなるコードの解説

この変更は、src/cmd/go/build.goファイル内のbuilder.libgcc関数にあります。この関数は、Goのビルドプロセス中にCgoが使用される際に、libgccライブラリのパスを特定するために呼び出されます。

変更前のコードでは、以下の条件文がありました。

if strings.Contains(gccCmd[0], "clang") && !filepath.IsAbs(string(f)) {
    return "", nil
}
  • strings.Contains(gccCmd[0], "clang"): これは、実行されているCコンパイラのコマンド名(gccCmd[0])が「clang」という文字列を含んでいるかどうかをチェックしています。つまり、コンパイラがclangである場合にのみ、この条件の後半部分が評価されます。
  • !filepath.IsAbs(string(f)): これは、libgccのパス(f)が絶対パスではない(つまり相対パスである)かどうかをチェックしています。

この条件文全体は、「もしコンパイラがclangであり、かつlibgccのパスが相対パスであるならば、空文字列を返す(libgccが見つからなかったと判断する)」という意味でした。これは、clanglibgccを見つけられない場合に「libgcc.a」のような相対パスを返すという特定の挙動に対応するためのものでした。

変更後のコードでは、strings.Contains(gccCmd[0], "clang")というclangに特化した条件が削除されました。

if !filepath.IsAbs(string(f)) {
    return "", nil
}

この修正により、条件文は「もしlibgccのパスが相対パスであるならば、コンパイラの種類に関わらず空文字列を返す」という意味に変わりました。

この変更の意図は以下の通りです。

  1. 汎用性の向上: clangに限定されていたチェックを、すべてのコンパイラに適用することで、clang以外のコンパイラが同様に相対パスを返した場合でも、cmd/goが適切に処理できるようになります。
  2. 堅牢性の強化: libgccのパスが絶対パスでない場合、それは通常、有効なライブラリパスではないと判断できます。この変更により、cmd/goは無効な相対パスを有効なものとして誤って解釈することを防ぎ、ビルドの失敗を回避します。
  3. コメントの更新: コードの変更に合わせて、コメントも「clang might not be able to find libgcc」から「The compiler might not be able to find libgcc」へと、より一般的な表現に修正されています。

この小さな変更は、Goのビルドシステムが様々な環境やコンパイラの挙動に対して、より柔軟かつ堅牢に対応できるようにするための重要な改善です。

関連リンク

参考にした情報源リンク

  • Web search results for "libgcc go build pkgsrc go" (provided by the tool)
  • path/filepath package documentation (Go standard library)
  • GCC documentation (for libgcc context)
  • LLVM/Clang documentation (for clang context)
  • pkgsrc documentation (for pkgsrc context)