Code a World
MoSync Intro
声明:本文完全是按照自己理解所写,不对内容的正确性和准确性负责,请以MoSync的官方文档和代码为准。
MoSync 是一个开源的移动应用的跨平台开发框架。
1. Intro
当前市面上流行的主要的系统有 Android (包括API3-12), Symbian 60 (v2, v3, v5) , IOS, Win Mobile (5, 6, 6pro), Meego... 如果你想只写一套代码能在上面所有平台都能运行,现在来说只能用Java, 而且Android,Meego还是得单独维护, MoSync 就是这样的一个平台, 你只要写一个MoSync Project, 然后看到右侧的图片了么,选择你的手机型号,双击,大功告成~,你想换一个型号么,选择,双击,OK,还能批量选择生成的。使用Android的手机,它就会生成apk程序给你;使用Symbian的手机,它就会生成sis程序给你;Win Mobile? 自然是cab程序了。
如果你开发过手机应用,几乎为每个型号都维护一个版本,每个型号都有单独的补丁,看到这里你一定激动万分。
2. MoSync
MoSync 的设计很宏大,它实际上是一个引擎, 目标是接受各种语言的Project(现在只支持C/C++), 输出满足任意型号手机(现在已支持流行的大部分手机)的程序。 实现这个目标理论上只有一种可能----虚拟机。MoSync的核心其实就是个虚拟机,是一个基于寄存器的虚拟机(jvm 是基于stack 的,Android自带的davik也是基于寄存器的),有自己的指令集, 支持自己的bytecode。这个虚拟机设计的非常小巧,针对移动平台优化,不用预装在手机上,会和你的程序打包在一起, 然后你的程序在手机运行的时候,其实是先启动的这个虚拟机。速度上起码要比jvm快。
MoSync 的代价是抛弃各个平台的SDK,程序必须按照它自己的API写, 意味着你必须花时间学习它的API,不过这点代价对程序员来说应该没什么问题, 而且其官方文档和示例也很全面。它还定制了Eclipse来作为专用的IDE。
3. MoSync Building Process
MoSync定制了GCC作为其编译器,它给GCC增加了一个自己的后端(back-end) 负责把程序编译成其自己的中间语言 MoSync IL, 然后用其链接器Pipe-tool把用到的libs一起链接成二进制程序(相当于java 的 class 文件),最后根据你选的手机型号来打包,把你的程序和对应手机平台的虚拟机打包在一起,生成对应的安装包(apk, sis, cab),就可以安装到手机了。
用MoSync为Mac开发程序要多走一步程序,因为这时Packaging打包生成的不是安装包,而是一个完整的XCode Project, 你需要用XCode打开这个project, 然后就像你以前开发Mac程序一样编译,安装就行了。
由此可见,MoSync真是煞费苦心,不惜从中间语言(IL) 逆向重新生成源文件来支持Mac,封闭系统害死人啊。
4. MoSync IL
每一个虚拟机都有一套自己的中间语言,包括特定的指令集,语法等等。 一般都有两种等价形式-----汇编形式和二进制形式, 只是可读和不可读的区别。
MoSync 的汇编IL包含了详细的stabs格式的元信息(由gcc -stabs 生成), 通过这些元信息,必要的时候完全可以将这些汇编语言转换回高级语言形式,自然也可以生成源代码,上面说的Mac的方式就是这样操作的。 二进制的bytecode 去掉了这些元信息。
MoSync IL的共有128个寄存器,常用的有32个[1][2]。指令集也非常简单,没有浮点指令,所有浮点运算都转化为调用相应的函数完成。
5. MoSync Pipe-Tool
Pipe-Tool 是一个复杂的工具,包含了资源编译器, 链接器,还有代码优化的功能[3]。从汇编语言生成源代码的活也是它干的,已经实现可以从汇编语言生成C++或者Java的源代码,无论你源码原来是用什么写的,当然目前你只能用c/c++来写... 下面是从其文档上摘录的几点特别的地方:
6. MoSync Runtime Core
Runtime 是MoSync 的核心, 就是虚拟机的部分。虚拟机最基本的功能就是一行行的解释执行bytecode,或者JIT的形式将bytecode转换成目标机器native的代码,然后再执行。 这两种形式MoSync都实现了,叫VM Core 和 Recompiler Core。 官方还有一种Core叫Generated Core, 说的就是为mac支持的那种重新生成源代码的形式, 这里就不叫它Core了... 我觉的它不算Runtime的部分。
第一个问题就是要保证MoSync 这个虚拟机本身能在所有手机平台高效运行,这就没什么好办法了,只能每个手机型号维护一个版本,尽量为每个型号进行优化了(这就是牺牲一人,幸福大家的精神啊)... 不过可想而知,为JVM实现的版本,就是JVM虚拟机上再运行MoSync虚拟机,效率肯定不会高。VM Core 最终是要抛弃的,Pipe-Toole 将为只能运行Java程序的手机直接生成Java bytecode, 省得再加一层虚拟机。Recompiler core (其实就是JIT,不知为什么非得再起个名字,弄得我查了半天与JIT的区别) 目前只实现了 win mobile 5 以上 和 symbian s60 以上的版本,程序再启动时先将代码转换成目标机native的代码,这样会有一点延时启动的效果,但是转换后的代码效率就要看转换引擎了。
关于Android版本的Recompiler Core正在开发当中, 目前采用的还是VM Core。因为涉及到Android 本身应用就不是Native的形式,所以Recompiler Core实现上有些复杂, 这点可以参考[4].
7. Benchmark
目前无论官方还是第三方都找不到任何MoSync 相关的Benchmark,无法给出准确的数据说明采用MoSync的实现对效率到底有多少影响。我自己做了一个关于win mobile 5 上Native程序与MoSync Recompiler Core 之间简单的Benchmark, 方法是用Zlib对1M随机文本进行内存压缩。 首先要移植Zlib 到MoSync,其实很简单,MoSync的标准C库采用 newlib, 所以直接把代码组织成 MoSync Project, 然后编译就行了(MoSync IDE 默认的是不是采用newlib, 需要设置一下[5])。 Native版本的Win Mobile Zlib 直接从网上下载的 zilbCE。使用同样的版本1.2.3,因为我能找到的最新 zlibCE就是1.2.3了... 采用内存压缩1M 随机文本也是无奈之举, 因为用MoSync 标准C库的 fopen 实现有问题, 无法读取手机上的文件, 而手机又很老了,能跑起来的程序最大只能处理1M文本了。 不过结果还可以还是有可比性的,因为每次都是随机生成的文本, 分别取10次运行的平均结果, MoSync程序用了8000多毫秒, Native的程序只用了不到4000毫秒, 还是有点差距的。
8. Conclusion
MoSync还在开发当中,能做到现在的程度已经很不错了,为了跨平台的可靠性, 为了不让程序员们不停的进行各种版本的测试和调试,MoSync自己本身就必须做更多的手机平台测试,而且要保证一致性。
最重要的是它的用户体验非常好,你只需要维护一套代码,然后去选择手机就可以了,应该没有比这更简单的策略了吧。所以还是很值得期待的。
更多详细内容请参考官方文档。
Reference
[1] http://www.mosync.com/content/how-many-number-registers-used-mosync-il
[2] http://www.mosync.com/files/MoSync%20IL%20register%20set.pdf
[3] http://www.mosync.com/documentation/manualpages/toolchain
[4] Generally questions affect to the MoSync Build Process http://www.mosync.com/node/6690
[5] http://www.mosync.com/content/sdl-stl-standard-cc-libs