初めに
ライブラリのリンク方法は3種類に分けられます。
「動的ライブラリ」や「動的リンク」といったキーワードでネット検索すると、3種類全てを説明しているサイトがかなり少ない印象を受けます。
そこで「ライブラリのリンク方法」、という切り口で整理してみます。
OSの対象は、WindowsとLinuxとmacOSです。macOSは調べていませんが、恐らくライブラリに関しては、Linuxと同様の見方で大丈夫です。(フォーマットの違い等、細かいことは、本記事では対象外です)
※コンパイルオプション等の説明は原則C/C++をイメージして記述しています。
<-- 2020/09/10 追記 start -->
読んでいただきありがとうございます。
macOSの内容を追記しました。
ライブラリ作成時に必要なオプションと、ライブラリ使用時に必要なオプションをごちゃごちゃにしていた為整理しました。
「動的ライブラリに対する補足」と「最後に」を追加しました。
<-- 2020/09/10 追記 end -->
3種類のリンク方法
No | リンク方法 | 対象ライブラリ | Windowsにおける拡張子 | Linuxにおける拡張子 | macOSにおける拡張子 | リンクタイミング |
---|---|---|---|---|---|---|
1 | 静的リンク | 静的ライブラリ(スタティックライブラリ) | lib(a) | a | a | ビルド時 |
2 | 動的リンク | 動的ライブラリ(ダイナミックライブラリ、共有ライブラリ) | dll | so | dylib(so) | 実行ファイルを実行する時 |
3 | 動的ロード | 動的ライブラリ(ダイナミックライブラリ、共有ライブラリ、バンドル) | dll | so | bundle(so) | プログラムが任意にライブラリをロードした時 |
拡張子「dll」はDynamic Link Libraryの略、拡張子「so」はShared Objectです。
あれ、共有ライブラリ=Shared Libraryならslでは?というつっこみはなしの方向で。。。
静的ライブラリと動的ライブラリを区別できる人は多いと思いますが、2と3を区別できる人は少ないのではないでしょうか。
1と2、または、1と3の組み合わせのみを解説しているサイトがやたらと多いです。。。
動的リンク
2の「動的リンク」は、Makefileに「-l」でライブラリ名を指定してビルドすると、実行ファイルを実行する時に、OSが指定したライブラリを決められた検索順番でディレクトリを検索し、ライブラリが見つかるとリンクします。
全ての検索パスを検索して見つからない時は、実行エラーになります。
動的ロード
3の「動的ロード」は、Windows(MinGW、MSVC)ならLoadLibrary()関数、Linux系(Cygwin、Ubuntu、macOS)ならdlopen()関数でライブラリをロードした時に、初めてライブラリの内容がメモリにロードされます。Makefileに「-l」で指定する必要はありません。
動的ロードする為のデフォルトのルールには、クラスのインスタンスを作成して読み出す、というAPIはありません。
従って、クラスのインスタンスを作成して読み出す為には、extern C{}で括った領域に、クラスをnewしてインスタンスを返すような関数をプログラマが独自に定義する必要があります。
この「独自に定義」する部分のルールを、よりしっかり作ったものが「プラグイン」と呼ばれるものです。
WebブラウザやIDEのプラグインのように、後から機能を追加できる仕組みです。
プラグインは動的ロードの1種といってよいと思います。
動的ライブラリに対する補足
動的リンクと動的ロード、どちらも動的ライブラリを作成しリンクするビルド方法は同じです。ソースコード的には、C言語レベルであれば同じコードが使用できます。C++の場合は上記に記述した通り、LoadLibrary()関数/dlopen()関数等の使用有無の違いがあります。
ライブラリ作成時に必要なコンパイルオプションはWindowsとLinuxは-shared、macOSは-dynamiclibです。(macOSはLinuxのライブラリも許容する関係か-sharedも使用できる)-fPICは必須ではありませんが、基本的に付けたほうがよいオプションです。(macOSでは明示的に記述しなくてもデフォルトで-fPICが付いています)
尚、macOSでは動的リンクの動的ライブラリを共有ライブラリ、動的ロードの動的ライブラリをバンドルと呼び分けています。
最後に
ライブラリの情報は各プラットフォーム毎に個別で扱われることが多く、各プラットフォームを横断的に見ることができるサイトはなかなか見つかりません。そこで、GCCコンパイラ限定ではありますが、Cygwin(Windows)、MinGW(Windows)、Ubuntu、macOSでそれぞれどのようにライブラリを作ったり、使ったりするのかを技術同人誌としてまとめてみました。BOOTHで頒布していますので、よかったら参考にしてみてください。
おまけ情報
「ライブラリを作ろう」本に入れられなかったライブラリとライブラリをリンクする話を
実行ファイル→動的ライブラリA→動的ライブラリBのリンク構成で、実行ファイルは動的ライブラリBに依存しないか
にまとめました。よかったら参考にしてください。