静的ライブラリの作成と利用


自称ライブラリアン(ホントか?)としては、ライブラリ開発が行えないと意味がないのです.

そんなわけで、そろそろコードも貯まってきたし、xcode でのライブラリ開発とその利用方法について調べてみました.

デバッグ用のマクロ設定

まずは、マクロ(プロジェクト定義define)の設定方法をまとめておく.

メニューバーから、[プロジェクト] - [プロジェクト設定を編集] とたどり、プロジェクト情報を表示する.

[ビルド] タブを選択し、"GCC 4.0 - Preprocessing" の項目にある、

  • Preprocessor Macros
  • Preprocessor Macros Not Used In Precompiled Headers

のいずれかに定数を記入する.


例)

構成 : Debug
Preprocessor Macros Not Used In Precompiled Headers : _DEBUG_

こうすると、 Debug 構成でビルドしたときには、define _DEBUG_ が設定される.

すなわち

void func()
{
#ifdef _DEBUG_
    print( "Debug.\n" );
#else
    print( "Release.\n" );
#endif
}

といった、デバッグ時だけ有効なコードを書くことができる.

デバッグ用のマクロ(補)

プロジェクトを作成した直後だと、"Preprocessor Macros" の項目はおろか、GCC関連のオプションはすべて存在しない.

これは、最初のビルド時に xcode が必要オプションを書き込んでいるためと思われる.

ビルド後には項目が追加されているはずだが、ウインドウ下の歯車マークを押下し、"ユーザ定義設定の追加"から先に項目の追加を行っておいても良い.

その際、項目名には "GCC_PREPROCESSOR_DEFINITIONS" を指定する.

ライブラリの作成

まずは、簡単なサンプルライブラリの開発から初める.

xcode を立ち上げ、[ファイル] - [新規プロジェクト] から、新規プロジェクト作成ダイアログを呼び出し、

[Max OS X] - [Static Library] - [BSD Static Library] を選択する.

適当な場所に、プロジェクトを作成する.

デフォルト設定のままだと、

$(プロジェクトディレクトリ)/Debug/lib$(プロジェクト名).a

にライブラリが出力されるが、扱いにくい気がするので出力場所を、

$(プロジェクトディレクトリ)/lib/Debug/lib$(プロジェクト名).a
$(プロジェクトディレクトリ)/lib/Release/lib$(プロジェクト名).a

になるように変更しておく.

出力先は、プロジェクト設定にある、[ビルド場所] - [構成ごとのビルドプロダクトのパス] に設定する.

次のように設定しておくと、Deubg/Release 毎に設定を分ける必要はなく、[すべての構成]で設定することができる.

lib/$(CONFIGURATION)

ライブラリの名称

xcode では、 "lib*.a" という名前のライブラリしかリンクできない.
(* には、適切なライブラリ名が入る)

Debug / Release といった構成毎に、 libmylibD.lib / libmylib.lib のようなライブラリを作成したい
のだが、設定方法がよく分からなかった.

(教えて偉い人)

ライブラリを利用するプロジェクトの作成

ライブラリ単体がビルドできただけではテストにすら困るので、利用する側のプロジェクトを作成する.

プロジェクトは、用途に応じて選べばよい.

ライブラリ利用する際に、ヘッダファイルを参照する必要がある.


ヘッダの検索パスを指定するためには、プロジェクト設定の "検索パス"の項目にある "ヘッダ検索パス" に、ライブラリのヘッダが置かれているパスを設定すればよい.

パスは、 *.xcodeproj ファイルの置かれている場所からの相対で指定するのが良いと思う

プロジェクトにファイルを追加することによるライブラリの指定

ライブラリ作成時にできあがった、lib*.a ファイルを、プロジェクトのウインドウにドラッグアンドドロップする.
(もしくは、ファイルの追加を行う)

すると、ターゲットの[バイナリをライブラリにリンク]の部分に、投げ込んだライブラリが追加されていることがわかる.

Release のデフォルト設定では、 [アクティブアーキテクチャのみをビルド] のフラグがオフになっているので、リンカでエラーが返される.

オンの状態だと、ユニバーサルバイナリが作成される(と思われる)ため、単純な構成のライブラリをリンクすることができないと推察する.
(よくしらない)

本来は、 debug / release で、利用するライブラリを変更したいと思うのだが、この手順での設定の方法はよく分からなかった.
(設定できないのか?教えて偉い人)

リンカオプションによるライブラリの指定

debug / release で利用するライブラリを変更するために、プロジェクト設定からリンクするライブラリを指定する方法を示す.
この場合、プロジェクトにライブラリファイルを追加する必要がないので、構成毎に利用するライブラリを指定できる.

  • プロジェクト設定の、 "検索パス"欄にある、"ライブラリ検索パス" に、ライブラリが置かれたパスを指定する.
  • "リンク" 欄の "他のリンクフラグ" に -l$(ライブラリ名) を指定する.

例)

ライブラリ検索パス : ../mylib/lib/release
他のリンクフラグ : -lmylib

他のリンクフラグに指定するフラグ "-l" は、リンクするライブラリを指定するオプション.

ライブラリは、 lib*.a という名前、(ライブラリ名が mylib だとすると、libmylib.a) になっているが、-l に続ける
のはライブラリ名(すなわち mylib) の点に注意.


ライブラリのプロジェクトを追加して依存関係を設定する

リンクフラグを設定すると、構成毎に利用するライブラリが区別できて便利だが、ライブラリ開発を行っている場合にはライブラリ自身のコードが変更されるので、プロジェクトを行ったり来たりする必要があって煩わしい.

そこで、ライブラリの xcode プロジェクト自身を、ライブラリを利用するプロジェクトに追加して、依存関係を設定することができる.

これが、今回の本命.

ライブラリを利用するプロジェクトに、ファイルの追加なり、ドラッグアンドドロップなどで、ライブラリのプロジェクトを追加する.

"グループとファイル" ウインドウに、追加された xcodeproj を開くと、ライブラリ(lib*.a)が表示されるので、それをターゲットの"バイナリをライブラリにリンク" 欄にドロップする.

ターゲットを右クリックして、[情報を見る] を選択.

[一般]タグに、[直接依存関係]の欄があるので、[+]を押して依存関係を付けるプロジェクトを追加する.

この設定を行っておくと、必要に応じて、依存関係先のビルドを行ってくれるし、Deubg / Relase の構成を切り替えても対応するライブラリのリンクを行ってくれるようになる.

また、ライブラリの xcodeproj をダブルクリックすると、そのプロジェクトを開くこともできる.

iPhone での利用

BSD static Library を作成して、同様の手順で利用すればよい.

まとめ

自分でライブラリを作って利用する分には、依存関係を利用するのが楽でよい.

他にも、プロジェクト内でライブラリと実行ファイルのターゲットを分割する方法があるようだ.

また、xcode では、スタティックライブラリの利用よりも、フレームワークの利用を進めているらしい.
(おそらく、ユニバーサルバイナリの関係かと思われる)