最近在开发跨平台项目使用语言时c/c++,网络库使用的libcurl,需要支持https。本篇文章主要介绍android平台的libcurl编译。
1.编译工具: Linux 16.04, ndk 23
2.开源包下载:
zlib库 http://www.zlib.net/ 最新版本就可以(作者下载版本2.13.0);
openssl库 https://www.openssl.org/source/ 根据需求下载版本(作者下载版本1.1.1);
libcurl库 https://curl.se/download.html 根据需求下载版本 (为了项目的兼容性,作者使用版本7.58.0)。
3.编译:
3.1 写通用shell, 文件名称build-env.sh
#!/bin/bash
#NDK path,openssl need ANDROID_NDK_ROOT var,so export
export ANDROID_NDK_ROOT=$HOME/android_libs/android-ndk-r23b
export ANDROID_NDK_HOME=$HOME/android_libs/android-ndk-r23b
#complier platform linux-x86_64
HOST_TAG=linux-x86_64
#Android api version
MIN_SDK_VERSION=23
#toolchains path
TOOLCHAIN=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/$HOST_TAG
#add path
PATH=$TOOLCHAIN/bin:$PATH
#out dir build
BUILD_DIR=$PWD/build
由于Android已经放弃了gcc,现在的编译器是clang和clang++。要适用于所有CPU架构,我们要编译armv8、armv7、x86、x86_64四个平台。他们会使用不同的clang来编译,aarch64-linux-android表示要编译armv8,armv7a-linux-androideabi表示要编译armv7a,i686-linux-android表示要编译x86,x86_64-linux-android表示要编译x86_64。
3.2 编译zlib, 配置好工具链后执行configure,我们同样编写脚本执行,脚本名称build-zlib.sh
#!/bin/bash
CRTDIR=$(pwd)
tar xzf $CRTDIR/zlib-1.2.13.tar.gz
source $CRTDIR/build-env.sh
INSTALL_DIR=$BUILD_DIR/zlib
if [ ! -d $INSTALL_DIR ]; then
mkdir -p $INSTALL_DIR
fi
cd zlib-1.2.13
function build() {
make distclean
TARGET_HOST=$1
ANDROID_ARCH=$2
AR=$TOOLCHAIN/bin/llvm-ar
CC=$TOOLCHAIN/bin/$TARGET_HOST$MIN_SDK_VERSION-clang
AS=$CC
CXX=$TOOLCHAIN/bin/$TARGET_HOST$MIN_SDK_VERSION-clang++
LD=$TOOLCHAIN/bin/ld
RANLIB=$TOOLCHAIN/bin/llvm-ranlib
STRIP=$TOOLCHAIN/bin/llvm-strip
./configure --prefix=$INSTALL_DIR/$ANDROID_ARCH --shared --enable-shared
make -j8
make install
make distclean
}
build aarch64-linux-android arm64-v8a
build x86_64-linux-android x86_64
cd ..
rm -rf cd $CRTDIR/zlib-1.2.13
这边我只需要arm64-v8a 和 x86_64平台的库,这边我编译出的arm64-v8a库有一点问题(libcurl检查连接时找不到libz动态库)。
3.3 openssl编译,我只需要arm64-v8a 和 x86_64平台的库,同样继续写脚本,名称build-openssl.sh
#!/bin/bash
CRTDIR=$(pwd)
tar xzf $CRTDIR/openssl-1.1.1s.tar.gz
source $CRTDIR/build-env.sh
INSTALL_DIR=$BUILD_DIR/openssl
if [ ! -d $INSTALL_DIR ]; then
mkdir -p $INSTALL_DIR
fi
cd openssl-1.1.1s
function build() {
TARGET_HOST=$1
ANDROID_ARCH=$2
OPENSSL_ARCH=$3
AR=$TOOLCHAIN/bin/llvm-ar
CC=$TOOLCHAIN/bin/$TARGET_HOST$MIN_SDK_VERSION-clang
AS=$CC
CXX=$TOOLCHAIN/bin/$TARGET_HOST$MIN_SDK_VERSION-clang++
LD=$TOOLCHAIN/bin/ld
RANLIB=$TOOLCHAIN/bin/llvm-ranlib
STRIP=$TOOLCHAIN/bin/llvm-strip
./Configure $OPENSSL_ARCH no-unit-test -shared -D__ANDROID_API__=$MIN_SDK_VERSION --prefix=$INSTALL_DIR/$ANDROID_ARCH
make -j8
make install_sw
make distclean
}
build aarch64-linux-android arm64-v8a android-arm64
build x86_64-linux-android x86_64 android-x86_64
cd ..
rm -rf $CRTDIR/openssl-1.1.1s
no-unit-test表示不需要单元测试,-D__ANDROID_API__=$MIN_SDK_VERSION传递Android api版本。
3.4 libcurl编译,准备工作已经完成(zlib,openssl编译完成),同样是configure,make,make install 步骤。关键参数可以查看configure文件使用。同样脚本文件执行,脚本名称build-curl.sh
#!/bin/bash
CRTDIR=$(pwd)
tar xzf $CRTDIR/curl-7.58.0.tar.gz
source $CRTDIR/build-env.sh
INSTALL_DIR=$BUILD_DIR/curl
if [ ! -d $INSTALL_DIR ]; then
mkdir -p $INSTALL_DIR
fi
cd curl-7.58.0
function build() {
export TARGET_HOST=$1
export ANDROID_ARCH=$2
export AR=$TOOLCHAIN/bin/llvm-ar
export CC=$TOOLCHAIN/bin/$TARGET_HOST$MIN_SDK_VERSION-clang
export AS=$CC
export CXX=$TOOLCHAIN/bin/$TARGET_HOST$MIN_SDK_VERSION-clang++
export LD=$TOOLCHAIN/bin/ld
export RANLIB=$TOOLCHAIN/bin/llvm-ranlib
export STRIP=$TOOLCHAIN/bin/llvm-strip
./configure --host=$TARGET_HOST --target=$TARGET_HOST --prefix=$INSTALL_DIR/$ANDROID_ARCH --with-zlib=$BUILD_DIR/zlib/$ANDROID_ARCH --with-ssl=$BUILD_DIR/openssl/$ANDROID_ARCH --with-ca-bundle=/data/zhangaichen/cacert.pem --with-pic --enable-shared --enable-static
make -j8
make install
make clean
}
build aarch64-linux-android arm64-v8a
build x86_64-linux-android x86_64
cd ..
rm -rf cd $CRTDIR/curl-7.58.0
执行脚本,生成的x86_64环境和arm64-v8a环境库。
4.编译中遇到问题
4.1 脚本执行使用sh,报错 source: not found,查找资料发现source属于bash脚本,执行 bash xxx.sh 解决此问题。
4.2libcurl编译库arm64-v8a环境的库不支持zlib,重新执行查看编译输出报configure: WARNING: configure found only the libz header file, not the lib! 没有找到zlib动态库,继续去本地找config.log(注释掉rm -rf cd $CRTDIR/curl-7.58.0这一行)查看日志,找到ld: error: /home/data/android_complier/build/zlib/arm64-v8a/lib/libz.so is incompatible with aarch64linux
clang-12: error: linker command failed with exit code 1 (use -v to see invocation),发现是libz.so与要求不符合,去查看arm64-v8a环境libz.so截图如下
将libz.so删除,从arm64-v8a系统里导出,放到此路径下,重新编译liburl的arm64-v8a环境支持zlib功能。
5.参考资料:
5.1 https://blog.csdn.net/lkun2002/article/details/129595631?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-5-129595631-blog-126852683.235v38pc_relevant_default_base&spm=1001.2101.3001.4242.4&utm_relevant_index=8
5.2 https://blog.csdn.net/weixin_41399054/article/details/121901382