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

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

このコミットは、Go言語のcmd/cgoツール内のsrc/cmd/cgo/gcc.goファイルに対する変更です。cmd/cgoは、GoプログラムがC言語のコードを呼び出すためのメカニズムを提供するツールです。gcc.goファイルは、cgoがCコンパイラ(GCCやClangなど)を呼び出す際のコマンドライン引数や設定を管理する役割を担っています。具体的には、Cコードのコンパイル時に使用されるフラグの調整が行われています。

コミット

cmd/cgo-fno-eliminate-unused-debug-typesフラグの使用を停止するコミットです。このフラグは、OS X上のllvm-gccフロントエンドにおけるデバッグ情報の問題を解決するために2010年1月に導入されましたが、clangへの移行とコンパイラの進化により不要となり、むしろ新しいバージョンのclangではエラーとなるため削除されました。

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

https://github.com/golang/go/commit/adda33483dbf9fe4753ecc54b56590d60c962acb

元コミット内容

commit adda33483dbf9fe4753ecc54b56590d60c962acb
Author: Russ Cox <rsc@golang.org>
Date:   Mon Oct 28 22:21:26 2013 -0400

    cmd/cgo: stop using -fno-eliminate-unused-debug-types
    
    This flag was added in January 2010, in CL 181102, to fix issue 497.
    (Numbers were just shorter back then.) The fix was for OS X machines
    and the llvm-gcc frontend.
    
    In July 2011 we had to change the way we get enum values, because
    there were no flags available to force Xcode's llvm-gcc to include the
    enum names and values in DWARF debug output.
    
    We now use clang, not llvm-gcc, on OS X machines.
    Earlier versions of clang printed a warning about not knowing the flag.
    Newer versions of clang now make that an error.
    
    That is:
     - The flag was added for OS X machines.
     - The flag is no longer necessary on OS X machines.
     - The flag now breaks some OS X machines.
    
    Remove it.
    
    I have run the original program from issue 497 successfully
    without the flag on both OS X and Linux machines.
    
    Fixes #6678.
    
    R=golang-dev, minux.ma
    CC=golang-dev
    https://golang.org/cl/18850043

変更の背景

この変更の背景には、Go言語のcgoツールがCコードをコンパイルする際に使用するコンパイラと、デバッグ情報の生成に関する歴史的な経緯があります。

元々、2010年1月にGo Issue 497を修正するために、cmd/cgo-fno-eliminate-unused-debug-typesというコンパイラフラグを使用するようになりました。この問題は、特にOS X環境でllvm-gccフロントエンドを使用している際に、デバッグ情報(特に列挙型(enum)の値)がDWARFデバッグ出力に含まれないというものでした。このフラグは、未使用のデバッグ型がコンパイラによって削除されるのを防ぐことで、この問題を回避していました。

しかし、2011年7月には、Xcodeのllvm-gccが列挙型の名前と値をDWARFデバッグ出力に強制的に含めるための利用可能なフラグがないため、列挙型の値を取得する方法を変更する必要がありました。

さらに重要な変更は、OS X環境におけるGoのビルドシステムがllvm-gccからclangへと移行したことです。初期のclangバージョンでは、この-fno-eliminate-unused-debug-typesフラグは認識されず、単なる警告として扱われていました。しかし、新しいバージョンのclangでは、この未知のフラグがエラーとして扱われるようになりました。

この状況により、以下の問題が発生しました。

  1. このフラグは元々OS X環境向けに追加されたものでした。
  2. 現在では、OS X環境においてもこのフラグは不要になっています。
  3. さらに、このフラグが存在することで、一部のOS X環境でビルドが失敗するようになりました。

これらの理由から、このフラグを削除することが決定されました。コミットメッセージには、Issue 497の元のプログラムが、このフラグなしでOS XとLinuxの両方で正常に動作することが確認されたと記載されています。これにより、このフラグがもはや必要ないことが裏付けられました。

前提知識の解説

cmd/cgo

cmd/cgoは、Go言語のツールチェーンの一部であり、GoプログラムがC言語の関数やデータ構造を呼び出すことを可能にするためのツールです。GoはCとの相互運用性(FFI: Foreign Function Interface)をサポートしており、cgoはその橋渡しをします。Goのソースコード内にimport "C"という記述があると、cgoはGoとCの間の呼び出し規約を処理するためのラッパーコードを生成します。これにより、GoコードからC関数を呼び出したり、CコードからGo関数を呼び出したりすることが可能になります。

-fno-eliminate-unused-debug-types

これはGCC(GNU Compiler Collection)系のコンパイラで使用されるコンパイラフラグの一つです。

  • debug-types: デバッグ情報に含まれる型情報(構造体、列挙型など)を指します。
  • eliminate-unused: コンパイラが最適化の一環として、コード内で使用されていないエンティティ(関数、変数、型など)を削除する処理を指します。
  • no-: その最適化を無効にする、という意味です。

したがって、-fno-eliminate-unused-debug-typesは、「コード内で直接使用されていないデバッグ型であっても、コンパイラがそれらをデバッグ情報から削除しないようにする」という指示になります。これは、デバッガがプログラムの実行中に、ソースコードには明示的に現れないが、デバッグ目的で参照したい型情報(例えば、特定の構造体の内部構造や列挙型の全メンバーなど)にアクセスできるようにするために重要となる場合があります。

DWARF

DWARF(Debugging With Attributed Record Formats)は、プログラムのソースコードとコンパイルされたバイナリコードの間のマッピングを記述するための標準的なデバッグ情報フォーマットです。デバッガはDWARF情報を使用して、実行中のプログラムの変数、関数、ソースコードの行番号などを理解し、開発者がブレークポイントを設定したり、変数の値を検査したりすることを可能にします。

DWARFは、以下のような情報を含みます。

  • ソースファイルと行番号のマッピング: 実行アドレスがどのソースファイルのどの行に対応するか。
  • 変数情報: 変数の名前、型、メモリ上の位置。
  • 関数情報: 関数の名前、引数、戻り値、ローカル変数。
  • 型情報: 構造体、共用体、列挙型、配列などの定義。

このコミットの文脈では、特に列挙型(enum)の値がDWARFデバッグ出力に含まれるかどうかが問題となっていました。

llvm-gccclang

  • llvm-gcc: これは、GCCのフロントエンドとLLVM(Low Level Virtual Machine)のバックエンドを組み合わせたコンパイラです。AppleがmacOS(旧OS X)のXcode開発ツールの一部として提供していました。GCCの構文解析や意味解析の能力と、LLVMの最適化およびコード生成の能力を組み合わせることで、パフォーマンスと柔軟性を両立させようとしたものです。しかし、GCCとLLVMの統合は複雑であり、最終的にはAppleはllvm-gccの開発を中止しました。
  • clang: clangは、LLVMプロジェクトの一部として開発されたC、C++、Objective-C、Objective-C++コンパイラのフロントエンドです。GCCとは異なり、clangは最初からLLVMのアーキテクチャに合わせて設計されており、よりモジュール化され、高速で、診断メッセージが優れているとされています。Appleはllvm-gccの後継としてclangを積極的に採用し、現在ではmacOSの主要なC/C++/Objective-Cコンパイラとなっています。

このコミットは、GoのビルドシステムがOS X上でllvm-gccからclangへと移行したことによって、以前のllvm-gcc向けの回避策が不要になっただけでなく、clangでは問題を引き起こすようになったという状況を反映しています。

Go Issue 497 と Go Issue 6678

  • Go Issue 497: "cmd/cgo: enum values not in debug info on OS X" (OS Xでcgoのenum値がデバッグ情報に含まれない)
    • この問題は、OS X上のllvm-gccでコンパイルされたCコードの列挙型が、デバッグ情報(DWARF)に適切に含まれないために、デバッガで列挙型のシンボリックな値(例えば、REDではなく0)が表示されないというものでした。-fno-eliminate-unused-debug-typesフラグは、この問題を一時的に解決するために導入されました。
  • Go Issue 6678: "cmd/cgo: clang warns about -fno-eliminate-unused-debug-types" (cgoが-fno-eliminate-unused-debug-typesについてclangが警告を出す)
    • この問題は、clang-fno-eliminate-unused-debug-typesフラグを認識せず、警告(後にエラー)を出すようになったことを報告しています。これは、clangへの移行に伴い、以前のllvm-gcc向けのフラグが互換性の問題を引き起こすようになったことを示しています。このコミットは、このIssue 6678を修正するものです。

技術的詳細

このコミットの技術的詳細を理解するためには、コンパイラのデバッグ情報生成の仕組みと、異なるコンパイラ間のフラグの互換性の問題に焦点を当てる必要があります。

デバッグ情報の生成と最適化

コンパイラは、ソースコードを機械語に変換する際に、デバッグ情報を生成することができます。このデバッグ情報は、デバッガがプログラムの実行を追跡し、変数や型を検査するために不可欠です。しかし、コンパイラは通常、生成されるバイナリのサイズを削減し、コンパイル時間を短縮するために、様々な最適化を行います。その一つが、使用されていないコードやデータの削除です。

-fno-eliminate-unused-debug-typesフラグは、この「使用されていないデバッグ型の削除」という最適化を無効にするためのものでした。Goのcgoツールは、Cコードをコンパイルする際に、Goコードから参照される可能性のあるCの型情報(特に列挙型)がデバッグ情報に確実に含まれるようにする必要がありました。OS Xのllvm-gccが、Goコードから直接参照されていない列挙型を「未使用」と判断してデバッグ情報から削除してしまう問題があったため、このフラグが導入されました。これにより、デバッガがGoとCの境界を越えてデバッグする際に、C側の列挙型のシンボリックな値を見ることができないという問題が回避されました。

コンパイラの進化とフラグの互換性

コンパイラは常に進化しており、新しい機能が追加されたり、古い機能が非推奨になったり、動作が変更されたりします。特に、llvm-gccからclangへの移行は、単なるバージョンアップではなく、異なる設計思想を持つコンパイラへの切り替えでした。

clangは、LLVMの設計原則に基づいており、GCCとは異なる内部構造を持っています。そのため、GCC系のコンパイラで使用されるすべてのフラグがclangでそのまま機能するわけではありません。初期のclangバージョンでは、認識できないフラグに対しては単に警告を出すだけでしたが、コンパイラの厳格化や、将来的な互換性の問題を避けるために、新しいバージョンではそのような未知のフラグをエラーとして扱うようになりました。

この変更は、GoのビルドシステムがOS X上でclangをデフォルトのCコンパイラとして使用するようになった結果として必然的に発生しました。-fno-eliminate-unused-debug-typesフラグは、もはやclangでは必要ないだけでなく、ビルドプロセスを中断させる原因となっていました。

影響の検証

コミットメッセージには、「I have run the original program from issue 497 successfully without the flag on both OS X and Linux machines.」と記載されています。これは、このフラグがなくても、元々解決しようとしていた問題(Issue 497)が再発しないことを確認したことを意味します。これは、cgoが列挙型の値を取得する方法が2011年7月に変更されたことや、clangがデバッグ情報をより適切に生成するようになったことなど、他の改善によって、このフラグの必要性がなくなったことを示唆しています。

このコミットは、Goのビルドシステムが特定のプラットフォーム(OS X)のコンパイラの進化に適応し、不要になった、あるいは問題を引き起こすようになったビルドフラグを削除することで、ビルドの安定性と互換性を維持するための重要なメンテナンス作業であったと言えます。

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

src/cmd/cgo/gcc.goファイルのgccCmd()関数内で、Cコンパイラに渡す引数のリストから-fno-eliminate-unused-debug-typesフラグが削除されています。

--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -742,13 +742,12 @@ func gccTmp() string {
 // the input.
 func (p *Package) gccCmd() []string {
 	c := append(p.gccBaseCmd(),
-		"-w",                                // no warnings
-		"-Wno-error",                        // warnings are not errors
-		"-o"+gccTmp(),                       // write object to tmp
-		"-gdwarf-2",                         // generate DWARF v2 debugging symbols
-		"-fno-eliminate-unused-debug-types", // gets rid of e.g. untyped enum otherwise
-		"-c",  // do not link
-		"-xc", // input language is C
+		"-w",          // no warnings
+		"-Wno-error",  // warnings are not errors
+		"-o"+gccTmp(), // write object to tmp
+		"-gdwarf-2",   // generate DWARF v2 debugging symbols
+		"-c",          // do not link
+		"-xc",         // input language is C
 	)
 	if strings.Contains(c[0], "clang") {
 		c = append(c,

コアとなるコードの解説

変更はsrc/cmd/cgo/gcc.go内のgccCmd()関数にあります。この関数は、cgoがCコンパイラ(通常はGCCまたはClang)を呼び出す際に使用するコマンドライン引数のスライス([]string)を構築します。

元のコードでは、append関数を使って、基本的なコンパイラコマンド(p.gccBaseCmd())に続けて、以下のようなフラグを追加していました。

		"-w",                                // no warnings
		"-Wno-error",                        // warnings are not errors
		"-o"+gccTmp(),                       // write object to tmp
		"-gdwarf-2",                         // generate DWARF v2 debugging symbols
		"-fno-eliminate-unused-debug-types", // gets rid of e.g. untyped enum otherwise
		"-c",  // do not link
		"-xc", // input language is C

このコミットでは、このリストから-fno-eliminate-unused-debug-typesの行が完全に削除されています。

		"-w",          // no warnings
		"-Wno-error",  // warnings are not errors
		"-o"+gccTmp(), // write object to tmp
		"-gdwarf-2",   // generate DWARF v2 debugging symbols
		"-c",          // do not link
		"-xc",         // input language is C

この変更により、cgoがCコードをコンパイルする際に、Cコンパイラに対して-fno-eliminate-unused-debug-typesフラグが渡されなくなります。これは、前述の「変更の背景」と「技術的詳細」で説明したように、このフラグがもはや必要なく、むしろ新しいバージョンのclangではビルドエラーを引き起こすようになったためです。

その他のフラグ(-w, -Wno-error, -o, -gdwarf-2, -c, -xc)はそのまま残されており、これらは引き続きCコードのコンパイルとデバッグ情報の生成(DWARF v2形式)に必要不可欠なものです。

この変更は、cgoのビルドプロセスを現代のコンパイラ環境(特にOS X上のclang)に適合させ、ビルドの安定性を向上させることを目的としています。

関連リンク

参考にした情報源リンク