android ndkbuild build BUILD_EXECUTABLE 为什么是这个application/x-sharedlib

下次自动登录
现在的位置:
& 综合 & 正文
android NDK编译(导入).a文件和编译多个so文件
一、编译一个静态库 libstatic_android.a
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)LOCAL_MODULE
:= static_android
LOCAL_SRC_FILES := libstatic_android.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE
:= fpdfembedsdk
LOCAL_SRC_FILES := xxxx.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../include/
LOCAL_LDLIBS := -llog -g -L. -ljnigraphics
#fill in the foxit library here
#LOCAL_LDLIBS += libstatic_android.aLOCAL_STATIC_LIBRARIES := static_android
include $(BUILD_SHARED_LIBRARY) #$(BUILD_STATIC_LIBRARY)
二、编译多个so文件
(1)Android.mk文件首先需要指定LOCAL_PATH变量,用于查找源文件。由于一般情况下Android.mk和需要编译的源文件在同一目录下,所以定义成如下形式:
LOCAL_PATH:=$(call my-dir)
上面的语句的意思是将LOCAL_PATH变量定义成本文件所在目录路径。(2)Android.mk中可以定义多个编译模块,每个编译模块都是以include $(CLEAR_VARS)开始,以include $(BUILD_XXX)结束。
include $(CLEAR_VARS)
CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE为你清除除LOCAL_PATH以外的所有LOCAL_XXX变量,
如LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_SHARED_LIBRARIES,LOCAL_STATIC_LIBRARIES等。
include $(BUILD_STATIC_LIBRARY)表示编译成静态库
include $(BUILD_SHARED_LIBRARY)表示编译成动态库。
include $(BUILD_EXECUTABLE)表示编译成可执行
(3)举例如下(frameworks/base/libs/audioflinger/Android.mk):
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
ifeq ($(AUDIO_POLICY_TEST),true)
ENABLE_AUDIO_DUMP := true
LOCAL_SRC_FILES:= \
AudioHardwareGeneric.cpp \
AudioHardwareStub.cpp \
AudioHardwareInterface.cpp
ifeq ($(ENABLE_AUDIO_DUMP),true)
LOCAL_SRC_FILES += AudioDumpInterface.cpp
LOCAL_CFLAGS += -DENABLE_AUDIO_DUMP
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder \
libmedia \
libhardware_legacy
ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
LOCAL_CFLAGS += -DGENERIC_AUDIO
LOCAL_MODULE:= libaudiointerface
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
LOCAL_SRC_FILES += A2dpAudioInterface.cpp
LOCAL_SHARED_LIBRARIES += liba2dp
LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
LOCAL_C_INCLUDES += $(call include-path-for, bluez)
include $(BUILD_STATIC_LIBRARY)
模块一编译成静态库
include $(CLEAR_VARS)
LOCAL_SRC_FILES:=
AudioPolicyManagerBase.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_LDLIBS += -ldl
LOCAL_SHARED_LIBRARIES += libdl
LOCAL_MODULE:= libaudiopolicybase
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
LOCAL_CFLAGS += -DWITH_A2DP
ifeq ($(AUDIO_POLICY_TEST),true)
LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
include $(BUILD_STATIC_LIBRARY) 模块二编译成静态库
include $(CLEAR_VARS) 模块三
LOCAL_SRC_FILES:=
AudioFlinger.cpp
AudioMixer.cpp.arm
AudioResampler.cpp.arm
AudioResamplerSinc.cpp.arm
AudioResamplerCubic.cpp.arm \
AudioPolicyService.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder \
libmedia \
libhardware_legacy
ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
LOCAL_STATIC_LIBRARIES += libaudiointerface libaudiopolicybase
LOCAL_CFLAGS += -DGENERIC_AUDIO
LOCAL_SHARED_LIBRARIES += libaudio libaudiopolicy
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_LDLIBS += -ldl
LOCAL_SHARED_LIBRARIES += libdl
LOCAL_MODULE:= libaudioflinger
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
LOCAL_SHARED_LIBRARIES += liba2dp
ifeq ($(AUDIO_POLICY_TEST),true)
LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
ifeq ($(TARGET_SIMULATOR),true)
ifeq ($(HOST_OS),linux)
LOCAL_LDLIBS += -lrt -lpthread
ifeq ($(BOARD_USE_LVMX),true)
LOCAL_CFLAGS += -DLVMX
LOCAL_C_INCLUDES += vendor/nxp
LOCAL_STATIC_LIBRARIES += liblifevibes
LOCAL_SHARED_LIBRARIES += liblvmxservice
LOCAL_SHARED_LIBRARIES += liblvmxipc
include $(BUILD_SHARED_LIBRARY) 模块三编译成动态库
(4)编译一个应用程序(APK)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Build all java files in the java subdirectory--&直译(建立在java子目录中的所有Java文件)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Name of the APK to build--&直译(创建APK的名称)
LOCAL_PACKAGE_NAME := LocalPackage
# Tell it to build an APK--&直译(告诉它来建立一个APK)
include $(BUILD_PACKAGE)
(5)编译一个依赖于静态Java库(static.jar)的应用程序
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# List of static libraries to include in the package
LOCAL_STATIC_JAVA_LIBRARIES := static-library
# Build all java files in the java subdirectory
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Name of the APK to build
LOCAL_PACKAGE_NAME := LocalPackage
# Tell it to build an APK
include $(BUILD_PACKAGE)
(6)编译一个需要用平台的key签名的应用程序
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Build all java files in the java subdirectory
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Name of the APK to build
LOCAL_PACKAGE_NAME := LocalPackage
LOCAL_CERTIFICATE := platform
# Tell it to build an APK
include $(BUILD_PACKAGE)
(7)编译一个需要用特定key前面的应用程序
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Build all java files in the java subdirectory
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Name of the APK to build
LOCAL_PACKAGE_NAME := LocalPackage
LOCAL_CERTIFICATE := vendor/example/certs/app
# Tell it to build an APK
include $(BUILD_PACKAGE)
(8)添加一个预编译应用程序
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Module name should match apk name to be installed.
LOCAL_MODULE := LocalModuleName
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
include $(BUILD_PREBUILT)
(9)添加一个静态JAVA库
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Build all java files in the java subdirectory
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Any libraries that this library depends on
LOCAL_JAVA_LIBRARIES := android.test.runner
# The name of the jar file to create
LOCAL_MODULE := sample
# Build a static jar file.
include $(BUILD_STATIC_JAVA_LIBRARY)
(10)Android.mk的编译模块中间可以定义相关的编译内容,也就是指定相关的变量如下:
LOCAL_AAPT_FLAGS
LOCAL_ACP_UNAVAILABLE
LOCAL_ADDITIONAL_JAVA_DIR
LOCAL_AIDL_INCLUDES
LOCAL_ALLOW_UNDEFINED_SYMBOLS
LOCAL_ARM_MODE
LOCAL_ASFLAGS
LOCAL_ASSET_DIR
LOCAL_ASSET_FILES 在Android.mk文件中编译应用程序(BUILD_PACKAGE)时设置此变量,表示资源文件,
通常会定义成LOCAL_ASSET_FILES += $(call find-subdir-assets)
LOCAL_BUILT_MODULE_STEM
LOCAL_C_INCLUDES 额外的C/编译头文件路径,用LOCAL_PATH表示本文件所在目录
举例如下:
LOCAL_C_INCLUDES += extlibs/zlib-1.2.3
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
LOCAL_CC 指定C编译器
LOCAL_CERTIFICATE
LOCAL_CFLAGS 为C/C++编译器定义额外的标志(如宏定义),举例:LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1
LOCAL_CLASSPATH
LOCAL_COMPRESS_MODULE_SYMBOLS
LOCAL_COPY_HEADERS install应用程序时需要复制的头文件,必须同时定义LOCAL_COPY_HEADERS_TO
LOCAL_COPY_HEADERS_TO install应用程序时复制头文件的目的路径
LOCAL_CPP_EXTENSION 如果你的C++文件不是以cpp为文件后缀,你可以通过LOCAL_CPP_EXTENSION指定C++文件后缀名
如:LOCAL_CPP_EXTENSION := .cc
注意统一模块中C++文件后缀必须保持一致。
LOCAL_CPPFLAGS 传递额外的标志给C++编译器,如:LOCAL_CPPFLAGS += -ffriend-injection
LOCAL_CXX 指定C++编译器
LOCAL_DX_FLAGS
LOCAL_EXPORT_PACKAGE_RESOURCES
LOCAL_FORCE_STATIC_EXECUTABLE 如果编译的可执行程序要进行静态链接(执行时不依赖于任何动态库),则设置LOCAL_FORCE_STATIC_EXECUTABLE:=true
目前只有libc有静态库形式,这个只有文件系统中/sbin目录下的应用程序会用到,这个目录下的应用程序在运行时通常
文件系统的其它部分还没有加载,所以必须进行静态链接。
LOCAL_GENERATED_SOURCES
LOCAL_INSTRUMENTATION_FOR
LOCAL_INSTRUMENTATION_FOR_PACKAGE_NAME
LOCAL_INTERMEDIATE_SOURCES
LOCAL_INTERMEDIATE_TARGETS
LOCAL_IS_HOST_MODULE
LOCAL_JAR_MANIFEST
LOCAL_JARJAR_RULES
LOCAL_JAVA_LIBRARIES 编译java应用程序和库的时候指定包含的java类库,目前有core和framework两种
多数情况下定义成:LOCAL_JAVA_LIBRARIES := core framework
注意LOCAL_JAVA_LIBRARIES不是必须的,而且编译APK时不允许定义(系统会自动添加)
LOCAL_JAVA_RESOURCE_DIRS
LOCAL_JAVA_RESOURCE_FILES
LOCAL_JNI_SHARED_LIBRARIES
LOCAL_LDFLAGS 传递额外的参数给连接器(务必注意参数的顺序)
LOCAL_LDLIBS 为可执行程序或者库的编译指定额外的库,指定库以"-lxxx"格式,举例:
LOCAL_LDLIBS += -lcurses -lpthread
LOCAL_LDLIBS += -Wl,-z,origin
LOCAL_MODULE 生成的模块的名称(注意应用程序名称用LOCAL_PACKAGE_NAME而不是LOCAL_MODULE)
LOCAL_MODULE_PATH 生成模块的路径
LOCAL_MODULE_STEM
LOCAL_MODULE_TAGS 生成模块的标记
LOCAL_NO_DEFAULT_COMPILER_FLAGS
LOCAL_NO_EMMA_COMPILE
LOCAL_NO_EMMA_INSTRUMENT
LOCAL_NO_STANDARD_LIBRARIES
LOCAL_OVERRIDES_PACKAGES
LOCAL_PACKAGE_NAME APK应用程序的名称
LOCAL_POST_PROCESS_COMMAND
LOCAL_PREBUILT_EXECUTABLES 预编译including $(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)时所用,指定需要复制的可执行文件
LOCAL_PREBUILT_JAVA_LIBRARIES
LOCAL_PREBUILT_LIBS 预编译including $(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)时所用, 指定需要复制的库.
LOCAL_PREBUILT_OBJ_FILES
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES
LOCAL_PRELINK_MODULE 是否需要预连接处理(默认需要,用来做动态库优化)
LOCAL_REQUIRED_MODULES 指定模块运行所依赖的模块(模块安装时将会同步安装它所依赖的模块)
LOCAL_RESOURCE_DIR
LOCAL_SDK_VERSION
LOCAL_SHARED_LIBRARIES 可链接动态库
LOCAL_SRC_FILES 编译源文件
LOCAL_STATIC_JAVA_LIBRARIES
LOCAL_STATIC_LIBRARIES 可链接静态库
LOCAL_UNINSTALLABLE_MODULE
LOCAL_UNSTRIPPED_PATH
LOCAL_WHOLE_STATIC_LIBRARIES 指定模块所需要载入的完整静态库(这些精通库在链接是不允许链接器删除其中无用的)
LOCAL_YACCFLAGS
OVERRIDE_BUILT_MODULE_PATH
&&&&推荐文章:
【上篇】【下篇】4104人阅读
ndk版本:android-ndk-r8d,基于ndk自带samples中的test-libstdc++工程进行修改。
1. 例子工程目录结构:
test-libstdc++ / jni / Android.mk
test-libstdc++ / jni / Application.mk
test-libstdc++ / jni / test-libstdc++.cpp
2. Android.mk文件:
#&A&simple&test&for&the&minimal&standard&C++&library
&&# &&LOCAL_PATH&:=&$(call&my-dir)&&&&include&$(CLEAR_VARS)&&LOCAL_MODULE&:=&test-libstl&&LOCAL_SRC_FILES&:=&test-libstl.cpp&&LOCAL_LDLIBS&&&&:=&-llog&&&&include&$(BUILD_EXECUTABLE)&&&&include&$(CLEAR_VARS)&&LOCAL_EXECUTABLE&:=&test-libstl&&
# A simple test for the minimal standard C++ library
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := test-libstl
LOCAL_SRC_FILES := test-libstl.cpp
LOCAL_LDLIBS
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_EXECUTABLE := test-libstl
3. Application.mk内容:
APP_STL&:=&stlport_static&&
APP_STL := stlport_static
4. test-libstdc++.cpp内容:
#include&&iostream& &&#include&&string& &&#include&&vector&
&&using&namespace&&&&&int&main()&{&&&&&&vector&string&&&&&&&&for&(int&i=0;&i&5;&i++)&&&&&&&{&&&&&&&&&&contents.push_back(string(&vector&));&&&&&&}&&&&&&&&&&&&for&(int&i=0;&i&5;&i++)&&&&&&&{&&&&&&&&&&cout&&&&contents[i]&&&&&&&&&&}&&&&&&&&&&&&cout&&&&&hello,&world\n&;&&&&&&return&0;&&}&&
#include &iostream&
#include &string&
#include &vector&
int main() {
vector&string&
for (int i=0; i&5; i++)
contents.push_back(string(&vector&));
for (int i=0; i&5; i++)
cout && contents[i] &&
cout && &hello, world\n&;
5. 最后在test-libstdc++\libs\armeabi目录下面生成test-libstl 可执行程序。原理类似tcpdump工具使用,通过adb推到手机上,在shell模式下运行改可执行程序:
D:\android-sdk-windows\platform-tools&adb&push&test-libstl&/data/local/&&1341&KB/s&(251396&bytes&in&0.182s)&&&&D:\android-sdk-windows\platform-tools&adb&shell&chmod&755&/data/local/test-libstl&&&&D:\android-sdk-windows\platform-tools&adb&shell&/data/local/test-libstl&&vector&&vector&&vector&&vector&&vector&&hello,&world&&
D:\android-sdk-windows\platform-tools&adb push test-libstl /data/local/
1341 KB/s (251396 bytes in 0.182s)
D:\android-sdk-windows\platform-tools&adb shell chmod 755 /data/local/test-libstl
D:\android-sdk-windows\platform-tools&adb shell /data/local/test-libstl
hello, world
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:673144次
积分:6535
积分:6535
排名:第3331名
原创:22篇
转载:325篇
评论:46条
(1)(4)(6)(1)(3)(5)(3)(11)(9)(8)(30)(40)(17)(6)(5)(16)(11)(3)(5)(5)(17)(30)(29)(22)(16)(21)(13)(15)(1)(1)(1)阅读前准备
这是一篇相对入门的文章。文中会涉及到少许NDK的知识,但个人认为对初学者来说都相对比较实用,因为都是在平时项目中遇到的(目前自己也是初学者)。一些其他高深的技术不再本文探讨范围之内(因为我不懂)。文章中可能会存在一些啰里八嗦的地方,抱歉,目前的行文风格如此,考虑以后变得牛逼点儿再改改文风,毕竟现在的阶段还是自嘲的情感因素占上风。
你要知道什么是NDK,我是用cocos2dx的,所以平日里还算经常有接触,如果不知道,那就skip这篇文章吧,否则你也看不懂,要不就自己google去。这里只会展开和Android相关的部分,iOS点到为止,详细不讨论。
我使用NDK的目的
cocos2dx之所以能跨平台,是因为那些被支持的设备的OS都能用某种方式运行C/C++生成的程序(或者库)。本身Android运行的cocos2dx的程序就是通过编译好一个大的动态库让Java加载实现程序启动的。一般情况下,cocos2dx的项目已经帮你屏蔽这些设置等的麻烦事情,至多增加一个你自己添加的源文件到mk文件中罢了,所以平时其实去接触这个的机会也不算太多,但是往往只要一有这种知识的涉及,就直接抓瞎了(这也是所谓框架带来的问题,虽然能让人从繁重的底层处理中解放出来,但是不知甚解往往遇到一些略微涉及到这些方面的问题就直接被拍死了,扯远了)。
特别是在接入其他平台SDK的时候尤为明显,好多三方的库都是带*.so文件的,这和平时用的代码隔了至少两层(cocos2dx的C++,Android的Java,Android的底层操作系统),因为*.so文件明显是给Android的OS去调用的,JAVA在这里知道个毛线。
就算不管三方的SDK接入,有很多情况还是会遇到一些棘手的问题。比如,你需要管理并使用socket,有好多解决方案, 比如在应用的C++层采用统一的接口,然后各自平台各自实现,Android的么就通过JNI去和JAVA交互,反正java的三方库是大而全的,基本找什么都有;iOS么也不差,类库也相当全(其他平台暂时省略,没弄过)。但是在cocos2dx中,首先要考虑的,我觉得是跨平台问题,如果各自平台各自实现,那就不要用cocos2dx了,直接按平台分几个项目组各自写就是了,难说执行效率还高好几个档次,但是开发成本就不好讲了。项目中,这个例子中我最终考虑使用的是libevent库,在Android和iOS上只要简单把对应的库编译出来就可以了,从调用到封装也都是C++的,和cocos2dx无缝连接,平滑过渡,个人感觉棒棒的。Android下面编译出动态库(也可以使用静态库)就靠NDK了,当然iOS上也有NDK的概念,反正说穿了,也就是个交叉编译的环境,XCode里面也带全了iOS对应的各种平台的交叉编译环境,原理是一样的,基于MAC是基于FreeBSD的前提,他们的编译过程其实也很类似(至少对我来讲),都是写个makefile文件,用各自平台对应的gcc折腾一下。
其实这次写这篇文章的起意是因为sqlite库的使用,下面文章中也会以这个做例子来阐述如何单独编译个动态库出来。
适用本篇文章的环境以及程序版本
操作系统:WIN7 (32bit/64/bit)(XP这种应该也问题不大)
NDK版本:r8、r9 ... (r8以下的么用过,不清楚)
cygwin:NULL(独立编译暂时用不到,虽然NDK的INSTALL文档里面说WINDOWS下还是需要装cygwin)
平时项目中NDK的使用
我自己项目中第一次去看和用NDK是iconv库。Android和iOS的程序都能很好得支持UTF8编码,但是因为我是用win32做测试,并且用VS2010作为开发工具的,平时的测试也都是VS调的,但是它对UTF8编码的支持很不友好,这点应该做cocos2dx的人都折腾过,开始翻来覆去想解决这个问题,后来找到篇文章说是编译器的缘故,并且MSDN上回复的意思是编译器小组也不准备就此问题来做适应修改(尼玛,心中千万只草泥马在奔腾),要么索性用UNICODE。UNICODE说实话之前被坑过几次,也没搞太明白,因为项目时间的缘故(尼玛,在开发时间和产品质量中找平衡是永远的痛)还是用自己熟悉的本地编码吧,反正目前没有国际化的预期,且碰到的问题都能解决。不过在字符串转换上还是要费点周章的,于是就用到了iconv库。这个在win32、android、iOS上都有对应的库(好嘛,就你了)。
在使用上(这里只记录下流水帐,详细不展开),其实也是照样画葫芦。首先把iconv源代码下过来,放cocos2dx源代码根目录下(这个是为了让NDK_MODULE_PATH中能找到iconv模块,这部分可以参考之前的一篇文章:),然后编写好iconv库的Android.mk文件(也就是编译所需要用到源代码和模块名称神马的,还有就是编译出来的是静态库还是动态库),打开项目的jni/Android.mk文件,添加上对应的库依赖即可。当你整个项目编译的时候就会看到iconv的源文件也一起编译了(不知道哪里看?尼玛,感觉不会再爱了&&)。
libevent库
这个是用到的第二个三方库,其载入的方法和iconv库一样,不再赘述,官方都有源码下载。或者翻这篇文章:,不过里面有些概念当时没理解,比如即使在ubuntu下交叉编译,用的也是NDK,不存在说使用ubuntu版本的gcc编译的情况(莫非这就是之前编译出来不能用的缘故?应该不会,呵呵)。
带着项目编译的麻烦之处
之前用到的iconv和libevent的库都是采用静态库的方式(前面没说明,反正也不是重点,因为用动态库的方式也一样),并且是带着项目一起编译的。如果来个新项目,这些代码还是会重新被编译,因为这几个库的Android.mk是在cocos2dx项目中的jni/Android.mk中被加载的。如果库小,还能忍受,因为编译一次的代价也不算太大,稍微等等就行了,但是如果是以下的情况,估计大家就会喝咖啡喝到吐为止:
库本身就比较大,一次编译需要的时间比较长
随着新功能增加和开发的持续,会加入各种三方库,本身库的数量会变多
你要编译不同CPU架构对应的库(这个真是太苦逼了)
并且,修改了Application.mk后势必会重新编译,那个苦啊(连同2dx的源文件一起重编啊,尼玛坑爹啊)。本身,程序在发布的时候,会移除Application.mk中的一些宏定义,比如 -DCOCOS_DEBUG=1。如果,我是说如果,以上三个条件都被无情得满足了,那么,一旦编译启动的时候,你就可以打个电话约上两三好友,跑到市中心的星巴克,点上几杯卡布其诺(做得不好看让他们重做,味道不对也让他们重做,以上动作可以重复N次),然后装逼一个下午,顺带可以和好友吐槽下这坑爹的交叉编译耗时冗长令人发指。聊得累了,也差不多可以告别这悠长的下午茶时间,跟着节奏慢悠悠回到电脑前,一看,尼玛,还在编译mips的版本。当然,后面的各渠道打包又是一条漫长的不归路。这时候我只想说两个字:『呵呵』。
回到正题,其实这方面的的问题,cocos2dx里面已经有很好的方法去避免了(其实也不算是cocos2dx去避免,而是gcc),那就是prebuilt。在cocos2dx\platform\third_party\android\prebuilt目录下,有好多预编译好的库,如libcurl,libpng等等。这些库是不会重新编译的(你也编译不了,只有头文件,除非你吃饱了去自己整源代码弄一份),可以参考项目的jni/Android.mk中对于这些库的加载,然后自己写一个。正好,昨天在做一个消息中心的东西,因为要保存用户的离线消息,所以,再三考虑,还是使用sqlite来作为『存储介质』。下面就来讲下生成sqlite的预编译版。
用NDK编译独立的库文件
从这里开始,建议对NDK不太了解的人去看下NDK解压后根目录下的README.txt,里面讲了你大致需要至少的知识,以及如果不知道要去看哪个文档。
硬盘里面要有NDK,版本建议r8以上(包含r8),并且把NDK的目录加到环境变量中去,使得shell能在任意目录访问到NDK目录下的ndk-build(或者ndk-build.cmd)文件。
Sqlite库的使用
cocos2dx源码中有sqlite的库,但是很奇怪的是只有win32的版本,虽然Android和iOS的系统中都自带sqlite库,但是如果我们程序中要用到的话,要么通过转接层(如JNI)去调用系统原生的方法去操作,要么自己挂一个sqlite库上去。前一种方法作为C/C++程序员来说显然很不愿意,虽然我对JAVA也不排斥,但是这么调来调去的,自己很容易搞晕,并且两边都有对应的代码,代码耦合度明显上升个数量级,关键尼玛Android和iOS还要各自实现一份,即使各自的实现不麻烦,但只要想到要这么做我就觉得好麻烦,囧rz。所以我毫不犹豫选择挂库的方式。
当然,我对cocos2dx不带Android和iOS的sqlite库的方式也有点想法,不知道是不是本来就不用实现呢?于是我把真机上system/lib目录下的libsqlite.so文件拿出来,然后加载到项目中去,竟然也可以用,呵呵,无语。不过link的时候,报了一堆的warning,估计是Android系统带的sqlite库是有其他库依赖,这些库明显在Android系统中。iOS的没试过,估计也差不多。每次编译都要看那一堆warning,好蛋痛,并且我发现最终我的方法还是会让这个libsqlite.so装到apk中(尼玛不是系统自带么),那还不如我自己编译一个放上去安全,还不用考虑版本兼容性的问题。
Sqlite库的编译
首先要去下载sqlite的源代码,我下载到的版本是3.8.0.2(),释放到任意目录,我是把它翻到NDK的samples里面了,反正编译一下还是要把那几个库文件拿出来放到cocos2dx的prebuilt目录下的。
建立一个文件夹叫sqlite3(呃,我还是带上大版本,以便于日后区分,目前看来是有点多此一举),然后建立jni文件夹,放上压缩包中的sqlite3.c和两个头文件(头文件目前可有可无),shell那个没用,不需要。然后在目录下建立两个mk文件,Android.mk和Application.mk。写完后,在win7下,可以在sqlite3目录下按住shift点右键,菜单中选择『从此处打开命令窗口(W)』,然后输入 ndk-build 来对项目进行编译。
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_MODULE := sqlite3
LOCAL_SRC_FILES := sqlite3.c
include $(BUILD_SHARED_LIBRARY)
这个文件表明要生成一个libsqlite3.so的动态库,模块名称叫做sqlite3。如果要编译的是静态库的版本,则把后面的$(BUILD_SHARED_LIBRARY)修改为$(BUILD_STATIC_LIBRARY)即可。
Application.mk
APP_OPTIM := release
APP_ABI = all
Application.mk的内容比较简单,首先表明是release版本(加不加对编译没有影响,就是编译器会对执行速度进行优化),然后APP_ABI中填入的是all,表明会进行所有支持的CPU架构的版本编译,针对的就是4个,armabi、armabi-v7a、x86、MIPS这四个。
编译速度,我觉得挺慢的。
然后再写一个可以作为库加载的Android.mk,连同这几个文件都放到prebuilt的下面去:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_MODULE := sqlite3
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libsqlite3.so
include $(PREBUILT_SHARED_LIBRARY)
之后就可以把它放到项目中使用了,当然,项目中要明确加载这个模块。这里只写了动态库的mk,静态库的自己照样画葫芦写一个吧,可以参考已有的实现。具体加载方法可以参考这篇文章:,昨天试验了下貌似不需要在Java中显示loadlibrary这个sqlite库,还是各自试验下吧。
我把编译好的静态库和动态库都放在这里可以下载(意思意思,卖一个币,贪财贪财):
阅读(...) 评论()}

我要回帖

更多关于 ndkbuild不是内部命令 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信