RScheme 移植到ARM

最近花了点时间,把RScheme 移植到arm上了,现在可以跑在Android和Cubieboard 的Debian上。把移植过程记录一下。

1、由于没有arm版的配置,需要在configure.in里面新增host 为arm,红色部分新增,这样能识别arm设备了,如下:

case "${host}" in
  m68k-*-*)     ARCH=m68k ; AC_DEFINE(PLATFORM_ARCH_M68K,1) ;;
  powerpc-*-*)  ARCH=powerpc ; AC_DEFINE(PLATFORM_ARCH_PPC,1) ;;
  rs6000-*-*)   ARCH=powerpc ; AC_DEFINE(PLATFORM_ARCH_PPC,1) ;;
  i?86-*-*)     ARCH=i386 ; AC_DEFINE(PLATFORM_ARCH_I386,1) ;;
  x86_64-*-*)   ARCH=x86_64 ; AC_DEFINE(PLATFORM_ARCH_X86_64,1) ;;
  mips-*-*)     ARCH=mips ; AC_DEFINE(PLATFORM_ARCH_MIPS,1) ;;
  sparc-*-*)    ARCH=sparc ; AC_DEFINE(PLATFORM_ARCH_SPARC,1) ;;
  alpha*-*-*)   ARCH=alpha ; AC_DEFINE(PLATFORM_ARCH_ALPHA,1) ;;
  s390-*-*)     ARCH=s390 ; AC_DEFINE(PLATFORM_ARCH_S390,1) ;;
  armv*-*-*)   ARCH=arm ; AC_DEFINE(PLATFORM_ARCH_ARM,1) ;;
  *-*-*)        ARCH=unknown ; AC_DEFINE(PLATFORM_ARCH_UNKNOWN,1) ;;

然后重新生成配置文件autoconf命令。但是这样还不行,跨平台的文件需要新增加对应的实现,在packages/fasl/ldcode.c中新增代码:

#if PLATFORM_ARCH_ARM
void init_stub_procs( struct FASL_Header *hdr, jump_addr stub )
{
  static UINT_32 stub_ptr;
  UINT_8 *d = (UINT_8 *)hdr->stub_proc;
  UINT_32 addr;
  
  stub_ptr = (UINT_32)stub;
  addr = (UINT_32)stub_ptr;
  *d++ = 0x04;
  *d++ = 0xf0;
  *d++ = 0x1f;
  *d++ = 0xe5;
  *d++ = addr & 0xFF;
  *d++ = (addr >> 8) & 0xFF;
  *d++ = (addr >> 16) & 0xFF;
  *d++ = (addr >> 24) & 0xFF;
}

#endif /*ARM android */

这段代码为arm汇编c的写法,对应的汇编指令很简单,为

to:
 ldr pc,=to

反编译后代码如下:

00008074 <to>:
    8074:    e51ff004     ldr    pc, [pc, #-4]    ; 8078 <to+0x4>
    8078:    00008074     .word    0x00008074

可见,e51ff004 对应签名的 *d++ = 0x04; *d++ = 0xf0;*d++ = 0x1f;*d++ = 0xe5;,然后下面就是jmp跳转的地址,arm里面跳转可以直接把地址放到pc里面去,pc是R15寄存器,如果没记错的话。这样好了,平台相关代码和配置完成了。

2、接下来,开始把环境搞起来,这里我们选择android作为编译环境,其它的ARM linux系统应该更简单,😄,不要说了,android的bionic坑多多,这里选Android 4.3.x作为编译环境。都是android上运行的工具。步骤如下:

1)gcc 4.9.1 如果找不到,可以用俺的lisp4droid,里面自带gcc,还有个lisp实现,只要你安装马上就有整套工具了。

2)busybox,这个必需有。自己google下,到处都是。

3)设置环境变量,export PATH=/data/data/org.evilbinary.cl/system/gcc/arm-linux-androideabi/lib:/data/data/org.evilbinary.cl/system/gcc/arm-linux-androideabi/bin:/data/local/busybox:$PATH:/data/data/org.evilbinary.cl/system/rs/bin ,注意红色,这里用lisp4droid作为默认gcc path。

4)修改一下环境,让shell找得到。

mount -o remount rw /
mkdir /bin
ln -s  /system/bin/sh /bin/sh
mkdir /sqlite_stmt_journals/
mkdir /tmp
ln -s /data/local/busybox/pwd /bin/pwd

5)进入RScheme源码路径,开始

./configure --prefix=/data/data/org.evilbinary.cl/system/rs CFLAGS="-DANDROID -g -O"

6)开始make,注意顺序

make all
make rsc
make shell

7)选择几个package android没有x11 guitk  rdyl db httpd rstore 有些库,还需要修改一些代码,等有空的时候移植一下,问题不大,这样生成了packages。

make PACKAGES="general fasl syscalls unixm threads calendar lss sets ttywin" packages

8)接下来生产fshell,这个好用,库多。

make fasl_shell

9)好了完毕。发现/data/data/org.evilbinary.cl/system/rs 下多了几个东西 。表示成功了。

root@generic:/data/data/org.evilbinary.cl/system/rs # ls
bin       include   lib       resource

10)现在可以跑起来了fshell,帅气有木有。然后可以折腾了。

root@generic:/data/data/org.evilbinary.cl/system/rs # fshell                 
RScheme (v0.7.3.4-b7u, 2007-05-30)
Copyright (C) 1995-2005 Donovan Kolbly <d.kolbly@rscheme.org>
RScheme comes with ABSOLUTELY NO WARRANTY.
type ",warranty" for details; type ",help" for some help
top[0]=>(display "hello,world!\n")
hello,world!
top[1]=>

11)最后,把库搞到android上可以开发了,java里面用RScheme,这里有一个项目RScheme for android欢迎来fork。

3、最后,有问题请在下面留言。