NDK介绍

来源:互联网 发布:mysql分类后显示合计 编辑:程序博客网 时间:2024/05/19 17:09

NDK介绍

1.        简介

NDK允许开发者将本地C/C++语言编译的库文件嵌入到Android应用程序中的一系列工具。

2.        Android NDK Goals

Android VM允许开发者通过JNI来调本地语言实现的接口

3.        Android NDK Non-Goals

使用NDK编写运行于Android设备上通用本地代码并不是一种好的方式。比如,为了防止应用程序出现未响应的情况出现而捕获Android系统消息或者处理Android应用程序的生命周期时,还是得通过编写Java语言。

NDK仅仅为一组有限的本地API和库文件提供了系统头文件。因此并不是所有的Android系统库都被NDK头文件支持。

4.        NDK开发步骤

4.1.       配置NDK

以前的NSK发布版本需要运行build/host-setup.sh脚本来配置NDK环境。这一步目前已经在NDK r4中移除了

4.2.       编写C/C++源码

将你的本地代码放到$PROJECT/jni目录下,$PROJECT为Android应用程序工程根目录。

你可以很自由的组织你的jni目录中的内容,该目录的命名及结构并不会影响你的应用程序的构建。你可以将源文件放到不同的目录,而只需要修改Android.mk文件。

4.3.       编写Android.mk编译脚本

Android.mk编译脚本(Android.mk使用)用于向NDK编译系统描述你的源文件信息及依赖信息。简单的说就是,描述NDK如何将你的源文件打包进modules,modules包括:静态库、动态库。

你可以将多个模块定义到一个Android.mk文件中,或者每个模块定义到单独的Android.mk文件中。

注意,一个单独的Android.mk文件可能会被编译系统解析多次,因此可能存在变量重复定义的问题。默认情况下,NDK会找$PROJECT/jni/Android.mk编译脚本。

如果你想将Android.mk编译脚本定义到子目录下,你应该将它们准确地包含到最高层的Android.mk编译脚本中,你可以通过include $(call all-subdir-makefiles)帮助函数来完成,该函数会用于包含当前目录下的子目录的所有Android.mk编译脚本。

4.4.       编写Application.mk编译脚本(可选)

Application.mk编译脚本(Application.mk使用)用于描述你的应用程序。比如:

应用程序需要的模块列表

用于生成机器代码的CPU架构

以及一些可选信息,比如,需要生成release版本还是debug的,指定C/C++编译标志,以及应用于所有模块的其他选项

有两种方式可以使用Appliction.mk编译脚本:

将其放到$PROJECT/jni目录下,ndk-build会自动寻找

将其放到$NDK/apps/<name>/目录下,然后,运行在NDK目录下运行”makeAPP”,该方式用于NDK r4之前的版本,建议使用第一种方式

4.5.       调用NDK编译工具

首选的编译方式是使用在NDK r4中介绍的ndk-build脚本,你也可以使用另外一种遗留的依赖于创建$NDK/apps子目录的方法。这两种方式都会将共享库拷贝到你的应用程序的工程路径。

使用ndk-build命令:

位于NDK安装根目录下的ndk-build脚本可以在你的应用程序根目录下调用(AndroidManifest,xml所在的目录)或者在应用程序的任何子目录,比如:

cd $PROJECT

$NDK/ndk-build

之后将会启动NDK编译脚本,并自动寻找你的开发系统及序言需要编译的工程文件

该命令也可增加参数,比如:

ndk-buildclean 清除构建的二进制文件

ndk-build –BV=1 强制完成重建,并显示命令

4.6.       编译Android apk

通过NDK编译完二进制文件后,你需要重新编译你的Android应用程序包(apk)。

5.        Android.mk语法

Android.mk在Android NDK中用于描述C/C++源文件信息以及依赖信息。

该文件实际上是GNU Makefile的片段,其会被编译系统解析一次或多次,因此定义的变量可能重复定义。

该文件的语法被设计成允许归并你的源文件到modules中,该modules可分为静态库、动态库、独立的可执行文件

编译系统掌握了很多详细的信息。比如,你不必在Android.mk中列出头文件以及明确的文件依赖关系,NDK编译系统会自动的完成这一切

5.1.       NDK提供的变量(NDK-provided variables)

NDK提供的变量在解析Android.mk之前都已经定义。在某些情况下该文件会被解析多次,每次的定义可能不一样。

5.1.1.      CLEAR_VARS

取消在Module-description部分描述的LOCAL_XXX形式的变量定义。该变量必须在编译新的module之前包含,示例:

include $(CLEAR_VARS)

5.1.2.      BUILD_SHARED_LIBRARY

搜集所有的在LOCAL_XXX形式的变量中提供的信息,并决定生成目标动态库的方式,生成的库名称为lib$(LOCAL_MODULE).so。注意,必须在之前定义LOCAL_MODULE和LOCAL_SRC_FILES变量,示例:

include $(BUILD_SHARED_LIBRARY)

5.1.3.      BUILD_STATIC_LIBRARY

该变量用于构建静态库。静态库不能被拷贝到library/packages目录下,但是会被用于构建动态库,生成的文件名为lib$(LOCAL_MODULE).a,示例:

Include $(BUILD_STATIC_LIBRARY)

5.1.4.      PREBUILD_SHARED_LIBRARY

指向一个用于预先构建的共享库的编译脚本,和BUILD_SHARED_LIBRARY/BUILD_STATIC_LIBRARY不同,LOCAL_SRC_FILES指向的是预先构建的共享库,而不是源文件,比如foo/libfoo.so。

5.1.5.      PREBUILT_STATIC_LIBRARY

该变量和PREBUILT_SHARED_LIBRARY作用一样,只是用于静态库。

5.1.6.      TARGET_ARCH

目标CPU架构的名称。

5.1.7.      TARGET_PLATFORM

当Android.mk被解析时指定目标平台的名称。比如android-3相当于Android 1.5系统镜像。

5.1.8.      TARGET_ARCH_ABI

当Android.mk被解析时指定CPU+ABI的名称。此时有四个值可以支持:

armeabi

         forARMv5TE

armeabi-v7a

         forARMv7

x86

         fori686

mips

         formips32(r1)

5.1.9.      TARGET_ABI

其为目标平台和ABI的连接,定义形式为$(TARGET_PLATFORM)-$(TARGET_ARCH_ABI),当你对一个真实的设备测试目标系统镜像时很有用。其默认值为android-3-armeabi

5.2.       NDK提供的函数宏(NDK-providedfunction macros)

Function macros必须通过$(call          )调用,其返回文本信息。

5.2.1.      my-dir

返回当前Android.mk的路径。其在Android.mk文件开始处通过LOCAL_PATH定义,示例:

LOCAL_PATH := $(call my-dir)

注意:

my-dir返回的是最近include的Android.mk文件的路径,因此不要在包含了另一个Android.mk之后再调用my-dir。示例:

LOCAL_PATH := $(call my-dir)

... declare one module

include $(LOCAL_PATH)/foo/`Android.mk`

LOCAL_PATH := $(call my-dir)

... declare another module

此时 LOCAL_PATH的值为$PATH/foo,因此应该将include放到后面,比如:

LOCAL_PATH := $(call my-dir)

... declare one module

LOCAL_PATH := $(call my-dir)

... declare another module

# extra includes at the end of the`Android.mk`

include $(LOCAL_PATH)/foo/`Android.mk

也可将之前的路径保存到变量中在使用,比如:

MY_LOCAL_PATH := $(call my-dir)

LOCAL_PATH := $(MY_LOCAL_PATH)

... declare one module

include $(LOCAL_PATH)/foo/`Android.mk`

LOCAL_PATH := $(MY_LOCAL_PATH)

... declare another module

5.2.2.      all-subdir-makefiles

返回当前Android.mk目录下的子目录的Android.mk列表。示例:

比如当前Android.mk所在目录包括以下子Android.mk文件:lib1/Android.mk,lib2/Android.mk

include $(call all-subdir-makefiles)将会将这两个子目录下的Android.mk文件包含到当前目录的Android.mk文件中。

5.2.3.      this-makefile

返回当前Makefile的路径。

5.2.4.      parent-makefile

Returns the path of the parent Makefile inthe inclusion tree, i.e. the path of the Makefile that included the current one.

5.2.5.      grand-parent-makefile

5.2.6.      import-module

查找并包含另一个module的Android.mk文件,示例:

$(call import-module, <name>)

该表达式将在NDK_MODULE_PATH环境变量所指定的目录下查找module的Android.mk并包含。

5.3.       模块描述变量(Module-description variables)

该变量向编译系统描述了你的模块信息。这些变量中的一些应该在include $(CLEAR_VARS)和include $(BUILD_XXXXX)之间定义。

5.3.1.      LOCAL_PATH

指定当前Android.mk文件的路径,其必须在Android.mk开始处定义,该变量不会被$(CLEAR_VARS)清除,因此除了定义多个module之外,该变量应该定义一次,示例:

LOCAL_PATH := $(call my-dir)

5.3.2.      LOCAL_MODULE

指定module的名称,其必须是唯一的,并且不能包含空格,以及必须在任何$(BUILD_XXXX)之前定义。

5.3.3.      LOCAL_MODULE_FILENAME

This variable is optional, and allows you toredefine the name of generated files. By default, module will alwaysgenerate a static library named lib.a or a shared library named lib.so,which are standard Unix conventions.

You can override this by defining LOCAL_MODULE_FILENAME,For example:

         LOCAL_MODULE := foo-version-1

         LOCAL_MODULE_FILENAME := libfoo

*NOTE(: You should not put a path or fileextension in your LOCAL_MODULE_FILENAME, these will be handledautomatically by the build system.

5.3.4.      LOCAL_SRC_FILES

编译模块的源文件列表。示例:

LOCAL_SRC_PATH := foo.c

5.3.5.      LOCAL_CPP_EXTENSION

可选的,用于描述C++文件的扩展名,必须以.开始,默认的扩展名为.cpp,但是可以修改,示例:

LOCAL_CPP_EXTENSION := .cxx .cpp

5.3.6.      LOCAL_CPP_FEATURES

可选项,用于描述你的代码依赖的C++特性,其可以让你的程序正确的编译和连接。比如使用了RTTI:

LOCAL_CPP_FEATURE := rtti

5.3.7.      LOCAL_C_INCLUDES

相对于NDK根目录的路径,其将会在编译时作为头文件的搜索路径,示例:

LOCAL_C_INCLUDES := sources/foo

5.3.8.      LOCA_CFLAGS

编译选项,在编译C/C++源文件时其可用于指定额外的宏定义或编译选项。

5.3.9.      LOCAL_CPPFLAGS

编译选项,在编译C++源文件时其可用于指定额外的宏定义或编译选项。

5.3.10.   LOCAL_CXXFLAGS

LOCAL_CPPFLAGS的别名。

5.3.11.   LOCAL_STATIC_LIBRARIES

指定当前模块依赖的静态库模块。

5.3.12.   LOCAL_SHARED_LIBRARIES

指定运行时依赖的动态库模块。

5.3.13.   LOCAL_WHOLE_STATIC_LIBRARIES

A variant of LOCAL_STATIC_LIBRARIES usedto express that the corresponding library module should be used as "wholearchives" to the linker. See the GNU linker's documentation for the --whole-archive flag.

This is generally useful whenthere are circular dependencies between several static libraries. Note thatwhen used to build a shared library, this will force all object files from yourwhole static libraries to be added to the final binary. This is not true whengenerating executables though.

5.3.14.   LOCAL_LDLIBS

在编译动态库或者可执行程序时用于指定额外的连接选项,示例:

LOCAL_LDLIBS := -lz

5.3.15.   LOCAL_LDFLAGS

在编译动态库或者可执行程序时用于指定其他的连接选项,示例:

LOCAL_LDFLAGS += -fuse-ld=bfd

5.3.16.   LOCAL_ALLOW_UNDEFINED_SYMBOLS

By default, any undefined referenceencountered when trying to build a shared library will result in an "undefinedsymbol" error. This is a great help to catch bugs in your source code.

However, if for some reason youneed to disable this check, set this variable to 'true'. Note that thecorresponding shared library may fail to load at runtime.

NOTE: This is ignored for static libraries, and ndk-build will print awarning if you define it in such a module

5.3.17.   LOCAL_ARM_MODE

By default, ARM target binaries will begenerated in 'thumb' mode, where each instruction are 16-bit wide. You candefine this variable to 'arm' if you want to force the generation of themodule's object files in 'arm' (32-bit instructions) mode. E.g.:

       LOCAL_ARM_MODE := arm

Note that you can also instruct the buildsystem to only build specific sources in ARM mode by appending an '.arm' suffixto its source file name. For example, with:

       LOCAL_SRC_FILES := foo.c bar.c.arm

Tells the build system to always compile 'bar.c'in ARM mode, and to build foo.c according to the value ofLOCAL_ARM_MODE.

NOTE: Setting APP_OPTIM to 'debug'in your Application.mk will also force the generation of ARM binariesas well. This is due to bugs in the toolchain debugger that don't deal too wellwith thumb code.

5.3.18.   LOCAL_ARM_NEON

5.3.19.   LOCAL_DISABLE_NO_EXECUTE

5.3.20.   LOCAL_DISABLE_RELRO

5.3.21.   LOCAL_DISABLE_FORMAT_STRING_CHECKS

5.3.22.   LOCAL_EXPORT_CFLAGS

5.3.23.   LOCAL_EXPORT_CPPFLAGS

5.3.24.   LOCAL_EXPORT_C_INCLUDES

5.3.25.   LOCAL_EXPORT_LDFLAGS

5.3.26.   LOCAL_EXPORT_LDLIBS

5.3.27.   LOCAL_SHORT_COMMANDS

5.3.28.   LOCAL_THIN_ARCHIVE

5.3.29.   LOCAL_FILTER_ASM

6.        Application.mk语法

0 0
原创粉丝点击