蛋疼的NDK

最近在ndk下面编译某个lib,可惜这个lib用到了神棍的boost中的regex,恰好regex不仅仅是头文件是需要编译的,而且还是很旧的boost版本。于是乎折腾了半天boost在ndk下面的编译。主要是和jam这个令人发狂的语言打交道(有时间我一定专门出来吐槽),最后即将崩溃的时候,灵光乍现搞定了这坨玩意儿,编译出了静态库。

本以为接下来天下太平,link完毕之后又出现运行时错误。折腾了两个晚上,第一晚搞明白了ndk中的g++是把wchar_t当做4字节处理的,第二晚搞明白了这样做的原因:

google你是在坑爹啊!!!!尼玛wchar_t相关的函数根本没实现啊!!!!运行时各种诡异啊!!!!你们这帮家伙在想神马啊!!!!

参考一下两个链接中的内容就知道我有多想抽他们了:

http://code.google.com/p/android/issues/detail?id=4780

http://www.crystax.net/trac/ticket/25#

不让用就搞得明显点嘛,编译通过之后搞各种trick是怎么回事啊,ndk二等公民的身份彰显无疑……这下彻底傻x了,等吧。

Android版SDL编译

NDK刚刚发布的时候,我想试试看怎么用于是去找了个开源的游戏,发现这个叫做《Alien Blaster》的游戏源码中带着移植好的SDL。最近搜了一下,这个作者貌似专心去搞SDL的Android移植了,具体可以看http://libsdl-android.sourceforge.net/。众所周知SDL是个适用范围挺广的跨平台图像库,所以这个东东一旦被移植到Android上,很快就可以出现一大堆其他移植作品。

于是从github上得到最新的代码,我开始尝试在cygwin下编译它。相比起早先的那个alienblaster项目,这个sdl-android的编译还挺诡异的,主要是作者自己在makefile外面包装了一堆自动化的东西,再加上linux和cygwin不完全一样,折腾了半天才搞定。稍后再吐槽……

先得确定NDK的版本,按照他目前的说明得用r4b,而SDK版本需要2.2,不过编译出来的程序可以跑在1.6上。在这里我不得不吐槽这帮搞android的家伙,头三个NDK版本都做的无比奇怪,想编译还得把自己的项目放在NDK的app目录下才行。到了r4终于不用把工程目录诺来挪去了,结果SDK的tools目录内容又起了大变化。还真是热爱折腾啊……

在确定NDK工作正常之后,进入sdl-android里面那个commandergenius目录,需要编译的脚本都已经放在里面了,可惜在Cygwin下需要修改才可使用。首先是他在代码文件中用了linux下的符号链接,目前发现的就是sdl-1.2里面很多文件都是链接到1.3里面的,需要修改。我是选择把1.3里对应的文件直接拷贝到1.2的目录里,省得麻烦。

在project/jni里面是各种lib的代码,比如我们最关心的SDL,还有其他一些开源的库,project/jni/application里面是各种独立的应用。按照readme里面的介绍,想编译哪个应用,就通过ln命令,把project/jni/application/下的源码目录做符号链接到project/jni/application/src,然后进行编译。这样makefile始终是编译project/jni/application/src下的东西。例如按照readme里面说的:

rm project/jni/application/src

ln -s ballfield project/jni/application/src

然后就是比较奇怪的地方了,这个作者喜欢在编译期决定各种配置,执行ChangeAppSettings.sh -a会生成一个配置文件,然后根据配置文件又修改了project/java下的java代码模板拷贝到project/src中。主要是配置项目有将近20个,执行脚本的时候会不停的询问各种问题,搞得无比烦躁。其实都是可以在运行时修改的东西没必要在编译期出来烦人的。后来发现每个appliction下的目录中都有一个现成的AndroidAppSettings.cfg,可以把这个直接拿来覆盖掉commandergenius/的那个,这样每次提问开始的时候直接回车就可以使用默认配置。

这步执行完毕之后再执行android update project -p project得到build.xml用于编译apk。至此就完成了一大半了。

接下来修改build.sh,把自己的NDK路径配置好。值得注意的是NDKBUILDPATH里面如果有空格记得加上引号,例如我是这样的:

NDKBUILDPATH=$NDK4:$PATH

#.....各种省略

cd project && env PATH="$NDKBUILDPATH" nice -n19 ndk-build -j4 V=1 && \

#.....各种省略

咱对linux各种不熟,env这一行卡了好久,感谢贾生同学指点迷津。嗯嗯,最后调用sh build.sh就可以开始编译了。基本上是执行了ndk-build之后再使用ant来编译java代码,大概都觉得eclipse太重口味了吧……build.sh里面包含了对adb install的调用,所以记得把SDK的platform-tools目录也加到PATH中。手动进入project目录编译lib,然后用eclipse编译安装也一样。

总结一下,我个人觉得这个SDL的移植版还是比较有用的,可惜java端的包装就有点粗糙了(或者说繁缛)。所以自己想用的话,还是得做一些额外的工作才行,除非接受作者的设定,例如从AndroidData或者设定的url下载数据自动解压安装屏幕上有奇怪的软件虚拟键盘还有要填写十几个问题的config问卷什么的= =b