以前少し触ったことはあったのですが、まともに触ったことがなかったのと、先日まつもとゆきひろさんとお話しさせていただいたときに mruby の話題もあったので、改めて mruby に触ってみました。とりあえず Mac 上で動かすところまでやってみたのでまとめてみます。
mruby とは
mruby とは組み込み等でハードウェアリソースが限られる環境でも動かせるように、メモリ消費量を小さくした Ruby 実装です。また、様々なアプリケーションにも組み込みやすくなっています。メモリ消費量を抑えるために実装されている機能は絞られていますので、普通の Ruby 実装では使えても mruby では使えないものも多くなっています。
mruby の開発は GitHub の下記リポジトリで行われています。
また、公式サイトも公開されています。
mruby 2.0.0 リリース
この記事を書いている数日前の 2018/12/11 に mruby 2.0.0 がリリースされていました。その前が 1.4.1 ですので、メジャーバージョンアップになります。
とりあえず動かしてみる
mruby でのコードの実行方法については下記サイトでも紹介されていまして、今回参考にさせていただきました。
Executing Ruby code with mruby
とりあえずデフォルトの構成で触ってみるということであれば、 mruby は rbenv でもインストールが可能です。下記のように rbenv のインストール可能なバージョンのリストに mruby 2.0.0 も既に含まれています。
$ rbenv install --list | grep mruby mruby-dev mruby-1.0.0 mruby-1.1.0 mruby-1.2.0 mruby-1.3.0 mruby-1.4.0 mruby-1.4.1 mruby-2.0.0
これをインストールします。
$ rbenv install mruby-2.0.0
Downloading 2.0.0.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/fa495898d51130c69480a13e90df5dc18cb1a9d9a31836268a895989d902048f
Installing mruby-2.0.0...
Installed mruby-2.0.0 to /Users/akanuma/.rbenv/versions/mruby-2.0.0
インストールされたら使用するバージョンを mruby 2.0.0 に設定します。
$ rbenv versions * system (set by /Users/akanuma/.rbenv/version) 2.0.0-dev 2.3.1 2.5.3 mruby-2.0.0 $ rbenv local mruby-2.0.0 $ rbenv version mruby-2.0.0 (set by /Users/akanuma/workspace/mruby_test/.ruby-version) $ ruby -v mruby 2.0.0 (2018-12-11)
mruby での REPL は mirb で、 irb を実行すると mirb が起動します。
$ irb
mirb - Embeddable Interactive Ruby Shell
>
irb と同じようにインタラクティブに mruby のコードを実行することができます。
> puts 'Hello World!' Hello World! => nil
ちなみに mirb での入力内容はコードが正しいかチェックされた後に、バイトコードにコンパイルされてから実行されているようで、二回のパースが必要ということのようです。
REPL 以外にも、もちろんコードを書いたファイルを実行することもできます。下記は hello.rb というファイル内のコードを実行する例です。
$ cat hello.rb puts 'Hello World!' $ ruby hello.rb Hello World!
この方法も、実行時に rb ファイルの内容がバイトコードにコンパイルされます。実行時のコンパイルを避けるため、あらかじめコンパイルしておくことも可能です。 mrbc というコンパイラを使ってコンパイルします。生成されたバイナリファイルを実行する時には、それがバイナリファイルであると示すために -b
オプションをつけて実行します。
$ mrbc hello.rb $ ls -l total 16 -rw-r--r-- 1 akanuma staff 98 Dec 15 12:21 hello.mrb -rw-r--r-- 1 akanuma staff 20 Dec 15 12:09 hello.rb $ ruby -b hello.mrb Hello World!
mrbgems
Ruby ではパッケージ管理システムとして RubyGems を使いますが、 mruby では gem コマンドはなく、 RubyGems の代わりに mrbgems を使用します。
$ gem
rbenv: gem: command not found
mrbgems では RubyGems のように gem コマンドでインストールしたり require で読み込むのではなく、ビルド時の設定ファイルに使用するライブラリを設定して一緒にコンパイルし、起動時に全てロードします。そのためにはソースコードからビルドする必要がありますので、 GitHub からソースコードを clone してきます。
$ git clone https://github.com/mruby/mruby.git
$ cd mruby
まずはそのままデフォルトの構成でビルドしてみます。ディレクトリの root で minirake
を実行します。
$ ./minirake
ビルドが成功すると、設定ファイルの内容に従って各環境用にビルドされたもののサマリが下記のように表示されます。 Included Gems の項目が、実際にコンパイルされた mrbgems の gem です。 mruby では環境に応じて必要なもののみを使えるように、 Ruby ではコア機能として組み込まれていたものも、 mruby では mrbgems として切り出して、必要に応じて使用するかどうかを切り替えられるようになっています。
Build summary: ================================================ Config Name: host Output Directory: build/host Binaries: mrbc Included Gems: mruby-metaprog - Meta-programming features for mruby mruby-io - IO and File class mruby-pack - Array#pack and String#unpack method mruby-sprintf - standard Kernel#sprintf method mruby-print - standard print/puts/p mruby-math - standard Math module mruby-time - standard Time class mruby-struct - standard Struct class mruby-compar-ext - Enumerable module extension mruby-enum-ext - Enumerable module extension mruby-string-ext - String class extension mruby-numeric-ext - Numeric class extension mruby-array-ext - Array class extension mruby-hash-ext - Hash class extension mruby-range-ext - Range class extension mruby-proc-ext - Proc class extension mruby-symbol-ext - Symbol class extension mruby-random - Random class mruby-object-ext - Object class extension mruby-objectspace - ObjectSpace class mruby-fiber - Fiber class mruby-enumerator - Enumerator class mruby-enum-lazy - Enumerator::Lazy class mruby-toplevel-ext - toplevel object (main) methods extension mruby-compiler - mruby compiler library mruby-bin-mirb - mirb command - Binaries: mirb mruby-error - extensional error handling mruby-bin-mruby - mruby command - Binaries: mruby mruby-bin-strip - irep dump debug section remover command - Binaries: mruby-strip mruby-kernel-ext - Kernel module extension mruby-class-ext - class/module extension mruby-bin-mrbc - mruby compiler executable ================================================
bin ディレクトリに mruby や mirb 等の実行ファイルが生成されますので、これを使ってみます。
$ bin/mirb mirb - Embeddable Interactive Ruby Shell > Time.now => Sat Dec 15 17:12:35 2018
Time クラスもコア機能としては含まれていませんが、 mruby-time gem が含まれているので、 Time クラスを使用することができています。試しに ENV
オブジェクトを使ってみると、 mruby では ENV はコアには含まれていないのでエラーになります。
> ENV (mirb):2: uninitialized constant ENV (NameError)
ENV
は mrbgems の mruby-env を組み込むことで使用できるようになりますので、 build_config.rb
に下記のように設定を追加します。
conf.gem :mgem => 'mruby-env'
config.gem での指定は、 gem のタイプによって少々異なります。今回は mgem-list に含まれているので、上記のように gem 名のみで使用可能です。
ちなみに複数の gem をひとまとめにしたものを GemBox と言い、デフォルトでは build_config.rb 内で default という GemBox が指定されていて、デフォルトで使用する gem が指定されています。
conf.gembox 'default'
では再度 minirake
でビルドします。
$ ./minirake
Build Summary をみると mruby-env が含まれているのがわかります。
Build summary: ================================================ Config Name: host Output Directory: build/host Binaries: mrbc Included Gems: mruby-env 〜〜〜以下略〜〜〜
下記のように実行してみると、 ENV モジュールが使用できるようになっています。
$ export DEBUG="TRUE" $ bin/mirb mirb - Embeddable Interactive Ruby Shell > ENV['DEBUG'] => "TRUE"
ちなみに mruby 2.0.0 での変更点の一つとして、メタプログラミング関連の機能は組込みシステム開発ではあまり使われないという前提のもと、 mruby-metaprog
という gem に切り出されました。
1.4.1 と 2.0.0 の違い
リリースノートの内容を参考に、 1.4.1 と 2.0.2 の違いを確認してみます。
2.0.0 では基本的な言語の機能として、キーワード引数に対応しています。サンプルとして下記のようなコードを書いて hello.rb
として保存します。
def hello(name: 'World') puts "Hello #{name}!" end hello(name: 'Hiro')
これを mruby 2.0.0 で実行すると下記のように正しく実行されます。
mruby_test $ ruby hello.rb Hello Hiro!
mruby 1.4.1 で試してみると下記のように Syntax Error になります。
$ ruby hello.rb hello.rb:1:15: syntax error, unexpected tLABEL_TAG, expecting ')' SyntaxError: syntax error
また、詳細は割愛しますが、下記の Core Libraries にもメソッドの追加等の変更が入っています。
mruby-kernel-ext
mruby-array-ext
mruby-string-ext
mruby-pack
mruby-sleep
mrbgems のところでも少し触れましたが、メタプログラミング関連の機能はコア機能から切り出されて、 mruby-metaprog という gem が追加されています。
その他メモリ使用量削減の対策が行われていたり、インタプリタにデバッグモード実行用のオプションや、ライブラリ読み込み用のオプションが追加されたりしています。詳細はリリースノートをご覧いただければと思います。
http://mruby.org/releases/2018/12/11/mruby-2.0.0-released.html
まとめ
組込み開発についてはまだまだ素人なのですが、Ruby が組込みでも使えるようになってくるとハードルが低くなってきますね。 mruby 2.0.0 になって Ruby にさらに近づいてきましたし、より開発しやすくなってそうです。実際に組込み開発で使うには、これをマイコン上で動かせるようにビルドしていったり、深く知っていく必要があるかと思いますが、少しずつでも掘り下げていければと思っています。