Ldの-rpath
オプションを$Origin
here とともに使用する基本的な例を作成しました(動作するバージョンの2番目の応答を参照)。 main.run
がfoo.so
にリンクし、次にbar.so
にリンクし、すべてrpath
および$Origin
を使用する例を作成しようとしています。
実行時のファイル構造は次のとおりです。
- 事業/
- lib /
- dir /
- サブ/
- bar.so
- foo.so
- run /
- main.run(ビルドに失敗)
私はfoo.soを構築しています:
g++ -c -o obj/foo.o src/foo.cpp -fPIC
g++ -shared -o lib/dir/foo.so obj/foo.o -Wl,-soname,foo.so -Wl,-rpath,'$Origin/sub' -Llib/dir/sub -l:bar.so
それはうまくいきます。 ldd lib/dir/foo.so
はbar.so
を見つけることもできます。
しかし、main.run
をfoo.so
にリンクしようとすると、foo.so
がbar.soを見つけることができません。
私はmain.soをビルドしています:
g++ -c -o obj/main.o src/main.cpp
g++ -o run/main.run obj/main.o -Wl,-rpath,'$Origin/../lib/dir' -Llib/dir -l:foo.so
これは、再帰的にリンクしない別のバージョンのfoo.so
が使用されている場合に正常に機能します。 (以下のプロジェクトのmake.shの行のコメントを外してテストします)。
ただし、通常のfoo.so
を使用すると、main.run
のビルド時にこのエラーが発生します。
/ usr/bin/ld:警告:bar.so、lib/dir/foo.soで必要、見つかりません(-rpathまたは-rpath-linkを使用してみてください)
だから私の質問は:
$Origin
はproject/lib/dir
(foo.so
が存在する場合)またはproject/run
(main.run
(それをリンクしている実行可能ファイル)が存在する場合)に解決されますか?project/lib/dir
であることを示しているようですが、これは最良の方法のようです(ただし、両方を想定してみました)。-rpath-link
を使用しないでください。プロジェクトをダウンロードできます here 。それは私が作ることができるのと同じくらい簡単です。 4つの短いソースとスクリプト。
抽出後、./make.sh
内からproject/
を実行するだけです。
注:私は-l:
を使用しています。これは、ライブラリの名前がfoo.so
ではなくlibfoo.so
のようになり、-l:foo.so
ではなく-lfoo
でランキングされることを除いて、何も変更しないでください。
まあ、私は何かが働いています。しかし、なぜそれが機能するのか本当にわかりません。これは、ldのバグのように感じます。
Main.runコンパイルのためにstrace -f -o /var/tmp/strace.out -- g++ ...
を実行しました。静的リンカーは、実際には、リテラル名が "$ Origin/lib/dir/sub/bar.so"のように見えるファイルを20〜30個開くようにしています。 (つまり、$Origin
という名前の実際のディレクトリを探しています。真剣に。)
「bar.so」だけでなく、「lib/dir/sub/bar.so」という名前の-rpath-linkパスも検索しているようです。理由がわかりません。
とにかく、これは私のために働いているmain.runへのリンクです:
g++ -o run/main.run obj/main.o -Wl,-rpath,'$Origin/../lib/dir' -Wl,-rpath-link,. -Llib/dir -l:foo.so
これはあなたのものと同じですが、-Wl,-rpath-link,.
が挿入されています。
[補遺]
何が起こっているのかわかりました。まず、静的リンカー(GNU ld)は、リンク先のライブラリーで$ Originを受け入れません。
次に、-lbar
と-l:bar.so
を使用したときの動作は大きく異なります。
readelf -a
でfoo.so
を実行します。ビルドでは、「lib/dir/sub/bar.so」への依存関係が表示されます。これが、rpath-linkを "。"に設定する理由です。 main.runのビルドを修正します。静的リンカで「。」を検索します。見つかった「lib/dir/sub/bar.so」の場合。
Bar.soの名前をlibbar.soに変更し、foo.soをリンクして-lbar
の代わりに-l:bar.so
を使用する場合、同じreadelfは、foo.soが「libbar.so」に依存していることを示します(パスコンポーネント)。そのfoo.soを使用すると、静的リンカーが$ Originを尊重しないことを知っていれば、-Wl,-rpath-link,lib/dir/sub
を使用してmain.runリンクを機能させることができます。
ちなみに、GNU ldマニュアルに記載されている-l:bar.so
構文はありません。好奇心から、どうやってそれを思いついたのですか?
サポートされている機能だとすると、これはバグのように見えます(-l:bar.soは、bar.soだけでなく、lib/dir/sub/bar.soへの依存関係を作成します)。 rpath-linkを「。」に設定することで、このバグに対処できます。 main.runの場合、または通常の方法で名前を変更できます(libxxx.so)。
ld-linux(8) マンページから:
$ Originとrpath
ld.soは、rpath仕様(DT_RPATHまたはDT_RUNPATH)の文字列$ Origin(または同等の$ {Origin})を理解して、アプリケーション実行可能ファイルを含むディレクトリを意味します。したがって、somedir/appにあるアプリケーションをgcc -Wl、-rpath、 '$ Origin /../ lib'でコンパイルすると、somedirがディレクトリのどこにあるかに関係なく、関連する共有ライブラリをsomedir/libで見つけることができます。階層。これにより、特別なディレクトリにインストールする必要がない「ターンキー」アプリケーションの作成が容易になりますが、代わりに任意のディレクトリに解凍しても、独自の共有ライブラリを見つけることができます。
したがって、最初の質問への回答では、$Origin
の値は1つだけです:project/run
。
したがって、2番目の質問に対する答えは、次のコマンドを使用してfoo.so
をリンクすることです。
g++ -shared -o lib/dir/foo.so obj/foo.o -Wl,-soname,foo.so -Wl,-rpath,'$Origin/../lib/dir/sub' -Llib/dir/sub -l:bar.so
まず、問題を引き起こす可能性のある$記号の展開に関する問題があります。私はPython=ソースからビルドしています、そしてこれを行います:
export LDFLAGS='-Wl,-rpath,\$${Origin}/../lib -Wl,-rpath,\$${Origin}/../usr/lib -Wl,--enable-new-dtags'
make
を実行する前。これは正常に機能し、第1レベルの依存関係を見つけます。このタイプのマクロ展開の問題を処理するときは、一重引用符と二重引用符に注意してください。
次に、バイナリまたはライブラリでobjdump -x
を実行すると、実際に含まれているRPATHヘッダーを確認できます。 objdump -x path/to/python |grep RPATH
を実行すると、this.RPATH $ {Origin} /../ lib:$ {Origin} /../ usr/lib`が表示されます
バイナリをチェックして、実際にRPATHヘッダーに何があるかを確認することをお勧めします。残念ながら、これで問題が解決するとは思いません。 ldd path/to/python
を実行すると、次のようになります。
libpython2.7.so.1.0 => /data1/python27/bin/../lib/libpython2.7.so.1.0 (0x00002ad369d4f000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00002ad36a12f000)
libdl.so.2 => /lib/libdl.so.2 (0x00002ad36a34d000)
libutil.so.1 => /lib/libutil.so.1 (0x00002ad36a551000)
libm.so.6 => /lib/libm.so.6 (0x00002ad36a754000)
libc.so.6 => /lib/libc.so.6 (0x00002ad36a9d8000)
/lib64/ld-linux-x86-64.so.2 (0x00002ad369b2d000)
ご覧のとおり、第1レベルの依存関係はrpath
によって正しく処理されますが、第2レベルの依存関係、つまりlibpythonの依存関係はシステムライブラリに戻ります。そして、はい、libpythonのバイナリにはまったく同じRPATHヘッダーがあります。ディストリビューションに依存しないパッケージを作成するという私の問題を解決するためにrpath recursive
をグーグル検索しているときに、あなたの質問を見つけました。
後で追加rpath
ヘッダーは、ライブラリを検索する最初のパスのみを変更します。そこで見つからない場合、ローダーは通常の場所で検索を続けます。 ldd
は、検索の結果として見つかったライブラリの実際のパスのみをリストします。これらのライブラリをrpath
ディレクトリにコピーすると、すべてが機能しました。基本的に、すべての依存関係を見つけてコピーするための整頓された方法はなく、ldd -v path/to/python
とその出力のいくつかの解析だけです。
私もこれについて調査してきましたが、Origin展開を使用するすべてのパスには-rpath-link
を使用する必要があることをお伝えします。例えば:
CC -shared (other flags) -R'$Origin/../lib/' -o /buildpath/lib/libmylib1.so
CC -shared (other flags) -R'$Origin/../lib/' -lmylib1 -o /buildpath/lib/libmylib2.so
# This fails to link 'somebinary'
CC (various flags) -R'$Origin/../lib/' -lmylib2 -o /buildpath/bin/somebinary
# This works correctly
CC (various flags) -R'$Origin/../lib/' -Wl,-rpath-link,/buildpath/lib/mylib1 -lmylib2 -o /buildpath/bin/somebinary
# The text above the carets to the right is a typo: ------------------^^^^^^
# I'm fairly sure it should read like this (though it has been awhile since I wrote this):
# (...) -Wl,-rpath-link,/buildpath/lib -lmylib1 (...)
ld
は、$Origin
を使用して指定されたパスまたはサブ依存関係のRPATHから取得したパス内で-rpath-link
を展開しません。上記の例では、mylib2
はmylib1
に依存しています。 somebinary
のリンク中に、ld
はlibmylib2.soに埋め込まれたリテラル/非拡張文字列mylib1
を使用して$Origin/../lib/
を見つけようとします。 ld.so
は実行時に実行されますが、ld
は実行されません。
また、-L
で指定されたパスを使用して、サブ依存関係のlibrar(y | ies)を検索しません。
チェック 私の変更したmakeスクリプトのバージョン 。基本的に、ld
は_-rpath-link
_をまったく理解しないため、_$Origin
_なしの追加の_$Origin
_を使用する必要があります。
あなたの質問も。
$Origin
_は実行時にのみ機能し、w.r.tです。各ライブラリ。したがって、共有ライブラリごとに_$Origin
_が異なります。rpath-link
_を追加するのが最善の方法だと思います。これは相対的であり、最終バージョンの実行可能ファイルには存在しないため、移植性には影響しません。これは、私のバージョンの_make.sh
_また、 これはリンクするもの全体についての私自身の理解です です。お役に立てば幸いです。
私の理解から、これはld(つまりbinutils)の問題であり、「Secondary Dependencies」をどのように解決するか
AFAIKはbinutils >= 2.30
から始まりました。依存関係のrpathが検索に追加されます。つまり、ld ... main.exe
find foo.so
、次にfoo.so
のRPATHを読み取り、bar.so
を見つけます。
ここで私のスタックオーバーフローの質問: Binutilsセカンダリ依存関係の変更
そして、さまざまなbinutilsバージョンをテストするためのさまざまなディストリビューション(dockerコンテナー内)の私の調査 https://github.com/Mizux/SecondaryDependency
注:travis-CIログを見てください...