OSvへmruby-cfuncを移植してみたらとてもあっさりと動いた話
OSvへmrubyを移植してみたらとてもあっさりと動いた話 - かーねる・う゛いえむにっきの続きです。
さて、OSvでmrubyが動くようになったのですがmrbgemsを追加していないのでこのままではAPIがむっちゃ少なくてなにも書けません。
でもmrbgemsの移植ってそれぞれ依存ライブラリあったりして動かすの面倒よなー、とか思ってたら、こんなのが目にとまりました。
GitHub - mobiruby/mruby-cfunc: Interface to C functions on mruby
|
\ __ /
_ (m) _ピコーン
|ミ|
/ `´ \
('A`)
ノヽノヽ
くく
OSvってプロセスがカーネル権限で走っていて何でも出来るしカーネルのC関数直接叩けるので、これ入れると何でもありになるんじゃね…?
危険だ、ヤバい。
じゃあ移植してみよう(いいのか)。
てな訳で、3分mrubyクッキング〜。
手始めに、build_config.rbにmruby-cfuncをくわえます。
conf.gem :github => 'mobiruby/mruby-cfunc', :branch => 'master'
これでビルドを試してみると、当然ffi.hがねーよって怒られます。
本来ならばlibffiもmrubyのようにOSvへ移植すべきでしょうが、幸いなことにOSvはある程度Linuxとの互換性があります。
…ので、今回は、libffiのクロスコンパイルを避けてLinuxバイナリとのリンクを目指します。
ヘッダはLinuxからコピーしちゃいます。Ubuntuだとこの辺ですね:
$ dpkg -L libffi-dev|grep ffi.h /usr/include/x86_64-linux-gnu/ffi.h
これをosv/mruby/includeを作ってそこに入れました。
そして、コンパイル時に見に行くようにcc.flagsへ”-I../../mruby/include”を追加します。
そうするとビルドは通りますが、libffiをリンクしていないためこのままでは動きません。
ダイナミックリンクライブラリのロード面倒だな、スタティックに行けないかなって思ってたら、こんなのを見つけました。
$ dpkg -L libffi-dev|grep libffi_pic.a /usr/lib/x86_64-linux-gnu/libffi_pic.a
これだ!
というわけで、これをosv/mruby/へコピー。
mruby/build.mkにlibffi_pic.aを足します。
mruby-objects = mruby/mruby.o mruby/libmruby.a mruby/libffi_pic.a mirb-objects = mruby/mirb.o mruby/libmruby.a mruby/libffi_pic.a
で、sudo make clean external allしてみるとビルド成功!
早速OSvでmirbを起動して試してみましょう。
syuu@hiratake:~/osv$ sudo ./scripts/run.py -n -v -e "/mirb.so" SCRIPT, tap0 acpi 0 apic 0 acpi 1 apic 1 acpi 2 apic 2 acpi 3 apic 3 APIC base fee00000 OSv v0.02-33-gfb74f15 Copyright 2013 Cloudius Systems locale works All ACPI Tables successfully acquired VFS: mounting ramfs at / VFS: mounting devfs at /dev ACPI: RSDP 0xfd8d0 00014 (v00 BOCHS )ACPI: RSDT 0x3fffe380 00034 (v01 BOCHS BXP CRSDT 00000001 BXPC 00000001)ACPI: FACP 0x3fffff80 00074 (v01 BOCHS BXPCFACP 00 000001 BXPC 00000001)ACPI: DSDT 0x3fffe3c0 011A9 (v01 BXPC BXDSDT 00000001 I NTL 20100528)ACPI: FACS 0x3fffff40 00040ACPI: SSDT 0x3ffff6e0 00858 (v01 BOCHS BXPCSSDT 00000001 BXPC 00000001)ACPI: APIC 0x3ffff5b0 00090 (v01 BOCHS BXPCAPIC 00000001 BXPC 00000001)ACPI: HPET 0x3ffff570 00038 (v01 BOCHS BXPCHPET 0000000 1 BXPC 00000001)ACPI: RSDP 0xfd8d0 00014 (v00 BOCHS )ACPI: RSDT 0x3fffe380 00034 (v01 BOCHS BXPCRSDT 00000001 BXPC 00000001)ACPI: FACP 0x3fffff80 00074 (v01 BO CHS BXPCFACP 00000001 BXPC 00000001)ACPI: DSDT 0x3fffe3c0 011A9 (v01 BXPC B XDSDT 00000001 INTL 20100528)ACPI: FACS 0x3fffff40 00040ACPI: SSDT 0x3ffff6e0 00 858 (v01 BOCHS BXPCSSDT 00000001 BXPC 00000001)ACPI: APIC 0x3ffff5b0 00090 (v01 BOCHS BXPCAPIC 00000001 BXPC 00000001)ACPI: HPET 0x3ffff570 00038 (v01 BOCHS BXPCHPET 00000001 BXPC 00000001)ACPI: RAM disk at 0x0xffffc0003e26b000 (4096K by tes) Initializing network stack... Done! eth0: ethernet address: 52:54:0:12:34:56 VFS: mounting zfs at /usr zfs: mounting osv/usr from device /dev/vblk0.1 [I/38 dhcp]: Waiting for IP... [I/329 dhcp]: Configuring eth0: ip 192.168.122.89 subnet mask 255.255.255.0 gate way 192.168.122.1 [I/329 dhcp]: Server acknowledged IP for interface eth0 mirb - Embeddable Interactive Ruby Shell This is a very early version, please test and report errors. Thanks :) ptr = CFunc::Pointer.malloc(12) > => <CFunc::Void pointer=0xffffc0003bea8e50> result = CFunc::call(CFunc::Pointer, "strcpy", ptr, "Hello") stub dlclose() > => <CFunc::Void pointer=0xffffc0003bea8e50> p result.to_s > "Hello" => "Hello" > => #<CFunc::UInt64:0xffffc0003bbf25a0> CFunc::call(CFunc::UInt64, "time", nil) stub dlclose() > => #<CFunc::UInt64:0xffffc0003bbf22d0> CFunc::call(CFunc::UInt64, "time", nil) stub dlclose() > => #<CFunc::UInt64:0xffffc0003bbdcfa0> CFunc::call(CFunc::UInt64, "time", nil) stub dlclose() > => #<CFunc::UInt64:0xffffc0003bbdce50> CFunc::call(CFunc::UInt64, "time", nil) stub dlclose() > => #<CFunc::UInt64:0xffffc0003bbdcd00> CFunc::call(CFunc::UInt64, "time", nil) stub dlclose() > => #<CFunc::UInt64:0xffffc0003bbdcbb0> CFunc::call(CFunc::UInt64, "time", nil) stub dlclose() > => #<CFunc::UInt64:0xffffc0003bbdca60>
構造体とかを使っていると指定が面倒くさいので、取り敢えずstrcpyとtimeを試してみましたが、どうやら動いてそうですね!
てなわけで、OSvはLinuxと互換性があってライブラリの移植が簡単だなぁ、というお話でした(今回はOSv関係あった!)