[インデックス 17933] ファイルの概要
このコミットは、Go言語のビルドシステムにおいて、Plan 9オペレーティングシステム上でのlibbio
ライブラリの扱いと、GNU Bisonによって生成されたファイルのコンパイルに関する変更を導入しています。具体的には、Plan 9環境でGoをビルドする際に、ホストシステムが提供するlibbio
を使用しないようにし、Go自身のlibbio
実装を使用するように修正しています。また、Plan 9コンパイラがGNU Bisonが生成するファイル(y.tab.c
, y.tab.h
)を適切に処理できるように、コンパイルフラグを調整しています。
コミット
commit 66c32384dda82752deb3db8ba45acb073e9c4c1e
Author: Anthony Martin <ality@pbrane.org>
Date: Mon Dec 9 18:39:58 2013 -0500
build: do not use the host's libbio on Plan 9
R=jas, lucio.dere, rsc
CC=golang-dev
https://golang.org/cl/14604047
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/66c32384dda82752deb3db8ba45acb073e9c4c1e
元コミット内容
build: do not use the host's libbio on Plan 9
R=jas, lucio.dere, rsc
CC=golang-dev
https://golang.org/cl/14604047
変更の背景
このコミットの背景には、Go言語のビルドプロセスが様々なオペレーティングシステム(特にPlan 9のような非UNIX系システム)で一貫して動作するようにするための努力があります。
-
Plan 9における
libbio
の競合: Plan 9は独自の標準ライブラリとシステムコールセットを持っています。Goのランタイムやツールチェーンの一部は、内部的に独自のI/Oバッファリングライブラリであるlibbio
を使用しています。しかし、Plan 9システム自体も同名のlibbio
を提供しており、これがGoのビルドプロセスにおいて意図しない競合や依存関係の問題を引き起こす可能性がありました。Goのビルドシステムがホストのlibbio
に依存してしまうと、Go自身のlibbio
実装が持つ特定の機能や最適化が利用できなくなったり、ビルド環境によって動作が不安定になったりする恐れがありました。このコミットは、Goが自身の提供するlibbio
を確実に使用するようにすることで、ビルドの信頼性と移植性を向上させることを目的としています。 -
GNU Bison生成ファイルのコンパイル問題: GNU Bisonは、パーサーやレキシカルアナライザーを生成するためのツールです。Goのツールチェーン(特にリンカやコンパイラの一部)は、内部的にBisonによって生成されたC言語のソースファイルを使用している場合があります。Plan 9のCコンパイラは、UNIX系のGCCなどとは異なる挙動や、特定のC言語の構文・マクロの解釈に違いがあることが知られています。特に、Bisonが生成するファイルには、Plan 9コンパイラがそのままでは処理できないようなマクロや構造が含まれることがありました。以前のGoのビルドスクリプトでは、Plan 9上でBison生成ファイルをコンパイルする際に、外部プリプロセッサ(
-Bp+
フラグ)を使用するなどの特別な対応が試みられていましたが、これが不十分であったり、より直接的な解決策が必要とされていました。このコミットは、Plan 9コンパイラに適切な定義(__STDC__=1
,__SIZE_TYPE__=ulong
など)を渡すことで、Bison生成ファイルが正しくコンパイルされるように修正しています。
これらの問題に対処することで、Go言語のツールチェーンがPlan 9環境でより堅牢に、かつ意図した通りに動作するようになります。
前提知識の解説
このコミットを理解するためには、以下の技術的な概念について知っておく必要があります。
-
Plan 9 from Bell Labs:
- ベル研究所で開発された分散オペレーティングシステム。UNIXの後継として設計され、"Everything is a file"という哲学に基づいています。
- ファイルシステムを通じてリソースを抽象化し、ネットワーク透過性を重視しています。
- 独自のCコンパイラ(
8c
,6c
,5c
など、ターゲットアーキテクチャに応じて異なる)と標準ライブラリを持っています。これらのコンパイラは、GCCなどの一般的なUNIX系コンパイラとは異なる挙動や、サポートするC言語の機能に差異がある場合があります。 - Go言語は、その設計思想の一部にPlan 9の影響を受けており、初期のGoコンパイラやツールチェーンはPlan 9のツールチェーンをベースにしていました。
-
libbio
:- "Buffered I/O"(バッファリングされた入出力)の略。
- ファイルやネットワークソケットからの読み書きを効率化するために、内部的にデータをバッファリングするライブラリです。
- Go言語のツールチェーン内部でも、ファイル操作などのために独自の
libbio
実装を使用しています。 - Plan 9システム自体も、同様の目的で
libbio
という名前のライブラリを提供しています。この名前の重複が、ビルド時の問題の原因となることがあります。
-
GNU Bison:
- GNU Projectが開発しているパーサージェネレータ。Yacc(Yet Another Compiler Compiler)のGNU版です。
- 文法定義ファイル(通常
.y
または.yy
拡張子)から、C言語(またはC++、Javaなど)のソースコードを生成します。この生成されたコードは、入力ストリームを解析し、文法規則に従ってアクションを実行するパーサーとなります。 - 生成されるC言語のファイルは、通常
y.tab.c
(パーサーの実装)とy.tab.h
(トークン定義など)という名前になります。 - これらの生成ファイルは、特定のC言語の機能やマクロ(例:
YYSTYPE
,YYLTYPE
など)を多用するため、コンパイラによっては特別なコンパイルオプションや定義が必要になることがあります。
-
Goのビルドシステム (
src/cmd/dist/build.c
):- Go言語のソースコードから、コンパイラ、リンカ、標準ライブラリなどのツールチェーン全体をビルドするためのC言語製のプログラムです。
- クロスコンパイル(異なるOSやアーキテクチャ向けのバイナリを生成すること)をサポートしており、
GOOS
(ターゲットOS)やGOARCH
(ターゲットアーキテクチャ)といった環境変数に基づいてビルドの挙動を調整します。 - このビルドスクリプトは、C言語のソースファイルをコンパイルする際に、ターゲットOSやアーキテクチャに応じた適切なコンパイラフラグを渡す役割を担っています。
-
プリプロセッサ (
#include
,#define
):- C言語のコンパイルプロセスの一部で、ソースコードがコンパイラに渡される前に処理されます。
#include
は、別のファイルのコンテンツを現在のファイルに挿入します。#define
は、マクロを定義します。これは、コンパイル時にテキスト置換が行われるものです。- コンパイラによっては、外部プリプロセッサを使用したり、特定のプリプロセッサ定義(
-D
フラグで指定)を渡すことで、コードの挙動を制御できます。
これらの知識は、コミットがなぜ特定のファイルを変更し、なぜ特定のコンパイルフラグを追加・削除したのかを理解する上で不可欠です。
技術的詳細
このコミットは、Go言語のビルドプロセスにおけるPlan 9固有の課題に対処するために、複数のファイルにわたる変更を行っています。
-
include/bio.h
からfcntl.h
の削除:- 変更前:
include/bio.h
はfcntl.h
をインクルードしていました。fcntl.h
はファイル制御操作(例:O_RDONLY
,O_WRONLY
)を定義するヘッダファイルで、主にUNIX系システムで使われます。 - 変更後:
fcntl.h
のインクルードが削除されました。これは、Go自身のlibbio
実装がPlan 9環境でホストのfcntl.h
に依存しないようにするため、またはGoのlibbio
がこれらの定義を内部的に持っているためと考えられます。これにより、Plan 9のシステムヘッダとの潜在的な競合や不必要な依存関係が解消されます。
- 変更前:
-
include/plan9/bio.h
の新規作成:- このコミットの最も重要な変更点の一つです。
include/plan9/bio.h
という新しいヘッダファイルが作成されました。- このファイルは、
#include "../bio.h"
を通じてGo自身のinclude/bio.h
をインクルードします。 - さらに、
#define fmtcharstod charstod
と#define lseek seek
というマクロ定義が含まれています。fmtcharstod
とcharstod
、lseek
とseek
は、Plan 9のCライブラリにおける関数名や型名の慣習が、Goの内部コードで使用されている名前と異なる場合に、互換性を提供するためのエイリアス定義と考えられます。これにより、GoのコードがPlan 9環境でコンパイルされる際に、Plan 9の標準的な関数名に自動的にマッピングされ、コンパイルエラーを回避できます。
-
src/cmd/dist/build.c
の変更:- このファイルはGoのビルドスクリプトの中核であり、コンパイルオプションやビルドロジックを制御します。
libbio.a
の除外ロジックの削除:- 変更前: Plan 9ホストで
libbio.a
がビルドされる場合、それをスキップするロジックがありました (if(streq(gohostos, "plan9") && hassuffix(p, "libbio.a")) continue;
)。これは、ホストのlibbio
を使用するという前提があったため、Go自身のlibbio
をビルドしないようにしていた可能性があります。 - 変更後: このロジックが削除されました。これは、Goが自身の
libbio
をビルドし、それを使用するように方針が変更されたことを意味します。これにより、Goのツールチェーンは自身のlibbio
実装に依存し、ホストのlibbio
との競合を避けることができます。
- 変更前: Plan 9ホストで
- GNU Bison生成ファイルのコンパイルロジックの変更:
- 変更前: Plan 9ホストで
y.tab.c
やy.tab.h
のようなBison生成ファイルが見つかった場合、外部プリプロセッサを使用するために-Bp+
フラグを追加していました。 - 変更後: この
-Bp+
フラグを使用するロジックが完全に削除されました。代わりに、Plan 9コンパイラに対して以下の新しいコンパイルフラグが追加されました。-FTVwp
: Plan 9コンパイラの特定のオプション。詳細な意味はコンパイラのドキュメントに依存しますが、通常は警告レベル、最適化、デバッグ情報などに関連します。-DPLAN9
:PLAN9
マクロを定義します。これにより、Goのソースコード内で#ifdef PLAN9
のような条件付きコンパイルが可能になり、Plan 9固有のコードパスを有効にできます。-D__STDC__=1
:__STDC__
マクロを1に定義します。これは、コンパイラがC標準に準拠していることを示すために使用されることが多く、Bison生成ファイルが期待する標準Cの挙動を保証するのに役立ちます。-D__SIZE_TYPE__=ulong
:__SIZE_TYPE__
マクロをulong
(符号なし長整数)に定義します。GNU Bisonが生成するコードは、内部的にsize_t
型(通常は__SIZE_TYPE__
によって定義される)を使用することがあります。Plan 9のCコンパイラがデフォルトでsize_t
を適切に扱わない場合、この定義によって互換性が確保されます。
// Work around Plan 9 C compiler's handling of #include with .. path.
というコメントと共にあった-I%s/src/cmd/ld
の追加も削除されました。これは、include/plan9/bio.h
の導入や他の変更により、相対パスのインクルードに関する問題が解決されたためと考えられます。
- 変更前: Plan 9ホストで
shouldbuild
関数の変更:libbio
ディレクトリ内のファイルをビルドしないようにするロジックが削除されました。これは、Goが自身のlibbio
をビルドするようになったため、この除外が不要になったことを裏付けています。
-
src/libbio/bgetrune.c
,src/libbio/bputrune.c
からutf.h
の削除:- これらのファイルは、Goの内部
libbio
実装の一部です。 - 変更前:
utf.h
をインクルードしていました。 - 変更後:
utf.h
のインクルードが削除されました。これは、libbio
のこれらの部分がUTF-8処理に直接依存しなくなったか、またはUTF-8関連の機能が別の方法で提供されるようになったためと考えられます。これにより、不必要な依存関係が減少し、コードのクリーンアップが図られています。
- これらのファイルは、Goの内部
-
src/libbio/bprint.c
の変更:fmtlocaleinit
関数の呼び出しが#ifndef PLAN9
で囲まれました。- これは、
fmtlocaleinit
関数がPlan 9環境では利用できないか、または異なる方法で初期化される必要があることを示しています。Plan 9ではロケール(地域設定)の概念がUNIX系システムとは異なるため、この関数が不要または互換性がない可能性があります。
-
src/libbio/bseek.c
の変更:sizeof(offset) != sizeof(off_t)
のチェックが、#if !defined(_WIN32)
から#if !defined(_WIN32) && !defined(PLAN9)
に変更されました。- これは、Plan 9環境でも
off_t
のサイズに関する特定のチェックをスキップするように指示しています。Plan 9のファイルシステムやI/Oインターフェースは、UNIX系のoff_t
とは異なるオフセット型を使用する可能性があるため、このチェックがPlan 9では不適切であると判断されたためです。
これらの変更は、GoのビルドシステムがPlan 9という特定の環境で、より正確かつ堅牢に動作するようにするための、細部にわたる調整を示しています。特に、Go自身のlibbio
実装を優先し、Plan 9コンパイラの特性に合わせたコンパイルオプションを適用することで、クロスプラットフォーム対応を強化しています。
コアとなるコードの変更箇所
このコミットのコアとなる変更は、主に以下の3つの領域に集中しています。
-
include/plan9/bio.h
の新規追加:--- /dev/null +++ b/include/plan9/bio.h @@ -0,0 +1,8 @@ +// Copyright 2013 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 "../bio.h" + +#define fmtcharstod charstod +#define lseek seek
-
src/cmd/dist/build.c
におけるPlan 9向けコンパイルフラグの調整とlibbio
関連ロジックの削除:--- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -778,8 +778,6 @@ install(char *dir) bsubst(&b1, "$GOARCH", goarch); p = bstr(&b1); if(hassuffix(p, ".a")) { - if(streq(gohostos, "plan9") && hassuffix(p, "libbio.a")) - continue; vadd(&lib, bpathf(&b, "%s", p)); continue; } @@ -933,20 +931,6 @@ install(char *dir) goto nobuild; } - // The files generated by GNU Bison use macros that aren't - // supported by the Plan 9 compilers so we have to use the - // external preprocessor when compiling. - usecpp = 0; - if(streq(gohostos, "plan9")) { - for(i=0; i<files.len; i++) { - p = files.p[i]; - if(hassuffix(p, "y.tab.c") || hassuffix(p, "y.tab.h")){ - usecpp = 1; - break; - } - } - } - // Compile the files. for(i=0; i<files.len; i++) { if(!hassuffix(files.p[i], ".c") && !hassuffix(files.p[i], ".s")) @@ -958,13 +942,12 @@ install(char *dir) // C library or tool. if(streq(gohostos, "plan9")) { vadd(&compile, bprintf(&b, "%sc", gohostchar)); - vadd(&compile, "-FTVw"); - if(usecpp) - vadd(&compile, "-Bp+"); + vadd(&compile, "-FTVwp"); + vadd(&compile, "-DPLAN9"); + vadd(&compile, "-D__STDC__=1"); + vadd(&compile, "-D__SIZE_TYPE__=ulong"); // for GNU Bison vadd(&compile, bpathf(&b, "-I%s/include/plan9", goroot)); vadd(&compile, bpathf(&b, "-I%s/include/plan9/%s", goroot, gohostarch)); - // Work around Plan 9 C compiler's handling of #include with .. path. - vadd(&compile, bpathf(&b, "-I%s/src/cmd/ld", goroot)); } else { vcopy(&compile, gccargs.p, gccargs.len); vadd(&compile, "-c"); @@ -1167,8 +1150,6 @@ shouldbuild(char *file, char *dir) if(!contains(name, "plan9")) return 0; } - if(streq(dir, "libbio")) - return 0; } // Check file name for GOOS or GOARCH.
-
src/libbio/bprint.c
におけるfmtlocaleinit
の条件付きコンパイル:--- a/src/libbio/bprint.c +++ b/src/libbio/bprint.c @@ -67,7 +67,9 @@ Bvprint(Biobuf *bp, char *fmt, va_list arg) Fmt f; memset(&f, 0, sizeof f); +#ifndef PLAN9 fmtlocaleinit(&f, nil, nil, nil); +#endif f.stop = bp->ebuf; f.to = (char*)f.stop + bp->ocount; f.flush = bflush;
コアとなるコードの解説
-
include/plan9/bio.h
の新規追加:- このファイルは、GoのビルドシステムがPlan 9環境でGo自身の
libbio
を使用するための重要なブリッジです。 #include "../bio.h"
: これは、Goのソースツリー内の共通のbio.h
ヘッダファイル(include/bio.h
)をインクルードします。これにより、Goのlibbio
のAPI定義がPlan 9固有のビルドパスでも利用可能になります。#define fmtcharstod charstod
と#define lseek seek
: これらのマクロは、Plan 9のCライブラリの慣習とGoの内部コードの間に互換性レイヤーを提供します。Plan 9では、UNIX系システムで一般的なlseek
関数がseek
という名前であったり、特定のフォーマット関数名が異なったりすることがあります。これらのマクロ定義により、Goのコードがこれらの異なる名前を使用している場合でも、Plan 9コンパイラが正しく解決できるようになります。これは、Goのコードベースが複数のプラットフォームで共通のソースを使用しつつ、各プラットフォームの特性に合わせた調整を行う典型的な方法です。
- このファイルは、GoのビルドシステムがPlan 9環境でGo自身の
-
src/cmd/dist/build.c
における変更:libbio.a
の除外ロジックの削除: 以前は、Plan 9上でlibbio.a
がビルドされるのを意図的にスキップしていました。これは、ホストのPlan 9システムが提供するlibbio
を使用するという前提があったためです。このロジックの削除は、GoのビルドシステムがPlan 9においてもGo自身のlibbio
をビルドし、それを使用するように方針転換したことを明確に示しています。これにより、Goのツールチェーンは自身の依存関係をより厳密に管理し、ホスト環境からの影響を減らすことができます。- GNU Bison生成ファイルのコンパイルフラグの調整:
- 以前の
-Bp+
(外部プリプロセッサの使用)の削除は、Plan 9コンパイラが内部的にプリプロセッサをより適切に処理できるようになったか、または新しいフラグの組み合わせで外部プリプロセッサが不要になったことを示唆しています。 -FTVwp
: これはPlan 9コンパイラ(8c
,6c
など)に渡される特定のフラグです。F
はフレームポインタ、T
はトレースバック、V
はバージョン情報、w
は警告の抑制、p
はプロファイリングなど、コンパイラの挙動を細かく制御するものです。これらのフラグは、Bison生成ファイルのような複雑なCコードをコンパイルする際に、特定の最適化やデバッグ情報、または互換性モードを有効にするために使用されます。-DPLAN9
,-D__STDC__=1
,-D__SIZE_TYPE__=ulong
: これらの-D
フラグは、プリプロセッサ定義をコンパイラに渡します。-DPLAN9
: Goのソースコード内で#ifdef PLAN9
のような条件付きコンパイルブロックを有効にし、Plan 9固有のコードパスや最適化を適用できるようにします。-D__STDC__=1
: C標準への準拠を示すマクロです。Bisonが生成するコードは、標準Cの特定の機能や挙動に依存していることが多いため、この定義はコンパイラが標準に準拠したモードでコンパイルを行うことを保証し、互換性の問題を回避します。-D__SIZE_TYPE__=ulong
: GNU Bisonが生成するコードは、size_t
型を内部的に使用することがあります。Plan 9のCコンパイラがsize_t
のデフォルト定義を異なるものとして扱ったり、特定のアーキテクチャで問題が発生したりする場合、このマクロ定義によってsize_t
がulong
(符号なし長整数)として扱われることを明示的に指定し、型の一貫性と正しいメモリサイズ計算を保証します。
-I%s/src/cmd/ld
の削除: 以前は、Plan 9コンパイラが..
を含むインクルードパスを正しく扱えない問題へのワークアラウンドとして、このパスが追加されていました。この削除は、他の変更(特にinclude/plan9/bio.h
の導入)によってこの問題が解決されたか、またはPlan 9コンパイラのバージョンアップによって問題が解消されたことを示唆しています。
- 以前の
-
src/libbio/bprint.c
におけるfmtlocaleinit
の条件付きコンパイル:fmtlocaleinit
関数は、おそらくロケール(地域設定)に関連するフォーマット初期化を行うものです。Plan 9はUNIX系システムとは異なるロケールモデルを持つため、この関数がPlan 9では不要であるか、または異なる実装が必要である可能性があります。#ifndef PLAN9
で囲むことで、Plan 9環境ではこの関数が呼び出されないようにし、ビルドエラーや実行時エラーを防いでいます。
これらの変更は、GoのビルドシステムがPlan 9という特定の、しかしGoにとって歴史的に重要なプラットフォームで、より自律的かつ堅牢に動作するようにするための、きめ細やかな調整を示しています。Go自身のライブラリ実装を優先し、プラットフォーム固有のコンパイラ特性に合わせた調整を行うことで、クロスプラットフォーム開発の複雑さを管理しています。
関連リンク
- Go言語の公式リポジトリ: https://github.com/golang/go
- Go言語のIssueトラッカー (このコミットに関連する可能性のあるIssueやCL): https://golang.org/issue
- Plan 9 from Bell Labs: https://9p.io/plan9/
- GNU Bison 公式サイト: https://www.gnu.org/software/bison/
参考にした情報源リンク
- Go言語のソースコード (特に
src/cmd/dist/build.c
およびsrc/libbio
ディレクトリ) - Plan 9のドキュメンテーション (Cコンパイラのフラグやライブラリに関する情報)
- GNU Bisonのドキュメンテーション (生成されるCコードの特性に関する情報)
- Go言語のコードレビューシステム (Gerrit) の該当コミットのCL (Change List) ページ: https://golang.org/cl/14604047 (コミットメッセージに記載されているURL)
- 一般的なC言語のプリプロセッサとコンパイルに関する知識