一、编译环境
操作系统: ubuntu16.04 32位
NDK版本: Android-ndk-r10b
源码版本: curl-7.61.0
环境变量:/etc/profile
export NDK_HOME=/opt/android/ndk/android-ndk-r10b
export PATH=/opt/android/ndk/android-ndk-r10b
export ANDROID_NDK_ROOT=/opt/android/ndk/android-ndk-r10b
export ANDROID_NDK_HOME=/opt/android/ndk/android-ndk-r10b
二、配置依赖库,设置编译参数
1.将libcurl移植(上)中生成的libcrypt.a libssl.a放到
/xxxx/android-ndk-r10b/plaforms/android-xx/arch-arm/usr/lib目录
2.将libcurl移植(上)中输出的头文件放到
/xxxx/android-ndk-r10b/plaforms/android-xx/arch-arm/usr/include目录
注意要将整个头文件所在openssl文件夹拷贝过去,不能只拷贝头文件.
3.生成工具链
/xxxx/android-ndk-r10b/build//make-standalone-toolchain.sh \
--platform=android-19 \ #指定目标平台版本
--install-dir=/tmp/my-android-toolchain
如果不加 --install-dir 选项,则会创建 /tmp/ndk/<toolchain-name>.tar.bz2。
三、编辑编译脚本
#注意下列脚本PATH需要替换为自己生成的工具链真实路径
export PATH=/opt/android/ndk/arm-linux-androideabi-4.6/bin:$PATH
export CC=arm-linux-androideabi-gcc
export CXX=arm-linux-androideabi-g++
#编辑依赖库选项 libc libssl libcrypto libc
#如何不链接libc 链接时可能会报pthread_xxxxx相关函数未定义,这是一个坑点
export LIBS="-ldl -lc -lssl -lcrypto "
#以下为指定生成与地址无关代码,同事指定附加的依赖库及头文件所在文件夹路径替换成自己的
export LDFLAGS="-pie -fPIE -L/opt/android/ndk/android-ndk-r10b/platforms/android-xx/arch-arm/usr/lib"
export CFLAGS="-I/opt/android/ndk/android-ndk-r10b/platforms/android-xx/arch-arm/usr/include"
#指定编译配置选项 --host指定目标平台 --with-ssl开启https支持
./configure --host=arm-linux-androideabi \#生成的目标平台
--with-ssl \#开启https支持
--disable-share\
--enable-static \
--disable-dict \
--disable-ftp \
--disable-imap \
--disable-ldap \
--disable-ldaps \
--disable-pop3 \
--disable-proxy \
--disable-rtsp \
--disable-smtp \
--disable-telnet \
--disable-tftp \
--disable-zlib \
--without-ca-bundle \
--without-gnutls \
--without-libidn \
--without-librtmp \
--without-libssh2 \
--without-nss \
--without-zlib \
--prefix=/usr/project/jni/curl-output #指定输出文件目录
#启动编译
make
#安装
make install
四、修改预处理宏定义
打开源码文件/xxx/curl-7.61.0/lib/curl_config.h.in,
打开以下宏定义 如#define HAVE_LIBSSL 1
HAVE_LIBSSL、 HAVE_OPENSSL_CRYPTO_H、HAVE_OPENSSL_ERR_H、HAVE_OPENSSL_PEM_H、 HAVE_OPENSSL_PKCS12_H、HAVE_OPENSSL_RSA_H、HAVE_OPENSSL_SSL_H、 HAVE_OPENSSL_X509_H、USE_OPENSSL、USE_SSLEAY
(但是注意android没有编译openssl中的 ,因此不要打开宏定义HAVE_OPENSSL_ENGINE_H),
注释掉宏定义HAVE_MALLOC_H和HAVE_IOCTL
五、执行编译脚本
命令行下执行流程三处编译的脚本。生成二进制文件及头文件在–prefix指定的目录中查找..
libcurl移植的几个坑
1.链接libcrypto libssl失败,已将该两处库拷贝到相应的公共库目录,链接时提示找不到对应的库,此时检查生成的lib库是否为arm版本,因前期移植过程中发现openssl配置选项为arm平台 但是生成的却是linux-x86平台
2.各种头文件找不到,openssl从网上下载的编译脚本setenv-android.sh由于不同源码版本差异可能需要配置的临时参数不同,openssl-1.1.0f编译时提示找不到头文件如assert.h,查看编译错误信息发现生成的编译参数 –sys_root=”“值为空,查看Makefile脚本发现 该值–sys_root=$(CROSS_SYSROOT)而CROSS_SYSROOT值在脚本上文中并未定义,因此需要在setenv-android.sh中进行公开声明导出CROSS_SYSROOT的值.
3.提示pthread_xxx_xxxx等函数找不到定义,是由于libcurl链接时依赖posix的pthread多线程库,但是android_9之后arm平台已没有pthread.a库,android_9及之前可以添加-lpthread来解决, 后续查询相关文档发现pthread多线程函数已迁移到libc库中,因此需要手动指定链接该库 所以需要在-LDFLAGS添加-lc选项 -l表明为一个需要链接的库, c代表库的名字,如-lssl、-lcrypto分别代表链接 libssl libcrypto等库,注意指定依赖库时如果库名字为libxxxx则添加的选项应为 -lxxxx.
4.编译完成后的程序运行时报PIE错误,此时需要在编译时添加 -pie -fPIE选项用来生成与地址无关代码