静的ライブラリは単なる.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
(_exit
Cランタイムから暗黙的です。.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ファイル、ソースコードはありません。シンボルを解決する必要があるオブジェクトファイルのみ。これが、ヘッダーファイルがここでは重要ではない理由ですが、コンパイル時に重要です。