MSYS2 (2)

Table of Contents

記念植樹で ruby

MSYS2を入れたので、記念植樹の第2段としてrubyを入れてみる。何、自分でコ ンパイルしてもいいんだけど、バグをトラックするのが面倒なので楽をするの さ。どんなのが有るか、とりあえず調べてみる。

$ pacman -Fy
:: Synchronizing package databases...
 mingw64                 5.4 MiB  1233 KiB/s 00:04 [#####################] 100%
 msys                 1202.1 KiB   587 KiB/s 00:02 [#####################] 100%

$ pacman -Fx bin/irb
mingw64/bin/irb is owned by mingw64/mingw-w64-x86_64-ruby 3.1.3-2
mingw64/bin/irb.bat is owned by mingw64/mingw-w64-x86_64-ruby 3.1.3-2
usr/bin/irb is owned by msys/ruby 3.1.3-2

aptで言うapt-file search相当。インデックスを更新してから検索。msys版 とmingw64版が出てきたけど、選ぶならスピードが速いmingw64の方ね。

pythonも植樹

rubyが入ったなら、対抗上入れざるをえない。直接入れるのじゃなくて、gdb 経由ね。いわゆるお邪魔虫ね。gdbも入れるのは、mingw64版の方。

$ python
Python 3.10.9 (main, Jan 14 2023, 21:23:14)  [GCC 12.2.0 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> quit()

perlはデフォで入いっているから、これで揃いぶみだな。昔はよく頑張って入 れたものだ。

gdb

gdbも試運転しとく。ハロワの奴ね。

$ gdb -q a.exe
Reading symbols from a.exe...
(gdb) b main
Breakpoint 1 at 0x1400014b1: file test.c, line 4.
(gdb) r
Starting program: C:\msys64\home\sakae\a.exe
[New Thread 1180.0x21bc]

Thread 1 hit Breakpoint 1, main () at test.c:4
4               printf("Hello MSYS2\n");
(gdb) disassemble
Dump of assembler code for function main:
   0x00007ff685ab14a4 <+0>:     push   %rbp
   0x00007ff685ab14a5 <+1>:     mov    %rsp,%rbp
   0x00007ff685ab14a8 <+4>:     sub    $0x20,%rsp
   0x00007ff685ab14ac <+8>:     call   0x7ff685ab1580 <__main>
=> 0x00007ff685ab14b1 <+13>:    lea    0x7b48(%rip),%rax        # 0x7ff685ab9000
   0x00007ff685ab14b8 <+20>:    mov    %rax,%rcx
   0x00007ff685ab14bb <+23>:    call   0x7ff685ab1450 <printf>
   0x00007ff685ab14c0 <+28>:    mov    $0x0,%eax
   0x00007ff685ab14c5 <+33>:    add    $0x20,%rsp
   0x00007ff685ab14c9 <+37>:    pop    %rbp
   0x00007ff685ab14ca <+38>:    ret
End of assembler dump.

こうやって、MSYS2が肥大してく。今やWSLで入れてたDebianは使う事はないな。 削除もとえ、卒業させよう。

wsl --unregister Debian

蛍の光ーーー。また会う日まで。。。 こうして、MSとの距離を保つのさ。

gdbついでに前回やった一番簡単なGUI版をやってみる。一応コードを再掲。

$ cat hello.c
#include <windows.h>

int WINAPI WinMain(HINSTANCE ins,
                   HINSTANCE previns,
                   LPSTR cmdline,
                   int cmd) {
    MessageBox(NULL, "Hello world.", "MBOX---------MBOX", MB_OK);
    return 0;
}
$ gdb -q a.exe
Reading symbols from a.exe...
(gdb) b MessageBox
Function "MessageBox" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (MessageBox) pending.
(gdb) r
Starting program: C:\msys64\tmp\a.exe
[New Thread 12392.0xc34]
[New Thread 12392.0x2084]
[New Thread 12392.0x1cac]
[New Thread 12392.0x2794]
[New Thread 12392.0x870]
[Thread 12392.0x870 exited with code 0]
[Thread 12392.0x2794 exited with code 0]
[Thread 12392.0x1cac exited with code 0]
[Thread 12392.0x2084 exited with code 0]
[Thread 12392.0xc34 exited with code 0]
[Inferior 1 (process 12392) exited normally]

MessageBoxにBPを設定できずに素通りしてしまった。これってひょっとしてマ クロかな? さあ、どうするって3秒考えて、

gcc -E hello.c >exp.c
$ tail -20 exp.c
int __attribute__((__stdcall__)) WinMain(HINSTANCE ins,
                   HINSTANCE previns,
                   LPSTR cmdline,
                   int cmd) {

# 7 "hello.c" 3
   MessageBoxA
# 7 "hello.c"
             (
# 7 "hello.c" 3 4
              ((void *)0)
# 7 "hello.c"
                  , "Hello world.", "MBOX---------MBOX",
# 7 "hello.c" 3
                                                         0x00000000l
# 7 "hello.c"
                                                              );

ここまで判れば、後はヤルダケーーーって、いっこさん風。

$ gdb -q a.exe
Reading symbols from a.exe...
(gdb) b MessageBoxA
Breakpoint 1 at 0x1400026c0
(gdb) r
Starting program: C:\msys64\tmp\a.exe
[New Thread 9996.0x1a70]
[New Thread 9996.0x1cb4]

Thread 1 hit Breakpoint 1, 0x00007ff81f29c2f4 in USER32!MessageBoxA () from C:\W
INDOWS\System32\user32.dll
(gdb) bt
#0  0x00007ff81f29c2f4 in USER32!MessageBoxA ()
   from C:\WINDOWS\System32\user32.dll
#1  0x00007ff7e1d2148d in WinMain (ins=0x7ff7e1d20000, previns=0x0,
    cmdline=0x25cc6d34746 "", cmd=10) at hello.c:7
#2  0x00007ff7e1d22791 in main (argc=<optimized out>, argv=<optimized out>,
    envp=<optimized out>)
    at C:/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexewin.c:70
#3  0x00007ff7e1d212ee in __tmainCRTStartup ()
    at C:/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:272
#4  0x00007ff7e1d21406 in mainCRTStartup ()
    at C:/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:193

後は醜いアヒルの子じゃなくて、糞石のそれをみておく。SKKの辞書に糞石っ て単語がなかったので即登録したよ。これからもよく使うだろうから。

(gdb) disassemble
Dump of assembler code for function USER32!MessageBoxA:
   0x00007ff81f29c2f0 <+0>:     sub    $0x38,%rsp
=> 0x00007ff81f29c2f4 <+4>:     xor    %r11d,%r11d
   0x00007ff81f29c2f7 <+7>:     cmp    %r11d,0x37ff2(%rip)        # 0x7ff81f2d42f0
   0x00007ff81f29c2fe <+14>:    je     0x7ff81f29c32e <USER32!MessageBoxA+62>
   0x00007ff81f29c300 <+16>:    mov    %gs:0x30,%rax
   0x00007ff81f29c309 <+25>:    mov    0x48(%rax),%r10
   0x00007ff81f29c30d <+29>:    xor    %eax,%eax
   0x00007ff81f29c30f <+31>:    lock cmpxchg %r10,0x38bb8(%rip)        # 0x7ff81f2d4ed0
   0x00007ff81f29c318 <+40>:    mov    0x38bb9(%rip),%r10        # 0x7ff81f2d4ed8
   0x00007ff81f29c31f <+47>:    lea    0x1(%r11),%eax
   0x00007ff81f29c323 <+51>:    cmove  %rax,%r10
   0x00007ff81f29c327 <+55>:    mov    %r10,0x38baa(%rip)        # 0x7ff81f2d4ed8
   0x00007ff81f29c32e <+62>:    orl    $0xffffffff,0x28(%rsp)
   0x00007ff81f29c333 <+67>:    mov    %r11w,0x20(%rsp)
   0x00007ff81f29c339 <+73>:    call   0x7ff81f29c620 <USER32!MessageBoxTimeoutA>
   0x00007ff81f29c33e <+78>:    add    $0x38,%rsp
   0x00007ff81f29c342 <+82>:    ret

参考までに、展開されたexp.cは10万行近くあった。Windowsって、とんでもな い奴だな。本格的にやるなら、 MinGWでWindowsプログラミングを行う方法 とか、 MinGWでWindowsソフト開発(ウィンドウ編) こういうのを参考にすればいいんだな。

ruby ri

折角入れたのはいいんだけど、下記のようにriが知らんぷりだ。こんな現象は OpenBSDでも、経験してた。そう、ri用の原稿は別なパッケージになってたの だ。Rails屋さんとかには不要でしょうからね。

$ ri String
Nothing known about String

色々探してみたけど、それっぽいのは無かった。で、ArchLinuxの /usr/local/share/ri以下をごっそりと貰ってきた。そしたら、一応反応する ようになった。但しlessの機能は働かない。なんで?

こういう時は強引に、

$ strace -o LOG ri String
strace.exe: error creating process ri, (error 2)

手探り状態、もっと易しいので挙動確認。何せ相手はWindowsと陸続きの環境 ですから、どこに落とし穴が潜んでいるか、判ったものじゃない。

$ strace -o LOG ls
LOG  a.exe  hello.c  tmux-197609
$ less LOG
--- Process 11020 created
--- Process 11020 loaded C:\Windows\System32\ntdll.dll at 00007ff8209f0000
--- Process 11020 loaded C:\Windows\System32\kernel32.dll at 00007ff820210000
--- Process 11020 loaded C:\Windows\System32\KernelBase.dll at 00007ff81e720000
--- Process 11020 thread 6220 created
--- Process 11020 thread 6132 created
--- Process 11020 loaded C:\msys64\usr\bin\msys-intl-8.dll at 0000000430b30000
--- Process 11020 loaded C:\msys64\usr\bin\msys-2.0.dll at 0000000180040000
--- Process 11020 thread 3012 created
--- Process 11020 loaded C:\msys64\usr\bin\msys-iconv-2.dll at 00000005603f0000
    0       0 [main] ls (11020) **********************************************
  314     314 [main] ls (11020) Program name: C:\msys64\usr\bin\ls.exe (windows pid 11020)
  103     417 [main] ls (11020) OS version:   Windows NT-10.0
  180     597 [main] ls (11020) **********************************************
   :

いきなり団子じゃなくて、いきなりアプリだと問題ないのか。riってGem経由 で、色々やってるからなあ。それを追跡出来ないのか。

同じ事をArchLinuxでやって、途中で止めてみた。こういう方法でバックトレー スを取得できるのね。

:/usr/local/lib/ruby/3.1.0/rdoc/ri/driver.rb:1355:in `close': Interrupt
        from /usr/local/lib/ruby/3.1.0/rdoc/ri/driver.rb:1355:in `page'
        from /usr/local/lib/ruby/3.1.0/rdoc/ri/driver.rb:805:in `display'
        from /usr/local/lib/ruby/3.1.0/rdoc/ri/driver.rb:827:in `display_class'
        from /usr/local/lib/ruby/3.1.0/rdoc/ri/driver.rb:853:in `display_name'
        from /usr/local/lib/ruby/3.1.0/rdoc/ri/driver.rb:880:in `block in display_names'
        from /usr/local/lib/ruby/3.1.0/rdoc/ri/driver.rb:877:in `each'
        from /usr/local/lib/ruby/3.1.0/rdoc/ri/driver.rb:877:in `display_names'
        from /usr/local/lib/ruby/3.1.0/rdoc/ri/driver.rb:1511:in `run'
        from /usr/local/lib/ruby/3.1.0/rdoc/ri/driver.rb:397:in `run'
        from /usr/local/lib/ruby/gems/3.1.0/gems/rdoc-6.4.0/exe/ri:12:in `<top (required)>'
        from /usr/local/bin/ri:25:in `load'
        from /usr/local/bin/ri:25:in `<main>'

straceのログには膨大なgemの痕跡が残っていた。オイラーにとってはgem公害 だな。もっとクリーンなrubyが欲しい今日この頃。

そしてパッケージにruby-docsと言うのを見つけて入れてみたけど、有効にな らなかった。なんでだろう? 深く追求するのは、打ち切りしとく。

パッケージの探しかた

Repos から、好きな所を選んでいけばよい。

ocamlとかluaとか有るぞ。各種言語は、単独で提供されてるけど、それらを個 別にインストールすると取り回しが悪い。mingw64で集約してしまえば、管理 がラクチンでいいぞ。

perl,ruby,python,gaucheとかのREPLは、emacsから使うのが楽だ。 tmuxで複数のターミナルを動かしておく。端末を終了させる時に、 tmuxが動いているけど、いいかって聞かれる。いいよで応答。 後日、端末を開いて tmux a すれば、止めた所から続行できる。 生活の知恵だな。

知恵と言えば、上記のパッケージ一覧を見た時に、眩暈がするだろう。ブラウ ザーの検索機能を使って、絞り込むのが楽だ。目grepは禁止ね。目を労りましょ う。

pythonの使い所

こんな記事がでてた。 venvモジュールを使って仮想環境を構築するには モジュールが喧嘩するのを避ける方法なんだな。頭の切り替えが大変そう。 オイラーならOS提供ってかMSYS2/mingw64が供給してる奴だけを使うのが、賢 明だろう。沼には嵌りたくない。

上で紹介したパッケージのログをゆっくりと眺めたい。簡単なスクリプトを 作くった。そう、emacsでのスクリプト作成支援が使えるかの確認もこめて。 コードを書いて、C-c C-x のループ。段々とフィルターを増設する方式ね。

$ cat conv.sh
#! /bin/sh

#  curl -s https://repo.msys2.org/mingw/mingw64/ >GW64

cat GW64           |
grep 'zst<'        |
sed -e 's/<.*">//' |
sed -e 's!</a>!!'  |
sed -e 's/mingw-w64-x86_64-//'

curlで一気にパイプしてもいいんだけど、ネットに負担をかけないように、一 旦ログに落としてからやってる。URLの最後に / を忘れない事。

ネットに負担をかけない、なんてサラッと言てるけど、これって、犬HKのチコ 番組でCO2削減のため電球一個にしてますってのと同じ構図だな。まやかしだ。 本当に削減したいなら、再放送はやめて停波しろよ。そしたら大幅にCO2の削 減ができるぞ。オイラーなら、OSのアップデートを月に一度にするとか。。

$ ./conv.sh | grep python
    :
python-lzo-1.12-2-any.pkg.tar.zst 23-Oct-2020 08:10     27K
python-lzo-1.12-3-any.pkg.tar.zst 16-Jul-2021 17:24     26K
python-lzo-1.14-1-any.pkg.tar.zst 09-Feb-2022 08:57     26K
python-lzo-1.14-2-any.pkg.tar.zst 11-Jun-2022 14:45     26K
python-pip-21.3-1-any.pkg.tar.zst 24-Oct-2021 12:25      2M
python-pip-22.2-1-any.pkg.tar.zst 26-Jul-2022 17:27      2M
python-pip-22.3-1-any.pkg.tar.zst 20-Oct-2022 11:03      2M
python-pip-23.0-1-any.pkg.tar.zst 31-Jan-2023 16:27      2M

Webから見た時は、随分沢山のパッケージが提供されてるかと思ったら、過去 のもので、水増しされてるだけだった。

オイラーが嬉しいpythonの機能。

sakae@atom MINGW64 /usr/share/doc/cygwin-api
$ python3 -m http.server 80
Serving HTTP on :: port 80 (http://[::]:80/) ...
::ffff:127.0.0.1 - - [07/Feb/2023 05:45:13] "GET / HTTP/1.1" 200 -
::ffff:127.0.0.1 - - [07/Feb/2023 05:45:14] "GET /docbook.css HTTP/1.1" 200 -

怖い事に80番で起動できちゃう。そして、普通にIPv6が利用されてる。これっ て、Windowsならではなんですかねぇ。

Windows GUI

Win32API 入門

一週間で身につくWIN32プログラミングの基本

# for Windows GUI
SRC=window.c
RC=menu.rc

OBJS=$(SRC:.c=.o)
OBJS+=$(RC:.rc=.o)
PROG=a.exe
CC=gcc
MENU=windres
SED=sed 's/\\/\\\\/'
CFLAGS=-Wall -O3
LDFLAGS=-mwindows
RM=rm

%.o: %.c
        $(CC) $(CFLAGS) -o $@ -c $<

%.o: %.rc
        $(SED) $(RC) | $(MENU) -o $*.o

.PHONY : all
all: $(PROG)

$(PROG): $(OBJS)
        $(CC) $(OBJS) $(LDFLAGS) -o $@

.PHONY : clean
clean:
        $(RM) -f $(OBJS) $(PROG)

雛形のファイル。これが有ればスイスイだな。 コピペさせて貰ったんだけど、その途中で重大な事に気付いてしまった。ファ イル名は大文字も小文字も区別しないっていう仕様、しようも無い仕様だ。 DOS時代からです。DNAなんです。こればっかりは変更できません。


This year's Index

Home