12

ビルド スクリプトで静的ライブラリをビルドし、それらの静的ライブラリを最終的な実行可能ファイルのリンクに使用したい場合、ファイルを指定する順序.aが重要です。

g++ main.o hw.a gui.a -o executable

gui.aリンクで定義されたものを使用すると失敗します。これhw.aは、その時点hw.aで処理されるため、リンカーは後で定義が必要であることをまだ認識しておらず、それを being.generated 実行可能ファイルに含めないためです。リンカー行を手動でいじるのは実用的ではないため、解決策は--start-groupandを使用することです--end-group。これにより、未定義のシンボルが見つからなくなるまで、リンカーがライブラリを 2 回実行します。

g++ main.o -Wl,--start-group hw.a gui.a -Wl,--end-group -o executable

ただし、GNU ld マニュアルには次のように書かれています

このオプションを使用すると、パフォーマンスが大幅に低下します。2 つ以上のアーカイブ間で避けられない循環参照がある場合にのみ使用することをお勧めします。

したがって、すべてのファイルを取得して、ファイルをリンクする必要がある順序を示すインデックス ( GNU ar のオプション) を使用.aして 1 つのファイルにまとめた方がよいのではないかと考えました。次に、その 1 つのファイルのみを に渡します。.a-s.ag++

しかし、グループコマンドを使用するよりも速いか遅いかは疑問です。そして、そのアプローチに問題はありますか?また、これらの相互依存性の問題を解決するためのより良い方法はありますか?


編集:ファイルのリストを.a取得してマージされたファイルを生成するプログラムを作成しました.a。GNU 共通arフォーマットで動作します。LLVM のすべての静的ライブラリをまとめてパックすると、次のように機能します

$ ./arcat -o combined.a ~/usr/llvm/lib/libLLVM*.a

すべてのファイルを手動で解凍し、インデックスを再計算して新しいファイル.aに入れる場合と速度を比較しました。私のツールを使用すると、約 500 ミリ秒の一貫したランタイムが得られます。手動の方法を使用すると、時間は大きく異なり、約 2 秒かかります。だから価値があると思います。.aararcat

コードはこちらです。私はそれをパブリックドメインに入れました:)

4

2 に答える 2

3

たとえば、lorderおよびユーティリティを使用して順序を決定できます。tsort

libs='/usr/lib/libncurses.a /usr/lib/libedit.a'
libs_ordered=$(lorder $libs | tsort)

/usr/lib/libedit.a /usr/lib/libncurses.alibedit は libncurses に依存しているためです。

リンク コマンドごとにand を再度--start-group実行しない場合、これはおそらく上記の利点のみです。また、相互/循環依存関係を許可しません。lordertsort--start-group

于 2011-08-14T10:27:06.457 に答える
2

最初に単一のライブラリを構築するだけの 3 番目のオプションはありますか? 私も同様の問題を抱えていたので、最終的に 3 番目のオプションを使用することにしました。

私の経験では、グループは .a ファイルを統合するよりも遅くなります。アーカイブからすべてのファイルを抽出し、小さいファイルから新しい .a ファイルを作成できます

ただし、両方のファイルに同じ定義が含まれている状況には注意する必要があります (nm各ライブラリに含まれている定義を確認するために を使用して、これを明示的に確認できます)。

于 2011-08-13T21:56:07.657 に答える