前回興味を持った内容の続きです。CランタイムやC++ランタイムをgccを使える環境でスタティックリンクで実行バイナリにリンクしてしまう!という話になります。
32bit,64bitビルドの区別
gccでコンパイルする際には、-m32, -m64 のオプションで生成するElfバイナリの形式を決めるようです。それぞれが32bit(x86)用コード生成、64bit(x86_64)用コード生成となります。このオプションを使わない場合、gccの実行環境で生成物が変わるようです(64bit Linux上なら64bit elfというように)。
準備
スタティックリンクをやろうとした際には、そもそもスタティックリンクのライブラリが存在しないといけないです。そのライブラリをインストールする必要があり、Ubuntuでは、下記のようにしてインストールしました。
sudo apt-get install build-essential g++-4.6-multilib lib32stdc++6
他の環境では、glibc-static というパッケージをインストールして準備完了というものもあるようです。
これらを忘れるとライブラリが見つからない!とエラーで悩むことになります。
C++
次のようなコードをサンプルとして使ってみました。
#includeint main() { std::cout << "Hello,world" << std::endl; return 0; }
これを下記のようにしてコンパイルして、依存関係を出力してみました。
g++ -m64 hoge.cpp ldd a.out linux-vdso.so.1 => (0x00007fffe4bff000) libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f7d2f7ec000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7d2f42c000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f7d2f12f000) /lib64/ld-linux-x86-64.so.2 (0x00007f7d2fb05000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f7d2ef19000)
確かに、libstdc++.so に依存しているのがわかります。
スタティックリンクのオプション(-static-libstdc++) をつけて同様にやってみます。
g++ -m64 hoge.cpp -static-libstdc++ ldd a.out linux-vdso.so.1 => (0x00007fffedae7000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fe5fb960000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe5fb5a0000) /lib64/ld-linux-x86-64.so.2 (0x00007fe5fbb8f000)
確かに、libstdc++.so への依存が消えましたが、Cランタイムへの動的リンクはそのまま残っているようです。
この libstdc++スタティックリンクのオプションは、gcc 4.5 から導入されたとのことです。
ちなみに、-static オプションをつけると全てスタティックリンクしてくれるような感じです。
g++ -m32 hoge.cpp -static ldd a.out 動的実行ファイルではありません
注意点
dlopenを利用して共有ライブラリをロードする際に、対象の共有ライブラリがダイナミックリンクした libstc++を使う場合、その so は使えないそうです。