ノード:Linking executables, 次:, 前:Linking libraries, 上:Using libtool



実行形式のリンク

ライブラリを実行形式とリンクする前に,インストールする(恒久的な 場所にそれを配置する)場所を選択した場合,リンクするためにlibtoolを使用 する必要はありません.ライブラリの位置を指定するため,単純に適切な -L-lフラグを使用してください.

システムのリンカによっては,結果として生じる実行形式に,共有ライブラリ の完全なディレクトリ名の符号化を強要するものもあります.libtoolは,恒 久的なディレクトリ名のみをインストールされた実行形式に書き込むことを確 実にするため,特別な魔法でこの設計ミスに関して動作する必要があります.

このバグの重要性は見落としてはなりません.それによるプログラムの暴走は 明白ではありません.それはセキュリティホールを作成し,さらに悪いことに は,パッケージのインストール後にライブラリソースコードを編集した場合, インストールされたプログラムの動作を変更してしまうでしょう!

そのため,インストールする前にライブラリとプログラムをリンクさせたい場 合,リンクするためにlibtoolを使用する必要があります.

インストールされていないライブラリとリンクする古い方法は,以下のように なります.

     burger$ gcc -g -O -o hell.old main.o libhello.a -lm
     burger$
     

libtoolの方法は,ほとんど同じです1(see Link mode).

     a23$ libtool --mode=link gcc -g -O -o hell main.o libhello.la -lm
     gcc -g -O -o hell main.o ./.libs/libhello.a -lm
     a23$
     

真実としてはあまりに単純に見えます.libtoolが行うことは, libhello.la./.libs/libhello.aに変換することが すべてですが,a23には共有ライブラリがないことを忘れないでくださ い.

burgerでは,状況が異なります.

     burger$ libtool --mode=link gcc -g -O -o hell main.o libhello.la -lm
     gcc -g -O -o .libs/hell main.o -L./.libs -R/usr/local/lib -lhello -lm
     creating hell
     burger$
     

さて,libhello.laが既にインストールされていると仮定し,新しいプ ログラムをそれとリンクしたいとします.自分でそれがある場所を探し,以下 を実行します.

     burger$ gcc -g -O -o test test.o -L/usr/local/lib -lhello
     

しかし,/usr/local/libが標準のライブラリ検索パスに無い場合, testを実行することはできません.しかし,既にインストールされて いるlibtoolライブラリとリンクするためlibtoolを使用する場合,それは The Right Thing (TM) (正解)となります.

     burger$ libtool --mode=link gcc -g -O -o test test.o /usr/local/lib/libhello.la
     gcc -g -O -o .libs/test test.o -Wl,--rpath
     -Wl,/usr/local/lib /usr/local/lib/libhello.a -lm
     creating test
     burger$
     

libtoolが,ライブラリlibhello.laが依存している-lm同様,必要なラ ンタイムパスフラグを追加していることに注意してください.いいですね,ふっ ふ?

libtoolがラッパースクリプトを作成したので,インストールとデバッグにも libtoolを使用したほうがいいでしょう.しかし,プログラムはインストール されていないlibtoolライブラリには全く依存しないので,ラッパースクリプ トを用いない場合でもおそらく有用でしょう.この場合は,ラッパースクリプ トの作成を避けるため,おそらくより賢くlibtoolを作成できたでしょうが, これは読者の演習として残しておきます.

実行形式hellは,実際には.libsサブディレクトリに 作成されることに注意してください.そして,ラッパースクリプトは現在のディ レクトリに作成されます.

NetBSD 1.2では,libtoolは-R/usr/local/libコンパイラフラグを使用 して,libhelloのディレクトリのインストールを符号化します.そし て,ラッパースクリプトは,正しくインストールされるまで実行形式が正しい (./.libsにある)共有ライブラリを見つけることを保証しま す.

二つの異なるプログラムを比較してみましょう.

     burger$ time ./hell.old
     Welcome to GNU Hell!
     ** This is not GNU Hello.  There is no built-in mail reader. **
             0.21 real         0.02 user         0.08 sys
     burger$ time ./hell
     Welcome to GNU Hell!
     ** This is not GNU Hello.  There is no built-in mail reader. **
             0.63 real         0.09 user         0.59 sys
     burger$
     

ラッパースクリプトは実行にかなり時間がかかりますが,共有ライブラリがイ ンストールされていなくても,少なくとも結果は正しくなります.

そのため,共有ライブラリがもたらした,全体的なスペース削減ははどうなっ ているのでしょう?

     burger$ ls -l hell.old libhello.a
     -rwxr-xr-x  1 gord  gord  15481 Nov 14 12:11 hell.old
     -rw-r--r--  1 gord  gord   4274 Nov 13 18:02 libhello.a
     burger$ ls -l .libs/hell .libs/libhello.*
     -rwxr-xr-x  1 gord  gord  11647 Nov 14 12:10 .libs/hell
     -rw-r--r--  1 gord  gord   4274 Nov 13 18:44 .libs/libhello.a
     -rwxr-xr-x  1 gord  gord  12205 Nov 13 18:44 .libs/libhello.so.0.0
     burger$
     

うーん,だめだなあ2.おそらく, 私はこのプロジェクトを破壊し,作成中のゆりかごを取り上げたほうがいいで しょう.

実際,それは重要なことを証明しています.共有ライブラリには,それが(関 連する)複雑さのため,オーバーへッドをがあります.この状況では,ダイナ ミックの価値は8キロバイトで,報酬は約4キロバイトです.そのため,少なく とも二,三個以上のプログラムとリンクするまで,共有される libhelloを維持することは利点になりません.


脚注

  1. しかし,インストールされて いないlibtoolライブラリにリンクするために,-L-lフラグ の使用は避けたほうがいいでしょう..laファイルに対する, ../intl/libintl.laのような相対パスのみを指定してください.これ は,インストールされていない共有ライブラリに対しリンクするとき,あらゆ る曖昧さを取り除くため決定された設計です.

  2. 訳注:原文は,Well, that sucks.