web-dev-qa-db-ja.com

共有オブジェクトを作成しようとすると、gccの「未定義の参照」エラーが発生するのはなぜですか?

Gccを使用して「未定義の参照」エラーが発生するのはなぜですか?

1つの関数「external()」をエクスポートする共有オブジェクト(.so)を作成しようとしています。次に、.soに対してリンクしようとしますが、「undefined reference'external '」を取得します。私はここで何が間違っているのですか?

ファイル:external.c

int external() {
    return 5;
}

ファイル:program.c

int external();
int main(char** argv, int* argc) {
    return external();
}

コマンド:

$ gcc -fPIC -c external.c
$ gcc -shared -o libexternal.so external.o
$ gcc -L. -lexternal -o program program.c
/tmp/cc3MmhAE.o: In function `main':
program.c:(.text+0x7): undefined reference to `external'
collect2: ld returned 1 exit status

Nmを実行して、.soが「外部」を定義していることを確認することもできます。

コマンド:

$ nm libexternal.so | grep external
0000040c T external

ここで何が欠けていますか?

20
Warren

Gcc/ldの最近のバージョンは、デフォルトで_--as-needed_とリンクしています。

これは、Cファイルの前に_-lexternal_を書き込むと、ライブラリが自動的に除外されることを意味します(このように「必要」かどうかをテストする場合は順序が重要です)

これは、次のいずれかで修正できます。

  • _gcc -L. -o program program.c -lexternal_
  • _gcc -L. -Wl,--no-as-needed -lexternal -o program program.c_

後者は_--no-as-needed_をリンカーに渡します。これにより、ライブラリからexternal()を呼び出さなくても、ライブラリはリンクされたままになります。

注:_-Wl,--no-as-needed_は、リンクされているすべてのものにグローバルに適用されるわけではなく、コマンドラインの順序でそれに続くものにのみ適用されます。したがって、_-lexternal -Wl,--no-as-needed_も機能しません。これは、動作を組み合わせて一致させることができることを意味します。たとえば、_gcc -L. -Wl,--no-as-needed -lexternal -Wl,--as-needed -o program program.c -lmightneed_は常に外部に対してリンクしますが、必要なものに対してのみリンクしますif program.c /libexternal.soの一方または両方が発生しますそれが必要になります。

37
Flexo