mrubyのメモ

いろいろおさわり中．随時追記します．

# バージョン
ソースはGithubからcloneしてきた．

```bash
$ git clone git@github.com:mruby/mruby.git
$ cd mruby
$ git log | head  -1
commit 4dac03cb2d53227bde2e5f50e70ca79596807e11
```

```bash
$ mruby -v
mruby 1.1.0 (2014-11-19)
```

# mrubyのビルド

```bash:
$ make
```

または

```bash:
$ ./minirake
```


```text:Build-Log
================================================                                                               
      Config Name: host
 Output Directory: build/host
         Binaries: mrbc
    Included Gems:
             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-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 - Enumerable::Lazy class
             mruby-toplevel-ext - toplevel object (main) methods extension
             mruby-compiler - mruby compiler library
             mruby-bin-mirb - mirb command
               - Binaries: mirb
             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-bin-mrbc - mruby compiler executable
================================================

================================================
      Config Name: host-debug
 Output Directory: build/host-debug
    Included Gems:
             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-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 - Enumerable::Lazy class
             mruby-toplevel-ext - toplevel object (main) methods extension
             mruby-compiler - mruby compiler library
             mruby-bin-mirb - mirb command
               - Binaries: mirb
             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-eval - standard Kernel#eval method
             mruby-bin-debugger - mruby debuggeer command
               - Binaries: mrdb
================================================
```

`build_config.rb` で定義された`MRuby::Build`に対応するビルドが実行される．
デフォルトだと、`MRuby::Build.new`と`MRuby::Build.new('host-debug')` が定義されているので、
それぞれビルドされている．

ビルドが終わると `bin/`の下に実行ファイルが、`build/`の下にライブラリが作成される．


# binの中身

```bash:
$ ls -l bin
total 7736
-rwxr-xr-x  1 tac  staff   850K  7 13 01:33 mirb*
-rwxr-xr-x  1 tac  staff   632K  7 13 01:33 mrbc*
-rwxr-xr-x  1 tac  staff   888K  7 13 01:33 mrdb*
-rwxr-xr-x  1 tac  staff   845K  7 13 01:33 mruby*
-rwxr-xr-x  1 tac  staff   644K  7 13 01:33 mruby-strip*
```

## mirb
`irb` に相当．実際は入力を都度バイトコンパイルして実行してるらしい

## mrbc
Rubyスクリプトをバイトコードにするコンパイラ．Rite形式またはC形式(配列)を出力する

```ruby:hello.rb

# -*- coding: utf-8 -*-
# Author::    TAC (tac@tac42.net)

puts "Hello,MRuby!!"
```

#### Rite形式

```bash:
$ mrbc --verbose hello.rb
00005 NODE_SCOPE:
00005   NODE_BEGIN:
00005     NODE_CALL:
00005       NODE_SELF
00005       method='puts' (218)
00005       args:
00005         NODE_STR "Hello,MRuby!!" len 13
irep 0x7f995140d7f0 nregs=4 nlocals=1 pools=1 syms=1 reps=0
file: hello.rb
    5 000 OP_LOADSELF   R1
    5 001 OP_STRING     R2      L(0)    ; "Hello,MRuby!!"
    5 002 OP_SEND       R1      :puts   1
    5 003 OP_STOP
```
Rite形式の `hoge.mrb` ができてる．


```bash:
$ od hello.mrb
0000000    044522  042524  030060  031460  026450  000000  063400  040515
0000020    055124  030060  030060  051111  050105  000000  044400  030060
0000040    030060  000000  040400  000400  002000  000000  000000  002000
0000060    100000  003000  000001  036400  100000  120000  000000  045000
0000100    000000  000400  000000  044015  066145  067554  046454  072522
0000120    074542  020441  000000  000400  002000  072560  071564  042400
0000140    042116  000000  000000  000010
0000147
```

#### C形式(配列)

`hello.rb` をシンボル`hello`の C配列にする．

```bash:
$ mrbc -Bhello hello.rb
```

`hello.c` ファイルができてる．

```c:hoge.c
/* dumped in little endian order.
   use `mrbc -E` option for big endian CPU. */
#include <stdint.h>
const uint8_t
#if defined __GNUC__
__attribute__((aligned(4)))
#elif defined _MSC_VER
__declspec(align(4))
#endif
hello[] = {
0x45,0x54,0x49,0x52,0x30,0x30,0x30,0x33,0x5e,0x45,0x00,0x00,0x00,0x67,0x4d,0x41,
0x54,0x5a,0x30,0x30,0x30,0x30,0x49,0x52,0x45,0x50,0x00,0x00,0x00,0x49,0x30,0x30,
0x30,0x30,0x00,0x00,0x00,0x41,0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x04,
0x06,0x00,0x80,0x00,0x3d,0x00,0x00,0x01,0xa0,0x00,0x80,0x00,0x4a,0x00,0x00,0x00,
0x00,0x00,0x00,0x01,0x00,0x00,0x0d,0x48,0x65,0x6c,0x6c,0x6f,0x2c,0x4d,0x52,0x75,
0x62,0x79,0x21,0x21,0x00,0x00,0x00,0x01,0x00,0x04,0x70,0x75,0x74,0x73,0x00,0x45,
0x4e,0x44,0x00,0x00,0x00,0x00,0x08,
};
```

これをコンパイル,リンクして組み込んで、

```c:Cのコード
extern const uint8_t hello[];
mrb_load_irep(mrb, hello);
```

とかって実行する．詳細は後述．

## mrdb
デバッガ．ruby -r debug とは若干動きが違う．

## mruby
`ruby` に相当．オプションなしでRubyスクリプト、または`-b`オプションでRite形式のバイナリを実行する．


```bash:
# ex) Rite形式のファイルを実行する
$ mruby -b hoge.mrb
```

## mruby-strip

```bash:
$ ./mruby-strip
no files to strip
Usage: ./mruby-strip [switches] irepfiles
switches:
  -l, --lvar   remove LVAR section too.
```



# クロスビルド
`build_config.rb` に設定を追加する．`MRuby::Build.new('hoge')`を追加することでビルドオプションの異なるバイナリをビルドできる．
ここにちょっと追加するだけでクロスビルドできる．すごい．



## `build_config.rb`
[ここ](https://github.com/mruby/mruby/tree/master/doc/compile)を読む．

途中のコメントを削るとこんなかんじ．

```ruby:build_config.rb
MRuby::Build.new do |conf|
  # load specific toolchain settings

  # Gets set by the VS command prompts.
  if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
    toolchain :visualcpp
  else
    toolchain :gcc
  end

  enable_debug

    conf.gembox 'default'
end


MRuby::Build.new('host-debug') do |conf|
  # load specific toolchain settings

  # Gets set by the VS command prompts.
  if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
    toolchain :visualcpp
  else
    toolchain :gcc
  end

  enable_debug

  # include the default GEMs
  conf.gembox 'default'

  # C compiler settings
  conf.cc.defines = %w(ENABLE_DEBUG)

  # Generate mruby debugger command (require mruby-eval)
  conf.gem :core => "mruby-bin-debugger"

  # bintest
  # conf.enable_bintest
end
```




# Cへの組み込み
`mrbc -B` で 出力したC配列を組み込んでみる．

1. `mruby/include` を `include` としてコピーしてくる
1. `mruby/build/{target}/lib/` を `lib` としてコピーしてくる
1. 以下のコード書く

```c:main.c
#include<stdio.h>

#include "mruby.h"
#include "mruby/compile.h"
#include "mruby/irep.h"

extern const uint8_t hoge[];

int main(int argc, char *argv[]){

  mrb_state* mrb;
  mrb = mrb_open();

  mrb_load_string(mrb,"puts 'Hello,World!'");
  mrb_load_irep(mrb, hoge);

  mrb_close(mrb);

  return 0;
}
```

ビルドして実行．

```bash:
$ gcc -Iinclude -o main main.c hoge.c lib/libmruby.a
$ ./main
Hello,World!
Hello,MRuby!!
```

# 参考文献などなど

+ https://github.com/mruby/mruby
+ http://www.kumikomi.net/archives/2012/12/ep17mrb3.php
+ http://harasou.github.io/2015/05/02/mruby-%E3%82%92%E3%81%95%E3%82%8F%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F/
+ MacOSX上でLinuxとWindowsとOSXで動くmrubyバイナリを簡単にクロスコンパイルできるmrbgem作った
http://hb.matsumoto-r.jp/entry/2015/05/02/232220

## あとで調べる

+ mrbc の Cオプションは廃止された？？
+ Rite形式について
+ libmruby.a とは？
+ Mrbgems とは？