之前我也写了一篇文章来说明
如何移植library到Android来说明大概要怎么移植。其实,里面有一些错误,错误的原因我觉得就是:水平有限。好了,废话不多说。进入正题。
一般来说,当你拿到一包library的source code,要按照如下的方式开始:
1.请仔细仔细的阅读Readme,以及各种文档.这里面包含了绝大部分你想要的东西。
2.
尝试的编译一个可以运行的版本出来看看效果。
a . 这时候你应该了解你要移植的库 , 是怎么编译的了吧?没有 ? Goto 1 : 继续往下阅读
b . 一般来说, source code 的编译会分成两种:
< 1 >. 只有一个 Makefile , 或者是有 configure 文件的。
这种的,最好是你阅读 makefile 文件 , 把这个 makefile 转换为 Android . mk 文件 , 使用 ndk build system 去编译。
< 2 >. 另一种的是大型的源代码系统。这种的通常都会有自己的 build system . 比如 android .
碰到这种大型的,可能源代码太多了,一时半会根本不能写出一个 Android . mk 文件。可以酱紫,换成你要的目标平台的 cross toolchain .
举个通常的 android 例子:
CC = $( Compile_Path )/ arm - eabi - gcc
STRIP = $( Compile_Path )/ arm - eabi - strip
AR = $( Compile_Path )/ arm - eabi - ar
LINK =&( Compile_Path )/ arm - eabi - g ++
再配合上一些编译参数:比如 , Compile_Flags = - fPIC , march = armv5t mno - thumb - interwork 之类的。
c . 试试看能不能编译出来。
能是最好的,不能,又要分几种情况了
< 1 >. 一般来说, source code 的逻辑不太会错误 . 所以不要尝试大幅度修改源代码(除非你有能力推翻重写 , 都重写那干嘛还要移植?) .
< 2 >. Compile 时,报语法错误,比如 result = obj -> func ()-> func2() ,会说类似“ XXX can ' t find func2 ”
你可以该成 : temp = obj -> func(); result = temp -> func2(); 这主要是编译器方面的差异。
< 3 >. Compile 时,报 "can't find xxx.h" or "can't find xxx.cpp xxx.c" 之类,请正确包含该文件;
比如你可以写上: INCLUDE_PATH += - I /../......./ include . 或者放到编译下的 include 路径。比如 ndk 目录下的 build / platforms / android - 3 / arch - arm / usr / include 下面 . 不过这不是好方法就是了 .
< 4 >. Link 时 , 报 "can't find reference XXX" ,基本是忘记添加库文件了。你可以写上 : Library_Path += - L /.../.../ lib 或者放到 ndk 下面的 build / platforms / android - 3 / arch - arm / usr / lib 下面。
< 5 >. 当你该加的 library 都加了,依然出现 "can't find reference XXX" , 那多半就是你用的库不是标准的,这里面没有 XXX 函数的实现 .
比如 android 的 bionic libc 就没有 ftime 函数(应该没记错吧?!)那你只好自己去添上实现文件了。
< 6 >. 又报 link error 了?通常来说,使用 android build system 的人,不应该会遇到这类问题。只有直接使用 toolchain 才有可能会出现这类问题,这类 link error 比较棘手。
解决的方法有:
( I) 库之间有依赖 , 正确的链接库的顺序;比如 libz . a 依赖 liby . a , 那么链接顺序是: ld liby . a libz . a
( II) 库版本不对,请仔细读 documentation . 这里要注意 version 的区别 , debug & release 的区别 , 是不是同一个编译器编译的库( ABI 会不一致) , static & shared 的区别
( III) C 和 C ++ 库之间的调用 . 要记得使用 extern "C" {}, 和# ifdef __PLUSPLUS
( IV) 我碰到这样一个问题,就是作者使用了 #define OWNFUNC(Function) NEWNAME##Function字符拼接宏,把所有的函数名都转换了,dumpobj时候当然找不到函数签名啦.
( V) 当你 link 成功了,运行的时候挂掉了 . 也可能是 link 的时候没有成功哦 . 举个列子来说明:
当你写了一个 android 的 c 版本的 helloworld , 编译链接过了,但是运行的时候告诉你 : "can't find _start symbol" , 这就是说 android OS 把执行权交个 c 的 runtime library 的时候 , 找不到入口 , 而这个入口就是 _start . 解决的办法是 : ld crtBegin_dynamic . o 以及 crtEnd_android . o
当然还有很多的问题不是上面说的这些,比如编译参数不对, - fPIC 和 - fpic , 应该编译 32 bit 的 arm 指令,却用了 16 bit thumb 指令 ... 等等。
< 7 > 大部分的问题,你都解决了。剩下各种平时都没见过的问题了?去论坛上问吧。我就挺喜欢到国外的论坛上去问的。
< 8 >. 考虑使用 ndk build system 方式来编译。
但不管怎么说,我推荐使用ndk build system方式。我曾经到 google ndk group 上去问过问题,得到过 David Turner 的回答:
You should not be trying to use the toolchain directly like this .... 省略 .... Really , you should use the NDK build system instead .
a . 这时候你应该了解你要移植的库 , 是怎么编译的了吧?没有 ? Goto 1 : 继续往下阅读
b . 一般来说, source code 的编译会分成两种:
< 1 >. 只有一个 Makefile , 或者是有 configure 文件的。
这种的,最好是你阅读 makefile 文件 , 把这个 makefile 转换为 Android . mk 文件 , 使用 ndk build system 去编译。
< 2 >. 另一种的是大型的源代码系统。这种的通常都会有自己的 build system . 比如 android .
碰到这种大型的,可能源代码太多了,一时半会根本不能写出一个 Android . mk 文件。可以酱紫,换成你要的目标平台的 cross toolchain .
举个通常的 android 例子:
CC = $( Compile_Path )/ arm - eabi - gcc
STRIP = $( Compile_Path )/ arm - eabi - strip
AR = $( Compile_Path )/ arm - eabi - ar
LINK =&( Compile_Path )/ arm - eabi - g ++
再配合上一些编译参数:比如 , Compile_Flags = - fPIC , march = armv5t mno - thumb - interwork 之类的。
c . 试试看能不能编译出来。
能是最好的,不能,又要分几种情况了
< 1 >. 一般来说, source code 的逻辑不太会错误 . 所以不要尝试大幅度修改源代码(除非你有能力推翻重写 , 都重写那干嘛还要移植?) .
< 2 >. Compile 时,报语法错误,比如 result = obj -> func ()-> func2() ,会说类似“ XXX can ' t find func2 ”
你可以该成 : temp = obj -> func(); result = temp -> func2(); 这主要是编译器方面的差异。
< 3 >. Compile 时,报 "can't find xxx.h" or "can't find xxx.cpp xxx.c" 之类,请正确包含该文件;
比如你可以写上: INCLUDE_PATH += - I /../......./ include . 或者放到编译下的 include 路径。比如 ndk 目录下的 build / platforms / android - 3 / arch - arm / usr / include 下面 . 不过这不是好方法就是了 .
< 4 >. Link 时 , 报 "can't find reference XXX" ,基本是忘记添加库文件了。你可以写上 : Library_Path += - L /.../.../ lib 或者放到 ndk 下面的 build / platforms / android - 3 / arch - arm / usr / lib 下面。
< 5 >. 当你该加的 library 都加了,依然出现 "can't find reference XXX" , 那多半就是你用的库不是标准的,这里面没有 XXX 函数的实现 .
比如 android 的 bionic libc 就没有 ftime 函数(应该没记错吧?!)那你只好自己去添上实现文件了。
< 6 >. 又报 link error 了?通常来说,使用 android build system 的人,不应该会遇到这类问题。只有直接使用 toolchain 才有可能会出现这类问题,这类 link error 比较棘手。
解决的方法有:
( I) 库之间有依赖 , 正确的链接库的顺序;比如 libz . a 依赖 liby . a , 那么链接顺序是: ld liby . a libz . a
( II) 库版本不对,请仔细读 documentation . 这里要注意 version 的区别 , debug & release 的区别 , 是不是同一个编译器编译的库( ABI 会不一致) , static & shared 的区别
( III) C 和 C ++ 库之间的调用 . 要记得使用 extern "C" {}, 和# ifdef __PLUSPLUS
( IV) 我碰到这样一个问题,就是作者使用了 #define OWNFUNC(Function) NEWNAME##Function字符拼接宏,把所有的函数名都转换了,dumpobj时候当然找不到函数签名啦.
( V) 当你 link 成功了,运行的时候挂掉了 . 也可能是 link 的时候没有成功哦 . 举个列子来说明:
当你写了一个 android 的 c 版本的 helloworld , 编译链接过了,但是运行的时候告诉你 : "can't find _start symbol" , 这就是说 android OS 把执行权交个 c 的 runtime library 的时候 , 找不到入口 , 而这个入口就是 _start . 解决的办法是 : ld crtBegin_dynamic . o 以及 crtEnd_android . o
当然还有很多的问题不是上面说的这些,比如编译参数不对, - fPIC 和 - fpic , 应该编译 32 bit 的 arm 指令,却用了 16 bit thumb 指令 ... 等等。
< 7 > 大部分的问题,你都解决了。剩下各种平时都没见过的问题了?去论坛上问吧。我就挺喜欢到国外的论坛上去问的。
< 8 >. 考虑使用 ndk build system 方式来编译。
但不管怎么说,我推荐使用ndk build system方式。我曾经到 google ndk group 上去问过问题,得到过 David Turner 的回答:
You should not be trying to use the toolchain directly like this .... 省略 .... Really , you should use the NDK build system instead .
3.
修改逻辑,添加逻辑适应自己的需要
.