mruby VM ポーティング手順マニュアル mrubyポーティング
mrubyポーティングとは
mruby を特定のシステム上で動作させるためには、 mruby の移植作業 (修正および再構築) が必要となる。この移植作業がポーティングである。 mrubyのポーティングでは、mruby の実⾏基盤である mruby仮想マシン (mruby VM) を 実⾏環境で動作させることが必要となる。 本稿では、mrubyをQSIPボードで動作させるために実施したポーティング作業の概要を示す。
1 mrubyポーティングの概要
mruby ポーティングの概要 QSIPボードにmrubyをポーティングする手順を以下に示す。 1. mruby ビルド環境の構築 mrubyをビルドするための開発環境を構築する。 本稿ではWindows上にmrubyビルド環境を構築した。
2. QSIP向けのmrubyクロスビルド mrubyをQSIPボード用にクロスコンパイルし、mrubyライブラリ (libmruby.a) を作成 する。 本稿では、 IAR Embedded Workbench for ARM にmruby クロスビルド環境を構 築した。
3. QSIP アプリケーションへの mruby 組み込み QSIPアプリケーションにmruby VM を呼び出す処理 (mruby API) を追加し、 mrubyライブラリ(libmruby.a)をリンクする。
4. QSIP用ライブラリの作成 QSIP ボードに搭載されているデバイスを制御するためのクラスライブラリを作成し、 mruby VMに組み込むことで、mrubyアプリケーションからQSIP搭載デバイスの制御を 可能とする。 5. 2 mrubyビルド環境の構築
Fujitsu3 Kyushu Network Technologies CONFIDENTIAL 環境構築
ターゲット環境仕様
mruby ポーティングのターゲット環境(QSIP ボード )の仕様を以下に示す。 メイン MPU プロセッサ MK24FN1M0VLL12 ROM 1MB RAM 256KB
サブサブサブ MPU プロセッサ MKL93Z32VFK4 ROM 32KB RAM 2KB
デバイス 外部フラシュメモリ 32MB センサ 磁力、電圧検出、光、温湿度、静電容量、ジャイロ インターフェイス RS232C 、JTAG
4 環境構築
開発環境仕様
mruby ポーティング作業に使用した環境を以下に示す。
PCPCPC モデル Fujitsu FMVNSS8AE OS Windows 7 Professional (32bit) プロセッサ Intel® Core™ is-3340M CPU (2.7GHz) RAM 4GB
ソフトウェア Cygwin 2.6.1-1 GNU Bison 2.4.1 Ruby 2.3.3 -p222 EWARM 7.80.4
5 環境構築
Windowsビルド環境構築
Windows 上に mruby ビルド環境を構築する
① C言語ビルド環境(Cygwin)のセットアップ
② Ruby のセットアップ
③ パーサージェネレータ(GNU Bison)のセットアップ
④ mrubyソースコードの入手・mrubyのビルド
⑤ 動作確認
6 Windows ビルド環境 ①ターミナル
Cygwin ダウンロード編 公式サイトよりインストール •http ://cygwin.com/
クリックして ダウンロード
参考URL •http://musashi.osdn.jp/cygwin/cygwin.html
7 Windows ビルド環境 ①ターミナル Cygwin インストール編 任意のフォルダを 指定
末尾 .jp を選択
任意のフォルダを 指定
(次スライドに続く)
8 Windows ビルド環境 ①ターミナル
Cygwin インストール編 “Category” の “Devel ” を Install にする “binutils” と “bison”、”gcc-core” を 最新バージョン にする
9 Windows ビルド環境 ②Ruby
Ruby ダウンロード編 公式サイトよりダウンロード •https://rubyinstaller.org/
クリックして ダウンロード
参考URL •http://www.rubylife.jp/install/install/index1.html
10 Windows ビルド環境 ②Ruby
Ruby インストール編 任意のフォルダを 指定
11 Windows ビルド環境 ③パーサー
bison ダウンロード編 公式サイトよりダウンロード •http:// gnuwin32.sourceforge.net/packages/bison.htm
クリックして ダウンロード
参考URL •http://ameblo.jp/oregano-blog/entry-10400001478.htm
12 Windows ビルド環境 ③パーサー bison インストール編 任意のフォルダを 指定
13 Windows ビルド環境 ④ビルド
mruby ソースコード ダウンロード編 GitHub から mruby の最新ソースコードをダウンロード • https://github.com/mruby/mruby
クリックして ダウンロード
取得リビジョン c48aef0b653ba83452c97b1d1017869de2a846b9 参考URL http://qiita.com/ko2a/items/b29acc616f67738465ea
14 Windows ビルド環境 ④ビルド
mruby ソースコード ビルド編 ダウンロードした zip ファイル(mruby --master ) を 任意のディレクトリ に解凍する。
Cygwin を起動し、 解凍先のディレクトリ に移動する。
15 Windows ビルド環境 ④ビルド
mruby ソースコード ビルド編 make コマンドを⼊⼒する ⇒ 下図の画面が表示されたらビルド成功。
16 Windows ビルド環境 ⑤動作確認
Hello, mruby world !! メイク編 mrubyソース(mrubymruby--mastermaster ) の binbinフォルダフォルダ に 「 Hello.rb 」 を作成する。
ソースコード "Hello.rb"
puts “Hello, mruby world !!”
17 Windows ビルド環境 ⑤動作確認
Hello, mruby world !! 動作確認編 mrubymruby--master/binmaster/binディレクトリディレクトリ に移動して、 ././mrubymruby HHello.rbello.rb コマンドを⼊⼒する。 ⇒ Hello, mruby world !! と表示されたら成功。
18 QSIP向けのmrubyクロスビルド
Fujitsu19 Kyushu Network Technologies CONFIDENTIAL 環境構築
mrubyクロスビルド
QSIP 向けクロスビルド環境 IAR Embedded Workbench for ARM を使用して、 mrubyをQSIP向けにクロスビルドする。
① IAR Embedded Workbench for ARM (EWARM) のセットアップ
② mruby のクロスビルド (libmruby.a の作成)
20 mrubyポーティング ①EWARMインストール IAR Embedded Workbench for ARM ダウンロード編 公式サイトより無償評価版(30日期間限定版)をダウンロード •https://www.iar.com/jp/
クリックして ダウンロード
セットアップ手順については ここ を参照してください
21 mrubyポーティング ②ビルド クロスコンパイル libmruby.a 作成編 mrubyソース(mrubymruby--mastermaster ) 内の build_config.rb を編集し、 再度 make すると 「 QSIP 」フォルダ配下に libmruby.a が生成される
MRuby::CrossBuild.new('QSIP') do |conf| toolchain :gcc conf.linker.flags << "-m32"
conf.cc do |cc| cc.command='C:/Devz/ARM/LAUNCHPAD/bin/arm-none-eabi-gcc' cc.flags = [] cc.flags << '-mcpu=cortex-m4 -march=armv7e-m -mtune=cortex-m4' cc.flags << '-mthumb -mlittle-endian -mno-unaligned-access' cc.flags << '-mapcs-frame -mno-sched-prolog -mfpu=fpv4-sp-d16 -mfloat-abi=soft ' cc.flags << '-std=gnu99 ' cc.flags << ' -fno -strict -aliasing -fsigned -char' cc.flags << '-ffunction-sections -fdata-sections ' cc.flags << '-fno-schedule-insns2 ' cc.flags << '--param max-inline-insns-single=1000 ' cc.flags << '-nostartfiles -fno-common ' cc.flags << '-fno-hosted' cc.flags << '-gdwarf-2 -O0 -flto-partition=none -fipa-sra' cc.flags << %w(-DMRB_USE_FLOAT)
cc.defines << %w(MRB_HEAP_PAGE_SIZE=8) cc.defines << %(MRB_IREP_ARRAY_INIT_SIZE=128u) cc.defines << %w(MRB_USE_IV_SEGLIST) cc.defines << %w(KHASH_DEFAULT_SIZE=8) cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20) #cc.defines << %w(DISABLE_STDIO) #if you dont need cc.defines << %w(MRB_GC_STRESS) #no document cc.defines << %w(POOL_PAGE_SIZE=256) #effective only for use with mruby-eval end
conf.archiver do |ar| ar.command = ‘C:/Devz/ARM/LAUNCHPAD/bin/arm-none-eabi-ar’ end
conf.bins = [] conf.build_mrbtest_lib_only # conf.gem :core => "mruby-print" conf.gem :core => "mruby -math“ # conf.gem :core => "mruby-enum-ext“ # conf.gem '../mruby-direct‘ end
22 mrubyポーティング ②ビルド
クロスコンパイル libmruby.a 作成編 mrubyソース(mrubymruby--mastermaster ) 内の build_config.rb を編集し、 再度 make すると 「 QSIP 」フォルダ配下に libmruby.a が生成される build_config.rb
MRuby::Build.new do |conf| # end # load specific toolchain settings # mrbc settings # Gets set by the VS command prompts. # conf.mrbc do |mrbc| if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] # mrbc.compile_options = "-g -B%{funcname} -o-" # The -g toolchain :visualcpp option is required for line numbers else # end toolchain :gcc end # Linker settings # conf.linker do |linker| enable_debug # linker.command = ENV['LD'] || 'gcc' # linker.flags = [ENV['LDFLAGS'] || []] # Use mrbgems # linker.flags_before_libraries = [] # conf.gem 'examples/mrbgems/ruby_extension_example' # linker.libraries = %w() # conf.gem 'examples/mrbgems/c_extension_example' do |g| # linker.flags_after_libraries = [] # g.cc.flags << '-g' # append cflags in this gem # linker.library_paths = [] # end # linker.option_library = ' -l%s ' # conf.gem 'examples/mrbgems/c_and_ruby_extension_example' # linker.option_library_path = '-L%s' # conf.gem :github => 'masuidrive/mrbgems- # linker.link_options = "%{flags} - example', :checksum_hash => o %{outfile} %{objs} %{libs}" '76518e8aecd131d047378448ac8055fa29d974a9' # end # conf.gem :git => '[email protected]:masuidrive/mrbgems- example.git', :branch => 'master', :options => '-v' # Archiver settings # conf.archiver do | archiver | # include the default GEMs # archiver.command = ENV['AR'] || 'ar' conf.gembox 'default' # archiver.archive_options = 'rs %{outfile} %{objs}' # C compiler settings # end # conf.cc do |cc| # cc.command = ENV['CC'] || 'gcc' # Parser generator settings # cc.flags = [ENV['CFLAGS'] || %w()] # conf.yacc do |yacc| # cc.include_paths = ["#{root}/include"] # yacc.command = ENV['YACC'] || 'bison' # cc.defines = %w(DISABLE_GEMS) # yacc.compile_options = '-o %{outfile} %{infile}' # cc.option_include_path = '-I%s' # end # cc.option_define = '-D%s' # cc.compile_options = "%{flags} -MMD -o %{outfile} - # gperf settings c %{infile}" # conf.gperf do |gperf|
23 mrubyポーティング ②ビルド
build_config.rb (続き )
# gperf.command = 'gperf' # gperf.compile_options = '-L ANSI-C -C -p -j1 -i 1 -g -o -t - MRuby::Build.new('test') do |conf| N mrb_reserved_word -k"1,3,$" %{infile} > %{outfile}' # Gets set by the VS command prompts. # end if ENV[' VisualStudioVersion '] || ENV['VSINSTALLDIR'] toolchain :visualcpp # file extensions else # conf.exts do |exts| toolchain :gcc # exts.object = '.o' end # exts.executable = '' # '.exe' if Windows # exts.library = '.a' enable_debug # end conf.enable_bintest conf.enable_test # file separetor # conf.file_separator = '/' conf.gembox 'default' end # bintest # conf.enable_bintest MRuby::Build.new('bench') do |conf| end # Gets set by the VS command prompts. if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] MRuby::Build.new('host-debug') do |conf| toolchain :visualcpp # load specific toolchain settings else toolchain :gcc # Gets set by the VS command prompts. conf.cc.flags << '-O3' if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] end toolchain :visualcpp else conf.gembox 'default' toolchain :gcc end end # Define cross build settings enable_debug # MRuby::CrossBuild.new('32bit') do |conf| # toolchain :gcc # include the default GEMs # conf.gembox 'default' # conf.cc.flags << "-m32" # conf.linker.flags << "-m32" # C compiler settings # conf.cc.defines = %w(MRB_ENABLE_DEBUG_HOOK) # conf.build_mrbtest_lib_only # # Generate mruby debugger command (require mruby-eval) # conf.gem 'examples/mrbgems/c_and_ruby_extension_example' conf.gem :core => "mruby-bin-debugger" # # conf.test_runner.command = 'env' # bintest # # conf.enable_bintest # end end
24 mrubyポーティング ②ビルド
build_config.rb (続き ) ※ 赤字は追加コード
#add QNET MRuby::CrossBuild.new('QSIP') do |conf| toolchain :gcc
conf.linker.flags << "-m32"
conf.cc do |cc| cc.command='C:/Devz/ARM/LAUNCHPAD/bin/arm-none-eabi-gcc' cc.flags = [] cc.flags << '-mcpu=cortex-m4 -march=armv7e-m -mtune=cortex- m4' cc.flags << '-mthumb -mlittle-endian -mno-unaligned-access' cc.flags << '-mapcs-frame -mno-sched-prolog -mfpu=fpv4-sp-d16 -mfloat-abi=soft ' cc.flags << '-std=gnu99 ' cc.flags << '-fno-strict-aliasing -fsigned-char' cc.flags << '-ffunction-sections -fdata-sections ' cc.flags << ' -fno -schedule -insns2 ' cc.flags << '--param max-inline-insns-single=1000 ' cc.flags << '-nostartfiles -fno-common ' cc.flags << '-fno-hosted' cc.flags << '-gdwarf-2 -O0 -flto-partition=none -fipa-sra' cc.flags << %w(-DMRB_USE_FLOAT) cc.defines << %w(MRB_HEAP_PAGE_SIZE=8) cc.defines << %(MRB_IREP_ARRAY_INIT_SIZE=128u) cc.defines << %w(MRB_USE_IV_SEGLIST) cc.defines << %w(KHASH_DEFAULT_SIZE=8) cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20) #cc.defines << %w(DISABLE_STDIO) #if you dont need cc.defines << %w(MRB_GC_STRESS) #no document cc.defines << %w(POOL_PAGE_SIZE=256) #effective only for use with mruby-eval end
conf.bins = [] conf.build_mrbtest_lib_only # conf.gem :core => "mruby-print" # conf.gem :core => "mruby-math" # conf.gem :core => "mruby-enum-ext" # conf.gem '../mruby-direct' end
25 QSIPアプリケーションへの mruby組み込み
Fujitsu26 Kyushu Network Technologies CONFIDENTIAL QSIPアプリケーションへのmruby組み込み
QSIP 用の C言語アプリケーションに mruby ライブラリ (libmruby.a )および mruby アプリケー ションをリンクする。
① EWARM 設定
1. QSIPアプリケーションへのmrubyソースコードの追加
2. インクルードディレクトリに mruby のインクルードパスを追加
3. リンカ設定でmrubyライブラリ (libmruby.a) を追加
② mruby 動作確認用アプリケーションの作成
27 mrubyポーティング ②ビルド EWARMへのmruby ソースコード追加 EWARM の ワークスペース > ファイル(既存ソースコード ) に mruby ソースコードを追加する
28 mrubyポーティング ②ビルド EWARMインクルードディレクトリの追加 EWARM の プロジェクト > オプション > カテゴリ :C,C++ コンパイラ > タブ :プリプロセッサ より、追加インクルードディレクトリに mruby ヘッダソースのパスを追加
29 mrubyポーティング ②ビルド EWARMのリンカ設定 EWARM の プロジェクト > オプション > カテゴリ:リンカ > タブ:ライブラリ より 前スライドで生成したライブラリ(libmruby.a )のパスをリンカに追加する
30 mrubyポーティング ③動作確認 mruby 動作確認用のアプリケーション作成 下記のソースコードを作成してQSIPアプリケーションをビルドし、アプリケーションを含 むファームウェアを QSIP ボードに書き込んで実⾏する。 QSIPアプリケーションからmruby VMが起動できていることを確認する。
#include "mruby.h" #include
void main(void) { printf(“mrb_open¥n”); // mruby 仮想マシンの作成 mrb_state *mrb = mrb_open ();
printf(“mrb_close¥n”); // 仮想マシンを閉じる mrb_close (mrb );
printf(“finish¥n”); }
31 QSIP用ライブラリの作成
Fujitsu32 Kyushu Network Technologies CONFIDENTIAL QSIPアプリケーションへのmruby組み込み
QSIP ボード用の mrbgems (mruby クラスライブラリ )を作成し、 libmruby.a にライブラリを 追加する。
① mrbgems 作成
② mruby VMへのmrbgems追加
③ mruby 動作確認用アプリケーションの作成
33 mrubyポーティング ④ライブラリ化
mrbgems 作成 mruby-master¥mrbgems以下に下記ディレクトリ、ファイルを作成する.
mruby-master¥ mrbgems¥ sample_qsip ¥ mrbgem.rake 作成対象 src ¥ sample_qsip.c
34 mrubyポーティング ④ライブラリ化 mrbgems 作成 mruby-master¥mrbgems¥sample_qsip¥mrbgem.rake
MRuby::Gem::Specification.new('sample_qsip') do |spec| spec.license = 'MIT' spec.author = 'QNET' spec.summary = 'QSIP sample library' end
35 mrubyポーティング ④ライブラリ化 mrbgems 作成 mruby-master¥mrbgems¥qsip_sample¥src¥qsip_sample.c
#include "mruby.h" #include
// ライブラリ化する処理 static mrb_value mrb_sample_qsip(mrb_state *mrb, mrb_value self) { puts("mruby on QSIP"); // 文字列を表示 return mrb_nil_value(); // nil を返す }
void mrb_sample_qsip_gem_init(mrb_state* mrb) { // Sample_QSIP モジュールの登録 struct RClass *class_sample_qsip = mrb_define_module(mrb, “Sample_QSIP"); // sample_qsip メソッドの登録 mrb_define_class_method(mrb, class_sample_qsip, “sample_qsip", mrb_sample_qsip, ARGS_NONE()); }
void mrb_sample_qsip_gem_final (mrb_state * mrb ) { }
Sample_QSIP :: sample_qsip メソッドとして実装した。
36 mrubyポーティング ④ライブラリ化
mruby VMへのmrbgems 追加 MRuby::CrossBuild.new('QSIP') do |conf| toolchain :gcc build_config.rb に conf.linker.flags << "-m32"
conf.cc do |cc| 作成した mrbgems を追記し、 cc.command ='C:/ Devz /ARM/LAUNCHPAD/bin/arm -none -eabi -gcc ' cc.flags = [] 再度 cc.flags << '-mcpu=cortex-m4 -march=armv7e-m -mtune=cortex-m4' make する。 cc.flags << '-mthumb -mlittle-endian -mno-unaligned-access' cc.flags << '-mapcs-frame -mno-sched-prolog -mfpu=fpv4-sp-d16 -mfloat-abi=soft ' cc.flags << '-std=gnu99 ' cc.flags << '-fno-strict-aliasing -fsigned-char' cc.flags << ' -ffunction -sections -fdata -sections ' build ¥QSIP ¥lib フォルダ 配下には cc.flags << '-fno-schedule-insns2 ' cc.flags << '--param max-inline-insns-single=1000 ' cc.flags << '-nostartfiles -fno-common ' 作成した mrbgems が追加された cc.flags << '-fno-hosted' cc.flags << '-gdwarf-2 -O0 -flto-partition=none -fipa-sra' libmruby.a が生成される cc.flags << %w(-DMRB_USE_FLOAT) cc.defines << %w(MRB_HEAP_PAGE_SIZE=8) cc.defines << %(MRB_IREP_ARRAY_INIT_SIZE=128u) cc.defines << %w(MRB_USE_IV_SEGLIST) cc.defines << %w(KHASH_DEFAULT_SIZE=8) cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20) #cc.defines << %w(DISABLE_STDIO) #if you dont need cc.defines << %w(MRB_GC_STRESS) #no document cc.defines << %w(POOL_PAGE_SIZE=256) #effective only for use with mruby-eval end
conf.archiver do |ar| ar.command = ‘C:/Devz/ARM/LAUNCHPAD/bin/arm-none-eabi-ar’ 作成した end conf.bins = [] mrbgems conf.build_mrbtest_lib_only conf.gem :core => "mruby-print" を追記 # conf.gem :core => "mruby-math“ # conf.gem :core => "mruby-enum-ext“ conf.gem :core => " mruby -sample -qsip “ # conf.gem '../mruby-direct‘ end
37 mrubyポーティング ④ライブラリ化 mrbgems 動作確認用のアプリケーション作成 下記のソースコード (app.rb) を作成する。 puts "mruby application start." Sample_QSIP::sample_qsip # mrbgems のメソッド呼び出し puts "mruby application end."
mruby コンパイラ (mrbc ) でコンパイルする。 mrbc –Bappbin –o./app.c app.rb
出⼒された app.c はアプリケーションプロジェクトに追加する。
38 mrubyポーティング ④ライブラリ化 mrbgems 動作確認用のアプリケーション作成 下記のソースコードを作成して、mrbgems組込み済みのlibmruby.aとリンクして QSIP アプリケーションを作成する。アプリケーションを含むファームウェアを QSIP ボード に書き込んで実⾏する。 QSIPアプリケーションからmrbgemsのメソッドが呼び出されることを確認する。
#include "mruby.h" #include "mruby/irep.h" #include
void main(void) { extern uint8_t appbin[]; // app.c のアプリケーションバイナリを外部参照する mrb_state *mrb = mrb_open(); printf ("mruby VM opened. ¥n");
mrb_load_irep(mrb, appbin); // mruby アプリケーション実⾏ printf("mruby application done.¥n");
mrb_close (mrb ); printf("mruby VM closed.¥n"); }
39