Objective-Cをはじめてみる。
まずはコンパイラ関連
新しい方がよかろうということで、4.2を入れました。
NSObjectはlibfoundationに入ってるらしいので、その辺も一緒くたに入れておきます。
ii gcc 4:4.1.2-9ubuntu2 The GNU C compiler ii gcc-4.1 4.1.2-16ubuntu2 The GNU C compiler ii gcc-4.1-base 4.1.2-16ubuntu2 The GNU Compiler Collection (base package) ii gcc-4.2 4.2.1-5ubuntu4 The GNU C compiler ii gcc-4.2-base 4.2.1-5ubuntu4 The GNU Compiler Collection (base package) ii gcc-4.2-multilib 4.2.1-5ubuntu4 The GNU C compiler (multilib files) ii gobjc 4:4.1.2-9ubuntu2 The GNU Objective-C compiler ii gobjc++-4.2 4.2.1-5ubuntu4 The GNU Objective-C++ compiler ii gobjc++-4.2-multilib 4.2.1-5ubuntu4 The GNU Objective-C++ compiler (multilib fil ii gobjc-4.1 4.1.2-16ubuntu2 The GNU Objective-C compiler ii gobjc-4.2 4.2.1-5ubuntu4 The GNU Objective-C compiler ii gobjc-4.2-multilib 4.2.1-5ubuntu4 The GNU Objective-C compiler (multilib files ii libfoundation-data 1.0.84-1ubuntu1 Static data files used by libFoundation ii libfoundation-tools 1.0.84-1ubuntu1 Configuration tools for libFoundation ii libfoundation1.0 1.0.84-1ubuntu1 Implementation of the OpenStep specification ii libfoundation1.0-dev 1.0.84-1ubuntu1 Development files for libfoundation
お約束
GNUStep形式でのお約束です。
#import <stdio.h> #import <objc/Object.h> @interface TestClass : Object - (void) getMessage; @end
#import "hello.h" @implementation TestClass - (void) getMessage { printf("helllo Objective-C\n"); } @end int main (int argc, char* argv[]) { id obj = [ TestClass alloc ]; [ obj getMessage ]; return 0; }
お約束2
Macの解説書にあるようにNSObject.hでもテストしてみました。面倒なので、ソースは1つで書いています。
#import <Foundation/NSObject.h> @interface TestClass : NSObject - (void) getMessage; @end @implementation TestClass - (void) getMessage { printf("Hello NSObject\n"); } @end int main (int args, char* argv[]){ id obj = [ TestClass alloc ]; [obj getMessage ]; return 0; }
コンパイルしてみたらエラーで怒られました。
sisyphus@ubuntu:~/src$ gcc -o nshello nshello.m -lobjc /tmp/ccr5N2Tr.o:(.data+0x2b8): undefined reference to `__objc_class_name_NSObject' collect2: ld returned 1 exit status
リンクしようにも、NSObjectが無いよと言ってます。リンカが怒ってるところから 「-lobjc」でリンクしているモノが違うといってるのだろうということぐらいは私にも察しはつきます。
そもそも「-lobjc」をおまじないとしていたツケがまわってきました。
「objc」の正体は[libobjc.so]で、それをリンクしていることが分かりました。
そこで、NSObjectはlibFoundation.soにあるのでこれを指定すれば良いということになるはずだと
判断しました。
そして、libobjc.soがobjcになるのであれば、libFoundation.soはFoundationになるだろう
ということで、試してみると
sisyphus@ubuntu:~/src$ gcc nshello.m -o nshello -lFoundation
うまくいきました。
リンカのマニュアルを見ておく
うまくいくとちゃんと調べずに放置してしまう悪い癖があるので、マニュアルを読んでおくことにしました。
必要なところは下記のところ。
- lar
アーカイブファイル ar をリンクするファイルのリストに加える。このオプションは何回でも指定できる。 ld は ar が指定されるごとに、 libar.a が見つかるまで検索パスを探す。
- Lsearchdir
このコマンドは searchdir を ld の書庫ライブラリの検索パスに追加する。このオプションは必要なだけ指定できる。
デフォルトの検索パス (-L が指定されなかったときの検索パス) は ld が用いているエミュレーションのモードに依存する。また設定に依存する場合もある。リンクスクリプトでは SEARCH_DIR コマンドを用いてこのパスを設定することもできる。
まさに今回の部分でlibFoundation.soをリンクしたかったら-lFoundationとしなさいということですね。
補足
よく使うライブラリがあれば、ld.so.confに書いておけというのを突然思い出しだしました。
今回はパッケージでいれたので、ld.so.conf(debianの場合はld.so.conf.dにファイルをおくみたいです)
の必要は無かったわけです。
HelloWorldのまとめ
これまでもLinuxをつかっていてソースからコンパイルすることはありましたが、完全にユーザーとしてだけ接していたのと、うまくいかなくてもネットで探すとそれなりの答えがあったりして放置していたのが
今回の失敗です。
リンカがライブラリを見つける仕組みを理解するといういきなり高いハードルが立ちはだかりましたが、
現状レベルでは、libをはずしたライブラリ名を指定するということで、
とりあえずコンパイルすることができたので、HelloWorldとしては十分なものを得たということにします(^^;)
「.a」なのか「.so」なのかなど気になる部分はありますし、本当にlibさえはずせば良いのかなど、
疑問はありますが、それは自分で共有ライブラリを作るときの課題に使用と思います。