记一次失败的折腾。
起因,Windows下Racket的命令行编辑不好用,因为不能使用libedit。查看了以下racket的readline的源码,发现 (ffi-lib "libedit" '("3" "2" "0.0.43" "0.0.53" "0" ""))))
,这些数字大概意味着所支持的libedit的版本。于是乎下载了WinEditline,把其中的edit.dll改名成libedit-2.dll,然后放到racket的lib文件及。在racket中执行(require readline)
倒是能够识别这个dll,但是由于WinEditline支持的特性有限,比如不支持history_base,所以无法使用。
WinEditline在MinGW环境中有相应的安装包。Windows下git发行版是MinGW编译的,所以git目录里面也能找到edit.dll。
editline
既然WinEditline不行,那就尝试下较新的editline吧。
先是打算在Ubuntu WSL上交叉编译。在Ubuntu上安装sudo apt install mingw-w64
。
由于editline依赖于ncurses,于是尝试在Ubuntu上编译ncurses。
参考How do I invoke the MinGW cross-compiler on Linux?,使用下面的命令进行编译:
./configure --host=x86_64-w64-mingw32 --without-zlib
结果出现错误:
/bin/sh -e ./tinfo/MKcaptab.sh mawk 1 ./tinfo/MKcaptab.awk ../include/Caps ../include/Caps-ncurses > comp_captab.c
./tinfo/MKcaptab.sh: 74: ./make_hash: not found
make[1]: *** [Makefile:264: comp_captab.c] Error 127
换用:
./configure CC=x86_64-w64-mingw32-gcc
错误依旧。
换用MSYS2
既然不能在Ubuntu WSL下交叉编译,那就试试MSYS2吧。
简单介绍以下MSYS2。MSYS2从Cygwin分支出来的,支持三种模式:msys2,mingw64, mingw32。msys2模式有点像Cygwin,posix兼容性好,但编出来的dll无法直接在win32下使用。mingw64和ming32对应的就是64位和32位的mingw环境。
使用scoop install msys2
安装msys2,安装完以后使用msys2 -mingw
进入mingw模式(64位系统下默认进入mingw64模式)。通过pacman把相关工具都装上。
pacman -S <pkg>
安装<pkg>
,对于mingw64,<pkg>
都是mingw64-
开头的。pacman -Ss <keyword>
按照<keyword>
查找相应的软件包。
在msys-mingw64下
出现以下错误:
../ncurses/./tinfo/lib_setup.c: In function '_nc_get_screensize':
../ncurses/./tinfo/lib_setup.c:337:6: error: unknown type name 'STRUCT_WINSIZE'
337 | STRUCT_WINSIZE size;
| ^~~~~~~~~~~~~~
../ncurses/./tinfo/lib_setup.c:341:7: warning: implicit declaration of function 'ioctl'; did you mean 'isoctal'? [-Wimplicit-function-declaration]
341 | if (ioctl(cur_term->Filedes, IOCTL_WINSIZE, &size) >= 0) {
| ^~~~~
| isoctal
../ncurses/./tinfo/lib_setup.c:341:32: error: 'IOCTL_WINSIZE' undeclared (first use in this function)
341 | if (ioctl(cur_term->Filedes, IOCTL_WINSIZE, &size) >= 0) {
| ^~~~~~~~~~~~~
../ncurses/./tinfo/lib_setup.c:341:32: note: each undeclared identifier is reported only once for each function it appears in
../ncurses/./tinfo/lib_setup.c:344:12: warning: implicit declaration of function 'WINSIZE_ROWS' [-Wimplicit-function-declaration]
344 | : WINSIZE_ROWS(size));
| ^~~~~~~~~~~~
../ncurses/./tinfo/lib_setup.c:345:15: warning: implicit declaration of function 'WINSIZE_COLS' [-Wimplicit-function-declaration]
345 | *colp = WINSIZE_COLS(size);
| ^~~~~~~~~~~~
采用Undefined reference building ncurses on cygwin提示的configure --enable-term-driver --enable-sp-funcs
也没有解决问题。
换用MSYS2自带的ncurses
好吧,不编ncurses了行不行,采用msys-mingw64自带的mingw-w64-x86_64-ncurses
直接编译editline呢?
试了以下,发现mingw没有termios.h这个头文件,从https://github.com/chjchoi/kai/tree/master/project/linux-cortexm-1.9.0/A2F/gdb-2011.03/cs-cygwin-wrapper
抄了termios.h|c的源代码,继续编译,竟然出现下面的错误:
In file included from el.h:50,
from chared.c:51:
chartype.h:46:3:In file included from el.h:50error: ,
from #error wchar_t must store ISO 10646 characters
46 | #common.c:50error wchar_t must store ISO 10646 characters
| :
^~~~~chartype.h:46:3:
error: #error wchar_t must store ISO 10646 characters
46 | #error wchar_t must store ISO 10646 characters
| ^~~~~
In file included from el.h:96,
from common.c:50:
tty.h:475:5: error: unknown type name 'speed_t'
475 | speed_t t_speed;
| ^~~~~~~
In file included from el.h:102,
from common.c:50:
算了放弃editline了。
其实ncurses自带有MinGW Port,不过所提供的版本是支持宽字符的版本,没有试出如何在editline中使用。
转向gnu的readline
readline-gpl可以使用gnu的readline替换editline。
下了readline 5.2的代码,在msys-mingw64上编译失败。
下了readline 6.2的代码,在msys-mingw64上依然编译失败。
clink使用的也是readline 6.2。尝试了以下clink中的readline,其默认是把readline当作静态库编译的。但是如果把readline当作动态库编译,依然会编译不过。
小结
本次折腾完全失败。看来cmd.exe还是半残的。要么在wsl中使用racket,要么在drracket中使用repl,要么在emacs中使用racket。
不过也不是完全没有收获,emacs的Geiser看似挺好用的,而且可以与Evil模式结合使用。
其他emacs相关的可以参考24.2 Emacs。
其他
- linenoise,A minimal, zero-config, BSD licensed, readline replacement used in Redis, MongoDB, and Android。
(本篇完)