Mac で ngx_mruby 込みで nginx をビルドする際にいろいろハマってた
ちょっと前に解決した話なんですが備忘録的に書いておきます。 (2017/10/03 記述に漏れがあったので修正しました)
前提
最近の openssl の Formula は link を --force を付けたとしても禁止しています。理解はできるけどサクッとビルドしたい時にやや面倒・・・
$ brew link openssl --force Warning: Refusing to link: openssl Linking keg-only openssl means you may end up linking against the insecure, deprecated system OpenSSL while using the headers from Homebrew's openssl. Instead, pass the full include/library paths to your compiler e.g.: -I/usr/local/opt/openssl/include -L/usr/local/opt/openssl/lib
Homebrew の Formula が入らないよ問題
nginx-full Formula はナイスなことにオプションで ngx_mruby を加えてビルドすることができるようになっています。 http://hb.matsumoto-r.jp/entry/2016/02/10/224532
しかし最近以下の点でハマるようになっていました。
- Homebrew がデフォルトで
sandbox-exec
してビルドするようになり、パーミッションの都合 --with-mruby-module ではビルドが通らなくなる- 一応 --no-sandbox すれば
sandbox-exec
しなくなるので回避できる
- 一応 --no-sandbox すれば
- ngx_mruby のリンク途中でコケる
前者の問題は本質的には mruby-nginx-module の Formula の構成の問題です。 Homebrew で sandbox-exec
してビルドする際、ビルド対象の Formula のディレクトリや /tmp などに書き込み権限を絞ってしまうため、現状の "nginx-full Formula から mruby-nginx-module Formula のビルドを行なう" ような操作が通らなくなります。
これは根が深い問題なので、今回はひとまず後者の問題を回避できるようにしました。
https://github.com/Homebrew/homebrew-nginx/pull/324
これで以下のようにすれば引き続き Homebrew で ngx_mruby をらくらくインストールすることができます。
# 残念ながら --no-sandbox は今のところ必要。しかたないね $ brew install nginx-full --with-mruby-module --no-sandbox
ngx_mruby をソースからビルドする時困るよ問題
前述の通り openssl のインクルードパスなどを、 ngx_mruby の場合は nginx や mruby のビルド時にも渡るようにしてやらなければならないので一工夫がいります。 幸いにも ngx_mruby の configure, Makefile ではいくつか nginx, mruby のビルド時に任意のオプションを渡すための記述がされているのでそれらを駆使するのが良さそうです。
(2017/10/03 追記・修正) nginx の ビルド時には難ありです。
openssl のソースコードを手元に用意して、 ngx_mruby の --with-ngx-src-root
にパスを渡すのがひとつのビルド方法に思われます。
./configure --with-ngx-src-root=/path/to/ngx_mruby/build/nginx_src --with-ngx_config_opt="--with-debug --with-http_stub_status_module --with-http_ssl_module --with-openssl=/path/to/openssl" ...
自分は面倒に感じてしまったので、 nginx の configure に以下のようなパッチを当てて、 Homebrew でインストールした openssl を参照するようにしてしまいました。。。
113a114,129 > if [ $ngx_found = no ]; then > > # Homebrew > > ngx_feature="OpenSSL library in /usr/local/opt/" > ngx_feature_path="/usr/local/opt/openssl/include" > > if [ $NGX_RPATH = YES ]; then > ngx_feature_libs="-R/usr/local/opt/openssl/lib -L/usr/local/opt/openssl/lib -lssl -lcrypto $NGX_LIBDL" > else > ngx_feature_libs="-L/usr/local/opt/openssl/lib -lssl -lcrypto $NGX_LIBDL" > fi > > . auto/feature > fi >
これを利用すれば以下の通りにビルドできます
$ ./configure --with-ngx-src-root=/path/to/ngx_mruby/build/nginx_src --with-ngx_config_opt="--with-debug --with-http_stub_status_module --with-http_ssl_module ... $ NGX_MRUBY_CFLAGS="-I/usr/local/opt/openssl/include" NGX_MRUBY_LDFLAGS="-L/usr/local/opt/openssl/lib -lcrypto" make ... checking for OpenSSL library ... not found checking for OpenSSL library in /usr/local/ ... not found checking for OpenSSL library in /usr/pkg/ ... not found checking for OpenSSL library in /opt/local/ ... not found checking for OpenSSL library in /usr/local/opt/ ... found ...
かなり遠回り感が出てしまいますが、自分の環境ではこれで無事ビルドできました
ところで
High Sierra では OpenSSL が LibreSSL に置き換わるらしいですね。こんな問題にはもうハマらなくて済むのか、あるいは別のハマりどころに結局苦しめられるのか・・・
mruby を使ってワンバイナリで Serverspec のテストを実行可能にするツール "sssspec" を作った
ながすぎる;よんでない
リポジトリは以下にあります。
- 本体
- 関連 mrbgems
以下のように spec を書いて…
def __main__(argv) describe file('mrblib') do it { should be_readable.by('yourgroup').by_user('you') } end end
sssspec をビルドして…
$ rake
生成されたバイナリひとつで spec を実行することができます
$ ./sssspec . Total: 1 OK: 1 KO: 0 Crash: 0 Time: 0.16 seconds
背景
Serverspec はプロセスの起動やパッケージのインストール状態、パッケージの存在確認などサーバの状態をテストするのに有用なツールです。
しかしながらこれをローカル実行するには当然 Ruby 処理系や関連 gem をインストールしておく必要があります。Serverspec の為だけに Ruby を導入する必要が出て来る場合、これはちょっとした障壁となると思われます。 また Serverspec は ssh 経由でリモート実行もできますが、構成上、自動化したい際はデプロイツールの都合、社内ルールの問題で利用できない可能性があります(と、ぼくは思ってるんですが、実際のところそういった制約はどの程度あるのだろう)
Serverspec の導入障壁を減らしたいと考えた僕は、 mruby-cli を利用してワンバイナリで実行可能にした Itamae であるところの MItamae を参考になんとかすることにしました。 そうだ、 mruby 、やろう。
構成など
必要なものたち
mruby で Serverspec を実行するために最低限必要なものは、以下のものと思われます。
これらのうち、 “Specinfra の mrbgem” については @k0kubun さんによって作られた mruby-specinfra が利用できそうです。 というわけで残り 3 コンポーネントを自前で用意することにしました。
mruby-rspec
mruby-rspec は mruby で RSpec を実行可能にする mrbgem です。
経緯の話をすると、当初は Ruby 向けの rspec-core などを mruby 向けに作り直そうと試みたのですが、 RSpec の既存資産がなかなか大きく、 mruby 向けに改修していく作業の途中で心が折れてしまいました。 現在は、限られた機能のみ mruby 向けに移植している(途中だったらしい) sagmor/mruby-spec をベースに mrbgem を実装しています。
mruby-rspec は未だかなり機能が少ないため、本記事の “sssspec” をまともに使い倒して行こうとすると、もう少し機能追加が必要なものと思われます。
mruby-serverspec
mruby-serverspec は本家 Serverspec の matcher, type をほぼ使いまわしで構成した mrbgems です。 ssh 経由でのリモート実行など一部のロジックは削っております。
この辺りは本家 Serverspec のコードを引っ張り出して無理やり mrbgems 化して、動かない箇所を片っ端から修正していくという大変泥臭い作業をして構成しました。
sssspec
sssspec は mruby-cli ベースのテンプレートを修正し、かつこれまで紹介した mrbgems を組み合わせて実現した、ワンバイナリで spec 実行可能なツールです。 実装は 9 割くらい mruby-cli のテンプレそのままで、あり解説すべき点は特に無いので省きます。 ちなみに名前は rrrspec を意識し、 “Single Shot ServerSpec” の略としています。
今後の展望
ひとまず動くところまで作りたかったので、 sssspec と周辺 mrbgems はかなり大雑把な作りになっています。まずは全体的にもう少しリファクタリング等していきたいです。
また現状 mruby-rspec の機能が少ないせいで実用に耐えない気がしています。個人的には少なくとも、 shared_examples が無いと辛いなと思っております。従ってそのあたりの RSpec 便利機能を mruby-rspec にも実装していきたいと思っております。
本記事と関係のない余談
ルビィの話書いてて思い出したんですが、 秋からラブライブ!サンシャイン!! の二期が放映開始されますね! ちなみに僕は渡辺曜ちゃんが好きです。
技術書典2でmrubyに関する薄い本をだします
表題のとおりです。
4/9(日) アキバ・スクエアで開催される 技術書典2 にて mruby に関する薄い本を出します! う-10 サークル名「なるはやでいい感じにやるマン」*1です。 https://techbookfest.org/event/tbf02/circle/5686683802533888
主なターゲット読者を Rubyist として、 mruby の言語処理系周り (mruby-compiler
とか RiteVM とか) や CRuby との差異 (khash とか GC とか) をいい感じに書いていければと思ってます。
もしご参加の際はぜひよろしくお願いいたします!
*1:なお原稿の進捗具合は、なるはやともいい感じとも言えない模様
KVS をゆるくつなぐ mrbgem "mruby-neco" を作ってみた
あけましておめでとうございます。正月は実家に帰省してネコと戯れて過ごしました。
新年一発目の記事は、新しく作成した mrbgem "mruby-neco" を紹介してみます。
mruby-neco について
mruby-neco は NoSQL Elastic Command Organizer の略としています。はい、言いたかっただけな名前です。
さて mruby-neco ですが、あまた在る NoSQL 、というか特に KVS について、 mruby スクリプト向けにひとまとめしたインタフェースを提供するものです。 具体的には現状下記プロダクトをサポートしています
これらのプロダクトに対して、下記のインタフェースを提供します。
- get
- key に対する value を取得する
- put
, - key に対する value を保存する
- delete
- key, value のペアを削除する
- each
- key, value のペアを受け取るブロックを回すイテレータ
- Enumerable を include してるので
map
とかfilter
とかreduce
も使える
それぞれの操作に対して、特定プロダクトを対象にするか、いくつかのプロダクトをひとまとめにした集合を対象にするかを選択できるようにしています
モチベーション
mruby-neco を作ったモチベーションですが、以前の記事で mruby-k2hash というmrbgem を実装した際に、他の KVS から値を持ってきていろいろできてもいいなぁと思ったのと、各プロダクトに付与されている場合がある cli ツールの操作感に差異があり、それを埋める手段が欲しいなぁと思った次第です。 既存の手段でその望みはかなえられる気がしないでもないですが、ここは mruby マンとして mruby でいい感じに KVS 間のデータのやり取りや加工をできると面白いのでは・・・と考えサクッと実装してみました。 ちまたに mrbgem も充実していて、苦労せず実装に踏み出せると考えたという背景もあります。
実際の mruby-neco 利用例
mruby-neco を利用して値を参照更新する例を掲載してみます Org という構造にメンバーを追加し、 Org を介して操作する、みたいな構造を取っています。 Org と各プロダクトのドライバ間の際は Adapter クラスで吸収する形になります。
org = Neco::KvsOrg.new org.add_member(:etcd, {:url => 'http://127.0.0.1:2379/v2'}) org.add_member(:lmdb, {:path => '/tmp/tmp.lmdb', :options => {:flags => MDB::NOSUBDIR}}) org.add_member(:redis, {:host => 'localhost', :port => 6379}) org.add_member(:k2hash, {:path => '/tmp/tmp.k2hash', :options => {:mode => 0666, :flags => K2Hash::NEWDB}}) org.put_to :etcd, 'key', 'etcd' org.put_to :lmdb, 'key', 'lmdb' org.put_to :redis, 'key', 'redis' org.put_to :k2hash, 'key', 'k2hash' p org.get_from_all 'key' #=> {:redis=>"redis"} org.put_to_all 'key', 'value' p org.get_from_all 'key' #=> {:etcd=>"value", :lmdb=>"value", :redis=>"value", :k2hash=>"value"} puts 'each_for :redis' org.each_for(:redis) do |key, value| puts "key: #{key}, value: #{value}" end puts 'each' org.each do |key, value| puts "key: #{key}, value: #{value}" end
コマンドラインから neco を利用する
モダンな mruby マンとしては mruby-cli も使ってみたいよね・・・というわけで、 neco-cli という、上記の get と put 操作をコマンドラインから行えるツールを作ってみました。 下記のような使用感になります。
$ neco-cli help usage: neco-cli <subcmd> neco-cli get <key> [--open <db options as JSON>] neco-cli put <key> <value> [--open <db options as JSON>] example: neco-cli set "key1" "value1" --open '{"name": redis, "addr": "127.0.0.1", "port": 6379}' $ neco-cli put key hoge --open '{"name": "redis", "host": "127.0.0.1", "port": 6379}' $ neco-cli get key --open '{"name": "redis", "host": "127.0.0.1", "port": 6379}' {"redis":"hoge"} $ neco-cli put key fuga --open '{"name": "redis", "host": "127.0.0.1", "port": 6379}' --open '{"name": "etcd", "url": "http://127.0.0.1:2379/v2"}' $ neco-cli get key --open '{"name": "redis", "host": "127.0.0.1", "port": 6379}' --open '{"name": "etcd", "url": "http://127.0.0.1:2379/v2"}' {"redis":"fuga","etcd":"fuga"}
open
オプションの内容と get で得た値のフォーマットは現状 JSON としています。
ネコについて
冒頭で触れた実家のネコですが、 4 ヶ月ほど顔を合わせてなかったにも関わらず僕のことを覚えているようで、全力で甘えに来てくれました(かわいい) しかしながらネコの中で何らかのポリシーがあるのか、あちらから触れてくることは多々あるのですが、こちらから頭を撫でるなど触れるとコレジャナイ感を覚えているような顔をして去っていってしまいます(かなしい)
Yahoo! JAPAN がオープンソースにした KVS "K2HASH" を mruby スクリプトから利用するための mgem "mruby-k2hash" をつくってみた
この記事は mruby Advent Calendar 2016 26 日目の記事です。・・・というのは嘘です! mruby Advent Calendar 2016 、つつがなく完走しましたね!みなさまお疲れ様でした!
本記事では表題の通り、 mruby-k2hash という mgem を作ってみたことに関する共有になります。
K2HASH とは
K2HASH は Yahoo! JAPANのブログ でちょろっと紹介されている KVS です。 ソースコードは GitHub で閲覧することができます。
上記の記事では簡潔な紹介のみになっていますが、 GitHub の wiki を読む限り下記の点から興味深いプロダクトなような気がします。
こうして列挙してみると、個人的な知識から考えるに Redis に近い機能を保有している気がします。 ただデーモンを立ち上げたりファイルに書き出すことすら必須ではないことから、結構気軽に利用できるように見えます。
mruby-k2hash について
基本方針
今回ご紹介する mruby-k2hash はこの K2HASH への操作を mruby スクリプトから行うことを可能にします。 この mruby-k2hash 、基本的には K2HASH の C インタフェースへの橋渡しをするだけになります。ですがその設計は少し考えた上で行っています。 K2HASH の基本的な機能を目を細めてみると・・・うーん・・・なんだか Ruby の標準ライブラリに存在する DBM に近い気がしてきます。
というわけで mruby-k2hash で実装しているメソッドは DBM が持つものを模倣する 形で行っています。 each も実装していることから Enumerable のメソッドも使えるようになっています。 mruby で dbm の mgem を実装したという例は僕が知る限り無い(あったらコッソリ教えてください!)ので、 mruby-k2hash は mruby で気軽に扱える dbm 代替のひとつ としても利用できるのではないかと考えています。
実際の動作例
mruby-k2hash の実際の動作の例としては下記のようになります。
K2Hash
クラスのコンストラクタにファイルパスなどなどを渡すとそのファイルを open しつつインスタンスが生成されます。 fetch
, []
メソッドで参照、 store
, []=
メソッドで更新が行えます。
> k2hash = K2Hash.new('/tmp/tmp.k2hash', 0666, K2Hash::WRCREAT) => #<K2Hash:0x127ada0> > k2hash.store('key', 'value') => nil > k2hash.fetch('key') => "value" > k2hash.store('key', 'new value') => nil > k2hash.fetch('key') => "new value" > k2hash['key2'] = 'value2' => "value2" > k2hash['key2'] => "value2" > k2hash.close => nil
each
メソッドや、それを実装したことによって Enumerable インタフェースのメソッド、例えば map
なども利用できます。
> k2hash = K2Hash.new('/tmp/tmp2.k2hash', 0666, K2Hash::WRCREAT) => #<K2Hash:0xcef7c0> > k2hash['key1'] = 'value1' => "value1" > k2hash['key2'] = 'value2' => "value2" > k2hash.each do |k,v|; puts k + ': ' + v; end key1: value1 key2: value2 => nil > k2hash.map do |k,v|; "key is #{k}, value is #{v}"; end => ["key is key1, value is value1", "key is key2, value is value2"]
気軽に試す
もろもろビルド済みの Docker image を push してあるので、 pull してご利用ください。
# コンテナ外 $ docker run -i -t syucream/mruby-k2hash /bin/bash # コンテナ内 root@9cc669af1607:/opt# ./mruby/bin/mirb mirb - Embeddable Interactive Ruby Shell > ... # あとはいいかんじにやる
テストとか
ちょっとだけ単体テストを書きました。テストコードを書くに際して IIJ が公開している mruby-mtest を使ってみました。
Travis CI でビルドする際はこの mgem を含めて mruby をビルドし、テストコードを bin/mruby
に食わせる形でテストするようにしました。楽でいいですわゾ〜! :D
おわりに
現状の mruby-k2hash は K2HASH の多くの機能(サブキーとかキューとか)を利用できない状態なので、なんとかしたいです。 そのうち気が向いたら機能追加します。
mrb_state を跨いで Proc オブジェクトをやり取りしたい話
この記事は mruby Advent Calendar 2016 11 日目の記事です。
Advent Calendar のネタとしてはやっぱりイカした mrbgem を作りました的な内容をブチ上げて行きたいところですが、残念ながらそのようなネタは思いつかず。 本記事では自分が拙作プロダクト ts_mruby を実装中ハマった問題をちょろっと共有するシンプルな内容になっています。
背景
ことのおこり
ts_mruby は Apache Traffic Server(以下ATS) に組み込むプラグインとして、 mod_mruby, ngx_mruby のような役割を担うことを目的に開発を続けています。 また、今年 9 月に バージョン 0.1 をリリースしています。
ATS は主な用途が HTTP プロキシサーバであり、プラグイン向けにいくつかのフックが用意されています。 ts_mruby-0.1 ではそのうちクライアントから ATS へリクエストが発生したタイミングでの mruby スクリプトによる制御はサポートしていたのですが、その他の、例えばオリジンサーバへリクエストを転送するタイミングやレスポンスを受け取るタイミングのフックに関しては、サポートが非常に弱い状態になっています。
このフックがサポートできないと、例えばレスポンスヘッダに関する情報の参照や修正など重要ないくつかの操作を受け付けることができません。
そこで ts_mruby-0.2 (今年中にリリース予定)ではこのサポートを厚くすることにしました。
具体的には下記のように mruby スクリプトからフックとイベントハンドラを登録可能にするクラス ATS::EventSystem
を実装し、フックの動作タイミングでイベントハンドラを実行するという方針で対応することにしました。
class MyHandler def on_send_request_hdr hout = ATS::Headers_out.new hout["x-on_send_request_hdr"] = "1" end def on_read_response_hdr hout = ATS::Headers_out.new hout["x-on_read_response_hdr"] = "2" end def on_send_response_hdr hout = ATS::Headers_out.new hout["x-on_send_response_hdr"] = "3" end end es = ATS::EventSystem.new es.register MyHandler
上記の MyHandler
クラスの各メソッドは、 ATS のフック における TS_HTTP_SEND_REQUEST_HDR_HOOK
, TS_HTTP_READ_RESPONSE_HDR_HOOK
, TS_HTTP_SEND_RESPONSE_HDR_HOOK
に相当しています。
問題
ATS::EventSystem
を実装するのは良いですが、下記の 2 点に配慮すべき事項があります。
まず ATS はマルチスレッド・イベント駆動で処理します。 そのためもちろんながらスレッドを跨いでリソースを共有する際はロックを取る必要がある場面が生じます。 また、先述のフックを処理するスレッドがどれになるかは不定です。
また、 ts_mruby はロックを取ることによる実装の煩雑さとロックを取ることによるパフォーマンス低下をきらい、スレッドローカルに mrb_state インスタンスを持つ設計にしています。
上記 2 点に配慮すると、最初のフックで ATS::EventSystem
を用いてフックとイベントハンドラを仕込んでも、その後のフックを処理するスレッドがイベントハンドラを知らないといけなくなります。
というわけで (別のスレッドがもつ)mrb_state インスタンスに、(イベントハンドラの) Proc オブジェクトを渡したい という要求が発生しました。
irep を dump することによるスレッド間の Proc オブジェクト受け渡し
irep の dump
Proc オブジェクト(C の型としては RProc
) は実行する命令などの情報を保持する mrb_irep 型のメンバを持ちます。
上記の問題を解決するため、今回は Proc オブジェクトの irep からバイトコードを dump し、それをスレッド間で持ち回すことを考えます。
RProc の mrb_irep メンバをバイトコードに戻す関数 mrb_dump_irep()
が mruby/dump.h に宣言されています。
mrb_dump_irep()
dump したバイトコードを、格納するのに必要な領域を mrb_malloc() で確保しつつ、 uint8_t* 型で返却します。
ここで取り出したバイトコードは同じく mruby/dump.h に宣言されている mrb_read_irep()
で mrb_irep 型に戻すことができます。
後はこれを mrb_closure_new()
で RProc 型に変換してから mrb_obj_value()
で mbr_value 型の Proc オブジェクトに変換し、最後に mrb_yield()
で proc オブジェクトを実行すれば元のイベントハンドラの実行まで完了です。
全体の流れを図示すると、下記のようになります。
ts_mruby への機能追加
上記で検討した irep を dump することによるイベントハンドラ受け渡しですが、実際の実装としては下記のようになります。 下記のソースコードは断片的なものですが、実際に組み込んだものを既に ts_mruby の master ブランチ にマージ済みなのでそちらでご確認いただけます。
イベントハンドラ登録処理
イベントハンドラを登録する側の処理は下記のようになります。
下記では省いていますが、 ATS 固有のフックの登録も行う必要があります。
また、 send_request_hdr_irep_
に格納したバイトコードはどうにかしてイベントハンドラを処理するスレッドに渡るようにする必要があります。
ts_mruby としては HTTP トランザクション処理に紐づくデータを登録できるので、そこに格納しています。
static const char* SEND_REQUEST_HDR_HANDLER = "on_send_request_hdr"; ... mrb_sym sym = mrb_intern_cstr(mrb, SEND_REQUEST_HDR_HANDLER); RProc* rproc = mrb_method_search(mrb, rclass, sym); uint8_t* send_request_hdr_irep_ = NULL; size_t binsize = 0; mrb_dump_irep(mrb, rproc->body.irep, DUMP_ENDIAN_NAT, &send_request_hdr_irep_, &binsize);
イベントハンドラ実行処理
イベントハンドラを処理する側の処理は下記のようになります。
(どのようにかして) send_request_hdr_irep_
を取り出し、前述の通りの変換を行って最終的に mrb_yield()
で実行します。
uint8_t* handler_irep = ... // send_request_hdr_irep_ RProc* closure = mrb_closure_new(mrb, mrb_read_irep(mrb, handler_irep)); mrb_value proc = mrb_obj_value(closure); mrb_value rv = mrb_yield(mrb, proc, mrb_nil_value());
所感
今回紹介したやり方ですが、やはり Proc オブジェクトを一旦 irep に dump した後に再度 irep に戻すという変換を行っているので、ややコストが高いです。 これとは別のやり方として下記の方法で Proc オブジェクトの mrb_value を直接複数スレッド複数 mrb_state インスタンス間でやり取りすることも検討し、一度は実装していました。
イベントハンドラ実行スレッドで先程の mrb_value を直接参照し、処理する
- 処理が終わったらスレッドセーフな「mbr_value を使い終わりましたメッセージ」を格納するキューにメッセージ追加
イベントハンドラ登録処理を実行したスレッドが次回実行する際、メッセージを確認する
- 使い終わった mrb_value に対しては
mrb_gc_unregister()
で GC root から取り外す
- 使い終わった mrb_value に対しては
ただしこの方針は実装が汚くなりがちで、あまりコストも低くないであろうことから廃止してしまいました。
おわりに
あまり一般的な問題という訳ではないでしょうが、本記事が誰かの役に立つと嬉しいです :D また、本記事の内容に要改善点などあればご指摘いただけると嬉しいです! (ちゃんと調べてないですが、本記事の工夫の代わりに mruby-marshal を使うなども有用かも?)
mruby の実装を読んで知見をまとめてみている
これは mruby Advent Calendar 2016 3 日目の記事です。
mruby に関するプロダクトを実装していると、 mruby 本体の実装に関して情報が欲しくなる場面があります。(ありますよね?) そんな時は Qiita 等巷で共有されている情報とか、あるいは 組込Ruby「mruby」のすべて を読んだりすると思うのですが、しばしばそれで満たされず mruby のソースコード を追うことがあります。 ご多分に漏れず僕もソースコードを読んだりとかしていたのですが、そこから得た知見をまとめておきたいなぁという気持ちがふつふつと湧き上がってきました。
というわけで mrubook というリポジトリを作成し、ソースコードから読み取ったノウハウをこの配下にしこしことドキュメント化してみています。
https://syucream.github.io/mrubook/
現状、下記のようなポリシーでドキュメント化を行っています。
- 基本的に mruby のリポジトリの src/ 以下の各ファイルに対応するドキュメントを個別のファイルとして書く
- フォーマットは 1) 概要 2) 詳細 3) C や mruby 向けの API に関する情報 の 3 本立て
- ドキュメントを html 化し、 gh-pages で閲覧可能にする
- 現在は Sphinx で html 生成をしている。 master ブランチに変更が入った際に travis-sphinx を用いてビルドを行い gh-pages ブランチを更新
まだまだ内容が乏しいですが、そのうち誰かの役に立ったら良いな・・・なんて思っております。 また PullRequest など大歓迎です!
さて短い内容で申し訳ありませんが、本記事としては以上になります。 明日 4 日目の記事は k0kubun さんによる「Rubyを評価するCLIツールはCRubyとmrubyのどちらで実装するべきか」とのことです。よろしくお願いいたします!