2010年1月10日日曜日

大忙しの一週間。アンドロイド、Maven、Rake、C拡張、そして…

原文: チャールズ=オリバー=ナター

(最後のブログ記事からどれ位経ったでしょうか?正解は「長い間」。カンファレンス続きで大忙しだった秋が終ったので、もっとブログを書くつもりです。これからは、一月に三つも会議に出かけないように忠告して下さい。)

やあ!この一週間はとても忙しかったです。でも、僕らは元気でせっせとコード書いてるって解るように、JRubyで何が起こってるかを見ていきましょう。

アンドロイド


今週の頭にJan Berkelの手伝いをやってRuboto IRBを最新のアンドロイド携帯環境で走らせる事に成功しました。細かい手直しが二つ三つ必要だったのと、Janが手伝うのに興味があるというので、この変更を追加して彼をRubotoのコミッタに追加しました。

Ruboto IRBのレポジトリはこちら→http://github.com/headius/ruboto-irb

最近、アンドロイド上で動くJRubyに対する私の興味が増してきました。極最近の事ですが、JRubyはJVMで動くメジャーな言語の内ではアンドロイド携帯で動いている間に新規のコードを作って動かす事が出来る凡そ唯一の言語なのだと思い至ったんです。GroovyやScalaやClojureでは双方向型のシェルを造るのは不可能。というのも、これらの言語はソースコードを一旦JVMのバイトコードにコンパイルする必要があって、JVMのバイトコードはDalvikのVMでは直接には動かないからです。


今週Ruboto IRBをいじくってて、もっと面白い事に気がつきました。以前にJRubyがアンドロイドで上手くいかなかった原因となっていたバグのほとんど全てが解消されていたのです!特筆すべきはandroid.*で現されるクラスにリフレクションが、アンドロイド1.6とアンドロイド2.0両方に備わった点が挙げられます。これがどうして凄いか、っていうと、Ruboto IRBを使うことでアンドロイドAPIの何でも弄くる事が出来るからです。



この例はアンドロイドActivity(Ruboto IRBの中のIRBクラス)にアクセスして、新しいWebViewインスタンスを造り、ちょっとしたHTMLをロードしてWebViewの中身を入れ替えています。それもユーザからのインプットを使って。携帯の上で。凄いです。



皆さんが、このRubotoの凄い力を悪用することなく、善の為だけに使ってくれると信じています。

RubyGemsとMavenの連携


JRubyの第一の使命はRubyの実装です。その結果、Javaプラットフォームとの統合を蔑(ないがし)ろにすることが時としてありました。でも、Ruby 1.8.7との互換性がガッチリとしてきて、1.9への取り組みが本格的になってきた今、Javaに再び目を向ける時がやって来ました。

プログラミング言語との統合を図る上で欠かせないのが、その言語を取り巻くツールをどうサポートするかです。そして、Javaでツールと言えば、必ずMavenが絡んできます。

一年ほど前、MavenのアーティファクトをRubyGemsに取り入れるプロジェクトを始めました。MavenのアーティファクトとRubyGemsの対応は簡単に解ると思います。どちらにも依存性、名前、叙述、個別ID、バージョン、そして各々のパッケージを記述する決まったフォーマットが有ります。maven_gemプロジェクトは、この二つの世界の融合が可能であることを証明するものです。

maven_gemのレポジトリはここ→http://github.com/jruby/maven_gem

このプロジェクトはこの秋に私が再び触れるまで埃を被ったままでしたが、Sonatypeの人たちに興味を持ってもらえたのをきっかけに、急速な進歩を遂げています。

SonatypeのTamas Cservenak氏の御陰で、不可能だと一度は諦めていた事も可能になりました。それは、RubyGemsと全てのMavenアーティファクトとの完全な融合です。

Nexus RubyGemsのレポジトリはここ→http://github.com/cstamas/nexus-ruby-support


~/projects/jruby ➔ gem install com.lowagie.itext-rtf
Successfully installed bouncycastle.bcmail-jdk14-138-java
Successfully installed bouncycastle.bcprov-jdk14-138-java
Successfully installed bouncycastle.bctsp-jdk14-138-java
Successfully installed com.lowagie.itext-rtf-2.1.7-java
4 gems installed
Installing ri documentation for bouncycastle.bcmail-jdk14-138-java...
Installing ri documentation for bouncycastle.bcprov-jdk14-138-java...
Installing ri documentation for bouncycastle.bctsp-jdk14-138-java...
Installing ri documentation for com.lowagie.itext-rtf-2.1.7-java...
Installing RDoc documentation for bouncycastle.bcmail-jdk14-138-java...
Installing RDoc documentation for bouncycastle.bcprov-jdk14-138-java...
Installing RDoc documentation for bouncycastle.bctsp-jdk14-138-java...
Installing RDoc documentation for com.lowagie.itext-rtf-2.1.7-java...


これを使ってRhinoをインストールし、それをirbで使うとこんな感じです。
http://gist.github.com/271764

この事がJRubyユーザにとって意味する事は重大です。JRuby 1.5以降では、公にアクセス出来るMavenレポジトリから、Javaのライブラリを、インストールまたは依存するライブラリの一つとして利用する事が出来るようになるのです。端的に言うと、6000を超える数の新しいライブラリをすぐに使えるということです。凄いでしょう?

このプロジェクトはもう幾つか不具合(例えば、RubyGems自体が6000ものgemを含む索引を生成するのに苦労する点)がありますが、テスト用のサーバは既に動いています。JRuby 1.5RC1がリリースされるまでにはこのような点は解消するつもりです。興味のある人はJRubyメーリングリストへ是非参加して下さい。

Rake?Ant?両方やろう!


Javaとの統合についてのもう一つ触れておきたいのがトム=エネボ氏がやっている、Rake(Rubyにおけるビルドのツール)とAntをシームレスに、相互に統合するプロジェクトです。これには以下の三つの側面が有ります。

  • RakeのタスクをAntで、逆にAntのタスクをRakeで使う。

  • RakeのターゲットをAntから、逆にAntのターゲットをRakeから呼び出す。

  • RakeとAntの両方を混ぜ合わせたビルド方式の構築



トムの作業はこれまでの所、第一点に焦点を合わせていましたが、他の二点についても作業が進んでいます。近いうちに、AntのスクリプトをRake用に書き換えて何の修正も加える事なく使えるようになったり、AntからRakeを呼び出したり、RakefileをAntターゲットの一つとして使用したり、といった事が可能になります。

Rakeからbuild.xmlの内容を導いて、ターゲットに拠ってはAntのタスクを呼び出すような例がこれです。


require 'ant'

ant.load 'build.xml' # defines tasks :mkdir + :setup in ant!

task :compile => [:mkdir, :setup] do
ant.javac(:srcdir => src_dir, :destdir => "./build/classes") do
classpath :refid => "project.class.path"
end
end


理想的には、統合する上で考えられるあらゆる場合にも対応して、RakeとAntの境界線をあやふやな物にしたいと考えています。ゆくゆくはJRubyのビルドをRakeに移す事が出来れば、皆が喜ぶでしょう。これもJRuby 1.5でリリースする予定です。

C拡張の問題


後回し後回しにしてきたRubyの側面の一つが、C拡張です。C拡張のユーザやデベロッパへの悪意からそうしていたのでは決して有りません。何かのスイッチ一つでC拡張が魔法のように使えるようになったらどんなにか素晴らしいでしょう。問題なのは、RubyのC拡張のAPIがオブジェクトの内側を露呈し過ぎてしまって、そのようなAPIを小さいコストで提供するのが不可能であるという事。(なぜかというと、一つ一つの操作にメモリをコピーする必要が生じてしまうから。)

代替案として模索しているのは、「C拡張APIのうち、『安全』な物をサポートし、『危険』な物については、それに取って代わる物を提供しよう」というもの。これを実現する為、ウェイン=マイスナー氏によりC拡張APIとの繋ぎとなるライブラリがgithubに発表されました。

レポジトリはここ→http://github.com/wmeissner/jruby-cext

昨晩ちょっとこれに時間を割いてMac OS Xで動かしてみました。自分でやって驚いたんですが、(非常に)些細な物を動かす事が出来ました!

Cで書かれている部分がこれ。MRI用に書くのとちっとも変わりません。


#include <stdio.h>
#include <ruby.h>

VALUE HelloModule = Qnil;
VALUE HelloClass = Qnil;

VALUE say_hello(VALUE self, VALUE hello);
VALUE get_hello(VALUE self);

void
Init_defineclass()
{
HelloClass = rb_define_class("Hello", rb_cObject);
rb_define_method(HelloClass, "get_hello", get_hello, 0);
rb_define_method(HelloClass, "say_hello", say_hello, 1);
}

VALUE
say_hello(VALUE self, VALUE hello)
{
return Qnil;
}
VALUE
get_hello(VALUE self)
{
return rb_str_new2("Hello, World");
}


これを読み込んで実行するRubyのコードがこれ。ModuleLoaderについての部分は最終のリリースバージョンではrequire/loadとして隠してしまう予定である事に注意して下さい。


require 'java'

m = org.jruby.cext.ModuleLoader.new
m.load(self, "defineclass")

h = Hello.new
puts "Hello.new returned #{h.inspect}"
puts "h.get_hello returns #{h.get_hello}"


C拡張APIのうち、JRubyではサポートする予定のないのは、RSTRING、RARRAY、RHASH等の文字配列、配列、ハッシュの内側へのアクセスを可能にする物や、Rubyのスレッドやランタイムに関する物などです。つまり、JNI(JVMのC拡張API)にそぐわない物はサポートする予定はありません。

これはC拡張を使用するユーザが主導のプロジェクトです。JRubyにおけるC拡張APIの実現に興味があるのなら、是非僕らに協力して下さい。僕らはJavaとRubyのサポートに忙しいばかりでなく、C拡張を書く事自体にはあまり慣れていません。上に挙げたレポジトリを覗いてみて、JRubyのメーリングリストに参加してください。力を合わせてやっていきましょう。

2010年のJRuby


この他にも2010年のJRubyには目玉が一杯です。コンパイルしたり、シリアル化したり、注釈を付けたり、設定ファイルで指し示す事が出来る、「本物」のJavaクラスをRubyのコードで作り出す事が可能になるでしょう。JRubyを商用している人達向けに、サポートの提供(バグの優先順位の決定等の参考にします)も始める予定です。Engine Yard CloudからJRubyを使った(Ruby以外のライブラリや、Java、Scala、Clojureのコードをも使える)手軽なクラウド商品も発売されます。そして、漸くJRubyの本も書きます。これにはチュートリアルや、リファレンス一覧、トラブルシューティングのヒント等、JRubyを今使いこなす為に必要な事項を盛り込む予定です。

素晴らしく、そしてワクワクする一年になりそうです。

0 件のコメント:

コメントを投稿