TenForward

技術ブログ。はてなダイアリーから移転しました

スタティックリンク

Cのプログラムはもう 10 年以上書いてないけど,最近 C で書かれた Linux 上で動くプログラムの評価をしていました.で,ちょっと調べていたこと.

環境による依存性をなくそうと,スタティックリンクしてあるプログラムなんですが,なぜか環境によって動かないということがありました.gethostbyname 辺りなんですが,よく考えてみると,ココって NSS (Name Service Switch) が絡むから,どうしてもダイナミックリンクになってしまうんですよね.nsswitch.conf の内容次第で,動かしてみないと何を使うか分からないですから.

pam なんかも同様かも知れませんね.あとは iconv 廻りとか.

JMのnsswitch.confの解説を見ると,

Solaris では NSS サービスを用いたプログラムをスタティックにリンクすることはできない。 Linux では問題なくスタティックリンクできる。

なんて一文があって,そもそも仕組としてスタティックリンク出来ないようになっている環境もあるようです.Linux でも当然リンクは出来るけど,実際はダイナミックにロードされるって事ですよね.

でも,どーしても環境依存したくないという場合もあると思います.で,そんなことが出来ないかなあと考えてみたりしてました.ちょっとぐぐってみると...

なんてページが.ELF STATIFIER なんてモノがあって,動的にリンクされたプログラムとライブラリを一つにまとめてくれるプログラムです.

Welcome – Gentoo Linux にも prelink なんてものがあって,同様の目的のモノでしょうか.しかし,prelink だと

"ダウンロードしたバイナリパッケージはすべてを自分自身に含んでいるため、ターゲットシステムのローカルライブラリに依存しないと考えます。しかしあいにくLinux、また他のGLIBCを使用したシステムで、これは完全に真ではありません。さまざまなデータベースへの認証、ネットワーク情報などの機能を提供する"libnss"(ネームサービススイッチライブラリ。ネットワークセキュリティシステムと呼ばれることもある)があります。これはそのマシンの実際のネットワークに依存しないアプリケーションプログラムを作ることができます。良い考えですが、GLIBCを変更するとロードするときに問題が置こる場合があります。"libnss"をスタティックリンクすることはできません。なぜならそれぞれのマシン個々で設定されているからです。その問題は主に他のGLIBCライブラリと静的にリンクれている場合に起こると考えます。特に"libnss"から個々に呼ばれる"libpthread"、"libm"、"libc"で起こります。"

なんて書かれています.

ELF STATIFIER の場合は statifier で動的リンクの実行ファイルを擬似的に静的リンクにする の「さらに追記」の部分に

LD_PRELOAD して statifier を実行するとどうすか、と指摘を受けました。さっそく試したところ、環境変数 LD_PRELOAD に /lib/libnss*.so を含めておけば、生成されるバイナリにこれらを含めることができました。

とあり,うまくいくようです (私は試してません ^^;).