android CDT调试和NDK脚本编写
一、CDT调试C/C++代码
1、Android工程导入
File->New->Project在弹出对话框选择android project from existing code
然后选在Next,在下面的对话框中选择工程目录:
单击Finish,即完成一个android工程添加。
2、将Android工程切换到C/C++工程
File->New->Other…在弹出对话框选中C/C++中的”convert to a C/C++ Project(Adds C/C++ Nature)”.如下图:
并在接下来的对话框中选中当前的工程,如下图:
3、设置SDK和NDK路径
Windows->preference弹出下面对话框:
在android选项卡中的SDK Location填写SDK的目录;在android选项卡中的builder的对话框中填写NDK目录
4、设置NDK编译的环境变量
在build variables设置环境变量:
将设置好的环境变量引用:
设置android-ndk编译:
通过以上操作就可以直接编译ndk代码了。
二、Android NDK 编译脚本
1、Application.mk
作用:描述了应用程序需要哪些动态库和静态库。
存放位置:文件通常放在项目目录的jni文件夹下。
变量定义:由于Application.mk说到底只是作为GNU makefile的一个片段,其中也需要定义一些变量。
(1) -APP_PROJECT_PATH
此变量应该被赋予项目的根目录地址,此项为可选项。
(2) -APP_MODULES
此项为可选项,当没有此选项时,NDK会自动编译android.mk文件中定义的所有模块及其包含的子模块。当有此选项时,必须是一个模块的列表,各个模块之间以空格为分隔符分开或者是向android.mk中罗列开来。
(3) -APP_OPTIM
此选项可以被定义为release 或debug。这个选项用于变更编译程序模块时的优化级别。默认的选项是release,此选项下会得到较高级别的优化。debug下为了便于调试不会进行过多优化。可以在AndroidManifest文件中
(4) -APP_BUILD_SCRIPT
默认条件下,NDK编译系统会到工程目录的jni文件夹下查找android.mk文件。如果你想覆盖这个行为的话就可以定义此变量此变量。如果你给定的是一个非绝对路径的话,那么这个路径总是被认为是相对于NDK顶层目录的路径。
(5) -APP_ABI
默认条件是armeabi,用户可以通过此选项进行修改,例如:为了在ARMv7上支持硬件FPU指令可以修改如下:
APP_ABI := armeabi-v7a
或者支持ARMv5TE 又支持ARMv7的设备:
APP_ABI := armeabi armeabi-v7a
(6)-APP_STL
默认条件下,NDK编译系统会使用android系统提供的轻量级C++运行时库/system/lib/libstdc++.so,NDK本身为用户提供了可选择的C++库,用户可以使用或是链接到自己的应用。例如:
APP_STL := stlport_static --> static STLport library
APP_STL := stlport_shared --> shared STLport library
APP_STL := system --> default C++ runtime library 2、Android.mk
作用:用来向编译器系统描述编译的源代码规则;该文件是GNU Makefile的一小部分,会被编译系统解析一次或多次,可以再每一个android.mk中定义一个或多个模块,也可以在几个模块中使用同一个源代码文件,每个模块属于下列类型之一:
●APK程序,一般的andorid程序,编译打包成圣的apk文件;
●JAVA库,java类库,编译打包生成jar文件;
●C/C++应用程序,可执行的C/C++应用程序;
●C/C++静态库,打包成.a文件;
●C/C++共享库,编译生成共享库,并打包成.so,有且只有共享库才能被安装复制到
你的应用软件APK包中;
(1) LOCAL_PATH
LOCAL_PATH := $(call my-dir)
一个andorid.mk文件首先必须定义好LOCAL_PATH变量,用来定义当前编译器的路径;调用my-dir后编译器会返回当前所处的目录;
(2) CLEAR_VARS
include $(CLEAR_VARS):CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE 为你清除许多LOCAL_XXX变量,除LOCAL_PATH,这是必要的,因为所有的编译控制文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的。
(3) LOCAL_MODULE
LOCAL_MODULE := aligbox:变量是必须定义的,以标识你在android.mk 文件中描述的每一个模块。名称必须是唯一的,而且不包含任何空格。注意编译
系统会自动产生合适的前缀和后缀,换句话说,一个被命名为foo的共享库模块,将会生成libfoo.so文件。
(4) LOCAL_SRC_FILES
LOCAL_SRC_FILES := $(SRC_CLASSES_PATH)/AppDelegate.cpp:此变量必须包含将要编译打包进模块中的C或者C++源代码,注意,你不用再这里列出头文件和包含的文件,因为编译系统将会自动为你找出依赖的文件,仅仅列出直接传递给编译器的源代码文件就好。
(5) LOCAL_C_INCLUDES
LOCAL_C_INCLUDES := $(CUR_LOCAL_FULL_PATH) :表示头文件的搜索路径,默认的头文件路径是LOCAL_PATH目录。
(6) TARGET_ARCH
目标 CPU平台的名字;TARGET_PLATFORM:Android.mk 解析的时候,目标Android 平台的名字;ARGET_ARCH_ABI:暂时只支持两个 value,armeabi 和armeabi-v7a。
(7)LOCAL_STATIC_LIBRARIES
表示该模块需要使用哪些静态库,以便在编译时进行链接。
(8)LOCAL_SHARED_LIBRARIES
表示模块在运行时要依赖的共享库(动态库),在链接时就需要,以便在生成文件时嵌入其相应的信息。
(9)LOCAL_LDLIBS
编译模块时要使用的附加的链接器选项。
(10)LOCAL_ARM_MODE
默认情况下, arm目标二进制会以 thumb 的形式生成(16 位),你可以通过设置这个变量为 arm如果你希望你的 module 是以 32 位指令的形式
(11)LOCAL_CFLAGS
可选的编译器选项,在编译 C 代码文件的时候使用
(12)include $(call all-subdir-makefiles)
返回一个位于当前'my-dir'路径的子目录中的所有Android.mk的列表。
(13)$(call import-add-path,$(CUR_NDK_PROJECT))
定义子模块android.mk的搜索目录;
3、Import-module注意事项与NDK_MODULE_PATH的配置
作用:导入外部模块的.mk文件,和include基本一样;区别在于include导入的是由我们自己写的.mk,而import-module导入的是外部库,模块提供的.mk。用法上include 的路径是.mk文件的绝对路径,而import是设置的路径指定到模块的.mk所在目录;是相对于NDK_MODULE_PATH中的路径列表的相对路径。
使用:$(call import-module, 相对路径)
以cocosdenshion模块的引用为例:
(1)静态模块名称、库文件名和路径
找到cocosdenshion模块的下andorid.mk的位置:
D:\cocos2d-x-2.2.2\CocosDenshion\android
其内容:
LOCAL_MODULE := cocosdenshion_static
LOCAL_MODULE_FILENAME := libcocosdenshion
……
include $(BUILD_STATIC_LIBRARY)
表示创建一个静态库libcocosdenshion,模块名称为cocosdenshion_static,那么在其他的地方需要引用此静态库就必须引用该模块。
(2)引用静态库
LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static //引用对应的静态库模块名称.
在android.mk的最后一行调用:
$(call import-module,CocosDenshion/android)
此句话意思是引用的模块搜索路径,指定这个路径下搜索应用库的android.mk文件。
注意事项:设置路径时,注意与NDK_MODULE_PATH中的路径相互匹配;导入模块的.mk中如果也有import-module,则注意其相对路径也要在NDK_MODULE_PATH中;如果import-module和include包含了同一个.mk,会报重复的错误。
(3)NDK_MODULE_PATH配置
作用:当android.mk中使用了$(call import-module, XXX)函数引入外部库文件时会用到,用以指示该往哪里去找个文件。如果NDK_MODULE_PATH没有设置或者设置不正确,编译时都是报错are you sure your NDK_MODULE_PATH variable is properly defined. NDK_MODULE_PATH是一个环境变量,不是android.mk中设置的变量,多个路径用冒号’:’,且整个字符串中间不能有空格。设置方法:
●在系统环境里手动添加这个环境变量;
●在build_native.sh中运行ndk-build之前使用export命令定义环境比昂
两NDK_MODULE_PATH,如:
export NDK_MODULE_PATH=路径1:路径2:路径3
●直接将NDK_MODULE_PATH=路径1:路径2:路径3加到ndk-build命令的参
数后面,ndk-build的参数最终会直接传递给make;如:
$NDK_ROOT_LOCAL/ndk-build -C $HELLOWORLD_ROOT NDK_MODULE_PATH=路径1:路径2
●还可以在andorid.mk中设置NDK_MODULE_PATH
在import语句之前加入:
$(call import-add-path,$(LOCAL_PATH)/platform/third_party/android/prebuilt) 备注:NDK_MODULE_PATH尽量设置在模块某个共同的根目录下。
4、实例说明
下面是cocos2dx编译的总脚本,依赖静态库“cocos_extension_static”,而静态库。
cocos_extension_static静态的编译脚本如下,在该脚本里面有嵌套其他静态库,最终再有上边脚本编译并链接成一个动态库文件。
在这两个脚本中,有一个配置文件至关重要,即:makeenv,这个文件用描述工程编译的全局环境变量,比如:开关宏,路径名,配置编译模块等。
Makeenv的内容如下:
5、NDK crash log抓取
adb logcat|ndk-stack -sym
D:\code\cocos2d-x-2.2.2\projects\android_make\obj\local\armeabi\objs 表示NDK编译的objs的目录路径。