PerlMotion

最近、PerliOSのアプリを作れるPerlMotionというプロダクトがリリースされました。個人的にRubyMotionを使っていて、テキストエディタとコマンドラインでiOSアプリを作る楽しさみたいなものを知ってしまったので、早速、試してみました。RubyMotionは残念ながらOSSではないので、中身を見ることはできないのですが、PerlMotionは全てOSSとして公開されています。

インストール方法

homebrewで最新のllvmをインストールします。ただ手元の環境だと普通にllvmをインストールしてもその後に必要になるCompiler::CodeGenerator::LLVMがインストールできなかったので、以下のサイトの手順に従って、最新のlibc++とllvmをインストールしました。

Homebrew で最新の libc++ と clang をビルドする

$ brew instal https://raw.github.com/rhysd/homebrew/13dbf9d3af83297eec66eeee8e579d82ab598da2/Library/Formula/llvm.rb --HEAD --with-clang --with-libcxx --disable-assertions

llvm以外で必要なライブラリをインストールします。

$ brew install reattach-to-user-namespace
$ brew install ios-sim

PerlMotionのgitリポジトリをcloneして、carton installすればインストールは完了です。(cartonやcpanmは事前に入れておく)

$ git clone https://github.com/goccy/perl-motion.git
$ cd perl-motion
$ carton install

carton installでエラーが出たのですが、Compiler::*のモジュールでSuccessfully installedと表示されていればインストールは完了しています。cpanfileのrequiresにgit repoを書いた場合は、今のところこういう状態になりますが、インストール自体は完了しているので、このまま説明を進めます。

とりあえずデモを動かしましょう。example/Helloディレクトリに移動してbuildコマンドを実行します。

$ cd example/Hello
$ ../../bin/perl-motion build

これでiOSシミュレータが起動すれば問題なくBuildできています。ここでperl-motionコマンドのPATHを通しておきましょう。

アプリの作り方

アプリの作り方を簡単に説明します。新規にアプリを作るには、createコマンドを実行します。

$ perl-motion create Test

これでアプリのひな形ができました。まずTestディレクトリにあるapp.confを見てみましょう。これはYAML形式のファイルで、app_nameにアプリ名、delegateにAppDelegateクラスを書きます。デフォルトでは、Test::AppDelegateクラスとなっています。

---
app_name: Test
delegate: Test::AppDelegate

アプリ本体は、lib配下にモジュールとして実装していきます。lib/Test/AppDelegate.pmを見てみましょう。

package Test::AppDelegate;
use base 'UIApplicationDelegate';
use UIWindow;
use UIScreen;
use Test::RootViewController;

# this method is entrypoint of your application
sub application {
    my ($app, $options) = @_;

    my $window = UIWindow->new()->init_with_frame(UIScreen->main_screen->bounds); 
    $window->root_view_controller(Test::RootViewController->new);
    $window->root_view_controller->wants_full_screen_layout(1);
    $window->make_key_and_visible;
    $app->window($window);
}

1;

アプリが起動するとAppDelegateクラスのapplicationメソッドが呼ばれます。ここで$appと$optionsが引数で渡されます。$appというのは、UIApplicationのインスタンスで、ここですることはUIWindowのオブジェクトを生成して、RootVIewControllerを設定することです。RootViewControllerというのは、一番最初に画面に表示する処理を書くControllerです。lib/Test/RootViewController.pmは次の通りです。

package Test::RootViewController;
use base 'UIViewController';
use UITableView;

sub load_view {
    my ($self) = @_;
    my $table_view = UITableView->new();
    $self->view($table_view);
}

1;

全てのコントローラは、UIViewControllerを継承します。画面に表示するViewを自前で生成したい場合は、load_viewメソッドをオーバーライドします。ここではUITableViewを設定しています。この状態でbuildすると真っ白なテーブルビューが表示されます。

モジュールの実装方法

Obj-Cの機能を持ったオブジェクトをPerlMotionで使いたい場合、普通にObj-Cのクラスとして実装します。先ほどuseしていたUITableViewは、perl-motion/lib/PerlMotion/Builder/PerlCompiler/UITableView.mに実装されています。 中身は普通にObj-Cのクラスであることがわかります。ただ、このディレクトリにモジュールを作っただけではモジュールを使えません。PerlCompilerのランタイムにモジュールとメソッドを登録する必要があります。UITableView.mでは、UITableView_setup関数でモジュールとメソッドを登録しています。このUITableView_setupをperl_motion_core_libs_common.mのstore_ios_native_library関数で呼ぶことでモジュールを使えるようになるようです。

デリゲートメソッドのオーバーライド

現状だとPerlMotion側からObj-Cのメソッドを直接呼ぶ方法はないようです。load_viewやapplicationのようにデリゲートメソッドをオーバーライドしたい場合は、PerlMotion側であらかじめメソッド名を決めておき、Obj-Cでデリゲートメソッドを全てオーバーライドしておいてから、あらかじめ決めておいたメソッドを呼び出すという実装をするようです。

RubyMotionとの比較

RubyMotionとPerlMotionは、llvmの機械語にコンパイルするという仕組みは同じだと思うのですが、RubyMotionは、RubyのオブジェクトとObj-Cのオブジェクトを透過的に扱えます。PerlMotionは今のところObj-Cの機能を使うには、Obj-Cを書く必要があります。このあたりはモジュールを書いていけば、基本的な機能はそろうのではないかと思っています。

まとめ

PerlMotionは、今のところ機能が足りないので、iOSアプリを作ったことがあってPerlがわかる人は開発に参加すると面白いのではないかと思います。

追記

との事なので、自前でブリッジを書かなくてもよくなりそうですね!