WindowsでSenna+Tritonn+Mysqlをビルドする

Windows上でSenna組み込みMysqlを使う機会があったので。


http://qwik.jp/senna/mysql_windows.html

一応公式に詳細な手順が載ってるのでそのままやってみたけどビルドでこける。1日ゴニュゴニョしてとりあえずうまくいったっぽいので備忘録的に手順を残しておきます。

環境とか

今回Windows上でコンパイルした環境は「Visual C++ 2005 Express Edition」(ダウンロードは「http://www.microsoft.com/japan/msdn/vstudio/express/visualc/」から)

※事前にこことかこことかみてPlatformSDKとか環境設定とか済ませておく。

1.Mecabのインストール

MecabについてはWindows用のバイナリがあるのでここからダウンロードしてインストールする。

追記

文字コードとかがちょっと気になるけどとりあえず放置。
↑やっぱり放置しちゃダメっぽい。もうちょっと調べてみる。


その後インストール先フォルダ内「bin\libmecab.dll」を「C:\Windows\system32」配下へコピーする。

2.Sennaのインストール

Sennaは2007/8/6時点ではバージョン1.0.8が出てるけど、Tritonnのバージョンと合わせるために1.0.4をビルドする。

(1)ダウンロード
まず「ダウンロードファイル一覧 - senna - OSDN」から「senna-1.0.4.tar.gz」をダウンロードし適当なフォルダ(※今回はD:\src)に保存する。

(2)展開&ビルド準備
保存したsenna-1.0.4.tar.gzを展開し「senna-1.0.4」フォルダを開く。
Mecabインストールフォルダ内の「sdk\libmecab.lib」と「sdk\mecab.h」をソースフォルダ内の「vcc\mecab」配下にコピーする。

(3)ビルド&インストール
プロジェクトlibsennaをrelease構成でビルドする。
ビルド完了後、生成されたファイルをそれぞれコピーする。
 ・「vcc\Release\libsenna.dll」→「C:\Windows\system32\libsenna.dll」
 ・「vcc\Release\libsenna.lib」→「C:\Program files\senna\lib\libsenna.lib」
 ・「senna.h」→「C:\Program files\senna\include\senna.h」

3.Mysqlのインストール

Mysqlはとりあえずインストーラ版をいれて初期データやらサービスやらの設定をしておく。
(※バージョンはTritonnと合わせるため5.0.37をインストール)

流れとしては、
(1)Linux上でソースにTritonnパッチを充ててmakeする
(2)Windows用ソースに必要なファイルをコピーする
(3)Windows用ソースをビルドする
という感じになりそう。

ということで、

(1)Linux上でTritonnパッチを充ててmake

mecab+senna+tritonn+mysqlLinuxでビルドする手順については「http://qwik.jp/tritonn/userguide.html」を参考に。DebianSargeでやったけどとくに詰まるところもなくいける。
今回はインストールする必要はないのでmakeが通った時点でストップ。

ついでに、後の作業の都合上ソースディレクトリ名「mysql-5.0.37」を「mysql-5.0.37-senna」に変更しておく。

(2)Windows用ソースに必要なファイルをコピーする

MySQL :: MySQL Product Archives」から、
5.0.37のWindows用ソースをとってくる。

$ cd ~/src
$ wget http://downloads.mysql.com/archives/mysql-5.0/mysql-5.0.37-win-src.tar.gz
$ tar vxzf mysql-5.0.37-win-src.tar.gz
$ mv mysql-5.0.37 mysql-5.0.37-win

で、以下のようなコマンドで先ほどmakeしたソースから必要なものをWindows用ソースへコピーする

$ cp mysql-5.0.37-senna/include/mysql_version.h mysql-5.0.37-win/include/mysql_version.h
$ cp mysql-5.0.37-senna/include/myisam.h mysql-5.0.37-win/include/myisam.h
$ cp mysql-5.0.37-senna/include/my_pthread.h mysql-5.0.37-win/include/my_pthread.h
$ cp mysql-5.0.37-senna/include/my_config.h mysql-5.0.37-win/include/my_config.h
$ cp mysql-5.0.37-senna/include/my_base.h mysql-5.0.37-win/include/my_base.h
$ cp mysql-5.0.37-senna/libmysqld/filesort.cc mysql-5.0.37-win/libmysqld/filesort.cpp
$ cp mysql-5.0.37-senna/libmysqld/ha_myisam.cc mysql-5.0.37-win/libmysqld/ha_myisam.cpp
$ cp mysql-5.0.37-senna/libmysqld/item_cmpfunc.cc mysql-5.0.37-win/libmysqld/item_cmpfunc.cpp
$ cp mysql-5.0.37-senna/libmysqld/item_func.cc mysql-5.0.37-win/libmysqld/item_func.cpp
$ cp mysql-5.0.37-senna/libmysqld/item_sum.cc mysql-5.0.37-win/libmysqld/item_sum.cpp
$ cp mysql-5.0.37-senna/libmysqld/records.cc mysql-5.0.37-win/libmysqld/records.cpp
$ cp mysql-5.0.37-senna/libmysqld/set_var.cc mysql-5.0.37-win/libmysqld/set_var.cpp
$ cp mysql-5.0.37-senna/libmysqld/sql_db.cc mysql-5.0.37-win/libmysqld/sql_db.cpp
$ cp mysql-5.0.37-senna/libmysqld/sql_delete.cc mysql-5.0.37-win/libmysqld/sql_delete.cpp
$ cp mysql-5.0.37-senna/libmysqld/sql_select.cc mysql-5.0.37-win/libmysqld/sql_select.cpp
$ cp mysql-5.0.37-senna/libmysqld/sql_show.cc mysql-5.0.37-win/libmysqld/sql_show.cpp
$ cp mysql-5.0.37-senna/libmysqld/sql_table.cc mysql-5.0.37-win/libmysqld/sql_table.cpp
$ cp mysql-5.0.37-senna/myisam/ft_boolean_search.c mysql-5.0.37-win/myisam/ft_boolean_search.c
$ cp mysql-5.0.37-senna/myisam/ft_nlq_search.c mysql-5.0.37-win/myisam/ft_nlq_search.c
$ cp mysql-5.0.37-senna/myisam/ft_update.c mysql-5.0.37-win/myisam/ft_update.c
$ cp mysql-5.0.37-senna/myisam/mi_check.c mysql-5.0.37-win/myisam/mi_check.c
$ cp mysql-5.0.37-senna/myisam/mi_close.c mysql-5.0.37-win/myisam/mi_close.c
$ cp mysql-5.0.37-senna/myisam/mi_create.c mysql-5.0.37-win/myisam/mi_create.c
$ cp mysql-5.0.37-senna/myisam/mi_delete_all.c mysql-5.0.37-win/myisam/mi_delete_all.c
$ cp mysql-5.0.37-senna/myisam/mi_delete_table.c mysql-5.0.37-win/myisam/mi_delete_table.c
$ cp mysql-5.0.37-senna/myisam/mi_info.c mysql-5.0.37-win/myisam/mi_info.c
$ cp mysql-5.0.37-senna/myisam/mi_open.c mysql-5.0.37-win/myisam/mi_open.c
$ cp mysql-5.0.37-senna/myisam/mi_rename.c mysql-5.0.37-win/myisam/mi_rename.c
$ cp mysql-5.0.37-senna/myisam/myisam_ftdump.c mysql-5.0.37-win/myisam/myisam_ftdump.c
$ cp mysql-5.0.37-senna/myisam/myisamchk.c mysql-5.0.37-win/myisam/myisamchk.c
$ cp mysql-5.0.37-senna/myisam/myisamlog.c mysql-5.0.37-win/myisam/myisamlog.c
$ cp mysql-5.0.37-senna/myisam/myisampack.c mysql-5.0.37-win/myisam/myisampack.c
$ cp mysql-5.0.37-senna/sql/sql_yacc.cc mysql-5.0.37-win/sql/sql_yacc.cpp
$ cp mysql-5.0.37-senna/sql/item_sum.cc mysql-5.0.37-win/sql/item_sum.cpp
$ cp mysql-5.0.37-senna/sql/records.cc mysql-5.0.37-win/sql/records.cpp
$ cp mysql-5.0.37-senna/sql/sql_select.cc mysql-5.0.37-win/sql/sql_select.cpp
$ cp mysql-5.0.37-senna/sql/filesort.cc mysql-5.0.37-win/sql/filesort.cpp
$ cp mysql-5.0.37-senna/sql/ha_myisam.cc mysql-5.0.37-win/sql/ha_myisam.cpp
$ cp mysql-5.0.37-senna/sql/item_cmpfunc.cc mysql-5.0.37-win/sql/item_cmpfunc.cpp
$ cp mysql-5.0.37-senna/sql/item_func.cc mysql-5.0.37-win/sql/item_func.cpp
$ cp mysql-5.0.37-senna/sql/mysqld.cc mysql-5.0.37-win/sql/mysqld.cpp
$ cp mysql-5.0.37-senna/sql/set_var.cc mysql-5.0.37-win/sql/set_var.cpp
$ cp mysql-5.0.37-senna/sql/sp_head.cc mysql-5.0.37-win/sql/sp_head.cpp
$ cp mysql-5.0.37-senna/sql/sql_db.cc mysql-5.0.37-win/sql/sql_db.cpp
$ cp mysql-5.0.37-senna/sql/sql_delete.cc mysql-5.0.37-win/sql/sql_delete.cpp
$ cp mysql-5.0.37-senna/sql/sql_parse.cc mysql-5.0.37-win/sql/sql_parse.cpp
$ cp mysql-5.0.37-senna/sql/sql_show.cc mysql-5.0.37-win/sql/sql_show.cpp
$ cp mysql-5.0.37-senna/sql/sql_table.cc mysql-5.0.37-win/sql/sql_table.cpp
$ cp mysql-5.0.37-senna/sql/lex_hash.h mysql-5.0.37-win/sql/lex_hash.h
$ cp mysql-5.0.37-senna/sql/sql_yacc.h mysql-5.0.37-win/sql/sql_yacc.h
$ cp mysql-5.0.37-senna/sql/item_func.h mysql-5.0.37-win/sql/item_func.h
$ cp mysql-5.0.37-senna/sql/handler.h mysql-5.0.37-win/sql/handler.h
$ cp mysql-5.0.37-senna/sql/item.h mysql-5.0.37-win/sql/item.h
$ cp mysql-5.0.37-senna/sql/item_cmpfunc.h mysql-5.0.37-win/sql/item_cmpfunc.h
$ cp mysql-5.0.37-senna/sql/lex.h mysql-5.0.37-win/sql/lex.h
$ cp mysql-5.0.37-senna/sql/mysql_priv.h mysql-5.0.37-win/sql/mysql_priv.h
$ cp mysql-5.0.37-senna/sql/set_var.h mysql-5.0.37-win/sql/set_var.h
$ cp mysql-5.0.37-senna/sql/sql_class.h mysql-5.0.37-win/sql/sql_class.h
$ cp mysql-5.0.37-senna/sql/sql_lex.h mysql-5.0.37-win/sql/sql_lex.h
$ cp mysql-5.0.37-senna/sql/structs.h mysql-5.0.37-win/sql/structs.h

・・・多い。

さらに「mysql-5.0.37-win/include/config-win.h」に以下のように追記する

$ echo "#define ENABLE_SENNA 1" >> mysql-5.0.37-win/include/config-win.h
(3)Windows用ソースをビルドする

(2)でできあがったソースを一旦tarでまとめてWindowsFTPとかで持ってくる。

$ tar czvf mysql-5.0.37-win-senna.tar.gz mysql-5.0.37-win

■■■以下Windowsでの作業■■

適当な場所にソースを展開し(※今回は「D:\src\mysql-5.0.37-win」に展開)ソース内の「mysql.dsw」を開く。

ウチの環境ではこのままビルドすると失敗するので以下のとおり修正。

  • libmysqlのプロジェクト依存関係に「strings」を含める
  • mysqld,myisamchk,myisamlog,myisam_ftdump,myisampackのライブラリに「C:\Program files\senna\lib\libsenna.lib」を追加
  • mysqld,myisamchk,myisamlog,myisam_ftdump,myisampackのインクルードディレクトリに「C:\Program files\senna\include」を追加
  • sql/sql_locale.cpp」の文字コード判別に失敗するので「BOM付き」UTF8に変更しておく。


上記変更を行い、mysqldをRelease/Debugでmyisamchk,myisamlog,myisam_ftdump,myisampacをReleaseでビルドして、エラーなしでビルド完了すればおk。

(4)ファイルを配置する

Windows用ソース内に「copy_mysql_files.bat」っていう便利そうなのがあるので実行する。
とりあえず

  • 「C:\mysql」にmysqlをインストール済み
  • データフォルダとかも全部「C:\mysql」を想定
  • mysql」というサービス名でサービス登録済み

という条件下ならこれでいいっぽい。

4.動作確認してみる

DROP DATABASE IF EXISTS senna_test;

CREATE DATABASE senna_test;

USE senna_test;

CREATE TABLE table01 (
    id INT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY(id),
    title VARCHAR(255),
    body TEXT,
    FULLTEXT(body)
) engine=MyISAM DEFAULT CHARSET utf8;

CREATE TABLE table02 (
    id INT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY(id),
    title VARCHAR(255),
    body TEXT,
    FULLTEXT INDEX ft USING NGRAM (body)
) ENGINE = MyISAM DEFAULT CHARSET utf8;

INSERT INTO table01 VALUES
(NULL, "衆院選挙について", "皆さんはどの党に投票するのでしょうか"),
(NULL, "果物", "apple リンゴ、orange オレンジ"),
(NULL, "歌", "わくわくさせてよ、ついてるねのってるね"),
(NULL, "MySQL", "MySQLリファレンスマニュアルを全部読め"),
(NULL, "ロボットのgood designとは", "先週末に開催された GoodDesignPresentation 2005");

INSERT INTO table02 VALUES
(NULL, "衆院選挙について", "皆さんはどの党に投票するのでしょうか"),
(NULL, "果物", "apple リンゴ、orange オレンジ"),
(NULL, "歌", "わくわくさせてよ、ついてるねのってるね"),
(NULL, "MySQL", "MySQLリファレンスマニュアルを全部読め"),
(NULL, "ロボットのgood designとは", "先週末に開催された GoodDesignPresentation 2005");

SELECT * FROM table01 WHERE MATCH(body) AGAINST('投票');
SELECT * FROM table01 WHERE MATCH(body) AGAINST('投票する');
SELECT * FROM table01 WHERE MATCH(body) AGAINST('apple');
SELECT * FROM table01 WHERE MATCH(body) AGAINST('リンゴ');
SELECT * FROM table01 WHERE MATCH(body) AGAINST('わくわく');
SELECT * FROM table01 WHERE MATCH(body) AGAINST('gooddesign');
SELECT * FROM table01 WHERE MATCH(body) AGAINST('読め');

SELECT * FROM table02 WHERE MATCH(body) AGAINST('投票');
SELECT * FROM table02 WHERE MATCH(body) AGAINST('投票する');
SELECT * FROM table02 WHERE MATCH(body) AGAINST('apple');
SELECT * FROM table02 WHERE MATCH(body) AGAINST('リンゴ');
SELECT * FROM table02 WHERE MATCH(body) AGAINST('わくわく');
SELECT * FROM table02 WHERE MATCH(body) AGAINST('gooddesign');
SELECT * FROM table02 WHERE MATCH(body) AGAINST('読め');

USE mysql;

DROP DATABASE IF EXISTS senna_test;

とりあえずこのSQLを流して反応見てみる。