mrubyの初手

#mruby

環境構築からmrubyを実行するCのコードをビルドするまで。

環境構築

$ mkdir hello-mruby
$ cd hello-mruby
$ vi Dockerfile
+FROM ruby:1.9
+RUN apt update && \
+  apt install -y bison --no-install-recommends && \
+  git clone https://github.com/mruby/mruby && \
+  cd mruby && \
+  ./minirake
+ENV PATH /mruby/bin:$PATH
+CMD ["bash"]
  • ドキュメントを読むと、mrubyのビルドにはRuby 1.8か1.9、gcc、ar、bisonが必要とのことだった。ruby:1.9のイメージをベースにして、入ってなかったbisonだけインストールした。
  • ./minirakeでmrubyがビルドされる。bin/以下にmrbcなどがあるのでPATHに追加しておく。
$ docker build . -t naoty/hello-mruby
$ docker run -it --rm naoty/hello-mruby
% mirb
mirb - Embeddable Interactive Ruby Shell

> MRUBY_VERSION
 => "2.0.1"
> exit
% exit
  • Dockerでmrubyをビルドできたことを確認した。

サンプルコードを追加する

$ vi Dockerfile
 FROM ruby:1.9
 RUN apt update && \
   apt install -y bison --no-install-recommends && \
   git clone https://github.com/mruby/mruby && \
   cd mruby && \
   ./minirake
 ENV PATH /mruby/bin:$PATH
+WORKDIR /hello-mruby
+COPY . /hello-mruby/
 CMD ["bash"]
  • サンプルコードを用意していくのでWORKDIRを用意する。
$ vi hello.rb
+puts "Hello, mruby!"
$ docker build . -t naoty/hello-mruby
  • サンプルコードを追加してDockerイメージに追加する。
$ docker run -it --rm -v $(pwd):/hello-mruby naoty/hello-mruby
% mrbc hello.rb
% exit
  • カレントディレクトリをマウントしてイメージを起動する。
  • mrbcでhello.rbからhello.mrbを生成する。マウントしているので、ホストにもhello.mrbが追加されている。

Cからmrubyを実行する

$ vi hello.c
+#include <mruby.h>
+#include <mruby/dump.h>
+#include <stdio.h>
+
+int main() {
+  mrb_state *mrb = mrb_open();
+
+  FILE *fd = fopen("hello.mrb", "r");
+  mrb_load_irep_file(mrb, fd);
+
+  mrb_close(mrb);
+
+  return 0;
+}
  • 生成したhello.mrbを実行するCのコードを書く。
  • Cのコードは雰囲気で書いてるけど、mrb_openmrb_closeはお約束みたいで、mrb_load_irep_fileによってmrbファイルをloadするっぽい。
$ docker run -it --rm -v $(pwd):/hello-mruby naoty/hello-mruby
% gcc hello.c -I/mruby/include -L/mruby/build/host/lib -lmruby -lm -o hello
% ./hello
Hello, mruby!
  • 書いたCのコードをビルドするため、もう一度Dockerイメージを起動する。
  • hello.cgccでビルドするには、まずヘッダーファイルmruby.hのパスを指定する必要がある。mrubyのヘッダーファイルは/mruby/include/以下にあるので、-Iオプションで指定している。
  • 次に、mruby本体のソースコードとともにhello.cをビルドする必要がある。mrubyのライブラリは/mruby/build/host/lib/libmruby.aなので、-Lオプションにパスを指定し、-lオプションでmrubyを指定している。
  • また、ビルドすると/mruby/src/numeric.c:321: undefined reference to 'round'のようなエラーが出てしまう。Mathのライブラリが足りなさそうなので、-lmオプションをつけてlibm.soをリンクしている。
  • 無事にビルドできた実行可能ファイルを実行してみると、hello.rbで書いたコードが実行された。

追記

とのことなので、ベースイメージをruby:2.6にしてみたけど問題なく上記の手順ができた。