9

ライブラリで使用したい関数に「未定義の参照」があることを示すコンパイラに問題があります。問題に関する情報を共有させてください。

  • Cのgccでクロスコンパイルしています。
  • プロトタイプを含む別のヘッダーを含むインクルードヘッダーを介してアクセスされるライブラリ関数を呼び出しています。
  • -I を使用してヘッダー ディレクトリを含めましたが、確実に見つかっています。
  • 最初に .o ファイルを作成してから、別のコマンドでそれらをリンクしています。

だから私の考えでは、ライブラリファイルをインクルードする順序かもしれませんが、それらを順序付ける正しい方法はわかりません. .o ファイルの前後に headers フォルダーを含めてみました。

リンカーがどのように機能するかについての説明が素晴らしいと示唆する人もいます。

ありがとう!


回答への対応

  • .a ライブラリ ファイルはなく、ライブラリには .h と .c だけがあるため、-l は適切ではありません
  • ライブラリ ファイルについての私の理解では、それは単なるヘッダー ファイルとソース ファイルのコレクションですが、ソースから作成された .o ファイルのコレクションではないでしょうか?!
  • ライブラリ オブジェクト ファイルが作成されていません。はい、インクルードとライブラリの違いを理解していないようです...私はそれに取り組みます:-)

すべての応答に感謝します! 私は図書館について多くのことを学びました。すべての回答を受け入れられた回答として掲載したいと思います:-)

4

6 に答える 6

6

ヘッダーは、関数宣言と関数定義を提供します。リンカが関数の実装を見つけられるようにする (そして未定義の参照を取り除く) には、コンパイラ ドライバ (gcc) に -l フラグを使用して関数が存在する特定のライブラリをリンクするように依頼する必要があります。たとえば、-lm は数学ライブラリをリンクします。通常、関数のマニュアル ページでは、その関数を見つけるために指定する必要があるライブラリがあれば指定します。

リンカーが指定したライブラリを見つけられない場合は、-L スイッチを使用してライブラリ検索パスを追加できます (たとえば、-L/usr/local/lib)。LIBRARY_PATH 環境変数を使用して、ライブラリ パスに永続的に影響を与えることもできます。

問題のデバッグに役立つ追加の詳細を次に示します。慣例により、ライブラリ ファイルの名前には lib というプレフィックスが付けられ、(静的な形式では) .a 拡張子が付きます。したがって、システムのデフォルトの数学ライブラリ (-lm でリンクしたもの) の静的にリンクされたバージョンは、通常、/usr/lib/libm.a にあります。特定のライブラリが定義するシンボルを確認するには、ライブラリ ファイルに対して nm --defined-only を実行します。私のシステムでは、libm.a でコマンドを実行すると、次のような出力が得られます。

e_atan2.o:
00000000 T atan2

e_asinf.o:
00000000 T asinf

e_asin.o:
00000000 T asin

コンパイラが使用するライブラリ パスとデフォルトで読み込まれるライブラリを確認するには、-v オプションを使用して gcc を呼び出します。再び私のシステムでは、これにより次の出力が得られます。

GNU assembler version 2.15 [FreeBSD] 2004-05-23 (i386-obrien-freebsd) 
using BFD version 2.15 [FreeBSD] 2004-05-23
/usr/bin/ld -V -dynamic-linker /libexec/ld-elf.so.1 /usr/lib/crt1.o 
/usr/lib/crti.o /usr/lib/crtbegin.o -L/usr/lib /var/tmp//ccIxJczl.o -lgcc -lc 
-lgcc /usr/lib/crtend.o /usr/lib/crtn.o
于 2008-09-27T12:23:51.040 に答える
5

ライブラリ内の .c ファイルをコンパイルして .o ファイルを生成していないようです。リンカーは、ライブラリのコンパイルによって生成された .o ファイルでプロトタイプの実装を探します。

ビルド プロセスはライブラリ .c ファイルをコンパイルしますか?

実際には単なるソースコードなのに、なぜ「ライブラリ」と呼ぶのですか?

于 2008-09-27T12:38:57.777 に答える
2

ライブラリとヘッダーの概念を混同しているのではないかと心配しています。libmylib.a関数と、そのプロトタイプを定義myfunc()する対応するヘッダーを含むライブラリがあるとします。mylib.hソース ファイルmyapp.cにヘッダーを直接、またはそれを含む別のヘッダーを含めます。例えば:

/* myapp.h
** Here I will include and define my stuff
*/
...
#include "mylib.h"
...

ソースファイルは次のようになります。

/* myapp.c
** Here is my real code
*/
...
#include "myapp.h"
...
/* Here I can use the function */
myfunc(3,"XYZ");

これで、コンパイルして以下を取得できますmyapp.o

gcc -c -I../mylib/includes myapp.c

-I はヘッダー ファイルの場所を gcc に伝えるだけで、ライブラリ自体とは何の関係もないことに注意してください。

これで、アプリケーションを実際のライブラリにリンクできます。

gcc -o myapp -L../mylib/libs myapp.o -lmylib

-Lスイッチは gcc にライブラリの場所を-l伝え、 はコードをライブラリにリンクするように指示することに注意してください。

この最後の手順を実行しないと、説明した問題が発生する可能性があります。

他にももっと複雑なケースがあるかもしれませんが、あなたの質問から、これがあなたの問題を解決するのに十分であることを願っています.

于 2008-09-27T12:33:28.757 に答える
1

メイクファイルと、呼び出そうとしているライブラリ関数を投稿してください。単純な gcc メイクファイルでさえ、通常、次のような行があります。

LIBFLAGS =-lc -lpthread -lrt -lstdc++ -lShared -L../shared

この場合、標準 C ライブラリなどをリンクすることを意味します。

于 2008-09-27T13:21:04.663 に答える
0

リンカーがライブラリーを見つけることができるパスを追加する必要があると思います。gcc/ld では -L で、libraray では -l でこれを行うことができます。

-Ldir, --library-path=dir

標準検索ディレクトリの前にディレクトリ dir を検索します (このオプションは、そのディレクトリを検索する -l オプションよりも前に行う必要があります)。

-larch, --library=アーカイブ

リンクするファイルのリストにアーカイブ ファイル arch を含めます。


回答への応答 - .a ライブラリ ファイルはなく、ライブラリには .h と .c だけがあるため、-l は適切ではありません

次に、最初にライブラリーを作成する必要があるかもしれませんか?

gcc -c mylib.c -o mylib.o
ar  rcs libmylib.a      mylib.o
于 2008-09-27T12:22:50.560 に答える