Openssl移植到Android都是使用别人提好(从Android源码)的Openssl代码,方法简单但过程不那么顺利,因为Openssl版本变动太频繁了,再加上NDK一堆BUG,极不愿意去调试原始配置,单单Openssl的模块编译前后就等了两个月直到Google推出NDK新版本R8C才编译通过。因为原生程序应用到很多Openssl签名、验证算法函数,就连Openssl的版本升级一下往往都要修改一些代码才能通过。
一、下载Openssl最新版本
可选的Openssl Android版本下载地址:
Openssl 1.0.0a:
https://github.com/guardianproject/openssl-android
Openssl 1.0.1c:
https://github.com/aluvalasuman/OpenSSL1.0.1cForAndroid
本文将要使用的Openssl版本为1.0.1c,前一1.0.0a版本未验证通过(NDKr8b),编译时会出现下文的编译错误。所以改用较新版本,目前已知1.0.1c在NDK r8b上编译会有很多问题,不是Openssl工程有兼容BUG就是NDK版本有BUG,反正不是那么容易调试通过。
二、编译过程
本文编译使用最新的NDK r8c(Ubuntu 12.04),下载Openssl android工程后解压,可以看到完整的NDK工程,简单的编译过程如下:
- 进入解压目录,执行:
- $NDK_HOME/ndk-build clean
- $NDK_HOME/ndk-build
- 编译结果在obj目录下(libcrypto-static.a和libssl-static.a或是libcrypto.so和libssl.so)
- 把结果拷贝出来放到自己的Android工程Helloworld对应目录下进行调用即可。
上述步骤4编译出Openssl的链接库,一般拷贝到ndk_r8c\platforms\android-10\arch-arm\usr\lib目录下(仅为示例),然后把openssl根下的include目录都拷贝出去就是编译头文件,这样就可以构建自己的helloworld工程了,在helloworld的Android.mk中增加类似如下调用:
LOCAL_LDLIBS := -L$(SYSROOT)/lib/ -llog -lcrypto -lssl
三、常见错误
以下编译错误,有的在1.0.0a版本中遇到,有的是在NDK r8b环境下遇到,此间涉及到OpenSSL版本问题、GCC版本问题、NDK版本BUG问题,等等都混到一起总结方便对应处理。
1、undefined reference to `zError’
openssl 库时错误如下:
SharedLibrary : libssl.so Executable : openssl /root/android-ndk-r8b/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/../lib/gcc/arm-linux-androideabi/4.6.x-google/../../../../arm-linux-androideabi/bin/ld: warning: libz.so, needed by ./obj/local/armeabi/libcrypto.so, not found (try using -rpath or -rpath-link) ./obj/local/armeabi/libcrypto.so: undefined reference to `zError' ./obj/local/armeabi/libcrypto.so: undefined reference to `inflateEnd' ./obj/local/armeabi/libcrypto.so: undefined reference to `deflate' ./obj/local/armeabi/libcrypto.so: undefined reference to `deflateInit_' ./obj/local/armeabi/libcrypto.so: undefined reference to `inflate' ./obj/local/armeabi/libcrypto.so: undefined reference to `deflateEnd' ./obj/local/armeabi/libcrypto.so: undefined reference to `inflateInit_' collect2: ld returned 1 exit status
解决办法:
1、$NDK_HOME/ndk-build NDK_TOOLCHAIN_VERSION=4.4.3
或
$NDK_HOME/ndk-build NDK_TOOLCHAIN=arm-linux-androideabi-4.4.3
该方法参考来自:android-ndk-r8b/doc/NDK-BUILD.html 说明,ndk-build可以携带 NDK_XXX这样的参数,来指定编译环境版本信息。具体参数有哪些?目前可以通过android-ndk-r8b/build/core/init.mk里查询到一些NDK_开头的参数。
2、在openssl的jni目录下的Application.mk中增加:
APP_PLATFORM := android-8
3、在openssl根下的android-config.mk中增加:
APP_ABI := armeabi armeabi-v7a
该参考来源android-ndk-r8b/docs/APPLICATION-MK.html
2、Unknown EABI object attribute 44
SharedLibrary : libssl.so /root/android-ndk-r8b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld: Warning: /root/android-ndk-r8b/platforms/android-8/arch-arm/usr/lib/crtend_so.o: Unknown EABI object attribute 44 Executable : openssl /root/android-ndk-r8b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld: Warning: /root/android-ndk-r8b/platforms/android-8/arch-arm/usr/lib/crtend_android.o: Unknown EABI object attribute 44 Install : openssl => /root/aluvalassuman/libs/armeabi/openssl Install : libssl.so => /root/aluvalassuman/libs/armeabi/libssl.so Compile thumb : ssltest <= ssltest.c Executable : ssltest /root/android-ndk-r8b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld: Warning: /root/android-ndk-r8b/platforms/android-8/arch-arm/usr/lib/crtend_android.o: Unknown EABI object attribute 44 Install : ssltest => /root/aluvalassuman/libs/armeabi/ssltest
解决办法:
4.4.3似乎跟链接库的编译环境可能对不上(44冲突),网上有说改成4.6就没问题了,不会出现该提示,但是4.6支持STL有BUG啊?
crypto/Android.mk 大约535行,添加:
LOCAL_EXPORT_LDLIBS := -lz
注意有没添加以下两个静态库,大约576行,添加(暂时不用):
LOCAL_LDLIBS := -lz –ldl
3、build/gmsl/__gmsl:512: *** non-numeric second
Complile Openssl:
Error:
build/gmsl/__gmsl:512: *** non-numeric second
Changes:
I changed the file __gmsl, the second wordlist argument(line 512),
and it’s running my jni example without errors:
int_encode = $(__gmsl_tr1)$(wordlist 1, $1,$(__gmsl_input_int))
to:
int_encode = $(__gmsl_tr1)$(wordlist 1,$(words $1),$
(__gmsl_input_int))
参考资料(下述可能有地址被墙了):
http://www.uml.org.cn/mobiledev/201108101.asp
http://blog.csdn.net/someonea/article/details/6312213
http://ssuman185.blogspot.sg/p/steps-for-porting-openssl-for-android.html
http://stackoverflow.com/questions/11856688/openssl-build-issue-with-android-ndk-r8
http://stackoverflow.com/questions/11929773/compiling-the-latest-openssl-for-android
https://groups.google.com/forum/?fromgroups=#!topic/android-ndk/b4DSxE1NAS0