25

「my_app」というメインの実行可能ファイルがあり、他のいくつかのライブラリを使用しているとします。3 つのライブラリは静的にリンクされ、他の 3 つのライブラリは動的にリンクされています。「my_app」に対してどの順序でリンクする必要がありますか?

しかし、これらはどの順序でリンクする必要がありますか?

libSB に依存する libSA (静的 A のように) と libSB に依存する libSC を取得したとします。

libSA -> libSB -> libSC

および 3 つの動的ライブラリ: libDA -> libDB -> libDC(libDAは基本、libDCは最高)

これらはどの順序でリンクする必要がありますか?基本的なものは最初ですか、それとも最後ですか?

g++ ... -g libSA libSB libSC -lDA -lDB -lDC -o my_app

正しい順序のように思えますが、そうですか?動的ライブラリと静的ライブラリの間に依存関係がある場合、またはその逆の場合はどうなりますか?

4

5 に答える 5

27

静的なケースでは、静的ライブラリを実際にリンクするわけではないため、実際には問題ではありません。オブジェクト ファイルを 1 つのアーカイブにまとめるだけです。オブジェクト ファイルをコンパイルするだけで、すぐにスタティック ライブラリを作成できます。

動的ライブラリの状況はより複雑で、次の 2 つの側面があります。

  1. 共有ライブラリは、静的ライブラリとまったく同じように機能します (共有セグメントが存在する場合は除きます)。これは、たとえば、libDA のシンボルが libDB では未定義として表示されることを意味します。

  2. 共有オブジェクトをリンクするときに、リンクするライブラリをコマンド ラインで指定できます。これは 1. と同じ効果がありますが、libDB が libDA を必要としているとマークします。

違いは、前者の方法を使用する場合、実行可能ファイルをリンクするときに、コマンド ラインで 3 つのライブラリ (-lDA、-lDB、-lDC) すべてを指定する必要があることです。後者を使用する場合は、-lDC を指定するだけで、リンク時に他のものを自動的にプルします。リンク時間は、プログラムが実行される直前であることに注意してください (つまり、異なるライブラリからでも、異なるバージョンのシンボルを取得できるということです)。

これはすべて UNIX に当てはまります。Windows DLL の動作はまったく異なります。

質問を明確にした後に編集します。

ldインフォマニュアルより引用。

リンカーは、コマンド ラインで指定された場所で、アーカイブを 1 回だけ検索します。アーカイブが、コマンド ラインでアーカイブの前に表示されたオブジェクトで未定義のシンボルを定義している場合、リンカーはアーカイブから適切なファイルをインクルードします。ただし、後でコマンド ラインに表示されるオブジェクト内の未定義のシンボルによって、リンカーがアーカイブを再度検索することはありません。

リンカにアーカイブを複数回検索させる方法については、`-(' オプションを参照してください。

コマンドラインで同じアーカイブを複数回リストすることができます。

このタイプのアーカイブ検索は、Unix リンカの標準です。ただし、AIX で「ld」を使用している場合は、AIX リンカの動作とは異なることに注意してください。

つまり、次のことを意味します。

他のライブラリに依存する静的ライブラリまたはオブジェクトは、コマンド ラインでその前に配置する必要があります。静的ライブラリが相互に循環的に依存している場合は、たとえば次のことができます。-(コマンド ライン オプションを使用するか、ライブラリをコマンド ラインに 2 回指定します ( -lDA -lDB -lDA)。動的ライブラリの順序は関係ありません。

于 2009-01-29T17:02:23.873 に答える
24

これは、些細な例によって最もよく解決される種類の問題です。本当!2 分で簡単な例をコーディングして、試してみてください。あなたは何かを学ぶでしょう、そしてそれは尋ねるよりも速いです.

たとえば、指定されたファイル:

a1.cc

#include <stdio.h>
void a1() { printf("a1\n"); }

a2.cc

#include <stdio.h>
extern void a1();
void a2() { printf("a2\n");  a1(); }

a3.cc

#include <stdio.h>
extern void a2();
void a3() { printf("a3\n"); a2(); }

aa.cc

extern void a3();
int main()
{
  a3();
}

ランニング:

g++ -Wall -g -c a1.cc
g++ -Wall -g -c a2.cc
g++ -Wall -g -c a3.cc
ar -r liba1.a a1.o
ar -r liba2.a a2.o
ar -r liba3.a a3.o
g++ -Wall -g aa.cc -o aa -la1 -la2 -la3 -L.

ショー:

./liba3.a(a3.o)(.text+0x14): In function `a3()':
/tmp/z/a3.C:4: undefined reference to `a2()'

一方:

g++ -Wall -g -c a1.C
g++ -Wall -g -c a2.C
g++ -Wall -g -c a3.C
ar -r liba1.a a1.o
ar -r liba2.a a2.o
ar -r liba3.a a3.o
g++ -Wall -g aa.C -o aa -la3 -la2 -la1 -L.

成功します。(-la3 -la2 -la1 パラメーターの順序だけが変更されます。)

PS:

nm --demangle liba*.a

liba1.a:
a1.o:
                 U __gxx_personality_v0
                 U printf
0000000000000000 T a1()

liba2.a:
a2.o:
                 U __gxx_personality_v0
                 U printf
                 U a1()
0000000000000000 T a2()

liba3.a:
a3.o:
                 U __gxx_personality_v0
                 U printf
                 U a2()
0000000000000000 T a3()

man nmから:

  • 小文字の場合、シンボルはローカルです。大文字の場合、シンボルはグローバル (外部) です。

  • "T" 記号はテキスト (コード) セクションにあります。

  • "U" 記号は未定義です。

于 2009-01-29T19:36:38.303 に答える
2

残念ながら、相互に依存している内部ライブラリの束を使用したプロジェクトで作業しました(そして、時間の経過とともに悪化しました)。リンク時にすべてのライブラリを2回指定するようにSConsを設定することで、これを「解決」しました。

g++ ... -la1 -la2 -la3 -la1 -la2 -la3 ...
于 2009-01-29T21:51:45.910 に答える
0

リンク順序の問題を回避するために、ライブラリを互いに独立させておくことをお勧めします。

于 2009-01-29T17:01:51.753 に答える
0

ライブラリまたは実行可能ファイルをリンクするための依存関係は、リンク時に存在する必要があるため、libXB が存在する前に libXC をリンクすることはできません。静的か動的かは関係ありません。

依存関係がない (またはプロジェクトの外にある) 最も基本的なものから始めます。

于 2009-01-29T16:42:03.367 に答える