最近需要在安卓jni里集成protobuf,网上找了一圈没有现成的so,只能自已下源码编译。
源码 github
开始
# 下载源码
$ git clone https://github.com/protocolbuffers/protobuf.git
# 切成自已需要的版本
$ git checkout v3.5.1
# 新建文件夹
$ mkdir jni && cd jni
然后把src里面的所有文件复制到jni目录
在jni目录下新建Application.mk文件,内容如下:
APP_ABI := all
APP_STL := c++_static
在jni目录下新建Android.mk文件,内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CPPFLAGS += -fexceptions
LOCAL_CPPFLAGS += -frtti
LOCAL_CPPFLAGS += -lstdc++
LOCAL_MODULE := libproto
LOCAL_SRC_FILES := google/protobuf/stubs/atomicops_internals_x86_gcc.cc \
google/protobuf/stubs/atomicops_internals_x86_msvc.cc \
google/protobuf/stubs/bytestream.cc \
google/protobuf/stubs/bytestream.h \
google/protobuf/stubs/common.cc \
google/protobuf/stubs/hash.h \
google/protobuf/stubs/int128.cc \
google/protobuf/stubs/int128.h \
google/protobuf/stubs/io_win32.cc \
google/protobuf/stubs/io_win32.h \
google/protobuf/stubs/map_util.h \
google/protobuf/stubs/mathutil.h \
google/protobuf/stubs/once.cc \
google/protobuf/stubs/shared_ptr.h \
google/protobuf/stubs/status.cc \
google/protobuf/stubs/status.h \
google/protobuf/stubs/status_macros.h \
google/protobuf/stubs/statusor.cc \
google/protobuf/stubs/statusor.h \
google/protobuf/stubs/stringpiece.cc \
google/protobuf/stubs/stringpiece.h \
google/protobuf/stubs/stringprintf.cc \
google/protobuf/stubs/stringprintf.h \
google/protobuf/stubs/structurally_valid.cc \
google/protobuf/stubs/strutil.cc \
google/protobuf/stubs/strutil.h \
google/protobuf/stubs/time.cc \
google/protobuf/stubs/time.h \
google/protobuf/arena.cc \
google/protobuf/arenastring.cc \
google/protobuf/extension_set.cc \
google/protobuf/generated_message_util.cc \
google/protobuf/generated_message_table_driven_lite.h \
google/protobuf/generated_message_table_driven_lite.cc \
google/protobuf/message_lite.cc \
google/protobuf/repeated_field.cc \
google/protobuf/wire_format_lite.cc \
google/protobuf/io/coded_stream.cc \
google/protobuf/io/coded_stream_inl.h \
google/protobuf/io/zero_copy_stream.cc \
google/protobuf/io/zero_copy_stream_impl_lite.cc \
google/protobuf/any.pb.cc \
google/protobuf/api.pb.cc \
google/protobuf/stubs/mathlimits.cc \
google/protobuf/stubs/mathlimits.h \
google/protobuf/any.cc \
google/protobuf/descriptor.cc \
google/protobuf/descriptor_database.cc \
google/protobuf/descriptor.pb.cc \
google/protobuf/duration.pb.cc \
google/protobuf/dynamic_message.cc \
google/protobuf/empty.pb.cc \
google/protobuf/extension_set_heavy.cc \
google/protobuf/field_mask.pb.cc \
google/protobuf/generated_message_reflection.cc \
google/protobuf/generated_message_table_driven_lite.h \
google/protobuf/generated_message_table_driven.cc \
google/protobuf/map_field.cc \
google/protobuf/message.cc \
google/protobuf/reflection_internal.h \
google/protobuf/reflection_ops.cc \
google/protobuf/service.cc \
google/protobuf/source_context.pb.cc \
google/protobuf/struct.pb.cc \
google/protobuf/stubs/substitute.cc \
google/protobuf/stubs/substitute.h \
google/protobuf/text_format.cc \
google/protobuf/timestamp.pb.cc \
google/protobuf/type.pb.cc \
google/protobuf/unknown_field_set.cc \
google/protobuf/wire_format.cc \
google/protobuf/wrappers.pb.cc \
google/protobuf/io/gzip_stream.cc \
google/protobuf/io/printer.cc \
google/protobuf/io/strtod.cc \
google/protobuf/io/tokenizer.cc \
google/protobuf/io/zero_copy_stream_impl.cc \
google/protobuf/compiler/importer.cc \
google/protobuf/compiler/parser.cc \
google/protobuf/util/delimited_message_util.cc \
google/protobuf/util/field_comparator.cc \
google/protobuf/util/field_mask_util.cc \
google/protobuf/util/internal/constants.h \
google/protobuf/util/internal/datapiece.cc \
google/protobuf/util/internal/datapiece.h \
google/protobuf/util/internal/default_value_objectwriter.cc \
google/protobuf/util/internal/default_value_objectwriter.h \
google/protobuf/util/internal/error_listener.cc \
google/protobuf/util/internal/error_listener.h \
google/protobuf/util/internal/expecting_objectwriter.h \
google/protobuf/util/internal/field_mask_utility.cc \
google/protobuf/util/internal/field_mask_utility.h \
google/protobuf/util/internal/json_escaping.cc \
google/protobuf/util/internal/json_escaping.h \
google/protobuf/util/internal/json_objectwriter.cc \
google/protobuf/util/internal/json_objectwriter.h \
google/protobuf/util/internal/json_stream_parser.cc \
google/protobuf/util/internal/json_stream_parser.h \
google/protobuf/util/internal/location_tracker.h \
google/protobuf/util/internal/mock_error_listener.h \
google/protobuf/util/internal/object_location_tracker.h \
google/protobuf/util/internal/object_source.h \
google/protobuf/util/internal/object_writer.cc \
google/protobuf/util/internal/object_writer.h \
google/protobuf/util/internal/protostream_objectsource.cc \
google/protobuf/util/internal/protostream_objectsource.h \
google/protobuf/util/internal/protostream_objectwriter.cc \
google/protobuf/util/internal/protostream_objectwriter.h \
google/protobuf/util/internal/proto_writer.cc \
google/protobuf/util/internal/proto_writer.h \
google/protobuf/util/internal/structured_objectwriter.h \
google/protobuf/util/internal/type_info.cc \
google/protobuf/util/internal/type_info.h \
google/protobuf/util/internal/type_info_test_helper.cc \
google/protobuf/util/internal/type_info_test_helper.h \
google/protobuf/util/internal/utility.cc \
google/protobuf/util/internal/utility.h \
google/protobuf/util/json_util.cc \
google/protobuf/util/message_differencer.cc \
google/protobuf/util/time_util.cc \
google/protobuf/util/type_resolver_util.cc
include $(BUILD_SHARED_LIBRARY)
LOCAL_SRC_FILES需要填入参与编译的所有源码文件路径,不同版本源码不同配置不同,可以查看protobuf/src/Makefile.am文件,选择对应的源码
在jni目录,使用以下命令开始编译,这个命令是你ndk的目录,里面有个ndk-build命令,需要替换成自已的ndk目录
$ /Users/xiaolin/Library/Android/sdk/ndk/24.0.8215888/ndk-build
错误
No suitable threading library available
/Users/xiaolin/qtt/code/android/ndkbuild/app/src/main/jni/google/protobuf/stubs/common.cc:52:2: error: "No suitable threading library available."
#error "No suitable threading library available."
解决:在源码/google/stubs/common.h里添加如下代码,github有相关问题记录 Issues
#ifndef HAVE_PTHREAD
#define HAVE_PTHREAD 1
#endif
error: undefined symbol: __android_log_write
ld: error: undefined symbol: __android_log_write
>>> referenced by common.cc:142 (google/protobuf/stubs/common.cc:142)
>>> /Users/xiaolin/qtt/code/android/ndkbuild/app/src/main/obj/local/arm64-v8a/objs/proto/google/protobuf/stubs/common.o:(google::protobuf::internal::DefaultLogHandler(google::protobuf::LogLevel, char const*, int, std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&))
>>> referenced by common.cc:150 (google/protobuf/stubs/common.cc:150)
>>> /Users/xiaolin/qtt/code/android/ndkbuild/app/src/main/obj/local/arm64-v8a/objs/proto/google/protobuf/stubs/common.o:(google::protobuf::internal::DefaultLogHandler(google::protobuf::LogLevel, char const*, int, std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&))
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
解决:全局搜索__android_log_write,把用到这个函数的地方注释掉,github有相关问题记录 Issues