4

2 つの外部静的ライブラリ B と C にリンクする必要がある共有ライブラリ A を構築しているとします。必要なのは、libB.a と libC.a とそれらのヘッダー ファイルだけです。

libA の単純化された Android.mk を次に示します。

LOCAL_LDLIBS := ../external/libB.a ../external/libC.a

include $(BUILD_SHARED_LIBRARY)

私の知る限り、共有ライブラリのリンクが機能する方法は次のとおりです。

  1. B と C のすべてのオブジェクト ファイルを取得します。
  2. A が参照しないオブジェクト ファイルを取り除く
  3. B と C の参照を解決する

これにより、B と C が相互に呼び出し、具体的には、A が呼び出さなかったために手順 2 で削除された関数を呼び出すため、リンク エラーが発生します。

静的ライブラリを自分で作成した場合は、LOCAL_STATIC_LIBRARIES を LOCAL_WHOLE_STATIC_LIBRARIES に置き換えるだけで済みます。これにより、コードのストリッピングが防止されます (コード サイズが犠牲になります)。内部では、 --whole-archive をリンカーに渡します。

B と C をビルドしていない (そして、それらを再ビルドするためのソースすら持っていない) ため、どのようなオプションがありますか?

  1. A から欠落している関数を手動で参照して、削除されないようにする
  2. --whole-archive を外部静的ライブラリのリンカーに渡す方法を理解する
  3. PREBUILT_STATIC_LIBRARY を使用します (言及されていますが、使用したことはありません。ドキュメントによると、この場合は適用できないようです)
  4. 共有ライブラリの代わりに実行可能ファイルをビルドします (同じようにコードを削除しません)。
  5. 外部ライブラリを移動/名前変更して、NDKビルドシステムをだましてそれらが私のものだと思わせ、LOCAL_WHOLE_STATIC_LIBRARIESに追加できるようにします。

オプション 1 が最初に機能したため、オプション 1 を使用しましたが、明らかに良くありません。より良い解決策があるかどうかを尋ねています。

この質問への回答 (事前にビルドされた静的ライブラリと共有ライブラリを Android NDK でリンクする際の問題) は、ビルド セットアップ (外部静的ライブラリにリンクする共有ライブラリ) を再評価する必要があるかどうか疑問に思いました。そこにコメントすることはできないので、ここで私自身の質問をしました。

4

1 に答える 1

6

答えは、binutils リンカーを使用して静的ライブラリ間の再帰的な依存関係に対処する方法で見つけることができますか? .

LOCAL_LDLIBS := -L ../external/ -lB -lC -lB

two-libs NDK サンプルを使用し、最小限の変更を加えて GitHubでテクニックを示しました。

更新 (2017)LOCAL_LDLIBS : 2012 年以降、NDK のルールがより厳格になり、システム以外のライブラリが含まれていると不平を言うようになりました。

Android NDK: 警告: Android.module: リンカー フラグの非システム ライブラリ: -la -lb
Android NDK: これにより、ビルドが正しく行われない可能性があります。代わりにLOCAL_STATIC_LIBRARIES
Android NDK: または LOCAL_SHARED_LIBRARIES を使用して、
Android NDK: 現在のモジュール のライブラリ依存関係を一覧表示してみてください。

これは単なる警告なので、無視してかまいません。

-lまたは、NDK 保護を裏切るためにスペースを追加します。

LOCAL_LDLIBS := -L ../external/ -l B -l C -l B

または、使用することができます

LOCAL_LDLIBS += -L ../external -Wl,--start-group -l B -l C -Wl,--end-group

関連するライブラリが事前にビルドされていない場合は、それらの場所を推測する必要はありません (Android Studio NDK 統合を使用する場合は特に注意が必要です)。使用する

LOCAL_LDLIBS := -L $(TARGET_OUT) …

「再帰的」リンクを使用しない代替アプローチが存在します。しかし、それには反復が伴います。まず、通常の方法で共有ライブラリを構築してみてください。これが未解決のシンボルで失敗した場合は、これらのシンボルをすべてクリップボードにコピーし、Android.mkに貼り付けます。extBaこれらのシンボルが, extBb, and であるとしましょうextBc(上記のシナリオでは、 libC の一部のオブジェクトがlibBのどこかに定義されているこれらのシンボルを見つけられないと思います。それがリンクが失敗する理由です)。今必要なものを追加

LOCAL_LDFLAGS += -Wl,-u'extBa' -Wl,-u'extBb' -Wl,-u'extBc'

次のステップを実行して、これをすべてlibCにバンドルすることができます。

LOCAL_EXPORT_LDFLAGS += -Wl,-u'extBa' -Wl,-u'extBb' -Wl,-u'extBc'

現在、libCを使用する共有ライブラリはこれらのシンボルを見逃すことはありません。

于 2012-12-02T10:23:17.223 に答える