mrubyのビルド方法

# mrubyをビルドする

　本記事では、mrubyのビルド方法について説明します。

　mrubyのビルドは、Rakeをベースとした独自のビルドシステムを使っています。

　これは主にmrbgemsとクロスビルドの為です。当初はmakeを使っていたのですがmrbgems対応の為にC言語で別コマンドを作るなど無理が出てきたので、2013/1にRakeベースの物に差し替えました。

　その際、Matzからの注文が

<blockquote class="twitter-tweet" lang="en"><p><a href="https://twitter.com/masuidrive">@masuidrive</a> <a href="https://twitter.com/mattn_jp">@mattn_jp</a> ビルドにRuby(CRuby)を使ってもいいですが、当面1.8/1.9両対応、かつRakeを使わないという条件を付けます。mrubyのためにいろいろインストール要求するのは避けたいので</p>&mdash; Yukihiro Matsumoto (@yukihiro_matz) <a href="https://twitter.com/yukihiro_matz/statuses/278810860439339008">December 12, 2012</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

　というモノだったので、Rakeの古いバージョンを元にRakeのサブセットのminirakeを作り、その上で動くビルドシステムを構築しました。


## 必要なもの

　Ruby 1.8以上。GCC/clang/VSなどのtoolchain。

## ビルド

　mrubyのビルドは下記のコマンドで行います。

```
$ ruby ./minirake
```

　ローカルにRakeが導入されている場合、minirakeの代わりにrakeコマンドでもビルドすることができます。

```
$ rake
```

　標準では、これで下記のファイルが生成されます。

- bin/mruby - mrubyコマンド
- bin/mirb - mruby interactive shell
- bin/mrbc - mruby compiler

　下記の様に実行する事で、mrubyを試すことができます。

```
$ ./bin/mirb 
mirb - Embeddable Interactive Ruby Shell
　
This is a very early version, please test and report errors.
Thanks :)
　
> puts "Hello World"
Hello World
 => nil
> 
```

## ビルドの設定

　mrubyのビルドの設定は、`build_config.rb`というファイルで行います。
デフォルトはカレントディレクトリの`build_config.rb`ですが、環境変数`MRUBY_CONFIG`で指定することができます。

```
MRUBY_CONFIG=./custom_config.rb ruby ./minirake
```

　デフォルトでは[build_config.rb](https://github.com/mruby/mruby/blob/master/build_config.rb)の様になっており、gccを使い一般的なUNIX環境(Linux, OSX, FreeBSDなど)でコンパイルできるようになっています。

　このファイルをブロックに分けて解説します。

### ビルド設定ブロック

```
MRuby::Build.new do |conf|
  ...
end
```
　mrubyのビルドに関する設定はこのブロックで行います。build_config.rbには必ず一つ以上のこのブロックが必要です。

　このブロックの中で行われる指定は、ローカルで動くmrubyのビルド設定です。クロスコンパイルの設定については別のブロックで行います。


### ツールチェーン設定

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

　コンパイルで使うツールチェーンを指定します。デフォルトで指定出来るツールチェーンは`gcc`, `clang`, `visualcpp`, `androideabi`です。

　実際にどのような設定が行われるかは、[tasks/toolchains](https://github.com/mruby/mruby/tree/master/tasks/toolchains/)にある同名のファイルを参照してください。


### mrbgemsのインストール

```
  # Use mrbgems
  # conf.gem 'examples/mrbgems/ruby_extension_example'
  # conf.gem 'examples/mrbgems/c_extension_example' do |g|
  #   g.cc.flags << '-g' # append cflags in this gem
  # end
  # conf.gem 'examples/mrbgems/c_and_ruby_extension_example'
  # conf.gem :github => 'masuidrive/mrbgems-example', :branch => 'master'
  # conf.gem :git => 'git@github.com:masuidrive/mrbgems-example.git', :branch => 'master', :options => '-v'
```

　mrubyの拡張モジュールであるmrbgemsの設定を行います。基本的にmrubyでは拡張モジュールを本体と共にコンパイルして一つのバイナリにします。
そのため、コンパイルのオプション追加などもココで行います。

　`conf.gem`ではmrbgemのソース位置として、ディレクトリパス、gitリポジトリ、githubリポジトリを指定できます。

　例のように指定することで、自動的にダウンロードして組み込まれます。git/githubではリモートでアップデートがあっても自動では反映されないので、`build/mrbgems`にダウンロードされているファイルを自分で`git pull`などしてください。

　`conf.gem`はブロックをつけることで、そのgemのコンパイル設定などを変更することができます。指定できる項目について、各mrbgemのドキュメントを参照してください。

### gembox

```
  # include the default GEMs
  conf.gembox 'default'
```

　mrggemsには依存関係を指定する方法がないのですが、その代わりに複数のmrbgemsをひとまとめにしたaliasとしてgemboxという指定ができます。

　[mrbgems](https://github.com/mruby/mruby/tree/master/mrbgems/)ディレクトリに、同名の.gemboxファイルがあり、その中にインストールされるmrbgemsが記述されています。

　この指定では、[default.gembox](https://github.com/mruby/mruby/blob/master/mrbgems/default.gembox)に記載されているmrbgemsが導入されます。

### Cコンパイラ設定
```
  # C compiler settings
  # conf.cc do |cc|
  #   cc.command = ENV['CC'] || 'gcc'
  #   cc.flags = [ENV['CFLAGS'] || %w()]
  #   cc.include_paths = ["#{root}/include"]
  #   cc.defines = %w(DISABLE_GEMS)
  #   cc.option_include_path = '-I%s'
  #   cc.option_define = '-D%s'
  #   cc.compile_options = "%{flags} -MMD -o %{outfile} -c %{infile}"
  # end
```

　mrubyをコンパイルするためのCコンパイラの設定です。

　すべてコメントアウトされていますが、デフォルトではこのような動作を行います。

　デフォルトでは、CCやCFLAGSというコンパイル時に一般的に使われる環境変数も参照されるようになっています。

### mrbcコンパイラ設定

```
  # mrbc settings
  # conf.mrbc do |mrbc|
  #   mrbc.compile_options = "-g -B%{funcname} -o-" # The -g option is required for line numbers
  # end
```

　mrubyではRubyで書かれたソースをバイナリ形式にコンパイルする事ができます。

　mruby-coreやmrbgemsの中でRubyで書かれたソースは、このmrbcでコンパイルされ本体にリンクされます。

　標準ではそのバイナリファイルにはデバッグ情報を含みますが、メモリ制約の厳しい環境では`-g`オプションを除いてください。

### コンパイル関係のツールオプション
```
  # Linker settings
  # conf.linker do |linker|
  #   linker.command = ENV['LD'] || 'gcc'
  #   linker.flags = [ENV['LDFLAGS'] || []]
  #   linker.flags_before_libraries = []
  #   linker.libraries = %w()
  #   linker.flags_after_libraries = []
  #   linker.library_paths = []
  #   linker.option_library = '-l%s'
  #   linker.option_library_path = '-L%s'
  #   linker.link_options = "%{flags} -o %{outfile} %{objs} %{libs}"
  # end

  # Archiver settings
  # conf.archiver do |archiver|
  #   archiver.command = ENV['AR'] || 'ar'
  #   archiver.archive_options = 'rs %{outfile} %{objs}'
  # end

  # Parser generator settings
  # conf.yacc do |yacc|
  #   yacc.command = ENV['YACC'] || 'bison'
  #   yacc.compile_options = '-o %{outfile} %{infile}'
  # end

  # gperf settings
  # conf.gperf do |gperf|
  #   gperf.command = 'gperf'
  #   gperf.compile_options = '-L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k"1,3,$" %{infile} > %{outfile}'
  # end
```

　リンカやアーカイバなどのツールのオプションをココで設定します。通常は変更する必要は無いでしょう。


### ファイルシステム設定

```
  # file extensions
  # conf.exts do |exts|
  #   exts.object = '.o'
  #   exts.executable = '' # '.exe' if Windows
  #   exts.library = '.a'
  # end

  # file separetor
  # conf.file_separator = '/'
```

　ローカルで使われる拡張子やディレクトリのセパレータの指定を行います。


## クロスコンパイル

```
# Define cross build settings
# MRuby::CrossBuild.new('32bit') do |conf|
#   toolchain :gcc
#
#   conf.cc.flags << "-m32"
#   conf.linker.flags << "-m32"
#
#   conf.build_mrbtest_lib_only
#
#   conf.gem 'examples/mrbgems/c_and_ruby_extension_example'
#
#   conf.test_runner.command = 'env'
#
# end
```

このブロックでは、クロスコンパイル用の設定を行います。

2013 advent calendarのどこかで、クロスコンパイル編も書きます。