The Linking Process Exposed – Static vs Dynamic Libraries
Creating Static and Dynamic Library
静的ライブラリの場合、バイナリファイル(拡張子.o
)のオブジェクトコードは、拡張子.a
の単一のアーカイブファイルに結合されます。 このアーカイブは、リンク時にそのライブラリを呼び出すプログラムで使用される可能性のあるすべてのツールを含むツールボックスと似ている。 ツールは必要な場所に挿入されます。 下の画像では、一連の .c
ファイルがあります。
ライブラリはオブジェクト コードのアーカイブなので、次のコマンドでこれらすべての .c
ファイルを .o
ファイルに変換する必要があります:
gcc -Wall -Wextra -Werror -pedantic -c *.c
オブジェクト コード ファイル生成後にリンク直前に -c
オプションでコンパイルを停止しています。
コマンドを実行すると、これらのファイルを 1 つの .a
ライブラリ ファイルにアーカイブすることができます。 ar
コマンドはアーカイブ、-r
オプションは拡張子.o
を持つメンバーの移動、-c
オプションはアーカイブが存在しない場合の作成に使用されます。 ライブラリファイルはプレフィックスがlib
で始まり、拡張子が.a
である。 システムによっては、リンクの速度を上げるためにアーカイブの内容に索引を付けることが必要な場合がある。 これは ranlib libholbertonschool.a
で行うことができます。
Using the Static Library
このライブラリをあるテストファイルで使用するには、次の 2 つのコマンドのいずれかを使用して、テストファイルをライブラリでコンパイルしなければなりません:
gcc test.c ./libholbertonschool.a -o exename
gcc test.c -L. -lholbertonschool -o exename
これらはどちらも同じことを行いますが、2 番目は少し不可解なものです。 -L.
オプションはカレントディレクトリにあるライブラリを検索し、 holbertonschool
に接続されている -l
は lib
接頭辞と .a
接尾辞が仮定されているライブラリファイルを暗黙のうちに検索するものである。 ライブラリファイルがない場合、gcc
はリンクしようとしている関数が提供されていないため、エラーを投げる。 コンパイル時にライブラリを提供することにより、コンパイラーは必要な関数をライブラリから検索し、必要な場所に挿入できるようになりました。
ダイナミック・ライブラリ
ダイナミック・ライブラリの作成は静的ライブラリとは若干異なりますが、コンセプトは概ね同じです。 同じ数の.c
ファイルと、そのプロトタイプを定義するヘッダーファイルがlists.h
というファイルにありますね。
.so
(共有オブジェクトの略)を持つ動的ライブラリを作成するには、以下のコンパイルコマンドを入力します。
gcc -fPIC -Wall -Werror -Wextra -pedantic *.c -shared -o libholberton.so
-fPIC
フラグは動的リンクに必要な位置独立コード(Position Independent Code)を意味しています。 この意味は、まさにそのとおりで、ダイナミックリンクされたライブラリは、メモリ上のどこにでも収まるので、このフラグにより、ライブラリファイルがどこに格納されていても使用できるようになります。
-shared
フラグにより共有アーカイブを作成し、-o
オプションにより出力ファイルの名前を libholberton.so
に変更できます。
このコマンドを実行後、共有ライブラリができました!
Using the Dynamic Library
以下のコードを持っているとします:
#include "holberton.h"
#include <stdlib.h>
#include <stdio.h>/**
* main - check the code for Holberton School students.
*
* Return: Always EXIT_SUCCESS.
*/
int main(void)
{
printf("%d\n", _strlen("Holberton"));
return (EXIT_SUCCESS);
}
私は以下のコードでプログラムをコンパイルできます。
gcc -Wall -pedantic -Werror -Wextra -L. 0-main.c -lholberton -o len
スタティックライブラリと同様に、-L.
オプションはライブラリファイルをディレクトリから検索し、holberton
の先頭に付加されている-l
は、プレフィックスlib
、サフィックス.so
、その間にholberton
を持つライブラリファイルを暗黙的に検索するものである。
作成したばかりのライブラリファイルを使用するには、コンパイラがメモリ内のすべてのライブラリファイルを見つけることができ、それらがそもそもメモリに正しくロードされていることを確認する必要があります。 今 ldd len
を実行すると、次のようになります:
行 libholberton.so => not found
から、先ほど作成したダイナミック ライブラリの依存関係が満たされていないことがわかります。 これを解決するには、環境変数$LD_LIBRARY_PATH
を理解する必要があります。 Linux では、この変数はシステムがライブラリ・ファイルを探すために調べるディレクトリをコロンで区切ったリストです。 上の画像では、現在の状態でこの変数をエコーすると空であることがわかります。したがって、共有ライブラリがロードできないため、私がプログラムを実行しようとしても(len
)うまくいかないのです。
私のカレント ディレクトリは次のようになります:
ご覧のように、ライブラリ ファイルは私のメイン ファイルおよびヘッダー ファイルと同じディレクトリにあります(現在のワーキング ディレクトリ)。 次の画像を観察してください:
コマンドは $LD_LIBRARY_PATH
環境変数を .:
で更新し、システムがライブラリーのために現在の作業ディレクトリを検索すべきことを表します。 export
コマンドはこの変更をグローバルにし、どのシェルも同じ値にアクセスできるようにする。 したがって、この変数を echo すると、自分の更新が表示されます。 もう一度 ldd len
を実行すると、libholberton.so
はアドレス位置 0x00007fb9216b9000
にあり、これはメモリ内の現在の作業ディレクトリにある場所と思われます。 このように、実行ファイルの共有ライブラリへの依存は満たされ、プログラムは「Holberton
」という単語の長さである9
を返します。