| C++ ユーザーズガイド |
第 6 章
ライブラリの構築
ライブラリとは
ライブラリには 2 つの利点があります。まず、ライブラリを使えば、コードをいくつかのアプリケーションで共有できます。共有したいコードがある場合は、そのコードを含むライブラリを作成し、コードを必要とするアプリケーションとリンクできます。次に、ライブラリを使えば、非常に大きなアプリケーションの複雑さを軽減できます。アプリケーションの中の、比較的独立した部分をライブラリとして構築および保守することで、プログラマは他の部分の作業により専念できるようになるためです。
ライブラリの構築とは、
.oファイルを作成し (コードを-cオプションでコンパイルし)、これらの.oファイルをCCコマンドでライブラリに結合することです。ライブラリには、静的 (アーカイブ) ライブラリと動的 (共有) ライブラリがあります。静的 (アーカイブ) ライブラリの場合は、ライブラリのオブジェクトがリンク時にプログラムの実行可能ファイルにリンクされます。アプリケーションにとって必要な
.oファイルだけがライブラリから実行可能ファイルにリンクされます。静的 (アーカイブ) ライブラリの名前には、通常、接尾辞.aが付きます。動的 (共有) ライブラリの場合は、ライブラリのオブジェクトはプログラムの実行可能ファイルにリンクされません。その代わりに、プログラムがこのライブラリに依存することをリンカーが実行可能ファイルに記録します。プログラムが実行されるとき、システムは、プログラムに必要な動的ライブラリを読み込みます。同じ動的ライブラリを使用する 2 つのプログラムが同時に実行されると、ライブラリはこれらのプログラムによって共有されます。動的 (共有) ライブラリの名前には、接尾辞として
.soが付きます。共有ライブラリを動的にリンクすることは、アーカイブライブラリを静的にリンクすることに比べていくつかの利点があります。
- 実行可能ファイルのサイズが小さくなる
- 実行時にコードのかなりの部分をプログラム間で共有できるため、メモリーの使用量が少なくなる
- ライブラリを実行時に置き換える場合でも、アプリケーションとリンクし直す必要がない (プログラムの再リンクや再配布をしなくても、Solaris 環境でプログラムが新しい機能を使用できるのは、主にこの仕組みのためです)
dlopen()関数呼び出しを使えば、共有ライブラリを実行時に読み込むことが
できる
- 実行時のリンクに時間がかかる
- 動的ライブラリを使用するプログラムを配布する場合には、それらのライブラリも同時に配布しなければならないことがある
- 共有ライブラリを別の場所に移動すると、システムがライブラリを検索できずに、プログラムを実行できなくなることがある (環境変数
LD_LIBRARY_PATHを使えば、この問題は解決できます)静的 (アーカイブ) ライブラリの構築
静的 (アーカイブ) ライブラリを構築する仕組みは、実行可能ファイルを構築することに似ています。一連のオブジェクト (
.o) ファイルは、CCで-xarオプションを使うことで 1 つのライブラリに結合できます。静的 (アーカイブ) ライブラリを構築する場合は、
arコマンドを直接使用せずにCC-xarを使用してください。C++ 言語では一般に、従来の.oファイルに収容できる情報より多くの情報 (特に、テンプレートインスタンス) をコンパイラが持たなければなりません。-xarオプションを使用すると、テンプレートインスタンスを含め、すべての必要な情報がライブラリに組み込まれます。makeではどのテンプレートファイルが実際に作成され、参照されているのかがわからないため、通常のプログラミング環境でこのようにすることは困難です。CC -xarを指定しないと、参照に必要なテンプレートインスタンスがライブラリに組み込まれないことがあります。構築の例を次に示します。
%CC -c foo.cc#mainを含むファイルをコンパイルし、テンプレート オブジェクトを作成する%CC -xar -o foo.a foo.o# すべてのオブジェクトを1つのライブラリに集める
-xarフラグによって、CCが静的 (アーカイブ) ライブラリを作成します。-o命令は、新しく作成するライブラリの名前を指定するために必要です。コンパイラは、コマンド行のオブジェクトファイルを調べ、これらのオブジェクトファイルと、テンプレートレポジトリで認識されているオブジェクトファイルとを相互参照します。そして、ユーザーのオブジェクトファイルに必要なテンプレートを (本体のオブジェクトファイルとともに) アーカイブに追加します。
注 --xarフラグは既存のアーカイブの作成や更新のためのもので、保守には使用できません。-xarオプションはar -crを実行するのと同じことです。
1 つの
.oファイルには 1 つの関数を入れることをお勧めします。アーカイブとリンクする場合、特定の.oファイルのシンボルが必要になると、.oファイル全体がアーカイブからアプリケーションにリンクされます。.oファイルに 1 つの関数を入れておけば、アプリケーションにとって必要なシンボルだけがアーカイブからリンクされます。動的 (共有) ライブラリの構築
動的 (共有) ライブラリの構築方法は、コマンド行に
-xarの代わりに-Gを指定することを除けば、静的 (アーカイブ) ライブラリの場合と同じです。
ldは直接使用しないでください。静的ライブラリの場合と同じように、CCコマンドを使用すると、必要なすべてのテンプレートインスタンスがテンプレートレポジトリからライブラリに組み込まれます (テンプレートを使用している場合)。さらに、CCコンパイラは、大域変数がライブラリに定義されている場合、動的ライブラリが正しく構築されていないと大域変数を初期化しません。アプリケーションにリンクされている動的ライブラリでは、すべての静的コンストラクタはmain()が実行される前に呼び出され、すべての静的デストラクタはmain()が終了した後に呼び出されます。dlopen()で共有ライブラリを開いた場合、すべての静的コンストラクタはdlopen()で実行され、すべての静的デストラクタはdlclose()で実行されます。CC-Gコマンドを使用して動的ライブラリを構築しないと、例外が機能しないことがあります。動的 (共有) ライブラリを構築するには、
CCの-Kpicや-KPICオプションで各オブジェクトをコンパイルして、再配置可能なオブジェクトファイルを作成する必要があります。次に、これらの再配置可能オブジェクトファイルから動的ライブラリを構築します。原因不明のリンクエラーがいくつも出る場合は、-Kpicや-KPICでコンパイルしていないオブジェクトがある可能性があります。ソースファイル
lsrc1.ccとlsrc2.ccから作成するオブジェクトファイルから C++ 動的ライブラリlibgoo.so.1を構築するには、次のようにします。
%CC -G -o libfoo.so -h libfoo.so -Kpic lsrc1.cc lsrc2.cc
-Gオプションは動的ライブラリの構築を指定し、-oオプションはライブラリのファイル名を指定します。-hオプションは、共有ライブラリの名前を指定しています。-Kpicオプションは、オブジェクトファイルが位置に依存しないことを指定しています。
注 -CC -Gコマンドは-lオプションをldに渡しません。共有ライブラリに他の共有ライブラリとの依存関係を持たせたい場合、必要な-lオプションをコマンド行に指定する必要があります。たとえば、共有ライブラリにlibCrun.soとの依存関係を持たせたい場合、-lCrunをコマンド行に指定する必要があります。
例外を含む共有ライブラリの構築
dlopen()で共有ライブラリを開く場合、例外が機能するようにするには、RTLD_GLOBALを使用する必要があります。
注 - 例外を含む共有ライブラリを構築するとき、ldに-Bsymbolicオプションを渡さないでください。必要な例外が捕獲されなくなる可能性があります。
非公開ライブラリの構築
ある組織の内部でしか使用しないライブラリを構築する場合には、一般的な使用には適さないオプションを使ってライブラリを構築することもできます。具体的には、ライブラリはシステムのアプリケーションバイナリインタフェース (ABI) に準拠していなくてもかまいません。たとえば、ライブラリを
-fastオプションでコンパイルして、特定のアーキテクチャ上でのパフォーマンスを向上させることができます。同じように、-xregs=floatオプションでコンパイルして、パフォーマンスを向上させることもできます。公開ライブラリの構築
他の組織からも使用できるライブラリを構築する場合は、ライブラリの管理やプラットフォームの汎用性などの問題が重要になります。ライブラリを公開にするかどうかを決める簡単な基準は、アプリケーションのプログラマがライブラリを簡単に再コンパイルできるかどうかということです。公開ライブラリは、システムの ABI に準拠して構築しなければなりません。一般に、これはプロセッサ固有のオプションを使用しないということを意味します (たとえば、
-fastや-xtargetは使用しないなど)。SPARC ABI では、いくつかのレジスタがアプリケーション専用で使用されます。V7 と V8 では、これらのレジスタは
%g2、%g3、%g4です。V9 では、これらのレジスタは%g2と%g3です。ほとんどのコンパイルはアプリケーション用に行われるので、C++ コンパイラは、デフォルトでこれらのレジスタを一時レジスタに使用して、プログラムのパフォーマンスを向上しようとします。しかし、公開ライブラリでこれらのレジスタを使用することは、SPARC ABI に適合しないことになります。公開ライブラリを構築するときには、アプリケーションレジスタを使用しないようにするために、すべてのオブジェクトを-xregs=no%applオプションでコンパイルしてください。C API を持つライブラリの構築
C++ で作成されたライブラリを C プログラムから使用できるようにするには、C API を作成する必要があります。そのためには、エクスポートされるすべての関数を
extern"C"にします。ただし、これができるのは大域関数だけで、メンバー関数にはできません。さらに、C++ 実行時ライブラリにもまったく依存しないようにするには、ライブラリソースに対して次のコーディング規則を適用する必要があります。
- どのような形式の
newまたはdeleteも使用しない (独自のnewまたはdeleteを定義する場合は除く)- 例外を使用しない
- 実行時型特定機構 (RunTime Type Information、RTTI) を使用しない
dlopenを使って C プログラムから C++ ライブラリにアクセスするC プログラムから
dlopenで C++ 共有ライブラリを開く場合は、共有ライブラリが適切な C++ 実行時ライブラリ (-compat=4の場合はlibC.so.5、-compat=5の場合はlibCrun.so.1) に依存していなければなりません。そのためには、共有ライブラリを構築するときに、
-compat=4の場合は-lc、-compat=5の場合は-lCrunを次のようにコマンド行に追加します。
example%CC -G -compat=4 ... -lCexample%CC -G -compat=5 ... -lCrun共有ライブラリが例外を使用している場合には、ライブラリが C++ 共有ライブラリに依存していないと、C プログラムが正しく動作しないことがあります。
注 - 共有ライブラリをdlopen()で開く場合は、RTLD_GLOBALを使用しないと、例外は機能しません。
マルチスレッド化されたプログラムの構築
|
サン・マイクロシステムズ株式会社 Copyright information. All rights reserved. |
ホーム | 目次 | 前ページへ | 次ページへ | 索引 |