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

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

このコミットは、Go言語のビルドツールであるcmd/gocgoツールを呼び出す際に、環境変数CGO_CFLAGSの値を適切にcgoに渡すように修正するものです。これにより、cgoプロジェクトをビルドする際に、代替のインクルードディレクトリが正しく機能するようになります。

コミット

commit eac86fd3f0edb3a82d51c3ced90a73fd17e22d81
Author: Jeff Hodges <jeff@somethingsimilar.com>
Date:   Mon Feb 6 11:26:15 2012 -0500

    cmd/go: pass env CGO_CFLAGS to cgo
    
    Passing the CGO_CFLAGS to cgo is required to make alternative include
    directories work when building a cgo project.
    
    R=rsc
    CC=golang-dev
    https://golang.org/cl/5635048

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

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

元コミット内容

cmd/go: pass env CGO_CFLAGS to cgo

Passing the CGO_CFLAGS to cgo is required to make alternative include
directories work when building a cgo project.

変更の背景

Go言語は、C言語のコードをGoプログラムに組み込むためのcgoというメカニズムを提供しています。cgoを使用すると、GoコードからC関数を呼び出したり、CコードからGo関数を呼び出したりすることができます。Cコードをコンパイルする際には、通常、コンパイラにインクルードパス(ヘッダーファイルがどこにあるかを指定するパス)を渡す必要があります。これはCFLAGSなどのコンパイラフラグを通じて行われます。

cgoを使用するプロジェクトでは、Goのビルドシステムが内部的にCコンパイラを呼び出す前に、cgoツールを介してCコードを処理します。この際、ユーザーが環境変数CGO_CFLAGSを通じて指定した追加のコンパイラフラグ(例えば、-I/path/to/custom/includeのようなインクルードディレクトリの指定)が、cgoツールに正しく渡されないという問題がありました。

この問題により、cgoプロジェクトが、標準以外の場所に存在するヘッダーファイルに依存している場合、ビルドが失敗していました。このコミットは、この問題を解決し、CGO_CFLAGSで指定されたインクルードディレクトリがcgoツールによって適切に処理されるようにすることを目的としています。

前提知識の解説

cgo

cgoは、GoプログラムがC言語のコードと相互運用するためのGoツールチェーンの一部です。Goのソースファイル内にimport "C"という行があると、Goコンパイラはcgoツールを呼び出します。cgoは、GoとCの間のブリッジコードを生成し、Cコンパイラ(通常はGCCやClang)を呼び出してCコードをコンパイルします。

CGO_CFLAGS

CGO_CFLAGSは、cgoがCコンパイラを呼び出す際に使用する追加のCコンパイラフラグを指定するための環境変数です。これには、インクルードパス(-I)、マクロ定義(-D)、警告オプション(-Wall)などが含まれます。例えば、CGO_CFLAGS="-I/usr/local/include"と設定すると、/usr/local/includeがCコンパイラのインクルードパスに追加されます。

Goのビルドプロセスとcgoの役割

Goのビルドプロセスにおいて、cgoが関与する場合の一般的な流れは以下のようになります。

  1. Goのビルドコマンド(go buildなど)が実行されます。
  2. Goのソースコードにimport "C"が含まれている場合、ビルドツールはcgoツールを起動します。
  3. cgoツールは、GoとCの間の相互運用に必要なGoとCのソースファイルを生成します。
  4. cgoは、生成されたCソースファイルと元のCソースファイル(もしあれば)を、CGO_CFLAGSなどの環境変数で指定されたフラグを使用してCコンパイラでコンパイルします。
  5. コンパイルされたCオブジェクトファイルは、Goのビルドプロセスに渡され、最終的なGo実行可能ファイルにリンクされます。

このコミット以前は、ステップ4でCGO_CFLAGScgoツールに適切に渡されていなかったため、Cコンパイラが正しいインクルードパスを知ることができませんでした。

技術的詳細

このコミットの技術的な核心は、Goのビルドシステム(src/cmd/go/build.go内のbuilder構造体とcgoメソッド)が、cgoツールを呼び出す際に、CGO_CFLAGS環境変数の値を明示的に引数として渡すように変更された点です。

以前のコードでは、cgoツールを呼び出すb.run関数に渡される引数リストに、CGO_CFLAGSに相当するものが含まれていませんでした。cgoツール自体は、CGO_CFLAGS環境変数を読み取る能力を持っていますが、Goのビルドシステムがcgoを子プロセスとして起動する際に、この環境変数が子プロセスに継承されない、あるいはcgoが期待する形式でフラグが渡されないという問題があったと考えられます。

この修正により、cgoツールが実行される際に、CGO_CFLAGSで指定されたフラグがコマンドライン引数として明示的に渡されるようになりました。これにより、cgoツールはこれらのフラグをCコンパイラに正しく渡し、結果としてCコンパイラは代替のインクルードディレクトリを認識できるようになります。

具体的には、cgoツールは、コマンドライン引数として渡された-CFLAGS-LDFLAGSなどのフラグを、環境変数から読み取ったものと同様に処理します。この変更は、Goのビルドシステムがcgoツールとの連携をより堅牢にし、ユーザーが指定したビルドオプションが確実に適用されるようにするためのものです。

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

変更はsrc/cmd/go/build.goファイル内のcgo関数にあります。

--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -1183,7 +1183,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
 	if _, ok := buildToolchain.(gccgoToolchain); ok {
 		cgoflags = append(cgoflags, "-gccgo")
 	}
-	if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, cgoflags, "--", p.CgoFiles); err != nil {
+	if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, cgoflags, "--", cgoCFLAGS, p.CgoFiles); err != nil {
 		return nil, nil, err
 	}
 	outGo = append(outGo, gofiles...)

コアとなるコードの解説

変更された行は、b.run関数を呼び出している部分です。b.run関数は、指定された実行可能ファイル(この場合はcgoExe、つまりcgoツール)を、与えられた引数で実行するためのヘルパー関数です。

  • 変更前:

    if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, cgoflags, "--", p.CgoFiles); err != nil {
    

    この行では、cgoExecgoツール)が、-objdirobjcgoflags--p.CgoFilesといった引数で実行されていました。ここでcgoflagsはGoのビルドシステムが内部的に生成するcgo関連のフラグですが、ユーザーが環境変数CGO_CFLAGSで指定した内容は含まれていませんでした。

  • 変更後:

    if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, cgoflags, "--", cgoCFLAGS, p.CgoFiles); err != nil {
    

    変更後では、引数リストに新たにcgoCFLAGSが追加されています。このcgoCFLAGSは、Goのビルドシステムが環境変数CGO_CFLAGSから取得した値を保持する変数です。これにより、ユーザーがCGO_CFLAGSに設定した値が、cgoツールへのコマンドライン引数として明示的に渡されるようになりました。

この修正により、cgoツールは、ユーザーが指定した追加のCコンパイラフラグ(特にインクルードディレクトリの指定)を正しく受け取り、それを内部的に呼び出すCコンパイラに渡すことができるようになります。結果として、代替のインクルードディレクトリにあるヘッダーファイルも正しく見つけられるようになり、cgoプロジェクトのビルドが成功するようになります。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード (src/cmd/go/build.go)
  • Go言語の公式ドキュメント
  • Go言語のコミット履歴と変更リスト (CL)
  • cgoの動作に関する一般的な知識