mecab で Java Binding
ここにもあるように、Mac ではデフォルトで mecab が入っている模様。
hyakushiki:~ takashi$ pkgutil --file-info /usr/lib/libmecab.dylib volume: / path: usr/lib/libmecab.dylib pkgid: com.apple.pkg.BaseSystem pkg-version: 10.5.0.1.1.1188305148 install-time: 1203610626 uid: 0 gid: 0 mode: 120755
com.apple.pkg.BaseSystem というのは、コアパッケージっぽい。すごいなぁ。。
とはいえ、mecab の Java Binding を試してみたかった為、別途インストールしてみます。が、極力楽したいので、まずは mac ports でインストールした後、Java Binding のみをインストールする方針で Go。
hyakushiki:~ takashi$ sudo port install mecab +utf8 mecab-ipadic-utf8 hyakushiki:~ takashi$ port info mecab mecab 0.96, textproc/mecab (Variants: universal, darwin_7, darwin_8, sjis, utf8, utf8only) http://mecab.sourceforge.net/ :
無事インストール後、0.96 の Java Binding のソースを落としてきて、ぱっと目につく Include や Java のパスを修正してビルドしようとするとMakefile の以下の部分で、
$(CXX) -shared $(TARGET)_wrap.o -o lib$(TARGET).so $(LIBS)
こんなエラーが発生。
Undefined symbols: "_main", referenced from: start in crt1.10.5.o ld: symbol(s) not found collect2: ld returned 1 exit status make: *** [all] Error 1
crt1.10.5.o はあるし、何だろうと思っていたら、man g++ をして衝撃の事実。
-shared
Produce a shared object which can then be linked with other objects to form an executable. Not all systems support this option.
For predictable results, you must also specify the same set of options that were used to generate code (-fpic, -fPIC, or model
suboptions) when you specify this option.[1]
This option is not supported on Mac OS X.
どうやら、これに該当しそうなオプションは -dynamiclib というのが正解の模様です。という事で、最終的に以下のように Makefile を書き換えて、make test まで成功。
hyakushiki:mecab-java-0.96 takashi$ diff -u Makefile.org Makefile --- Makefile.org 2007-06-10 23:32:44.000000000 +0900 +++ Makefile 2008-07-15 02:57:25.000000000 +0900 @@ -1,27 +1,29 @@ +JAVA_BASE=/System/Library/Frameworks/JavaVM.framework/Versions/1.5 +JAVA_HOME=$(JAVA_BASE)/Home TARGET=MeCab -JAVAC=javac -JAVA=java -JAR=jar -CXX=c++ -INCLUDE=/usr/local/jdk/include +JAVAC=$(JAVA_HOME)/bin/javac -encoding eucjp +JAVA=$(JAVA_HOME)/bin/java +JAR=$(JAVA_HOME)/bin/jar +CXX=g++ +INCLUDE=$(JAVA_BASE)/Headers PACKAGE=org/chasen/mecab LIBS=`mecab-config --libs` -INC=`mecab-config --cflags` -I$(INCLUDE) -I$(INCLUDE)/linux +INC=`mecab-config --cflags` -I$(INCLUDE) all: - $(CXX) -O3 -c -fpic $(TARGET)_wrap.cxx $(INC) - $(CXX) -shared $(TARGET)_wrap.o -o lib$(TARGET).so $(LIBS) + $(CXX) -O3 -c -fPIC $(TARGET)_wrap.cxx $(INC) + $(CXX) -dynamiclib $(TARGET)_wrap.o -o lib$(TARGET).dylib $(LIBS) $(JAVAC) $(PACKAGE)/*.java $(JAVAC) test.java $(JAR) cfv $(TARGET).jar $(PACKAGE)/*.class test: - env LD_LIBRARY_PATH=. $(JAVA) test + env DYLD_LIBRARY_PATH=. $(JAVA) test clean: - rm -fr *.jar *.o *.so *.class $(PACKAGE)/*.class + rm -fr *.jar *.o *.dylib *.class $(PACKAGE)/*.class cleanall: rm -fr $(TARGET).java *.cxx
ポイントは以下の通り。
- JAVA_HOME 周りは適宜設定
- INCLUDE はヘッダのディレクトリを指定
- JAVAC にソースのエンコーディングを追加
- INC で、linux では $(INCLUDE)/linux を指定しているけれど、ここにあるヘッダは $(JAVA_BASE)/Headers に含まれているので問題なし
- -fpic はないと怒られるので -fPIC で
- -shared の代わりに -dynamiclib で、拡張子も dylib に
- 実行時の環境変数は LD_LIBRARY_PATH から DYLD_LIBRARY_PATH へ
余談。Linux/Solaris などでおなじみの ldd はない模様。代わりに otool を発見。
hyakushiki:mecab-java-0.96 takashi$ otool -L libMeCab.dylib libMeCab.dylib: libMeCab.dylib (compatibility version 0.0.0, current version 0.0.0) /opt/local/lib/libmecab.1.dylib (compatibility version 2.0.0, current version 2.0.0) /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.4.0) /usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.1.1)