静的ライブラリは単なる.oファイルのバンドルです。それらは意味のある方法で「リンク」されていません。連結しただけです。シンボルが解決されるのは、実際のリンク手順を実行するまではありません。
.a基本的に、を実行可能ファイルにリンクすることと、同等のソースコードを実行可能ファイルのプロジェクトにコピーすることの間に違いはありません。したがって、それまでは、追加のフレームワークやライブラリとリンクする必要はありません。
次の演習は教育的かもしれません:
以下を作成しますcomptest.c。
#include <stdio.h>
int main() {
printf("Hello world.\n");
return 0;
}
プリプロセッサの機能を確認してください。
gcc -E comptest.c > comptest-cpp.c
これにより、が削除#includeされ、参照ファイルの内容に置き換えられます。このファイルは、コンパイラーが実際に見るものです。
ここで、コンパイラーの機能を確認します(>ここと以下の構文を使用しているので、物事はと並行しています-E)。
gcc -S comptest.c > comptest.s
これは、前処理とコンパイル後に生成されたアセンブリ言語です。これを.oに変換します。
gcc -c comptest.c > comptest.o
それでは、その.oに何が含まれているのか見てみましょう。
$ nm comptest.o
0000000000000040 s EH_frame0
000000000000002d s L_.str
0000000000000000 T _main
0000000000000058 S _main.eh
U _puts
ここで重要なのは_mainと_putsです。_mainこのファイルのアドレス0で定義されています_puts。は未定義です。したがって、リンクするものはそれを提供する方がよいでしょう。何もせずにリンクしてみましょう:
$ gcc -nodefaultlibs comptest.o
Undefined symbols for architecture x86_64:
"_exit", referenced from:
start in crt1.10.6.o
"_puts", referenced from:
_main in comptest.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
(_exitCランタイムから暗黙的です。.oで直接参照されません)
これで、すべてをまとめる準備が整いました。明示します:
gcc -nodefaultlibs comptest.o /usr/lib/libc.dylib -o comptest
comptest.oこれは、動的ライブラリと一緒にリンクすることを意味しますlibc。参照されるすべてのシンボルがこれらのファイルの1つによって提供されることを約束します。結果のバイナリに、シンボルを動的にロードする必要があることをメモします/usr/lib/libc.dylib(これは、適切なライブラリではなく、それ自体が「アンブレラフレームワーク」であるlibSystem.B.dylibへのシンボリックリンクですが、必要なものを少し超えていますほとんどの場合を知るために;あなたはそれputs()がlibSystemにあるふりをすることができます):
$ otool -L comptest
comptest:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
静的ライブラリとリンクする場合、コマンドラインに含まれるすべての.oファイルを一覧表示するのと同じです。
リンクステップには、.oファイルと.dylibファイルがあることに注意してください(.aは.oの単なるパッケージです)。.cファイル、.hファイル、.sファイル、ソースコードはありません。シンボルを解決する必要があるオブジェクトファイルのみ。これが、ヘッダーファイルがここでは重要ではない理由ですが、コンパイル時に重要です。