本文记录在实际使用中编译 Android Native 的 Protobuf 库的过程,以备不时之需。我是采用 NDK 的独立工具链的形式编译的,编译的 Protobuf 的版本是 2.6.1 。更高版本的编译方法可以参考如下第二篇文献。
参考:
1. 制作 NDK 独立工具链
首先,基于NDK17制作一个独立工具链,后面通过此工具链来编译 Protobuf 。
# 使用 ndk17 生成一个工具链
bash /Users/lixiaoqing/Library/Android/sdk/ndk/17.2.4988734/build/tools/make-standalone-toolchain.sh \
--arch=arm \
--platform=android-17 \
--toolchain=arm-linux-androideabi-4.9 \
--install-dir=/Users/lixiaoqing/Desktop/Tools/toolchains/arm-ndk17
2. 下载 Protobuf 源码
cd /Users/lixiaoqing/Desktop/Tools/protobuf/
git clone https://github.com/protocolbuffers/protobuf.git
cd protobuf
git checkout v2.6.1
./autogen.sh
mkdir build && cd build
vim build_protobuf_android.sh
注意:如果在执行 autogen.sh
脚本的时候提示 tar 错误,原因是之前的网址已经没有 googletest 的资源,需要修改该脚本为:
#curl http://googletest.googlecode.com/files/gtest-1.5.0.tar.bz2 | tar jx
#mv gtest-1.5.0 gtest
curl -L https://github.com/google/googletest/archive/release-1.5.0.tar.gz | tar zx
mv googletest-release-1.5.0 gtest
3. 编译 Protobuf
基于 llvm 的 c++_shared.so 编译 protobuf :
toolchain_path=/Users/lixiaoqing/Desktop/Tools/toolchains/arm-ndk17/
export NDK_ROOT=/Users/lixiaoqing/Library/Android/sdk/ndk/17.2.4988734
export PREFIX=/Users/lixiaoqing/Desktop/Tools/protobuf/build
export PATH=${toolchain_path}/bin:$PATH
export SYSROOT=${toolchain_path}/sysroot
export CC="arm-linux-androideabi-gcc --sysroot $SYSROOT"
export CXX="arm-linux-androideabi-g++ --sysroot $SYSROOT"
export CXXSTL=$NDK_ROOT/sources/cxx-stl/llvm-libc++
../configure \
--prefix=$PREFIX \
--host=arm-linux-androideabi \
--with-sysroot="${SYSROOT}" \
--enable-shared \
--enable-cross-compile \
--with-protoc=protoc \
CFLAGS="-march=armv7-a -D__ANDROID_API__=17" \
CXXFLAGS="-frtti -fexceptions -march=armv7-a -D__ANDROID_API__=17" \
LDFLAGS="-L${NDK_ROOT}/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a" \
LIBS="-llog -lz -lc++_shared"
make -j10
make install
然后运行该脚本,开始编译 protobuf ,编译成功的 protobuf 库和头文件在上面脚本文件中 PREFIX 目录下:
# 库目录
lib/
# 头文件目录
include/
问题
但是,我通过此方法编出来的 protobuf 和一位同事编出来的库不一致。比如对于这个符号 SerializeToString ,我编出来的库是这样的:
$ nm libprotobuf.a | grep SerializeToString
00001b10 T _ZNK6google8protobuf11MessageLite17SerializeToStringEPSs
U _ZNK6google8protobuf11MessageLite17SerializeToStringEPSs
而同事编出来的符号是这样的:
$ nm libprotobuf.a | grep SerializeToString
000021d8 T _ZNK6google8protobuf11MessageLite17SerializeToStringEPNSt6__ndk112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE
U _ZNK6google8protobuf11MessageLite17SerializeToStringEPNSt6__ndk112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE
项目如果使用我编的库会出现问题,而使用同事编的库则没有问题。尝试了多次我编出来的库还是会有一样的问题,我也不知道问题出在了哪,各位如果知道的话还请不吝赐教,感谢~