Linux 下使用 NDK 编译 protobuf 2.6.1
1. Android.mk 文件相关基础
Android 工程中,src 子目录存放 Android 工程的 java 代码, jni 子目录存放 Android 工程的 C/C++ 代码。
将文件夹 protobuf-2.6.1 拷贝到 jni 目录下,编写模块编译脚本 jni/Android.mk 内容如下:
LOCAL_PATH := $(call my-dir)################## Build ProtoBuf ################include $(CLEAR_VARS)LOCAL_ARM_MODE := armLOCAL_CPPFLAGS += -frtti#LOCAL_MODULE_CLASS 为编译后的文件保存位置,SHARED_LIBRARIES 为 /system/libLOCAL_MODULE_CLASS := SHARED_LIBRARIES LOCAL_MODULE := libProtobufLOCAL_MODULE_TAGS := optionalLOCAL_CPP_EXTENSION := .ccLOCAL_SRC_FILES := \protobuf-2.6.1/src/google/protobuf/io/coded_stream.cc \protobuf-2.6.1/src/google/protobuf/stubs/common.cc \protobuf-2.6.1/src/google/protobuf/descriptor.cc \protobuf-2.6.1/src/google/protobuf/descriptor.pb.cc \protobuf-2.6.1/src/google/protobuf/descriptor_database.cc \protobuf-2.6.1/src/google/protobuf/dynamic_message.cc \protobuf-2.6.1/src/google/protobuf/extension_set.cc \protobuf-2.6.1/src/google/protobuf/extension_set_heavy.cc \protobuf-2.6.1/src/google/protobuf/generated_message_reflection.cc \protobuf-2.6.1/src/google/protobuf/generated_message_util.cc \protobuf-2.6.1/src/google/protobuf/io/gzip_stream.cc \protobuf-2.6.1/src/google/protobuf/compiler/importer.cc \protobuf-2.6.1/src/google/protobuf/message.cc \protobuf-2.6.1/src/google/protobuf/message_lite.cc \protobuf-2.6.1/src/google/protobuf/stubs/once.cc \protobuf-2.6.1/src/google/protobuf/compiler/parser.cc \protobuf-2.6.1/src/google/protobuf/io/printer.cc \protobuf-2.6.1/src/google/protobuf/reflection_ops.cc \protobuf-2.6.1/src/google/protobuf/repeated_field.cc \protobuf-2.6.1/src/google/protobuf/service.cc \protobuf-2.6.1/src/google/protobuf/stubs/stringprintf.cc \protobuf-2.6.1/src/google/protobuf/io/strtod.cc \protobuf-2.6.1/src/google/protobuf/stubs/structurally_valid.cc \protobuf-2.6.1/src/google/protobuf/stubs/strutil.cc \protobuf-2.6.1/src/google/protobuf/stubs/substitute.cc \protobuf-2.6.1/src/google/protobuf/text_format.cc \protobuf-2.6.1/src/google/protobuf/io/tokenizer.cc \protobuf-2.6.1/src/google/protobuf/unknown_field_set.cc \protobuf-2.6.1/src/google/protobuf/wire_format.cc \protobuf-2.6.1/src/google/protobuf/wire_format_lite.cc \protobuf-2.6.1/src/google/protobuf/io/zero_copy_stream.cc \protobuf-2.6.1/src/google/protobuf/io/zero_copy_stream_impl.cc \protobuf-2.6.1/src/google/protobuf/io/zero_copy_stream_impl_lite.cc \LOCAL_C_INCLUDES += . \$(LOCAL_PATH)/protobuf-2.6.1/src \$(LOCAL_PATH)/protobuf-2.6.1 \$(LOCAL_PATH)/protobuf-2.6.1/vsprojects \LOCAL_LDLIBS := -llog -pthread LOCAL_STATIC_LIBRARIES := -lgcc /home/conner/android-ndk-r9/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi/libsupc++.a \ifndef NDK_ROOTinclude external/stlport/libstlport.mkendifinclude $(BUILD_SHARED_LIBRARY)
以上内容解释如下:
LOCAL_PATH := $(call my-dir)
每个Android.mk文件都必须在开头定义 LOCAL_PATH 变量。这个变量被用来寻找C/C++源文件。在该例中,my-dir 是一个由编译系统提供的宏函数,用于返回Android.mk所在目录的路径。
include $(CLEAR_VARS)
CLEAR_VARS是编译系统预定义的一个变量,它指向一个特殊的Makefile,这个Makefile负责清除 LOCAL_xxx 的变量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES 等)但不会清除 LOCAL_PATH。之所以需要清理这些变量是因为所有的编译控制文件是在一趟make执行过程中完成的,而所有的变量都是全局的,会对其他Android.mk文件产生影响。
LOCAL_ARM_MODE := arm
默认情况下,arm目标二进制会以thumb的形式生成(16位),你可以通过设置这个变量为arm如果你希望你的module是以32位指令的形式。 'arm' (32-bit instructions) mode. E.g.: LOCAL_ARM_MODE := arm
注意你同样可以在编译的时候告诉系统编译特定的类型,比如 LOCAL_SRC_FILES := foo.c bar.c.arm
这样就告诉系统总是将bar.c以arm的模式编译
LOCAL_MODULE := hello-jni
LOCAL_MODULE 用来给每个模块定义一个名字,不同模块的名字不能相同,不能有空格。这里的名字会传给NDK编译系统,然后加上lib前缀和.so后缀 (例如,变成libhello-jni.so)。注意,如果你在LOCAL_MODULE定义中自己加上了lib前缀,则ndk在处理的时候就不会再加上lib前缀了(为了兼容Android系统的一些源码)。
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_TAGS 后的参数有 user eng tests optional debug。eng: 指该模块只在eng版本下才编译(makePRODUCT-XXX-eng,); tests: 指该模块只在tests版本下才编译并且生成(makePRODUCT-XXX-tests,不会生成image和system/app/,在data/app/下生成包含LOCAL_MODULE_TAGS :=tests的apk,不会受the product definition files的影响,不会编译非tag=tests的模块);debug: 指该模块只在userdebug版本下才编译(makePRODUCT-XXX-userdebug);optional:指该模块在所有版本下都编译(经过测试optional在tests版本下不编译,其他的版本都会编译,如果该模块the product definition files则会打包成apk)。
LOCAL_SRC_FILES := ...
在LOCAL_SRC_FILES 变量里面列举出对应于同一个模块的、要编译的那些文件,这里不要把头文件加进来,编译系统可以自动检测头文件依赖关系。默认情况下,C++源码文件的扩展名应该是cpp,如果想修改的话,将变量LOCAL_CPP_EXTENSION修改为你想要的扩展名,注意句点。例如:LOCAL_CPP_EXTENSION := .cxx
include $(BUILD_SHARED_LIBRARY)
这个 BUILD_SHARED_LIBRARY也是预定义的变量,也是指向一个Makefile,负责将你在 LOCAL_XXX 等变量中定义信息收集起来,确定要编译的文件、如何编译。如果要编译的是静态库而不是动态库,则可以用 BUILD_STATIC_LIBRARY。
LOCAL_LDLIBS := -llog -pthread
LOCAL_LDLIBS 表示要链接的动态库,LOCAL_STATIC_LIBRARIES 表示要链接的静态库LOCAL_C_INCLUDES += . $(LOCAL_PATH)/protobuf-2.6.1/vsprojects
是因为代码中用到此目录下的 config.h 文件,也可以直接把 config.h 文件拷贝到 src 目录下,就可以不用包含这个路径,此路径下的 config.h 是VS工程用的,所以需要修改:
/* protobuf config.h for MSVC. On other platforms, this is generated * automatically by autoheader / autoconf / configure. *//* the location of <hash_map> *///#define HASH_MAP_H <hash_map>/* the namespace of hash_map/hash_set */// Apparently Microsoft decided to move hash_map *back* to the std namespace// in MSVC 2010:// http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx// TODO(kenton): Use unordered_map instead, which is available in MSVC 2010.#if _MSC_VER < 1310 || _MSC_VER >= 1600#define HASH_NAMESPACE std#else#ifdef _WIN32#define HASH_NAMESPACE stdext#else #define HASH_SET_H <ext/hash_set>#define HASH_MAP_H <ext/hash_map>#define HASH_NAMESPACE __gun_cxx#endif#endif/* the location of <hash_set> *//* define if the compiler has hash_map *///#define HAVE_HASH_MAP 1/* define if the compiler has hash_set *///#define HAVE_HASH_SET 1/* define if you want to use zlib. See readme.txt for additional * requirements. */// #define HAVE_ZLIB 1#define HAVE_PTHREAD
2. jni 目录下还需要 Application.mk 文件,内容如下:
APP_PLATFORM := android-18#APP_STL := stlport_static APP_STL := gnustl_static
3.工程目录下执行 ndk-build 命令,进行编译
参考:
http://blog.csdn.net/smfwuxiao/article/details/8530742
更多相关文章
- MTK Android(安卓)6.0 上新增KeyCode
- 在Android中自动实现横竖屏切换的问题
- Android:Debug certificate expired on DATE 解决方法
- android工具链与GNU工具链的比较
- Android文件访问权限问题
- ant 一键打包
- android Immutable bitmap passed to Canvas constructor异常
- Android(安卓)studio 下的svn配置使用
- NPM 和webpack 的基础使用