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

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

このコミットは、Go言語プロジェクトのlib9ライブラリに対する重要な変更を導入しています。主な目的は、lib9を「自動ビルドに対して安全にする」こと、すなわち、異なるオペレーティングシステム(特にWindowsと非Windowsシステム)上でのビルドの堅牢性と移植性を向上させることです。具体的には、Unix固有の機能の削除または条件付きコンパイル、およびファイル名の命名規則の統一が行われています。

コミット

commit b53ce1e66221be41a0b869869ceba73b795c8c3e
Author: Russ Cox <rsc@golang.org>
Date:   Wed Feb 1 18:25:40 2012 -0500

    lib9: make safe for automatic builds

    R=golang-dev, adg, bradfitz
    CC=golang-dev
    https://golang.org/cl/5615046

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

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

元コミット内容

lib9: make safe for automatic builds

R=golang-dev, adg, bradfitz
CC=golang-dev
https://golang.org/cl/5615046

変更の背景

このコミットの背景には、Go言語がクロスプラットフォーム対応を強化し、様々な環境での自動ビルドプロセスをよりスムーズにするという目標があります。lib9は、Plan 9オペレーティングシステムのCライブラリをUnix系システムに移植したものであり、Goの初期段階では低レベルのシステム操作や互換性レイヤーのために利用されていました。しかし、lib9にはUnix固有の機能が多く含まれており、これがWindowsなどの非Unix環境でのビルドの障壁となっていました。

「自動ビルドに対して安全にする」という目的は、CI/CD(継続的インテグレーション/継続的デリバリー)システムや、開発者が異なるOS上でGoプロジェクトをビルドする際に、予期せぬコンパイルエラーやランタイムエラーが発生しないようにすることを示唆しています。特に、fork()システムコールやerrnoに基づくエラー処理など、POSIX準拠のシステムに特化した機能は、Windowsでは利用できないか、異なる動作をするため、これらを適切に扱う必要がありました。

前提知識の解説

  • lib9: Plan 9オペレーティングシステムの標準Cライブラリ(libc)のサブセットを、Unix系システム(Linux, macOSなど)に移植したものです。Plan 9はベル研究所で開発された実験的なOSで、その設計思想やAPIはGo言語にも大きな影響を与えています。lib9は、Goの初期のランタイムや標準ライブラリの一部で、Plan 9の哲学に基づいた低レベルの操作を提供するために使用されていました。
  • Goビルドタグ (// +build): Goのソースファイルに記述される特殊なコメントで、そのファイルがどの環境でコンパイルされるべきかを制御します。例えば、// +build windowsはWindowsでのみコンパイルされることを意味し、// +build !windowsはWindows以外のシステムでのみコンパイルされることを意味します。これにより、OS固有のコードを分離し、クロスプラットフォーム対応を容易にします。
  • fork()システムコール: Unix系OSにおけるプロセス生成のためのシステムコールです。親プロセスを複製して新しい子プロセスを作成します。Windowsには直接的なfork()に相当するAPIは存在せず、プロセス生成にはCreateProcessなどの異なるAPIを使用します。
  • strerror(errno): C言語の標準ライブラリ関数で、グローバル変数errnoに格納されたエラーコードに対応するエラーメッセージ文字列を返します。errnoはPOSIX標準の一部であり、Unix系システムで広く使われるエラー報告メカニズムです。Windowsではエラー処理のメカニズムが異なります(例: GetLastError()FormatMessage())。

技術的詳細

このコミットは、lib9のクロスプラットフォーム互換性を向上させるために、以下の主要な技術的変更を加えています。

  1. Unix固有機能の削除:

    • src/lib9/fmt/errfmt.cの削除: このファイルには__errfmt関数が含まれており、内部でstrerror(errno)を使用していました。errnostrerrorはUnix固有のエラー処理メカニズムであるため、これを削除することで、Goのエラー処理をよりポータブルな方法に統一するか、あるいはこの機能がもはやlib9のスコープ外になったことを示しています。Go自体は独自の強力なエラー処理メカニズム(errorインターフェース)を持っているため、Cライブラリのerrnoに依存する部分は不要になったと考えられます。
    • src/lib9/fork.cの削除: このファイルにはp9fork関数が含まれており、これはUnixのfork()システムコールをラップしていました。fork()はWindowsでは利用できないため、このファイルの削除は、lib9が直接的なプロセスフォークに依存するのをやめ、Goのランタイムが提供するより抽象化されたプロセス管理機能(例: os/execパッケージ)に移行したことを意味します。これにより、Windows上でのビルド時のリンカーエラーやランタイムエラーが回避されます。
  2. 条件付きコンパイルの導入:

    • src/lib9/await.c, src/lib9/getuser.c, src/lib9/jmp.c, src/lib9/notify.c, src/lib9/rfork.cの各ファイルの先頭に// +build !windowsディレクティブが追加されました。これは、これらのファイルがWindows以外のシステムでのみコンパイルされるべきであることをGoのビルドシステムに指示します。これらのファイルは、それぞれawait(子プロセスの終了待機)、getuser(ユーザー情報の取得)、jmpsetjmp/longjmpのような非ローカルジャンプ)、notify(シグナル通知)、rfork(Plan 9スタイルのリソースフォーク)といった、Unix系OSに特有の機能や概念に関連しています。これにより、Windowsビルドからこれらの非互換なコードが自動的に除外され、ビルドエラーを防ぎます。
  3. ファイル名の命名規則の統一:

    • src/lib9/win32.csrc/lib9/windows.cにリネームされました。これは、Goの標準的な命名規則(OS名を小文字で統一する)に合わせるための変更です。Goのビルドタグもwindowsと小文字で記述されるため、ファイル名もそれに合わせることで、一貫性と可読性が向上します。Makefileもこの変更に合わせてwin32.$Oからwindows.$Oに修正されています。

これらの変更は、lib9がGoのクロスプラットフォーム戦略に適合し、より広範な環境で安定して動作するための基盤を固めるものです。

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

このコミットにおける主要なコード変更は以下の通りです。

  • src/lib9/Makefile:

    --- a/src/lib9/Makefile
    +++ b/src/lib9/Makefile
    @@ -85,7 +85,7 @@ LIB9OFILES=\
     
     ifeq ($(GOHOSTOS),windows)
     LIB9OFILES+=\
    -	win32.$O\
    +	windows.$O\
     
     else
     LIB9OFILES+=\
    

    win32.$Oというオブジェクトファイル名がwindows.$Oに変更されています。

  • src/lib9/await.c, src/lib9/getuser.c, src/lib9/jmp.c, src/lib9/notify.c, src/lib9/rfork.c: これらの各ファイルの先頭に以下の行が追加されています。

    // +build !windows
    
  • src/lib9/fmt/errfmt.c: ファイル全体が削除されました。

    --- a/src/lib9/fmt/errfmt.c
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -/*
    - * The authors of this software are Rob Pike and Ken Thompson,
    - * with contributions from Mike Burrows and Sean Dorward.
    - * ... (省略) ...
    - */
    -
    -#include <u.h>
    -#include <libc.h>
    -#include "fmtdef.h"
    -
    -int
    -__errfmt(Fmt *f)
    -{
    -	char *s;
    -
    -	s = strerror(errno);
    -	return fmtstrcpy(f, s);
    -}
    
  • src/lib9/fork.c: ファイル全体が削除されました。

    --- a/src/lib9/fork.c
    +++ /dev/null
    @@ -1,46 +0,0 @@
    -/*
    -Plan 9 from User Space src/lib9/fork.c
    -... (省略) ...
    -*/
    -#include <u.h>
    -#include <signal.h>
    -#include <libc.h>
    -#include "9proc.h"
    -#undef fork
    -
    -int
    -p9fork(void)
    -{
    -	int pid;
    -	sigset_t all, old;
    -
    -	sigfillset(&all);
    -	sigprocmask(SIG_SETMASK, &all, &old);
    -	pid = fork();
    -	if(pid == 0){
    -		_clearuproc();
    -		_p9uproc(0);
    -	}
    -	sigprocmask(SIG_SETMASK, &old, nil);
    -	return pid;
    -}
    
  • src/lib9/win32.c: ファイル名がsrc/lib9/windows.cにリネームされました。内容に変更はありません。

コアとなるコードの解説

  • Makefileの変更: この変更は、ビルドシステムがWindows固有のオブジェクトファイルをリンクする際に、新しい命名規則windows.$Oを使用するように指示しています。これは、ファイル名のリネームと同期した変更であり、ビルドプロセスの一貫性を保つために不可欠です。

  • // +build !windowsディレクティブの追加: これはGoのビルドタグの典型的な使用例です。await.cgetuser.cjmp.cnotify.crfork.cといったファイルは、Unix系システムに深く根ざした機能を提供しています。例えば、await.cは子プロセスの終了を待つ機能、jmp.cはC言語のsetjmp/longjmpに似た非ローカルジャンプ機能を提供している可能性があります。これらの機能はWindowsでは異なるAPIで実装されるか、Goのランタイムが提供する抽象化された機能で代替されるため、Windowsビルドから除外することで、コンパイルエラーや互換性の問題を回避します。

  • errfmt.cの削除: errfmt.cstrerror(errno)を使用してエラーメッセージをフォーマットしていました。Goは独自の強力なエラー処理メカニズム(errorインターフェース)を持っているため、C言語のerrnoに依存するこの種のユーティリティは、Goの標準ライブラリやランタイムの進化に伴い不要になったか、よりGoらしい方法で再実装されたと考えられます。これにより、lib9の依存関係が簡素化され、クロスプラットフォームでのエラー処理の統一が図られます。

  • fork.cの削除: fork.cはUnixのfork()システムコールをラップしていました。Goは軽量な並行処理の単位であるゴルーチン(goroutine)と、それらを管理するランタイムを持っています。プロセス生成に関しても、os/execパッケージなどを通じてOSに依存しない抽象化されたインターフェースを提供しています。fork.cの削除は、lib9が直接的なfork()の使用から脱却し、Goのネイティブな並行処理およびプロセス管理モデルに完全に移行したことを示しています。これは、特にWindowsのようなfork()が存在しない環境でのGoの移植性を大幅に向上させるための重要なステップです。

  • win32.cからwindows.cへのリネーム: これは主に命名規則の統一とコードベースの整理を目的とした変更です。Goコミュニティでは、OS固有のファイルやビルドタグに小文字のOS名を使用する慣習があります(例: linux, windows, darwin)。このリネームにより、lib9内のファイル名がGoの一般的な慣習に沿うようになり、コードベース全体の整合性が向上します。

これらの変更は全体として、lib9をよりモジュール化し、Goのクロスプラットフォーム戦略に適合させることを目指しています。Unix固有の依存関係を減らし、Goのビルドタグを活用することで、異なるOS上でのGoアプリケーションのビルドと実行の信頼性を高めています。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Plan 9 from User Spaceのソースコードとドキュメント
  • C言語の標準ライブラリ関数に関する一般的な知識
  • UnixおよびWindowsのシステムプログラミングに関する一般的な知識
  • Go言語のコミット履歴と関連するコードレビュー(CL: Change List)