Objective-Cをはじめてみる。

まずはコンパイラ関連

Ubuntuです。coLinuxにのせてます。

新しい方がよかろうということで、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

うまくいきました。

リンカのマニュアルを見ておく

うまくいくとちゃんと調べずに放置してしまう悪い癖があるので、マニュアルを読んでおくことにしました。

Manpage of ld

必要なところは下記のところ。

  • 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さえはずせば良いのかなど、
疑問はありますが、それは自分で共有ライブラリを作るときの課題に使用と思います。