web-dev-qa-db-ja.com

コンパイル中にBoostライブラリをリンクすることについての混乱

クライアントの場合、システムにブースト1.54を追加する必要がありました。そこで、最新バージョン(1.55)をダウンロードして、特別なディレクトリ/usr/local/lib/boost1.55/内にビルドしました。これは機能します。次に、Makefileをこのように適合させる必要がありました。

LIBS = $(SUBLIBS)-L/usr/lib/x86_64-linux-gnu -LC:/ deps/miniupnpc -lminiupnpc -lqrencode -lrt -LC:/ deps/boost/stage/lib -Lc:/ deps/db/build_unix -Lc:/ deps/ssl -LC:/deps/libqrencode/.libs -lssl -lcrypto -ldb_cxx -L/usr/local/lib/boost1.55/boost_system-mgw46-mt-sd-1_54 -L/usr /local/lib/boost1.55/boost_filesystem-mgw46-mt-sd-1_54 -L/usr/local/lib/boost1.55/boost_program_options-mgw46-mt-sd-1_54 -L/usr/local/lib/boost1 .55/boost_thread-mgw46-mt-sd-1_54 -lQtDBus -lQtGui -lQtCore -lpthread -lboost_system -lboost_filesystem -lboost_program_options -lboost_thread

変更されていないMakefileでは、ブーストリンクは次のようになりました。

-lboost_thread-mgw46-mt-sd-1_54

しかし、これはうまくいきませんでした。見つからなかったため、コンパイルできませんでした。だから私は追加しました(あなたが上で見ることができるように)

-L/usr/local/lib/boost1.55/boost_thread-mgw46-mt-sd-1_54

そして

-lboost_thread

そうでなければ、どちらもコンパイルされません。コンパイルが成功した後、バイナリでlddを実行すると、次のように表示されます。

libboost_system.so.1.53.0 => /usr/lib/x86_64-linux-gnu/libboost_system.so.1.53.0(0x00007f416c169000)libboost_filesystem.so.1.53.0 =>/usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.53.0(0x00007f416bf52000)libboost_program_options.so.1.53.0 => /usr/lib/x86_64-linux-gnu/libboost_program_options.so.1.53.0(0x00007f416bce4000)libboost_thread.so.1.53.0 =>/usr/lib/x86_64-linux-gnu/libboost_thread.so.1.53.0(0x00007f416bace000)

1.53は、パッケージマネージャーによってインストールされたバージョンです。なぜこのバージョンにリンクしているのかわかりません。 1.55をインストールしなかった場合、コンパイルされませんでしたが、現在はこのバージョンにリンクしていません。その説明はありますか?

実際、私の目標はダイナミックリンクライブラリを使用しないことであり、その方法はまだわかりませんでしたが、上記が期待どおりに機能しない理由を知りたいと思います。

4
Bevor

これがLinuxのディストリビューションであるかどうかはわかりませんが、動的にリンク可能なライブラリを追加できるディレクトリが存在することがよくあります。 FedoraなどのRedhatディストリビューションでは、このディレクトリは/etc/ld.so.conf.d/です。

LD

次のように、新しくインストールしたライブラリへのパスを使用して、このディレクトリにファイルを追加できます。

$ cat /etc/ld.so.conf.d/myboost.conf
/usr/local/lib/boost1.55

次に、次のコマンドを実行します。

$ ldconfig -v

これにより、すべてのライブラリが処理され、「キャッシュ」/etc/ld.so.cacheが再構築されます。このキャッシュは、-lboost_thread-mgw46-mt-sd-1_54のように指定されたときにライブラリを見つけるために使用されるものです。

出力例

$ ldconfig -v
/usr/lib64/atlas:
        libclapack.so.3 -> libclapack.so.3.0
        libptcblas.so.3 -> libptcblas.so.3.0
        libf77blas.so.3 -> libf77blas.so.3.0
        libcblas.so.3 -> libcblas.so.3.0
        liblapack.so.3 -> liblapack.so.3.0
        libptf77blas.so.3 -> libptf77blas.so.3.0
        libatlas.so.3 -> libatlas.so.3.0
/usr/lib64/wxSmithContribItems:
        libwxflatnotebook.so.0 -> libwxflatnotebook.so.0.0.1
...

セットアップにパスを追加するときは、この出力を調べて、期待どおりに処理が行われていることを確認します。

LDのキャッシュ

次のコマンドを使用して、.cacheファイルの内容をいつでも印刷できます。

$ ldconfig -p | head -10
2957 libs found in cache `/etc/ld.so.cache'
    lib3ds-1.so.3 (libc6,x86-64) => /usr/lib64/lib3ds-1.so.3
    libzvbi.so.0 (libc6,x86-64) => /usr/lib64/libzvbi.so.0
    libzvbi-chains.so.0 (libc6,x86-64) => /usr/lib64/libzvbi-chains.so.0
    libzrtpcpp-1.4.so.0 (libc6,x86-64) => /usr/lib64/libzrtpcpp-1.4.so.0
    libzmq.so.1 (libc6,x86-64) => /usr/lib64/libzmq.so.1
    libzmq.so (libc6,x86-64) => /usr/lib64/libzmq.so
    libzipios.so.0 (libc6,x86-64) => /usr/lib64/libzipios.so.0
    libzipios.so (libc6,x86-64) => /usr/lib64/libzipios.so
    libzip.so.1 (libc6,x86-64) => /usr/lib64/libzip.so.1

Ldd出力がまだ1.53を使用しているのはなぜですか?

これは、バイナリがダイナミックライブラリを使用しているためです。したがって、バイナリがコンパイルされたとき、それはライブラリの1.55バージョンに反していました。ただし、lddを使用してバイナリに問い合わせると、.cacheファイルの内容を使用している環境内にあります。したがって、このバイナリで使用されるシンボルに関連付けられているキャッシュ内のライブラリは1.53のライブラリと一致するため、これらのライブラリが表示されます。

ご使用の環境は1.55ライブラリについて何も認識しておらず、ビルド環境、つまりMakefileのみがこれを認識しています。

ダイナミックライブラリ

これらの中の機能をシンボルと考えてください。シンボルは名前であるため、これらの名前は、ライブラリのバージョンごとに変更されないことがよくあります。したがって、boostなどのライブラリを調べる場合は、ツールreadelfを使用して、これらの.soファイルの1つに含まれるシンボルのリストを取得できます。

$ readelf -Ws /usr/lib64/libboost_date_time-mt.so | head -10

Symbol table '.dynsym' contains 261 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 000000335aa096a8     0 SECTION LOCAL  DEFAULT    9 
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSt8bad_castD2Ev@GLIBCXX_3.4 (2)
     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSt6locale5_ImplD1Ev@GLIBCXX_3.4 (2)
     4: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  UND _ZTINSt6locale5facetE@GLIBCXX_3.4 (2)
     5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND wcslen@GLIBC_2.2.5 (3)
     6: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  UND _ZTISt11logic_error@GLIBCXX_3.4 (2)

上記の出力では、いくつかのFUNC定義を見ることができます。これらは、実行可能ファイル内の関数をいくつかの.soライブラリの関数と「リンク」するために使用される名前です。

私はこれを単純化しすぎて、おそらく少し説明がずれていますが、ボンネットの下の機械がどのように機能するかについての一般的な考え方を提供しようとしているだけです。

参考文献

6
slm

ダイナミックライブラリを使用するソフトウェアをコンパイルする場合、 [〜#〜] rpath [〜#〜] をコンパイル済みバイナリにハードコーディングしない限り、実行可能ファイルを実行する(またはそれに対してlddを実行する)と、 OSの定義済み検索パス(多くの場合、/ etc/ld.so.confで設定)でライブラリを検索します。

独自のソフトウェアをコンパイルしてライブラリ検索パスの外部にインストールした場合は、ハードコードされたRPATHを使用してバイナリをコンパイルする必要があります。これは、リンカーに-rpathを渡すことによって行われます。ただし、ほとんどの場合、Makefileはリンカーを直接実行しないため、通常は-Wl,-rpath,/usr/local/whatever/libCFLAGSに追加して、リンカーに渡すようにgccに指示する必要があります。

パスをハードコーディングしたくない場合は、$LD_LIBRARY_PATH環境変数を更新して、ランタイムライブラリ検索パスの前に追加するライブラリディレクトリのコンマ区切りのコレクションを含めることができます。 $LD_LIBRARY_PATHの設定は一時的なものであり、バイナリには何の影響も与えないため、実行可能ファイルを実行する必要があるときはいつでも設定する必要があります。 (これを定期的に実行する場合は、 環境モジュール を参照してください)

3
jsbillings