「ソフテックだより」では、ソフトウェア開発に関する情報や開発現場における社員の取り組みなどを定期的にお知らせしています。
さまざまなテーマを取り上げていますので、他のソフテックだよりも、ぜひご覧下さい。
ソフテックだより(発行日順)のページへ
ソフテックだより 技術レポート(技術分野別)のページへ
ソフテックだより 現場の声(シーン別)のページへ
私はソフテックに入社して、主にC、C++、C#で開発するアプリケーション開発を担当しております。
プログラムを開発する上で、汎用性が高く、複数のプログラムで使用することがある機能はライブラリ化することがよくあります。
以前、私が携わったLinuxのアプリケーション開発の案件でも一部の機能を自身が開発したアプリケーション以外からも使えるように、ライブラリ化し、提供しました。
Linuxでのライブラリ開発はあまり機会がなかったので、今回のソフテックだよりでは「Linuxのライブラリ開発」を紹介します。
Linuxのライブラリには大きく分けて、静的ライブラリと共有ライブラリの2種類があります。静的ライブラリはプログラムのコンパイル時にリンクされるライブラリです。共有ライブラリはプログラム実行と同時にメモリ上に展開されるライブラリです。
また、共有ライブラリには実行時に動的にリンクするか、またはプログラムの制御によって、動的にロードして使用するかの2種類があります。今回の共有ライブラリは実行時に動的にリンクする方法についてのみ記載をいたします。
図1. ライブラリの種類とプログラムの関係
Eclipseを使ったLinuxのライブラリ作成方法を紹介します。
Eclipseのバージョンは3.5.1 Galileoになります。
プロジェクト作成時に、Project typeで作成するLibraryのタイプを選択します。
共有ライブラリを作成する場合は『Shared Library』を選択します。
静的ライブラリを作成する場合は『Static Library』を選択します。
図2. 新規作成プロジェクト画面
プロジェクト画面でライブラリの種類を選択するだけで、設定は完了になります。
作成したライブラリ名は以下のようになります。ライブラリ名はプロジェクト名になります。
ライブラリの種類 | ライブラリ名 | ファイル名 |
---|---|---|
静的ライブラリ | static | libstatic.a |
共有ライブラリ | shared | libshared.so |
表1. ライブラリ名
静的ライブラリの場合、”libxxxx.a”となります。
共有ライブラリの場合、”libxxxx.so”となります。
プレフィックスのlibと拡張子の.aおよび.soは自動で付与されます。
静的ライブラリの場合、作成したプログラムのビルド時にリンクをするため、ライブラリの配置場所はあまり考慮する必要がありませんが、共有ライブラリの場合、プログラム実行時にリンクされるため、特定のディレクトリに配置する必要があります。
作成した共有ライブラリは用途に応じ、以下のいずれかのディレクトリに配置します。
ディレクトリ | 内容 |
---|---|
/lib | システムが使用するライブラリ |
/usr/lib | ユーザープログラムが使用するライブラリ |
/usr/local/lib | システム管理者用のローカルファイル用ライブラリ |
表2. 共有ライブラリ配置場所
Windowsの場合はライブラリの中にバージョン情報が埋め込まれ、プロパティ等で、確認をすることができますが、Linuxの場合はライブラリのバージョン情報はライブラリの中に埋め込まれず、ファイル名でバージョン管理を行います。
バージョン情報は以下のように管理します。
共有ライブラリ名:libxxx.so.X.Y.Z
項目 | 内容 |
---|---|
X | メジャーバージョン ソース互換を失うとき等、大きな変更が発生した時にバージョンアップを行う。 |
Y | マイナーバージョン ソース互換は失わないが、変更が発生した時にバージョンアップを行う。 |
Z | リリースバージョン(オプション) 細かい変更が発生した時、リリースバージョンを管理するのに使用する。 |
表3. バージョン番号の使い分け
Linuxのライブラリの名称として、バージョンが付与されていない.soまでの名称を”linker name”と呼びます。メジャーバージョンまでの名称を”soname”と呼びます。実際のファイル名の名称を”real name”と呼びます。
バージョンを付与した共有ライブラリはそのままだと共有ライブラリを使う側は実際のファイル名の名称である”real name”でリンク指定をする必要があります。
この指定だと、共有ライブラリのバージョンを更新した場合、共有ライブラリを使う側のプログラムをリビルドする必要があります。
共有ライブラリの更新が発生しても、共有ライブラリを使う側がリビルドしなくても使用できるようにするため、シンボリックリンクを作成します。
これにより、共有ライブラリを使う側のプログラムがバージョンを意識せずリンクできるようになります。
シンボリックリンクの作成方法は以下になります。
Linuxのシェルを起動し、以下のコマンドを実行します。
prompt> ldconfig -n update_directory
update_directoryは共有ライブラリの依存関係を更新するディレクトリを指定します。
ldconfigコマンドはオプションの指定をしない場合、/libと/usr/lib、そして/etc/ld.so.conf(および/etc/ld.so.conf.d/*)ファイル内で指定されたディレクトリを更新しますが、-nオプションを使用することで、更新対象のディレクトリを指定できます。
以下のコマンドを実行します。
prompt>ln soname linkername
シンボリックリンク作成の確認は以下のコマンドで行います。
prompt> ls -l file name*
“*”でワイルドカードの指定を行えば一覧で確認をすることができます。
共有ライブラリのファイル名とシンボリックリンクの関係は以下のようになります。
種類 | ファイル名 | シンボリックリンク先 |
---|---|---|
real name | libxxxx.so.X.Y(.Z) | ファイル本体 |
soname | libxxxx.so.X | libxxxx.so.X.Y(real name) |
linker name | libxxxx.so | libxxxx.so.X(soname) |
表4. 共有ライブラリのシンボリックリンクファイル
real nameとsonameはldconfigコマンドを使用し、自動でシンボリックリンクが作成されますが、linker nameはlnコマンドを使用し、手動でシンボリックリンクを作成します。そのため、古いバージョンのライブラリを使用する時は古いバージョンのsonameでシンボリックリンクを作成します。
Eclipseで共有ライブラリのsoname, real nameの指定は以下のようにします。
図3. soname設定画面
Shared object nameにsonameを指定します。
ldconfigコマンドはここで指定したsonameとreal nameのシンボリックリンクを作成します。そのため、ここに命名規則から外れる名称を指定することも可能です。
図4. 拡張子設定画面
rtifact extensionにsoの後ろに任意のバージョンを付与します。
上記の場合ですと、”libshared.so.1.0”というファイル名で出力されます。
作成した共有ライブラリのsonameの確認は以下のコマンドで行います。
prompt> readelf -d file name | grep SONAME
Eclipseの場合は自動的にMake fileが作成されますが、直接Make fileを作成する場合に、使用するコマンドについて紹介します。
arコマンドを使用し、”libxxx.a”というファイルを指定します。
xxxにはライブラリ名称を指定します。
※プレフィックスのlibとエクステンションの.aは指定すると、リンク時に使用する-lオプションがリンクするライブラリ名に自動的に付与し、ライブラリが指定したディレクトリにライブラリが存在するかをチェックします。
g++ -shared -o “libshared.so” ./Shared.o
(例2) sonameを付与する場合
g++ -shared -Wl,-soname=libshared.so.1 -o"libshared.so.1.0" ./Shared.o
g++のオプションで『-shared』を指定します。
sonameを付与する場合は『-W1,-soname=soname』を指定します。
(例2)の場合はlibshared.so.1がsonameになります。
作成したライブラリをリンクする方法について紹介します。
ライブラリをリンクする方法は基本的に静的ライブラリも共有ライブラリも同様の設定になります。
プロジェクト設定画面の[GCC C+ Linkers]- [Libraries]にてライブラリ名称とライブラリがあるパスを指定します。ライブラリ名称にはlibと.a/.soは指定不要になります。また、共有ライブラリの場合、”Library Search Path”の指定は不要です。
図5. ライブラリリンク方法
静的ライブラリの場合、実行ファイルの一部としてライブラリが組み込まれます。
共有ライブラリの場合、実行ファイルにはライブラリとのリンク内容のみが組み込まれます。そのため、共有ライブラリとリンクした実行ファイルが、どのバージョンの共有ライブラリとリンクされているかを確認したい場合、以下のコマンドで確認することができます。
prompt> ldd exec_file
exec_fileは実行ファイル名になります。
Linuxのライブラリ開発は単純に作って使うということだけなら、比較的簡単にできます。ただ、どういう動きでそうなっているかを理解するのに手間がかかりました。sonameやreal name、シンボリックリンクなど、特に知らなくてもおまじないのように行えば作れてしまいます。
自分自身もなんとなく理解しているつもりでしたが、今回この原稿を記載するにあたり、まだ理解が足りていないなという点がありました。
ソフテックだよりはソフテックが持っている技術を紹介するだけでなく、記載する側の理解の整理にもなるというように感じました。
(S.O.)
関連ページへのリンク
関連するソフテックだより