说明一下,示例中使用的是 zsh 语法。bash 用户的话——先在电脑上用上 zsh 再考虑给手机装吧 ^_^
在网上能够找到 zshaolin 这么个包含 zsh 的 Android 包,但是它是收费的。于是,在成功编译了不少 Android 的东东后, 我决定自己编译个 zsh。
首先,把 Android NDK 放到 $PATH 里来:
path+=/opt/android-ndk/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86/bin
其次是./configure
命令。其中那个LDFLAGS
的路径里有我之前编译的 ncurses。注意这里必须指定使用 ncurses 库,否则会莫名其妙地失败。使用 Android 自己的 Bionic 这个 C 库的话,就只好禁用多字节字符的支持了。
另外,ncurses 编译的时候记得禁用 C++ 支持。
LDFLAGS=-L/ldata/media/temp/android/installed_binaries/lib \ CC='arm-linux-androideabi-gcc --sysroot=/opt/android-ndk/platforms/android-14/arch-arm' \ ./configure --host=arm-linux-gnu --prefix=/system --with-term-lib=ncurses \ --disable-multibyte --bindir=/system/xbin
然后做点小修改,将Src/init.c
中TIOCSETD
相关的两处代码注释掉,不然程序会卡在这个ioctl
调用上。还要把所有_mktemp
函数调用换掉。在config.h
中注释掉HAVE__MKTEMP
宏的定义即可。
接下来是编译。完成之后修改最后一行链接代码,将 ncurses 静态链接进去:
arm-linux-androideabi-gcc --sysroot=/opt/android-ndk/platforms/android-14/arch-arm \ -L/ldata/media/temp/android/installed_binaries/lib -rdynamic \ -o zsh main.o `cat stamp-modobjs` -ldl -lm -lc /ldata/media/temp/android/installed_binaries/lib/libncurses.a
然后make install
安装,把生成的zsh
可执行文件弄到手机上任何你喜欢放可执行文件的地方,share
目录弄到配置的目录里去(我这里是/system
)。或者我猜设置fpath
变量也行?
我第一次编译成功的 zsh 没有去掉TIOCSETD
的ioctl
调用,于是启动时卡在那里一动也不动了。要调试这种情况当然是 strace 了。但很不幸的是,strace 用到了太多 Bionic 不支持的宏定义、结构体成员等。后来我换了 zshaolin 使用的这个工具链静态链接了个 strace,终于可以用了。
最后,我编译好的二进制文件下载链接。要注意的是,此 zsh 并不支持多字节字符(如中文)(但是人家 Kindle 上的就支持呢)。
2014年3月8日更新:如果遇到任务控制(job control)时无法将后台任务切换到前台,打印出「unknown signal」的问题,可将Src/signal.c:435
处的WCONTINUED
改成WSTOPPED
(注意不是WIFSTOPPED
),即:
--- Src/signal.c +++ Src/signal.c @@ -432,7 +432,7 @@ */ #if defined(HAVE_WAIT3) || defined(HAVE_WAITPID) # ifdef WCONTINUED -# define WAITFLAGS (WNOHANG|WUNTRACED|WCONTINUED) +# define WAITFLAGS (WNOHANG|WUNTRACED|WSTOPPED) # else # define WAITFLAGS (WNOHANG|WUNTRACED) # endif
这个方案是我通过 strace 手机上的 busybox 的 sh 学来的 =w= 新编译的 zsh 5.0.5 可以由此下载。