chez沼
chez-sys
前回からの続き。rustからchezschemeを動かそうと言う試み。lib.rsに少し追加して、何かやらせようという算段。
#[cfg(test)] mod tests { ▶︎ Run Tests|Debug use super::*; fn myadd(x: i64, y: i64) -> i64 { unsafe { let ti = Stop_level_value(Sstring_to_symbol("+".as_ptr() as *const i8)); Sfixnum_value(Scall2(ti, Sfixnum(x), Sfixnum(y))) } } #[test] fn it_works() { ▶︎ Run Test|Debug unsafe { Sscheme_init(None); Sregister_boot_file("/tmp/t/petite.boot".as_ptr() as *const i8); // Sregister_boot_file("/tmp/t/scheme.boot".as_ptr() as *const i8); Sbuild_heap(0 as *const i8, None); println!("{}", myadd(123, 456)); } } }
petite.bootは、抜き出してきて、/tmp/t に置いた。これで走らせると
sakae@pen:/tmp/chez-sys$ cargo t Finished test [unoptimized + debuginfo] target(s) in 0.01s Running unittests (target/debug/deps/chez_sys-143b01c762533554) running 1 test cannot open boot file /tmp/t/petite.boot S_generic_invoke return error: test failed, to rerun pass '--lib'
見事に失敗してる。これが動くべきなんだろうけど、いまいち自信が無い。これはもう、一旦rustを離れて、慣れ親しんだC言語でやってみるべきだろう。
chez scheme
chezはたまに使う亊があるけど、単にaptから入れてる、一般ユーザーレべる。どんな構成になってるかなんて、知る由もない。で、周り道だと思いつつ、周りをあたってみた。
sakae@deb:/usr/lib$ tree csv9.5.4/ csv9.5.4/ └── ti3le ├── chezscheme.boot -> scheme.boot ├── equates.h ├── kernel.o ├── main.o ├── petite.boot ├── scheme.boot ├── scheme.h └── scheme-script.boot -> scheme.boot
ふむ、核心部分だな。なんか、オブジェクトファイルが置いてあるって、中々新鮮。
sakae@deb:/usr/lib/csv9.5.4/ti3le$ nm main.o | grep ' S' U Sbuild_heap U Scall1 U Senable_expeditor U Sinteger U Skernel_version U Sregister_boot_file U Sretain_static_relocation U Sscheme_deinit U Sscheme_init U Sscheme_program U Sscheme_script U Sscheme_start U Sset_verbose U Sstring U Sstring_to_symbol U Sstring_utf8 U Stop_level_value
main.oってのは、多分schemeのメインなんだろうね。こいつにライブラリィーを組み込むと、ユーザーが起動するschemeになるんだな。
Debianの場合はschemeの本体が/etc/alternatives/scheme経由で、chezschemeに接続されてた。
sakae@deb:/usr/bin$ ldd chezscheme linux-gate.so.1 (0xb7f0a000) libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb7b37000) libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xb7b31000) libtinfo.so.6 => /lib/i386-linux-gnu/libtinfo.so.6 (0xb7b08000) libz.so.1 => /lib/i386-linux-gnu/libz.so.1 (0xb7aeb000) liblz4.so.1 => /lib/i386-linux-gnu/liblz4.so.1 (0xb7ac7000) libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xb7aa5000) libuuid.so.1 => /lib/i386-linux-gnu/libuuid.so.1 (0xb7a9b000) libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb78b2000) /lib/ld-linux.so.2 (0xb7f0c000)
核心部分にあるkernel.oがschemeの機能を搭載してるに違いない。
sakae@deb:/usr/lib/csv9.5.4/ti3le$ nm kernel.o | grep Sscheme_ 00034420 T Sscheme_deinit 000338b0 T Sscheme_init 000343c0 T Sscheme_program 00034390 T Sscheme_script 00034200 T Sscheme_start
どうやらビンゴだな。
参考に、chezのファイルの役割を解説したものを見付けた。 Welcome to the ChezScheme wiki! see Runtime C側をRuntimeって表現してるのが、目から鱗ですよ。
at Debian 32bit
手慰めで、世界で一番簡単なchezの呼出をやってみる。舞台は、debian 32bit
#include "scheme.h" #include <stdio.h> double myadd(double x, double y) { ptr times = Stop_level_value(Sstring_to_symbol("+")); return Sflonum_value(Scall2(times, Sflonum(x), Sflonum(y))); } int main(){ Sscheme_init(NULL); Sregister_boot_file("./petite.boot"); Sregister_boot_file("./scheme.boot"); Sbuild_heap(0, 0); printf("%f\n", myadd(1.111, 2.222)); }
実験コードは、浮動少数点の足し算。これをkernel.oと共にコンパイルして、chezの機能を使ってみようという作戦。
@deb:/tmp/t$ cc hoge.c kernel.o -lm -ldl -ltinfo -lz -lpthread -luuid -llz4 /usr/bin/ld: cannot find -llz4 collect2: error: ld returned 1 exit status
が、あろう亊か、変なエラーで引掛った。悩んでいてもしょうがないので、別環境でやってみる。
at Debian 64bit
rustのサンプル chez-sys/build.rsの例に合わせてコンパイル・インストールすると
sakae@pen:/usr/lib/csv9.5.6/a6le$ ls libkernel.a libz.a petite.boot scheme.boot scheme-script.boot liblz4.a main.o revision scheme.h
こんな風になったので、必要な物を取出して/tmp/tに配置。libkernel.aは、リナスに怒られそうなので、libchez.aに改名してる。
sakae@pen:/tmp/t$ cc hoge.c -L/tmp/t -lchez -lz -lm -llz4 -ldl -luuid sakae@pen:/tmp/t$ ./a.out 3.333000
-ldl,-lm,-luuidとかの必要そうなのは、/usr/bin/schemeをlddで成分調査して入れ込んだ。
どうやら動いてくれたな。
蛇足になるけど、ライブラリィーのリンクを忘れると、勿論下記のようなエラーになる。
sakae@pen:/tmp/t$ cc hoge.c -L/tmp/t -lchez -lz -lm -llz4 -ldl /usr/bin/ld: /tmp/t/libchez.a(stats.o): in function `S_unique_id': stats.c:(.text+0x1c): undefined rehference to `uuid_generate' collect2: error: ld returned 1 exit status
この例だと、 S_unique_id
の関数で使ってるやつが名前解決出来無いとな。一つぐらいのエラーなら追い掛ける元気も有るけど、バーと出て来るとうんざりするね。手本に習うのが一番だ。
at FreeBSD 32bit
FreeBSDにもportsで用意されてるので、試してみた。
[sakae@fb /tmp/ti3fb]$ ldd /usr/local/bin/chez-scheme /usr/local/bin/chez-scheme: libm.so.5 => /lib/libm.so.5 (0x204bd000) libncursesw.so.9 => /lib/libncursesw.so.9 (0x204ef000) libthr.so.3 => /lib/libthr.so.3 (0x20555000) libossp-uuid.so.16 => /usr/local/lib/libossp-uuid.so.16 (0x2057e000) libuuid.so.1 => /usr/local/lib/libuuid.so.1 (0x2058d000) libc.so.7 => /lib/libc.so.7 (0x20594000)
核心部分は、/usr/local/lib/csv9.5.4/ti3fbにあるんで、丸ごと/tmpにコピー。コンパイル時に長々PATHを入力するのが面倒なので、単なる手抜きです。
[sakae@fb /tmp/ti3fb]$ cc hoge.c kernel.o -lm -lncursesw -lthr -lossp-uuid -luuid ld: error: unable to find library -lossp-uuid ld: error: unable to find library -luuid cc: error: linker command failed with exit code 1 (use -v to see invocation) [sakae@fb /tmp/ti3fb]$ cc hoge.c kernel.o -L/usr/local/lib -lm -lncursesw -lthr -lossp-uuid -luuid [sakae@fb /tmp/ti3fb]$ ./a.out 3.333000
まあ、動いたな。
FreeBSDとくれば次はOpenBSDかと思うんだけど、portsには無い。Ciscoの支援を嫌って親分が許しませんなのかな。ライセンスは、APACHE20 だから、目くじら立てる程の亊もないな。
=> Attempting to fetch http://distfiles.pirateparty.in/ashish/chez-scheme-boot-ta6fb-9.5.6.tar.xz
コンパイルに必要なやつは、こういう所からDLしてる。って、何よそれ。
source tour
折角なので、ソースと対面しとく。
BUILDING
上であげたOpenBSDはサポートしていないのか?
On OpenBSD, Chez Scheme must be built and installed on a filesystem that is mounted with wxallowed.
こんな注意書きがあるって亊は、過去にはサポートされてたって亊だ。更に更新記録であるLOGをみると、
9.4.1 changes: : - commented out one of the thread mats that consistently causes indefinite delays under Windows and OpenBSD due to starvation. thread.ms
て亊で、痕跡はある。gitからheadを取ってきて、tagを確認するとv9.4ってのが存在。switchしてみたけど、OpenBSDとかは現れず。残念。
boot
[sakae@fb /tmp/csv9.5.6]$ ls boot a6le/ arm32le/ i3osx/ ta6osx/ ti3osx/ a6nt/ i3le/ ta6le/ ti3le/ a6osx/ i3nt/ ta6nt/ ti3nt/
現在、公式にサポートしてるのは、これだけ。頭についてるtは、スレッド版。i3とかa6は、インテルさんの石の区別。その後ろにあるleはlinux。osx,ntは言わずと知れたやつ。
configure
その証拠は、手書きされたconfigureにも残っている。どんな石とOSがサポートされてたかは、このファイルを開いてみればよい。面倒なら、これでもOK
[sakae@fb /tmp/csv9.5.6]$ ls s/M* s/Mf-a6fb s/Mf-arm32le s/Mf-i3ob s/Mf-ta6nb s/Mf-ti3nb s/Mf-a6le s/Mf-base s/Mf-i3osx s/Mf-ta6nt s/Mf-ti3nt s/Mf-a6nb s/Mf-cross s/Mf-i3qnx s/Mf-ta6ob s/Mf-ti3ob :
configureできっちりMakefileを作成しなかった、つけがこういう所に現れている。それぞれが、個別のシステムのMakefileになる。
Mf-baseは、共通なMakefileだ。Schemeなソースをどんな風にコンパイルするとかの設定とか、実際のコンパイルはS式になってるとか、見所満載ですよ。
from make log
Makefileをチマチマ見ていくよりも、実行来歴を見るのて手っ取り速い。 ログは、
make |& tee LOG-make
とかやって採取するのがお手軽だ。
ar rc ../boot/a6le/libkernel.a statics.o segment.o alloc.o symbol.o intern.o gc\ wrapper.o gc-011.o gc-ocd.o gc-oce.o number.o schsig.o io.o new-io.o print.o fa\ sl.o stats.o foreign.o prim.o prim5.o flushcache.o schlib.o thread.o expeditor.\ o scheme.o compress-io.o i3le.o gcc -m64 -msse2 -Wpointer-arith -Wall -Wextra -Werror -Wno-implicit-fallthroug\ h -O2 -c -DX86_64 -I../boot/a6le -I../zlib -I../lz4/lib main.c cp -p main.o ../boot/a6le/main.o gcc -m64 -msse2 -Wpointer-arith -Wall -Wextra -Werror -Wno-implicit-fallthroug\ h -O2 -rdynamic -o ../bin/a6le/scheme ../boot/a6le/main.o ../boot/a6le/libkern\ el.a -lm -ldl -lrt -luuid ../zlib/libz.a ../lz4/lib/liblz4.a
Runtime関係のコンパイル
'(delete-file (string-append (path-root "../boot/a6le/scheme.boot"\ ) ".covin"))'\ '(apply #%$make-boot-file "../boot/a6le/scheme.boot" (quote a6le) \ (quote ("petite"))'\ ' (map symbol->string (quote (cpnanopass.a6le compile.a6le cback.\ a6le))))'\ '(when #f (profile-dump-html))'\ '(when #f (profile-dump-data "source.pd"))'\ '(when #f (profile-dump-data "block.pd"))'\ > script.all
こちらは、scheme.bootの作りかただ。
cannot find -llz4
冒頭の方で取り上げたdebian 32bit のリンク問題、悔しいのでネットで調べてみた。sudo ldconfig してキャッシュを更新してみたらってのが出でた。もう一つ、リンクを作り直したらってのも有った。ldconfigは効果がなかったので、2番目の方法。
sakae@deb:/lib/i386-linux-gnu$ ls -l liblz4* lrwxrwxrwx 1 root root 15 May 5 2021 liblz4.so.1 -> liblz4.so.1.9.3 -rw-r--r-- 1 root root 140828 May 5 2021 liblz4.so.1.9.3 sakae@deb:/lib/i386-linux-gnu$ sudo ln -s liblz4.so.1.9.3 liblz4.so sakae@deb:/lib/i386-linux-gnu$ sudo ldconfig
ちゃんとリンクが張られていた。でも、libzの方に習って、しつこくリンクを追加。おまけでldconfigも実行。
sakae@deb:/tmp/t$ cc hoge.c kernel.o -lm -ldl -ltinfo -lz -lpthread -luuid -llz4 sakae@deb:/tmp/t$ ./a.out 3.333000 sakae@deb:/tmp/t$ ldd ./a.out linux-gate.so.1 (0xb7eda000) libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb7b0c000) libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xb7b06000) libtinfo.so.6 => /lib/i386-linux-gnu/libtinfo.so.6 (0xb7add000) libz.so.1 => /lib/i386-linux-gnu/libz.so.1 (0xb7ac0000) libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xb7a9e000) libuuid.so.1 => /lib/i386-linux-gnu/libuuid.so.1 (0xb7a94000) liblz4.so.1 => /lib/i386-linux-gnu/liblz4.so.1 (0xb7a70000) libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7887000) /lib/ld-linux.so.2 (0xb7edc000)
何故か動いた。どうもリナは挙動不審な部分があるな。余り深入りしないで、そっとしておこう。
single binary
petite等は、複数のファイルから構成されてる。少くともRuntimeに必要なpetiteと、Schemeのソースをコンパイルしたpetite.bootが必要。
sakae@pen:/tmp/csv9.5.6/s$ petite --verbose trying /usr/lib/csv9.5.6/a6le/petite.boot...opened version and machine type check Petite Chez Scheme Version 9.5.6 Copyright 1984-2021 Cisco Systems, Inc. : sakae@pen:/tmp/csv9.5.6/s$ scheme --verbose trying /usr/lib/csv9.5.6/a6le/scheme.boot...opened version and machine type check trying /usr/lib/csv9.5.6/a6le/petite.boot...opened version and machine type check Chez Scheme Version 9.5.6
ファイルが複数になってると扱いにくい。gaucheは多数のユーザー要求で、ひとつのファイルにまとめてしまう亊が出来るようになった。これが世界の潮流と思っていたら、前回、一つのファイルにpetiteをまとめてしまう技を、中国の方が発表されてた。
最初に、make.txtに習ってmain.cをコンパイル。foo.ssは簡易なrepl。この2つをsession.txtに習って、融合させるとな。
chez-sys lib -> bin but …
chez-sysのlib.rsにあるtestを走らせていたけど、ひょっとしたらbinに切り換えたら動くようにならないか。淡い期待を込めて、ちょっとソースを改造。 Cargo.toml
#[lib] #name = "chez_sys" #path = "src/lib.rs"
libを無効にするとbinになるんだろうな。
src/main.rs
mod bindings; pub use bindings::*; fn myadd(x: i64, y: i64) -> i64 { unsafe { let ti = Stop_level_value(Sstring_to_symbol("+".as_ptr() as *const i8)); Sfixnum_value(Scall2(ti, Sfixnum(x), Sfixnum(y))) } } fn main() { unsafe { Sscheme_init(None); Sregister_boot_file("/tmp/t/petite.boot".as_ptr() as *const i8); Sregister_boot_file("/tmp/t/scheme.boot".as_ptr() as *const i8); Sbuild_heap(0 as *const i8, None); println!("{}", myadd(123, 456)); } }
lib.rsの名前をmain.rsに変更しつつ、体裁をbinを作るようにした。
sakae@pen:/tmp/chez-sys$ cargo r Finished dev [unoptimized + debuginfo] target(s) in 0.01s Running `target/debug/chez-sys` cannot open boot file /tmp/t/petite.boot/tmp/t/scheme.boot S_generic_invoke return
やっぱり、エラーだ。何か特有の処理が必要なんだろうか?
rust 本、2冊追加
なかなかよさげ。オイラーみたいに野生の感を頼りにしてきた人が、まとめで読む本かな
手を動かして考えればよくわかる高効率言語 Rust 書きかた・作りかた
誰でも知ってるPythonからrustに乗り換えて自慢する本。みんなrustなんて知らないからrust語をPython語に翻訳してみせて、ドヤ顔するのにうってつけ。ざっと見、面白そうな話題を扱っているな。波形合成なんて面白そう。