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

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

このコミットは、Go言語プロジェクトのmisc/distディレクトリに、Linux向けのGoバイナリディストリビューションパッケージングスクリプトdist.bashを新規追加するものです。このスクリプトは、GoのソースコードをMercurialリポジトリからクローンし、指定されたタグのバージョンをビルドし、最終的にtar.gz形式のバイナリパッケージとして出力する一連の自動化されたプロセスを提供します。

コミット

commit 159ee8a42f2ad9216267a1da0217427346d1d331
Author: Andrew Gerrand <adg@golang.org>
Date:   Mon Feb 13 21:18:16 2012 +1100

    misc/dist: add binary distribution packaging script for linux
    
    R=golang-dev, bradfitz, iant
    CC=golang-dev
    https://golang.org/cl/5639064

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

https://github.com/golang/go/commit/159ee8a42f2ad9216267a1da0217427346d1d331

元コミット内容

diff --git a/misc/dist/linux/dist.bash b/misc/dist/linux/dist.bash
new file mode 100755
index 0000000000..9270782ad9
--- /dev/null
+++ b/misc/dist/linux/dist.bash
@@ -0,0 +1,55 @@
+#!/usr/bin/env bash
+# Copyright 2012 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.
+
+set -e
+
+TAG=$1
+if [ "$TAG" == "" ]; then
+	echo >&2 'usage: dist.bash <tag>'
+	exit 2
+fi
+
+GOOS=${GOOS:-linux}
+GOARCH=${GOARCH:-amd64}
+
+ROOT=/tmp/godist.linux.$GOARCH
+rm -rf $ROOT
+mkdir -p $ROOT
+pushd $ROOT>/dev/null
+
+# clone Go distribution
+echo "Preparing new GOROOT"
+hg clone -q https://code.google.com/p/go go
+pushd go > /dev/null
+hg update $TAG
+
+# get version
+pushd src > /dev/null
+echo "Building dist tool to get VERSION"
+./make.bash --dist-tool 2>&1 | sed 's/^/  /' >&2
+../bin/tool/dist version > ../VERSION
+popd > /dev/null
+VERSION="$(cat VERSION | awk '{ print $1 }')"
+echo "  Version: $VERSION"
+
+# remove mercurial stuff
+rm -rf .hg*
+
+# build Go
+echo "Building Go"
+unset GOROOT
+export GOOS
+export GOARCH
+export GOROOT_FINAL=/usr/local/go
+pushd src > /dev/null
+./all.bash 2>&1 | sed 's/^/  /' >&2
+popd > /dev/null
+popd > /dev/null
+
+# tar it up
+DEST=go.$VERSION.$GOOS-$GOARCH.tar.gz
+echo "Writing tarball: $ROOT/$DEST"
+tar czf $DEST go
+popd > /dev/null

変更の背景

このコミットが行われた2012年当時、Go言語はまだ比較的新しい言語であり、その配布方法は進化の途上にありました。Goのユーザーが特定のバージョン(タグ)のGoバイナリを簡単に取得し、システムにインストールできるようにするためには、自動化されたパッケージングプロセスが必要でした。特にLinux環境では、ソースからビルドする手間を省き、すぐに利用できるバイナリ形式で提供することが、ユーザーエクスペリエンスの向上に直結します。

このスクリプトの追加は、Goプロジェクトが公式なバイナリディストリビューションの提供を強化し、ユーザーがより手軽にGoを利用できる環境を整備するための一環として行われました。これにより、開発者は特定のGoバージョンを簡単にダウンロードし、tar.gzファイルを展開するだけでGo開発環境をセットアップできるようになります。

前提知識の解説

このコミットの理解には、以下の技術的知識が役立ちます。

  • Bashスクリプト: dist.bashはBashシェルスクリプトで書かれています。set -e(コマンドが失敗した場合にスクリプトを終了する)、echo(標準出力)、>&2(標準エラー出力へのリダイレクト)、pushd/popd(ディレクトリスタック操作)、rm -rf(強制削除)、mkdir -p(ディレクトリ作成)、export(環境変数設定)、パイプライン(|)、sed(ストリームエディタ)、awk(テキスト処理)などの基本的なコマンドと概念が使われています。
  • Mercurial (Hg): 2012年当時、Go言語の公式リポジトリはGitではなくMercurial(Hg)で管理されていました。hg cloneはリポジトリをクローンするコマンド、hg updateは指定されたタグやリビジョンに作業ディレクトリを更新するコマンドです。このスクリプトはGoのソースコードをMercurialリポジトリから取得しています。
  • Go言語のビルドシステム:
    • GOROOT: Goのインストールディレクトリを指す環境変数です。GoのツールチェインがGoのソースコードや標準ライブラリを見つけるために使用します。
    • GOOS / GOARCH: ビルドターゲットのオペレーティングシステム(例: linux)とアーキテクチャ(例: amd64)を指定する環境変数です。
    • GOROOT_FINAL: Goのバイナリが最終的にインストールされるパスを指定する環境変数です。このスクリプトでは/usr/local/goに設定されており、これは一般的なGoのインストールパスです。
    • ./make.bash / ./all.bash: Goのソースツリーに含まれるビルドスクリプトです。make.bashはGoのビルドツールを構築するために使用され、all.bashはGoのコンパイラ、ツール、標準ライブラリなど、Go全体をビルドするために使用されます。
  • tarコマンド: ファイルやディレクトリをアーカイブ(まとめる)および圧縮(サイズを小さくする)するためのUNIX系コマンドです。tar czf <output_file> <input_directory>は、指定されたディレクトリをgzipで圧縮されたtarアーカイブとして出力します。

技術的詳細

dist.bashスクリプトは、GoのLinuxバイナリディストリビューションを作成するための一連のステップを自動化します。

  1. 引数の検証:

    • スクリプトは引数としてGoのバージョンタグ(例: go1.0)を一つ受け取ります。
    • 引数が提供されない場合、使用法メッセージを表示して終了します。
  2. 環境変数の設定:

    • GOOSGOARCHは、それぞれデフォルトでlinuxamd64に設定されますが、環境変数として既に設定されていればその値が優先されます。これにより、異なるOS/アーキテクチャのバイナリをビルドする柔軟性が提供されます。
  3. 一時作業ディレクトリの準備:

    • /tmp/godist.linux.$GOARCHという形式の一時ディレクトリ(例: /tmp/godist.linux.amd64)を作成します。
    • 既存のディレクトリがあれば削除し、新しく作成します。
    • このディレクトリに移動し、以降の操作のベースとします。
  4. Goソースコードのクローンと更新:

    • hg clone -q https://code.google.com/p/go goコマンドを使用して、Goの公式Mercurialリポジトリをgoという名前のディレクトリにクローンします。-qオプションは静かに(quietly)クローンすることを意味します。
    • クローンしたgoディレクトリに移動します。
    • hg update $TAGコマンドで、スクリプトに渡されたタグ(例: go1.0)に対応するバージョンにソースコードを更新します。
  5. Goバージョンの取得:

    • go/srcディレクトリに移動します。
    • ./make.bash --dist-toolを実行して、Goのビルドツール(distツールなど)をビルドします。この出力は標準エラーにリダイレクトされ、sedで整形されます。
    • ../bin/tool/dist versionを実行し、ビルドされたdistツールを使ってGoのバージョン情報を取得し、../VERSIONファイルに保存します。
    • VERSIONファイルからawkを使ってバージョン文字列を抽出し、VERSIONシェル変数に格納します。
  6. Mercurial関連ファイルの削除:

    • ビルドされたGoのディレクトリから、.hg*(Mercurialのリポジトリ情報)ファイルを削除します。これにより、配布されるtarballには不要なリポジトリメタデータが含まれなくなります。
  7. Goのビルド:

    • GOROOT環境変数をunset(設定解除)します。これは、ビルドプロセスが現在の環境のGOROOTに依存しないようにするためです。
    • GOOSGOARCH、そしてGOROOT_FINAL=/usr/local/goをエクスポートします。GOROOT_FINALは、ビルドされたGoバイナリが最終的にインストールされるパスをGoのビルドシステムに伝えます。
    • go/srcディレクトリに移動し、./all.bashを実行してGo全体をビルドします。このコマンドはGoのコンパイラ、標準ライブラリ、およびその他のツールをコンパイルします。出力は標準エラーにリダイレクトされ、sedで整形されます。
  8. tarballの作成:

    • ビルドが完了した後、一時作業ディレクトリのルートに戻ります。
    • DEST=go.$VERSION.$GOOS-$GOARCH.tar.gzという形式で出力ファイル名を定義します(例: go.1.0.linux-amd64.tar.gz)。
    • tar czf $DEST goコマンドを使用して、ビルドされたgoディレクトリ全体をgzip圧縮されたtarアーカイブとしてパッケージングします。

このスクリプトは、Goのバイナリ配布に必要なすべてのステップを自動化し、クリーンでポータブルなGoのインストールパッケージを生成します。

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

このコミットは、misc/dist/linux/dist.bashという新しいファイルを追加しています。

#!/usr/bin/env bash
# Copyright 2012 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.

set -e

TAG=$1
if [ "$TAG" == "" ]; then
	echo >&2 'usage: dist.bash <tag>'
	exit 2
fi

GOOS=${GOOS:-linux}
GOARCH=${GOARCH:-amd64}

ROOT=/tmp/godist.linux.$GOARCH
rm -rf $ROOT
mkdir -p $ROOT
pushd $ROOT>/dev/null

# clone Go distribution
echo "Preparing new GOROOT"
hg clone -q https://code.google.com/p/go go
pushd go > /dev/null
hg update $TAG

# get version
pushd src > /dev/null
echo "Building dist tool to get VERSION"
./make.bash --dist-tool 2>&1 | sed 's/^/  /' >&2
../bin/tool/dist version > ../VERSION
popd > /dev/null
VERSION="$(cat VERSION | awk '{ print $1 }')"
echo "  Version: $VERSION"

# remove mercurial stuff
rm -rf .hg*

# build Go
echo "Building Go"
unset GOROOT
export GOOS
export GOARCH
export GOROOT_FINAL=/usr/local/go
pushd src > /dev/null
./all.bash 2>&1 | sed 's/^/  /' >&2
popd > /dev/null
popd > /dev/null

# tar it up
DEST=go.$VERSION.$GOOS-$GOARCH.tar.gz
echo "Writing tarball: $ROOT/$DEST"
tar czf $DEST go
popd > /dev/null

コアとなるコードの解説

  • #!/usr/bin/env bash: シバン(shebang)。このスクリプトがBashシェルで実行されることを指定します。
  • set -e: スクリプト内で実行されるコマンドが一つでも失敗(ゼロ以外の終了ステータスを返す)した場合、スクリプト全体の実行を即座に終了させます。これにより、エラーが発生した際に不完全なパッケージが生成されるのを防ぎます。
  • TAG=$1: スクリプトに渡された最初の引数をTAG変数に代入します。これがビルドするGoのバージョンタグになります。
  • if [ "$TAG" == "" ]; then ... fi: TAGが空文字列(引数が渡されなかった場合)であれば、使用法メッセージを標準エラー出力に表示し、終了コード2でスクリプトを終了します。
  • GOOS=${GOOS:-linux} / GOARCH=${GOARCH:-amd64}: 環境変数GOOSGOARCHが設定されていればその値を使用し、設定されていなければそれぞれlinuxamd64をデフォルト値として使用します。
  • ROOT=/tmp/godist.linux.$GOARCH: 一時作業ディレクトリのパスを定義します。/tmp以下にアーキテクチャ名を含むユニークなディレクトリを作成します。
  • rm -rf $ROOT / mkdir -p $ROOT: 既存の一時ディレクトリを削除し、新しく作成します。-pオプションは、親ディレクトリが存在しない場合でも作成します。
  • pushd $ROOT>/dev/null: $ROOTディレクトリに移動し、現在のディレクトリをスタックにプッシュします。>/dev/nullは、pushdコマンドの出力を抑制します。
  • hg clone -q https://code.google.com/p/go go: GoのMercurialリポジトリをgoという名前のサブディレクトリにクローンします。-qは静かに実行するオプションです。
  • hg update $TAG: クローンしたGoリポジトリを、指定されたTAGのバージョンに更新します。
  • ./make.bash --dist-tool 2>&1 | sed 's/^/ /' >&2: Goのビルドツールをビルドします。2>&1は標準エラーを標準出力にリダイレクトし、| sed 's/^/ /'は各行の先頭にスペース2つを追加してインデントし、>&2で再び標準エラーに戻しています。これは、ビルドの進行状況をユーザーに分かりやすく表示するための整形です。
  • ../bin/tool/dist version > ../VERSION: ビルドされたdistツールを使ってGoのバージョン情報を取得し、親ディレクトリ(goディレクトリ)のVERSIONファイルに保存します。
  • VERSION="$(cat VERSION | awk '{ print $1 }')": VERSIONファイルの内容を読み込み、awkを使って最初の単語(バージョン番号)を抽出し、VERSIONシェル変数に代入します。
  • rm -rf .hg*: クローンしたGoリポジトリからMercurial関連の隠しファイルやディレクトリ(.hgディレクトリなど)を削除します。これにより、配布されるパッケージがクリーンになります。
  • unset GOROOT: Goのビルド前にGOROOT環境変数を解除します。これは、ビルドプロセスが現在の環境のGOROOTに依存せず、クリーンな状態でビルドを開始できるようにするためです。
  • export GOOS / export GOARCH / export GOROOT_FINAL=/usr/local/go: ビルドターゲットのOS、アーキテクチャ、および最終的なインストールパスを環境変数としてエクスポートします。GOROOT_FINALは、Goのビルドシステムがバイナリを生成する際に、そのバイナリが最終的にどこにインストールされるかを考慮するために重要です。
  • ./all.bash 2>&1 | sed 's/^/ /' >&2: Goのコンパイラ、ツール、標準ライブラリなど、Go全体をビルドします。make.bashと同様に、出力は整形されて標準エラーに表示されます。
  • DEST=go.$VERSION.$GOOS-$GOARCH.tar.gz: 生成されるtarballのファイル名を定義します。バージョン、OS、アーキテクチャが含まれることで、ファイル名から内容が分かりやすくなります。
  • tar czf $DEST go: goディレクトリ全体をgzip圧縮されたtarアーカイブとして$DESTに保存します。
  • popd > /dev/null: pushdでプッシュしたディレクトリスタックから一つ戻ります。これにより、スクリプトは元の開始ディレクトリに戻ります。

関連リンク

参考にした情報源リンク

  • Mercurial公式サイト: https://www.mercurial-scm.org/
  • Bashスクリプトの基本的なコマンドと概念に関する一般的なドキュメント
  • Go言語のビルドプロセスに関する一般的な情報 (Goの公式ドキュメントやブログ記事)
  • tarコマンドのマニュアルページ
  • sedコマンドのマニュアルページ
  • awkコマンドのマニュアルページ
  • pushd / popd コマンドのマニュアルページ
  • set コマンドのマニュアルページ
  • export コマンドのマニュアルページ
  • unset コマンドのマニュアルページ
  • echo コマンドのマニュアルページ
  • if 文に関するBashのドキュメント
  • [ (test) コマンドのマニュアルページ
  • > / &> / 2>&1 など、リダイレクトに関するBashのドキュメント
  • パイプライン (|) に関するBashのドキュメント
  • #!/usr/bin/env に関する一般的な情報
  • Go言語の歴史とMercurialからGitへの移行に関する情報 (Goの公式ブログやメーリングリストのアーカイブ)