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

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

このコミットは、Goプロジェクトのビルドスクリプトである src/run.bash におけるNetBSD環境でのビルド問題を修正するものです。具体的には、環境変数の参照方法のtypoを修正し、NetBSD上でのテスト実行が正しく行われるようにします。

コミット

commit 560471fbabc3a493e0271a27eb1b16dee6546c7b
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Tue Apr 15 23:54:04 2014 -0400

    run.bash: fix build on netbsd builders.

    LGTM=bradfitz
    R=golang-codereviews, bradfitz, dave
    CC=golang-codereviews
    https://golang.org/cl/88000044

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

https://github.com/golang/go/commit/560471fbabc3a493e0271a27eb1b16dee6546c7b

元コミット内容

run.bash: fix build on netbsd builders.

このコミットは、run.bash スクリプトがNetBSD環境のビルドボットで正しく動作しない問題を修正します。

変更の背景

Goプロジェクトは、様々なオペレーティングシステムとアーキテクチャの組み合わせ(OS/ARCH)で動作するように設計されており、継続的インテグレーション(CI)システムを通じてこれらの環境でのビルドとテストを自動的に行っています。run.bash は、Goのソースコードをビルドし、テストを実行するための主要なスクリプトの一つです。

このコミットが行われた当時、NetBSD環境のビルドボット(CIシステムの一部)でビルドまたはテストが失敗する問題が発生していました。問題の原因は、run.bash スクリプト内でGoのホストOSとアーキテクチャを組み合わせた文字列を評価する際に、環境変数の参照方法に誤りがあったためです。具体的には、$GOHOSTOS-GOARCH という記述が意図せず GOHOSTOS 変数の値とリテラル文字列 -GOARCH を連結してしまい、期待される GOHOSTOS-GOHOSTARCH の組み合わせ(例: netbsd-386)を正しく生成できていませんでした。これにより、case 文のパターンマッチングが失敗し、NetBSD固有のビルドロジックが適用されず、結果としてビルドエラーやテスト失敗につながっていました。

この修正は、GoのCIシステムがNetBSD環境で安定して動作し、GoがNetBSDプラットフォームを適切にサポートし続けるために不可欠でした。

前提知識の解説

run.bash スクリプト

run.bash は、Goプロジェクトのルートディレクトリにあるシェルスクリプトで、Goのツールチェインのビルド、テストの実行、および様々なプラットフォームでの動作確認を行うための主要なエントリポイントです。これは、開発者がローカルでGoをビルド・テストする際や、GoのCIシステム(ビルドボット)が自動的にビルド・テストを実行する際に利用されます。

GOHOSTOSGOARCH 環境変数

  • GOHOSTOS: Goのツールチェインが動作しているホストオペレーティングシステムを示します。例えば、linuxdarwin (macOS)、windowsfreebsdnetbsd などがあります。
  • GOARCH: Goのツールチェインが動作しているホストアーキテクチャを示します。例えば、amd64386arm などがあります。

これらの環境変数は、Goのビルドプロセスにおいて、特定のOSやアーキテクチャに依存するコードパスを選択したり、クロスコンパイルのターゲットを決定したりするために広く利用されます。

シェルスクリプトにおける変数展開

Bashなどのシェルスクリプトでは、変数を参照する際に $変数名 の形式を使用します。複雑な変数名や、変数とリテラル文字列を連結する場合には、{} を使用して変数の範囲を明示することが推奨されます。例えば、$VAR_NAME_SUFFIX と書くと VAR_NAME_SUFFIX という単一の変数を参照しようとしますが、${VAR_NAME}_SUFFIX と書くと VAR_NAME の値に _SUFFIX という文字列を連結したものを生成します。

このコミットの文脈では、$GOHOSTOS-GOARCHGOHOSTOS の値とリテラル文字列 -GOARCH を連結してしまいます。期待されるのは GOHOSTOS の値と GOARCH の値をハイフンで連結した文字列(例: netbsd-amd64)です。これを実現するには、$GOHOSTOS-$GOARCH のように、それぞれの変数を個別に展開する必要があります。

静的リンクと動的リンク

  • 静的リンク (Static Linking): プログラムが必要とするすべてのライブラリコードを、コンパイル時に実行可能ファイルに直接組み込む方式です。これにより、実行可能ファイルは自己完結型となり、外部ライブラリに依存せずに実行できます。しかし、ファイルサイズが大きくなる傾向があります。
  • 動的リンク (Dynamic Linking): プログラムが必要とするライブラリコードを、実行時に外部の共有ライブラリ(例: .so.dll)からロードする方式です。これにより、実行可能ファイルのサイズを小さく保ち、複数のプログラムで同じライブラリを共有できます。しかし、実行環境に適切な共有ライブラリが存在しないとプログラムが実行できません。

Goのビルドシステムでは、go test -ldflags オプションを使用してリンカーのフラグを渡すことができます。-linkmode=external は外部リンカーを使用することを示し、-extldflags はその外部リンカーに渡す追加のフラグを指定します。-static は静的リンクを指示するリンカーフラグです。

NetBSDのような一部のシステムでは、特定の条件下(特にGoのテストスイートのような複雑なケース)で静的リンクがサポートされていない、または問題を引き起こすことがあります。そのため、run.bash スクリプトにはNetBSD環境では静的リンクを試みないという特別なロジックが含まれていました。

技術的詳細

このコミットの技術的詳細は、シェルスクリプトにおける変数展開の正確性に集約されます。

src/run.bash スクリプトの該当箇所では、Goのテストスイートを実行する際に、特定のOS/ARCHの組み合わせに対して特別なリンキングオプションを適用するかどうかを判断していました。

元のコード:

case "$GOHOSTOS-GOARCH" in
netbsd-386 | netbsd-amd64) ;; # no static linking
*)
    go test -ldflags '-linkmode=external -extldflags "-static -pthread"' ../testtls || exit 1

この case 文は、$GOHOSTOS-GOARCH という文字列を評価しています。ここで問題となるのは、$GOHOSTOS-GOARCHGOHOSTOS 環境変数の値と、リテラル文字列 -GOARCH を連結した結果になることです。例えば、GOHOSTOSnetbsdGOARCHamd64 の場合、この式は netbsd-GOARCH という文字列を生成してしまいます。

これにより、netbsd-386 | netbsd-amd64 というパターンには決してマッチせず、NetBSD環境であっても常に *) のブロック(静的リンクを試みるロジック)が実行されていました。NetBSDでは静的リンクがサポートされていない、または問題があるため、これがビルド失敗の原因となっていました。

修正後のコード:

case "$GOHOSTOS-$GOARCH" in
netbsd-386 | netbsd-amd64) ;; # no static linking
*)
    go test -ldflags '-linkmode=external -extldflags "-static -pthread"' ../testtls || exit 1

修正では、$GOHOSTOS-GOARCH$GOHOSTOS-$GOARCH に変更しています。これにより、GOHOSTOSGOARCH の両方の環境変数が正しく展開され、それらがハイフンで連結された文字列(例: netbsd-amd64)が生成されます。この正しい文字列が case 文のパターン netbsd-386 | netbsd-amd64 と正確にマッチするようになり、NetBSD環境では静的リンクを回避するロジックが正しく適用されるようになりました。

この修正は、Goのビルドシステムが様々なプラットフォームで堅牢に動作するための、細かではあるが重要な改善です。

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

変更は src/run.bash ファイルの1箇所のみです。

--- a/src/run.bash
+++ b/src/run.bash
@@ -132,7 +132,7 @@ dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | linux-386 | linu
 	go test -ldflags \'-linkmode=auto\' ../testtls || exit 1
 	go test -ldflags \'-linkmode=external\' ../testtls || exit 1
 	
-	case \"$GOHOSTOS-GOARCH\" in
+	case \"$GOHOSTOS-$GOARCH\" in
 	netbsd-386 | netbsd-amd64) ;; # no static linking
 	*)
 		go test -ldflags \'-linkmode=external -extldflags \"-static -pthread\"\' ../testtls || exit 1

コアとなるコードの解説

変更された行は、case 文の条件式です。

  • 変更前: case "$GOHOSTOS-GOARCH"
    • これは $GOHOSTOS の値とリテラル文字列 -GOARCH を連結します。例えば、GOHOSTOS=netbsd の場合、この式は netbsd-GOARCH と評価されます。
  • 変更後: case "$GOHOSTOS-$GOARCH"
    • これは $GOHOSTOS の値と $GOARCH の値をそれぞれ展開し、それらをハイフンで連結します。例えば、GOHOSTOS=netbsdGOARCH=amd64 の場合、この式は netbsd-amd64 と評価されます。

この修正により、case 文はNetBSDの特定のアーキテクチャ(386またはamd64)に対して正しくパターンマッチングを行い、静的リンクを回避するロジックが適用されるようになりました。これにより、NetBSDビルドボットでのビルド失敗が解消されました。

関連リンク

参考にした情報源リンク

  • Goの公式ドキュメント (特にビルドと環境変数に関するセクション)
  • Bashのシェルスクリプトに関するドキュメント (変数展開について)
  • GoプロジェクトのGitHubリポジトリ (特に src/run.bash の履歴と関連するコミット)
  • GoのGerritコードレビューシステム (CL 88000044)
  • NetBSDの静的リンクに関する一般的な情報 (必要に応じて)
  • GoのCIシステムに関する情報 (Go Dashboardなど)