V言語

携帯の中身

前回ipadのスタンドを求めて100均へ行った事を書いた。 その時、勢いで目の前に有った、スマホ用充電兼通信用ケーブルも買ってしまった。USBタイプAとタイプCのコネクタが付いた奴。

なんでかと言うと、着信音をモールス信号にしたく、他の音源が見えるなら、どれかをモールス音に置き換えてしまいたいから。

Orz、携帯側の口が合わないぞ。タイプCのやつじゃないのか? 調べてみたらマイクロUSBってやつだった。そんな規格が有るなんて初めて知ったぞ。で、はたと気が付いた。

携帯買った時に付けて貰った、充電器一式どうなってる。充電器側はUSBタイプAだった。もっと早く気が付けよ。まったくボケてるぞ。いや、ここは100均の魔力に憑りつかれた事にして、自分を慰めておこう。

長い前ぶりだったけど、本題。残念ながら音源は露出してなかった。ユーザーが取った動画とかは、内蔵のSDメモリーに保存されるんだけど、携帯(システム)が使うデータは、ユーザーの手が届かない場所に入っている風。但し、待ち受けに使うような絵は、

├── Pictures
│   ├── 風景1.jpg
│   └── 風景2.jpg

こんな具合に露出してた。富士山と浜辺の絵だったよ。権利の関係でROMに焼けなかったのかな?

├── DCIM
│   └── 100KYCRA
│       ├── KIMG0001.JPG
│       ├── KIMG0002.JPG
│       └── KVID0003.mp4

自分が取った写真とか動画は、こんな具合だった。

└── VoiceRecordings
    └── 20210328_voicedata.wav

年寄り用携帯なんで、詐欺電話はきちんと録音出来るようになってる。おまけで、ボイスレコーダーの機能も付いてた。

debian:VoiceRecordings$ play 20210328_voicedata.wav
play WARN alsa: can't encode 0-bit Unknown or not applicable

20210328_voicedata.wav:

 File Size: 634k      Bit Rate: 719k
  Encoding: Signed PCM
  Channels: 1 @ 16-bit
Samplerate: 44100Hz
Replaygain: off
  Duration: 00:00:07.06

In:100%  00:00:07.06 [00:00:00.00] Out:311k  [      |      ]        Clip:0

CD品質で録音してるのね。近頃の電話って、そんなに音域が広いのか。

├── IrDA
│   └── telecom
│       └── pb.vcf

IrDAって、赤外線通信だよな。そこに置いてあるデータって、アドレス帳かな? 開いてみれば分かるな。

BEGIN:VCARD
VERSION:2.1
N;CHARSET=SHIFT_JIS:権兵衛;;;;
SOUND;X-IRMC-N;CHARSET=SHIFT_JIS:ゴン;;;;
TEL;PREF;CELL:080xxxxyyyy
EMAIL;PREF;CELL:xxxxxxx@eyyyy.ne.jp
X-GNO:0
X-GN;CHARSET=SHIFT_JIS:グループ0
X-CLASS:PUBLIC
REV:20090222T222255Z
END:VCARD

携帯変えた時、ショップでアドレス帳を移行してくれたけど、自分でやるなら、赤外線通信でやればいいのか。このカードからすると先代の携帯は12年使ってた事になるな。それにしてもシフトJISがはびこっているな。

debian:databases$ ls -l
total 28
-rwxr----- 1 sakae sakae 16384 Mar 31 04:58 datafolder.db*
-rwxr----- 1 sakae sakae  8720 Mar 31 04:58 datafolder.db-journal*
debian:databases$ file datafolder.db
datafolder.db: SQLite 3.x database, user version 1, last written using SQLite version 3008006

生意気にsqlite3ですって。

debian:databases$ sqlite3 datafolder.db
sqlite> .schema
CREATE TABLE android_metadata (locale TEXT);
CREATE TABLE FAVORITE_TABLE ( _id INTEGER PRIMARY KEY,file_path TEXT NOT NULL);

詳しい事は、 SQLite3を用いたSQL入門 あたりを見ればいいのかな。アンドロイド製のブラウザーなんて、使っていないので、多分データは空だろうけど。

V

rustならきっとGUIがお手軽に出来ると思ったんだ。んでもってggしてたら面白いものを見つけた。

V言語: Goのようにシンプルで、Rustのように小さいバイナリ

V プログラミング言語 (マニュアルの和訳)

The V Programming Language (本家)

これはもう試してみる鹿。和訳が出ているって事は、流行季に入っているんだな。

install v on debian(32Bit)

マニュアルに倣ってgitから取り寄せ。後はmakeするだけ。

debian:src$ git clone https://github.com/vlang/v
debian:src$ cd v
debian:v$ make
make fresh_vc
make[1]: Entering directory '/home/sakae/src/v'
rm -rf ./vc
git clone --depth 1 --quiet --single-branch https://github.com/vlang/vc ./vc
make[1]: Leaving directory '/home/sakae/src/v'
cd ./vc && git clean -xf && git pull --quiet
make fresh_tcc
make[1]: Entering directory '/home/sakae/src/v'
rm -rf ./thirdparty/tcc
Pre-built TCC not available for thirdparty-linux-i686 at https://github.com/vlang/tccbin, will use the system compiler: cc
git clone --depth 1 --quiet --single-branch --branch thirdparty-unknown-unknown https://github.com/vlang/tccbin ./thirdparty/tcc
make[1]: Leaving directory '/home/sakae/src/v'
cd ./thirdparty/tcc && git clean -xf && git pull --quiet
cc  -g -std=gnu99 -w -o ./v ./vc/v.c -lm -lpthread
./v -o v2.exe cmd/v
mv -f v2.exe v
V has been successfully built
V 0.2.2 76dc4cfy

tccが使えればそれを利用するけど、無ければgccで我慢するよって態度。鈍重なgccは嫌いみたいだ。

次はインストールだな。って、srcは後でupdateの時に必要になるんで残しておき、リンクを貼るだけだ。その為だけに専用のコマンドが用意されてる。

debian:v$ sudo ./v symlink
Symlink "/usr/local/bin/v" has been created

install v on FreeBSD

Makefileを見ていたら、何やらFreeBSDでもって記述が有った。それにsrc一式の中にBSDMakefileなんてのも有るし。。。

これはもう、FreeBSDでも楽しめと言ってるようなもの。一応確認の為ports/langの下を見たらvのportsが有った。Makefileを見ると、0.1.29版を去年の夏にリリースしてた。作るにはc11とgmakeが必要ってなってた。

自己責任でやってみる。

[sakae@fb ~/src/v]$ cat BSDmakefile
CC ?= cc

all:
        rm -rf vc/
        git clone --depth 1 --quiet https://github.com/vlang/vc
        $(CC) -std=gnu11 -w -o v vc/v.c -lm -lexecinfo
        rm -rf vc/
        @echo "V has been successfully built"

ソースは一本だけなのね。そんな簡単なの? 走らせてみる。

[sakae@fb ~/src/v]$ make -f BSDmakefile
rm -rf vc/
git clone --depth 1 --quiet https://github.com/vlang/vc
cc -std=gnu11 -w -o v vc/v.c -lm -lexecinfo
rm -rf vc/
V has been successfully built

面白いsubcommandが有ったので、試してみた。これBUGを発見した時、医者に見せる為の、環境調査表だな。

[sakae@fb /tmp]$ v doctor
OS: freebsd, 12.2-RELEASE-p4, FreeBSD 12.2-RELEASE-p4 GENERIC
Processor: 1 cpus, 64bit, little endian
CC version: FreeBSD clang version 10.0.1 (git@github.com:llvm/llvm-project.git llvmorg-10.0.1-0-gef32c611aa2)

getwd: /tmp
vmodules: /home/sakae/.vmodules
vroot: /usr/home/sakae/src/v
vexe: /usr/home/sakae/src/v/v
vexe mtime: 2021-03-29 03:57:42
is vroot writable: true
is vmodules writable: true
V full version: V 0.2.2 92f19f5

Git version: git version 2.30.1
Git vroot status: weekly.2021.12.2-32-g76dc4cf1 (1 commit(s) behind V master)
.git/config present: true
thirdparty/tcc status: thirdparty-unknown-unknown de82a130

install v on OpenBSD

気を良くしたオイラーはOpenBSDでも挑戦。ダメ元ですから。

vbox$ make -f BSDmakefile
rm -rf vc/
git clone --depth 1 --quiet https://github.com/vlang/vc
cc -std=gnu11 -w -o v vc/v.c -lm -lexecinfo
ld: error: unable to find library -lexecinfo
cc: error: linker command failed with exit code 1 (use -v to see invocation)
 *** Error 1 in /tmp/v (BSDmakefile:6 'all')
vbox$ cc -std=gnu11 -w -o v vc/v.c -L/usr/local/lib -lm -lexecinfo
vbox$ ./v doctor
OS: openbsd, 6.8, GENERIC#5
Processor: 1 cpus, 32bit, little endian
CC version: OpenBSD clang version 10.0.1

getwd: /tmp/v
vmodules: /home/sakae/.vmodules
vroot: /tmp/v
vexe: /tmp/v/v
vexe mtime: 2021-03-30 05:42:22
is vroot writable: true
is vmodules writable: true
V full version: V 0.2.2 c1d4074
 :

何とか動いている模様。

gc

gcと言っても、みんなが想像するような話では無い。ゴミ箱漁りさ。何気に/tmpの下を見たらvなんてdirが出来ていた。して、その中身は?

[sakae@fb /tmp]$ ls -l v
total 1248
-rw-r--r--  1 sakae  wheel  1272491 Mar 29 13:11 vdoctor.11874509941111691879.tmp.c
-rw-r--r--  1 sakae  wheel      140 Mar 29 13:11 vdoctor.11874509941111691879.tmp.c.rsp

先程 v doctor したけど、その残骸なんだな。やけに長ったらしいCのソースと、もう一つは何だ? 漁ってみる。

[sakae@fb /tmp]$ cat v/vdoctor.11874509941111691879.tmp.c.rsp
  -std=gnu99 -g -o "/usr/home/sakae/src/v/cmd/tools/vdoctor" 
    "/tmp/v/vdoctor.11874509941111691879.tmp.c" 
    -rdynamic -lm -lpthread -lexecinfo

一行になってたけど、見易いように改行をいれてみた。頭にgccとかccとかを付ければ、立派なコンパイル用のコマンドじゃないですか。

更に想像すれば、v語のソースをvを使ってC語に変換してから、コンパイルしてるんだな。

宝の山

どうやら宝の山は、/home/sakae/src/v/cmd/tools に有りそうだ。 vのsubcommandのソースがわんさかと置いてあった。一度実行したものは、そのバイナリーも置いてある。そういう仕組みになってたのね。

実は、debianでリンクした時、/usr/local/bin/vに張られた。これ変更したい場合どうするの?ってんで、v.cやらMakefileやらを一生懸命に家探ししてたんだ。

勝利の印に、vsymlink.vの該当部分をあげておく。

fn setup_symlink_unix(vexe string) {
        mut link_path := '/data/data/com.termux/files/usr/bin/v'
        if os.system("uname -o | grep -q '[A/a]ndroid'") == 1 {
                link_dir := '/usr/local/bin'
                if !os.exists(link_dir) {
                        os.mkdir_all(link_dir) or { panic(err) }
                }
                link_path = link_dir + '/v'
        }
        ret := os.execute_or_panic('ln -sf $vexe $link_path')
        if ret.exit_code == 0 {
                println('Symlink "$link_path" has been created')
        } else {
                eprintln('Failed to create symlink "$link_path". Try again with  sudo.')
        }
}

どうでもいいけど、v語のソースをemacsで開くとverilogモードに成るなあ。go-modeで代用すればいいかな。

v -> c

v語からC語への変換は簡単だわさ。

sakae@fb /tmp/hoge]$ v -o xx.c hello.v
[sakae@fb /tmp/hoge]$ wc *
       4       8      51 hello.v
    9288   39038  345603 xx.c

もの凄く太った。これには訳が有り。例えばOpenBSDとかでコンパイル出来るとな。

[sakae@fb /tmp/hoge]$ cc xx.c  -rdynamic -lm -lpthread -lexecinfo
[sakae@fb /tmp/hoge]$ ./a.out
Hello World!

普通に実行でけた。

c -> v

直交性を満たす為には、C語をv語に変換出来なければならない。それで何が嬉しいかボンクラーズ頭のオイラーには、想像が付かないけどね。

sakae@pen:/tmp/hoge$ v translate test.c
Translating C to V will be available in V 0.3

お預けを喰らってしまった。実現されるまでに、アイデアを考えておけ。一つ思い付く事は、ラウンドトリップだね。

C語をv語に変換して、それをコンパイル。往復してくるわけだな。で、結果が同じになるか? 英語を日本語に翻訳。その日本語を英語に翻訳。結果が同じか? AIのテスト手法の一つだ。 これとて、何が嬉しいかは疑問であります。

GUIは鬼門?

https://github.com/vlang/v

をみてたんだ。そしたら面白い広告が出てた。簡単にGUI出来るよと。

テトリス

その代表が、みんなが知ってるテトリス。スマホが無くても、きっと楽しめるだろう。

sakae@pen:/tmp/examples/tetris$ v tetris.v
/home/sakae/src/v/thirdparty/stb_image/stbi.o not found, building it in /home/sa
kae/.vmodules/cache/a5/a5639b783be9fcb26fa74e27cfa3a88a.o ...

builder error: 'X11/extensions/XInput2.h' not found
sakae@pen:/tmp/examples/tetris$ apt-file search XInput2.h
libxi-dev: /usr/include/X11/extensions/XInput2.h
sakae@pen:/tmp/examples/tetris$ sudo apt install libxi-dev
sakae@pen:/tmp/examples/tetris$ v tetris.v
builder error: 'X11/Xcursor/Xcursor.h' not found
sakae@pen:/tmp/examples/tetris$ sudo apt install libxcursor-dev
sakae@pen:/tmp/examples/tetris$ v tetris.v
sakae@pen:/tmp/examples/tetris$ ./tetris
gg error: GLX: failed to create GL context
7fb6c8ceb7bb : at ???: RUNTIME ERROR: abort() called
/home/sakae/src/v/thirdparty/sokol/sokol_app.h:8642: by _sapp_glx_create_context
/home/sakae/src/v/thirdparty/sokol/sokol_app.h:9357: by _sapp_linux_run
/home/sakae/src/v/thirdparty/sokol/sokol_app.h:9418: by sapp_run
/tmp/v/tetris.16026074825815320953.tmp.c:18076: by sokol__sapp__run
/tmp/v/tetris.16026074825815320953.tmp.c:19185: by gg__Context_run
/tmp/v/tetris.16026074825815320953.tmp.c:20252: by main__main
/tmp/v/tetris.16026074825815320953.tmp.c:20830: by main

何が悪いんでしょ? こうなったら手の施しようがありません。

ui

もう一つ紹介されてた。由緒正しい、サンプルGUIっぽい。試してみる鹿。

sakae@pen:~/src/v$ v up
Updating V...
Current V version:
V 0.2.2 c1d4074, timestamp: 2021-03-29 11:27:34 +0200
sakae@pen:~/src/v$ v install ui
Installing module "ui" from https://github.com/vlang/ui to /home/sakae/.vmodules/ui ...

パッケージシステムを入れるんだな。

sakae@pen:~$ cd .vmodules/ui/examples/
sakae@pen:~/.vmodules/ui/examples$ v run users.v
Using font /usr/share/fonts/truetype/freefont/FreeSans.ttf
libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
gg error: GLX: failed to create GL context
7f1ec0e797bb : at ???: RUNTIME ERROR: abort() called
/home/sakae/src/v/thirdparty/sokol/sokol_app.h:8642: by _sapp_glx_create_context
/home/sakae/src/v/thirdparty/sokol/sokol_app.h:9357: by _sapp_linux_run
/home/sakae/src/v/thirdparty/sokol/sokol_app.h:9418: by sapp_run
/tmp/v/users.2203378481056197343.tmp.c:20600: by sokol__sapp__run
/tmp/v/users.2203378481056197343.tmp.c:21718: by gg__Context_run
/tmp/v/users.2203378481056197343.tmp.c:29560: by ui__run
/tmp/v/users.2203378481056197343.tmp.c:31120: by main__main
/tmp/v/users.2203378481056197343.tmp.c:31381: by main

で、そこの例を実行すると、やはりエラーだわさ。根本が腐っているのかな。ええ、XはWindows側に任せているって負い目が有りますから。

libGLでエラーが出てたって普通にfirefoxとかのGUI系は動いているしねぇ。

無罪確定

ってんで、ちゃんとしたGUIが動いてるDesktopでやってみる。そう、VMWarePlayerのGUIです(普段は、PuTTYからsshしてて、XはWindows10に入れたVcXsrvに任せてる)。

これで、ちゃんとテトリスとかuiのサンプルが動いた。 LinuxのGUIとしては、これで無罪が確定した。

uiで提供されてる例で、一番行数の少ないやつは、counter.vだった。たったの47行。これだけで、ボタンとカウンター値を表示するGUIのアプリになってる。

作りも今風である。そもそもこのv語を知ったのは、rustにtcl/tkのバインディングが有るかggしてたんだ。そしたら、今更tcl/tkってそりゃあんた20年遅れてるよと馬鹿にされたんだ。

それでGUIをサクッと作れる事を目標にした、v語を知った次第。

参考までに、テトリスの成分表を載せておく。

sakae@pen:/tmp/hoge$ ldd ./tetris
        linux-vdso.so.1 (0x00007fffad3ea000)
        libX11.so.6 => /lib/x86_64-linux-gnu/libX11.so.6 (0x00007f2759ce9000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2759b28000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f2759b07000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f2759b02000)
        libGL.so.1 => /lib/x86_64-linux-gnu/libGL.so.1 (0x00007f2759a6e000)
        libXcursor.so.1 => /lib/x86_64-linux-gnu/libXcursor.so.1 (0x00007f2759a61000)
        libXi.so.6 => /lib/x86_64-linux-gnu/libXi.so.6 (0x00007f275984f000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f27596cc000)
        libxcb.so.1 => /lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f27596a2000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f2759e46000)
        libGLX.so.0 => /lib/x86_64-linux-gnu/libGLX.so.0 (0x00007f275966e000)
        libGLdispatch.so.0 => /lib/x86_64-linux-gnu/libGLdispatch.so.0 (0x00007f27595b1000)
        libXrender.so.1 => /lib/x86_64-linux-gnu/libXrender.so.1 (0x00007f27593a7000)
        libXfixes.so.3 => /lib/x86_64-linux-gnu/libXfixes.so.3 (0x00007f275919f000)
        libXext.so.6 => /lib/x86_64-linux-gnu/libXext.so.6 (0x00007f2758f8d000)
        libXau.so.6 => /lib/x86_64-linux-gnu/libXau.so.6 (0x00007f2758d89000)
        libXdmcp.so.6 => /lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f2758b83000)
        libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007f2758b69000)
        librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f2758b5d000)

これが今風なんですかねぇ。Windows10にWSL,WSL2あたりを入れて、GUIしましょってのを良く見る。VcXsrvでは、これに(多分)対処出来ないでしょう。誰か、解決策をご存知なら、是非教えてください。

debian(32bit)機は、純粋なDeskTop環境なんだけど、エラーでテトリスはおろかuiサンプルが動かず。そんなおんぼろはリナ業界では、爪弾きなんだな。

vertualboxに入れたFreeBSDでは、Desktop環境(但しtwmと言う元祖のウィンドウ・マネージャー)で、テトリス動いた。GUIは、これぐらいにしとく。

コンパイルスピード

Is V still fast? なんてのが本家のページの目立つ所にリンクされてる。コミットの度に、コンパイルスピードが計測されてる。普通、コンパイルがパスしたかどうかぐらいの表示だと思うんだけど、あえて、自分自身をコンパイルして、その時間を公表。並々ならぬ自信の表われだ(と思う)。

オイラーもスピード比べ。まずは、テトリスのソースをコンパイルしてバイナリーを作るに要した時間。

sakae@pen:/tmp/hoge$ time v tetris.v

real    0m0.412s
user    0m0.340s
sys     0m0.072s

下記はv語をC語に変換するのに要した時間。これが本来のv語のスピードになる。残りの時間は、C語のソースをコンパイルする時間になるはず。

sakae@pen:/tmp/hoge$ time v -o x.c tetris.v

real    0m0.281s
user    0m0.256s
sys     0m0.025s
sakae@pen:/tmp/hoge$ wc tetris.v x.c
   518   1908  11863 tetris.v
 20836  81361 728342 x.c

ほう、518行が2000行超えに膨らむのか。

C語のコンパイル時間が、light-speed-C 並みに速いな。ここで言ってるlight-speed-Cってのは、超昔にMacでごにょごにょやってた時の記憶だ。あと、Turbo-Pascalなんてのも有ったな。 下記は、~/.vmodules/cache/の下にあった記録。

sakae@pen:~/.vmodules/cache$ cat a5/a5....a88a.description.txt
/home/sakae/src/v/thirdparty/stb_image/stbi.o @ 
/home/sakae/src/v/thirdparty/tcc/tcc.exe   -std=gnu99  -fPIC 
  -I "/home/sakae/src/v/thirdparty/stb_image" 
  -o "/home/sakae/.vmodules/cache/a5/a5.....a88a.o" 
  -c "/home/sakae/src/v/thirdparty/stb_image/stbi.c"

爆速コンパイルは、tccのおかげです。

cross compile for Windows 10

GUIの本場 Windows10で、テトリスしてみる。下記はその試行錯誤。

sakae@pen:/tmp$ v new towin
Input your project description: towin
Input your project version: (0.0.0) 0.1.0
Input your project license: (MIT)
Initialising ...
Complete!
sakae@pen:/tmp$ cd towin/
sakae@pen:/tmp/towin$ v .
sakae@pen:/tmp/towin$ ls
towin  towin.v  v.mod
sakae@pen:/tmp/towin$ ./towin
Hello World!

sakae@pen:/tmp/towin$ v -os windows .
Cross compiling for Windows...
sh: 1: x86_64-w64-mingw32-gcc: not found
Cross compilation for Windows failed. Make sure you have mingw-w64 installed.
Try `sudo apt install -y mingw-w64` on Debian based distros, or `sudo pacman -S
mingw-w64-gcc` on Arch, etc...

sakae@pen:/tmp/towin$ sudo apt install -y mingw-w64
sakae@pen:/tmp/towin$ cp ../tetris.v towin.v
sakae@pen:/tmp/towin$ v -os windows .
Cross compiling for Windows...
/tmp/towin/towin.exe has been successfully compiled
sakae@pen:/tmp/towin$ file towin.exe
towin.exe: PE32+ executable (console) x86-64, for MS 

プロジェクトを作ると、プロジェクト名.v って言うハロワが出来る。後は指示に従って、mingw-w64を入れる(137Mのサイズですって)。

それから、tetris.v で、towin.vを上書き。そしてコンパイル。コンソールアプリになるんだけど、Windowsへ持って行って、ファイルをダブルクリックして起動。

黒い窓が出て、それと同時にテトリス窓が出現、オイラーは運動音痴って事が証明されてしまったわい。

font file "C:\Users\sakae\assets\fonts\RobotoMono-Regular.ttf" 
does not exist, the system font was used instead.

黒い窓に、こんなメッセージが出てくるのは、おまけなんだな。

etc