mruby-yeahとmruby-cliで小さいWebアプリのhello world


自動翻訳感のあるタイトルですが間違ってはいないのでこのまま行きます。

mruby-yeahとmruby-cliを使って単一実行ファイルで動くWebアプリのサンプルを作ります。

前提

  • ubuntu
  • docker, docker-compose: コンパイルするのに必要です。導入手順は割愛。

  • mruby-cli 0.0.4: 単一実行ファイルにコンパイルされるcliツールの実装を行うためのライブラリ

    • クロスコンパイル対応の設定ファイルやプロジェクト用のディレクトリを生成してくれる
  • mruby-yeah: mrubyでWebアプリを実装するためのライブラリ

mruby-cliで雛形を作る

まずmruby-cliの実行ファイルを落としてきてパスを通し実行できる状態にします。

次に開発を行うためのディレクトリと関連ファイルをmruby-cliで生成します。

mruby-cli --set-up sample
cd sample

一度コンパイルして実行してみてHello Worldが表示されれば成功です。

sudo docker-compose up --build
sudo docker-compose run compile
sudo ./mruby/build/host/bin/sample

mruby-cliで生成したファイルのmrubyバージョン指定を変更する

大筋で生成されるファイルに問題はないのですが、
mruby-cli バージョン0.0.4が生成するファイルはmruby1.2でビルドを行っており、
mruby-yeahが動作するのはmruby1.4のようなので一部ファイルを修正します。

一度コンパイルしていると既に1.2のmrubyがダウンロードされているので、
sampleディレクトリ直下のmrubyディレクトリも削除しておいてください。

vim Rakefile
 require 'fileutils'

-MRUBY_VERSION="1.2.0"
+MRUBY_VERSION="1.4.0"

 file :mruby do
   #sh "git clone --depth=1 https://github.com/mruby/mruby"
-  sh "curl -L --fail --retry 3 --retry-delay 1 https://github.com/mruby/mruby/archive/1.2.0.tar.gz -s -o - | tar zxf -"
-  FileUtils.mv("mruby-1.2.0", "mruby")
+  sh "curl -L --fail --retry 3 --retry-delay 1 https://github.com/mruby/mruby/archive/#{MRUBY_VERSION}.tar.gz -s -o - | tar zxf -"
+  FileUtils.mv("mruby-#{MRUBY_VERSION}", "mruby")
 end

 APP_NAME=ENV["APP_NAME"] || "sample"
sudo rm -rf mruby

windows向けのコンパイルはコメントアウトする

mruby-cliの生成する雛形ではwindows向けのクロスコンパイルも含まれます。
mruby-yeahを含めた場合だとコンパイルが通らなかったのでWindows向けのクロスコンパイルに関する記述をコメントアウトします。

デフォルトでは他にmac向け、linuxの32bit, 64bit向けのビルドも行われます。
コンパイル時間に影響するはずなので他にも不要な物は外してしまっても良いでしょう。

vim build_config.rb
--- build_config.rb.before_rm_windows   2018-03-31 16:44:13.485515441 +0900
+++ build_config.rb 2018-03-31 16:47:28.389557167 +0900
@@ -61,34 +61,34 @@
   gem_config(conf)
 end

-MRuby::CrossBuild.new('x86_64-w64-mingw32') do |conf|
-  toolchain :gcc
-
-  [conf.cc, conf.linker].each do |cc|
-    cc.command = 'x86_64-w64-mingw32-gcc'
-  end
-  conf.cxx.command      = 'x86_64-w64-mingw32-cpp'
-  conf.archiver.command = 'x86_64-w64-mingw32-gcc-ar'
-  conf.exts.executable  = ".exe"
-
-  conf.build_target     = 'x86_64-pc-linux-gnu'
-  conf.host_target      = 'x86_64-w64-mingw32'
-
-  gem_config(conf)
-end
-
-MRuby::CrossBuild.new('i686-w64-mingw32') do |conf|
-  toolchain :gcc
-
-  [conf.cc, conf.linker].each do |cc|
-    cc.command = 'i686-w64-mingw32-gcc'
-  end
-  conf.cxx.command      = 'i686-w64-mingw32-cpp'
-  conf.archiver.command = 'i686-w64-mingw32-gcc-ar'
-  conf.exts.executable  = ".exe"
-
-  conf.build_target     = 'i686-pc-linux-gnu'
-  conf.host_target      = 'i686-w64-mingw32'
-
-  gem_config(conf)
-end
+# MRuby::CrossBuild.new('x86_64-w64-mingw32') do |conf|
...中略
+# end
+
+# MRuby::CrossBuild.new('i686-w64-mingw32') do |conf|
...中略
+# end

webアプリとしてのコードを書く

まずmruby-yeahをmruby-cliが生成した mrbgem.rake に追記します。
これにより次のコンパイル時にmruby-yeahも取り込んだ実行ファイルが生成されます。

MRuby::Gem::Specification.new('sample') do |spec|
  spec.license = 'MIT'
  spec.author  = 'MRuby Developer'
  spec.summary = 'sample'
  spec.bins    = ['sample']

  spec.add_dependency 'mruby-print', :core => 'mruby-print'
  spec.add_dependency 'mruby-mtest', :mgem => 'mruby-mtest'
  spec.add_dependency 'mruby-yeah' # この行を追加
end

mruby-cliが生成したmrblib/sample.rbファイルにmruby-yeah向けのコードを書きます。
getアクセスされたら Hello web app! とレスポンスを返すようにします。

vim ./mrblib/sample.rb
# 実装の例

# '-p 3000' または '--port 3000'
# オプションでポート番号を指定可能になります。
opt(:port) { |p| set(port: p) }

# curl localhost:<port>/test
# => Hello web app!
get('/test') do
  'Hello web app!'
end

実行

mruby1.4とmruby-yeahの取得、sampleの再コンパイルをした上で
HTTPリクエストをした際の動作が期待通りか見てみます。

curlでHTTPアクセスを飛ばして Hello web app! が表示されれば成功です。

sudo docker-compose run compile
export SHELF_ENV=development # 何かしら指定しないとエラー。デフォルトでdevelopにしてくれたりはしない模様
sudo chmod +r -R mruby
./mruby/build/host/bin/sample --port 3000

# 別のターミナルで
curl http://localhost:3000/test