mruby on Tizen 2.0

さて、いきなりマニアックな話題で。

最近は仕事で Tizen というモバイル OS 向けの Native プログラムを C++ で書いてたりします。

コンパイラは -std=c++0x オプションを受け付けてくれたりするので多少は現代的なプログラミングができているのでその点は楽しいです。

しかし、Tizen プラットフォームのコードはちょっと古くさい規約で書かれている(たとえばテンプレートとか例外は使用していないし、イベントハンドラとかの書き方は古き良き Java っぽい)ので、文字列処理とか I/O がからむ処理とかはかなり面倒、非同期処理にいたっては、(ry なわけです。

そんなときにはやっぱり Ruby が懐かしくなるわけですね。

Tizen はかなり Pure な Linux 環境という印象なので、Ruby(CRuby)も動いちゃいそうな気はしますが、TPK(Tizen のパッケージ。Android でいう APK みたいなもの)にパッケージングして配布したりすることを考えると、mruby のように自分のパッケージの中に組み込みやすそうなもののほうが良さそうです。

というわけで mruby をビルドしてみました。

以下の内容を build_config.rb の末尾にくっつけてビルドしました:

TIZEN_SDK = "#{ENV['HOME']}/tizen-sdk"
TIZEN_GCC_I386_TOOLCHAIN_BASE = "#{TIZEN_SDK}/tools/i386-linux-gnueabi-gcc-4.5"
TIZEN_GCC_I386_BIN = "#{TIZEN_GCC_I386_TOOLCHAIN_BASE}/bin"
TIZEN_GCC_I386_EMULATOR_BASE = "#{TIZEN_SDK}/platforms/tizen2.0/rootstraps/tizen-emulator-2.0.cpp"
#TIZEN_GCC_I386 = "#{TIZEN_GCC_I386_TOOLCHAIN_BASE}/i386-linux-gnueabi"
#TIZEN_GCC_I386_LIB = "#{TIZEN_GCC_I386_TOOLCHAIN_BASE}/lib/gcc/i386-linux-gnueabi/4.5.4"

MRuby::CrossBuild.new('tizen-x86') do |conf|
  toolchain :gcc

  # Use standard print/puts/p
  conf.gem "#{root}/mrbgems/mruby-print"

  # Use Process class and Kernel $$, ::exit, ::fork, ::sleep, ::system
  conf.gem :git => 'https://github.com/iij/mruby-process.git'

  # Generate mirb command
  conf.gem "#{root}/mrbgems/mruby-bin-mirb"

  # Generate mruby command
  conf.gem "#{root}/mrbgems/mruby-bin-mruby"

  conf.cc.command = "#{TIZEN_GCC_I386_BIN}/i386-linux-gnueabi-gcc"
  conf.cc.flags << "-O0 -g3 -Wall -c -fmessage-length=0 -fPIE " +
    "--sysroot=\"#{TIZEN_GCC_I386_EMULATOR_BASE}\" " +
    "-I\"#{TIZEN_GCC_I386_EMULATOR_BASE}/usr/include\" " +
    "-I\"#{TIZEN_GCC_I386_EMULATOR_BASE}/usr/include/libxml2\" " +
    "-I\"#{TIZEN_GCC_I386_EMULATOR_BASE}/usr/include/osp\" " +
    "-I\"#{TIZEN_SDK}/library\" " +
    "-D_DEBUG"

  conf.linker.command = "#{TIZEN_GCC_I386_BIN}/i386-linux-gnueabi-g++"
  conf.linker.flags << "-Xlinker --as-needed -pie -lpthread -Xlinker -rpath=\$$ORIGIN/.. " +
    "-Xlinker -rpath=\$$ORIGIN/../lib -Xlinker -rpath=/home/developer/sdk_tools/lib " +
    "--sysroot=\"#{TIZEN_GCC_I386_EMULATOR_BASE}\" " +
    "-L\"#{TIZEN_GCC_I386_EMULATOR_BASE}/usr/lib\" " +
    "-L\"#{TIZEN_GCC_I386_EMULATOR_BASE}/usr/lib/osp\" " +
    "-losp-appfw -losp-uifw -losp-image -losp-json -losp-ime -losp-net -lpthread " +
    "-losp-content -losp-locations -losp-telephony -losp-uix -losp-media -losp-messaging " +
    "-losp-web -losp-social -losp-wifi -losp-bluetooth -losp-nfc -losp-face -losp-speech-tts " +
    "-losp-speech-stt -losp-shell -losp-shell-core -lxml2"

  conf.archiver.command = "#{TIZEN_GCC_I386_BIN}/i386-linux-gnueabi-ar"

  conf.build_mrbtest_lib_only

  conf.gem 'examples/mrbgems/c_and_ruby_extension_example'
end


TIZEN_GCC_ARM_TOOLCHAIN_BASE = "#{TIZEN_SDK}/tools/arm-linux-gnueabi-gcc-4.5"
TIZEN_GCC_ARM_BIN = "#{TIZEN_GCC_ARM_TOOLCHAIN_BASE}/bin"
TIZEN_GCC_ARM_DEVICE_BASE = "#{TIZEN_SDK}/platforms/tizen2.0/rootstraps/tizen-device-2.0.cpp"
#TIZEN_GCC_ARM = "#{TIZEN_GCC_ARM_TOOLCHAIN_BASE}/arm-linux-gnueabi"
#TIZEN_GCC_ARMlib = "#{TIZEN_GCC_ARM_TOOLCHAIN_BASE}/lib/gcc/arm-linux-gnueabi/4.5.4"

MRuby::CrossBuild.new('tizen-arm') do |conf|
  toolchain :gcc

  # Use standard print/puts/p
  conf.gem "#{root}/mrbgems/mruby-print"

  # Use Process class and Kernel $$, ::exit, ::fork, ::sleep, ::system
  conf.gem :git => 'https://github.com/iij/mruby-process.git'

  # Generate mirb command
  conf.gem "#{root}/mrbgems/mruby-bin-mirb"

  # Generate mruby command
  conf.gem "#{root}/mrbgems/mruby-bin-mruby"

  conf.cc.command = "#{TIZEN_GCC_ARM_BIN}/arm-linux-gnueabi-gcc"
  conf.cc.flags << "-O0 -g3 -Wall -c -fmessage-length=0 -fPIE " +
    "--sysroot=\"#{TIZEN_GCC_ARM_DEVICE_BASE}\" " +
    "-I\"#{TIZEN_GCC_ARM_DEVICE_BASE}/usr/include\" " +
    "-I\"#{TIZEN_GCC_ARM_DEVICE_BASE}/usr/include/libxml2\" " +
    "-I\"#{TIZEN_GCC_ARM_DEVICE_BASE}/usr/include/osp\" " +
    "-I\"#{TIZEN_SDK}/library\" " +
    "-D_DEBUG"

  conf.linker.command = "#{TIZEN_GCC_ARM_BIN}/arm-linux-gnueabi-g++"
  conf.linker.flags << "-Xlinker --as-needed -pie -lpthread -Xlinker -rpath=\$$ORIGIN/.. " +
    "-Xlinker -rpath=\$$ORIGIN/../lib -Xlinker -rpath=/home/developer/sdk_tools/lib " +
    "--sysroot=\"#{TIZEN_GCC_ARM_DEVICE_BASE}\" " +
    "-L\"#{TIZEN_GCC_ARM_DEVICE_BASE}/usr/lib\" " +
    "-L\"#{TIZEN_GCC_ARM_DEVICE_BASE}/usr/lib/osp\" " +
    "-losp-appfw -losp-uifw -losp-image -losp-json -losp-ime -losp-net -lpthread " +
    "-losp-content -losp-locations -losp-telephony -losp-uix -losp-media -losp-messaging " +
    "-losp-web -losp-social -losp-wifi -losp-bluetooth -losp-nfc -losp-face -losp-speech-tts " +
    "-losp-speech-stt -losp-shell -losp-shell-core -lxml2"

  conf.archiver.command = "#{TIZEN_GCC_ARM_BIN}/arm-linux-gnueabi-ar"

  conf.build_mrbtest_lib_only

  conf.gem 'examples/mrbgems/c_and_ruby_extension_example'
end

mruby のバージョンは 2013年4月25日時点でクローンしたものです。
Tizen SDK は 2.0 の Public 版を利用しています。
mrbgems は print と process の 2 つしか組み込んでいません。
必要に応じてお好きなものを組み込んでください。


上記の設定内容でビルドしてエミュレータ上で動かしてみたところ:

(host)$ cd mruby
(host)$ ./minirake
(host)$ sdb -e push build/tizen-x86/ /opt/apps/mruby/
(host)$ sdb -e shell
sh-4.1# /opt/apps/mruby/bin/mruby -e 'system("cat /etc/tizen-release")'        
Tizen release 2.0.0 (Tizen)

このあとは、Native プログラムに mruby を組み込んで GUI アプリとかサービスアプリとかを作ってみたいと思います。それから、mruby で Tizen Native Framework を利用できる mruby-tizen 的なものを作ってみたいと思います。(風呂敷広げすぎ?)