[インデックス 17722] ファイルの概要
このコミットは、Go言語のツールチェインを静的にリンクしてビルドする機能を追加するものです。具体的には、cmd/dist
ツールとmake.bash
スクリプトに変更が加えられ、GO_DISTFLAGS
という新しい環境変数を導入することで、静的リンクされたツールチェインのビルドをサポートします。
コミット
commit 6b188ef57a644838bd4c673d6d14b49879db6297
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Tue Oct 1 23:44:20 2013 -0400
cmd/dist, build: support building statically linked toolchain
Added a new $GO_DISTFLAGS to make.bash, and while we're here,
added mention $CXX in make.bash (CL 13704044).
Fixes #6448.
Update #3564
We can pass GO_DISTFLAGS=-s from misc/dist to make.bash so that
it will build a statically linked toolchain.
(Note: OS X doesn't have the concept of static linking, so don't
pass GO_DISTFLAGS=-s for OS X builds)
R=adg, rsc, iant
CC=golang-dev
https://golang.org/cl/13887043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/6b188ef57a644838bd4c673d6d14b49879db6297
元コミット内容
cmd/dist, build: support building statically linked toolchain
このコミットは、Goのビルドシステムにおいて、静的にリンクされたツールチェインを構築する機能を追加します。make.bash
スクリプトに$GO_DISTFLAGS
という新しい環境変数が導入され、これを通じて静的リンクを制御できるようになります。また、make.bash
に$CXX
(C++コンパイラ)に関する記述も追加されています(これは関連する変更として同時に行われました)。
この変更により、GO_DISTFLAGS=-s
をmisc/dist
からmake.bash
に渡すことで、静的にリンクされたツールチェインをビルドできるようになります。ただし、OS X(現在のmacOS)では静的リンクの概念が異なるため、OS Xビルドではこのフラグを渡すべきではないという注意書きがあります。
このコミットは、Issue #6448を修正し、Issue #3564を更新します。
変更の背景
このコミットの背景には、Goツールチェインの配布と実行に関する課題がありました。通常、Goのバイナリは動的にリンクされており、実行時にシステムに存在する共有ライブラリに依存します。しかし、異なる環境でGoツールチェインを実行する場合、必要な共有ライブラリが不足していると、ツールチェインが正しく動作しない可能性があります。
静的リンクされたバイナリは、必要なすべてのライブラリをバイナリ自体に含めるため、外部の共有ライブラリに依存しません。これにより、ツールチェインのポータビリティが向上し、様々な環境でのデプロイが容易になります。
コミットメッセージで言及されているIssue #6448は、まさにこの静的リンクの必要性に関する議論であり、Goツールチェインをより堅牢で移植性の高いものにするための要望に応えるものです。Issue #3564は、Goのビルドシステム全般に関するもので、このコミットはその一部を改善するものです。
前提知識の解説
1. 静的リンクと動的リンク
- 静的リンク (Static Linking): プログラムがコンパイルされる際に、必要なライブラリのコードが実行可能ファイルに直接組み込まれる方式です。
- 利点:
- 実行可能ファイルが自己完結型になるため、他のシステムにデプロイする際にライブラリの依存関係を気にする必要がありません。
- 起動が速い場合があります(共有ライブラリのロードが不要なため)。
- 欠点:
- 実行可能ファイルのサイズが大きくなります。
- ライブラリの更新があった場合、そのライブラリを使用するすべてのプログラムを再コンパイルする必要があります。
- 複数のプログラムが同じライブラリを使用する場合、メモリ上でライブラリのコードが重複してロードされる可能性があります。
- 利点:
- 動的リンク (Dynamic Linking): プログラムが実行される際に、必要なライブラリがメモリにロードされ、プログラムとリンクされる方式です。共有ライブラリ(WindowsではDLL、Linuxでは.so、macOSでは.dylib)として提供されます。
- 利点:
- 実行可能ファイルのサイズが小さくなります。
- ライブラリの更新があった場合、プログラムを再コンパイルすることなく、新しいライブラリを利用できます。
- 複数のプログラムが同じライブラリを使用する場合、メモリ上でライブラリのコードが共有されるため、メモリ効率が良いです。
- 欠点:
- 実行時に必要な共有ライブラリが存在しない場合、プログラムが起動できません(「DLLが見つかりません」などのエラー)。
- 起動に時間がかかる場合があります(共有ライブラリのロードとリンクが必要なため)。
- 利点:
Goのツールチェインを静的にリンクすることで、Goのコンパイラやその他のツールが、それらが実行されるシステムに特定の共有ライブラリが存在することを前提としなくなるため、より幅広い環境での利用が可能になります。
2. Goのビルドシステム (cmd/dist
とmake.bash
)
Go言語のビルドプロセスは、他の多くの言語とは異なり、Go自身でGoのコンパイラやツールチェインをビルドする「ブートストラップ」という仕組みを持っています。
make.bash
: Goのソースコードリポジトリのルートにあるシェルスクリプトです。Goのツールチェイン全体をビルドするための主要なエントリポイントとなります。このスクリプトは、Goのコンパイラ、リンカ、アセンブラなどのツールをビルドし、Goの標準ライブラリをコンパイルします。cmd/dist
: Goのツールチェインの一部であり、make.bash
によって呼び出される内部ツールです。dist
コマンドは、Goのビルドプロセスにおける様々な低レベルのタスク(例えば、ブートストラップコンパイラのビルド、標準ライブラリのインストール、テストの実行など)を管理します。このツールはGoで書かれており、Goのビルドシステムの中核をなします。
このコミットでは、make.bash
がcmd/dist
を呼び出す際に、静的リンクを指示するフラグを渡せるように変更されています。
3. GO_DISTFLAGS
環境変数
Goのビルドプロセスでは、様々な環境変数を使用して挙動を制御できます。GO_DISTFLAGS
は、このコミットで新しく導入された環境変数で、cmd/dist
ツールに渡される追加のフラグを指定するために使用されます。これにより、make.bash
からdist
コマンドの挙動を外部からカスタマイズできるようになります。
技術的詳細
このコミットは、Goツールチェインのビルドプロセスに静的リンクのオプションを導入するために、以下の主要な変更を行っています。
-
sflag
の導入:src/cmd/dist/a.h
:sflag
という新しいグローバル変数が宣言されています。これは、静的リンクオプションが有効になっているかどうかを示すフラグとして機能します。src/cmd/dist/main.c
:sflag
が初期化され、cmd/dist
プロセス全体で利用可能になります。
-
cmd/dist
での-static
フラグの処理:src/cmd/dist/build.c
:cmdbootstrap
関数とcmdinstall
関数(Goツールチェインのブートストラップビルドとインストールを担当)のコマンドライン引数解析部分に、新しいケース's'
が追加されています。これにより、-s
フラグが渡された場合にsflag
がインクリメントされます。install
関数内で、sflag
が設定されている場合に、コンパイラ(gcc
など)に渡すリンクオプションに-static
が追加されるようになります。これは、GoのツールチェインがC/C++コード(例えば、cgo
が使用するランタイムサポートや、一部の低レベルなアセンブリコード)をコンパイル・リンクする際に、静的リンクを強制するための重要な変更です。
-
make.bash
でのGO_DISTFLAGS
の利用:src/make.bash
:- 新しい環境変数
GO_DISTFLAGS
に関する説明が追加されています。この変数はdist bootstrap
に渡される追加フラグを指定するために使用され、-s
を渡すことで静的リンクされたツールチェインをビルドできることが明記されています。 ./cmd/dist/dist bootstrap
コマンドの呼び出し部分に$GO_DISTFLAGS
が追加されています。これにより、make.bash
を実行する際にGO_DISTFLAGS
環境変数を設定することで、dist
コマンドに-s
フラグを渡すことが可能になります。
- 新しい環境変数
-
CXX
の言及追加:src/make.bash
:CC
(Cコンパイラ)の記述に加えて、CXX
(C++コンパイラ)に関する記述が追加されています。これは、cgo
を使用する際にC++コンパイラが関与する場合があるため、その設定方法を明確にするためのものです。この変更は静的リンク機能とは直接関係ありませんが、同じコミットで同時に行われました。
これらの変更により、ユーザーはGO_DISTFLAGS=-s ./make.bash
のようにコマンドを実行することで、Goツールチェイン全体を静的にリンクされたバイナリとしてビルドできるようになります。これにより、ビルドされたツールチェインは、実行環境に特定の共有ライブラリが存在しなくても動作するようになります。
コアとなるコードの変更箇所
src/cmd/dist/a.h
--- a/src/cmd/dist/a.h
+++ b/src/cmd/dist/a.h
@@ -112,6 +112,7 @@ void goc2c(char*, char*);
// main.c
extern int vflag;
+extern int sflag;
void usage(void);
void xmain(int argc, char **argv);
sflag
という新しい外部変数が宣言されています。これは、静的リンクモードが有効かどうかを示すフラグとして使用されます。
src/cmd/dist/build.c
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -720,6 +720,8 @@ install(char *dir)
tvadd(&link, bpathf(&b, "%s/%s", tooldir, name));
} else {
vcopy(&link, gccargs.p, gccargs.len);
+ if(sflag)
+ tvadd(&link, "-static");
tvadd(&link, "-o");
targ = link.len;
tvadd(&link, bpathf(&b, "%s/%s%s", tooldir, name, exe));
@@ -1527,6 +1529,9 @@ cmdbootstrap(int argc, char **argv)
case 'a':
rebuildall = 1;
break;
+ case 's':
+ sflag++;
+ break;
case 'v':
vflag++;
break;
@@ -1613,6 +1618,9 @@ cmdinstall(int argc, char **argv)
int i;
ARGBEGIN{
+ case 's':
+ sflag++;
+ break;
case 'v':
vflag++;
break;
install
関数内で、sflag
が真の場合にリンカオプションとして-static
が追加されるようになります。これにより、Goツールチェインが依存するC/C++コードが静的にリンクされます。
また、cmdbootstrap
とcmdinstall
関数に-s
オプションの処理が追加され、このオプションが渡されるとsflag
がインクリメントされます。
src/cmd/dist/main.c
--- a/src/cmd/dist/main.c
+++ b/src/cmd/dist/main.c
@@ -5,6 +5,7 @@
#include "a.h"
int vflag;
+int sflag;
char *argv0;
// cmdtab records the available commands.
sflag
が定義され、cmd/dist
プログラム全体で利用可能なグローバル変数として設定されています。
src/make.bash
--- a/src/make.bash
+++ b/src/make.bash
@@ -37,6 +37,11 @@
#
# CC: Command line to run to get at host C compiler.
# Default is "gcc". Also supported: "clang".
+# CXX: Command line to run to get at host C++ compiler, only recorded
+# for cgo use. Default is "g++". Also supported: "clang++".
+#
+# GO_DISTFLAGS: extra flags to provide to "dist bootstrap". Use "-s"
+# to build a statically linked toolchain.
set -e
if [ ! -f run.bash ]; then
@@ -140,7 +145,7 @@ buildall=\"-a\"\n if [ \"$1\" = \"--no-clean\" ]; then
\tbuildall=\"\"\n fi
-./cmd/dist/dist bootstrap $buildall -v # builds go_bootstrap
+./cmd/dist/dist bootstrap $buildall $GO_DISTFLAGS -v # builds go_bootstrap
# Delay move of dist tool to now, because bootstrap may clear tool directory.
mv cmd/dist/dist "$GOTOOLDIR"/dist
"$GOTOOLDIR"/go_bootstrap clean -i std
GO_DISTFLAGS
という新しい環境変数に関する説明が追加され、-s
フラグを使って静的リンクされたツールチェインをビルドできることが示されています。
./cmd/dist/dist bootstrap
コマンドの呼び出しに$GO_DISTFLAGS
が追加され、この環境変数を介してdist
コマンドにフラグを渡せるようになります。
また、CXX
環境変数に関する説明も追加されています。
コアとなるコードの解説
このコミットの核心は、GoのビルドシステムがC/C++コンパイラ(通常はGCCやClang)を呼び出す際に、静的リンクを指示する-static
フラグを条件付きで追加するロジックにあります。
-
sflag
の役割:sflag
は、ユーザーが静的リンクを要求したかどうかをcmd/dist
ツール全体で追跡するための単純な整数フラグです。コマンドラインで-s
オプションが指定されるたびにインクリメントされます。 -
build.c
における-static
の挿入:src/cmd/dist/build.c
のinstall
関数は、Goツールチェインの各コンポーネント(コンパイラ、リンカなど)をビルドし、インストールする役割を担っています。- この関数内で、GoのツールがC/C++コードをコンパイル・リンクするために外部のC/C++コンパイラ(
gcc
など)を呼び出す部分があります。 if(sflag)
という条件文が追加され、もしsflag
が設定されていれば、vadd(&link, "-static");
という行が実行されます。これは、コンパイラに渡される引数リストに-static
という文字列を追加することを意味します。-static
フラグは、GCCやClangのようなコンパイラに対して、可能な限りすべてのライブラリを静的にリンクするよう指示する標準的なオプションです。これにより、Goツールチェインが依存するCランタイムライブラリなどが、共有ライブラリとしてではなく、ツールチェインのバイナリ自体に組み込まれるようになります。
-
make.bash
とGO_DISTFLAGS
の連携:make.bash
はGoのビルドプロセスの最上位スクリプトです。- 以前は、
./cmd/dist/dist bootstrap
というコマンドが直接呼び出されていましたが、このコミットにより$GO_DISTFLAGS
が追加されました。 - これにより、ユーザーは
GO_DISTFLAGS="-s" ./make.bash
のように環境変数を設定してmake.bash
を実行することで、dist bootstrap
コマンドに-s
フラグを透過的に渡すことができます。 dist
コマンドは-s
フラグを受け取ると、内部のsflag
をセットし、その後のビルドプロセスでC/C++コンパイラを呼び出す際に-static
オプションを付加するようになります。
この一連の変更により、Goツールチェインのビルド時に静的リンクを簡単に有効にできるようになり、Goツールのポータビリティと独立性が向上しました。ただし、OS Xでは静的リンクの概念が異なるため、このフラグは適用されないという注意が必要です。これは、OS Xのシステムライブラリが通常、動的リンクを前提としているためです。
関連リンク
- Go Issue #6448: cmd/dist: support building statically linked toolchain
- Go Issue #3564: cmd/dist: make it easier to build Go from source
- Go Code Review CL 13887043: cmd/dist, build: support building statically linked toolchain
参考にした情報源リンク
- Static vs. Dynamic Linking
- GCC Command Options - Link Options (特に
-static
オプションについて) - Go's build process (Goのソースからのビルドに関する公式ドキュメント)
- Go source code on GitHub
- Go issue tracker
- Go code review system