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

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

このコミットは、Go言語のリンカ(ld)におけるPlan 9ビルドの問題を修正するものです。具体的には、src/cmd/ld/pobj.cファイル内で、ポインタの比較に使用されていたNULLをGo言語の慣習に合わせたnilに置き換えることで、Plan 9環境でのビルドエラーを解消しています。

コミット

commit 2784a3ea8527083a3d819272f879fa508dcca3b5
Author: David du Colombier <0intro@gmail.com>
Date:   Tue Dec 17 08:46:07 2013 -0800

    ld: fix Plan 9 build
    
    R=golang-dev, jas, bradfitz
    CC=golang-dev
    https://golang.org/cl/43420043

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

https://github.com/golang/go/commit/2784a3ea8527083a3d819272f879fa508dcca3b5

元コミット内容

ld: fix Plan 9 build

R=golang-dev, jas, bradfitz
CC=golang-dev
https://golang.org/cl/43420043

変更の背景

このコミットの背景には、Go言語のリンカ(ld)がPlan 9オペレーティングシステム上で正しくビルドされないという問題がありました。Go言語のツールチェインは、様々なプラットフォームをサポートするように設計されており、Plan 9もその一つです。

Go言語のコードベースでは、C言語のコードも多く含まれており、特にツールチェインの低レベル部分(リンカなど)ではC言語の慣習が残っていることがあります。C言語ではヌルポインタを表すためにNULLマクロが一般的に使用されますが、Go言語ではヌルポインタはnilキーワードで表現されます。

この問題は、src/cmd/ld/pobj.cファイル内でheadstring == NULLというC言語式のヌルポインタチェックが行われていたことに起因します。Plan 9環境でのビルドプロセスにおいて、このNULLの定義が問題を引き起こし、コンパイルエラーや予期せぬ動作を招いていたと考えられます。Go言語のコードベース全体で一貫性を保ち、クロスプラットフォームビルドの堅牢性を高めるために、このNULLをGo言語のnilに修正する必要がありました。

前提知識の解説

Go言語のリンカ (ld)

Go言語のリンカは、コンパイラによって生成されたオブジェクトファイル(.oファイル)を結合し、実行可能なバイナリファイルを生成するツールです。Go言語のビルドプロセスにおいて非常に重要な役割を担っており、プログラムが依存するライブラリやランタイムコードを適切にリンクします。ldsrc/cmd/ldディレクトリにソースコードがあります。

Plan 9

Plan 9 from Bell Labsは、ベル研究所で開発された分散オペレーティングシステムです。Unixの後継として設計され、その設計思想はGo言語にも大きな影響を与えています。Go言語は、Plan 9の設計原則、特にシンプルさ、モジュール性、そして強力な並行処理のサポートを多く取り入れています。Go言語のツールチェインは、Plan 9を含む複数のオペレーティングシステムをターゲットとしてビルドできるように設計されています。

HEADTYPEheadstring

Go言語のリンカにおいて、HEADTYPEは生成される実行ファイルのヘッダタイプ(フォーマット)を決定する定数です。例えば、ELF(Linux)、Mach-O(macOS)、PE(Windows)、Plan 9などがこれに該当します。リンカは、ターゲットOSに応じて適切なHEADTYPEを選択し、それに基づいて実行ファイルの構造を決定します。

headstringは、このHEADTYPEに対応する文字列表現を保持する変数です。例えば、HEADTYPEがELFであればheadstringは"ELF"のような値を持つことが考えられます。この変数は、デバッグ情報や内部処理で利用されることがあります。

NULLnil

  • NULL: C言語におけるヌルポインタ定数です。通常、#define NULL ((void*)0)のように定義され、ポインタが何も指していないことを示します。C言語のコードでは、ポインタが有効なメモリを指しているかどうかをチェックするためにif (ptr == NULL)のような形で頻繁に使用されます。
  • nil: Go言語におけるゼロ値の一つで、ポインタ、インターフェース、マップ、スライス、チャネル、関数などの参照型が何も指していないことを示します。Go言語では、C言語のようなNULLマクロは存在せず、ヌルポインタの概念はnilによって統一的に扱われます。Go言語のコードでは、if ptr == nilのように使用されます。

このコミットは、C言語のコードとGo言語のコードが混在するGoツールチェインの文脈で、C言語のNULLがGo言語のnilに置き換えられたという点で重要です。これは、Go言語のコードベース全体での一貫性を保ち、Go言語の慣習に従うための変更と言えます。

技術的詳細

このコミットの技術的な核心は、src/cmd/ld/pobj.cファイル内のポインタ比較の修正です。

変更前のコード:

if (headstring == NULL)

変更後のコード:

if (headstring == nil)

pobj.cは、Go言語のリンカの一部であり、おそらくオブジェクトファイルの処理に関連するC言語のソースファイルです。このファイル内でheadstringという変数が使用されており、その値がヌルであるかどうかをチェックしています。

Go言語のツールチェインは、C言語で書かれた部分とGo言語で書かれた部分が混在しています。特に初期のGo言語のツールチェインや、低レベルのシステムプログラミングに近い部分では、C言語のコードが多用されていました。このようなC言語のコードがGo言語のビルドシステムやランタイムと連携する際に、C言語のNULLとGo言語のnilの間の互換性や定義の差異が問題となることがあります。

この特定のケースでは、Plan 9環境でのビルド時に、C言語のコンパイラがNULLの定義を期待する一方で、Go言語のビルドシステムが提供する環境やヘッダファイルがnilを適切に扱っていた、あるいはNULLの定義が欠落していた、または競合していた可能性があります。

NULLはC言語の標準ライブラリで定義されるマクロであり、その定義はコンパイラやプラットフォームによって異なる場合があります(例: (void*)00Lなど)。一方、nilはGo言語のキーワードであり、Go言語のコンパイラによって直接解釈されます。

この修正は、C言語のコードであってもGo言語のツールチェインの一部としてビルドされる際には、Go言語の慣習であるnilを使用することで、クロスプラットフォームビルドの堅牢性を高め、特にPlan 9のような特定の環境でのビルドエラーを回避することを目的としています。これにより、Go言語のツールチェイン全体の一貫性が向上し、将来的なメンテナンスも容易になります。

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

--- a/src/cmd/ld/pobj.c
+++ b/src/cmd/ld/pobj.c
@@ -138,7 +138,7 @@ main(int argc, char *argv[])
 	if(HEADTYPE == -1)
 		HEADTYPE = headtype(goos);
 	ctxt->headtype = HEADTYPE;
-	if (headstring == NULL)
+	if (headstring == nil)
 		headstring = headstr(HEADTYPE);
 
 	archinit();

コアとなるコードの解説

変更されたコードはsrc/cmd/ld/pobj.cファイルのmain関数内の一部です。

元のコード:

if (headstring == NULL)

この行は、headstringという変数がヌルポインタであるかどうかをC言語のNULLマクロを使ってチェックしていました。もしheadstringがヌルであれば、次の行でheadstr(HEADTYPE)関数を呼び出してその値を初期化します。

変更後のコード:

if (headstring == nil)

この行では、NULLがGo言語のnilキーワードに置き換えられています。機能的には同じヌルポインタチェックを行いますが、Go言語のツールチェインのコンテキストにおいて、nilを使用することでよりGo言語の慣習に沿った形になります。

この変更は、Go言語のツールチェインがC言語とGo言語のコードを混在させている環境で、特にPlan 9のような特定のターゲットプラットフォームでのビルド互換性を確保するために行われました。NULLの定義がプラットフォームやコンパイラによって異なる可能性があるのに対し、nilはGo言語のキーワードとして一貫した振る舞いを保証します。これにより、Plan 9環境でのリンカのビルドが正常に行われるようになりました。

関連リンク

参考にした情報源リンク