SnowLeopardにhomebrewで、MySQLにmysqlftppc mecab pluginをICU対応で入れようとして頓挫した話


MySQLmecabのインストールまでは、macportsからHomebrewに乗り換えてMySQL5.1をインストールするまでの流れ 参照

mysqlftppc mecab pluginって何?


MySQLでFULLTEXTインデックスをパースする時に、mecabを使うようにするプラグイン

FULLTEXTインデックスって何?


MySQLで使える全文検索機能用のインデックス
like検索より早い
内部的にはパーサを使って文章を分割して、インデックス用のデータを作っている
標準のパーサだと、カンマや空白区切りでパースするので、日本語の検索に向かない

FULLTEXT パーサは特定の区切り文字を見て、語の頭と最後を定義します。
その例には、‘ ’ ( スペース ) , ‘,’ ( カンマ ) , そして ‘.’ ( ピリオド ) があります。
単語が非区切り文字 ( 例えば中国語 ) で区切られている場合は、FULLTEXT パーサは単語の最初と最後を定義することができません。
単語や、インデックスのついた他の表現をそのような言語で FULLTEXT インデックスに加えるには、事前に処理して ‘"’ などの任意の区切り文字で区切る必要があります。 


なので、FULLTEXTインデックスを作るときのパーサーをプラグインで拡張する必要がある
上記mysqlftppc mecab pluginは、mecabを使って文章を解析してFULLTEXTインデックスを作ってくれるプラグイン

mecabのインストール

$ brew install mecab

mecab用の辞書 naist-jdic をインストール


mecabは標準では、IPAdicという辞書を使うような設定になっているのだけど、
IPAdicはライセンス上の問題があったりするので、IPAdicの改良版のnaist-jdic を入れるのが良いらしい

$ brew create "http://sourceforge.jp/frs/redir.php?m=iij&f=%2Fnaist-jdic%2F48487%2Fmecab-naist-jdic-0.6.3-20100801.tar.gz"
$ cd /usr/local/Library/Formula
# すごい名前になるのでmv
$ mv redir.php\?m=iij\&f=%2fnaist-jdic%2f48487%2fmecab-naist-jdic.rb mecab-naist-jdic.rb
# コンパイル時に、/etc/mecab が必要なので作っておく
$ sudo mkdir /etc/mecab
$ sudo chown kobayashi /etc/mecab
$ vim mecab-naist-jdic.rb

一部設定を編集

require 'formula'

# Documentation: https://github.com/mxcl/homebrew/wiki/Formula-Cookbook
# PLEASE REMOVE ALL GENERATED COMMENTS BEFORE SUBMITTING YOUR PULL REQUEST!

# class名も修正
class MecabNaistJdic < Formula
  homepage ''
  url 'http://sourceforge.jp/frs/redir.php?m=iij&f=%2Fnaist-jdic%2F48487%2Fmecab-naist-jdic-0.6.3-20100801.tar.gz'
  version '0.6.3-20100801'
  homepage 'http://sourceforge.jp/projects/naist-jdic/' #追加した
  sha1 '86ccbb15d208a99d81ebcef9f31aee384cc7b31e'

  # depends_on 'cmake' => :build
  depends_on :x11 # if your formula requires any X11/XQuartz components

  def install
    # ENV.j1  # if your formula's build system can't parallelize
    system "./configure", "--disable-debug", "--disable-dependency-tracking",
                          "--prefix=#{prefix}", "--with-charset=utf8" # utf8を追加
    # system "cmake", ".", *std_cmake_args
    system "make install" # if this fails, try separate make/make install steps
  end

  def test
    # This test will fail and we won't accept that! It's enough to just replace
    # "false" with the main program this formula installs, but it'd be nice if you
    # were more thorough. Run the test with `brew test redir.php?m=iij&f=%2Fnaist-jdic%2F48487%2Fmecab-naist-jdic`.
    system "false"
  end
end
$ brew install mecab-naist-jdic
辞書の設定を更新


mecab-naist-jdicを使うように設定ファイルを更新

vim /usr/local/Cellar/mecab/0.994/etc/mecabrc
;dicdir =  /usr/local/Cellar/mecab/0.994/lib/mecab/dic/ipadic
dicdir =  /usr/local/Cellar/mecab/0.994/lib/mecab/dic/naist-jdic
動作確認


ここまではOK

$ echo "東急東横線" | mecab
東急東横        名詞,固有名詞,一般,*,*,*,東急東横,トウキュウトウヨコ,トーキュートーヨコ,,
線      名詞,接尾,一般,*,*,*,線,セン,セン,,
EOS

icu4cをインストール

$ brew install icu4c
icuって?


ICUUnicode国際化コンポーネント
4cは、c++,c 向けのICUのライブラリらしい
これをmysqlftppc-mecabに組み込むことでUnicode正規化に対応できるらしい
Unicode正規化とは? → http://sourceforge.net/apps/mediawiki/mysqlftppc/index.php?title=Home-j#Unicode_.E6.AD.A3.E8.A6.8F.E5.8C.96
全角と半角文字の比較とかができるようになるらしい → 検索精度が上がる

mysqlftppc-mecabをインストール

$ brew create http://sourceforge.net/projects/mysqlftppc/files/mysqlftppc/1.6.1/mysqlftppc-mecab-1.6.1.tar.gz/download?use_mirror=jaist
$ cd /usr/local/Library/Formula
$ mv download\?use.rb mysqlftppc-mecab.rb
$ vim mysqlftppc-mecab.rb
require 'formula'

# Documentation: https://github.com/mxcl/homebrew/wiki/Formula-Cookbook
# PLEASE REMOVE ALL GENERATED COMMENTS BEFORE SUBMITTING YOUR PULL REQUEST!

# class名も修正
class MysqlftppcMecab < Formula
  homepage ''
  url 'http://sourceforge.net/projects/mysqlftppc/files/mysqlftppc/1.6.1/mysqlftppc-mecab-1.6.1.tar.gz/download?use_mirror=jaist'
  version '1.6.1'
  sha1 'dbccb787f4f6f588481e0b0623993cec5ba0f106'

  # depends_on 'cmake' => :build
  depends_on :x11 # if your formula requires any X11/XQuartz components

  def install
    # ENV.j1  # if your formula's build system can't parallelize

    system "./configure", "--disable-debug", "--disable-dependency-tracking",
                          "--prefix=#{prefix}"
                          "--enable-utf8-only",
                          # icuを使うように設定
                          "--with-icu-config=/usr/local/Cellar/icu4c/50.1/bin/icu-config"
    # system "cmake", ".", *std_cmake_args
    system "make install" # if this fails, try separate make/make install steps
  end

  def test
    # This test will fail and we won't accept that! It's enough to just replace
    # "false" with the main program this formula installs, but it'd be nice if you
    # were more thorough. Run the test with `brew test download?use`.
    system "false"
  end
end
インストール
$ brew install mysqlftppc-mecab
==> Downloading http://sourceforge.net/projects/mysqlftppc/files/mysqlftppc/1.6.1/mysqlftppc-mecab-1.6.1.tar.gz/download?use_mirror=jaist
Already downloaded: /Library/Caches/Homebrew/mysqlftppc-mecab-1.6.1
==> ./configure --prefix=/usr/local/Cellar/mysqlftppc-mecab/1.6.1 --enable-utf8-only --with-icu-dir=/usr/local/Cellar/icu4c/50.1
==> make install
i686-apple-darwin10-gcc-4.2.1: c: No such file or directory
i686-apple-darwin10-gcc-4.2.1: c: No such file or directory
make: *** [libftmecab_la-ftnorm.lo] Error 1
make: *** Waiting for unfinished jobs....
make: *** [libftmecab_la-ftbool.lo] Error 1

READ THIS: https://github.com/mxcl/homebrew/wiki/troubleshooting


エラーが発生

64bitを明示的に指定して手動でコンパイル
tar-ball をダウンロードした場合は展開した後、configureスクリプトを実行してください。
mysqld_config が見つからない場合は、--mysqld-config=/path/to/mysqld_config 引数をつけてください。
mysqld 自体が 64bit でビルドされていたり、debug=full でコンパイルされている場合は、適宜適切な CFLAGS を渡してください。


と、あるので明示的に64bitでコンパイルしてみる

$ make clean
$ CFLAGS="-m64" ./configure --disable-debug --disable-dependency-tracking --enable-utf8-only --with-icu-config=/usr/local/Cellar/icu4c/50.1/bin/icu-config
$ make
$ make install

make/bin/sh ./libtool --tag=CC --mode=compile gcc -DPACKAGE_NAME=\"plugin_mecab\" -DPACKAGE_TARNAME=\"plugin_mecab\" -DPACKAGE_VERSION=\"1.6.1\" -DPACKAGE_STRING=\"plugin_mecab\ 1.6.1\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE=\"plugin_mecab\" -DVERSION=\"1.6.1\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1  -I. -I. -I./include -I./include -I/usr/local/Cellar/mysql51/5.1.67/include/mysql  -I/usr/local/Cellar/mecab/0.994/include -F/usr/local/Frameworks     -I/usr/local/Cellar/icu4c/50.1/include \c -DMYSQL_DYNAMIC_PLUGIN -m64 -DHAVE_ICU -c -o libftmecab_la-ftnorm.lo `test -f 'ftnorm.c' || echo './'`ftnorm.c
mkdir .libs
 gcc -DPACKAGE_NAME=\"plugin_mecab\" -DPACKAGE_TARNAME=\"plugin_mecab\" -DPACKAGE_VERSION=\"1.6.1\" "-DPACKAGE_STRING=\"plugin_mecab 1.6.1\"" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE=\"plugin_mecab\" -DVERSION=\"1.6.1\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -I. -I. -I./include -I./include -I/usr/local/Cellar/mysql51/5.1.67/include/mysql -I/usr/local/Cellar/mecab/0.994/include -F/usr/local/Frameworks -I/usr/local/Cellar/icu4c/50.1/include c -DMYSQL_DYNAMIC_PLUGIN -m64 -DHAVE_ICU -c ftnorm.c  -fno-common -DPIC -o .libs/libftmecab_la-ftnorm.o
i686-apple-darwin10-gcc-4.2.1: c: No such file or directory
In file included from /usr/local/Cellar/mysql51/5.1.67/include/mysql/my_global.h:86,
                 from ftnorm.c:2:
/usr/local/Cellar/mysql51/5.1.67/include/mysql/my_config.h:1167:1: warning: "PACKAGE" redefined
<command-line>: warning: this is the location of the previous definition
/usr/local/Cellar/mysql51/5.1.67/include/mysql/my_config.h:1173:1: warning: "PACKAGE_NAME" redefined
<command-line>: warning: this is the location of the previous definition
/usr/local/Cellar/mysql51/5.1.67/include/mysql/my_config.h:1176:1: warning: "PACKAGE_STRING" redefined
<command-line>: warning: this is the location of the previous definition
/usr/local/Cellar/mysql51/5.1.67/include/mysql/my_config.h:1179:1: warning: "PACKAGE_TARNAME" redefined
<command-line>: warning: this is the location of the previous definition
/usr/local/Cellar/mysql51/5.1.67/include/mysql/my_config.h:1182:1: warning: "PACKAGE_VERSION" redefined
<command-line>: warning: this is the location of the previous definition
/usr/local/Cellar/mysql51/5.1.67/include/mysql/my_config.h:1298:1: warning: "VERSION" redefined
<command-line>: warning: this is the location of the previous definition
make: *** [libftmecab_la-ftnorm.lo] Error 1


やっぱりエラー

諦めて、icuを外してみる
$ make clean
$ CFLAGS="-m64" ./configure --disable-debug --disable-dependency-tracking --enable-utf8-only
$ make
$ make install
make[1]: Nothing to be done for `install-exec-am'.
test -z "/usr/local/Cellar/mysql51/5.1.67/lib/mysql/plugin" || /Users/kobayashi/tmp/mysqlftppc-mecab/mysqlftppc-mecab-1.6.1/install-sh -d "/usr/local/Cellar/mysql51/5.1.67/lib/mysql/plugin"
 /bin/sh ./libtool --mode=install /usr/bin/install -c  'libftmecab.la' '/usr/local/Cellar/mysql51/5.1.67/lib/mysql/plugin/libftmecab.la'
/usr/bin/install -c .libs/libftmecab.0.0.0.so /usr/local/Cellar/mysql51/5.1.67/lib/mysql/plugin/libftmecab.0.0.0.so
(cd /usr/local/Cellar/mysql51/5.1.67/lib/mysql/plugin && { ln -s -f libftmecab.0.0.0.so libftmecab.0.so || { rm -f libftmecab.0.so && ln -s libftmecab.0.0.0.so libftmecab.0.so; }; })
(cd /usr/local/Cellar/mysql51/5.1.67/lib/mysql/plugin && { ln -s -f libftmecab.0.0.0.so libftmecab.so || { rm -f libftmecab.so && ln -s libftmecab.0.0.0.so libftmecab.so; }; })
/usr/bin/install -c .libs/libftmecab.lai /usr/local/Cellar/mysql51/5.1.67/lib/mysql/plugin/libftmecab.la
----------------------------------------------------------------------
Libraries have been installed in:
   /usr/local/Cellar/mysql51/5.1.67/lib/mysql/plugin

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `DYLD_LIBRARY_PATH' environment variable
     during execution

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------


あっさり成功


必要なファイルが作られていることを確認

$ ll /usr/local/Cellar/mysql51/5.1.67/lib/mysql/plugin | grep ftm
-rwxr-xr-x  1 kobayashi  admin    20392  1  7 18:58 libftmecab.0.0.0.so*
lrwxr-xr-x  1 kobayashi  admin       19  1  7 18:58 libftmecab.0.so@ -> libftmecab.0.0.0.so
-rwxr-xr-x  1 kobayashi  admin      890  1  7 18:58 libftmecab.la*
lrwxr-xr-x  1 kobayashi  admin       19  1  7 18:58 libftmecab.so@ -> libftmecab.0.0.0.so


MySQLプラグインをインストールする

mysql> INSTALL PLUGIN mecab SONAME 'libftmecab.so';
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW STATUS LIKE "Mecab_info";
+---------------+-------------------------------+
| Variable_name | Value                         |
+---------------+-------------------------------+
| Mecab_info    | with mecab 0.994, without ICU |
+---------------+-------------------------------+
1 row in set (0.00 sec)


ICUが入っていないmecabプラグインが追加されたことを確認

参考


まめ畑

  • ここだと明示的にicu-configの場所を指定してない。自前の環境だとwithoutICUになる...


MySQL full-text parser plugin collectionのmecab pluginを入れる - kouheiの日記

  • エラーの内容が似ている。後日調査


PHP で MySQL FULLTEXT + MeCab で簡単に全文検索を実装する | ウェブル

  • FULLTEXTインデックスの説明や、MeCebを選択する理由などがわかりやすくまとめられている

チラシの裏


以下うまくいかない原因の考察

SnowLeopardでは、32bitアプリと64bitアプリが混在しているけどこの辺が悪さをしている?


例えば、icuを32bitでしか作ってなくて、mysqlftppcを64bitでコンパイルしようとしたためにエラーが出たとか
Homebrewには、ユニバーサルバイナリでmakeするか否かを決める環境変数を設定するメソッドがある


Library/Homebrew/extend/ENV.rb

  # i386 and x86_64 (no PPC)
  def universal_binary
    append_to_cflags '-arch i386 -arch x86_64'
    replace_in_cflags '-O4', '-O3' # O4 seems to cause the build to fail
    append 'LDFLAGS', '-arch i386 -arch x86_64'

    unless compiler == :clang
      # Can't mix "-march" for a 32-bit CPU  with "-arch x86_64"
      replace_in_cflags(/-march=\S*/, '-Xarch_i386 \0') if Hardware.is_32_bit?
    end
  end


で、MySQLとか、icu4cのFormulaでは、ユニバーサルバイナリコンパイルする設定が書かれている

  def install
    # Make universal for bindings to universal applications
    ENV.universal_binary if build.universal?


だけど、mysqlftppc-mecabは自作の為そのような設定が無いのでそれが原因かなぁ... と思ったけど
そもそも、build.universal? がfalseを返していて64bit版を作っていたので違った


Lionだと特に躓くことも無くあっさりICU版がインストールできた


なので、SnowLeopard環境に何かしらの原因があるはずだが...

mysql> SHOW STATUS LIKE "Mecab_info";
+---------------+-----------------------------------------+
| Variable_name | Value                                   |
+---------------+-----------------------------------------+
| Mecab_info    | with mecab 0.994, ICU 50.1(Unicode 6.2) |
+---------------+-----------------------------------------+
1 row in set (0.01 sec)


そんな煮え切らない感じで