内容简介:C/C++语言基础 –> JNI编程 –> NDK编程 –> 音视频处理 –> 图像处理等等 ,从零到一 , 零基础学习NDK开发 。学习本专题 , 你需要具备一定的Android开发知识 C/C++基础, 知道如何创建一个Android工程 , 有一定的开发经验更佳 。Android.mk 的文件配置详解,能够读懂Android.mk;为何Google推荐使用cmake,而不在使用Android.mk?Android.mk存在哪些缺陷?如何生成静态库与动态库(在上几篇文章中讲过)?
C/C++语言基础 –> JNI编程 –> NDK编程 –> 音视频处理 –> 图像处理等等 ,从零到一 , 零基础学习NDK开发 。学习本专题 , 你需要具备一定的Android开发知识 C/C++基础, 知道如何创建一个Android工程 , 有一定的开发经验更佳 。
前言
Android.mk 的文件配置详解,能够读懂Android.mk;为何Google推荐使用cmake,而不在使用Android.mk?Android.mk存在哪些缺陷?
如何生成静态库与动态库(在上几篇文章中讲过)?
Android.mk 如何配置动态库(.so文件)、配置静态库(.a文件)?
静态库与动态库的区别?
带着这些问题,思考,往下看。
环境:
AS 3.1.0 版本
NDK 16 版本
命令行: Mac 自带的命令行
通过命令来生成动态库和静态库
这里用mac的终端来演示,通过vim 命令来生成一个.c文件,这个就不必细说了吧。 在NDK 开发必知必会1⃣️CC++编译器配置,中有详细的讲解
输入: vim a.c
然后配置一个临时的变量:
export CC="/Users/prim/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-gcc --sysroot=/Users/prim/Library/Android/sdk/ndk-bundle/platforms/android-21/arch-arm -isystem /Users/prim/Library/Android/sdk/ndk-bundle/sysroot/usr/include -isystem /Users/prim/Library/Android/sdk/ndk-bundle/sysroot/usr/include/arm-linux-androideabi"
输入 :echo $CC 验证变量是否配置成功
输入 :$CC -fPIC -shared a.c -o libA.so 生成libA.so文件,这里便生成了一个动态库
输入:$CC -fPIC -c a.c -o a.o 生成a.o 文件,用于生成静态库
输入 : /Users/prim/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-ar r libA.a a.o
会生成libA.a 静态库文件。
将得到的libA.so libA.a copy到项目的cpp 文件夹下( cpp可参照如何配置NDK开发环境 )。
配置依赖动态库
NDK 环境的配置,这里就不再细说了,配置完成如下图:
gradle 配置
下面是重点,Android.mk文件如何配置动态库
LOCAL_PATH := $(call my-dir) # 预编译库引入(提前编译好的库) include $(CLEAR_VARS) LOCAL_MODULE := A LOCAL_SRC_FILES := libA.so # 构建动态库 include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := holle-jni LOCAL_SRC_FILES := holle-jni.c # 编译holle-jni模块 需要连接A模块 # A模块是一个预编译库模块 动态库 LOCAL_SHARED_LIBRARIES := A # 动态库配置 include $(BUILD_SHARED_LIBRARY)
LOCAL_PATH := $(call my-dir)表示:源文件在的位置。宏函数 my-dir 返回当前目录(包含 Android.mk 文件本身的目录)的路径。
include $(CLEAR_VARS):引入其他makefile文件。CLEAR_VARS 变量指向特殊 GNU Makefile,可为您清除许多 LOCAL_XXX 变量
不会清理 LOCAL_PATH 变量
LOCAL_MODULE := hello-jni:存储您要构建的模块的名称 每个模块名称必须唯一,且不含任何空格
#如果模块名称的开头已是 lib,则构建系统不会附加额外的前缀 lib;而是按原样采用模块名称,并添加 .so 扩展名。
LOCAL_SRC_FILES := hello-jni.c:包含要构建到模块中的 C 和/或 C++ 源文件列表 以空格分开
构建动态库 include $(BUILD_SHARED_LIBRARY)
这样便配置好了动态库,build一下看cpp文件有没有变亮,如果变亮则动态库配置成功。
会生成两个so包libholle-jni.so libA.so
如何使用libA.so中的函数呢?
编辑 holle-jni.c
#include <jni.h> //libA.so 中的方法 extern int test1(); JNIEXPORT void JNICALL Java_ndk_config_com_configndk_MainActivity_useLibAMoudle(JNIEnv *env, jobject instance) { // TODO test1(); }
Activity 中代码
static { System.loadLibrary("holle-jni"); }
这样就可以调用动态库中的函数了。
Android.mk 配置动态库的缺陷
在4.4上 如果load一个动态库 ,需要先将这个动态库的依赖的其他动态库load进来
比如:在Android 4.4 先要load holle-jni 链接的动态库,要在load holle-jni 之前load进来
System.loadLibrary("A"); System.loadLibrary("holle-jni");
从6.0开始 使用Android.mk 如果来引入一个预编译动态库 有问题
在6.0以下 System.loadLibrary 不会自动为我们加载依赖的动态库
6.0以上 System.loadLibrary 会自动为我们加载依赖的动态库
那么在6.0 以上就不能使用,如下方法loadlibary,否则项目会报错:
System.loadLibrary("A"); System.loadLibrary("holle-jni");
改成,因为6.0以上会自动加载依赖的动态库。
System.loadLibrary("holle-jni");
这里并没有太好的解决方法,或许是因为这个原因,Google才推荐使用cmake的方式,现在的ndk对mk的支持已经接近放弃阶段了。
配置依赖静态库
LOCAL_PATH := $(call my-dir) # 预编译库引入(提前编译好的库) include $(CLEAR_VARS) LOCAL_MODULE := A LOCAL_SRC_FILES := libA.a # 构建静态库 include $(PREBUILT_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := holle-jni LOCAL_SRC_FILES := holle-jni.c # 构建静态库 LOCAL_STATIC_LIBRARIES := A # 动态库配置 include $(BUILD_SHARED_LIBRARY)
调用静态库的函数和调用动态库的函数方式一致。
同时Activity只需要,便可以,静态库不需要动态的加载依赖,在打包时已经将静态库打进去了。
System.loadLibrary("holle-jni");
使用静态库会生成一个so文件,很显然apk会小很多
静态库与动态库的区别
静态库节省时间:不需要再进行动态链接,需要调用的代码直接就在代码内部
动态库节省空间:如果一个动态库被两个程序调用,那么这个动态库只需要在内存中
Java中在不经过封装的情况下只能直接使用动态库。
我们可以这样比喻两个库的区别:
jar包 =》 a.java b.java c.java
app: app.java(a.java),app.java 调用jar包的 a.java
假设jar包是静态库,那么打包的apk 只包含 app.java + a.java 而没有将 b.java c. java 打进apk包中。
app.apk –> app.java+a.java
假设jar包是动态库,直接将整个jar包打入到apk包中。
app.apk: app.java+ jar包(a.java b.java c.java)
显然,如果我们使用静态库(.a)打的apk包要比动态库(.so)打的apk包小很多。
MakeFile 配置详解
变量和宏
定义自己的任意变量。在定义变量时请注意,NDK 构建系统会预留以下变量名称:
以 LOCAL_ 开头的名称,例如 LOCAL_MODULE。
以 PRIVATE_、NDK_ 或 APP 开头的名称。构建系统在内部使用这些变量。
小写名称,例如 my-dir。构建系统也是在内部使用这些变量。
如果为了方便而需要在 Android.mk 文件中定义自己的变量,建议在名称前附加 MY_。
常用内置变量
变量名 | 含义 | 示例 |
---|---|---|
BUILD_STATIC_LIBRARY | 构建静态库的Makefile脚本 | include $(BUILD_STATIC_LIBRARY) |
PREBUILT_SHARED_LIBRARY | 预编译共享库的Makeifle脚本 | include $(PREBUILT_SHARED_LIBRARY) |
PREBUILT_STATIC_LIBRARY | 预编译静态库的Makeifle脚本 | include $(PREBUILT_STATIC_LIBRARY) |
TARGET_PLATFORM Android API | 级别号 | TARGET_PLATFORM := android-22 |
TARGET_ARCH | CUP架构 | arm arm64 x86 x86_64 |
TARGET_ARCH_ABI | CPU架构 | armeabi armeabi-v7a arm64-v8a |
模块描述变量
变量名 | 描述 | 例 |
---|---|---|
LOCAL_MODULE_FILENAME | 覆盖构建系统默认用于其生成的文件的名称 | LOCAL_MODULE := foo LOCAL_MODULE_FILENAME := libnewfoo |
LOCAL_CPP_FEATURES | 特定 C++ 功能 | 支持异常:LOCAL_CPP_FEATURES := exceptions |
LOCAL_C_INCLUDES | 头文件目录查找路径 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/include |
LOCAL_CFLAGS | 构建 C 和 C++ 的编译参数 | LOCAL_CPPFLAGS c++ |
LOCAL_STATIC_LIBRARIES | 当前模块依赖的静态库模块列表 | LOCAL_SHARED_LIBRARIES |
LOCAL_WHOLE_STATIC_LIBRARIES | –whole-archive | 将未使用的函数符号也加入编译进入这个模块 |
LOCAL_LDLIBS | 依赖 系统库 | LOCAL_LDLIBS := -lz |
导出给引入模块的模块使用:
LOCAL_EXPORT_CFLAGS
LOCAL_EXPORT_CPPFLAGS
LOCAL_EXPORT_C_INCLUDES
LOCAL_EXPORT_LDLIBS
引入其他模块
#将一个新的路径加入NDK_MODULE_PATH变量 #NDK_MODULE_PATH 变量是系统环境变量 $(call import-add-path,$(LOCAL_PATH)/platform/third_party/android/prebuilt) #包含CocosDenshion/android目录下的mk文件 $(call import-module,CocosDenshion/android) #这里即为 我需要引入 CocosDenshion/android 下面的Android.mk #CocosDenshion/android 的路径会从 $(LOCAL_PATH)/platform/third_party/android/prebuilt 去查找
以上所述就是小编给大家介绍的《01-05 NDK开发必知必会3⃣️MakeFile详解》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Flutter 完整开发实战详解(十六、详解自定义布局实战)
- iOS开发-RunLoop详解
- PHP开发比特币详解
- C#比特币开发详解
- springmvc教程--注解开发基础详解
- 开源区块链Tendermint开发详解
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
JSP应用开发技术
柳永坡 / 人民邮电出版社 / 2005-9 / 52.00元
本书全面系统地介绍了JSP应用开发技术,包括JSP预备知识和环境配置、JSP编程基础、JSP应用开发进阶、在JSP中使用数据库、Servlet技术、标签库和表达式语言、Web编程模式和应用框架等几个方面的内容。本书不但由浅入深地介绍了JSP程序设计的原理、方法和技术,还提供了大量的JSP应用开发实例,给出了相应的实用技巧、操作步骤及优化思路。 本书着重于JSP技术的应用性和可操作性,......一起来看看 《JSP应用开发技术》 这本书的介绍吧!