1. ホーム
  2. gcc

[解決済み] 依存関係のある動的ライブラリとリンクする

2023-06-04 22:03:46

質問

次のようなシナリオを考えてみましょう。

  • 共有ライブラリ libA.so ,依存関係なし。
  • 共有ライブラリ libB.so、依存関係にあるのはlibA.soです。

libBとリンクするバイナリをコンパイルしたい。 libBのみとリンクするのか、libAともリンクするのかどちらでしょうか?

直接の依存関係にあるものだけをリンクし、依存関係から未解決のシンボルの解決を実行時にさせる方法はありますか?

ライブラリ libB の実装が将来変更され、他の依存関係 (たとえば libC、libD、libE) を導入する可能性があるという事実が心配です。私はそれについて問題を抱えることになるのでしょうか?

言い換えれば

  • libAファイル:a.cpp a.h
  • libBファイル:b.cpp b.h
  • メインプログラムファイル:main.cpp

もちろん、b.cppはa.hを含み、main.cppはb.hを含んでいます。

コンパイルコマンドです。

g++ -fPIC a.cpp -c
g++ -shared -o libA.so a.o

g++ -fPIC b.cpp -c -I.
g++ -shared -o libB.so b.o -L. -lA

以下のオプションのうち、どれを使用すればよいですか?

g++ main.cpp -o main -I. -L. -lB

または

g++ main.cpp -o main -I. -L. -lB -lA

最初のオプションは使えませんでした。リンカはライブラリlibAからの未解決のシンボルについて文句を言います。しかし、それは私には少し奇妙に聞こえます。

どうもありがとうございました。

-- コメントを更新しました。

バイナリをリンクする際、リンカーはmainとlibBからすべてのシンボルを解決しようとします。しかし、libB は libA から未定義のシンボルを持っています。そのため、リンカはそのことについて文句を言うのです。

というわけで、libAも一緒にリンクする必要があります。 しかし、私は共有ライブラリからの未解決シンボルを無視する方法を見つけました。 次のコマンドラインを使用する必要があるようです。

g++ main.cpp -o main -I. -L. -lB -Wl,-unresolved-symbols=ignore-in-shared-libs

見た目はまだ -rpath オプションの使用は可能なようです。 しかし、私はそれをもう少し理解する必要があります。

を使用する際に起こりうる落とし穴をご存知の方はいらっしゃいますか? -Wl,-unresolved-symbols=ignore-in-shared-libs オプションを使用する際の落とし穴をご存知の方はいらっしゃいますか?

-- コメント2を更新しました。

-rpath は、この目的のために使用すべきではありません。指定されたディレクトリにあるライブラリを強制的に見つけるのに便利です。そのため -unresolved-symbol のアプローチの方がずっと良さそうです。

本当にありがとうございます。

どのように解決するのですか?

もうほとんど解決しているようですね。よく調べましたね。その背後にある「理由」を明らかにする手助けができるかどうか見てみましょう。

リンカーが行っていることは次のとおりです。実行ファイル (上記の 'main') をリンクするとき、未解決のシンボル (関数やその他のもの) がいくつか存在します。リンカーは未解決のシンボルを解決しようと、その後に続くライブラリのリストを調べます。その過程で、いくつかのシンボルが libB.so によって提供されていることがわかり、現在ではこのライブラリによって解決されていることを記録します。

しかし、これらのシンボルのいくつかは、実行ファイルでまだ解決されていない他のシンボルを使用していることも発見されたので、それらも解決する必要があります。libA.so に対してリンクしなければ、アプリケーションは不完全なものになります。libA.so に対してリンクすると、すべてのシンボルが解決され、リンクが完了します。

ご覧のように -unresolved-symbols-in-shared-libs を使用しても問題は解決されません。それは、それらのシンボルが実行時に解決されるように、問題を延期するだけです。それが -rpath は、実行時に検索するライブラリを指定するためのものです。実行時にシンボルを解決できない場合、アプリは起動に失敗します。

シンボルは複数のライブラリで提供され、それらのいずれかに対してリンクすることで満たされる可能性があるため、ライブラリの依存関係を把握するのは簡単なことではありません。

このプロセスについては、こちらにも記述があります。 なぜ、ライブラリがリンクされる順序は、ときどきGCCでエラーを引き起こすのですか?