動的ライブラリに静的ライブラリの異なるバージョンをラッピング
-
25-09-2019 - |
質問
私のプロジェクトでは、静的ライブラリへの依存は、サードパーティから(ちょうど今からlibsomething
と呼ばれる)があります。最近、libsomething
は別のバージョンで利用可能になりました。私の仕事は、古いものと新しいバージョンのサポートと私のソフトウェアを提供することです。のみlibsomething
の1つのバージョンは、任意の時点で、実行時に使用されますが、これはどのバージョンのプログラムの実行の間で設定可能である必要があります。
私は二次的な目的は、LinuxおよびGCCに切り替えるために準備になることです、WinXPの上MSVC2005を使用しています。
両方のバージョンのシンボルが、リンク時に各地を衝突しようとしているように、 libsomething
の両方のバージョンが私の実行可能ファイルにリンクする、それらの両方を同じ記号を使用しているので問題外です。
私は2つの実行可能ファイル(古いバージョンに対して1つのリンク、新しいバージョンを使用して他の1)を作成することができますが、私は、最終的なデプロイメント環境(レガシー上の理由)で呼び出すための実行可能の判断を実装することはできません。
私はlibsomething
のバージョンごとに動的ライブラリのラッパーを作成し、いくつかの設定ファイルに応じて、実行時にそれらを結ぶというアイデアを思い付きました。 MSCVで、これはLinux上で私が使用LoadLibrary()
とGetProcAddress()
に持っているだろうが、などdlopen()
、dlsym()
を、使用しての道を行くのを意味します。
は私がlibtool
を使用して(すなわち、libtldl
)が共有ライブラリを使用するため、このプラットフォーム依存性をラップしていることを理解します。これは、従うべき適切なパスですか?より良い(あるいは、少なくとも、異なる)の方法がありますか?オープンソースとしてlibtldl
のが存在のための選択肢をしますか?
解決
これは、ここ数年が経ちましたが、私は完全のための別の解決策に言及したいと思います。代わりに、手動dlopen
の、あなたは、ライブラリのバージョンが必要とされているかを決定、それをロードし、アドレスの解決に必要なすべての機能のためのシンプルなスタブを生成し、最初の呼び出しで(またはプログラム起動時に)可能性があります。
dlsym
あなたは、具体的プロジェクトや使用 Implib.so のツールに合わせたスクリプトを書くことができます:
# This will generate mylib.so.init.c and mylib.so.tramp.S
# which implement stubs. These need to be linked to your
# executable.
$ implib-gen.py mylib.so
Implib.soは、Linuxのみの気圧ですが、Windowsに簡単に適応する必要があります。
他のヒント
私はあなたが原因実行するの決定に2つの実行を使用することができないと言いましたけど、あなたは設定?
で選択されているバージョンに応じて、実行ファイル間を行き来することができませんでしたexec
上のLinuxは、それが正しいバージョンの共有ライブラリと使用シンボリックリンクへのリンクにあなたのために容易になるだろう - 。IMOそれはdlopen()
+ dlsym()
を使用するよりもはるかに簡単です。
このように、あなたはあなたのライブラリーの古いものと新しいバージョンの共有ライブラリを作成します
g++ -shared -o libshared.so.1.1 -Wl,-soname=libshared.so.1 -L. -Wl,--whole-archive libstatic.a.old -Wl,-no-whole-archive
と
g++ -shared -o libshared.so.1.2 -Wl,-soname=libshared.so.1 -L. -Wl,--whole-archive libstatic.a.new -Wl,-no-whole-archive
シンボリックリンクを作成します:
ln -s libshared.so.1.1 libshared.so.1
ln -s libshared.so.1 libshared.so
ライブラリの古いバージョンにリンク、アプリケーションをビルドします。私は両方のバージョンが(ABIが壊れていない)バイナリ互換性があるとしますが、新しいものは、いくつかの新しいシンボルを持つことができます。
g++ -o myapp myapp.cpp -L. -lshared
SONAME
がlibshared.so.1
されているので、あなたのアプリケーションは、それに依存し、libshared.so.1
からのパスに/etc/ld.so.conf
を検索したり、LD_LIBRARY_PATH
あなたがlibshared.so.1
またはlibshared.so.1.2
をポイントにlibshared.so.1.1
のシンボリックリンクを設定することがあります。
ここで使用されるリンカーオプションについてリトル情報:
- 全体 - アーカイブ
--whole・アーカイブ・オプションの後に、コマンドライン上で述べた各アーカイブ、についてでアーカイブ内のすべてのオブジェクトファイルをインクルード リンクではなく、必要なオブジェクトファイルのアーカイブを検索するよりも。これは通常の共有にアーカイブファイルを回すために使用されています 結果の共有ライブラリに含まれるすべてのオブジェクトを強制的にライブラリー。このオプションは複数回使用することができます。
2つのノートのgccからこのオプションを使用する:まず、gccがこのオプションについて知らないので、あなたは-Wl、-whole-アーカイブを使用する必要があります。 第二には、gccがあなたにアーカイブの独自のリストが追加されますので、アーカイブのリストの後-Wl、-no-全アーカイブを使用することを忘れないでください リンクとあなたはこのフラグが同様にそれらに影響を与えたくない場合があります。-soname =名前
ELFを作成すると、オブジェクトを共有するとき、指定された名前に内部DT_SONAMEフィールドを設定します。実行可能ファイルは、Aとリンクされている場合 実行可能ファイルが実行されるときDT_SONAMEフィールドを持つオブジェクトを共有し、動的リンカーは、共有オブジェクトをロードしようとし DT_SONAMEフィールドで指定されたのではなくリンカに指定したファイル名を使用します。