[インデックス 10945] ファイルの概要
このコミットは、Go言語の標準ライブラリであるos/user
パッケージにおける、ARMアーキテクチャ環境でCGO(C言語との連携機能)が無効な場合に発生するユーザー情報ルックアップの問題を修正するものです。具体的には、ビルドタグの調整により、CGOが利用できない環境下で適切なユーザー情報取得のスタブ実装が選択されるように変更されています。
コミット
commit 721e19c24c84ef130528901ed8abedfcb49259b1
Author: Russ Cox <rsc@golang.org>
Date: Wed Dec 21 10:17:37 2011 -0500
os/user: fix for arm (non-cgo)
TBR=golang-dev
CC=golang-dev
https://golang.org/cl/5504056
---
src/pkg/os/user/lookup_stubs.go | 2 +-\n src/pkg/os/user/lookup_unix.go | 1 +\n 2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/pkg/os/user/lookup_stubs.go b/src/pkg/os/user/lookup_stubs.go
index 7fc087c4dc..ea01f9683d 100644
--- a/src/pkg/os/user/lookup_stubs.go
+++ b/src/pkg/os/user/lookup_stubs.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build netbsd openbsd plan9 windows
+// +build nocgo
package user
diff --git a/src/pkg/os/user/lookup_unix.go b/src/pkg/os/user/lookup_unix.go
index a77aeb73bb..21c8346b2f 100644
--- a/src/pkg/os/user/lookup_unix.go
+++ b/src/pkg/os/user/lookup_unix.go
@@ -3,6 +3,7 @@
// license that can be found in the LICENSE file.
// +build darwin freebsd linux
+// +build cgo
package user
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/721e19c24c84ef130528901ed8abedfcb49259b1
元コミット内容
os/user: fix for arm (non-cgo)
TBR=golang-dev
CC=golang-dev
https://golang.org/cl/5504056
変更の背景
このコミットは、Go言語のos/user
パッケージが、ARMアーキテクチャ上でCGO(GoとC言語の相互運用機能)を無効にしてビルドされた際に、ユーザー情報のルックアップ(ユーザー名からUIDを取得するなど)が正しく機能しない問題を解決するために導入されました。
Goのos/user
パッケージは、システム上のユーザー情報を取得するために、通常はC言語の標準ライブラリ(libc)が提供する関数(例: getpwnam
, getpwuid
など)を利用します。これらのC言語関数をGoから呼び出すためにはCGOが必要です。しかし、組み込みシステムやクロスコンパイル環境など、CGOが利用できない、あるいは意図的に無効にされるケースがあります。
以前の実装では、CGOが利用できないARM環境において、ユーザー情報を取得するための適切なフォールバックメカニズムが欠けていたか、あるいは誤った実装が選択されていました。その結果、os/user
パッケージの関数が期待通りに動作せず、アプリケーションがユーザー情報を取得できない、またはエラーを返すといった問題が発生していました。このコミットは、ビルドタグを修正することで、CGOの有無に応じて適切な実装ファイルがコンパイルされるようにし、この問題を解消することを目的としています。
前提知識の解説
Go言語のos/user
パッケージ
os/user
パッケージは、現在のユーザーや指定されたユーザーの情報を取得するための機能を提供します。例えば、user.Current()
で現在のユーザー情報を、user.Lookup(username)
で指定されたユーザー名の情報を、user.LookupId(uid)
で指定されたUIDの情報を取得できます。これらの情報は、ユーザー名、UID(User ID)、GID(Group ID)、ホームディレクトリ、シェルパスなどを含みます。
CGO
CGOは、GoプログラムからC言語のコードを呼び出すためのGoの機能です。Goは通常、完全に独立したバイナリを生成しますが、OSのシステムコールや既存のCライブラリの機能を利用する際にはCGOが非常に有用です。os/user
パッケージがユーザー情報を取得する際にC言語の関数を利用するのは、OSが提供するユーザー管理機能がC言語のAPIとして提供されているためです。CGOを使用するには、Goのビルド時にCコンパイラ(通常はGCCやClang)が必要です。ビルド時にCGO_ENABLED=0
を設定することでCGOを無効にできます。
Goのビルドタグ(Build Tags)
Goのビルドタグは、ソースファイルの先頭に// +build tagname
のようなコメントを記述することで、そのファイルを特定の条件でのみコンパイル対象に含めるように制御するメカニズムです。複数のタグをスペースで区切って記述するとAND条件(例: +build linux amd64
はLinuxかつAMD64の場合にコンパイル)、カンマで区切るとOR条件(例: +build linux,windows
はLinuxまたはWindowsの場合にコンパイル)になります。
このコミットで重要なのは以下のタグです。
nocgo
: CGOが無効な場合にファイルを含めるためのタグ。cgo
: CGOが有効な場合にファイルを含めるためのタグ。- OS名(例:
darwin
,freebsd
,linux
,netbsd
,openbsd
,plan9
,windows
): 特定のOSでのみファイルを含めるためのタグ。
これらのタグを適切に設定することで、異なるOS、アーキテクチャ、またはビルドオプション(CGOの有無など)に応じて、Goプログラムが適切なコードパスを選択し、コンパイルされるようにします。
ARMアーキテクチャ
ARM(Advanced RISC Machine)は、主にモバイルデバイス、組み込みシステム、IoTデバイスなどで広く使用されているCPUアーキテクチャです。低消費電力と高性能を両立させる設計が特徴です。Go言語はARMアーキテクチャもサポートしており、クロスコンパイルによってARMデバイス向けのバイナリを生成できます。
技術的詳細
このコミットの技術的な核心は、Goのビルドシステムがos/user
パッケージのどのソースファイルを使用するかを決定する際のロジックを修正することにあります。
Goのos/user
パッケージは、内部的に複数のファイルに分割されており、それぞれが異なるプラットフォームやビルド条件に対応する実装を含んでいます。
-
src/pkg/os/user/lookup_stubs.go
: このファイルは、ユーザー情報ルックアップの「スタブ」実装、つまり、CGOが利用できない場合や、特定のOSでよりシンプルなフォールバックが必要な場合に利用される、限定的な機能を提供するコードを含んでいます。 変更前:// +build netbsd openbsd plan9 windows
このタグは、NetBSD、OpenBSD、Plan 9、Windowsといった特定のOSでのみこのファイルがコンパイルされることを意味していました。 変更後:// +build nocgo
このタグに変更されたことで、このファイルはCGOが無効な場合に常にコンパイルされるようになりました。これにより、ARMを含むCGOが利用できないすべての環境で、このスタブ実装が適切に選択されるようになります。 -
src/pkg/os/user/lookup_unix.go
: このファイルは、Unix系OS(Darwin, FreeBSD, Linuxなど)におけるユーザー情報ルックアップの主要な実装を含んでいます。この実装は、通常、C言語のシステムコールをCGO経由で呼び出すことに依存しています。 変更前:// +build darwin freebsd linux
このタグは、Darwin、FreeBSD、LinuxといったUnix系OSでこのファイルがコンパイルされることを意味していました。 変更後:// +build darwin freebsd linux // +build cgo
新しい行
// +build cgo
が追加されました。これにより、このファイルはUnix系OSであり、かつCGOが有効な場合にのみコンパイルされるようになりました。
この変更の組み合わせにより、Goのビルドシステムは以下のように動作します。
- Unix系OS + CGO有効:
lookup_unix.go
がコンパイルされ、CGO経由でC言語のユーザー情報取得関数が利用されます。 - Unix系OS + CGO無効:
lookup_unix.go
は+build cgo
タグのためにコンパイルされません。代わりに、lookup_stubs.go
が+build nocgo
タグのためにコンパイルされ、CGOに依存しないスタブ実装が使用されます。 - 非Unix系OS(例: Windows): 以前と同様に
lookup_stubs.go
がコンパイルされます(+build nocgo
が適用されるか、あるいはWindows固有のファイルがある場合)。
この修正により、ARMアーキテクチャを含む様々な環境で、CGOの有無に関わらずos/user
パッケージが安定して動作するようになりました。特に、CGOが利用できない環境での堅牢性が向上しています。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更は、Goソースファイルの先頭に記述されるビルドタグ(build tags)の修正です。
-
src/pkg/os/user/lookup_stubs.go
- 変更前:
// +build netbsd openbsd plan9 windows
- 変更後:
// +build nocgo
- 変更前:
-
src/pkg/os/user/lookup_unix.go
- 変更前:
// +build darwin freebsd linux
- 変更後:
(既存のタグに加えて、// +build darwin freebsd linux // +build cgo
// +build cgo
が追加)
- 変更前:
コアとなるコードの解説
これらのビルドタグの変更は、Goのコンパイラがどのソースファイルをビルドに含めるかを決定するロジックに直接影響を与えます。
-
lookup_stubs.go
の変更: 以前は、このスタブ実装ファイルは特定の非Unix系OS(NetBSD, OpenBSD, Plan 9, Windows)でのみコンパイルされていました。しかし、CGOが利用できない環境(例えば、クロスコンパイルされたARMバイナリでCGOが無効な場合)では、これらのOS以外でもCGOに依存しないフォールバックが必要になります。// +build nocgo
に変更されたことで、このファイルはCGOが有効になっていないすべてのビルドでコンパイルされるようになりました。これにより、CGOが利用できない環境であれば、OSの種類に関わらず(ただし、より具体的な実装が存在しない限り)、このスタブ実装が使用されることが保証されます。これは、ARMのようなCGOが利用できない環境でのユーザー情報ルックアップの失敗を防ぐ上で非常に重要です。 -
lookup_unix.go
の変更: このファイルはUnix系OS(Darwin, FreeBSD, Linux)向けの主要な実装を含んでおり、通常はCGOを介してC言語のシステムコールに依存しています。// +build cgo
タグが追加されたことで、このファイルはUnix系OSであり、かつCGOが有効な場合にのみコンパイルされるようになりました。もしCGOが無効な状態でUnix系OS向けにビルドしようとすると、このファイルはコンパイル対象から外れ、代わりにlookup_stubs.go
(+build nocgo
によって選択される)が使用されることになります。 これにより、CGOが有効な場合は高性能なCGOベースの実装を、CGOが無効な場合は堅牢なスタブ実装を、それぞれ適切に選択できるようになり、ビルドの柔軟性と信頼性が向上しました。
このコミットは、Goのビルドシステムとビルドタグの強力な機能を活用して、異なるビルド環境(特にCGOの有無)におけるos/user
パッケージの動作を正確に制御し、堅牢性を高めた典型的な例と言えます。
関連リンク
- Go Change List (CL) 5504056: このコミットに対応するGoのコードレビューページです。詳細な議論や変更履歴を確認できます。 https://golang.org/cl/5504056
参考にした情報源リンク
- Go言語の公式ドキュメント - Build Constraints: Goのビルドタグ(ビルド制約)に関する公式ドキュメント。 https://pkg.go.dev/cmd/go#hdr-Build_constraints
- Go言語の公式ドキュメント - Cgo: GoとC言語の相互運用(CGO)に関する公式ドキュメント。 https://pkg.go.dev/cmd/cgo
- Go言語の公式ドキュメント -
os/user
パッケージ:os/user
パッケージのAPIリファレンス。 https://pkg.go.dev/os/user - Go言語のクロスコンパイルに関する情報: Goのクロスコンパイルに関する一般的な情報源(例: 各種ブログ記事やチュートリアル)。 (具体的なURLは割愛しますが、"Go cross compile arm"などで検索すると多数の情報が見つかります。)
- C言語のユーザー情報取得関数(
getpwnam
,getpwuid
など)に関する情報: Unix系OSにおけるユーザー情報取得のC言語APIに関する一般的な情報源(例: manページ)。 (具体的なURLは割愛しますが、"man getpwnam"などで検索すると多数の情報が見つかります。)