NDK jni mk文件 so文件 巴啦啦 初体验

概念
JNI(Java Native Interface,Java本地接口),实现了Java和其他语言的交互(主要是C/C++),如:Java程序通过JNI调用C/C++编写的在Windows上运行的DLL动态链接库。

so(shared object,共享对象),Linux系统中的动态库,类似于Windows系统中的DLL。.so有时被直接调用,有时会参与到编译中。Android由Linux内核发展而来,因此在Android系统中也使用.so。

Android NDK(Android Native Development Kit),是Google提供的一系列的工具,简化通过JNI将C/C++动态库编译为.so库的过程。NDK集成了交叉编译器,并提供了相应的.mk文件隔离CPU、平台、ABI等差异,开发者只需要简单修改mk文件,执行编译脚本就可以创建.so。

NDK与JNI的关系:

JNI是Java与其他语言交互的机制,是Java语言自身的特性,与Android无关。

Android在框架上分为Application应用层、Application Framework应用框架层、libraries类库、Linux kernel内核。在应用框架层以及之上,使用Java语言进行开发;在此之下,Android自身的类库、驱动使用C/C++编写,再通过JNI提供接口给上层的Java调用。所以,Android框架使用了大量的JNI技术,让应用层的开发人员使用Java操控C/C++。

通常的Android开发都在应用框架层以及之上进行,但有时也需要对底层进行实现。显然,对底层的开发要复杂得多,NDK则是Google推出的帮助开发者通过C/C++编写应用的开发包,包含部分Android底层中常用的C/C++的头文件、库文件、说明文档和示例代码。

NDK只需要简单地编写几个.mk文件即可将c/c++代码编译为Android的java工程/Android手机可以识别、加载和运行的库或者应用程序。

Android.mk
ndk-build命令实际是执行了%NDK_PROJECT_PATH%/jni/Android.mk这个makefile文件,如果未配置%NDK_PROJECT_PATH%环境变量,则需要定位到工程目录。同时,待编译的.c和编译配置文件Android.mk也需要位于名为jni的目录下。

Android.mk是NDK编译的配置文件,其中定义了需要编译的.c文件、依赖的.h头文件、编译出的so库名等等信息,是使用NDK进行编译的关键。

为什么使用NDK

  • 代码的保护。由于apk的java层代码很容易被反编译,而C/C++库反汇难度较大。

  • 可以方便地使用现存的开源库。大部分现存的开源库都是用C/C++代码编写的。

  • 提高程序的执行效率。将要求高性能的应用逻辑使用C开发,从而提高应用程序的执行效率。

  • 便于移植。用C/C++写得库可以方便在其他的嵌入式平台上再次使用。

mk文件中的语法:

1.LOCAL_PATH

这个变量用于给出当前文件的路径。你必须在Android.mk的开头定义。例如:

LOCAL_PATH := $(call my-dir)

2.LOCAL_MODULE

这是你模块的名字,它必须是唯一的,而且不能包含空格。你必须在包含任一的$(BUILD_XXXX)脚本之前定义它。模块的名字决定了生成文件的名字。

3.LOCAL_MODULE_FILENAME

默认的情况下,编译生成的文件名为lib$(LOCAL_MODULE).so/a在使用的此变量后,会用此变量的名来覆盖系统默认的生成文件名。例如:

LOCAL_MODULE := foo-version-1

LOCAL_MODULE_FILENAME := foo生成的文件名为libfoo.so/a

4.LOCAL_SRC_FILES

要直接传递给编译器的源代码文件列表。只要列出要传递给编译器的文件即可,因为编译系统自动为你计算依赖

5.LOCAL_C_INCLUDES


可选的路径列表,相对于NDK的根目录,当编译所有的源文件(C、C++、或者汇编)时将被追加到搜索路径中
例如:
LOCAL_C_INCLUDES:=sources/foo
或者
LOCAL_C_INCLUDES:=$(LOCAL_PATH)/../foo

6.LOCAL_EXPORT_CFLAGS

定义这个变量用来记录C/C++编译器标志集合

     include $(CLEAR_VARS)

        LOCAL_MODULE := foo

        LOCAL_SRC_FILES := foo/foo.c

        LOCAL_EXPORT_CFLAGS := -DFOO=1

        include $(BUILD_STATIC_LIBRARY)

  定义-DFOO 为1

7.import-module

此函数用于按模块名称来查找和包含模块的 Android.mk 文件。 典型的示例如下所示:

$(call import-module,<name>) 

在此示例中,构建系统在 NDK_MODULE_PATH 环境变量所引用的目录列表中查找以 <name> 标记的模块,并且自动包括其 Android.mk 文件。

8.include

include可Android多以这样的形式出现,如:include $( CLEAR_VARS),include $(BUILD_SHARED_LIBRARY).其实这个include可以理解成"执行"的意思,那么执行什么呢?当然是看后边的宏了.

宏CLEAR_VARS表示清除一些变量.

宏BUILD_SHARED_LIBRARY表示生成共享库,即生成.so文件,它负责收集自从上次调用 include $(CLEAR_VARS) 后的所有LOCAL_XXX信息。并决定编译为什么。

因此include $(BUILD_SHARED_LIBRARY)就是指定在/system/lib/目录下生成一个lib$(LOCAL_MOUDULE).so文件,同样类型的宏如下:

CLEAR_VARS                                             清除LOCAL_xxx变量
BUILD_SHARED_LIBRARY                     在/system/lib/目录下生成lib$(LOCAL_MOUDULE).so文件
BUILD_STATIC_LIBRARY                         生成lib$(LOCAL_MOUDULE).a文件
BUILD_EXECUTABLE                               在/system/bin/目录下生成可执行文件
BUILD_PACKAGE                                      编译成一个apk文件

原文地址:https://www.cnblogs.com/lixiao24/p/10686403.html