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

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

このコミットは、Go言語のビルドシステムにおける問題、特にcmd/distツールに関連するビルドの修正を目的としています。具体的には、src/cmd/dist/buildgo.cという新しいC言語のソースファイルを追加することで、cmd/goおよびcmd/cgoが使用するデフォルトのCコンパイラ情報を生成するメカニズムを導入しています。この修正は、以前のコミットでファイルがバージョン管理システム(Mercurial)に追加されていなかったために発生したビルドエラーを解決するものです。

コミット

commit b8c8cb85092aba7dda9b5f27b1a6c940aaf3c985
Author: Russ Cox <rsc@golang.org>
Date:   Fri Aug 2 15:20:42 2013 -0400

    cmd/dist: fix build again
    
    I am really bad at this. Didn't hg add this file.
    
    TBR=bradfitz
    CC=golang-dev
    https://golang.org/cl/12372043
---
 src/cmd/dist/buildgo.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/src/cmd/dist/buildgo.c b/src/cmd/dist/buildgo.c
new file mode 100644
index 0000000000..a7602d9edd
--- /dev/null
+++ b/src/cmd/dist/buildgo.c
@@ -0,0 +1,44 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "a.h"
+
+/*
+ * Helpers for building cmd/go and cmd/cgo.
+ */
+
+// mkzdefaultcc writes zdefaultcc.go:
+//
+//
+//	package main
+//	const defaultCC = <defaultcc>
+//
+// It is invoked to write cmd/go/zdefaultcc.go
+// but we also write cmd/cgo/zdefaultcc.go.
+void
+mkzdefaultcc(char *dir, char *file)
+{
+	Buf b, out;
+	
+	USED(dir);
+
+	binit(&out);
+	bprintf(&out,
+		"// auto generated by go tool dist\\n"
+		"\\n"
+		"package main\\n"
+		"\\n"
+		"const defaultCC = `%s`\\n",
+		defaultcc);
+
+	writefile(&out, file, 0);
+
+	// Convert file name to replace.
+	binit(&b);	
+	bwritestr(&b, file);
+	bsubst(&b, "/go/zdefaultcc.go", "/cgo/zdefaultcc.go");
+	writefile(&out, bstr(&b), 0);
+
+	bfree(&b);
+	bfree(&out);
+}

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

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

元コミット内容

cmd/dist: fix build again I am really bad at this. Didn't hg add this file.

このコミットは、Goのビルドツールであるcmd/distのビルド問題を再度修正するものです。コミットメッセージには、作者であるRuss Cox氏が「私はこれが本当に苦手だ。このファイルをhg addし忘れていた」と述べており、以前のコミットで必要なファイルがMercurial(hg)リポジトリに追加されていなかったことが原因でビルドが失敗していたことを示唆しています。

変更の背景

この変更の背景には、Go言語のビルドプロセスにおける依存関係の管理ミスがあります。Goのビルドシステムは、Go自身をビルドするためにcmd/distのような内部ツールを使用します。これらのツールは、Goのソースコードからコンパイラや標準ライブラリなどを生成する役割を担っています。

今回の問題は、zdefaultcc.goというファイルがビルドプロセスで必要とされていたにもかかわらず、以前のコミットでMercurialリポジトリに適切に追加されていなかったために発生しました。Mercurialのhg addコマンドは、新しいファイルをリポジトリの追跡対象に追加するために使用されます。この操作が漏れていたため、ビルドシステムがこのファイルを見つけられず、結果としてビルドが失敗していました。

このコミットは、src/cmd/dist/buildgo.cという新しいC言語のソースファイルを追加することで、この問題を解決します。このCファイルには、zdefaultcc.goを動的に生成するロジックが含まれており、ビルド時に必要なファイルが確実に存在するようにします。これにより、hg addの漏れによるビルド失敗が回避され、Goのビルドプロセスが安定化されます。

前提知識の解説

cmd/dist

cmd/distは、Go言語のソースコードからGoツールチェイン全体(コンパイラ、アセンブラ、標準ライブラリなど)をビルド、テスト、および管理するための内部ツールです。Goの自己ホスト型コンパイラ(Goで書かれたコンパイラがGo自身をコンパイルする)のブートストラッププロセスにおいて重要な役割を果たします。go tool distコマンドとして利用され、Goのバージョン管理、ビルド環境の設定、テストの実行など、Go開発者がGo自身を開発する際に使用する主要なツールの一つです。

zdefaultcc.godefaultCC

zdefaultcc.goは、Goのビルドプロセス中に自動生成されるGoのソースファイルです。このファイルは、cgoツールがC言語のコードをコンパイルする際に使用するデフォルトのCコンパイラ(例: gcc)のパスを定義するdefaultCCという定数を含んでいます。cgoは、GoプログラムからC言語の関数を呼び出すためのメカニズムを提供し、その際にCコンパイラが必要となります。zdefaultcc.goは、Goのビルドシステムが特定の環境(OSやアーキテクチャ)に適したCコンパイラを自動的に選択・設定するために利用されます。

Mercurial (hg) と hg add

Mercurial(hg)は、Gitと同様の分散型バージョン管理システムです。Goプロジェクトは、初期にはMercurialを使用してバージョン管理を行っていました(後にGitに移行)。

  • hg add <ファイル名>: このコマンドは、指定されたファイルをMercurialリポジトリの追跡対象に追加します。新しいファイルを作成した場合、このコマンドを実行しない限り、Mercurialはそのファイルをバージョン管理の対象として認識しません。したがって、hg addを忘れると、そのファイルはコミットに含まれず、他の開発者がリポジトリをクローンまたは更新した際にそのファイルが存在しないため、ビルドエラーなどの問題が発生する可能性があります。

技術的詳細

このコミットで追加されたsrc/cmd/dist/buildgo.cファイルは、mkzdefaultccというC言語の関数を定義しています。この関数の主な目的は、Goのビルドプロセス中にzdefaultcc.goというGoソースファイルを生成することです。

mkzdefaultcc関数の詳細:

  • 引数:
    • char *dir: 生成されるファイルのディレクトリパス(このコミットのコードではUSED(dir);とあり、実際には使用されていませんが、関数のシグネチャに含まれています)。
    • char *file: 生成される最初のzdefaultcc.goファイルのフルパス(例: cmd/go/zdefaultcc.go)。
  • 処理内容:
    1. Buf b, out;: Buf型の変数boutを宣言します。これらは、文字列バッファとして機能し、ファイルの内容を構築するために使用されます。
    2. binit(&out);: outバッファを初期化します。
    3. bprintf(&out, ...);: outバッファに、zdefaultcc.goファイルの内容となるGoのソースコードを書き込みます。このコードは、package mainを宣言し、defaultCCという定数を定義します。defaultCCの値は、defaultccというC言語の変数(おそらくGoのビルドシステムによって設定されるグローバル変数)から取得されます。
      "// auto generated by go tool dist\\n"
      "\\n"
      "package main\\n"
      "\\n"
      "const defaultCC = `%s`\\n",
      defaultcc
      
      このフォーマット文字列は、Goのソースコードとして解釈され、defaultCC定数に現在のデフォルトCコンパイラのパスが埋め込まれます。
    4. writefile(&out, file, 0);: outバッファに格納された内容を、引数fileで指定されたパス(例: cmd/go/zdefaultcc.go)に書き込みます。
    5. cmd/cgo用のファイル生成: ここがこの関数の重要な部分です。
      • binit(&b);: bバッファを初期化します。
      • bwritestr(&b, file);: bバッファに、最初のファイルパス(例: /go/zdefaultcc.go)を書き込みます。
      • bsubst(&b, "/go/zdefaultcc.go", "/cgo/zdefaultcc.go");: bバッファ内の文字列を置換します。具体的には、パス内の/go/zdefaultcc.go/cgo/zdefaultcc.goに変換します。これにより、cmd/cgoディレクトリ用のファイルパスが生成されます。
      • writefile(&out, bstr(&b), 0);: outバッファに格納されている同じ内容を、新しく生成されたパス(例: cmd/cgo/zdefaultcc.go)に書き込みます。これは、cmd/gocmd/cgoの両方が同じdefaultCC定数を持つzdefaultcc.goファイルを必要とすることを示しています。
    6. bfree(&b); bfree(&out);: 使用したバッファを解放します。

このメカニズムにより、zdefaultcc.goファイルがビルド時に動的に生成されるため、手動でバージョン管理システムに追加し忘れるというヒューマンエラーが原因でビルドが失敗するのを防ぐことができます。

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

diff --git a/src/cmd/dist/buildgo.c b/src/cmd/dist/buildgo.c
new file mode 100644
index 0000000000..a7602d9edd
--- /dev/null
+++ b/src/cmd/dist/buildgo.c
@@ -0,0 +1,44 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "a.h"
+
+/*
+ * Helpers for building cmd/go and cmd/cgo.
+ */
+
+// mkzdefaultcc writes zdefaultcc.go:
+//
+//
+//	package main
+//	const defaultCC = <defaultcc>
+//
+// It is invoked to write cmd/go/zdefaultcc.go
+// but we also write cmd/cgo/zdefaultcc.go.
+void
+mkzdefaultcc(char *dir, char *file)
+{
+	Buf b, out;
+	
+	USED(dir);
+
+	binit(&out);
+	bprintf(&out,
+		"// auto generated by go tool dist\\n"
+		"\\n"
+		"package main\\n"
+		"\\n"
+		"const defaultCC = `%s`\\n",
+		defaultcc);
+
+	writefile(&out, file, 0);
+
+	// Convert file name to replace.
+	binit(&b);	
+	bwritestr(&b, file);
+	bsubst(&b, "/go/zdefaultcc.go", "/cgo/zdefaultcc.go");
+	writefile(&out, bstr(&b), 0);
+
+	bfree(&b);
+	bfree(&out);
+}

このコミットでは、src/cmd/dist/buildgo.cという新しいファイルが追加されています。このファイルは、Goのビルドプロセスの一部としてコンパイルされ、mkzdefaultcc関数を提供します。

コアとなるコードの解説

追加されたsrc/cmd/dist/buildgo.cファイルは、Goのビルドシステムが内部的に使用するC言語のヘルパー関数を定義しています。その中心となるのがmkzdefaultcc関数です。

この関数は、Goのソースファイルzdefaultcc.goを生成する役割を担っています。zdefaultcc.goは、Goのmainパッケージに属し、defaultCCという定数を定義します。この定数には、Goのビルド環境におけるデフォルトのCコンパイラのパスが文字列として格納されます。

特筆すべきは、mkzdefaultcc関数が、引数で渡されたファイルパス(例: cmd/go/zdefaultcc.go)に加えて、パスを操作してcmd/cgo/zdefaultcc.goという別のファイルも生成している点です。これは、cmd/gocmd/cgoの両方が、それぞれ自身のビルドプロセスでデフォルトのCコンパイラ情報を必要とするためです。同じ内容のファイルを2つの異なる場所に生成することで、両方のツールが適切に機能するようにしています。

このCコードは、GoのビルドプロセスがC言語のツール(この場合はcmd/distの一部)を利用して、Go言語のソースコードを動的に生成するという、Goのブートストラッププロセスの複雑さの一端を示しています。

関連リンク

参考にした情報源リンク