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
ここで何が欠けていますか?
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の一方または両方が発生しますそれが必要になります。