2012-02-23 17 views
16

私はlibrtを使用する小さなCプログラムを書いています。GCCを使用してライブラリリンカーフラグが最後に移動する必要があるのはなぜですか?

gcc -o prog prog.c -lrt -std=gnu99

:私はプログラムをコンパイルするために、現時点で

:私は開始時に代わりの最後にリンクフラグを配置すると、プログラムがコンパイルされませんことを、非常に驚​​いています私は以下を実行した場合

、それはlibrt内の関数を見つけるために失敗します。

gcc -std=gnu99 -lrt -o prog prog.c

しかし、これは他のライブラリで動作します。シンプルなMakefileを使用しようとしたときに問題が見つかりました。最初に好きなように実際にコンパイルしたprog.cを作成し(-cフラグを使用して)、リンクを行いました。

これはMakefileのです:入力を行うとき、私はなるだろう

CC = gcc 

CFLAGS = -std=gnu99 

LIBS= -lrt 

LDFLAGS := -lrt 


prog: prog.o 

     $(CC) -o prog prog.c -lrt -std=gnu99 

出力は次のようになります。

gcc -std=gnu99 -c -o prog.o prog.c 
gcc -lrt prog.o -o prog 
prog.o: In function `main': 
prog.c:(.text+0xe6): undefined reference to `clock_gettime' 
prog.c:(.text+0x2fc): undefined reference to `clock_gettime' 
collect2: ld returned 1 exit status 
make: *** [buff] Error 1 

私は今、GCCの末尾にリンクを置くMakefileを作り上げてきましたしかし、リンクフラグが最初にあれば、なぜ動作しないのか困惑しています。

誰かが私にこのことを説明できるかどうかは分かります。ありがとう。

+1

これは100%ではありませんが、リンカーがlibrtを見ていて、それに何も必要ないと判断するかもしれないと思います。 librtは静的ライブラリですか? – spencercw

+0

静的リンクが順序依存である理由の説明については、この質問への回答を参照してください。http://stackoverflow.com/questions/45135/linker-order-gcc –

+2

リンカーの* as-needed *オプションが使用されている可能性がありますデフォルトでは'gcc -std = gnu99 -Wl、-no-as-needed -lrt -o prog prog.c'を試すことができます。 –

答えて

19

リンカは各モジュール(ライブラリまたはオブジェクトファイル)を処理するので、定義されていない各シンボルを解決しようとしますが、未定義シンボルのリストに追加する可能性があります。モジュールのリストに到達すると、未定義のシンボルをすべて解決して成功するか、未定義のシンボルを報告します。

あなたのケースでは、librtを処理するときに未定義のシンボルがありませんでした。 procを処理すると、clock_gettimeが未定義シンボルになりました。 gccは戻って、定義されていないシンボルについてlibrtを調べません。

このような理由から、まずコードを作成してからライブラリを作成し、続いてプラットフォーム提供のライブラリを作成する必要があります。

これが役に立ちます。 ld(GNUリンカ)ドキュメント(http://sourceware.org/binutils/docs/ld/Options.html#Options)から

+1

マイナーノート:オブジェクトファイルは重要ではありません。別のオブジェクトファイル内のシンボルを参照するオブジェクトファイルは、必ずしもコマンドライン上にある必要はありません。もちろん、まだ定義されていない参照があっても、オブジェクトファイルのすべてのシンボルが最終的なイメージに含まれているとみなし、定義されたシンボルのリストに追加されることを考慮すれば意味があります。別のオブジェクトファイルでは、未定義のシンボルにつながることはありません。 – eriktous

+0

@eriktous訂正していただきありがとうございます。 – Lou

11

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

ライブラリをあまりにも早く指定すると、リンカはそれをスキャンしますが、興味のあるものは見つけられません。その後、リンカーはコンパイラによって生成されたオブジェクトファイルに移動し、解決する必要のある参照を見つけますが、すでにライブラリをスキャンしていますので、再度参照する必要はありません。

関連する問題