このエントリは、mruby-cliを使ってみて、わかったことのメモです。 mruby-cliを使うと、mrubyでスタンドアローンなコマンドラインアプリケーションを、複数のプラットフォーム向けに簡単にビルドすることができます。
対象ソフトウェア
ソフトウェア | バージョン | 備考 |
---|---|---|
Debian | stretch | - |
Docker | 1.11.0 | - |
Docker Compose | 1.5.2 | - |
mruby-cli | 0.0.4 | https://github.com/hone/mruby-cli/releases/tag/v0.0.4 |
mruby-cliの概要
mruby-cliが提供するのはmruby-cli
というコマンドだけです。 mruby-cli
は--setup
オプションで、mrubyでアプリケーションを開発するためのファイル郡を生成します。
ファイル郡には、
- mruby本体
- アプリケーションのソースコードの雛形
- ビルド用の
Rakefile
やdocker-compose.yml
等
が含まれます。
アプリケーションのビルドはdocker-compose
コマンドで、クロスプラットフォーム向けのビルド環境が整ったDockerコンテナ内で行います。 デフォルトのターゲットプラットフォームはLinux, MacOS X, Windowsで、ビルド時には全プラットフォーム向けのバイナリがそれぞれ出力されます。
ビルドにはDockerを使用するため、mruby-cliを作者の想定どおり使用するには、DockerとDocker Composeが必要です。 もちろん、ビルド環境さえ整っていればDockerとDocker Composeを使わずに、rake
でアプリケーションをビルドすることもできます。
インストール
mruby-cliのGitHubからlatest releaseをダウンロードしてくるのが良いです。 mruby-cli自体がmruby-cliで作られているため、ワンバイナリの恩恵に預かりましよう。
- Releases · hone/mruby-cli – https://github.com/hone/mruby-cli/releases
私が試した環境はLinuxですので、mruby-cli-0.0.4-x86_64-pc-linux-gnu.tgz
をダウンロードしました。 これを展開すると、mruby-cli
という実行可能ファイルが出てきます。
次のアプリケーションのファイル郡の生成は、このmruby-cli
を使って行います。 必要ならパスを通しておくと良いでしょう。
アプリケーションの生成
このエントリではhellomruby
というコマンドラインアプリケーションを作ることにします。 以下のように--setup
もしくは-s
オプションでアプリケーション名を指定して、mruby-cli
を実行します。 カレントディレクトリの下にアプリケーション名のディレクトリが作成され、ファイル郡が配置されます。
mruby-cli -s hellomruby
出力されるファイル郡は以下のとおりです。
hellomruby
├── bintest
│ └── hellomruby.rb
├── build_config.rb
├── docker-compose.yml
├── Dockerfile
├── mrbgem.rake
├── mrblib
│ ├── hellomruby
│ │ └── version.rb
│ └── hellomruby.rb
├── Rakefile
├── test
│ └── test_hellomruby.rb
└── tools
└── hellomruby
└── hellomruby.c
アプリケーションの実装
アプリケーションのコードの雛形はmrblib
以下に出力されています。 この例ではhellomruby.rb
が本体です。
def __main__(argv)
if argv[1] == "version"
puts "v#{Hellomruby::VERSION}"
else
puts "Hello World"
end
end
mruby-cliで作成するアプリケーションは__main__
メソッドが最初に実行されます。 これはtools/hellomruby.c
として生成されたC部分のコードから、__main__
を呼び出す仕組みのためです。
雛形では、引数なしで実行した場合にHello World
を出力します。 またversion
オプションが指定された時に、version.rb
で定義した、アプリケーションのバージョンを表示するようになっています。
お気づきかも知れませんが、__main__
に渡されるargv
は、argv[1]
が1つ目のコマンドラインオプションです。 RubyのARGV
とは勝手が違い、argv[0]
にはアプリケーションのファイル名そのものが格納されているのでご注意下さい。 (ようは、C言語のmain()
が受け取った第2引数が、そのまま渡される)
このままでも良いのですが、ここは遊び心で、出力するメッセージをHello mruby
に変えてみます。
def __main__(argv)
if argv[1] == "version"
puts "v#{Hellomruby::VERSION}"
else
puts "Hello mruby"
end
end
ビルドの設定の変更
上記のファイルをビルドするだけなら、この手順は必要ありません。
build_config.rb
ビルドの設定を変更したい場合は、アプリケーション名の直下に生成されるbuild_config.rb
を編集します。 内容は以下のようになっています。
def gem_config(conf)
#conf.gembox 'default'
# be sure to include this gem (the cli app)
conf.gem File.expand_path(File.dirname(__FILE__))
end
MRuby::Build.new do |conf|
toolchain :clang
conf.enable_bintest
conf.enable_debug
conf.enable_test
gem_config(conf)
end
MRuby::Build.new('x86_64-pc-linux-gnu') do |conf|
toolchain :gcc
gem_config(conf)
end
# 以下省略...
ポイントは、以下の2点です。
- クロスコンパイルするプラットフォーム毎に
MRuby::Build.new
が分かれている - 冒頭で定義されている
gem_config
メソッドが、すべてのMruby::Build.new
のブロック内から呼び出されている -
gem-config
メソッドでは、アプリケーション自体のgemがconf.gem
で追加されている
全プラットフォームで共通の設定は、gem_config
メソッドを書き換えれば良く、もしプラットフォーム毎に切り替えたい部分があれば、各プラットフォームのMruby::Build.new
のブロック内を書き換えれば良いということです。
また、特定のプラットフォームをクロスコンパイルの対象から除外したい場合は、そのプラットフォームのMRuby::Build.new
をまるごと消してしまえばビルドされなくなります。
アプリケーション自体のgemが追加されていますので、mrbgemsの依存関係は、次に説明するmrbgems.rake
を編集することで、変更することができます。
mrbgems.rakeの変更
mrbgems.rake
のデフォルトの内容は以下のとおりです。 mrbgemsの依存関係がある場合はadd_dependency
で依存関係を追加すれば良いです。
MRuby::Gem::Specification.new('hellomruby') do |spec|
spec.license = 'MIT'
spec.author = 'MRuby Developer'
spec.summary = 'hellomruby'
spec.bins = ['hellomruby']
spec.add_dependency 'mruby-print', :core => 'mruby-print'
spec.add_dependency 'mruby-mtest', :mgem => 'mruby-mtest'
end
ビルド
docker-compose run compile
で、Dockerを使用してコマンドラインアプリケーションを全プラットフォーム向けにクロスコンパイルできます。
docker-compose
はカレントディレクトリのdocker-compose.yml
を読み込んでコンテナを起動します。 このためアプリケーションのルートディレクトリで実行して下さい。
docker-compose run compile
ビルドしたバイナリの出力先はmruby/build
のプラットフォーム名のディレクトリ以下になります。
mruby/build/host/bin/hellomruby
mruby/build/i686-pc-linux-gnu/bin/hellomruby
mruby/build/i386-apple-darwin14/bin/hellomruby
mruby/build/x86_64-pc-linux-gnu/bin/hellomruby
mruby/build/x86_64-apple-darwin14/bin/hellomruby
実行
自分のプラットフォーム向けのバイナリを実行してみましょう。
mruby/build/x86_64-pc-linux-gnu/bin/hellomruby
出力は以下のとおりです。
Hello mruby
ちゃんと動きましたね!
補足:mrub-cliの使用する Dockerfile / docker-compose.yml について
Dockerfile
はこれだけです。
FROM hone/mruby-cli
DockerHubのhone/mruby-cliイメージを落としてくるだけの内容です。 DockerHub上ではlatest
のサイズは575MBと、結構なサイズがあります。
このDockerイメージは、Githubへのリンクが設定されていませんが、以下のDockerfile
をビルドしたもののようです。 ubuntu-debootstrap:14.04
ベースで、Rubyとクロスコンパイルに必要なビルド環境をインストールしたイメージとなっています。
次にdocker-compose.yml
ですが、以下のとおりで、compile
がデフォルトです。 volumes
が多少怖いですが、カレントディレクトリがコンテナ内で/home/mruby/code
にマウントされます。
compile
ではbuild: .
でDockerfile
をビルドし、起動時にはrake compile
を実行するようになっています。 特にREADME.md
に解説は無いですがtest
やbintest
など、compile
以外の操作も、コンテナ内で実行できるように書かれていることがわかります。
compile: &defaults
build: .
volumes:
- .:/home/mruby/code:rw
command: rake compile
test:
<<: *defaults
command: rake test
bintest:
<<: *defaults
command: rake test:bintest
mtest:
<<: *defaults
command: rake test:mtest
clean:
<<: *defaults
command: rake clean
shell:
<<: *defaults
command: bash
補足:Dockerを使わないビルド
上記のとおりdocker-compose run compile
は、ビルド環境が整ったコンテナ内でrake
しているだけです。 このため、mruby-cliのアプリケーションを、Dockerを使わずにrake
でビルドすることもできます。 もちろん、この場合は全ターゲットプラットフォーム向けのビルド環境を、予め準備しておく必要があります。
rake
ビルド環境が整ったコンテナを使ってビルドするのがmruby-cliの良いところですので、あまりオススメできません。