本サイトでは、アフィリエイト広告およびGoogleアドセンスを利用しています。

gccによるC/C++ランタイムのスタティックリンク

前回興味を持った内容の続きです。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++

次のようなコードをサンプルとして使ってみました。

#include 

int 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 は使えないそうです。

プログラミング
すらりんをフォローする
すらりん日記
タイトルとURLをコピーしました