株式会社クリアコード > ククログ

ククログ

最新
2008|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|
タグ:

*roonga族リリース

肉の日なのでgroongaとその関連プロジェクトがリリースされました。

このうち、mroongaの変更点が大きめなので、mroonga 0.7の変更点について紹介します。

mroongaとは

mroonga*1はMySQLにgroongaの全文検索機能を追加するストレージエンジンです。ストレージエンジンというのはMySQLのデータストア機能・検索機能を担当するモジュールのことです。ここがプラグインとして後から追加できる仕組みになっています。groongaをバックエンドとしてストレージエンジンを実装しているのがmroongaです*2

mroongaを使うと嬉しいこと

mroongaを使うと使い慣れたRDBやSQLを使って全文検索機能が得意なアプリケーションを開発できるようになります。既存の資産を活かしながら本格的な全文検索機能も使えることが嬉しいことですね。

現在は、RDBとSolrを組み合わせて全文検索機能付きのアプリケーションを実現していることも多いかもしれませんが、そうすると管理対象が増えたりデータが分散したりして管理コストが上がってしまいます*3

mroongaはこれまでと同様にMySQLサーバーを管理するだけでよいので、新しく管理対象が増えたりしません。

これまでのmroonga: ストレージモード

mroonga 0.6までは、データストア機能も通常の検索機能も全文検索機能も提供するひとり立ちしたストレージエンジンでした。このように動くモードをストレージモードと呼びます。図にすると以下のようになります。MyISAMやInnoDBと同じように扱える1つのストレージエンジンとしてmroongaが存在しています。

ストレージモード

このモードではカラムストアであるgroongaの特性を活かすことができるため、 不必要なデータアクセスを避けた高速な動作ができるというメリットがあります。しかし、データストアの信頼性という点では、実績のあるInnoDBなどには及ばないというデメリットがあります。

このデメリットを解決するために追加されたのがラッパーモードです*4

0.7で追加されたモード: ラッパーモード

mroonga 0.7では新しくラッパーモードという動作モードを追加しました。このモードでは、他のストレージエンジンと連携して動作します。mroongaは全文検索機能だけ実現し、データストア機能や通常の検索機能は他のストレージエンジンに任せます。図にすると以下のようになります。MySQLからはmroongaしか見えませんが、mroongaの後ろにMyISAMやInnoDBなど既存のストレージエンジンが存在します。mroongaはMySQLと既存のストレージエンジンの間に入り、全文検索機能関連のみ処理し、それ以外は既存のストレージエンジンに処理してもらいます。

ラッパーモード

このモードでは任意の既存のストレージエンジンにgroongaの高性能な全文検索機能を追加できるというメリットがあります。例えば、信頼性のあるInnoDBに全文検索機能を追加して、便利で高速で安心なRDBを実現できます。

まとめ

今月も*roonga族がリリースされました。今回は特にmroongaについて紹介しました。

ラッパーモードの使い方についてはmroongaのラッパーモードのドキュメントを参照してください。なお、同じページに現時点での注意点も説明してあるので、そちらも確認してください。

*1  正式名称は「groongaストレージエンジン」で、「mroonga」は開発コードネームという位置付けだったのですが、最近は「mroongaの方がいいやすいよね?」、「正式名称もmroongaでいいんじゃない?」みたいな流れもでてきています。1.0がリリースされるまでにはどうなるかが決まるはずです。

*2  groongaのSQLインターフェイスと考えてもよい。

*3  Sphinxという選択肢もありますが、構成上それはそれで管理コストが上がってしまいます。

*4  ストレージモードがなくなるわけではありません。

つづき: 2011-12-26
タグ: groonga
2011-06-29

Sphinxの国際化機能を使って複数言語用ドキュメントを用意する方法(使い方)

Sphinxの国際化機能を使って複数言語用ドキュメントを用意する方法(概要)で示した複数言語用ドキュメントを用意する仕組みの使い方を紹介します。本当は仕組みについて説明するつもりだったのですが、使い方を書いていたら長くなったので分けることにしました。この仕組みは実際にgroongaで使っているもので、以下のような使い方になります。

  • ドキュメントを英語で書く。
  • 他の言語への翻訳をPOファイルに書く。
  • それぞれの言語毎にHTMLを生成する。

まずファイル構成を紹介して、その後、実例を示しながら具体的な作業を紹介します。

ファイル構成

まずファイル構成です。これで概要を掴んでください。

groongaはAutomakeなどのGNUビルドシステムを利用しているため、このような構成になっています。違うビルドシステムを利用している場合は違う構成にした方がよいかもしれません。その場合でも英語を特別扱いせずにdoc/locale/以下に各言語毎のディレクトリを作るという方法は真似した方がよいでしょう。この方が規則を単純化できるため、ビルドシステムが単純になるはずです。

.
|-- build
|   `-- makefiles (doc/locale/#{言語}/以下で共有するMakefile)
|       |-- LC_MESSAGES.am (doc/locale/#{言語}/LC_MESSAGES/Makefile.amでinclude)
|       |-- gettext-files.am
|       |-- gettext.am
|       |-- locale.am (doc/locale/#{言語}/Makefile.amでinclude)
|       |-- sphinx-build.am
|       `-- sphinx.am
`-- doc
    |-- Makefile.am
    |-- locale (各言語用ディレクトリ置き場)
    |   |-- Makefile.am
    |   |-- en (英語用ディレクトリ)
    |   |   |-- LC_MESSAGES(翻訳テキストなし。単なる置き場所。)
    |   |   |   |-- Makefile.am
    |   |   |   |-- *.po
    |   |   |   `-- *.mo
    |   |   |-- Makefile.am
    |   |   |-- html/ (生成された英語のHTML)
    |   |   |-- html-build-stamp (HTMLが生成されたことを示すだけのファイル)
    |   |   |-- man/ (生成された英語のman)
    |   |   `-- man-build-stamp (manが生成されたことを示すだけのファイル)
    |   `-- ja (日本語用ディレクトリ)
    |       |-- LC_MESSAGES (英語→日本語の翻訳テキスト)
    |       |   |-- Makefile.am
    |       |   |-- *.po
    |       |   `-- *.mo
    |       |-- Makefile.am
    |       |-- html/ (生成された日本語のHTML)
    |       |-- html-build-stamp (HTMLが生成されたことを示すだけのファイル)
    |       |-- man/ (生成された日本語のman)
    |       `-- man-build-stamp (manが生成されたことを示すだけのファイル)
    |-- source/ (ドキュメント本体)
    `-- sphinx/ (最新のSphinx)

Sphinxの国際化のドキュメント(英語)ではsource/以下にtranslated/#{言語}/LC_MESSAGES/というディレクトリを作って、そこに*.moを置くような例になっています。しかし、上記の構成ではsource/の下ではなく、source/と同じディレクトリにlocale/#{言語}/LC_MESSAGES/を作っています。これは、source/以下に*.moなど自動生成するファイルを置かないようにするためです。

source/以下にファイルがあるとデフォルトでsphinx-buildの処理対象となってしまいます。そのため、source/以下にtranslated/#{言語}/LC_MESSAGES/を置く場合はconf.py内でexclude_patternsを使って処理対象でないことを明示する必要があります。明示的に処理対象外とするくらいなら、はじめからsource/以下ではなく場所に置いた方がよいのではないか、ということでsource/の下ではなく、同じディレクトリにlocale/#{言語}/LC_MESSAGES/を置いています。

使い方

それではこの仕組みを使ったドキュメントの作成方法です。

ドキュメント作成の流れは以下のようになります。ここでは、new-documentというドキュメントを追加するという例で話を進めます。

  1. doc/source/new-document.txtを作成し、英語でドキュメントを書く。
  2. doc/locale/ja/LC_MESSAGES/へ移動する。
  3. make initを実行する。
  4. ↑でnew-document.poができるので、それをリポジトリへ追加する。
  5. new-document.poを翻訳する。
  6. doc/locale/ja/へ移動する。
  7. make htmlを実行する。
  8. ↑でdoc/locale/ja/html/以下に翻訳されたHTMLが生成されるので確認する。

ドキュメントの作成はこの作業を繰り返すことになります。実例を以下に示します。

1. 英語でドキュメントを書く。

まず、英語でドキュメントを作成します。以下の内容のドキュメントにしたとします。

doc/source/new-document.txt:

New Document
============

Hi! This is new document.

次に、既存のページからリンクを張ります。こうしないとどこからも辿れないページになってしまいます。

doc/source/index.txt:

...
* :doc:`new-document`
...

これでオリジナルのドキュメントができました。

2., 3., 4. POファイルの作成

次は、翻訳テキストを書くファイルであるPOファイルを作成します。

[groonga]% cd doc/locale/ja/LC_MESSAGES
[groonga/doc/locale/ja/LC_MESSAGES]% make init
...
ユーザが翻訳に関するフィードバックをあなたに送ることができるように,
新しいメッセージカタログにはあなたの email アドレスを含めてください.
またこれは, 予期せぬ技術的な問題が発生した場合に管理者があなたに連絡が取れる
ようにするという目的もあります.

Is the following your email address?
  kou@clear-code.com
Please confirm by pressing Return, or enter your email address.
kou@clear-code.com ← 入力
http://translationproject.org/team/index.html を検索中... 完了.
A translation team for your language (ja) does not exist yet.
If you want to create a new translation team for ja, please visit
  http://www.iro.umontreal.ca/contrib/po/HTML/teams.html
  http://www.iro.umontreal.ca/contrib/po/HTML/leaders.html
  http://www.iro.umontreal.ca/contrib/po/HTML/index.html

new-document.po を生成.
[groonga/doc/locale/ja/LC_MESSAGES]%

上記のコマンドで以下のような内容のPOファイルが作成されます。

doc/locale/ja/LC_MESSAGES/new-document.po:

# Japanese translations for 1.2.2 package.
# Copyright (C) 2009-2011, Brazil, Inc
# This file is distributed under the same license as the groonga package.
# Kouhei Sutou <kou@clear-code.com>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: 1.2.2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-06-19 19:18\n"
"PO-Revision-Date: 2011-06-19 19:18+0900\n"
"Last-Translator: Kouhei Sutou <kou@clear-code.com>\n"
"Language-Team: Japanese\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ja\n"
"Plural-Forms: nplurals=1; plural=0;\n"

#: ../../../source/new-document.txt:2
msgid "New Document"
msgstr ""

#: ../../../source/new-document.txt:4
msgid "Hi! This is new document."
msgstr ""

翻訳対象のメッセージはmsgid "New Document"msgid "Hi! This is new document."の部分です。

内容を確認したらリポジトリに登録しましょう。

[groonga/doc/locale/ja/LC_MESSAGES]% git add new-document.pot
[groonga/doc/locale/ja/LC_MESSAGES]% git commit

(ここでbuild/makefiles/Makefile.amの中にあるpo_filesmo_filesなどを更新する必要があるのですが、ここでは割愛します。)

5. POファイルの更新

生成されたPOファイルはmsgstr ""msgstrの部分が空文字列になっています。ここに翻訳後のテキストを入力します。

doc/locale/ja/LC_MESSAGES/new-document.po:

...
#: ../../../source/new-document.txt:2
msgid "New Document"
msgstr "新しいドキュメント"

#: ../../../source/new-document.txt:4
msgid "Hi! This is new document."
msgstr "わーい!新しいドキュメントだよー。"
6., 7., 8. 翻訳されたドキュメントの確認

以下の手順で翻訳され日本語ドキュメントとなったHTMLを出力できます。

[groonga/doc/locale/ja/LC_MESSAGES]% cd ..
[groonga/doc/locale/ja]% make html
[groonga/doc/locale/ja]% firefox html/new-document.html

以下のようなHTMLがブラウザで表示されたはずです。

...
<h1>新しいドキュメント...</h1>
<p>わーい!新しいドキュメントだよー。</p>
...

まとめ

groongaで採用しているSphinxの国際化機能を使って複数言語用ドキュメントを用意する方法の使い方について紹介しました。なお、新しい言語の追加方法についてはgroongaの翻訳方法のドキュメントで説明しています。

次こそはこの仕組みについて説明できるはずです。

つづき: 2011-07-07
タグ: groonga
2011-06-19

日本Ruby会議2011でLDAPの話をしませんか?

日本Ruby会議2011Lightning Talkの締め切りが残り数日になっていますが、みなさんいかがお過ごしでしょうか。

去年開催された日本Ruby2010では、はRuby で扱う LDAP のススメ - 選択肢とその事例という企画があり、RubyとLDAPに関する情報を共有する場になりました。(企画を主催した高瀬さんのまとめ

日本では「RubyでLDAPを使う」というケースを情報共有する場が無く、この企画はとても意義のあるものでした。今年も同じような場が設けられると有意義でしょう。ということで、RubyKaigi2011の講演以外の企画についてを参考に、日本 Ruby会議2011でそういう場を設けるための方法案をまとめてみました。興味がでてきた人はぜひ実現させてください。

Lightning Talk

自分が知っていることなどを発表して情報を共有できるでしょう。ただし、持ち時間5分のなかで質疑応答などをすることはできないので、別の機会で行うことを考慮した方がよいでしょう。

会期中は会場3Fの和室をハッカソンなどのために開放します

日本Ruby会議2010でやった企画のように、「数人の発表者 + 質疑応答」というスタイルを実現できるかもしれません。あるいは、その場で一緒にコードを書いたりすることもできるかもしれません。

または、Lightning Talkと組み合わせて質疑応答をこちらで行うということも考えられます。

会期中にアンカンファンレス、!RubyKaigi(NotRubyKaigi)2011を開催しておきます

Lightning Talkより自由度が高いので、この時間だけで「発表 + 質疑応答」ができるかもしれません。

RubyKaigi Advent Calendar 2011

日本Ruby会議 2011の会期中ではなく、それより前に場を設けるという方法です。他の方法より準備が大変そうですが、一番自由度は高くなります。いろいろやりたいことがある場合はこの方法がよいかもしれません。

まとめ

日本Ruby会議2011でRubyとLDAPの話をする場を設ける方法案を紹介してみました。興味が出てきた方は[activeldap:88] 今年も日本Ruby会議2011に参加しませんか?へどうぞ。

(どの方法案もLDAPに関係ないような気がします。)

タグ: Ruby
2011-06-16

本社移転のお知らせ

来月7/11に本社を移転します。場所は今の本社から歩いて5-10分くらいのところです。

人数が増えて手狭になってきたことが移転の理由です。人が増えることで、これまでよりもクリアコードを目にする機会が増えるかと思います。

これまでと同様に移転後もクリアコードはフリーソフトウェアを開発していきますので、これからもどうぞよろしくおねがいします。

つづき: 2011-07-11
2011-06-09

日本Ruby会議2011でるりまとテスティングフレームワークについて話します

日本Ruby会議2011のスケジュールが発表されました。クリアコードのメンバーはるりまに関することとテスティングフレームワークに関することを話します。面白そうだなと思ったら聞きに来てください。

タグ: Ruby
2011-06-07

Sphinxの国際化機能を使って複数言語用ドキュメントを用意する方法(概要)

YARDのことの続きを書きたいと思いつつもなかなか辿りつきません。今回はPython製のドキュメントツールSphinxの話です。groongaのケースを例にしてSphinxで複数言語用のドキュメントを生成する方法の概要を紹介します。書いていたら長くなったので、具体的にどうするかというのは次の機会にします。

5/29にgroonga 1.2.2がリリースされました。今後は日本だけではなく世界でも使ってもらえるように、英語でも情報を発信していく方向になりました。そこで、今回のリリースに合わせてサイトデザインをリニューアルし、英語のページも用意しました。ただし、すでにあった日本語のコンテンツを今回のリリースで全部英語にした、というものではありません。今回のリリースでやったのは「日本語と英語という複数の言語で情報を発信する仕組み」を作るところまでです。せっかくなので、今回のリリースで導入した、Sphinxを使って実現している複数言語用のドキュメントを用意する仕組み(の概要)を紹介します。

なお、実際のページは以下のようになります。英語のページでも日本語の文章がまだまだ多く残っていますが、これはおいおい改善していく予定です*1

それぞれのページのヘッダーには他の言語へのリンクを用意してあり、すぐに対応する他の言語のページに行けるようになっています。

概要

まず、複数言語用のドキュメントを用意する仕組みの概要を説明します。

しばらくしたらリリースされるだろうSphinx 1.1には国際化機能がついています。(Sphinx本家の国際化についてのドキュメント(英語)。)今回紹介する仕組みはこの機能をベースにした仕組みになります*2

国際化機能を使うと、ベースとなるドキュメント1つから、そのドキュメントを他の言語に翻訳したドキュメントを複数生成することができます。ふつうはベースとなるドキュメントは英語で記述するので、以下のようなイメージになります。

他の言語に翻訳したドキュメントを複数生成

ポイントは、本文のテキストだけ他の言語に翻訳すればよいというところです。章分けや説明する順序などの文章の構造などはベースとなる英語のドキュメントと同じものを共有します。

以下のようにドキュメント全体を翻訳する方法もありますが、この場合は文章の構造は共有していません。それぞれの翻訳されたドキュメントは翻訳した時点の英語のドキュメントの文書の構造をコピーしています。そのため、英語のドキュメントの文書の構造が変わったら、それにあわせて翻訳したドキュメントの方も変える必要があります*3

ドキュメント全体を翻訳

ドキュメント全体を翻訳する場合は元のドキュメントをコピーして翻訳するだけなので、通常のドキュメント作成作業と作業の流れはそれほど違いはないでしょう。

しかし、Sphinxが採用しているのは本文のみ翻訳する方法なので、通常の作業の流れとはだいぶ異なる流れになります。

翻訳の流れ

Sphinxでは「元の本文」を「翻訳した本文」に置き換えるためにgettextを使っています。gettextは昔からある国際化用ライブラリで、Sphinxが使っているのはgettextのPython実装です。

昔からあるだけあって、周辺ツールがそろっていることが利点です。例えば、元の本文と翻訳した本文とを比較して、変更された本文を自動検出するツールがあったりします。「一度翻訳して終わり」という場合は必要のないツールですが、「元の本文に追従して翻訳も更新する」という場合には有用なツールです。

groongaは継続して開発しているソフトウェアなのでドキュメントも更新されます。この場合は翻訳作業は以下のような流れになります。

翻訳の流れ

「(1)本文を抽出」*4と「(4)本文の差分抽出」*5の部分がツールを使って自動化できる部分です。この部分は手動でやるには大変な部分なのでとても助かります。

「(3)更新」の部分は翻訳とは関係なく通常のドキュメント更新作業と同じです。

残りの(2)と(5)の「日本語へ翻訳」がメインの翻訳作業になりますが、ここの作業が通常の翻訳作業とやり方が違う部分になります。これは、gettextの作法に従う必要があるためです。

翻訳のしかた

gettextはPO (Portable Object)というファイルで「元のテキスト」と「翻訳したテキスト」を関連付けます。POは以下のようなフォーマットのテキストです*6

#: ${元のテキストがあるファイルのパス1}:${行1}
msgid "${元のテキスト1}"
msgstr "${翻訳したテキスト1}"

#: ${元のテキストがあるファイルのパス2}:${行2}
msgid "${元のテキスト2}"
msgstr "${翻訳したテキスト2}"

元の文書から本文を抽出した段階では${翻訳したテキスト}の部分が空になっているので、淡々とそこを埋めていく作業が翻訳作業になります。POファイルはテキストなので好きなエディタで編集できますが、専用の編集ツールもあります。Emacsのpo-modeやGNOMEのGtranslator、KDEのLokalizeなどです。

翻訳ができたら、それと元のドキュメントを使ってHTML形式でドキュメントを生成できます。

まとめ

Sphinxを使った複数言語用のドキュメントを用意する仕組みの概要を紹介しました。具体的な設定などは次の機会に紹介する予定ですが、待ちきれない人はgroongaのリポジトリをのぞいてみてください。

図はblockdiagで作りましたが、便利ですね。

*1  このあたりの改善に興味のある方はgroongaのドキュメントの国際化の方法を参考にチャレンジしてみてください!

*2  未リリースの機能を使っているだけあって、いろいろ大変なところもありました。いくつかは修正してSphinx本体に取り込んでもらいましたが、まだまだ細かくいろいろ問題が残っています。Sphinx推しのみなさんは今のうちに国際化機能を使って、1.1がリリースされる前にもっと改良してみてはいかがでしょうか。

*3  それでもこの方法で複数の言語のドキュメントを用意したい場合はドキュメントの翻訳にSphinxを使うなどを参考にしてみてはいかがでしょうか。

*4  Sphinxが生成したMakefileを使うとmake gettextで抽出できます。

*5  make gettextmsgmergeを組み合わせます。

*6  詳細は本家のThe Format of PO Filesを参照。

タグ: groonga
2011-05-31

日本Ruby会議2011にGoldスポンサーとして参加

昨年に引き続き、クリアコードは今年も日本Ruby会議2011のGoldスポンサーになりました。

まだでていませんが、発表などでも参加する予定なので、会場で見かけたら声でもかけてください。

開催は2ヶ月後で、まだ少し時間がありますが、RubyKaigi2011の講演以外の企画についてRubyKaigi Advent Calendar 2011など関連情報がいくつかでています。Online.kaigi.rbなど日本Ruby会議2011以前に行われるイベントもあるようなので、興味のある方はそちらにも参加してみてはいかがでしょうか。

タグ: Ruby
2011-05-19

64bit版Windows用のRubyInstallerの作り方

WindowsにRubyをインストールする場合、どうやってインストールしますか?現在のところ、以下のようにいくつも選択肢があります。

それぞれ特徴があるので自分の使い方にあったものを選ぶ必要がありますが、今回の話の趣旨は「これがオススメです!」というものを伝えることではないので、簡単に紹介するだけにしておきます。ピンときたものがあったら、それについてもう少し詳しく調べてみることをおすすめします。

  • Ruby-mswin32: インストーラではなく、バイナリをzip形式のアーカイブで配布。展開すればそのまま使える。32bit版と64bit版の両方あり。1.8と1.9の両方あり。Visual Studioでビルド。
  • ActiveScriptRuby: インストーラ形式。32bit版のみ。1.8と1.9の両方あり。HTML Application内でRubyを使うことができる。Visual Studioでビルド。
  • RubyInstaller for Windows: インストーラ形式。ただし、メッセージは英語。32bit版のみ。1.8と1.9の両方あり。MinGWでビルド。
  • Rumix: インストーラ形式。32bit版のみ。1.8と1.9の両方あり。バイナリはRuby-mswin32のものを利用。
  • 能楽堂: インストーラ形式。64bit版のみ。1.9.3(2011/05/15時点では未リリース)のみ。Visual Studioでビルド。Rails実行環境入り。

今回の話ではRubyInstaller for Windowsを使います。では、どうしてRubyInstaller for Windowsを使うのでしょうか。

RubyInstaller for Windowsの特長

今回挙げたビルド済みRubyのパッケージの中で、RubyInstaller for WindowsのみがMinGWでRubyをビルドしています。これが、今回RubyInstaller for Windowsを選んだ理由です。RubyがMinGWでビルドされているとDebian GNU/Linux上で拡張ライブラリをクロスコンパイルすることができます*1

GNU/Linuxなどでは64bit版Rubyが普通に使われていますが、Windowsではまだそうでもないようです。しかし、今後はWindowsでも64bit版Rubyの利用が進んでいくでしょう。そうなった場合、拡張ライブラリは64bit版Ruby用のバイナリ入りで配布することが求められます*2

普段からWindowsで開発している拡張ライブラリであれば簡単に64bit版Ruby用バイナリを作成できるでしょうが、メインの開発環境がGNU/Linux*3という場合は難しいです。GNU/Linuxで開発している場合は、GNU/Linux上でクロスコンパイルして64bit版Ruby用バイナリを作成できるととても便利です。そして、MinGW-w64を利用すれば64bit版Windows用のDLLをクロスコンパイルできるのです。

しかし、RubyInstallerはまだ64bit版Rubyには対応していません。つまり、64bit版Ruby用の拡張ライブラリをクロスコンパイルしてバイナリを作っても、それを使うための64bit版Rubyの入手が困難な状況ということです。

64bit版Ruby対応RubyInstaller

RubyInstallerが64bit版Rubyに対応していないため、クロスコンパイルした拡張ライブラリを使える64bit版Rubyを簡単にインストールできない問題をどのように解決すればよいでしょうか?簡単ですね。RubyInstallerを64bit版Rubyに対応させればいいのです。

ということで、対応させたものがGitHub上のkou/rubyinstallerのmingw-w64ブランチにあります。これを使って作成した64bit版Ruby*4用のRubyInstallerと、Debian GNU/Linux上でクロスコンパイルしたrroongaのgemを以下に置いておきます*5

rroongaのチュートリアルで、実際にきちんと動くことを確認できます。

というように、なんとなく動くようになっていますが、まだいくつかやらなければいけないことがあります。

ということで、Ruby 1.9.3がリリースされるまでにみなさんがこれらの修正できるように64bit版Ruby用RubyInstallerの作り方を紹介します。タイトルからは想像できなかった展開ですね。

64bit版Ruby用RubyInstallerの作り方

まず、初期設定の方法を紹介し、それからRubyをビルド・テストする方法とRubyInstallerを作成する方法を紹介します。

初期設定

必要なものは以下の通りです。

  • Ruby 1.8.7の実行ファイル
  • Inno Setup
  • Cygwin
  • Ruby trunkのソースコード
  • RubyInstall for Windowsのソースコード

Ruby 1.8.7はすでにあるRubyInstaller for Windowsを使ってインストールします。Ruby 1.9.2では動作しないので注意してください。

Inno SetupはWindowsインストーラを作成するフリーソフトウェアです。ダウンロードページからisetup-5.4.2.exeをダウンロードしてインストールします。

本当はCygwinはなくてもよいのですが、初期設定が楽なのでCygwinを使います。まず、setup.exeをダウンロードしてCygwinをインストールします。追加でインストールするソフトウェアは以下の通りです。

  • subversion
  • autoconf
  • git

必須ではありませんが、mingw64-x86_64-binutilsもあると便利でしょう。

CygwinをインストールしたらRubyをチェックアウトします。trunkのRubyを修正しないと取り込んでもらえないからです。また、作業は~/work/ruby/*6以下で行うことにします。

% mkdir -p ~/work/ruby
% cd ~/work/ruby
% svn co http://svn.ruby-lang.org/repos/ruby/trunk ruby
% cd ruby
% autoconf

RubyInstaller for Windowsのソースコードもチェックアウトします。mingw-w64ブランチの成果はオフィシャルリポジトリに取り込まれそうな雰囲気はあるのですが、まだ取り込まれていないのでmingw-w64ブランチを使います。

% cd ~/work/ruby
% git clone https://github.com/kou/rubyinstaller.git
% cd rubyinstaller
% git checkout mingw-w64

以上が初期設定です。ここまでの作業は最初に1回行うだけです。今後は~/work/ruby/rubyinstaller/で作業を行います。

ビルド

ここからはcmd.exe上で実行します。ただし、cmd.exe上で長いコマンドを打つのは大変なので、バッチファイルを作成します。

build.bat:

c:\Ruby187\bin\ruby.exe c:\Ruby187\bin\rake ruby19 LOCAL='C:\Cygwin\home\kou\work\ruby\ruby' ProgramFiles='c:\Program Files (x86)' dkver=mingw64-64-4.5.4 --trace > build.log 2>&1

これをC:\cygwin\home\kou\work\ruby\rubyinstaller\で実行します。

C:\cygwin\home\kou\work\ruby\rubyinstaller>build.bat

小一時間ほど待つとsandbox\ruby19_mingw\以下に64bit用Rubyが作成されているはずです。

C:\cygwin\home\kou\work\ruby\rubyinstaller>sandbox\ruby19_mingw\bin\ruby.exe --version
ruby 1.9.3dev (2011-05-14) [x64-mingw32]

ビルド時のログはbuild.logに保存されているので、問題が発生した場合はログを見て問題を解決し、RubyやRubyInstallerの開発チームに報告して解決内容を取り込んでもらいましょう。開発チームにコンタクトをとる方法など、関連リソースについては一番最後に書いてあるので参考にしてください。

パッケージの作成

パッケージの作成もコマンドが長いのでバッチファイルを作成します。

package.bat:

c:\Ruby187\bin\ruby.exe c:\Ruby187\bin\rake ruby19:package LOCAL='C:\cygwin\home\kou\work\ruby\ruby' ProgramFiles='c:\Program Files (x86)' dkver=mingw64-64-4.5.4 --trace > package.log 2>&1

これをC:\cygwin\home\kou\work\ruby\rubyinstaller\で実行します。

C:\cygwin\home\kou\work\ruby\rubyinstaller>package.bat

10分ほど待つとpkg\以下にRubyInstallerが作成されているはずです。このRubyInstallerにはsandbox\ruby19_mingw\以下にビルドされたRuby用が含まれています。RubyInstallerのファイル名はpkg\rubyinstaller-1.9.2-p180.exeになっていて、直さなければいけないものの1つです。ただ、このファイル名は後で直すことにして、まずは、試しにインストールしてみましょう。インストーラをダブルクリックするとインストールできます*7

ここまでくればパッケージの修正作業はできますね。現在のところ、以下のような問題があります。

テスト

テストの実行もコマンドが長いのでバッチファイルとシェルスクリプトを作成します。テストはMSYS上で実行するため、まずはcmd.exeからMSYSのbashに入るためのバッチファイルが必要です。

shell.bat:

c:\Ruby187\bin\ruby.exe c:\Ruby187\bin\rake devkit:sh LOCAL='C:\Cygwin\home\kou\work\ruby\ruby' ProgramFiles='c:\Program Files (x86)' dkver=mingw64-64-4.5.4

次に、bash上でテストを実行するためのシェルスクリプトです。

run-test.sh:

1
2
3
4
5
6
#!/bin/sh

export PATH=$PWD/sandbox/ruby19_mingw/bin:$PATH
ruby --version
cd sandbox/ruby19_build
make test-all

以下のように使います。

C:\cygwin\home\kou\work\ruby\rubyinstaller>shell.bat
...
sh-3.1#$ ./run-test.sh > test.log 2>&1

テスト結果はtest.logに出力されます。この結果ですべてのテストがパスするようにしましょう。なお、r31560では「9486 tests,1877705 assertions, 29 failures, 8 errors, 82 skips」となりました。結果の詳細は以下にあります。

やりがいがありそうですね。

まとめ

MinGW-w64で64bit版Rubyをビルド・テストする方法と、ビルドした64bit版RubyのRubyInstallerを作成する方法を紹介しました。まだ、いくつか問題があるのでピンときた人はRuby 1.9.3がでるまでに修正してみてはいかがでしょうか?

関連リソース:

*1  補足すると、Ruby-mswin32とActiveScruptRubyで配布されている32bit版Ruby用の拡張ライブラリもクロスコンパイルできます。しかし、64bit版Ruby用の拡張ライブラリをクロスコンパイルできません。理由はVisual Studioでビルドした64bit版Rubyではmsvcrt.dllではなくmsvcr80.dllやmsvcr100.dllが使われているためです。MinGWでクロスコンパイルするとmsvcrt.dllを使うようになるため、異なるCランタイムライブラリを使うことになってしまい、うまく動かないのです。参考: C ランタイム ライブラリの「アプリケーションで msvcrt.dll と msvcr100.dll の両方を使用した場合に発生する問題」のところなど。

*2  Windows上でも需要がある拡張ライブラリであれば。

*3  rroongaやrcairoのケース。

*4  ruby --versionは"ruby 1.9.3dev (2011-05-14) [x64-mingw32]"。

*5  一時的に作ったものを置いているだけなので、ある日突然削除されているかもしれません。

*6  WindowsのパスではC:\cygwin\home\kou\work\ruby\。

*7  右クリックで「管理者として実行」を選ばないといけないかもしれません。

つづき: 2011-12-26
タグ: Ruby
2011-05-15

RDocとYARDの比較

リファレンスマニュアルの記述方法を検討し、埋め込み方式のドキュメントツールを採用したとします。Rubyで埋め込み方式のドキュメントツールを使うとしたらRDocかYARDになります*1

RDocからYARDへの移行方法につなげたいのでYARDを使う方向で話を進めたいわけですが、その前にRDocとYARDの背景や機能の違いを確認しておきましょう。

RDocの背景

RDocはRuby 1.8.1からRuby本体に標準添付されています。Ruby1.8.1は2003年のクリスマスにリリースされているので、もう7年くらい前になります。Ruby本体や標準添付されているライブラリもRDoc用にドキュメントが書かれていますし、Rubyで標準的なドキュメントツールといえばRDocという存在です。

RDocは2004年くらいまではRuby本体のリポジトリ上で活発に開発されていましたが、それから数年は開発が停滞していました。その後、2008年頃より開発リポジトリをRuby本体のリポジトリからRubyForgeのリポジトリに移動して*2、再び開発が活発になりはじめます*3。RDoc 2.Xがはじまったのもこの頃です。2年後の2010年の12月にRDoc 3.Xがはじまるなど、今でも開発のペースは衰えていません。

と、こう書くとRDocでいいんじゃないかと思うところです。しかし、Ruby 1.9を使っていて日本語も含むドキュメントを扱っていた人はそんなことはないということに気づいているはずです。Ruby 1.9の大きな変更の1つがEncodingの導入ですが、RDoc 2はEncodingの対応が不十分です。RDoc 2でHTMLを生成しようとして、Encoding関連の例外が発生した人もいるのではないでしょうか。

そして、ハマリポイントなのが、Ruby 1.9.2に標準添付されているRDocは RDoc 3ではなくRDoc 2だということです。Encoding関連で問題が発生している人はgemでRDoc 3をインストールして、そっちを試してみてください。

RDocの機能

RDocではドキュメントのマークアップ言語として独自のマークアップ言語を作成しています。MarkdownTextileなどといったマークアップ言語よりもシンプルで、機能が足りないと感じることが多いかもしれません。特に、Ruby用のドキュメントシステムとして開発されたのにも関わらず、コード用の専用マークアップがないことには驚くかもしれません*4

クラスやメソッド用のメタ情報記述方法ではRuby用ドキュメントツールらしい記述がサポートされています。Rubyは動的な言語なので「メソッドを定義するメソッド」*5も定義できます。そのようなメソッドのドキュメントも記述できるようになっています。

例えば、以下のようにprotected_attr_readerという独自の「メソッドを定義するメソッド」を定義したとします。このとき、protected_attr_readerで定義したメソッドもattr_readerと同じように読み込み専用属性としてドキュメント化して欲しいですよね。RDocでは以下のように記述することによって、独自の「メソッドを定義するメソッド」で定義したメソッドにも適切にドキュメントを記述することができます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class CoveredBook
  class << self
    def protected_attr_reader(name)
      attr_reader name
      protected name
    end
  end

  ##
  # :attr_reader:
  # タイトルを返す。ただし、内部からのみから利用可能。
  protected_attr_reader :title

  def initialize(title)
    @title = title
  end
end

と、こう書くとRDocでいいんじゃないかと思うところです。しかし、DoxygenGTK-Docなど他のドキュメントツールにはあるような専用マークアップがありません。例えば、メソッドの引数*6や戻り値*7のドキュメントを記述するための専用マークアップがありません。これらはメソッドのドキュメントを読みやすく整形するときに便利です。また、「バージョンいくつから追加された機能」*8や「非推奨のAPI」*9を記述する専用マークアップもありません。

現在も開発が継続しており、RDoc 3もリリースされ、継続的に改良されている*10のですが、まだ細かいところのサポートが不足しているという印象です。

YARDの背景

YARDは2007年から開発が始まっています。RDocの開発が再び活発になりはじめたのが2008年頃なので、あまり改良されていなかった当時のRDocに不満を持っていたのかもしれません。

YARDが重視していることは拡張のしやすさです。YARDのトップページにはアピールポイントとして「Preview As You Document」、「Easily Customize Templates」、「Support Your Own DSL」、「Extend, Extend, Extend!」の4つが挙げられています。このうち3つは拡張性に関することです。Rubyは動的な言語なので使われ方も様々です。様々な使われ方をしているときでもドキュメントを記述できるように拡張性を高くしているものと考えられます。

また、RDocとの互換性も重視しています。RDoc用に書かれたドキュメントを変更なしで処理できるため、RDocからの移行も容易です。

YARDの機能

YARDは複数のマークアップ言語をサポートしています。組み込みではRDoc由来のマークアップ言語だけのサポートですが、gemをインストールすることでMarkdownやTextileも利用することができます。チュートリアルや設計に関する文書など、ある程度長めの文書を書くときはRDocのマークアップではなく、より汎用的なマークアップ言語の方を使うのがよいでしょう。

YARDはメソッドなどのメタ情報の記述方法はRDocとは異なる書式を採用しています。YARDはDoxygenやGTK-Docなどと同様に@タグ名という記述方法を採用しています*11。YARDではこれをタグと呼んでいます。組み込みで利用できるタグにはRDocにはなかった、引数記述用タグ、戻り値記述用タグ、初出バージョン記述用タグ、非推奨API記述用タグなどライブラリのドキュメントを記述するために必要そうなタグが一通り揃っています。また、タグを追加することもできます*12

また、ドキュメントとして抽出したテキスト情報やメタ情報を再利用しやすい形で提供しています。これを利用することでるりまサーチのようなドキュメント検索システムを作りやすくなりそうですが、これについてはまた別の機会にします。

今後はRDocも記述力が高まったりメタ情報の扱いが改良されていくのかもしれませんが、現時点ではYARDの方がより実践的な機能を持っているといえるでしょう。ただし、ドキュメント生成速度はRDoc 3の方が圧倒的に速いです*13

まとめ

Ruby用のドキュメントツールであるRDocとYARDについて比較しました*14。YARDの方がよさそうに思えるように書いているので、YARDを使いたくなったかもしれません。次こそはYARDの使い方を紹介できるかもしれません。

*1  他にもsdocとかあったりします。

*2  今はGitHubのリポジトリに移動しています。

*3  つまり、RDocがRuby本体のリポジトリと独自リポジトリの複数のリポジトリに存在するようになったのもこの頃です。RDocは今でも標準添付ライブラリなので、RDocのリポジトリを更新するだけではなく、Ruby本体のリポジトリのRDocも更新する必要があります。これは、新しいバージョンをリリースしたタイミングなどでごっそりRuby本体のリポジトリのRDocを上書きするという方法で行われています。これに関してはいろいろ意見がある人もいるので、このあたりに興味がある人は、Rubyの開発を見ていたり参加したりしているまわりの人に聞いてみましょう。

*4  整形済みテキスト用のマークアップはあります。

*5  RDocではメタメソッドと呼んでいるようです。

*6  Doxygenなら\param、GTK-Docなら@引数名

*7  Doxygenなら\return、GTK-DocならReturns:

*8  Doxygenなら\since、GTK-Docなら@since

*9  Doxygenなら\deprecated、GTK-Docなら#ifdef ... #endifから自動抽出。

*10  ドキュメントの生成速度はだいぶ速くなっているという印象です。

*11  Doxygenは\sinceでも@sinceでもどちらでも書けます。

*12  RDocでもできるようです。

*13  ここで「YARDに速度改善パッチを送れるなぁ」と考えられる人はいいセンスを持っていますよ。:-)

*14  偏った視点が含まれているので、自分が必要な機能に関する部分は念のため自分で本家の情報を確認することをオススメします。

タグ: Ruby
2011-05-11

リファレンスマニュアルの記述方法

Rubyではライブラリのリファレンスマニュアル作成のドキュメントツールとしてRDocが標準となっています。これは、古くからあるという理由とRuby本体に標準添付されているという理由からです。しかし、RDocはそれほど活発に開発されていないため、最近のドキュメントツールとして機能不足と言わざるをえません*1。どのような機能が足りないのかについては別の機会にします。

数年前からYARD(Yey! A Ruby Documentation Tool)というドキュメントツールが開発されています。YARDはRDocとの互換性を残したまま機能を拡張しているため、RDocからの移行も容易です。実は、YARDは第2回フクオカRuby大賞(SSLの証明書の期限が切れているので警告がでます)に「Improving Documentation in the Ruby Community」というタイトルで応募していたので知っている人もいるのではないでしょうか*2

そこで、ドキュメントツールとしてRDocではなくYARDを使う方法を紹介します。と、いきたいところですが、その前にプログラミング言語に依存しないレベルでライブラリのリファレンスマニュアルの記述方法について振り返っておきます。

記述方法

ライブラリのリファレンスマニュアルを記述する方法には大きく分けて以下の2つの方法があります。

  1. ソースコードの中にドキュメントも埋め込む
  2. ソースコードとは別にドキュメントを記述する

ソースコードに埋め込む方式でも、インターフェイスを記述しているファイル(CやC++ならヘッダーファイル)に埋め込む方式や実装を記述しているファイルに埋め込む方式などいくつか違いがあります。また、コメントとしてドキュメントを記述する方式の他にも、言語が提供するdocstringという仕組みを利用する場合もあります*3。これらは採用しているドキュメントツールや言語などに依存することなので、ここでは深く考えないことにします。

ソースコードに埋め込む方式を採用しているドキュメントツールはDoxygenJavadocGTK-Docなどです。RDocやYARDもこの方式です。この方式の方がソースコードと分離する方式よりもメジャーです。分離方式ではなくこの方式を採用しているドキュメントツール・プロジェクトの方が多いです。

ソースコードとは別に記述する方式を採用しているドキュメントツールはSphinxBitClustTexinfo、RDtool*4などです。Sphinxを利用しているプロジェクトはPythonなどです。BitClustを利用しているプロジェクトはRubyの日本語リファレンスマニュアルを整備しているるりまプロジェクトです。Texinfoを利用しているプロジェクトはGaucheなどです。RDtoolを利用しているプロジェクトはRuby-GNOME2プロジェクトなどです。

分離方式は、ドキュメント量が大きいプロジェクトや、より厳密に公開したいAPIだけを選別したいプロジェクトのリファレンスマニュアルを作成する場合に使われることが多いのかもしれません。例えば、プログラミング言語を開発しているプロジェクトにはそういうニーズが多いのかもしれません。また、動的に生成するコードのドキュメントはソースコード中に対応するドキュメントを埋め込めません*5。この場合は埋め込み方式は使えないため、埋め込み方式でなんとかやりくりするかこの方式を利用します*6。これについては後述します。

記述方法によるメリット・デメリット

ソースコードに埋め込む方式と分離する方式ではそれぞれにメリットとデメリットがあります。これらについて検討して自分のプロジェクトにあった方式を選びましょう。「どちらでもいいな」と思ったらよりメジャーな埋め込み方式を選ぶとよいでしょう。

埋め込み方式のメリット・デメリット

ソースコードに埋め込む方式のメリット・デメリットは以下の通りです。

メリット
  • ソースコードの近くにドキュメントがあるので、ソースコードだけ変更してドキュメントの変更を忘れるということを防ぎやすい*7
  • ドキュメントを書いていなくてもドキュメント対象(メソッドなど)を自動的に収集してくれるため、ドキュメントが不足していても多少は役に立つことがある。
デメリット
  • ソースコードファイル中にコードよりもドキュメントの方が多くなってしまってコードが読みにくくなる(と感じる場合がある)*8
  • 自動でドキュメント対象が収集されるため、意図していないAPIがドキュメント化されてしまうことがある。
  • プログラミングとドキュメント作成を分業しづらい。
  • ドキュメントツールだけの仕組みでは複数の(自然)言語用のドキュメントを作成できない*9

埋め込み方式では網羅的にAPIのリファレンスマニュアルを整備しやすくなります。よって、すでにソースコード中にドキュメントを記述するスタイルの場合や特にこだわりのない場合はこの方式を採用するとよいでしょう。

ただし、同じ方法で英語と日本語など複数の言語向けのリファレンスマニュアルを作成することはやめた方がよいです。この方式で複数の言語をサポートする場合はドキュメント中に「言語タグ」のようなものを仕込んで、対応する言語のドキュメントをすべてソースコード中に記述することになります。例えば以下のようになります。

1
2
3
4
5
# @en logs message on debug mode.
# @ja デバッグモードのときだけmessageを出力する。
def debug(message)
  puts message if $DEBUG
end

しかし、このやり方にはいくつも問題があります。まず、このやり方に対応したドキュメントツールがありません。また、あったとしても、メリットの1つである「ソースコードとドキュメントの不整合を防ぎやすくなる」を実現できなくなります。これは、ソースコードを変更する人がすべての言語のドキュメントを書けるわけではないからです。例えば、GNOMEは174の言語で利用できます*10が、GNOMEの関係者全員がすべての言語を読み書きできるわけではありません。GNOMEは特に多言語サポートが進んでいるプロジェクトですが、これほどでなくても、対応する言語が3言語以上になったらソースコードを書きながらドキュメントも整備することは無理でしょう。

なお、より現実的に複数の言語に対応する方法については別の機会に紹介します。

ドキュメント分離方式のメリット・デメリット

ソースコードとドキュメントを分ける方式のメリット・デメリットは以下の通りです。

メリット
  • 公開したいAPIだけを選別して公開しやすい。
  • 開発とは別のペースで進めやすい。
  • 複数の(自然)言語をサポートしやすい*11
デメリット
  • ソースコードの更新に追従するために変更分を確認するツールが必要になる。
  • ドキュメント化するAPIを収集するツールが必要になる。

埋め込み方式のドキュメントツールにはAPI収集機能が確実についています。それと同じようなAPI収集機能を用意できるのならば、小さなプロジェクトでも分離方式を採用できます。Ruby-GNOME2プロジェクトはAPIを収集するツールを作ってこの方式を採用しています。

プロジェクトに関わる人数が多くなってきたり、複数の言語に対応したい場合はこの方式のメリットが大きくなるかもしれません。そうでない場合は埋め込み方式で十分でしょう。

まとめ

ドキュメントツールとしてRDocではなくYARDを使う方法と、複数の言語に対応したリファレンスマニュアルの作成方法を書くつもりだったのですが、その予備知識としてリファレンスマニュアルの記述方法に書いたら長くなってしまったのでそれだけで一区切りとしました。

読みやすく利用しやすいリファレンスマニュアルを作成するためにも、使いやすく書きやすいドキュメントツールを採用したいですね。

*1  Ruby 1.8に標準添付されていた頃のTest::Unitみたいですね。

*2  受賞はしていません。RubyやRuby周辺をよくするツールが評価される機会がもっと増えるといいですね。

*3  Lisp系の言語やPythonなど

*4  =beginと=endを使うことにより埋め込み方式でも利用可能です。Yuguiさん、ありがとうございます!ただ、メソッドを抽出する機能がないので他の埋め込み方式よりは不便です。

*5  最新のYARDではこのケースにも対応できる仕組みを提供しています。

*6  RubyやLispでevalしたりCやLispでマクロを使う場合など。

*7  確実に防げるわけではないことに注意。ソースコードとドキュメントが違うことを言っていて苦労した覚えはありませんか?

*8  ドキュメントの中にコードがある状態。

*9  少なくとも現実的ではない

*10  2011/05/05現在。

*11  ただし、言語毎にファイルなどを分けている場合に限る。Gaucheは1ファイル中に英語と日本語を書いているためそれ以上の言語のサポートは難しい。

2011-05-05

最新
2008|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|
タグ:
RubyKaigi2008Speaker
RubyKaigi2009Sponsor
RubyKaigi2009Speaker
SapporoRubyKaigi02Sponsor
SapporoRubyKaigi02Speaker
RubyKaigi2010 Sponsor RubyKaigi2010 Speaker RubyKaigi2010 Committer badge_speaker.gif RubyKaigi2010 Sponsor RubyKaigi2010 Speaker RubyKaigi2010 Committer