11.22.2009

MinGWでObjective-Cを試してみる。

ちょっくらObjective-Cに興味があって、前々から調べていたんだけれども、この休みに……と思って、MinGW環境でObjective-Cを試してみた。

なんでわざわざMinGWを使う買って言うと、Linux環境では既に成功しているから。
せっかくだし、Windows環境でも動いたら嬉しいなと思ったのだ。

まずはMinGWの公式サイトにいって、アーカイブをもらってくる。
ここで注意しないといけないのは、普通に配ってるインストーラを使っての導入だと、gccのバージョンが3.x系になってしまうこと。
だから、Getting Startedにあるようにマニュアルインストールを行う。

リストに上がっている
binutils
mingw-runtime (dev and dll)
w32api
Required runtime libraries for GCC (gmp, libiconv, MPFR and pthreads)
gcc-core (bin and dll)

のほか、

gcc-objc (bin and dll) for Objective C



mingw-gdb for debugger
mingw32-make for make
mingw-utils for MinGW Utilities

総勢15のファイルを取ってきて、C:\MinGWフォルダ以下に展開しておく。
解凍には7-zipというフリーソフトを用いた。スゲー便利。

で、起動用バッチファイルを用意。
環境変数を直接いじってもいいんだけれども、なんとなく今回はバッチファイルを使うことにした。
mingw.cmdとかいう名前で、C:\MinGW直下に保存。
内容は今のところ
@echo off
set PATH=%PATH%;C:\mingw\bin
set INCLUDE_PATH=C:\mingw\include;C:\mingw\lib\gcc\mingw32\4.4.0\include
set LIBRARY_PATH=C:\mingw\lib;C:\mingw\lib\gcc\mingw32\4.4.0
set LIBPATH=C:\mingw\lib;C:\mingw\lib\gcc\mingw32\4.4.0
set LD_LIBRARY_PATH=C:\mingw\lib;C:\mingw\lib\gcc\mingw32\4.4.0
set TEMP=C:\TMP
set TMP=C:\TMP
set LANG=C
cd C:\mingw\src
@echo on

な感じ。まだ試行錯誤中なので、今後変わる可能性大。
ちなみに、最後のcdコマンドは作業ディレクトリに移動するためのコマンド。
C:\workで作業するならそれに書き換えてあげると楽。

で、ここまで出来たら、デスクトップにコマンドプロンプトのショートカットを作って、プロパティから、リンク先を
%SystemRoot%\system32\cmd.exe /k "C:\mingw\mingw"

とかしてあげる。

これができたら、そのショートカットからコマンドプロンプトを起動して、
$ gcc --version

でgccのインストールを確認する。

次に、Objective-CでHello worldを書く。
例えばhello.mの内容を
#import < stdio.h >
#import < objc/object.h >

@interface Test : Object
- (void)Hello;
@end

@implementation Test
- (void)Hello {
 printf("Hello Objective-C World\n");
}
@end

int main() {
 id obj = [Test alloc];
 [obj Hello];
 
 return 0;
}

とかしてあげる。たぶん、allocしたのにfreeしてないとか、ツッコミどころはあるんだろうけど、ネットで適当に拾ってきたソースの改変かつコンパイルのテストなので、そこは目をつむっておく。

これができたら、先ほどのコマンドプロンプトに戻り
$ gcc -lobjc hello.m

とかする。通常は、これでうまくいくらしい。
通常はと書いたのは、ウチでは以下のエラーを吐いて、コンパイル(正確にはリンク)がコケてしまったからだ。

C:\TMP\cczsTv17.o:hello.m:(.text+0x24): undefined reference to `objc_msg_lookup_
super'
C:\TMP\cczsTv17.o:hello.m:(.text+0x69): undefined reference to `objc_get_class'
C:\TMP\cczsTv17.o:hello.m:(.text+0x7c): undefined reference to `objc_msg_lookup'

C:\TMP\cczsTv17.o:hello.m:(.text+0x9d): undefined reference to `objc_msg_lookup'

C:\TMP\cczsTv17.o:hello.m:(.text+0xc4): undefined reference to `objc_msg_lookup'

C:\TMP\cczsTv17.o:hello.m:(.text+0xe7): undefined reference to `objc_msg_lookup'

C:\TMP\cczsTv17.o:hello.m:(.text+0x112): undefined reference to `__objc_exec_cla
ss'
C:\TMP\cczsTv17.o:hello.m:(.data+0x140): undefined reference to `__objc_class_na
me_Object'
collect2: ld returned 1 exit status


ネットを探しても、さしたる情報は出てこない。
ldでコケてるのは間違いないから、LD_LIBRARY_PATHとかを環境変数に追加してみたものの、一向にエラーは消えない。

Linuxなら、/etc/ld.so.confに代表される、ldの設定ファイルいじるとか(そもそもLD_LIBRARY_PATHがあるのに通らないのが変なんだけど)できるけど、Windowsはよく分からないのでお手上げ状態。

で、結局解決策として
$ gcc hello.m C:\mingw\lib\gcc\mingw32\4.4.0\libobjc.a

という、直接ライブラリを指定してリンクさせる方法を取った。
たぶん、作法的には汚いやり方なんだろうけど、他に解決策が思いつかないのだから仕方ない。
どなたか、このldのエラーについて解決策を知っていたら、ぜひとも知らせて欲しいデス。切実に。

他に同じエラーで困っている人が居たら、一応の解決策として上記みたいなことができるよってことで、メモ代わりにエントリを挙げときます。

3 件のコメント:

匿名 さんのコメント...

-lobjc

代わりにこれを追加してみても面白いかも

匿名 さんのコメント...

かなり亀レスですが・・・

gcc -lobjc hello.m

ではなく

gcc hello.m -lobjc

で行けるはずです。

匿名 さんのコメント...

私も同じ現象で困っていたのですが、
LD_LIBRARY_PATHにlibexec以下の指定も追加し、

set LD_LIBRARY_PATH=C:\MinGW\lib;C:\MinGW\lib\gcc\mingw32\4.6.1;C:\MinGW\libexec\gcc\mingw32\4.6.1;

とすると私の環境ではうまくコンパイルできました。

(TDM-GCCを使用しているので若干挙動が異なるかもしれません)